Skip to content

Commit

Permalink
feat: make add command group style same with single command (OpenAtom…
Browse files Browse the repository at this point in the history
…Foundation#296)

* feat: make add command group style same with single command

* chore: make date/commit id print only printed in release mode

---
changes since v1:
- make cmake key words UPPERCASE

* feat: add framework of debug command, 3 subcommands supported first

* chore: make date/commit id target compile options to reduce scope
  • Loading branch information
iyenli authored May 20, 2024
1 parent 3931060 commit 128d408
Show file tree
Hide file tree
Showing 8 changed files with 153 additions and 24 deletions.
35 changes: 17 additions & 18 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,24 +29,23 @@ ELSEIF (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
ENDIF ()
ENDIF ()

# get current date and time
EXECUTE_PROCESS(COMMAND date "+%Y-%m-%d_%H:%M:%S" OUTPUT_VARIABLE BUILD_TIMESTAMP OUTPUT_STRIP_TRAILING_WHITESPACE)
message(STATUS "Build timestamp: ${BUILD_TIMESTAMP}")

# get git commit id
EXECUTE_PROCESS(COMMAND git rev-parse HEAD OUTPUT_VARIABLE GIT_COMMIT_ID OUTPUT_STRIP_TRAILING_WHITESPACE)
MESSAGE(STATUS "Git commit id: ${GIT_COMMIT_ID}")

############# You should enable sanitizer if you are developing pikiwidb #############
# Uncomment the following two lines to enable AddressSanitizer to detect memory leaks and other memory-related bugs.
# SET(CMAKE_BUILD_TYPE "Debug")
# SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address -O0 -fno-omit-frame-pointer -fno-optimize-sibling-calls")

# [Notice] AddressSanitizer and ThreadSanitizer can not be enabled at the same time.

# Uncomment the following two lines to enable ThreadSanitizer to detect data race and other thread-related issue.
# SET(CMAKE_BUILD_TYPE "Debug")
# SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=thread -O0 -fno-omit-frame-pointer -fno-optimize-sibling-calls")
IF(CMAKE_BUILD_TYPE STREQUAL "Release")
MESSAGE("Building in Release mode")
ELSE()
MESSAGE("Building in Debug mode")
OPTION(ADDRESS_SANITIZER "Enable AddressSanitizer (default sanitizer)" ON)
OPTION(THREAD_SANITIZER "Enable ThreadSanitizer" OFF)

IF(THREAD_SANITIZER)
# enable ThreadSanitizer to detect data race and other thread-related issue.
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=thread -O0 -fno-omit-frame-pointer -fno-optimize-sibling-calls")
MESSAGE(STATUS "ThreadSanitizer is enabled.")
ELSEIF(ADDRESS_SANITIZER)
# enable AddressSanitizer to detect memory leaks and other memory-related bugs.
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address -O0 -fno-omit-frame-pointer -fno-optimize-sibling-calls")
MESSAGE(STATUS "AddressSanitizer is enabled.")
ENDIF()
ENDIF()

EXECUTE_PROCESS(COMMAND uname -p OUTPUT_VARIABLE HOST_ARCH)
STRING(TOLOWER ${HOST_ARCH} HOST_ARCH)
Expand Down
14 changes: 12 additions & 2 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,18 @@
AUX_SOURCE_DIRECTORY(. PIKIWIDB_SRC)

ADD_EXECUTABLE(pikiwidb ${PIKIWIDB_SRC})
TARGET_COMPILE_DEFINITIONS(pikiwidb PRIVATE KPIKIWIDB_BUILD_DATE="${BUILD_TIMESTAMP}")
TARGET_COMPILE_DEFINITIONS(pikiwidb PRIVATE KPIKIWIDB_GIT_COMMIT_ID="${GIT_COMMIT_ID}")

IF(CMAKE_BUILD_TYPE STREQUAL "Release")
# get current date and time and git commit id
EXECUTE_PROCESS(COMMAND date "+%Y-%m-%d_%H:%M:%S" OUTPUT_VARIABLE BUILD_TIMESTAMP OUTPUT_STRIP_TRAILING_WHITESPACE)
EXECUTE_PROCESS(COMMAND git rev-parse HEAD OUTPUT_VARIABLE GIT_COMMIT_ID OUTPUT_STRIP_TRAILING_WHITESPACE)

MESSAGE(STATUS "Build timestamp: ${BUILD_TIMESTAMP}")
MESSAGE(STATUS "Git commit id: ${GIT_COMMIT_ID}")

TARGET_COMPILE_DEFINITIONS(pikiwidb PRIVATE KPIKIWIDB_BUILD_DATE="${BUILD_TIMESTAMP}" KPIKIWIDB_GIT_COMMIT_ID="${GIT_COMMIT_ID}")
ENDIF()

SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

TARGET_INCLUDE_DIRECTORIES(pikiwidb
Expand Down
6 changes: 6 additions & 0 deletions src/base_cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,17 @@ const std::string kCmdNameDiscard = "discard";

// admin
const std::string kCmdNameConfig = "config";
const std::string kSubCmdNameConfigGet = "get";
const std::string kSubCmdNameConfigSet = "set";
const std::string kCmdNameFlushdb = "flushdb";
const std::string kCmdNameFlushall = "flushall";
const std::string kCmdNameAuth = "auth";
const std::string kCmdNameSelect = "select";
const std::string kCmdNameShutdown = "shutdown";
const std::string kCmdNameDebug = "debug";
const std::string kSubCmdNameDebugHelp = "help";
const std::string kSubCmdNameDebugOOM = "oom";
const std::string kSubCmdNameDebugSegfault = "segfault";
const std::string kCmdNameInfo = "info";

// hash cmd
Expand Down
32 changes: 32 additions & 0 deletions src/cmd_admin.cc
Original file line number Diff line number Diff line change
Expand Up @@ -227,4 +227,36 @@ void InfoCmd::InfoData(PClient* client) {
client->AppendString(message);
}

CmdDebug::CmdDebug(const std::string& name, int arity) : BaseCmdGroup(name, kCmdFlagsAdmin, kAclCategoryAdmin) {}

bool CmdDebug::HasSubCommand() const { return true; }

CmdDebugHelp::CmdDebugHelp(const std::string& name, int16_t arity)
: BaseCmd(name, arity, kCmdFlagsAdmin | kCmdFlagsWrite, kAclCategoryAdmin) {}

bool CmdDebugHelp::DoInitial(PClient* client) { return true; }

void CmdDebugHelp::DoCmd(PClient* client) { client->AppendStringVector(debugHelps); }

CmdDebugOOM::CmdDebugOOM(const std::string& name, int16_t arity)
: BaseCmd(name, arity, kCmdFlagsAdmin | kCmdFlagsWrite, kAclCategoryAdmin) {}

bool CmdDebugOOM::DoInitial(PClient* client) { return true; }

void CmdDebugOOM::DoCmd(PClient* client) {
auto ptr = ::operator new(std::numeric_limits<unsigned long>::max());
::operator delete(ptr);
client->SetRes(CmdRes::kErrOther);
}

CmdDebugSegfault::CmdDebugSegfault(const std::string& name, int16_t arity)
: BaseCmd(name, arity, kCmdFlagsAdmin | kCmdFlagsWrite, kAclCategoryAdmin) {}

bool CmdDebugSegfault::DoInitial(PClient* client) { return true; }

void CmdDebugSegfault::DoCmd(PClient* client) {
auto ptr = reinterpret_cast<int*>(0);
*ptr = 0;
}

} // namespace pikiwidb
54 changes: 54 additions & 0 deletions src/cmd_admin.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@
#include "base_cmd.h"
#include "config.h"

const std::vector<std::string> debugHelps = {"DEBUG <subcommand> [<arg> [value] [opt] ...]. Subcommands are:",
"HELP",
" Print this help.",
"SEGFAULT",
" Crash the server with sigsegv.",
"OOM",
" Crash the server simulating an out-of-memory error."};

namespace pikiwidb {

class CmdConfig : public BaseCmdGroup {
Expand Down Expand Up @@ -118,4 +126,50 @@ class InfoCmd : public BaseCmd {
void InfoData(PClient* client);
};

class CmdDebug : public BaseCmdGroup {
public:
CmdDebug(const std::string& name, int arity);

bool HasSubCommand() const override;

protected:
bool DoInitial(PClient* client) override { return true; };

private:
void DoCmd(PClient* client) override{};
};

class CmdDebugHelp : public BaseCmd {
public:
CmdDebugHelp(const std::string& name, int16_t arity);

protected:
bool DoInitial(PClient* client) override;

private:
void DoCmd(PClient* client) override;
};

class CmdDebugOOM : public BaseCmd {
public:
CmdDebugOOM(const std::string& name, int16_t arity);

protected:
bool DoInitial(PClient* client) override;

private:
void DoCmd(PClient* client) override;
};

class CmdDebugSegfault : public BaseCmd {
public:
CmdDebugSegfault(const std::string& name, int16_t arity);

protected:
bool DoInitial(PClient* client) override;

private:
void DoCmd(PClient* client) override;
};

} // namespace pikiwidb
25 changes: 21 additions & 4 deletions src/cmd_table_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,20 @@ namespace pikiwidb {
cmds_->insert(std::make_pair(kCmdName##cmd, std::move(ptr))); \
} while (0)

#define ADD_COMMAND_GROUP(cmd, argc) \
do { \
std::unique_ptr<BaseCmd> ptr = std::make_unique<Cmd##cmd>(kCmdName##cmd, argc); \
cmds_->insert(std::make_pair(kCmdName##cmd, std::move(ptr))); \
} while (0)

#define ADD_SUBCOMMAND(cmd, subcmd, argc) \
do { \
auto it##cmd = cmds_->find(kCmdName##cmd); \
auto ptr##cmd = std::unique_ptr<BaseCmdGroup>(static_cast<BaseCmdGroup*>(it##cmd->second.release())); \
ptr##cmd->AddSubCmd(std::make_unique<Cmd##cmd##subcmd>(kSubCmdName##cmd##subcmd, argc)); \
it##cmd->second = std::move(ptr##cmd); \
} while (0)

CmdTableManager::CmdTableManager() {
cmds_ = std::make_unique<CmdTable>();
cmds_->reserve(300);
Expand All @@ -35,11 +49,14 @@ void CmdTableManager::InitCmdTable() {
std::unique_lock wl(mutex_);

// admin
auto configPtr = std::make_unique<CmdConfig>(kCmdNameConfig, -2);
configPtr->AddSubCmd(std::make_unique<CmdConfigGet>("get", -3));
configPtr->AddSubCmd(std::make_unique<CmdConfigSet>("set", -4));
cmds_->insert(std::make_pair(kCmdNameConfig, std::move(configPtr)));
ADD_COMMAND_GROUP(Config, -2);
ADD_SUBCOMMAND(Config, Get, -3);
ADD_SUBCOMMAND(Config, Set, -4);
ADD_COMMAND(Ping, 0);
ADD_COMMAND_GROUP(Debug, -2);
ADD_SUBCOMMAND(Debug, Help, 2);
ADD_SUBCOMMAND(Debug, OOM, 2);
ADD_SUBCOMMAND(Debug, Segfault, 2);

// server
ADD_COMMAND(Flushdb, 1);
Expand Down
4 changes: 4 additions & 0 deletions src/pikiwidb.cc
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,12 @@ bool PikiwiDB::ParseArgs(int ac, char* av[]) {
std::cerr << "PikiwiDB Server version: " << KPIKIWIDB_VERSION << " bits=" << (sizeof(void*) == 8 ? 64 : 32)
<< std::endl;
std::cerr << "PikiwiDB Server Build Type: " << KPIKIWIDB_BUILD_TYPE << std::endl;
#if defined(KPIKIWIDB_BUILD_DATE)
std::cerr << "PikiwiDB Server Build Date: " << KPIKIWIDB_BUILD_DATE << std::endl;
#endif
#if defined(KPIKIWIDB_GIT_COMMIT_ID)
std::cerr << "PikiwiDB Server Build GIT SHA: " << KPIKIWIDB_GIT_COMMIT_ID << std::endl;
#endif

exit(0);
} else if (strncasecmp(av[i], "-h", 2) == 0 || strncasecmp(av[i], "--help", 6) == 0) {
Expand Down
7 changes: 7 additions & 0 deletions tests/admin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,4 +152,11 @@ var _ = Describe("Admin", Ordered, func() {
ping := client.Ping(ctx)
Expect(ping.Err()).NotTo(HaveOccurred())
})

It("Cmd Debug", func() {
// TODO: enable test after implementing DebugObject
// res := client.DebugObject(ctx, "timeout")
// Expect(res.Err()).NotTo(HaveOccurred())
// Expect(res.Val()).To(Equal(map[string]string{"timeout": "0"}))
})
})

0 comments on commit 128d408

Please sign in to comment.