1/*
2 *   Copyright (c) International Business Machines Corp., 2001-2004
3 *
4 *   This program is free software;  you can redistribute it and/or modify
5 *   it under the terms of the GNU General Public License as published by
6 *   the Free Software Foundation; either version 2 of the License, or
7 *   (at your option) any later version.
8 *
9 *   This program is distributed in the hope that it will be useful,
10 *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
11 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
12 *   the GNU General Public License for more details.
13 *
14 *   You should have received a copy of the GNU General Public License
15 *   along with this program;  if not, write to the Free Software
16 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18#ifndef _FFSB_TG_H_
19#define _FFSB_TG_H_
20#include <inttypes.h>
21#include <stdlib.h>
22#include <sys/types.h>
23
24#include <pthread.h>
25
26#include "ffsb.h"
27#include "ffsb_op.h"
28#include "ffsb_thread.h"
29#include "ffsb_fs.h"
30#include "ffsb_stats.h"
31
32#include "util.h" /* for barrier obj */
33
34/* "Thread Group" object defs.
35 *
36 *  A thread group contains configuration information and can run its
37 *  "gang" of threads performing a particular mix of operations.
38 *
39 * The thread group is responsible for creating the ffsb_thread
40 * objects which must ask the thread group object to select an
41 * operation and a filesystem to run that operation on.  The thread
42 * objects don't contain any of the configuration information.
43 *
44 * Thread groups are also abstracted so they can be "run" arbitrarily
45 * which is useful because we can reuse them for aging.  The running
46 * is a bit complex, the thread group has to have a callback function
47 * which is runs at a specified interval to determine when to
48 * terminate.
49 *
50 * To synchronize starting across many thread groups there are two
51 * barriers used, the first one "tg_barrier" in the run_params is to
52 * synchronize multiple thread-groups being ready to start, meaning
53 * that all their threads have been spawned The second one
54 * "thread_barrier" synchronizes all threads across multiple thread
55 * groups, so that they all start at once.
56*/
57
58struct ffsb_thread;
59struct ffsb_config;
60
61typedef struct ffsb_tg {
62	unsigned tg_num;
63	unsigned num_threads;
64	unsigned op_weights[FFSB_NUMOPS];
65	struct ffsb_thread *threads;
66
67	/* A threadgroup can be bound to just one filesystem.
68	 * A value * < 0 , means we aren't bound to any.
69	*/
70	int bindfs;
71
72	int read_random;	/* boolean */
73	uint64_t read_size;
74	uint32_t read_blocksize;
75
76	int read_skip;		/* boolean */
77	uint32_t read_skipsize;
78
79	int write_random;	/* boolean */
80	uint64_t write_size;
81	uint32_t write_blocksize;
82
83	int fsync_file;		/* boolean */
84
85	/* Should be max(write_blocksize, read_blocksize) */
86	uint32_t thread_bufsize;
87
88	/* these fields are calculated/set by tg_run() */
89	unsigned sum_weights;
90	struct ffsb_config *fc;
91	ffsb_barrier_t *start_barrier;
92
93	/* Used for stopping the threads */
94	int flagval;
95	int stopval;
96
97	/* Delay between every operation, in milliseconds*/
98	unsigned wait_time;
99
100	/* stats configuration */
101	int need_stats;
102	ffsb_statsc_t fsc;
103} ffsb_tg_t;
104
105/* Init should be the very first thing called on the tg.  After that,
106 * the user can call the set methods and finally run.
107 */
108void init_ffsb_tg(ffsb_tg_t *tg, unsigned num_threads, unsigned tg_num);
109void destroy_ffsb_tg(ffsb_tg_t *tg);
110
111/* Parameters needed to fire off a thread group.  The main thread will
112 * evaluate poll_fn(poll_data) until it gets a nonzero return value.
113 * It will sleep for wait_time secs between calls The ffsb_config
114 * struct is needed for fs selection.  Barriers are to synchronize
115 * multiple tgs and all threads pt is for pthread_create()
116 */
117typedef struct tg_run_params {
118	ffsb_tg_t *tg;
119	int (*poll_fn)(void *);
120	void *poll_data;
121	unsigned wait_time; /* in sec */
122	struct ffsb_config *fc;
123	ffsb_barrier_t *tg_barrier;
124
125	/* Should be initialized by caller to tg_run() */
126	ffsb_barrier_t *thread_barrier;
127	pthread_t  pt;
128} tg_run_params_t;
129
130/* This function is meant to be called as a parameter to
131 * pthread_create()
132 */
133void *tg_run(void *);
134
135void tg_print_config(ffsb_tg_t *tg);
136void tg_print_config_aging(ffsb_tg_t *tg, char *fsname);
137
138/* Adds all of this tg's results to res */
139void tg_collect_results(ffsb_tg_t *tg, ffsb_op_results_t *res);
140
141/* Adds up all this tg's stats to totals */
142void tg_collect_stats(ffsb_tg_t *tg, ffsb_statsd_t *totals);
143
144/* getters/setters, setters should not be called after a run has begun */
145
146void tg_set_statsc(ffsb_tg_t *tg, ffsb_statsc_t *fsc);
147
148void tg_set_bindfs(ffsb_tg_t *tg, int fsnum);
149int  tg_get_bindfs(ffsb_tg_t *tg);
150
151unsigned tg_get_numthreads(ffsb_tg_t *tg);
152
153void tg_set_op_weight(ffsb_tg_t *tg, char *opname, unsigned weight);
154unsigned tg_get_op_weight(ffsb_tg_t *tg, char *opname);
155
156void tg_set_read_random(ffsb_tg_t *tg, int rr);
157void tg_set_write_random(ffsb_tg_t *tg, int wr);
158void tg_set_fsync_file(ffsb_tg_t *tg, int fsync);
159
160int tg_get_read_random(ffsb_tg_t *tg);
161int tg_get_write_random(ffsb_tg_t *tg);
162int tg_get_fsync_file(ffsb_tg_t *tg);
163
164void tg_set_read_size(ffsb_tg_t *tg, uint64_t rs);
165void tg_set_read_blocksize(ffsb_tg_t *tg, uint32_t rs);
166
167void tg_set_read_skipsize(ffsb_tg_t *tg, uint32_t rs);
168void tg_set_read_skip(ffsb_tg_t *tg, int rs);
169
170void tg_set_write_size(ffsb_tg_t *tg, uint64_t ws);
171void tg_set_write_blocksize(ffsb_tg_t *tg, uint32_t ws);
172
173uint64_t tg_get_read_size(ffsb_tg_t *tg);
174uint32_t tg_get_read_blocksize(ffsb_tg_t *tg);
175
176int tg_get_read_skip(ffsb_tg_t *tg);
177uint32_t tg_get_read_skipsize(ffsb_tg_t *tg);
178
179uint64_t tg_get_write_size(ffsb_tg_t *tg);
180uint32_t tg_get_write_blocksize(ffsb_tg_t *tg);
181
182void tg_set_waittime(ffsb_tg_t *tg, unsigned time);
183unsigned tg_get_waittime(ffsb_tg_t *tg);
184
185/* The threads in the tg should be the only ones using these (below)
186 * funcs.
187 */
188ffsb_barrier_t *tg_get_start_barrier(ffsb_tg_t *tg);
189int tg_get_stopval(ffsb_tg_t *tg);
190int tg_get_flagval(ffsb_tg_t *tg);
191
192/* The threads in this tg will use this function to get an op to run,
193 * so all configuration specific information is kept in this object.
194 */
195typedef struct tg_op_params {
196	struct ffsb_fs *fs;     /* out parameter */
197	unsigned opnum;         /* out parameter */
198} tg_op_params_t;
199
200/* tg and rd and in parameters, everything in params is out */
201void  tg_get_op(ffsb_tg_t *tg, randdata_t *rd, tg_op_params_t *params);
202
203/* want stats for this tg ? */
204int tg_needs_stats(ffsb_tg_t *tg);
205
206#endif /* _FFSB_TG_H_ */
207