Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

libroach/engine: plumb support for SingleDelete operation #33440

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 23 additions & 3 deletions c-deps/libroach/batch.cc
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ DBStatus ProcessDeltaKey(Getter* base, rocksdb::WBWIIterator* delta, rocksdb::Sl
}
break;
}
case rocksdb::kSingleDeleteRecord:
// Treating a SingleDelete operation as a standard Delete doesn't
// quite mirror SingleDelete's expected implementation, but it
// doesn't violate the operation's contract:
// https://github.com/facebook/rocksdb/wiki/Single-Delete.
case rocksdb::kDeleteRecord:
if (value->data != NULL) {
free(value->data);
Expand Down Expand Up @@ -418,7 +423,7 @@ class DBBatchInserter : public rocksdb::WriteBatch::Handler {
DBBatchInserter(rocksdb::WriteBatchBase* batch) : batch_(batch) {}

virtual rocksdb::Status PutCF(uint32_t column_family_id, const rocksdb::Slice& key,
const rocksdb::Slice& value) {
const rocksdb::Slice& value) {
if (column_family_id != 0) {
return rocksdb::Status::InvalidArgument("DBBatchInserter: column families not supported");
}
Expand All @@ -431,10 +436,13 @@ class DBBatchInserter : public rocksdb::WriteBatch::Handler {
return batch_->Delete(key);
}
virtual rocksdb::Status SingleDeleteCF(uint32_t column_family_id, const rocksdb::Slice& key) {
return rocksdb::Status::InvalidArgument("DBBatchInserter: SingleDelete not supported");
if (column_family_id != 0) {
return rocksdb::Status::InvalidArgument("DBBatchInserter: column families not supported");
}
return batch_->SingleDelete(key);
}
virtual rocksdb::Status MergeCF(uint32_t column_family_id, const rocksdb::Slice& key,
const rocksdb::Slice& value) {
const rocksdb::Slice& value) {
if (column_family_id != 0) {
return rocksdb::Status::InvalidArgument("DBBatchInserter: column families not supported");
}
Expand Down Expand Up @@ -494,6 +502,12 @@ DBStatus DBBatch::Delete(DBKey key) {
return kSuccess;
}

DBStatus DBBatch::SingleDelete(DBKey key) {
++updates;
batch.SingleDelete(EncodeKey(key));
return kSuccess;
}

DBStatus DBBatch::DeleteRange(DBKey start, DBKey end) {
++updates;
has_delete_range = true;
Expand Down Expand Up @@ -597,6 +611,12 @@ DBStatus DBWriteOnlyBatch::Delete(DBKey key) {
return kSuccess;
}

DBStatus DBWriteOnlyBatch::SingleDelete(DBKey key) {
++updates;
batch.SingleDelete(EncodeKey(key));
return kSuccess;
}

DBStatus DBWriteOnlyBatch::DeleteRange(DBKey start, DBKey end) {
++updates;
batch.DeleteRange(EncodeKey(start), EncodeKey(end));
Expand Down
2 changes: 2 additions & 0 deletions c-deps/libroach/batch.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ struct DBBatch : public DBEngine {
virtual DBStatus Put(DBKey key, DBSlice value);
virtual DBStatus Merge(DBKey key, DBSlice value);
virtual DBStatus Delete(DBKey key);
virtual DBStatus SingleDelete(DBKey key);
virtual DBStatus DeleteRange(DBKey start, DBKey end);
virtual DBStatus CommitBatch(bool sync);
virtual DBStatus ApplyBatchRepr(DBSlice repr, bool sync);
Expand Down Expand Up @@ -63,6 +64,7 @@ struct DBWriteOnlyBatch : public DBEngine {
virtual DBStatus Put(DBKey key, DBSlice value);
virtual DBStatus Merge(DBKey key, DBSlice value);
virtual DBStatus Delete(DBKey key);
virtual DBStatus SingleDelete(DBKey key);
virtual DBStatus DeleteRange(DBKey start, DBKey end);
virtual DBStatus CommitBatch(bool sync);
virtual DBStatus ApplyBatchRepr(DBSlice repr, bool sync);
Expand Down
6 changes: 4 additions & 2 deletions c-deps/libroach/db.cc
Original file line number Diff line number Diff line change
Expand Up @@ -411,12 +411,12 @@ DBStatus DBCompactRange(DBEngine* db, DBSlice start, DBSlice end, bool force_bot
return kSuccess;
}

DBStatus DBDisableAutoCompaction(DBEngine *db) {
DBStatus DBDisableAutoCompaction(DBEngine* db) {
auto status = db->rep->SetOptions({{"disable_auto_compactions", "true"}});
return ToDBStatus(status);
}

DBStatus DBEnableAutoCompaction(DBEngine *db) {
DBStatus DBEnableAutoCompaction(DBEngine* db) {
auto status = db->rep->EnableAutoCompaction({db->rep->DefaultColumnFamily()});
return ToDBStatus(status);
}
Expand All @@ -439,6 +439,8 @@ DBStatus DBGet(DBEngine* db, DBKey key, DBString* value) { return db->Get(key, v

DBStatus DBDelete(DBEngine* db, DBKey key) { return db->Delete(key); }

DBStatus DBSingleDelete(DBEngine* db, DBKey key) { return db->SingleDelete(key); }

DBStatus DBDeleteRange(DBEngine* db, DBKey start, DBKey end) { return db->DeleteRange(start, end); }

DBStatus DBDeleteIterRange(DBEngine* db, DBIterator* iter, DBKey start, DBKey end) {
Expand Down
5 changes: 5 additions & 0 deletions c-deps/libroach/engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,11 @@ DBStatus DBImpl::Delete(DBKey key) {
return ToDBStatus(rep->Delete(options, EncodeKey(key)));
}

DBStatus DBImpl::SingleDelete(DBKey key) {
rocksdb::WriteOptions options;
return ToDBStatus(rep->SingleDelete(options, EncodeKey(key)));
}

DBStatus DBImpl::DeleteRange(DBKey start, DBKey end) {
rocksdb::WriteOptions options;
return ToDBStatus(
Expand Down
2 changes: 2 additions & 0 deletions c-deps/libroach/engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ struct DBEngine {
virtual DBStatus Put(DBKey key, DBSlice value) = 0;
virtual DBStatus Merge(DBKey key, DBSlice value) = 0;
virtual DBStatus Delete(DBKey key) = 0;
virtual DBStatus SingleDelete(DBKey key) = 0;
virtual DBStatus DeleteRange(DBKey start, DBKey end) = 0;
virtual DBStatus CommitBatch(bool sync) = 0;
virtual DBStatus ApplyBatchRepr(DBSlice repr, bool sync) = 0;
Expand Down Expand Up @@ -80,6 +81,7 @@ struct DBImpl : public DBEngine {
virtual DBStatus Put(DBKey key, DBSlice value);
virtual DBStatus Merge(DBKey key, DBSlice value);
virtual DBStatus Delete(DBKey key);
virtual DBStatus SingleDelete(DBKey key);
virtual DBStatus DeleteRange(DBKey start, DBKey end);
virtual DBStatus CommitBatch(bool sync);
virtual DBStatus ApplyBatchRepr(DBSlice repr, bool sync);
Expand Down
12 changes: 9 additions & 3 deletions c-deps/libroach/include/libroach.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,8 @@ DBStatus DBCompactRange(DBEngine* db, DBSlice start, DBSlice end, bool force_bot
// Disable/enable automatic compactions. Automatic compactions are
// enabled by default. Disabling is provided for testing purposes so
// that automatic compactions do not interfere with test expectations.
DBStatus DBDisableAutoCompaction(DBEngine *db);
DBStatus DBEnableAutoCompaction(DBEngine *db);
DBStatus DBDisableAutoCompaction(DBEngine* db);
DBStatus DBEnableAutoCompaction(DBEngine* db);

// Stores the approximate on-disk size of the given key range into the
// supplied uint64.
Expand All @@ -153,6 +153,11 @@ DBStatus DBGet(DBEngine* db, DBKey key, DBString* value);
// Deletes the database entry for "key".
DBStatus DBDelete(DBEngine* db, DBKey key);

// Deletes the most recent database entry for "key". See the following
// documentation for details on the subtleties of this operation:
// https://github.com/facebook/rocksdb/wiki/Single-Delete.
DBStatus DBSingleDelete(DBEngine* db, DBKey key);

// Deletes a range of keys from start (inclusive) to end (exclusive).
DBStatus DBDeleteRange(DBEngine* db, DBKey start, DBKey end);

Expand Down Expand Up @@ -326,7 +331,8 @@ typedef struct {
DBScanResults MVCCGet(DBIterator* iter, DBSlice key, DBTimestamp timestamp, DBTxn txn,
bool inconsistent, bool tombstones);
DBScanResults MVCCScan(DBIterator* iter, DBSlice start, DBSlice end, DBTimestamp timestamp,
int64_t max_keys, DBTxn txn, bool inconsistent, bool reverse, bool tombstones);
int64_t max_keys, DBTxn txn, bool inconsistent, bool reverse,
bool tombstones);

// DBStatsResult contains various runtime stats for RocksDB.
typedef struct {
Expand Down
2 changes: 2 additions & 0 deletions c-deps/libroach/snapshot.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ DBStatus DBSnapshot::Get(DBKey key, DBString* value) {

DBStatus DBSnapshot::Delete(DBKey key) { return FmtStatus("unsupported"); }

DBStatus DBSnapshot::SingleDelete(DBKey key) { return FmtStatus("unsupported"); }

DBStatus DBSnapshot::DeleteRange(DBKey start, DBKey end) { return FmtStatus("unsupported"); }

DBStatus DBSnapshot::CommitBatch(bool sync) { return FmtStatus("unsupported"); }
Expand Down
1 change: 1 addition & 0 deletions c-deps/libroach/snapshot.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ struct DBSnapshot : public DBEngine {
virtual DBStatus Put(DBKey key, DBSlice value);
virtual DBStatus Merge(DBKey key, DBSlice value);
virtual DBStatus Delete(DBKey key);
virtual DBStatus SingleDelete(DBKey key);
virtual DBStatus DeleteRange(DBKey start, DBKey end);
virtual DBStatus CommitBatch(bool sync);
virtual DBStatus ApplyBatchRepr(DBSlice repr, bool sync);
Expand Down
36 changes: 20 additions & 16 deletions pkg/storage/engine/batch.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const (
// BatchTypeColumnFamilyDeletion = 0x4
// BatchTypeColumnFamilyValue = 0x5
// BatchTypeColumnFamilyMerge = 0x6
// BatchTypeSingleDeletion = 0x7
BatchTypeSingleDeletion = 0x7
// BatchTypeColumnFamilySingleDeletion = 0x8
// BatchTypeBeginPrepareXID = 0x9
// BatchTypeEndPrepareXID = 0xA
Expand Down Expand Up @@ -75,10 +75,10 @@ const (
// data: uint8[len]
//
// The RocksDBBatchBuilder code currently only supports kTypeValue
// (BatchTypeValue), kTypeDeletion (BatchTypeDeletion)and kTypeMerge
// (BatchTypeMerge) operations. Before a batch is written to the RocksDB
// write-ahead-log, the sequence number is 0. The "fixed32" format is little
// endian.
// (BatchTypeValue), kTypeDeletion (BatchTypeDeletion), kTypeMerge
// (BatchTypeMerge), and kTypeSingleDeletion (BatchTypeSingleDeletion)
// operations. Before a batch is written to the RocksDB write-ahead-log,
// the sequence number is 0. The "fixed32" format is little endian.
//
// The keys encoded into the batch are MVCC keys: a string key with a timestamp
// suffix. MVCC keys are encoded as:
Expand Down Expand Up @@ -262,6 +262,15 @@ func (b *RocksDBBatchBuilder) Clear(key MVCCKey) {
b.repr[pos] = byte(BatchTypeDeletion)
}

// SingleClear removes the most recent item from the db with the given key.
func (b *RocksDBBatchBuilder) SingleClear(key MVCCKey) {
b.maybeInit()
b.count++
pos := len(b.repr)
b.encodeKey(key, 0)
b.repr[pos] = byte(BatchTypeSingleDeletion)
}

// LogData adds a blob of log data to the batch. It will be written to the WAL,
// but otherwise uninterpreted by RocksDB.
func (b *RocksDBBatchBuilder) LogData(data []byte) {
Expand Down Expand Up @@ -385,6 +394,8 @@ func rocksDBBatchVarString(repr []byte) (s []byte, orepr []byte, err error) {
// fmt.Printf("put(%x,%x)", r.Key(), r.Value())
// case BatchTypeMerge:
// fmt.Printf("merge(%x,%x)", r.Key(), r.Value())
// case BatchTypeSingleDeletion:
// fmt.Printf("single_delete(%x)", r.Key())
// }
// }
// if err := r.Error(); err != nil {
Expand All @@ -400,7 +411,7 @@ type RocksDBBatchReader struct {
count int

// The following all represent the current entry and are updated by Next.
// `value` is not applicable for BatchTypeDeletion.
// `value` is not applicable for BatchTypeDeletion or BatchTypeSingleDeletion.
offset int
typ BatchType
key []byte
Expand Down Expand Up @@ -447,7 +458,7 @@ func (r *RocksDBBatchReader) MVCCKey() (MVCCKey, error) {
// Value returns the value of the current batch entry. Value panics if the
// BatchType is BatchTypeDeleted.
func (r *RocksDBBatchReader) Value() []byte {
if r.typ == BatchTypeDeletion {
if r.typ == BatchTypeDeletion || r.typ == BatchTypeSingleDeletion {
panic("cannot call Value on a deletion entry")
}
return r.value
Expand All @@ -471,18 +482,11 @@ func (r *RocksDBBatchReader) Next() bool {
r.typ = BatchType(r.repr[0])
r.repr = r.repr[1:]
switch r.typ {
case BatchTypeDeletion:
case BatchTypeDeletion, BatchTypeSingleDeletion:
if r.key, r.err = r.varstring(); r.err != nil {
return false
}
case BatchTypeValue:
if r.key, r.err = r.varstring(); r.err != nil {
return false
}
if r.value, r.err = r.varstring(); r.err != nil {
return false
}
case BatchTypeMerge:
case BatchTypeValue, BatchTypeMerge:
if r.key, r.err = r.varstring(); r.err != nil {
return false
}
Expand Down
Loading