| 981 | } |
| 982 | |
| 983 | void ListSpans(int64_t starting_realtime, size_t max_scan, |
| 984 | std::deque<BriefSpan>* out, SpanFilter* filter) { |
| 985 | out->clear(); |
| 986 | butil::intrusive_ptr<SpanDB> db; |
| 987 | if (GetSpanDB(&db) != 0) { |
| 988 | return; |
| 989 | } |
| 990 | leveldb::Iterator* it = db->time_db->NewIterator(leveldb::ReadOptions()); |
| 991 | uint32_t time_data[2]; |
| 992 | ToBigEndian(starting_realtime, time_data); |
| 993 | leveldb::Slice key((char*)time_data, sizeof(time_data)); |
| 994 | it->Seek(key); |
| 995 | if (!it->Valid()) { |
| 996 | it->SeekToLast(); |
| 997 | } |
| 998 | BriefSpan brief; |
| 999 | size_t nscan = 0; |
| 1000 | for (; nscan < max_scan && it->Valid(); it->Prev()) { |
| 1001 | const int64_t key_tm = ToLittleEndian((const uint32_t*)it->key().data()); |
| 1002 | // May have some bigger time at the beginning, because leveldb returns |
| 1003 | // keys >= starting_realtime. |
| 1004 | if (key_tm > starting_realtime) { |
| 1005 | continue; |
| 1006 | } |
| 1007 | brief.Clear(); |
| 1008 | if (brief.ParseFromArray(it->value().data(), it->value().size())) { |
| 1009 | if (NULL == filter || filter->Keep(brief)) { |
| 1010 | out->push_back(brief); |
| 1011 | } |
| 1012 | // We increase the count no matter filter passed or not to avoid |
| 1013 | // scaning too many entries. |
| 1014 | ++nscan; |
| 1015 | } else { |
| 1016 | LOG(ERROR) << "Fail to parse from value"; |
| 1017 | } |
| 1018 | } |
| 1019 | delete it; |
| 1020 | } |
| 1021 | |
| 1022 | void DescribeSpanDB(std::ostream& os) { |
| 1023 | butil::intrusive_ptr<SpanDB> db; |
no test coverage detected