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]; |