From fb6540eb5df9e4ece2a4f413366de7de4e08f66c Mon Sep 17 00:00:00 2001 From: Leviathan Date: Wed, 17 Jan 2018 10:42:40 +0800 Subject: [PATCH] add Setnx() and Append() (#1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add examples * add Setnx() and Append() * bugfix add the lock before Put() * bugfix logic errors“ --- .gitignore | 2 ++ examples/strings_example.cc | 18 ++++++++++++ include/blackwidow/blackwidow.h | 2 ++ src/blackwidow.cc | 8 ++++++ src/redis_strings.cc | 50 +++++++++++++++++++++++++++++++++ src/redis_strings.h | 2 ++ 6 files changed, 82 insertions(+) diff --git a/.gitignore b/.gitignore index 13f03ed23a..25b113db35 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,5 @@ # Others tags src/build_version.cc +examples/strings_example +examples/db diff --git a/examples/strings_example.cc b/examples/strings_example.cc index a1a47a4322..c4aa2570f1 100644 --- a/examples/strings_example.cc +++ b/examples/strings_example.cc @@ -18,16 +18,34 @@ int main() { printf("Open failed, error: %s\n", s.ToString().c_str()); return -1; } + // Set s = db.Set("TEST_KEY", "TEST_VALUE"); printf("Set return: %s\n", s.ToString().c_str()); + + // Get std::string value; s = db.Get("TEST_KEY", &value); printf("Get return: %s, value: %s\n", s.ToString().c_str(), value.c_str()); + + // Setnx + int32_t ret; + s = db.Setnx("TEST_KEY", "TEST_VALUE", &ret); + printf("Setnx return: %s, value: %s, ret: %d\n", s.ToString().c_str(), value.c_str(), ret); + + // Append + std::string append_value; + s = db.Append("TEST_KEY", "APPEND_VALUE", &ret); + s = db.Get("TEST_KEY", &append_value); + printf("Append return: %s, value: %s, ret: %d\n", s.ToString().c_str(), append_value.c_str(), ret); + + // Expire s = db.Expire("TEST_KEY", 1); printf("Expire return: %s\n", s.ToString().c_str()); std::this_thread::sleep_for(std::chrono::milliseconds(2500)); s = db.Get("TEST_KEY", &value); printf("Get return: %s, value: %s\n", s.ToString().c_str(), value.c_str()); + + // Compact s = db.Compact(); printf("Compact return: %s\n", s.ToString().c_str()); diff --git a/include/blackwidow/blackwidow.h b/include/blackwidow/blackwidow.h index e4f6ee0ce0..920a1a640b 100644 --- a/include/blackwidow/blackwidow.h +++ b/include/blackwidow/blackwidow.h @@ -31,6 +31,8 @@ class BlackWidow { // Strings Commands Status Set(const Slice& key, const Slice& value); Status Get(const Slice& key, std::string* value); + Status Setnx(const Slice& key, const Slice& value, int32_t* ret); + Status Append(const Slice& key, const Slice& value, int32_t* ret); // Keys Commands Status Expire(const Slice& key, int32_t ttl); diff --git a/src/blackwidow.cc b/src/blackwidow.cc index 11d38b760b..2d070637ff 100644 --- a/src/blackwidow.cc +++ b/src/blackwidow.cc @@ -45,6 +45,14 @@ Status BlackWidow::Get(const Slice& key, std::string* value) { return strings_db_->Get(key, value); } +Status BlackWidow::Setnx(const Slice& key, const Slice& value, int32_t* ret) { + return strings_db_->Setnx(key, value, ret); +} + +Status BlackWidow::Append(const Slice& key, const Slice& value, int32_t* ret) { + return strings_db_->Append(key, value, ret); +} + Status BlackWidow::Expire(const Slice& key, int32_t ttl) { return strings_db_->Expire(key, ttl); } diff --git a/src/redis_strings.cc b/src/redis_strings.cc index 02fc629e2a..074e81df10 100644 --- a/src/redis_strings.cc +++ b/src/redis_strings.cc @@ -39,6 +39,56 @@ Status RedisStrings::Get(const Slice& key, std::string* value) { return s; } +Status RedisStrings::Setnx(const Slice& key, const Slice& value, int32_t* ret) { + *ret = 0; + std::string old_value; + ScopeRecordLock l(lock_mgr_, key); + Status s = db_->Get(default_read_options_, key, &old_value); + if (s.ok()) { + ParsedInternalStringsValue internal_value(&old_value); + if (internal_value.IsStale()) { + InternalStringsValue new_value(value); + s = db_->Put(default_write_options_, key, new_value.Encode()); + if (s.ok()) { + *ret = 1; + } + } + } else if (s.IsNotFound()) { + InternalStringsValue new_value(value); + s = db_->Put(default_write_options_, key, new_value.Encode()); + if (s.ok()) { + *ret = 1; + } + } + return s; +} + +Status RedisStrings::Append(const Slice& key, const Slice& value, int32_t* ret) { + std::string old_value; + *ret = 0; + ScopeRecordLock l(lock_mgr_, key); + Status s = db_->Get(default_read_options_, key, &old_value); + if (s.ok()) { + ParsedInternalStringsValue internal_value(&old_value); + if (internal_value.IsStale()) { + *ret = value.size(); + InternalStringsValue new_value(value); + return db_->Put(default_write_options_, key, new_value.Encode()); + } else { + internal_value.StripSuffix(); + *ret = old_value.size() + value.size(); + old_value += value.data(); + InternalStringsValue new_value(old_value); + return db_->Put(default_write_options_, key, new_value.Encode()); + } + } else if (s.IsNotFound()) { + *ret = value.size(); + InternalStringsValue internal_value(value); + return db_->Put(default_write_options_, key, internal_value.Encode()); + } + return s; +} + Status RedisStrings::Expire(const Slice& key, int32_t ttl) { std::string value; ScopeRecordLock l(lock_mgr_, key); diff --git a/src/redis_strings.h b/src/redis_strings.h index 5fe48d5fd3..5031832a44 100644 --- a/src/redis_strings.h +++ b/src/redis_strings.h @@ -21,6 +21,8 @@ class RedisStrings : public Redis { // Strings Commands Status Set(const Slice& key, const Slice& value); Status Get(const Slice& key, std::string* value); + Status Setnx(const Slice& key, const Slice& value, int32_t* ret); + Status Append(const Slice& key, const Slice& value, int32_t* ret); // Common Commands virtual Status Open(const rocksdb::Options& options,