1488570ebSJim Harris /* SPDX-License-Identifier: BSD-3-Clause 2a6dbe372Spaul luse * Copyright (C) 2021 Intel Corporation. 3d919a197SKonrad Sztyber * All rights reserved. 4d919a197SKonrad Sztyber */ 5d919a197SKonrad Sztyber 6d919a197SKonrad Sztyber #include "spdk/stdinc.h" 7ffaec5f9SKonrad Sztyber #include "spdk/likely.h" 855f64c36SKonrad Sztyber #include "spdk/log.h" 9d919a197SKonrad Sztyber #include "spdk/trace_parser.h" 1041ba2b30SKonrad Sztyber #include "spdk/util.h" 11*ee32a82bSAnisa Su #include "spdk/env.h" 12d919a197SKonrad Sztyber 1355f64c36SKonrad Sztyber #include <exception> 144ba77072SKonrad Sztyber #include <map> 1555f64c36SKonrad Sztyber #include <new> 1655f64c36SKonrad Sztyber 174ba77072SKonrad Sztyber struct entry_key { 184ba77072SKonrad Sztyber entry_key(uint16_t _lcore, uint64_t _tsc) : lcore(_lcore), tsc(_tsc) {} 194ba77072SKonrad Sztyber uint16_t lcore; 204ba77072SKonrad Sztyber uint64_t tsc; 214ba77072SKonrad Sztyber }; 224ba77072SKonrad Sztyber 234ba77072SKonrad Sztyber class compare_entry_key 244ba77072SKonrad Sztyber { 254ba77072SKonrad Sztyber public: 264ba77072SKonrad Sztyber bool operator()(const entry_key &first, const entry_key &second) const 274ba77072SKonrad Sztyber { 284ba77072SKonrad Sztyber if (first.tsc == second.tsc) { 294ba77072SKonrad Sztyber return first.lcore < second.lcore; 304ba77072SKonrad Sztyber } else { 314ba77072SKonrad Sztyber return first.tsc < second.tsc; 324ba77072SKonrad Sztyber } 334ba77072SKonrad Sztyber } 344ba77072SKonrad Sztyber }; 354ba77072SKonrad Sztyber 364ba77072SKonrad Sztyber typedef std::map<entry_key, spdk_trace_entry *, compare_entry_key> entry_map; 374ba77072SKonrad Sztyber 38ffaec5f9SKonrad Sztyber struct argument_context { 39ffaec5f9SKonrad Sztyber spdk_trace_entry *entry; 40ffaec5f9SKonrad Sztyber spdk_trace_entry_buffer *buffer; 41ffaec5f9SKonrad Sztyber uint16_t lcore; 42ffaec5f9SKonrad Sztyber size_t offset; 43ffaec5f9SKonrad Sztyber 44ffaec5f9SKonrad Sztyber argument_context(spdk_trace_entry *entry, uint16_t lcore) : 45ffaec5f9SKonrad Sztyber entry(entry), lcore(lcore) 46ffaec5f9SKonrad Sztyber { 47ffaec5f9SKonrad Sztyber buffer = reinterpret_cast<spdk_trace_entry_buffer *>(entry); 48ffaec5f9SKonrad Sztyber 49ffaec5f9SKonrad Sztyber /* The first argument resides within the spdk_trace_entry structure, so the initial 50ffaec5f9SKonrad Sztyber * offset needs to be adjusted to the start of the spdk_trace_entry.args array 51ffaec5f9SKonrad Sztyber */ 52ffaec5f9SKonrad Sztyber offset = offsetof(spdk_trace_entry, args) - 53ffaec5f9SKonrad Sztyber offsetof(spdk_trace_entry_buffer, data); 54ffaec5f9SKonrad Sztyber } 55ffaec5f9SKonrad Sztyber }; 56ffaec5f9SKonrad Sztyber 57f243f624SKonrad Sztyber struct object_stats { 58f243f624SKonrad Sztyber std::map<uint64_t, uint64_t> index; 59f243f624SKonrad Sztyber std::map<uint64_t, uint64_t> start; 60f243f624SKonrad Sztyber uint64_t counter; 61f243f624SKonrad Sztyber 62f243f624SKonrad Sztyber object_stats() : counter(0) {} 63f243f624SKonrad Sztyber }; 64f243f624SKonrad Sztyber 6555f64c36SKonrad Sztyber struct spdk_trace_parser { 6655f64c36SKonrad Sztyber spdk_trace_parser(const spdk_trace_parser_opts *opts); 6755f64c36SKonrad Sztyber ~spdk_trace_parser(); 6855f64c36SKonrad Sztyber spdk_trace_parser(const spdk_trace_parser &) = delete; 6955f64c36SKonrad Sztyber spdk_trace_parser &operator=(const spdk_trace_parser &) = delete; 7023dbcec5SJim Harris const spdk_trace_file *file() const { return _trace_file; } 716727cc38SKonrad Sztyber uint64_t tsc_offset() const { return _tsc_offset; } 72279b7babSKonrad Sztyber bool next_entry(spdk_trace_parser_entry *entry); 73189b0f09SKonrad Sztyber uint64_t entry_count(uint16_t lcore) const; 7455f64c36SKonrad Sztyber private: 75ffaec5f9SKonrad Sztyber spdk_trace_entry_buffer *get_next_buffer(spdk_trace_entry_buffer *buf, uint16_t lcore); 76ffaec5f9SKonrad Sztyber bool build_arg(argument_context *argctx, const spdk_trace_argument *arg, int argid, 77ffaec5f9SKonrad Sztyber spdk_trace_parser_entry *pe); 78*ee32a82bSAnisa Su void populate_events(spdk_trace_history *history, int num_entries, bool overflowed); 7955f64c36SKonrad Sztyber bool init(const spdk_trace_parser_opts *opts); 8055f64c36SKonrad Sztyber void cleanup(); 8155f64c36SKonrad Sztyber 8214e26b9dSJim Harris spdk_trace_file *_trace_file; 8355f64c36SKonrad Sztyber size_t _map_size; 8455f64c36SKonrad Sztyber int _fd; 854ba77072SKonrad Sztyber uint64_t _tsc_offset; 864ba77072SKonrad Sztyber entry_map _entries; 87279b7babSKonrad Sztyber entry_map::iterator _iter; 88f243f624SKonrad Sztyber object_stats _stats[SPDK_TRACE_MAX_OBJECT]; 8955f64c36SKonrad Sztyber }; 9055f64c36SKonrad Sztyber 91189b0f09SKonrad Sztyber uint64_t 92189b0f09SKonrad Sztyber spdk_trace_parser::entry_count(uint16_t lcore) const 93189b0f09SKonrad Sztyber { 94189b0f09SKonrad Sztyber spdk_trace_history *history; 95189b0f09SKonrad Sztyber 96189b0f09SKonrad Sztyber if (lcore >= SPDK_TRACE_MAX_LCORE) { 97189b0f09SKonrad Sztyber return 0; 98189b0f09SKonrad Sztyber } 99189b0f09SKonrad Sztyber 10014e26b9dSJim Harris history = spdk_get_per_lcore_history(_trace_file, lcore); 101189b0f09SKonrad Sztyber 10218c8b52aSJim Harris return history == NULL ? 0 : history->num_entries; 103189b0f09SKonrad Sztyber } 104189b0f09SKonrad Sztyber 105ffaec5f9SKonrad Sztyber spdk_trace_entry_buffer * 106ffaec5f9SKonrad Sztyber spdk_trace_parser::get_next_buffer(spdk_trace_entry_buffer *buf, uint16_t lcore) 107279b7babSKonrad Sztyber { 108ffaec5f9SKonrad Sztyber spdk_trace_history *history; 109ffaec5f9SKonrad Sztyber 11014e26b9dSJim Harris history = spdk_get_per_lcore_history(_trace_file, lcore); 111ffaec5f9SKonrad Sztyber assert(history); 112ffaec5f9SKonrad Sztyber 113ffaec5f9SKonrad Sztyber if (spdk_unlikely(static_cast<void *>(buf) == 114ffaec5f9SKonrad Sztyber static_cast<void *>(&history->entries[history->num_entries - 1]))) { 115ffaec5f9SKonrad Sztyber return reinterpret_cast<spdk_trace_entry_buffer *>(&history->entries[0]); 116ffaec5f9SKonrad Sztyber } else { 117ffaec5f9SKonrad Sztyber return buf + 1; 118ffaec5f9SKonrad Sztyber } 119ffaec5f9SKonrad Sztyber } 120ffaec5f9SKonrad Sztyber 121ffaec5f9SKonrad Sztyber bool 122ffaec5f9SKonrad Sztyber spdk_trace_parser::build_arg(argument_context *argctx, const spdk_trace_argument *arg, int argid, 123ffaec5f9SKonrad Sztyber spdk_trace_parser_entry *pe) 124ffaec5f9SKonrad Sztyber { 125ffaec5f9SKonrad Sztyber spdk_trace_entry *entry = argctx->entry; 126ffaec5f9SKonrad Sztyber spdk_trace_entry_buffer *buffer = argctx->buffer; 127ffaec5f9SKonrad Sztyber size_t curlen, argoff; 128ffaec5f9SKonrad Sztyber 129ffaec5f9SKonrad Sztyber argoff = 0; 13067eb86e3SJim Harris pe->args[argid].is_related = false; 131cdb0726bSJim Harris /* Make sure that if we only copy a 4-byte integer, that the upper bytes have already been 132cdb0726bSJim Harris * zeroed. 133cdb0726bSJim Harris */ 134b4ba6cdfSJim Harris pe->args[argid].u.integer = 0; 135ffaec5f9SKonrad Sztyber while (argoff < arg->size) { 136ffaec5f9SKonrad Sztyber if (argctx->offset == sizeof(buffer->data)) { 137ffaec5f9SKonrad Sztyber buffer = get_next_buffer(buffer, argctx->lcore); 138ffaec5f9SKonrad Sztyber if (spdk_unlikely(buffer->tpoint_id != SPDK_TRACE_MAX_TPOINT_ID || 139ffaec5f9SKonrad Sztyber buffer->tsc != entry->tsc)) { 140ffaec5f9SKonrad Sztyber return false; 141ffaec5f9SKonrad Sztyber } 142ffaec5f9SKonrad Sztyber 143ffaec5f9SKonrad Sztyber argctx->offset = 0; 144ffaec5f9SKonrad Sztyber argctx->buffer = buffer; 145ffaec5f9SKonrad Sztyber } 146ffaec5f9SKonrad Sztyber 147ffaec5f9SKonrad Sztyber curlen = spdk_min(sizeof(buffer->data) - argctx->offset, arg->size - argoff); 1487025ceb9SMarcin Spiewak if (argoff < sizeof(pe->args[0].u.string)) { 149b4ba6cdfSJim Harris memcpy(&pe->args[argid].u.string[argoff], &buffer->data[argctx->offset], 1507025ceb9SMarcin Spiewak spdk_min(curlen, sizeof(pe->args[0].u.string) - argoff)); 151ffaec5f9SKonrad Sztyber } 152ffaec5f9SKonrad Sztyber 153ffaec5f9SKonrad Sztyber argctx->offset += curlen; 154ffaec5f9SKonrad Sztyber argoff += curlen; 155ffaec5f9SKonrad Sztyber } 156ffaec5f9SKonrad Sztyber 157ffaec5f9SKonrad Sztyber return true; 158ffaec5f9SKonrad Sztyber } 159ffaec5f9SKonrad Sztyber 160ffaec5f9SKonrad Sztyber bool 161ffaec5f9SKonrad Sztyber spdk_trace_parser::next_entry(spdk_trace_parser_entry *pe) 162ffaec5f9SKonrad Sztyber { 163ffaec5f9SKonrad Sztyber spdk_trace_tpoint *tpoint; 164ffaec5f9SKonrad Sztyber spdk_trace_entry *entry; 165f243f624SKonrad Sztyber object_stats *stats; 16670c17160SKrzysztof Karas std::map<uint64_t, uint64_t>::iterator related_kv; 167ffaec5f9SKonrad Sztyber 168279b7babSKonrad Sztyber if (_iter == _entries.end()) { 169279b7babSKonrad Sztyber return false; 170279b7babSKonrad Sztyber } 171279b7babSKonrad Sztyber 172ffaec5f9SKonrad Sztyber pe->entry = entry = _iter->second; 173ffaec5f9SKonrad Sztyber pe->lcore = _iter->first.lcore; 17470c17160SKrzysztof Karas /* Set related index to the max value to indicate "empty" state */ 17570c17160SKrzysztof Karas pe->related_index = UINT64_MAX; 17670c17160SKrzysztof Karas pe->related_type = OBJECT_NONE; 17723dbcec5SJim Harris tpoint = &_trace_file->tpoint[entry->tpoint_id]; 178f243f624SKonrad Sztyber stats = &_stats[tpoint->object_type]; 179f243f624SKonrad Sztyber 180f243f624SKonrad Sztyber if (tpoint->new_object) { 181f243f624SKonrad Sztyber stats->index[entry->object_id] = stats->counter++; 182f243f624SKonrad Sztyber stats->start[entry->object_id] = entry->tsc; 183f243f624SKonrad Sztyber } 184f243f624SKonrad Sztyber 185f243f624SKonrad Sztyber if (tpoint->object_type != OBJECT_NONE) { 186f243f624SKonrad Sztyber if (spdk_likely(stats->start.find(entry->object_id) != stats->start.end())) { 187f243f624SKonrad Sztyber pe->object_index = stats->index[entry->object_id]; 188f243f624SKonrad Sztyber pe->object_start = stats->start[entry->object_id]; 189f243f624SKonrad Sztyber } else { 190f243f624SKonrad Sztyber pe->object_index = UINT64_MAX; 191f243f624SKonrad Sztyber pe->object_start = UINT64_MAX; 192f243f624SKonrad Sztyber } 193f243f624SKonrad Sztyber } 194ffaec5f9SKonrad Sztyber 195ffaec5f9SKonrad Sztyber argument_context argctx(entry, pe->lcore); 196ffaec5f9SKonrad Sztyber for (uint8_t i = 0; i < tpoint->num_args; ++i) { 197ffaec5f9SKonrad Sztyber if (!build_arg(&argctx, &tpoint->args[i], i, pe)) { 198ffaec5f9SKonrad Sztyber SPDK_ERRLOG("Failed to parse tracepoint argument\n"); 199ffaec5f9SKonrad Sztyber return false; 200ffaec5f9SKonrad Sztyber } 201ffaec5f9SKonrad Sztyber } 202279b7babSKonrad Sztyber 20370c17160SKrzysztof Karas for (uint8_t i = 0; i < SPDK_TRACE_MAX_RELATIONS; ++i) { 20470c17160SKrzysztof Karas /* The relations are stored inside a tpoint, which means there might be 20570c17160SKrzysztof Karas * multiple objects bound to a single tpoint. */ 20670c17160SKrzysztof Karas if (tpoint->related_objects[i].object_type == OBJECT_NONE) { 20770c17160SKrzysztof Karas break; 20870c17160SKrzysztof Karas } 20970c17160SKrzysztof Karas stats = &_stats[tpoint->related_objects[i].object_type]; 21070c17160SKrzysztof Karas related_kv = stats->index.find(reinterpret_cast<uint64_t> 211b4ba6cdfSJim Harris (pe->args[tpoint->related_objects[i].arg_index].u.pointer)); 21270c17160SKrzysztof Karas /* To avoid parsing the whole array, object index and type are stored 21370c17160SKrzysztof Karas * directly inside spdk_trace_parser_entry. */ 21470c17160SKrzysztof Karas if (related_kv != stats->index.end()) { 21570c17160SKrzysztof Karas pe->related_index = related_kv->second; 21670c17160SKrzysztof Karas pe->related_type = tpoint->related_objects[i].object_type; 21767eb86e3SJim Harris pe->args[tpoint->related_objects[i].arg_index].is_related = true; 21870c17160SKrzysztof Karas break; 21970c17160SKrzysztof Karas } 22070c17160SKrzysztof Karas } 22170c17160SKrzysztof Karas 222279b7babSKonrad Sztyber _iter++; 223279b7babSKonrad Sztyber return true; 224279b7babSKonrad Sztyber } 225279b7babSKonrad Sztyber 2264ba77072SKonrad Sztyber void 227*ee32a82bSAnisa Su spdk_trace_parser::populate_events(spdk_trace_history *history, int num_entries, bool overflowed) 2284ba77072SKonrad Sztyber { 2294ba77072SKonrad Sztyber int i, num_entries_filled; 2304ba77072SKonrad Sztyber spdk_trace_entry *e; 2314ba77072SKonrad Sztyber int first, last, lcore; 2324ba77072SKonrad Sztyber 2334ba77072SKonrad Sztyber lcore = history->lcore; 2344ba77072SKonrad Sztyber e = history->entries; 2354ba77072SKonrad Sztyber 2364ba77072SKonrad Sztyber num_entries_filled = num_entries; 2374ba77072SKonrad Sztyber while (e[num_entries_filled - 1].tsc == 0) { 2384ba77072SKonrad Sztyber num_entries_filled--; 2394ba77072SKonrad Sztyber } 2404ba77072SKonrad Sztyber 2414ba77072SKonrad Sztyber if (num_entries == num_entries_filled) { 2424ba77072SKonrad Sztyber first = last = 0; 2434ba77072SKonrad Sztyber for (i = 1; i < num_entries; i++) { 2444ba77072SKonrad Sztyber if (e[i].tsc < e[first].tsc) { 2454ba77072SKonrad Sztyber first = i; 2464ba77072SKonrad Sztyber } 2474ba77072SKonrad Sztyber if (e[i].tsc > e[last].tsc) { 2484ba77072SKonrad Sztyber last = i; 2494ba77072SKonrad Sztyber } 2504ba77072SKonrad Sztyber } 2514ba77072SKonrad Sztyber } else { 2524ba77072SKonrad Sztyber first = 0; 2534ba77072SKonrad Sztyber last = num_entries_filled - 1; 2544ba77072SKonrad Sztyber } 2554ba77072SKonrad Sztyber 2564ba77072SKonrad Sztyber /* 257*ee32a82bSAnisa Su * We keep track of the highest first TSC out of all reactors iff. any 258*ee32a82bSAnisa Su * have overflowed their circular buffer. 259cc6920a4SJosh Soref * We will ignore any events that occurred before this TSC on any 2604ba77072SKonrad Sztyber * other reactors. This will ensure we only print data for the 2614ba77072SKonrad Sztyber * subset of time where we have data across all reactors. 2624ba77072SKonrad Sztyber */ 263*ee32a82bSAnisa Su if (e[first].tsc > _tsc_offset && overflowed) { 2644ba77072SKonrad Sztyber _tsc_offset = e[first].tsc; 2654ba77072SKonrad Sztyber } 2664ba77072SKonrad Sztyber 2674ba77072SKonrad Sztyber i = first; 2684ba77072SKonrad Sztyber while (1) { 2694ba77072SKonrad Sztyber if (e[i].tpoint_id != SPDK_TRACE_MAX_TPOINT_ID) { 2704ba77072SKonrad Sztyber _entries[entry_key(lcore, e[i].tsc)] = &e[i]; 2714ba77072SKonrad Sztyber } 2724ba77072SKonrad Sztyber if (i == last) { 2734ba77072SKonrad Sztyber break; 2744ba77072SKonrad Sztyber } 2754ba77072SKonrad Sztyber i++; 2764ba77072SKonrad Sztyber if (i == num_entries_filled) { 2774ba77072SKonrad Sztyber i = 0; 2784ba77072SKonrad Sztyber } 2794ba77072SKonrad Sztyber } 2804ba77072SKonrad Sztyber } 2814ba77072SKonrad Sztyber 28255f64c36SKonrad Sztyber bool 28355f64c36SKonrad Sztyber spdk_trace_parser::init(const spdk_trace_parser_opts *opts) 28455f64c36SKonrad Sztyber { 2854ba77072SKonrad Sztyber spdk_trace_history *history; 28655f64c36SKonrad Sztyber struct stat st; 287*ee32a82bSAnisa Su int rc, i, entry_num; 288*ee32a82bSAnisa Su bool overflowed; 28955f64c36SKonrad Sztyber 29055f64c36SKonrad Sztyber switch (opts->mode) { 29155f64c36SKonrad Sztyber case SPDK_TRACE_PARSER_MODE_FILE: 29255f64c36SKonrad Sztyber _fd = open(opts->filename, O_RDONLY); 29355f64c36SKonrad Sztyber break; 29455f64c36SKonrad Sztyber case SPDK_TRACE_PARSER_MODE_SHM: 29555f64c36SKonrad Sztyber _fd = shm_open(opts->filename, O_RDONLY, 0600); 29655f64c36SKonrad Sztyber break; 29755f64c36SKonrad Sztyber default: 29855f64c36SKonrad Sztyber SPDK_ERRLOG("Invalid mode: %d\n", opts->mode); 29955f64c36SKonrad Sztyber return false; 30055f64c36SKonrad Sztyber } 30155f64c36SKonrad Sztyber 30255f64c36SKonrad Sztyber if (_fd < 0) { 30355f64c36SKonrad Sztyber SPDK_ERRLOG("Could not open trace file: %s (%d)\n", opts->filename, errno); 30455f64c36SKonrad Sztyber return false; 30555f64c36SKonrad Sztyber } 30655f64c36SKonrad Sztyber 30755f64c36SKonrad Sztyber rc = fstat(_fd, &st); 30855f64c36SKonrad Sztyber if (rc < 0) { 30955f64c36SKonrad Sztyber SPDK_ERRLOG("Could not get size of trace file: %s\n", opts->filename); 31055f64c36SKonrad Sztyber return false; 31155f64c36SKonrad Sztyber } 31255f64c36SKonrad Sztyber 31314e26b9dSJim Harris if ((size_t)st.st_size < sizeof(*_trace_file)) { 31455f64c36SKonrad Sztyber SPDK_ERRLOG("Invalid trace file: %s\n", opts->filename); 31555f64c36SKonrad Sztyber return false; 31655f64c36SKonrad Sztyber } 31755f64c36SKonrad Sztyber 31855f64c36SKonrad Sztyber /* Map the header of trace file */ 31914e26b9dSJim Harris _map_size = sizeof(*_trace_file); 32014e26b9dSJim Harris _trace_file = static_cast<spdk_trace_file *>(mmap(NULL, _map_size, PROT_READ, 32155f64c36SKonrad Sztyber MAP_SHARED, _fd, 0)); 32214e26b9dSJim Harris if (_trace_file == MAP_FAILED) { 32355f64c36SKonrad Sztyber SPDK_ERRLOG("Could not mmap trace file: %s\n", opts->filename); 32414e26b9dSJim Harris _trace_file = NULL; 32555f64c36SKonrad Sztyber return false; 32655f64c36SKonrad Sztyber } 32755f64c36SKonrad Sztyber 32855f64c36SKonrad Sztyber /* Remap the entire trace file */ 32914e26b9dSJim Harris _map_size = spdk_get_trace_file_size(_trace_file); 33014e26b9dSJim Harris munmap(_trace_file, sizeof(*_trace_file)); 33155f64c36SKonrad Sztyber if ((size_t)st.st_size < _map_size) { 33255f64c36SKonrad Sztyber SPDK_ERRLOG("Trace file %s is not valid\n", opts->filename); 33314e26b9dSJim Harris _trace_file = NULL; 33455f64c36SKonrad Sztyber return false; 33555f64c36SKonrad Sztyber } 33614e26b9dSJim Harris _trace_file = static_cast<spdk_trace_file *>(mmap(NULL, _map_size, PROT_READ, 33755f64c36SKonrad Sztyber MAP_SHARED, _fd, 0)); 33814e26b9dSJim Harris if (_trace_file == MAP_FAILED) { 33955f64c36SKonrad Sztyber SPDK_ERRLOG("Could not mmap trace file: %s\n", opts->filename); 34014e26b9dSJim Harris _trace_file = NULL; 34155f64c36SKonrad Sztyber return false; 34255f64c36SKonrad Sztyber } 34355f64c36SKonrad Sztyber 3444ba77072SKonrad Sztyber if (opts->lcore == SPDK_TRACE_MAX_LCORE) { 345*ee32a82bSAnisa Su /* Check if any reactors have overwritten their circular buffer. */ 3464ba77072SKonrad Sztyber for (i = 0; i < SPDK_TRACE_MAX_LCORE; i++) { 34714e26b9dSJim Harris history = spdk_get_per_lcore_history(_trace_file, i); 34818c8b52aSJim Harris if (history == NULL || history->num_entries == 0 || history->entries[0].tsc == 0) { 3494ba77072SKonrad Sztyber continue; 3504ba77072SKonrad Sztyber } 351*ee32a82bSAnisa Su entry_num = history->num_entries - 1; 352*ee32a82bSAnisa Su overflowed = true; 353*ee32a82bSAnisa Su while (entry_num >= 0) { 354*ee32a82bSAnisa Su if (history->entries[entry_num].tsc == 0) { 355*ee32a82bSAnisa Su overflowed = false; 356*ee32a82bSAnisa Su break; 357*ee32a82bSAnisa Su } 358*ee32a82bSAnisa Su entry_num--; 359*ee32a82bSAnisa Su } 360*ee32a82bSAnisa Su if (overflowed) { 361*ee32a82bSAnisa Su break; 362*ee32a82bSAnisa Su } 3634ba77072SKonrad Sztyber 364*ee32a82bSAnisa Su } 365*ee32a82bSAnisa Su for (i = 0; i < SPDK_TRACE_MAX_LCORE; i++) { 366*ee32a82bSAnisa Su history = spdk_get_per_lcore_history(_trace_file, i); 367*ee32a82bSAnisa Su if (history == NULL || history->num_entries == 0 || history->entries[0].tsc == 0) { 368*ee32a82bSAnisa Su continue; 369*ee32a82bSAnisa Su } 370*ee32a82bSAnisa Su populate_events(history, history->num_entries, overflowed); 3714ba77072SKonrad Sztyber } 3724ba77072SKonrad Sztyber } else { 37314e26b9dSJim Harris history = spdk_get_per_lcore_history(_trace_file, opts->lcore); 37418c8b52aSJim Harris if (history == NULL) { 37518c8b52aSJim Harris SPDK_ERRLOG("Trace file %s has no trace history for lcore %d\n", 37618c8b52aSJim Harris opts->filename, opts->lcore); 37718c8b52aSJim Harris return false; 37818c8b52aSJim Harris } 3794ba77072SKonrad Sztyber if (history->num_entries > 0 && history->entries[0].tsc != 0) { 380*ee32a82bSAnisa Su populate_events(history, history->num_entries, false); 3814ba77072SKonrad Sztyber } 3824ba77072SKonrad Sztyber } 3834ba77072SKonrad Sztyber 384279b7babSKonrad Sztyber _iter = _entries.begin(); 38555f64c36SKonrad Sztyber return true; 38655f64c36SKonrad Sztyber } 38755f64c36SKonrad Sztyber 38855f64c36SKonrad Sztyber void 38955f64c36SKonrad Sztyber spdk_trace_parser::cleanup() 39055f64c36SKonrad Sztyber { 39114e26b9dSJim Harris if (_trace_file != NULL) { 39214e26b9dSJim Harris munmap(_trace_file, _map_size); 39355f64c36SKonrad Sztyber } 39455f64c36SKonrad Sztyber 39555f64c36SKonrad Sztyber if (_fd > 0) { 39655f64c36SKonrad Sztyber close(_fd); 39755f64c36SKonrad Sztyber } 39855f64c36SKonrad Sztyber } 39955f64c36SKonrad Sztyber 40055f64c36SKonrad Sztyber spdk_trace_parser::spdk_trace_parser(const spdk_trace_parser_opts *opts) : 40114e26b9dSJim Harris _trace_file(NULL), 40255f64c36SKonrad Sztyber _map_size(0), 4034ba77072SKonrad Sztyber _fd(-1), 4044ba77072SKonrad Sztyber _tsc_offset(0) 40555f64c36SKonrad Sztyber { 40655f64c36SKonrad Sztyber if (!init(opts)) { 40755f64c36SKonrad Sztyber cleanup(); 40855f64c36SKonrad Sztyber throw std::exception(); 40955f64c36SKonrad Sztyber } 41055f64c36SKonrad Sztyber } 41155f64c36SKonrad Sztyber 41255f64c36SKonrad Sztyber spdk_trace_parser::~spdk_trace_parser() 41355f64c36SKonrad Sztyber { 41455f64c36SKonrad Sztyber cleanup(); 41555f64c36SKonrad Sztyber } 41655f64c36SKonrad Sztyber 417d919a197SKonrad Sztyber struct spdk_trace_parser * 418d919a197SKonrad Sztyber spdk_trace_parser_init(const struct spdk_trace_parser_opts *opts) 419d919a197SKonrad Sztyber { 42055f64c36SKonrad Sztyber try { 42155f64c36SKonrad Sztyber return new spdk_trace_parser(opts); 42255f64c36SKonrad Sztyber } catch (...) { 423d919a197SKonrad Sztyber return NULL; 424d919a197SKonrad Sztyber } 42555f64c36SKonrad Sztyber } 426d919a197SKonrad Sztyber 427d919a197SKonrad Sztyber void 428d919a197SKonrad Sztyber spdk_trace_parser_cleanup(struct spdk_trace_parser *parser) 42955f64c36SKonrad Sztyber { 43055f64c36SKonrad Sztyber delete parser; 43155f64c36SKonrad Sztyber } 43241ba2b30SKonrad Sztyber 43323dbcec5SJim Harris const struct spdk_trace_file * 43423dbcec5SJim Harris spdk_trace_parser_get_file(const struct spdk_trace_parser *parser) 43541ba2b30SKonrad Sztyber { 43623dbcec5SJim Harris return parser->file(); 43741ba2b30SKonrad Sztyber } 4386727cc38SKonrad Sztyber 4396727cc38SKonrad Sztyber uint64_t 4406727cc38SKonrad Sztyber spdk_trace_parser_get_tsc_offset(const struct spdk_trace_parser *parser) 4416727cc38SKonrad Sztyber { 4426727cc38SKonrad Sztyber return parser->tsc_offset(); 4436727cc38SKonrad Sztyber } 444279b7babSKonrad Sztyber 445279b7babSKonrad Sztyber bool 446279b7babSKonrad Sztyber spdk_trace_parser_next_entry(struct spdk_trace_parser *parser, 447279b7babSKonrad Sztyber struct spdk_trace_parser_entry *entry) 448279b7babSKonrad Sztyber { 449279b7babSKonrad Sztyber return parser->next_entry(entry); 450279b7babSKonrad Sztyber } 451189b0f09SKonrad Sztyber 452189b0f09SKonrad Sztyber uint64_t 453189b0f09SKonrad Sztyber spdk_trace_parser_get_entry_count(const struct spdk_trace_parser *parser, uint16_t lcore) 454189b0f09SKonrad Sztyber { 455189b0f09SKonrad Sztyber return parser->entry_count(lcore); 456189b0f09SKonrad Sztyber } 457