Skip to content
This repository was archived by the owner on Mar 21, 2025. It is now read-only.

Commit 1ad2cce

Browse files
author
Alex Gaetano Padula
committed
Correction skiplist should skip tombstoned keys on traversal
1 parent 7caad95 commit 1ad2cce

3 files changed

Lines changed: 28 additions & 56 deletions

File tree

k4.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,8 @@ type WALIterator struct {
117117

118118
// KV mainly used for serialization
119119
type KV struct {
120-
Key []byte
121-
Value []byte
120+
Key []byte // Binary array of key
121+
Value []byte // Binary array of keys value
122122
}
123123

124124
// Open opens a new K4 instance at the specified directory.
@@ -185,7 +185,7 @@ func Open(directory string, memtableFlushThreshold int, compactionInterval int,
185185
// We open sstable files in the configured directory
186186
k4.loadSSTables()
187187

188-
// If logging is set we will open a loggin file, so we can write to it
188+
// If logging is set we will open a logging file, so we can write to it
189189
if logging {
190190
// Create log file
191191
logFile, err := os.OpenFile(directory+string(os.PathSeparator)+LOG_EXTENSION, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
@@ -312,18 +312,18 @@ func (k4 *K4) backgroundWalWriter() {
312312

313313
// serializeOp serializes an operation
314314
func serializeOp(op OPR_CODE, key, value []byte) []byte {
315-
var buf bytes.Buffer
316-
317-
// use gob
315+
var buf bytes.Buffer // create a buffer
318316

319-
enc := gob.NewEncoder(&buf)
317+
enc := gob.NewEncoder(&buf) // create a new encoder with the buffer
320318

319+
// create an operation struct and initialize it
321320
operation := Operation{
322321
Op: op,
323322
Key: key,
324323
Value: value,
325324
}
326325

326+
// encode the operation
327327
err := enc.Encode(&operation)
328328
if err != nil {
329329
return nil
@@ -887,7 +887,7 @@ func (txn *Transaction) Rollback(k4 *K4) error {
887887
op := txn.ops[i]
888888
switch op.Op {
889889
case PUT:
890-
err := k4.appendToWALQueue(PUT, op.Key, op.Value)
890+
err := k4.appendToWALQueue(PUT, op.Key, []byte(TOMBSTONE_VALUE))
891891
if err != nil {
892892
return err
893893
}

skiplist/skiplist.go

Lines changed: 11 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -120,20 +120,10 @@ func (sl *SkipList) Insert(key, value []byte, ttl *time.Duration) {
120120

121121
// Traverse the skip list to find the position of the key
122122
for i := sl.level; i >= 0; i-- {
123-
for current.forward[i] != nil && string(current.forward[i].key) < string(key) {
124-
if current.forward[i].IsExpired() {
125-
//sl.Delete(current.forward[i].key)
126-
// We mark as tombstone and delete later
127-
current.forward[i].ttl = nil
128-
129-
// Subtraction of the size of the old value
130-
sl.size -= current.forward[i].Size()
131-
// Mark as tombstone
132-
current.forward[i].value = []byte(TOMBSTONE_VALUE)
133-
134-
// Add the size of the tombstone
135-
sl.size += current.forward[i].Size()
136-
123+
for current.forward[i] != nil && (string(current.forward[i].key) < string(key) || bytes.Equal(current.forward[i].value, []byte(TOMBSTONE_VALUE))) {
124+
if current.forward[i].IsExpired() || bytes.Equal(current.forward[i].value, []byte(TOMBSTONE_VALUE)) {
125+
// Skip nodes with tombstone values
126+
current = current.forward[i]
137127
} else {
138128
current = current.forward[i]
139129
}
@@ -181,19 +171,10 @@ func (sl *SkipList) Delete(key []byte) {
181171
current := sl.header
182172

183173
for i := sl.level; i >= 0; i-- {
184-
for current.forward[i] != nil && string(current.forward[i].key) < string(key) {
185-
if current.forward[i].IsExpired() {
186-
//sl.Delete(current.forward[i].key)
187-
// We mark as tombstone and delete later
188-
current.forward[i].ttl = nil
189-
190-
// Subtraction of the size of the old value
191-
sl.size -= current.forward[i].Size()
192-
// Mark as tombstone
193-
current.forward[i].value = []byte(TOMBSTONE_VALUE)
194-
195-
// Add the size of the tombstone
196-
sl.size += current.forward[i].Size()
174+
for current.forward[i] != nil && (string(current.forward[i].key) < string(key) || bytes.Equal(current.forward[i].value, []byte(TOMBSTONE_VALUE))) {
175+
if current.forward[i].IsExpired() || bytes.Equal(current.forward[i].value, []byte(TOMBSTONE_VALUE)) {
176+
// Skip nodes with tombstone values
177+
current = current.forward[i]
197178
} else {
198179
current = current.forward[i]
199180
}
@@ -222,18 +203,10 @@ func (sl *SkipList) Delete(key []byte) {
222203
func (sl *SkipList) Search(key []byte) ([]byte, bool) {
223204
current := sl.header
224205
for i := sl.level; i >= 0; i-- {
225-
for current.forward[i] != nil && string(current.forward[i].key) < string(key) {
206+
for current.forward[i] != nil && (string(current.forward[i].key) < string(key) || bytes.Equal(current.forward[i].value, []byte(TOMBSTONE_VALUE))) {
226207
if current.forward[i].IsExpired() || bytes.Equal(current.forward[i].value, []byte(TOMBSTONE_VALUE)) {
227-
// Mark as tombstone and delete later
228-
current.forward[i].ttl = nil
229-
230-
// Subtraction of the size of the old value
231-
sl.size -= current.forward[i].Size()
232-
// Mark as tombstone
233-
current.forward[i].value = []byte(TOMBSTONE_VALUE)
234-
235-
// Add the size of the tombstone
236-
sl.size += current.forward[i].Size()
208+
// Skip nodes with tombstone values
209+
current = current.forward[i]
237210
} else {
238211
current = current.forward[i]
239212
}
@@ -242,16 +215,6 @@ func (sl *SkipList) Search(key []byte) ([]byte, bool) {
242215
current = current.forward[0]
243216
if current != nil && string(current.key) == string(key) {
244217
if current.IsExpired() || bytes.Equal(current.value, []byte(TOMBSTONE_VALUE)) {
245-
// Mark as tombstone and delete later
246-
current.ttl = nil
247-
248-
// Subtraction of the size of the old value
249-
sl.size -= current.Size()
250-
// Mark as tombstone
251-
current.value = []byte(TOMBSTONE_VALUE)
252-
253-
// Add the size of the tombstone
254-
sl.size += current.Size()
255218
return nil, false
256219
}
257220
return current.value, true

skiplist/skiplist_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,4 +158,13 @@ func TestInsertTombstone(t *testing.T) {
158158
if found {
159159
t.Fatal("Expected key to be deleted")
160160
}
161+
162+
key = []byte("key2")
163+
value = []byte("$tombstone")
164+
165+
sl.Insert(key, value, nil)
166+
_, found = sl.Search(key)
167+
if found {
168+
t.Fatal("Expected key to be deleted")
169+
}
161170
}

0 commit comments

Comments
 (0)