21
21
#include < utility>
22
22
#include < vector>
23
23
24
+ #include " Firestore/core/src/credentials/user.h"
24
25
#include " Firestore/core/src/local/leveldb_key.h"
25
26
#include " Firestore/core/src/local/leveldb_persistence.h"
26
27
#include " Firestore/core/src/local/local_serializer.h"
@@ -35,6 +36,7 @@ namespace firebase {
35
36
namespace firestore {
36
37
namespace local {
37
38
39
+ using credentials::User;
38
40
using model::DocumentKey;
39
41
using model::FieldIndex;
40
42
using model::IndexState;
@@ -49,21 +51,15 @@ struct DbIndexState {
49
51
int32_t nanos;
50
52
std::string key;
51
53
model::ListenSequenceNumber sequence_number;
54
+ model::BatchId largest_batch_id;
52
55
};
53
56
54
- // TODO(wuandy): Uncomment this when needed.
55
- // void to_json(json& j, const DbIndexState& s) {
56
- // j = json{{"seconds", s.seconds},
57
- // {"nanos", s.nanos},
58
- // {"key", s.key},
59
- // {"seq_num", s.sequence_number}};
60
- // }
61
-
62
57
void from_json (const json& j, DbIndexState& s) {
63
58
j.at (" seconds" ).get_to (s.seconds );
64
59
j.at (" nanos" ).get_to (s.nanos );
65
60
j.at (" key" ).get_to (s.key );
66
61
j.at (" seq_num" ).get_to (s.sequence_number );
62
+ j.at (" largest_batch" ).get_to (s.largest_batch_id );
67
63
}
68
64
69
65
IndexState DecodeIndexState (const std::string& encoded) {
@@ -72,16 +68,34 @@ IndexState DecodeIndexState(const std::string& encoded) {
72
68
auto db_state = j.get <DbIndexState>();
73
69
return {db_state.sequence_number ,
74
70
SnapshotVersion (Timestamp (db_state.seconds , db_state.nanos )),
75
- DocumentKey::FromPathString (db_state.key )};
71
+ DocumentKey::FromPathString (db_state.key ), db_state.largest_batch_id };
72
+ }
73
+
74
+ std::string EncodeIndexState (const IndexState& state) {
75
+ return json{
76
+ {" seconds" , state.index_offset ().read_time ().timestamp ().seconds ()},
77
+ {" nanos" , state.index_offset ().read_time ().timestamp ().nanoseconds ()},
78
+ {" key" , state.index_offset ().document_key ().ToString ()},
79
+ {" seq_num" , state.sequence_number ()},
80
+ {" largest_batch" , state.index_offset ().largest_batch_id ()}}
81
+ .dump ();
76
82
}
77
83
78
84
} // namespace
79
85
80
- LevelDbIndexManager::LevelDbIndexManager (LevelDbPersistence* db,
86
+ LevelDbIndexManager::LevelDbIndexManager (const User& user,
87
+ LevelDbPersistence* db,
81
88
LocalSerializer* serializer)
82
- : db_(db), serializer_(serializer) {
89
+ : db_(db), serializer_(serializer), uid_(user.uid()) {
90
+ // The contract for this comparison expected by priority queue is
91
+ // `std::less`, but std::priority_queue's default order is descending.
92
+ // We change the order to be ascending by doing left >= right instead.
83
93
auto cmp = [](FieldIndex* left, FieldIndex* right) {
84
- return left->index_state ().sequence_number () <
94
+ if (left->index_state ().sequence_number () ==
95
+ right->index_state ().sequence_number ()) {
96
+ return left->collection_group () >= right->collection_group ();
97
+ }
98
+ return left->index_state ().sequence_number () >
85
99
right->index_state ().sequence_number ();
86
100
};
87
101
next_index_to_update_ = std::priority_queue<
@@ -225,7 +239,8 @@ void LevelDbIndexManager::MemoizeIndex(FieldIndex index) {
225
239
}
226
240
227
241
// Moves `index` into `existing_indexes`.
228
- existing_indexes.insert ({index_id, std::move (index)});
242
+ existing_indexes[index_id] = std::move (index);
243
+
229
244
// next_index_to_update_ holds a pointer to the index owned by
230
245
// `existing_indexes`.
231
246
next_index_to_update_.push (&existing_indexes.find (index_id)->second );
@@ -300,9 +315,11 @@ std::vector<FieldIndex> LevelDbIndexManager::GetFieldIndexes(
300
315
HARD_ASSERT (started_, " IndexManager not started" );
301
316
302
317
std::vector<FieldIndex> result;
303
- const auto & indexes = memoized_indexes_[collection_group];
304
- for (const auto & entry : indexes) {
305
- result.push_back (entry.second );
318
+ const auto iter = memoized_indexes_.find (collection_group);
319
+ if (iter != memoized_indexes_.end ()) {
320
+ for (const auto & entry : iter->second ) {
321
+ result.push_back (entry.second );
322
+ }
306
323
}
307
324
308
325
return result;
@@ -335,13 +352,30 @@ LevelDbIndexManager::GetDocumentsMatchingTarget(model::FieldIndex field_index,
335
352
336
353
absl::optional<std::string>
337
354
LevelDbIndexManager::GetNextCollectionGroupToUpdate () {
338
- return {};
355
+ if (next_index_to_update_.empty ()) {
356
+ return absl::nullopt ;
357
+ }
358
+
359
+ return next_index_to_update_.top ()->collection_group ();
339
360
}
340
361
341
362
void LevelDbIndexManager::UpdateCollectionGroup (
342
363
const std::string& collection_group, model::IndexOffset offset) {
343
- (void )collection_group;
344
- (void )offset;
364
+ HARD_ASSERT (started_, " IndexManager not started" );
365
+
366
+ ++memoized_max_sequence_number_;
367
+ for (const auto & field_index : GetFieldIndexes (collection_group)) {
368
+ IndexState updated_state{memoized_max_sequence_number_, offset};
369
+
370
+ auto state_key = LevelDbIndexStateKey::Key (uid_, field_index.index_id ());
371
+ auto val = EncodeIndexState (updated_state);
372
+ db_->current_transaction ()->Put (std::move (state_key),
373
+ EncodeIndexState (updated_state));
374
+
375
+ MemoizeIndex (FieldIndex{field_index.index_id (),
376
+ field_index.collection_group (),
377
+ field_index.segments (), std::move (updated_state)});
378
+ }
345
379
}
346
380
347
381
void LevelDbIndexManager::UpdateIndexEntries (
0 commit comments