diff options
| author | Paul Bütow <pbuetow@mimecast.com> | 2018-03-01 11:21:26 +0000 |
|---|---|---|
| committer | Paul Bütow <pbuetow@mimecast.com> | 2018-03-01 11:21:26 +0000 |
| commit | 56f8cdff9aaa9bf00c5dc9441a7569374f2cbafb (patch) | |
| tree | b5b440b504b9879e241733fa38d19089fb3377b2 /ioreplay/src/generate/gparser.c | |
initial commit0.1
Diffstat (limited to 'ioreplay/src/generate/gparser.c')
| -rw-r--r-- | ioreplay/src/generate/gparser.c | 356 |
1 files changed, 356 insertions, 0 deletions
diff --git a/ioreplay/src/generate/gparser.c b/ioreplay/src/generate/gparser.c new file mode 100644 index 0000000..514128f --- /dev/null +++ b/ioreplay/src/generate/gparser.c @@ -0,0 +1,356 @@ +// Copyright 2018 Mimecast Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "gparser.h" + +#include "gtask.h" +#include "gwriter.h" + +void* gparser_pthread_start(void *data) +{ + gparser_s *p = data; + generate_s *g = p->generate; + gwriter_s *w = g->writer; + gtask_s *t = NULL; + + do { + while (NULL != (t = rbuffer_get_next(p->queue))) { + // First extract + gparser_extract(p, t); + // Second, pass the task to the writer thread + rbuffer_insert(w->queue, t); + } + usleep(100); + } while (!p->terminate); + + while (NULL != (t = rbuffer_get_next(p->queue))) { + gparser_extract(p, t); + rbuffer_insert(w->queue, t); + } + + return NULL; +} + +gparser_s* gparser_new(generate_s *g) +{ + gparser_s *p = Malloc(gparser_s); + + p->generate = g; + p->terminate = false; + p->queue = rbuffer_new(1024); + + return p; +} + +void gparser_start(gparser_s *p) +{ + start_pthread(&p->pthread, gparser_pthread_start, (void*)p); +} + +void gparser_destroy(gparser_s *p) +{ + rbuffer_destroy(p->queue); + free(p); +} + +void gparser_terminate(gparser_s *p) +{ + p->terminate = true; + pthread_join(p->pthread, NULL); +} + +void gparser_extract(gparser_s *p, gtask_s *t) +{ + status_e ret = SUCCESS; + generate_s *g = p->generate; + + char *saveptr; + char* tok = strtok2_r(t->line, ";:,", &saveptr); + int ntoks = 0; + + while (tok) { + if (++ntoks > MAX_TOKENS) { + ret = ERROR; + break; + } + ret = gparser_extract_tok(p, t, tok); + if (ret != SUCCESS) + break; + + tok = strtok2_r(NULL, ";:,", &saveptr); + } + + if (ret == SUCCESS) { + + // Check for the existance of mandatory values! + if (t->pid < 0 || t->tid < 0) { + Cleanup(ERROR); + + } else if (t->op == NULL) { + Cleanup(ERROR); + + } else if (t->mapped_time == -1) { + Cleanup(ERROR); + } + + // We are inserting ".ioreplay/NAME" to the paths. This enables us to + // run multiple tests simoultaneously. + + if (t->path) { + if (!mounts_transform_path(g->mps, g->name, + t->path, &t->path_r)) { + Cleanup(ERROR); + } + if (t->path_r) + t->path = t->path_r; + } + + if (t->path2) { + if (!mounts_transform_path(g->mps, g->name, + t->path2, &t->path2_r)) { + Cleanup(ERROR); + } + if (t->path2_r) + t->path2 = t->path2_r; + } + + } + +cleanup: + + t->ret = ret; + +#ifdef LOG_FILTERED + t->filtered_where = __FILE__; +#endif +} + +status_e gparser_extract_tok(gparser_s *p, gtask_s *t, char *tok) +{ + status_e ret = SUCCESS; + + if (gparser_token_not_ok(p, tok)) { + Cleanup(ERROR); + } + + generate_s *g = t->generate; + + char key = tok[0]; + char *value = tok; + value += 2; + + switch (key) { + case 'a': + // Address + t->address = strtol(value, NULL, 10); + break; + + case 'A': + // Address 2 + t->address2 = strtol(value, NULL, 10); + break; + + case 'b': + // Bytes + if (t->bytes != -1) { + Cleanup(ERROR); + } + if (is_number(value) == 0) { + Cleanup(ERROR); + } + t->bytes = strtol(value, NULL, 10); + break; + + case 'c': + // Count + if (t->count != -1) { + Cleanup(ERROR); + } + if (is_number(value) == 0) { + Cleanup(ERROR); + } + t->count = strtol(value, NULL, 10); + break; + + case 'd': + // Descriptor + if (t->fd != -1) { + Cleanup(ERROR); + } + if (is_number(value) == 0) { + Cleanup(ERROR); + } + t->fd = atoi(value); + if (t->fd > 0) + t->has_fd = true; + break; + + case 'f': + // Flags + if (is_number(value) == 0) { + Cleanup(ERROR); + } + t->flags = atoi(value); + break; + + case 'i': + // PID:TID + t->pidtid = value; + // Extract PID and TID from "PID:TID" + if (!gparser_get_pidtid(p, t->pidtid, &t->pid, &t->tid)) { + Cleanup(ERROR); + } + break; + + case 'm': + // Mode + if (is_number(value) == 0) { + Cleanup(ERROR); + } + t->mode = atoi(value); + break; + + case 'o': + // Operation + t->op = value; + break; + + case 'O': + if (is_number(value) == 0) { + Cleanup(ERROR); + } + t->offset = strtol(value, NULL, 10); + break; + + case 'W': + if (is_number(value) == 0) { + Cleanup(ERROR); + } + t->whence = strtol(value, NULL, 10); + break; + + case 'p': + // File path + t->path = value; + chreplace(t->path, '|', '_'); + strunquote(t->path); + break; + + case 'P': + // File path 2 + t->path2 = value; + chreplace(t->path2, '|', '_'); + strunquote(t->path2); + break; + + case 's': + // Cleanup status + if (is_number(value) == 0) { + Cleanup(ERROR); + } + t->status = atoi(value); + break; + + case 't': + // Time + if (is_number(value) == 0) { + Cleanup(ERROR); + } + t->mapped_time = strtol(value, NULL, 10); + // Start replay time from 0 + if (g->start_time == -1) { + g->start_time = t->mapped_time; + } + t->mapped_time -= g->start_time; + break; + + case 'F': + // FCNTL function + if (is_number(value) == 0) { + Cleanup(ERROR); + } + t->F = atoi(value); + break; + + case 'G': + // FCNTL argument + if (is_number(value) == 0) { + Cleanup(ERROR); + } + t->G = atoi(value); + break; + + case 'T': + break; + + default: + // Unknown key + { + Cleanup(ERROR); + } + } + +cleanup: + if (t->path_r) { + free(t->path_r); + t->path_r = NULL; + } + if (t->path2_r) { + free(t->path2_r); + t->path2_r = NULL; + } + + return ret; +} + +bool gparser_token_not_ok(gparser_s *p, char *tok) +{ + if (strlen(tok) < 3) { + return true; + + } else if (tok[1] != '=') { + return true; + } + + return false; +} + +bool gparser_get_pidtid(gparser_s *p, char *pidtid, long *pid, long *tid) +{ + char *pos = strchr(pidtid, ':'); + + if (pos) { + char *tmp = pos; + tmp++; + + if (is_number(tmp)) { + *tid = atol(tmp); + } else { + return false; + } + + pos[0] = '\0'; + if (is_number(pidtid)) { + *pid = atol(pidtid); + } else { + return false; + } + } + + else { + return false; + } + + return (*pid >= 0 && *tid >= 0); +} |
