Home | History | Annotate | Download | only in ffsb-6.0-rc2
      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 #include <string.h>
     19 #include <stdio.h>
     20 #include <assert.h>
     21 #include <pthread.h>
     22 
     23 #include "ffsb_tg.h"
     24 #include "util.h"
     25 
     26 void init_ffsb_tg(ffsb_tg_t * tg, unsigned num_threads, unsigned tg_num)
     27 {
     28 	int i;
     29 	memset(tg, 0, sizeof(ffsb_tg_t));
     30 
     31 	tg->threads = ffsb_malloc(sizeof(ffsb_thread_t) * num_threads);
     32 	tg->tg_num = tg_num;
     33 	tg->num_threads = num_threads;
     34 
     35 	tg->bindfs = -1;	/* default is not bound */
     36 
     37 	tg->thread_bufsize = 0;
     38 	for (i = 0; i < num_threads; i++)
     39 		init_ffsb_thread(tg->threads + i, tg, 0, tg_num, i);
     40 }
     41 
     42 void destroy_ffsb_tg(ffsb_tg_t * tg)
     43 {
     44 	int i;
     45 	for (i = 0; i < tg->num_threads; i++)
     46 		destroy_ffsb_thread(tg->threads + i);
     47 	free(tg->threads);
     48 	if (tg_needs_stats(tg))
     49 		ffsb_statsc_destroy(&tg->fsc);
     50 }
     51 
     52 void *tg_run(void *data)
     53 {
     54 	tg_run_params_t *params = (tg_run_params_t *) data;
     55 	ffsb_tg_t *tg = params->tg;
     56 	int i;
     57 	pthread_attr_t attr;
     58 
     59 	pthread_attr_init(&attr);
     60 	pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
     61 
     62 	tg->start_barrier = params->thread_barrier;
     63 
     64 	/* Sum up the weights for use later by tg_get_op() */
     65 	tg->sum_weights = 0;
     66 	for (i = 0; i < FFSB_NUMOPS; i++)
     67 		tg->sum_weights += tg->op_weights[i];
     68 
     69 	tg->fc = params->fc;
     70 	tg->flagval = -1;
     71 	tg->stopval = 1;
     72 
     73 	/* spawn threads */
     74 	for (i = 0; i < tg->num_threads; i++) {
     75 		ffsb_thread_t *ft = &tg->threads[i];
     76 		pthread_create(&ft->ptid, &attr, ft_run, ft);
     77 	}
     78 
     79 	if (params->tg_barrier)
     80 		ffsb_barrier_wait(params->tg_barrier);
     81 
     82 	/* wait for termination condition to be true */
     83 	do {
     84 		ffsb_sleep(params->wait_time);
     85 	} while (params->poll_fn(params->poll_data) == 0);
     86 
     87 	/* set flag value */
     88 	tg->flagval = tg->stopval;
     89 
     90 	/* wait on theads to finish */
     91 	for (i = 0; i < tg->num_threads; i++)
     92 		pthread_join(tg->threads[i].ptid, NULL);
     93 
     94 	return NULL;
     95 }
     96 
     97 /* Needs to set params->opnum and params->fs */
     98 void tg_get_op(ffsb_tg_t * tg, randdata_t * rd, tg_op_params_t * params)
     99 {
    100 	unsigned curop;
    101 	int num;
    102 	int fsnum;
    103 
    104 	num = 1 + getrandom(rd, tg->sum_weights);
    105 	curop = 0;
    106 
    107 	while (tg->op_weights[curop] < num) {
    108 		num -= tg->op_weights[curop];
    109 		curop++;
    110 	}
    111 
    112 	params->opnum = curop;
    113 
    114 	/* If we're bound to a particular filesystem, use that,
    115 	 * otherwise, pick one at random.
    116 	 */
    117 	fsnum = tg->bindfs;
    118 	if (fsnum < 0)
    119 		fsnum = getrandom(rd, tg->fc->num_filesys);
    120 
    121 	params->fs = fc_get_fs(tg->fc, fsnum);
    122 }
    123 
    124 void tg_set_op_weight(ffsb_tg_t * tg, char *opname, unsigned weight)
    125 {
    126 	int opnum = ops_find_op(opname);
    127 	assert(opnum >= 0);
    128 	tg->op_weights[opnum] = weight;
    129 }
    130 
    131 unsigned tg_get_op_weight(ffsb_tg_t * tg, char *opname)
    132 {
    133 	int opnum = ops_find_op(opname);
    134 	assert(opnum >= 0);
    135 	return tg->op_weights[opnum];
    136 }
    137 
    138 void tg_set_bindfs(ffsb_tg_t * tg, int fsnum)
    139 {
    140 	tg->bindfs = fsnum;
    141 }
    142 
    143 int tg_get_bindfs(ffsb_tg_t * tg)
    144 {
    145 	return tg->bindfs;
    146 }
    147 
    148 unsigned tg_get_numthreads(ffsb_tg_t * tg)
    149 {
    150 	return tg->num_threads;
    151 }
    152 
    153 static void update_bufsize(ffsb_tg_t * tg)
    154 {
    155 	int i;
    156 	uint32_t newmax = max(tg->read_blocksize, tg->write_blocksize);
    157 
    158 	if (newmax == max(newmax, tg->thread_bufsize))
    159 		for (i = 0; i < tg->num_threads; i++)
    160 			ft_alter_bufsize(tg->threads + i, newmax);
    161 }
    162 
    163 void tg_set_read_random(ffsb_tg_t * tg, int rr)
    164 {
    165 	tg->read_random = rr;
    166 }
    167 
    168 void tg_set_write_random(ffsb_tg_t * tg, int wr)
    169 {
    170 	tg->write_random = wr;
    171 }
    172 
    173 void tg_set_fsync_file(ffsb_tg_t * tg, int fsync)
    174 {
    175 	tg->fsync_file = fsync;
    176 }
    177 
    178 void tg_set_read_size(ffsb_tg_t * tg, uint64_t rs)
    179 {
    180 	tg->read_size = rs;
    181 }
    182 
    183 void tg_set_read_blocksize(ffsb_tg_t * tg, uint32_t rs)
    184 {
    185 	tg->read_blocksize = rs;
    186 	update_bufsize(tg);
    187 }
    188 
    189 void tg_set_read_skip(ffsb_tg_t * tg, int rs)
    190 {
    191 	tg->read_skip = rs;
    192 }
    193 
    194 void tg_set_read_skipsize(ffsb_tg_t * tg, uint32_t rs)
    195 {
    196 	tg->read_skipsize = rs;
    197 }
    198 
    199 void tg_set_write_size(ffsb_tg_t * tg, uint64_t ws)
    200 {
    201 	tg->write_size = ws;
    202 }
    203 
    204 void tg_set_write_blocksize(ffsb_tg_t * tg, uint32_t ws)
    205 {
    206 	tg->write_blocksize = ws;
    207 	update_bufsize(tg);
    208 }
    209 
    210 int tg_get_read_random(ffsb_tg_t * tg)
    211 {
    212 	return tg->read_random;
    213 }
    214 
    215 int tg_get_write_random(ffsb_tg_t * tg)
    216 {
    217 	return tg->write_random;
    218 }
    219 
    220 int tg_get_fsync_file(ffsb_tg_t * tg)
    221 {
    222 	return tg->fsync_file;
    223 }
    224 
    225 uint64_t tg_get_read_size(ffsb_tg_t * tg)
    226 {
    227 	return tg->read_size;
    228 }
    229 
    230 uint32_t tg_get_read_blocksize(ffsb_tg_t * tg)
    231 {
    232 	return tg->read_blocksize;
    233 }
    234 
    235 int tg_get_read_skip(ffsb_tg_t * tg)
    236 {
    237 	return tg->read_skip;
    238 }
    239 
    240 uint32_t tg_get_read_skipsize(ffsb_tg_t * tg)
    241 {
    242 	return tg->read_skipsize;
    243 }
    244 
    245 uint64_t tg_get_write_size(ffsb_tg_t * tg)
    246 {
    247 	return tg->write_size;
    248 }
    249 
    250 uint32_t tg_get_write_blocksize(ffsb_tg_t * tg)
    251 {
    252 	return tg->write_blocksize;
    253 }
    254 
    255 int tg_get_stopval(ffsb_tg_t * tg)
    256 {
    257 	return tg->stopval;
    258 }
    259 
    260 ffsb_barrier_t *tg_get_start_barrier(ffsb_tg_t * tg)
    261 {
    262 	return tg->start_barrier;
    263 }
    264 
    265 static void tg_print_config_helper(ffsb_tg_t * tg)
    266 {
    267 	int i;
    268 	int sumweights = 0;
    269 	char buf[256];
    270 
    271 	printf("\t num_threads      = %d\n", tg->num_threads);
    272 	printf("\t\n");
    273 	printf("\t read_random      = %s\n", (tg->read_random) ? "on" : "off");
    274 	printf("\t read_size        = %llu\t(%s)\n", tg->read_size,
    275 	       ffsb_printsize(buf, tg->read_size, 256));
    276 	printf("\t read_blocksize   = %u\t(%s)\n", tg->read_blocksize,
    277 	       ffsb_printsize(buf, tg->read_blocksize, 256));
    278 	printf("\t read_skip        = %s\n", (tg->read_skip) ? "on" : "off");
    279 	printf("\t read_skipsize    = %u\t(%s)\n", tg->read_skipsize,
    280 	       ffsb_printsize(buf, tg->read_skipsize, 256));
    281 	printf("\t\n");
    282 	printf("\t write_random     = %s\n", (tg->write_random) ? "on" : "off");
    283 	printf("\t write_size       = %llu\t(%s)\n", tg->write_size,
    284 	       ffsb_printsize(buf, tg->write_size, 256));
    285 	printf("\t fsync_file       = %d\n", tg->fsync_file);
    286 	printf("\t write_blocksize  = %u\t(%s)\n", tg->write_blocksize,
    287 	       ffsb_printsize(buf, tg->write_blocksize, 256));
    288 	printf("\t wait time        = %u\n", tg->wait_time);
    289 	if (tg->bindfs >= 0) {
    290 		printf("\t\n");
    291 		printf("\t bound to fs %d\n", tg->bindfs);
    292 	}
    293 	printf("\t\n");
    294 	printf("\t op weights\n");
    295 
    296 	for (i = 0; i < FFSB_NUMOPS; i++)
    297 		sumweights += tg->op_weights[i];
    298 
    299 	for (i = 0; i < FFSB_NUMOPS; i++)
    300 		printf("\t %20s = %d (%.2f%%)\n", op_get_name(i),
    301 		       tg->op_weights[i], 100 * (float)tg->op_weights[i] /
    302 		       (float)sumweights);
    303 	printf("\t\n");
    304 }
    305 
    306 void tg_print_config(ffsb_tg_t * tg)
    307 {
    308 	printf("ThreadGroup %d\n", tg->tg_num);
    309 	printf("================\n");
    310 	tg_print_config_helper(tg);
    311 }
    312 
    313 void tg_print_config_aging(ffsb_tg_t * tg, char *fsname)
    314 {
    315 	printf("\t Aging ThreadGroup for fs %s\n", fsname);
    316 	printf("\t ================\n");
    317 	tg_print_config_helper(tg);
    318 }
    319 
    320 void tg_collect_results(ffsb_tg_t * tg, ffsb_op_results_t * r)
    321 {
    322 	int i;
    323 	for (i = 0; i < tg_get_numthreads(tg); i++)
    324 		add_results(r, ft_get_results(tg->threads + i));
    325 }
    326 
    327 void tg_set_waittime(ffsb_tg_t * tg, unsigned time)
    328 {
    329 	tg->wait_time = time;
    330 }
    331 
    332 unsigned tg_get_waittime(ffsb_tg_t * tg)
    333 {
    334 	return tg->wait_time;
    335 }
    336 
    337 int tg_get_flagval(ffsb_tg_t * tg)
    338 {
    339 	return tg->flagval;
    340 }
    341 
    342 void tg_set_statsc(ffsb_tg_t * tg, ffsb_statsc_t * fsc)
    343 {
    344 	if (fsc) {
    345 		int i;
    346 
    347 		tg->need_stats = 1;
    348 		ffsb_statsc_copy(&tg->fsc, fsc);
    349 
    350 		for (i = 0; i < tg->num_threads; i++)
    351 			ft_set_statsc(tg->threads + i, &tg->fsc);
    352 	}
    353 }
    354 
    355 void tg_collect_stats(ffsb_tg_t * tg, ffsb_statsd_t * fsd)
    356 {
    357 	int i;
    358 
    359 	assert(tg->need_stats);
    360 	ffsb_statsd_init(fsd, &tg->fsc);
    361 
    362 	for (i = 0; i < tg_get_numthreads(tg); i++)
    363 		ffsb_statsd_add(fsd, ft_get_stats_data(tg->threads + i));
    364 }
    365 
    366 int tg_needs_stats(ffsb_tg_t * tg)
    367 {
    368 	return tg->need_stats;
    369 }
    370