/* * Copyright (c) International Business Machines Corp., 2001-2004 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _FFSB_TG_H_ #define _FFSB_TG_H_ #include #include #include #include #include "ffsb.h" #include "ffsb_op.h" #include "ffsb_thread.h" #include "ffsb_fs.h" #include "ffsb_stats.h" #include "util.h" /* for barrier obj */ /* "Thread Group" object defs. * * A thread group contains configuration information and can run its * "gang" of threads performing a particular mix of operations. * * The thread group is responsible for creating the ffsb_thread * objects which must ask the thread group object to select an * operation and a filesystem to run that operation on. The thread * objects don't contain any of the configuration information. * * Thread groups are also abstracted so they can be "run" arbitrarily * which is useful because we can reuse them for aging. The running * is a bit complex, the thread group has to have a callback function * which is runs at a specified interval to determine when to * terminate. * * To synchronize starting across many thread groups there are two * barriers used, the first one "tg_barrier" in the run_params is to * synchronize multiple thread-groups being ready to start, meaning * that all their threads have been spawned The second one * "thread_barrier" synchronizes all threads across multiple thread * groups, so that they all start at once. */ struct ffsb_thread; struct ffsb_config; typedef struct ffsb_tg { unsigned tg_num; unsigned num_threads; unsigned op_weights[FFSB_NUMOPS]; struct ffsb_thread *threads; /* A threadgroup can be bound to just one filesystem. * A value * < 0 , means we aren't bound to any. */ int bindfs; int read_random; /* boolean */ uint64_t read_size; uint32_t read_blocksize; int read_skip; /* boolean */ uint32_t read_skipsize; int write_random; /* boolean */ uint64_t write_size; uint32_t write_blocksize; int fsync_file; /* boolean */ /* Should be max(write_blocksize, read_blocksize) */ uint32_t thread_bufsize; /* these fields are calculated/set by tg_run() */ unsigned sum_weights; struct ffsb_config *fc; ffsb_barrier_t *start_barrier; /* Used for stopping the threads */ int flagval; int stopval; /* Delay between every operation, in milliseconds*/ unsigned wait_time; /* stats configuration */ int need_stats; ffsb_statsc_t fsc; } ffsb_tg_t; /* Init should be the very first thing called on the tg. After that, * the user can call the set methods and finally run. */ void init_ffsb_tg(ffsb_tg_t *tg, unsigned num_threads, unsigned tg_num); void destroy_ffsb_tg(ffsb_tg_t *tg); /* Parameters needed to fire off a thread group. The main thread will * evaluate poll_fn(poll_data) until it gets a nonzero return value. * It will sleep for wait_time secs between calls The ffsb_config * struct is needed for fs selection. Barriers are to synchronize * multiple tgs and all threads pt is for pthread_create() */ typedef struct tg_run_params { ffsb_tg_t *tg; int (*poll_fn)(void *); void *poll_data; unsigned wait_time; /* in sec */ struct ffsb_config *fc; ffsb_barrier_t *tg_barrier; /* Should be initialized by caller to tg_run() */ ffsb_barrier_t *thread_barrier; pthread_t pt; } tg_run_params_t; /* This function is meant to be called as a parameter to * pthread_create() */ void *tg_run(void *); void tg_print_config(ffsb_tg_t *tg); void tg_print_config_aging(ffsb_tg_t *tg, char *fsname); /* Adds all of this tg's results to res */ void tg_collect_results(ffsb_tg_t *tg, ffsb_op_results_t *res); /* Adds up all this tg's stats to totals */ void tg_collect_stats(ffsb_tg_t *tg, ffsb_statsd_t *totals); /* getters/setters, setters should not be called after a run has begun */ void tg_set_statsc(ffsb_tg_t *tg, ffsb_statsc_t *fsc); void tg_set_bindfs(ffsb_tg_t *tg, int fsnum); int tg_get_bindfs(ffsb_tg_t *tg); unsigned tg_get_numthreads(ffsb_tg_t *tg); void tg_set_op_weight(ffsb_tg_t *tg, char *opname, unsigned weight); unsigned tg_get_op_weight(ffsb_tg_t *tg, char *opname); void tg_set_read_random(ffsb_tg_t *tg, int rr); void tg_set_write_random(ffsb_tg_t *tg, int wr); void tg_set_fsync_file(ffsb_tg_t *tg, int fsync); int tg_get_read_random(ffsb_tg_t *tg); int tg_get_write_random(ffsb_tg_t *tg); int tg_get_fsync_file(ffsb_tg_t *tg); void tg_set_read_size(ffsb_tg_t *tg, uint64_t rs); void tg_set_read_blocksize(ffsb_tg_t *tg, uint32_t rs); void tg_set_read_skipsize(ffsb_tg_t *tg, uint32_t rs); void tg_set_read_skip(ffsb_tg_t *tg, int rs); void tg_set_write_size(ffsb_tg_t *tg, uint64_t ws); void tg_set_write_blocksize(ffsb_tg_t *tg, uint32_t ws); uint64_t tg_get_read_size(ffsb_tg_t *tg); uint32_t tg_get_read_blocksize(ffsb_tg_t *tg); int tg_get_read_skip(ffsb_tg_t *tg); uint32_t tg_get_read_skipsize(ffsb_tg_t *tg); uint64_t tg_get_write_size(ffsb_tg_t *tg); uint32_t tg_get_write_blocksize(ffsb_tg_t *tg); void tg_set_waittime(ffsb_tg_t *tg, unsigned time); unsigned tg_get_waittime(ffsb_tg_t *tg); /* The threads in the tg should be the only ones using these (below) * funcs. */ ffsb_barrier_t *tg_get_start_barrier(ffsb_tg_t *tg); int tg_get_stopval(ffsb_tg_t *tg); int tg_get_flagval(ffsb_tg_t *tg); /* The threads in this tg will use this function to get an op to run, * so all configuration specific information is kept in this object. */ typedef struct tg_op_params { struct ffsb_fs *fs; /* out parameter */ unsigned opnum; /* out parameter */ } tg_op_params_t; /* tg and rd and in parameters, everything in params is out */ void tg_get_op(ffsb_tg_t *tg, randdata_t *rd, tg_op_params_t *params); /* want stats for this tg ? */ int tg_needs_stats(ffsb_tg_t *tg); #endif /* _FFSB_TG_H_ */