diff options
| author | Steven Rostedt <srostedt@redhat.com> | 2010-02-10 13:10:48 -0500 |
|---|---|---|
| committer | Steven Rostedt <rostedt@goodmis.org> | 2010-02-10 13:10:48 -0500 |
| commit | ffc9da087d4168a00640ef04376e2e4f42e7fa42 (patch) | |
| tree | 8527f3df050f05c450cc57cb25b8e75850a8ef6f | |
| parent | 37fe347963f8f43d95ca0ccd978a769fd6cc96f3 (diff) | |
trace-cmd: Add tracecmd_read_prev()
Add the tracecmd_read_prev(handle, record) that returns the record
before the given record.
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
| -rw-r--r-- | trace-cmd.h | 3 | ||||
| -rw-r--r-- | trace-input.c | 99 |
2 files changed, 102 insertions, 0 deletions
diff --git a/trace-cmd.h b/trace-cmd.h index b7cd5cc..7228a6d 100644 --- a/trace-cmd.h +++ b/trace-cmd.h | |||
| @@ -64,6 +64,9 @@ struct record * | |||
| 64 | tracecmd_read_data(struct tracecmd_input *handle, int cpu); | 64 | tracecmd_read_data(struct tracecmd_input *handle, int cpu); |
| 65 | 65 | ||
| 66 | struct record * | 66 | struct record * |
| 67 | tracecmd_read_prev(struct tracecmd_input *handle, struct record *record); | ||
| 68 | |||
| 69 | struct record * | ||
| 67 | tracecmd_read_next_data(struct tracecmd_input *handle, int *rec_cpu); | 70 | tracecmd_read_next_data(struct tracecmd_input *handle, int *rec_cpu); |
| 68 | 71 | ||
| 69 | struct record * | 72 | struct record * |
diff --git a/trace-input.c b/trace-input.c index ce7bd09..279382a 100644 --- a/trace-input.c +++ b/trace-input.c | |||
| @@ -1500,6 +1500,105 @@ tracecmd_read_next_data(struct tracecmd_input *handle, int *rec_cpu) | |||
| 1500 | return NULL; | 1500 | return NULL; |
| 1501 | } | 1501 | } |
| 1502 | 1502 | ||
| 1503 | /** | ||
| 1504 | * tracecmd_read_prev - read the record before the given record | ||
| 1505 | * @handle: input handle to the trace.dat file | ||
| 1506 | * @record: the record to use to find the previous record. | ||
| 1507 | * | ||
| 1508 | * This returns the record before the @record on its CPU. If | ||
| 1509 | * @record is the first record, NULL is returned. The cursor is set | ||
| 1510 | * as if the previous record was read by tracecmd_read_data(). | ||
| 1511 | * | ||
| 1512 | * @record can not be NULL, otherwise NULL is returned. | ||
| 1513 | * | ||
| 1514 | * Note, this is not that fast of an algorithm, since it needs | ||
| 1515 | * to build the timestamp for the record. | ||
| 1516 | * | ||
| 1517 | * Note 2: This may free any record allocoted with tracecmd_peek_data(). | ||
| 1518 | * | ||
| 1519 | * The record returned must be freed with free_record(). | ||
| 1520 | */ | ||
| 1521 | struct record * | ||
| 1522 | tracecmd_read_prev(struct tracecmd_input *handle, struct record *record) | ||
| 1523 | { | ||
| 1524 | unsigned long long offset, page_offset;; | ||
| 1525 | struct cpu_data *cpu_data; | ||
| 1526 | int index; | ||
| 1527 | int cpu; | ||
| 1528 | |||
| 1529 | if (!record) | ||
| 1530 | return NULL; | ||
| 1531 | |||
| 1532 | cpu = record->cpu; | ||
| 1533 | offset = record->offset; | ||
| 1534 | cpu_data = &handle->cpu_data[cpu]; | ||
| 1535 | |||
| 1536 | page_offset = calc_page_offset(handle, offset); | ||
| 1537 | index = offset - page_offset; | ||
| 1538 | |||
| 1539 | /* Note, the record passed in could have been a peek */ | ||
| 1540 | if (cpu_data->next) { | ||
| 1541 | free_record(cpu_data->next); | ||
| 1542 | cpu_data->next = NULL; | ||
| 1543 | } | ||
| 1544 | |||
| 1545 | /* Reset the cursor */ | ||
| 1546 | /* Should not happen */ | ||
| 1547 | if (get_page(handle, cpu, page_offset) < 0) | ||
| 1548 | return NULL; | ||
| 1549 | |||
| 1550 | update_page_info(handle, cpu); | ||
| 1551 | |||
| 1552 | /* Find the record before this record */ | ||
| 1553 | index = 0; | ||
| 1554 | for (;;) { | ||
| 1555 | record = tracecmd_read_data(handle, cpu); | ||
| 1556 | /* Should not happen! */ | ||
| 1557 | if (!record) | ||
| 1558 | return NULL; | ||
| 1559 | if (record->offset == offset) | ||
| 1560 | break; | ||
| 1561 | index = record->offset - page_offset; | ||
| 1562 | free_record(record); | ||
| 1563 | } | ||
| 1564 | free_record(record); | ||
| 1565 | |||
| 1566 | if (index) | ||
| 1567 | /* we found our record */ | ||
| 1568 | return tracecmd_read_at(handle, page_offset + index, NULL); | ||
| 1569 | |||
| 1570 | /* The previous record is on the previous page */ | ||
| 1571 | for (;;) { | ||
| 1572 | /* check if this is the first page */ | ||
| 1573 | if (page_offset == cpu_data->file_offset) | ||
| 1574 | return NULL; | ||
| 1575 | page_offset -= handle->page_size; | ||
| 1576 | |||
| 1577 | /* Updating page to a new page will reset index to 0 */ | ||
| 1578 | get_page(handle, cpu, page_offset); | ||
| 1579 | |||
| 1580 | record = NULL; | ||
| 1581 | index = 0; | ||
| 1582 | do { | ||
| 1583 | if (record) { | ||
| 1584 | index = record->offset - page_offset; | ||
| 1585 | free_record(record); | ||
| 1586 | } | ||
| 1587 | record = tracecmd_read_data(handle, cpu); | ||
| 1588 | /* Should not happen */ | ||
| 1589 | if (!record) | ||
| 1590 | return NULL; | ||
| 1591 | } while (record->offset != offset); | ||
| 1592 | free_record(record); | ||
| 1593 | |||
| 1594 | if (index) | ||
| 1595 | /* we found our record */ | ||
| 1596 | return tracecmd_read_at(handle, page_offset + index, NULL); | ||
| 1597 | } | ||
| 1598 | |||
| 1599 | /* Not reached */ | ||
| 1600 | } | ||
| 1601 | |||
| 1503 | static int init_cpu(struct tracecmd_input *handle, int cpu) | 1602 | static int init_cpu(struct tracecmd_input *handle, int cpu) |
| 1504 | { | 1603 | { |
| 1505 | struct cpu_data *cpu_data = &handle->cpu_data[cpu]; | 1604 | struct cpu_data *cpu_data = &handle->cpu_data[cpu]; |
