From 80cccc97eb5f2b57dd76a14df0ac730c10427bb2 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Tue, 29 Jan 2019 13:34:21 +0100 Subject: Improvements to get_pattern() --- src/im-sandbox.c | 274 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 158 insertions(+), 116 deletions(-) (limited to 'src/im-sandbox.c') diff --git a/src/im-sandbox.c b/src/im-sandbox.c index 4c3314bf..55ed939c 100644 --- a/src/im-sandbox.c +++ b/src/im-sandbox.c @@ -96,6 +96,17 @@ struct sandbox Stream *stream; }; +struct get_pattern_ctx +{ + FILE *fh; + int use_basename; + struct detector *det; + const char *prefix; + char *filename; + struct event_list *events; + int event_index; +}; + #ifdef HAVE_CLOCK_GETTIME @@ -163,151 +174,175 @@ static void check_hung_workers(struct sandbox *sb) } -static struct filename_plus_event *get_pattern(FILE *fh, int config_basename, - struct detector *det, - const char *prefix) +static char *read_prefixed_filename(struct get_pattern_ctx *gpctx, char **event) { - char *line = NULL; - size_t len; - struct filename_plus_event *fne; - struct hdfile *hdfile; - char filename_buf[2014]; - char event_buf[2014]; - - static char *filename = NULL; - static struct event_list *ev_list = NULL; - static int event_index = -1; - - line = malloc(1024*sizeof(char)); + char* line; - while ( event_index == -1 ) { + if ( event != NULL ) *event = NULL; - int scan_check; + line = malloc(1024); + if ( line == NULL ) return NULL; - do { - - /* Get the next filename */ - char *rval; - - rval = fgets(line, 1023, fh); - if ( rval == NULL ) { - free(line); - free(filename); - filename = NULL; - return NULL; + do { + if ( fgets(line, 1023, gpctx->fh) == NULL ) + { + if ( !feof(gpctx->fh) ) { + ERROR("Input file read error.\n"); } + return NULL; + } + chomp(line); + + } while ( line[0] == '\0' ); + + /* Chop off event ID if requested */ + if ( event != NULL ) { + size_t n = strlen(line); + while ( line[n] != ' ' && n > 2 ) n--; + if ( n != 2 ) { + /* Event descriptor must contain "//". + * If it doesn't, assume the filename just contains a + * space. */ + if ( strstr(&line[n], "//") != NULL ) { + line[n] = '\0'; + *event = strdup(&line[n]); + } + } /* else no spaces at all */ + } - chomp(line); - - } while ( strlen(line) == 0 ); + if ( gpctx->use_basename ) { + char *tmp; + tmp = safe_basename(line); + free(line); + line = tmp; + } - if ( config_basename ) { - char *tmp; - tmp = safe_basename(line); - free(line); - line = tmp; + /* Add prefix */ + if ( gpctx->prefix != NULL ) { + char *tmp; + size_t len = strlen(line) + strlen(gpctx->prefix) + 1; + tmp = malloc(len); + if ( tmp == NULL ) { + ERROR("Couldn't allocate memory for filename\n"); + return NULL; } + strcpy(tmp, gpctx->prefix); + strcat(tmp, line); + free(line); + line = tmp; + } - scan_check = sscanf(line, "%s %s", filename_buf, event_buf); + return line; +} - len = strlen(prefix)+strlen(filename_buf)+1; - /* Round the length of the buffer, to keep Valgrind quiet when - * it gets given to write() a bit later on */ - len += 4 - (len % 4); +static struct filename_plus_event *get_pattern(struct get_pattern_ctx *gpctx) +{ + char *filename; + char *evstr; - if ( filename == NULL ) { - filename = malloc(len); - } else { - char *new_filename; - new_filename = realloc(filename, len*sizeof(char)); - if ( filename == NULL ) { - return NULL; - } - filename = new_filename; + /* If single-event geometry, just return next filename */ + if ( !multi_event_geometry(gpctx->det) ) + { + struct filename_plus_event *fne; + fne = malloc(sizeof(struct filename_plus_event)); + if ( fne == NULL ) return NULL; + fne->filename = read_prefixed_filename(gpctx, NULL); + STATUS("Got '%s'\n", fne->filename); + if ( fne->filename == NULL ) { + free(fne); + return NULL; } + fne->ev = NULL; + return fne; + } - snprintf(filename, 1023, "%s%s", prefix, filename_buf); - - if ( det->path_dim != 0 || det->dim_dim != 0 ) { - - if ( is_cbf_file(filename) == 1 ) { - ERROR("Your geometry file is for a multi-event " - "format, but this file is in CBF format.\n"); - ERROR("Your geometry file probably needs to be " - "changed.\n"); - return NULL; - } - - ev_list = initialize_event_list(); + /* Ok, multi-event geometry. Is an event available already? */ + if ( (gpctx->events != NULL) + && (gpctx->event_index < gpctx->events->num_events) ) + { + struct filename_plus_event *fne; + fne = malloc(sizeof(struct filename_plus_event)); + fne->filename = strdup(gpctx->filename); + fne->ev = copy_event(gpctx->events->events[gpctx->event_index++]); - if ( scan_check == 1 ) { + return fne; + } - hdfile = hdfile_open(filename); - if ( hdfile == NULL ) { - ERROR("Failed to open %s\n", filename); - free(line); - return NULL; - } + /* No events in list. Time to top it up */ + filename = read_prefixed_filename(gpctx, &evstr); - if ( ev_list != NULL ) { - free_event_list(ev_list); - } + /* Nothing left in file -> we're done */ + if ( filename == NULL ) return NULL; - ev_list = fill_event_list(hdfile, det); - if ( ev_list == NULL ) { - ERROR("Failed to get event list.\n"); - return NULL; - } + /* Muppet check */ + if ( is_cbf_file(filename) == 1 ) { + ERROR("Your geometry file is for a multi-event format, but " + "this file is in CBF format.\n"); + ERROR("Your geometry file probably needs to be changed.\n"); + return NULL; + } - if ( ev_list->num_events == 0 ) { - event_index = -1; - } else { - event_index = 0; - } + /* Does the line from the input file contain an event ID? */ + if ( evstr != NULL ) { - hdfile_close(hdfile); + /* Make an event list with only one item */ + struct event *ev = get_event_from_event_string(evstr); + if ( ev == NULL ) { + ERROR("Bad event descriptor: '%s'\n", evstr); + } else { + free_event_list(gpctx->events); + gpctx->events = initialize_event_list(); + append_event_to_event_list(gpctx->events, ev); + free_event(ev); + } - } else { + } else { - struct event *ev_to_add; + /* Enumerate all the events in the file */ + struct hdfile *hdfile; - ev_to_add = get_event_from_event_string(event_buf); - if ( ev_to_add == NULL ) { - ERROR("Bad event descriptor: '%s'\n", - event_buf); - } else { - append_event_to_event_list(ev_list, - ev_to_add); - free_event(ev_to_add); - event_index = 0; - } + hdfile = hdfile_open(filename); + if ( hdfile == NULL ) { + ERROR("Failed to open %s\n", filename); + return NULL; + } - } + if ( gpctx->events != NULL ) { + free_event_list(gpctx->events); + } - } else { + gpctx->events = fill_event_list(hdfile, gpctx->det); + if ( gpctx->events == NULL ) { + ERROR("Failed to get event list.\n"); + return NULL; + } - event_index = 0; + hdfile_close(hdfile); - } } - fne = malloc(sizeof(struct filename_plus_event)); - fne->filename = strdup(filename); + /* If the filename has changed, return NULL now. The next caller will + * receive the event(s) just added */ + if ( gpctx->filename != NULL ) { - if ( multi_event_geometry(gpctx->det) ) { - fne->ev = copy_event(ev_list->events[event_index]); - if ( event_index != ev_list->num_events-1 ) { - event_index += 1; + if ( strcmp(filename, gpctx->filename) != 0 ) { + free(gpctx->filename); + gpctx->filename = filename; + return NULL; } else { - event_index = -1; + free(filename); /* gpctx->filename will be used */ } + } else { - fne->ev = NULL; - event_index = -1; + /* First filename */ + gpctx->filename = filename; } - free(line); + struct filename_plus_event *fne; + fne = malloc(sizeof(struct filename_plus_event)); + fne->filename = strdup(gpctx->filename); + fne->ev = copy_event(gpctx->events->events[gpctx->event_index++]); return fne; } @@ -779,15 +814,14 @@ static char *maybe_get_event_string(struct event *ev) /* Assumes the caller is already holding queue_lock! */ -static int fill_queue(FILE *fh, int config_basename, struct detector *det, - const char *prefix, struct sandbox *sb) +static int fill_queue(struct get_pattern_ctx *gpctx, struct sandbox *sb) { while ( sb->shared->n_events < QUEUE_SIZE ) { struct filename_plus_event *ne; char ev_string[MAX_EV_LEN]; - ne = get_pattern(fh, config_basename, det, prefix); + ne = get_pattern(gpctx); if ( ne == NULL ) return 1; /* No more */ memset(ev_string, 0, MAX_EV_LEN); @@ -972,6 +1006,7 @@ int create_sandbox(struct index_args *iargs, int n_proc, char *prefix, int no_more = 0; int allDone = 0; TimeAccounts *taccs; + struct get_pattern_ctx gpctx; if ( n_proc > MAX_NUM_WORKERS ) { ERROR("Number of workers (%i) is too large. Using %i\n", @@ -996,6 +1031,14 @@ int create_sandbox(struct index_args *iargs, int n_proc, char *prefix, sb->fhs = NULL; sb->stream = stream; + gpctx.fh = fh; + gpctx.use_basename = config_basename; + gpctx.det = iargs->det; + gpctx.prefix = prefix; + gpctx.filename = NULL; + gpctx.events = NULL; + gpctx.event_index = 0; + if ( setup_shm(sb) ) { ERROR("Failed to set up SHM.\n"); free(sb); @@ -1028,7 +1071,7 @@ int create_sandbox(struct index_args *iargs, int n_proc, char *prefix, /* Fill the queue */ pthread_mutex_lock(&sb->shared->queue_lock); sb->shared->n_events = 0; - fill_queue(fh, config_basename, iargs->det, prefix, sb); + fill_queue(&gpctx, sb); sb->shared->no_more = 0; pthread_mutex_unlock(&sb->shared->queue_lock); @@ -1082,8 +1125,7 @@ int create_sandbox(struct index_args *iargs, int n_proc, char *prefix, time_accounts_set(taccs, TACC_QUEUETOPUP); pthread_mutex_lock(&sb->shared->queue_lock); if ( !no_more && (sb->shared->n_events < QUEUE_SIZE/2) ) { - if ( fill_queue(fh, config_basename, iargs->det, - prefix, sb) ) no_more = 1; + if ( fill_queue(&gpctx, sb) ) no_more = 1; } pthread_mutex_unlock(&sb->shared->queue_lock); -- cgit v1.2.3