@@ -207,116 +207,147 @@ void MemTable::Add(SequenceNumber s, ValueType type,
207
207
}
208
208
}
209
209
210
+ // Callback from MemTable::Get()
211
+ namespace {
212
+
213
+ struct Saver {
214
+ Status* status;
215
+ const LookupKey* key;
216
+ bool * found_final_value; // Is value set correctly? Used by KeyMayExist
217
+ bool * merge_in_progress;
218
+ std::string* value;
219
+ const MergeOperator* merge_operator;
220
+ // the merge operations encountered;
221
+ MergeContext* merge_context;
222
+ MemTable* mem;
223
+ Logger* logger;
224
+ Statistics* statistics;
225
+ bool inplace_update_support;
226
+ };
227
+ } // namespace
228
+
229
+ static bool SaveValue (void * arg, const char * entry) {
230
+ Saver* s = reinterpret_cast <Saver*>(arg);
231
+ MergeContext* merge_context = s->merge_context ;
232
+ const MergeOperator* merge_operator = s->merge_operator ;
233
+
234
+ assert (s != nullptr && merge_context != nullptr );
235
+
236
+ // entry format is:
237
+ // klength varint32
238
+ // userkey char[klength-8]
239
+ // tag uint64
240
+ // vlength varint32
241
+ // value char[vlength]
242
+ // Check that it belongs to same user key. We do not check the
243
+ // sequence number since the Seek() call above should have skipped
244
+ // all entries with overly large sequence numbers.
245
+ uint32_t key_length;
246
+ const char * key_ptr = GetVarint32Ptr (entry, entry + 5 , &key_length);
247
+ if (s->mem ->GetInternalKeyComparator ().user_comparator ()->Compare (
248
+ Slice (key_ptr, key_length - 8 ), s->key ->user_key ()) == 0 ) {
249
+ // Correct user key
250
+ const uint64_t tag = DecodeFixed64 (key_ptr + key_length - 8 );
251
+ switch (static_cast <ValueType>(tag & 0xff )) {
252
+ case kTypeValue : {
253
+ if (s->inplace_update_support ) {
254
+ s->mem ->GetLock (s->key ->user_key ())->ReadLock ();
255
+ }
256
+ Slice v = GetLengthPrefixedSlice (key_ptr + key_length);
257
+ *(s->status ) = Status::OK ();
258
+ if (*(s->merge_in_progress )) {
259
+ assert (merge_operator);
260
+ if (!merge_operator->FullMerge (s->key ->user_key (), &v,
261
+ merge_context->GetOperands (), s->value ,
262
+ s->logger )) {
263
+ RecordTick (s->statistics , NUMBER_MERGE_FAILURES);
264
+ *(s->status ) =
265
+ Status::Corruption (" Error: Could not perform merge." );
266
+ }
267
+ } else {
268
+ s->value ->assign (v.data (), v.size ());
269
+ }
270
+ if (s->inplace_update_support ) {
271
+ s->mem ->GetLock (s->key ->user_key ())->Unlock ();
272
+ }
273
+ *(s->found_final_value ) = true ;
274
+ return false ;
275
+ }
276
+ case kTypeDeletion : {
277
+ if (*(s->merge_in_progress )) {
278
+ assert (merge_operator);
279
+ *(s->status ) = Status::OK ();
280
+ if (!merge_operator->FullMerge (s->key ->user_key (), nullptr ,
281
+ merge_context->GetOperands (), s->value ,
282
+ s->logger )) {
283
+ RecordTick (s->statistics , NUMBER_MERGE_FAILURES);
284
+ *(s->status ) =
285
+ Status::Corruption (" Error: Could not perform merge." );
286
+ }
287
+ } else {
288
+ *(s->status ) = Status::NotFound ();
289
+ }
290
+ *(s->found_final_value ) = true ;
291
+ return false ;
292
+ }
293
+ case kTypeMerge : {
294
+ std::string merge_result; // temporary area for merge results later
295
+ Slice v = GetLengthPrefixedSlice (key_ptr + key_length);
296
+ *(s->merge_in_progress ) = true ;
297
+ merge_context->PushOperand (v);
298
+ while (merge_context->GetNumOperands () >= 2 ) {
299
+ // Attempt to associative merge. (Returns true if successful)
300
+ if (merge_operator->PartialMerge (
301
+ s->key ->user_key (), merge_context->GetOperand (0 ),
302
+ merge_context->GetOperand (1 ), &merge_result, s->logger )) {
303
+ merge_context->PushPartialMergeResult (merge_result);
304
+ } else {
305
+ // Stack them because user can't associative merge
306
+ break ;
307
+ }
308
+ }
309
+ return true ;
310
+ }
311
+ default :
312
+ assert (false );
313
+ return true ;
314
+ }
315
+ }
316
+
317
+ // s->state could be Corrupt, merge or notfound
318
+ return false ;
319
+ }
320
+
210
321
bool MemTable::Get (const LookupKey& key, std::string* value, Status* s,
211
322
MergeContext& merge_context, const Options& options) {
212
323
StopWatchNano memtable_get_timer (options.env , false );
213
324
StartPerfTimer (&memtable_get_timer);
214
325
215
- Slice mem_key = key.memtable_key ();
216
326
Slice user_key = key.user_key ();
327
+ bool found_final_value = false ;
328
+ bool merge_in_progress = s->IsMergeInProgress ();
217
329
218
- std::unique_ptr<MemTableRep::Iterator> iter;
219
330
if (prefix_bloom_ &&
220
331
!prefix_bloom_->MayContain (prefix_extractor_->Transform (user_key))) {
221
332
// iter is null if prefix bloom says the key does not exist
222
333
} else {
223
- iter.reset (table_->GetIterator (user_key));
224
- iter->Seek (key.internal_key (), mem_key.data ());
225
- }
226
-
227
- bool merge_in_progress = s->IsMergeInProgress ();
228
- auto merge_operator = options.merge_operator .get ();
229
- auto logger = options.info_log ;
230
- std::string merge_result;
231
-
232
- bool found_final_value = false ;
233
- for (; !found_final_value && iter && iter->Valid (); iter->Next ()) {
234
- // entry format is:
235
- // klength varint32
236
- // userkey char[klength-8]
237
- // tag uint64
238
- // vlength varint32
239
- // value char[vlength]
240
- // Check that it belongs to same user key. We do not check the
241
- // sequence number since the Seek() call above should have skipped
242
- // all entries with overly large sequence numbers.
243
- const char * entry = iter->key ();
244
- uint32_t key_length = 0 ;
245
- const char * key_ptr = GetVarint32Ptr (entry, entry + 5 , &key_length);
246
- if (comparator_.comparator .user_comparator ()->Compare (
247
- Slice (key_ptr, key_length - 8 ), key.user_key ()) == 0 ) {
248
- // Correct user key
249
- const uint64_t tag = DecodeFixed64 (key_ptr + key_length - 8 );
250
- switch (static_cast <ValueType>(tag & 0xff )) {
251
- case kTypeValue : {
252
- if (options.inplace_update_support ) {
253
- GetLock (key.user_key ())->ReadLock ();
254
- }
255
- Slice v = GetLengthPrefixedSlice (key_ptr + key_length);
256
- *s = Status::OK ();
257
- if (merge_in_progress) {
258
- assert (merge_operator);
259
- if (!merge_operator->FullMerge (key.user_key (), &v,
260
- merge_context.GetOperands (), value,
261
- logger.get ())) {
262
- RecordTick (options.statistics .get (), NUMBER_MERGE_FAILURES);
263
- *s = Status::Corruption (" Error: Could not perform merge." );
264
- }
265
- } else {
266
- value->assign (v.data (), v.size ());
267
- }
268
- if (options.inplace_update_support ) {
269
- GetLock (key.user_key ())->Unlock ();
270
- }
271
- found_final_value = true ;
272
- break ;
273
- }
274
- case kTypeDeletion : {
275
- if (merge_in_progress) {
276
- assert (merge_operator);
277
- *s = Status::OK ();
278
- if (!merge_operator->FullMerge (key.user_key (), nullptr ,
279
- merge_context.GetOperands (), value,
280
- logger.get ())) {
281
- RecordTick (options.statistics .get (), NUMBER_MERGE_FAILURES);
282
- *s = Status::Corruption (" Error: Could not perform merge." );
283
- }
284
- } else {
285
- *s = Status::NotFound ();
286
- }
287
- found_final_value = true ;
288
- break ;
289
- }
290
- case kTypeMerge : {
291
- Slice v = GetLengthPrefixedSlice (key_ptr + key_length);
292
- merge_in_progress = true ;
293
- merge_context.PushOperand (v);
294
- while (merge_context.GetNumOperands () >= 2 ) {
295
- // Attempt to associative merge. (Returns true if successful)
296
- if (merge_operator->PartialMerge (key.user_key (),
297
- merge_context.GetOperand (0 ),
298
- merge_context.GetOperand (1 ),
299
- &merge_result, logger.get ())) {
300
- merge_context.PushPartialMergeResult (merge_result);
301
- } else {
302
- // Stack them because user can't associative merge
303
- break ;
304
- }
305
- }
306
- break ;
307
- }
308
- default :
309
- assert (false );
310
- break ;
311
- }
312
- } else {
313
- // exit loop if user key does not match
314
- break ;
315
- }
334
+ Saver saver;
335
+ saver.status = s;
336
+ saver.found_final_value = &found_final_value;
337
+ saver.merge_in_progress = &merge_in_progress;
338
+ saver.key = &key;
339
+ saver.value = value;
340
+ saver.status = s;
341
+ saver.mem = this ;
342
+ saver.merge_context = &merge_context;
343
+ saver.merge_operator = options.merge_operator .get ();
344
+ saver.logger = options.info_log .get ();
345
+ saver.inplace_update_support = options.inplace_update_support ;
346
+ saver.statistics = options.statistics .get ();
347
+ table_->Get (key, &saver, SaveValue);
316
348
}
317
349
318
350
// No change to value, since we have not yet found a Put/Delete
319
-
320
351
if (!found_final_value && merge_in_progress) {
321
352
*s = Status::MergeInProgress (" " );
322
353
}
@@ -488,4 +519,13 @@ size_t MemTable::CountSuccessiveMergeEntries(const LookupKey& key) {
488
519
return num_successive_merges;
489
520
}
490
521
522
+ void MemTableRep::Get (const LookupKey& k, void * callback_args,
523
+ bool (*callback_func)(void * arg, const char * entry)) {
524
+ auto iter = GetIterator (k.user_key ());
525
+ for (iter->Seek (k.internal_key (), k.memtable_key ().data ());
526
+ iter->Valid () && callback_func (callback_args, iter->key ());
527
+ iter->Next ()) {
528
+ }
529
+ }
530
+
491
531
} // namespace rocksdb
0 commit comments