@@ -221,8 +221,8 @@ class SkipList {
221
221
222
222
public:
223
223
224
- SkipList (KeyComparator key_cmp_obj, KeyEqualityChecker key_eq_check_obj) :
225
- key_cmp_obj_ (key_cmp_obj), key_eq_check_obj_(key_eq_check_obj) {
224
+ SkipList (KeyComparator key_cmp_obj, KeyEqualityChecker key_eq_check_obj, bool is_unique ) :
225
+ key_cmp_obj_ (key_cmp_obj), key_eq_check_obj_(key_eq_check_obj), is_unique_(is_unique) {
226
226
// InitHeadTower();
227
227
// No tower root needed or set for head tower
228
228
root_ = new SKIPLISTHEADNODE_TYPE (nullptr , nullptr , nullptr , nullptr , 1 );
@@ -308,9 +308,7 @@ class SkipList {
308
308
int curr_level = reinterpret_cast <SKIPLISTHEADNODE_TYPE *>(curr_node)->GetLevel ();
309
309
310
310
NodeNodePair node_node;
311
- // while (curr_level > level) {
312
311
313
- // int curr_level = node_level.second;
314
312
while (curr_level > level) { // search down to level v + 1
315
313
if (traversal_mode == SKIPLISTNODE_TYPE::TraversalMode::GO_DOWN_ON_LEQ)
316
314
node_node = SearchRightLEQ (key, curr_node);
@@ -326,8 +324,6 @@ class SkipList {
326
324
node_node = SearchRightLEQ (key, curr_node);
327
325
else if (traversal_mode == SKIPLISTNODE_TYPE::TraversalMode::GO_DOWN_ON_LT)
328
326
node_node = SearchRightLT (key, curr_node);
329
-
330
-
331
327
return node_node;
332
328
}
333
329
@@ -430,27 +426,70 @@ class SkipList {
430
426
}
431
427
432
428
429
+ bool DuplicateKeyValue (const NodeNodePair &arg_pair, const KeyType &key, const ValueType &value) {
430
+ assert (arg_pair.first );
431
+ if (arg_pair.second == nullptr ) {
432
+ return false ;
433
+ }
434
+ SKIPLISTNODE_TYPE *curr_node = arg_pair.first , *next_node = arg_pair.second ;
435
+ while (next_node && key_cmp_obj_ (next_node->GetKey (), key)<=0 ){
436
+ /*
437
+ * next_node has been marked for deletion,
438
+ * help with the deletion and then
439
+ * continue traversing.
440
+ */
441
+ while (next_node!=nullptr && SKIPLISTNODE_TYPE::IsMarkedReference (next_node->GetTowerRoot ()->GetSucc ())){
442
+ NodeStatusResultTuple tuple = TryFlagNode (curr_node, next_node);
443
+
444
+ StatusType status = std::get<1 >(tuple);
445
+
446
+ if (status==StatusType::FLAGGED){
447
+ HelpFlagged (curr_node, next_node);
448
+ }
449
+ next_node = curr_node->GetRight ();
450
+ }
451
+ if (next_node && key_eq_check_obj_ (next_node->GetKey (), key) &&
452
+ val_eq_check_obj_ (reinterpret_cast <SKIPLISTLEAFNODE_TYPE *>(next_node)->GetValue (), value)) {
453
+ return true ;
454
+ }
455
+
456
+ if (next_node && key_cmp_obj_ (next_node->GetKey (), key)<=0 ) {
457
+ curr_node = next_node;
458
+ next_node = curr_node->GetRight ();
459
+ }
460
+ }
461
+ return false ;
462
+ }
463
+
433
464
434
465
bool Insert (const KeyType &key, const ValueType &value) {
435
466
436
467
int tower_height = 1 , curr_level = 1 ;
437
468
438
469
439
- NodeNodePair node_node = SearchToLevel (key, 1 , SKIPLISTNODE_TYPE::TraversalMode::GO_DOWN_ON_LEQ);
470
+ NodeNodePair node_node;
471
+ if (is_unique_) {
472
+ node_node = SearchToLevel (key, 1 , SKIPLISTNODE_TYPE::TraversalMode::GO_DOWN_ON_LEQ);
473
+ } else {
474
+ node_node = SearchToLevel (key, 1 , SKIPLISTNODE_TYPE::TraversalMode::GO_DOWN_ON_LT);
475
+ }
440
476
441
477
442
478
SKIPLISTNODE_TYPE *inserted_node;
443
479
SKIPLISTNODE_TYPE *prev_node = node_node.first , *next_node = node_node.second ;
444
480
445
481
PL_ASSERT (prev_node);
446
482
447
-
448
- if (prev_node->GetTowerType () != SKIPLISTNODE_TYPE::TowerType::HEAD_TOWER) {
483
+ if (is_unique_ && prev_node->GetTowerType () != SKIPLISTNODE_TYPE::TowerType::HEAD_TOWER) {
449
484
if (key_eq_check_obj_ (prev_node->GetKey (), key)) {
450
485
return false ; // DUPLICATE
451
486
}
452
487
}
453
488
489
+ if (is_unique_ == false && DuplicateKeyValue (node_node, key, value)) {
490
+ return false ;
491
+ }
492
+
454
493
SKIPLISTNODE_TYPE *new_root_node = reinterpret_cast <SKIPLISTNODE_TYPE *>(
455
494
new SKIPLISTLEAFNODE_TYPE (
456
495
key, SKIPLISTNODE_TYPE::TowerType::MIDDLE_TOWER,
@@ -494,7 +533,7 @@ class SkipList {
494
533
if (SKIPLISTNODE_TYPE::IsMarkedReference (tower_root->GetSucc ())){
495
534
if (inserted_node == new_node && new_node != tower_root) {
496
535
// TODO(gandeevan): uncomment this later
497
- // DeleteNode(prev_node, new_node);
536
+ // DeleteNode(prev_node, new_node);
498
537
}
499
538
return true ;
500
539
}
@@ -511,8 +550,11 @@ class SkipList {
511
550
512
551
// NOTE: Search being done for level 1, 2, ....n. This might hurt performance if not a lot of concurrency.
513
552
// Should we also store the prev and curr at every level while doing searchtolevel?
514
- result_pair = SearchToLevel (key, curr_level, SKIPLISTNODE_TYPE::TraversalMode::GO_DOWN_ON_LEQ);
515
-
553
+ if (is_unique_) {
554
+ result_pair = SearchToLevel (key, curr_level, SKIPLISTNODE_TYPE::TraversalMode::GO_DOWN_ON_LEQ);
555
+ } else {
556
+ result_pair = SearchToLevel (key, curr_level, SKIPLISTNODE_TYPE::TraversalMode::GO_DOWN_ON_LT);
557
+ }
516
558
prev_node = result_pair.first ;
517
559
next_node = result_pair.second ;
518
560
}
@@ -566,14 +608,13 @@ class SkipList {
566
608
567
609
bool Delete (const KeyType &key, const ValueType &value) {
568
610
569
- (void ) value;
570
-
571
611
NodeNodePair result = SearchToLevel (key, 1 , SKIPLISTNODE_TYPE::TraversalMode::GO_DOWN_ON_LT);
572
612
if (!key_eq_check_obj_ (result.second ->GetKey (), key)) {
573
613
return false ;
574
614
}
575
-
576
-
615
+ if (is_unique_ == false && !DuplicateKeyValue (result, key, value)) {
616
+ return false ;
617
+ }
577
618
578
619
/* Unlinks the root node of the tower */
579
620
SKIPLISTNODE_TYPE *root_node = DeleteNode (result.first , result.second );
@@ -691,6 +732,8 @@ class SkipList {
691
732
SKIPLISTHEADNODE_TYPE *root_;
692
733
const KeyComparator key_cmp_obj_;
693
734
const KeyEqualityChecker key_eq_check_obj_;
735
+ const ValueEqualityChecker val_eq_check_obj_;
736
+ bool is_unique_;
694
737
};
695
738
696
739
} // namespace index
0 commit comments