This is an automated email from the ASF dual-hosted git repository.
tison pushed a commit to branch unstable
in repository https://gitbox.apache.org/repos/asf/incubator-kvrocks.git
The following commit(s) were added to refs/heads/unstable by this push:
new 7b3b6dca Introduce fmt dependency to simplify string formatting (#1139)
7b3b6dca is described below
commit 7b3b6dcabcb05e5bff21c45334eafe3930589712
Author: Twice <[email protected]>
AuthorDate: Fri Nov 25 19:07:48 2022 +0800
Introduce fmt dependency to simplify string formatting (#1139)
---
CMakeLists.txt | 2 ++
NOTICE | 33 ++++++++++++++++++++++++
cmake/fmt.cmake | 27 ++++++++++++++++++++
src/cluster/cluster.cc | 31 +++++++++++------------
src/cluster/replication.cc | 15 ++++++-----
src/cluster/slot_import.cc | 2 +-
src/cluster/slot_migrate.cc | 10 ++++----
src/common/util.cc | 57 ++++++++++++++++++------------------------
src/config/config.cc | 33 +++++++++++++-----------
src/server/redis_connection.cc | 11 ++++----
src/server/server.cc | 17 ++++++-------
src/server/worker.cc | 6 ++---
src/stats/stats.cc | 6 ++---
src/storage/scripting.cc | 10 +++-----
src/types/redis_stream_base.h | 3 ++-
15 files changed, 157 insertions(+), 106 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e7a2160b..348d7aa3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -116,6 +116,7 @@ include(cmake/zlib.cmake)
include(cmake/zstd.cmake)
include(cmake/rocksdb.cmake)
include(cmake/libevent.cmake)
+include(cmake/fmt.cmake)
if (USE_LUAJIT)
include(cmake/luajit.cmake)
@@ -132,6 +133,7 @@ list(APPEND EXTERNAL_LIBS event_with_headers)
list(APPEND EXTERNAL_LIBS lz4)
list(APPEND EXTERNAL_LIBS zstd)
list(APPEND EXTERNAL_LIBS zlib_with_headers)
+list(APPEND EXTERNAL_LIBS fmt)
if (USE_LUAJIT)
list(APPEND EXTERNAL_LIBS luajit)
else()
diff --git a/NOTICE b/NOTICE
index b34a504d..3c72f25e 100644
--- a/NOTICE
+++ b/NOTICE
@@ -189,6 +189,39 @@ zlib is a massively spiffy yet delicately unobtrusive
compression library. It is
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
+For the library fmt(https://github.com/fmtlib/fmt):
+
+{fmt} is an open-source formatting library providing a fast and safe
alternative to C stdio and C++ iostreams.
+It is under the MIT license with an optional exception:
+
+ Copyright (c) 2012 - present, Victor Zverovich
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ --- Optional exception to the license ---
+
+ As an exception, if, as a result of your compiling your source code,
portions
+ of this Software are embedded into a machine-executable object form of such
+ source code, you may redistribute such embedded portions in such object
form
+ without including the above copyright and permission notices.
+
For src/types/geohash.*, src/common/rand.*, src/common/sha1.*,
src/storage/scripting.* and
some functions in src/common/util.cc are modified from Redis.
diff --git a/cmake/fmt.cmake b/cmake/fmt.cmake
new file mode 100644
index 00000000..094930e4
--- /dev/null
+++ b/cmake/fmt.cmake
@@ -0,0 +1,27 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+include_guard()
+
+include(cmake/utils.cmake)
+
+FetchContent_DeclareGitHubWithMirror(fmt
+ fmtlib/fmt 9.1.0
+ MD5=e6754011ff56bfc37631fcc90961e377
+)
+
+FetchContent_MakeAvailableWithArgs(fmt)
diff --git a/src/cluster/cluster.cc b/src/cluster/cluster.cc
index 50b4561a..d9bb378b 100644
--- a/src/cluster/cluster.cc
+++ b/src/cluster/cluster.cc
@@ -26,6 +26,7 @@
#include <memory>
#include "commands/redis_cmd.h"
+#include "fmt/format.h"
#include "parse_util.h"
#include "replication.h"
#include "server/server.h"
@@ -313,7 +314,7 @@ Status Cluster::ImportSlot(Redis::Connection *conn, int
slot, int state) {
switch (state) {
case kImportStart:
if (!svr_->slot_import_->Start(conn->GetFD(), slot)) {
- return Status(Status::NotOK, "Can't start importing slot " +
std::to_string(slot));
+ return {Status::NotOK, fmt::format("Can't start importing slot {}",
slot)};
}
// Set link importing
conn->SetImporting();
@@ -330,7 +331,7 @@ Status Cluster::ImportSlot(Redis::Connection *conn, int
slot, int state) {
if (!svr_->slot_import_->Success(slot)) {
LOG(ERROR) << "[import] Failed to set slot importing success, maybe
slot is wrong"
<< ", received slot: " << slot << ", current slot: " <<
svr_->slot_import_->GetSlot();
- return Status(Status::NotOK, "Failed to set slot " +
std::to_string(slot) + " importing success");
+ return {Status::NotOK, fmt::format("Failed to set slot {} importing
success", slot)};
}
LOG(INFO) << "[import] Succeed to import slot " << slot;
break;
@@ -338,12 +339,12 @@ Status Cluster::ImportSlot(Redis::Connection *conn, int
slot, int state) {
if (!svr_->slot_import_->Fail(slot)) {
LOG(ERROR) << "[import] Failed to set slot importing error, maybe slot
is wrong"
<< ", received slot: " << slot << ", current slot: " <<
svr_->slot_import_->GetSlot();
- return Status(Status::NotOK, "Failed to set slot " +
std::to_string(slot) + " importing error");
+ return {Status::NotOK, fmt::format("Failed to set slot {} importing
error", slot)};
}
LOG(INFO) << "[import] Failed to import slot " << slot;
break;
default:
- return Status(Status::NotOK, errInvalidImportState);
+ return {Status::NotOK, errInvalidImportState};
}
return Status::OK();
}
@@ -469,9 +470,9 @@ std::string Cluster::GenNodesDescription() {
// Generate slots info when occur different node with start or end of slot
if (i == kClusterSlots || n != slots_nodes_[i]) {
if (start == i - 1) {
- n->slots_info_ += std::to_string(start) + " ";
+ n->slots_info_ += fmt::format("{} ", start);
} else {
- n->slots_info_ += std::to_string(start) + "-" + std::to_string(i - 1)
+ " ";
+ n->slots_info_ += fmt::format("{}-{} ", start, i - 1);
}
if (i == kClusterSlots) break;
n = slots_nodes_[i];
@@ -486,8 +487,7 @@ std::string Cluster::GenNodesDescription() {
std::string node_str;
// ID, host, port
node_str.append(n->id_ + " ");
- node_str.append(n->host_ + ":" + std::to_string(n->port_) + "@" +
std::to_string(n->port_ + kClusterPortIncr) +
- " ");
+ node_str.append(fmt::format("{}:{}@{} ", n->host_, n->port_, n->port_ +
kClusterPortIncr));
// Flags
if (n->id_ == myid_) node_str.append("myself,");
@@ -499,8 +499,7 @@ std::string Cluster::GenNodesDescription() {
// Ping sent, pong received, config epoch, link status
auto now = Util::GetTimeStampMS();
- node_str.append(std::to_string(now - 1) + " " + std::to_string(now) + " "
+ std::to_string(version_) + " " +
- "connected");
+ node_str.append(fmt::format("{} {} {} connected", now - 1, now, version_));
// Slots
if (n->slots_info_.size() > 0) n->slots_info_.pop_back(); // Trim space
@@ -642,24 +641,24 @@ Status Cluster::CanExecByMySelf(const
Redis::CommandAttributes *attributes, cons
int cur_slot = GetSlotNumFromKey(cmd_tokens[i]);
if (slot == -1) slot = cur_slot;
if (slot != cur_slot) {
- return Status(Status::RedisExecErr, "CROSSSLOT Attempted to access keys
that don't hash to the same slot");
+ return {Status::RedisExecErr, "CROSSSLOT Attempted to access keys that
don't hash to the same slot"};
}
}
if (slot == -1) return Status::OK();
if (slots_nodes_[slot] == nullptr) {
- return Status(Status::ClusterDown, "CLUSTERDOWN Hash slot not served");
+ return {Status::ClusterDown, "CLUSTERDOWN Hash slot not served"};
} else if (myself_ && myself_ == slots_nodes_[slot]) {
// We use central controller to manage the topology of the cluster.
// Server can't change the topology directly, so we record the migrated
slots
// to move the requests of the migrated slots to the destination node.
if (migrated_slots_.count(slot)) { // I'm not serving the migrated slot
- return Status(Status::RedisExecErr, "MOVED " + std::to_string(slot) + "
" + migrated_slots_[slot]);
+ return {Status::RedisExecErr, fmt::format("MOVED {} {}", slot,
migrated_slots_[slot])};
}
// To keep data consistency, slot will be forbidden write while sending
the last incremental data.
// During this phase, the requests of the migrating slot has to be
rejected.
if (attributes->is_write() && IsWriteForbiddenSlot(slot)) {
- return Status(Status::RedisExecErr, "Can't write to slot being migrated
which is in write forbidden phase");
+ return {Status::RedisExecErr, "Can't write to slot being migrated which
is in write forbidden phase"};
}
return Status::OK(); // I'm serving this slot
} else if (myself_ && myself_->importing_slot_ == slot &&
conn->IsImporting()) {
@@ -677,7 +676,7 @@ Status Cluster::CanExecByMySelf(const
Redis::CommandAttributes *attributes, cons
nodes_.find(myself_->master_id_) != nodes_.end() &&
nodes_[myself_->master_id_] == slots_nodes_[slot]) {
return Status::OK(); // My mater is serving this slot
} else {
- std::string ip_port = slots_nodes_[slot]->host_ + ":" +
std::to_string(slots_nodes_[slot]->port_);
- return Status(Status::RedisExecErr, "MOVED " + std::to_string(slot) + " "
+ ip_port);
+ return {Status::RedisExecErr,
+ fmt::format("MOVED {} {}:{}", slot, slots_nodes_[slot]->host_,
slots_nodes_[slot]->port_)};
}
}
diff --git a/src/cluster/replication.cc b/src/cluster/replication.cc
index 6bb5d6ff..0de4427d 100644
--- a/src/cluster/replication.cc
+++ b/src/cluster/replication.cc
@@ -34,6 +34,7 @@
#include "event_util.h"
#include "fd_util.h"
+#include "fmt/format.h"
#include "rocksdb_crc32c.h"
#include "server/redis_reply.h"
#include "server/server.h"
@@ -797,13 +798,13 @@ Status ReplicationThread::fetchFile(int sock_fd, evbuffer
*evbuf, const std::str
UniqueEvbufReadln line(evbuf, EVBUFFER_EOL_CRLF_STRICT);
if (!line) {
if (evbuffer_read(evbuf, sock_fd, -1) <= 0) {
- return Status(Status::NotOK, std::string("read size: ") +
strerror(errno));
+ return {Status::NotOK, fmt::format("read size: {}", strerror(errno))};
}
continue;
}
if (line[0] == '-') {
std::string msg(line.get());
- return Status(Status::NotOK, msg);
+ return {Status::NotOK, msg};
}
file_size = line.length > 0 ? std::strtoull(line.get(), nullptr, 10) : 0;
break;
@@ -812,7 +813,7 @@ Status ReplicationThread::fetchFile(int sock_fd, evbuffer
*evbuf, const std::str
// Write to tmp file
auto tmp_file = Engine::Storage::ReplDataManager::NewTmpFile(storage_, dir,
file);
if (!tmp_file) {
- return Status(Status::NotOK, "unable to create tmp file");
+ return {Status::NotOK, "unable to create tmp file"};
}
size_t remain = file_size;
@@ -823,22 +824,20 @@ Status ReplicationThread::fetchFile(int sock_fd, evbuffer
*evbuf, const std::str
auto data_len = evbuffer_remove(evbuf, data, remain > 16 * 1024 ? 16 *
1024 : remain);
if (data_len == 0) continue;
if (data_len < 0) {
- return Status(Status::NotOK, "read sst file data error");
+ return {Status::NotOK, "read sst file data error"};
}
tmp_file->Append(rocksdb::Slice(data, data_len));
tmp_crc = rocksdb::crc32c::Extend(tmp_crc, data, data_len);
remain -= data_len;
} else {
if (evbuffer_read(evbuf, sock_fd, -1) <= 0) {
- return Status(Status::NotOK, std::string("read sst file: ") +
strerror(errno));
+ return {Status::NotOK, fmt::format("read sst file: {}",
strerror(errno))};
}
}
}
// Verify file crc checksum if crc is not 0
if (crc && crc != tmp_crc) {
- char err_buf[64];
- snprintf(err_buf, sizeof(err_buf), "CRC mismatched, %u was expected but
got %u", crc, tmp_crc);
- return Status(Status::NotOK, err_buf);
+ return {Status::NotOK, fmt::format("CRC mismatched, {} was expected but
got {}", crc, tmp_crc)};
}
// File is OK, rename to formal name
auto s = Engine::Storage::ReplDataManager::SwapTmpFile(storage_, dir, file);
diff --git a/src/cluster/slot_import.cc b/src/cluster/slot_import.cc
index 03533422..76e2914c 100644
--- a/src/cluster/slot_import.cc
+++ b/src/cluster/slot_import.cc
@@ -153,5 +153,5 @@ void SlotImport::GetImportInfo(std::string *info) {
break;
}
- *info = "importing_slot: " + std::to_string(import_slot_) + "\r\n" +
"import_state: " + import_stat + "\r\n";
+ *info = fmt::format("importing_slot: {}\r\nimport_state: {}\r\n",
import_slot_, import_stat);
}
diff --git a/src/cluster/slot_migrate.cc b/src/cluster/slot_migrate.cc
index b880cea3..8f7b8924 100644
--- a/src/cluster/slot_migrate.cc
+++ b/src/cluster/slot_migrate.cc
@@ -24,6 +24,7 @@
#include <utility>
#include "event_util.h"
+#include "fmt/format.h"
#include "storage/batch_extractor.h"
static std::map<RedisType, std::string> type_to_cmd = {
@@ -481,7 +482,7 @@ bool SlotMigrate::CheckResponseWithCounts(int sock_fd, int
total) {
while (true) {
// Read response data from socket buffer to the event buffer
if (evbuffer_read(evbuf.get(), sock_fd, -1) <= 0) {
- LOG(ERROR) << "[migrate] Failed to read response, Err: " +
std::string(strerror(errno));
+ LOG(ERROR) << "[migrate] Failed to read response, Err: " <<
strerror(errno);
return false;
}
@@ -499,8 +500,7 @@ bool SlotMigrate::CheckResponseWithCounts(int sock_fd, int
total) {
}
if (line[0] == '-') {
- LOG(ERROR) << "[migrate] Got invalid response: " +
std::string(line.get())
- << ", line length: " << line.length;
+ LOG(ERROR) << "[migrate] Got invalid response: " << line.get() <<
", line length: " << line.length;
stat_ = Error;
} else if (line[0] == '$') {
auto parse_result = ParseInt<uint64_t>(std::string(line.get() + 1,
line.length - 1), 10);
@@ -985,6 +985,6 @@ void SlotMigrate::GetMigrateInfo(std::string *info) {
break;
}
- *info = "migrating_slot: " + std::to_string(slot) + "\r\n" +
"destination_node: " + dst_node_ + "\r\n" +
- "migrating_state: " + task_state + "\r\n";
+ *info =
+ fmt::format("migrating_slot: {}\r\ndestination_node:
{}\r\nmigrating_state: {}\r\n", slot, dst_node_, task_state);
}
diff --git a/src/common/util.cc b/src/common/util.cc
index 66af04c7..2679b12f 100644
--- a/src/common/util.cc
+++ b/src/common/util.cc
@@ -18,6 +18,7 @@
*
*/
+#include "fmt/core.h"
#define __STDC_FORMAT_MACROS
#include <event2/buffer.h>
@@ -67,17 +68,14 @@
namespace Util {
Status SockConnect(const std::string &host, uint32_t port, int *fd) {
- int rv;
- char portstr[6]; /* strlen("65535") + 1; */
addrinfo hints, *servinfo, *p;
- snprintf(portstr, sizeof(portstr), "%u", port);
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
- if ((rv = getaddrinfo(host.c_str(), portstr, &hints, &servinfo)) != 0) {
- return Status(Status::NotOK, gai_strerror(rv));
+ if (int rv = getaddrinfo(host.c_str(), std::to_string(port).c_str(), &hints,
&servinfo); rv != 0) {
+ return {Status::NotOK, gai_strerror(rv)};
}
auto exit = MakeScopeExit([servinfo] { freeaddrinfo(servinfo); });
@@ -108,14 +106,12 @@ const std::string Float2String(double d) {
return d > 0 ? "inf" : "-inf";
}
- char buf[128];
- snprintf(buf, sizeof(buf), "%.17g", d);
- return buf;
+ return fmt::format("{:.17g}", d);
}
Status SockSetTcpNoDelay(int fd, int val) {
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)) == -1) {
- return Status(Status::NotOK, strerror(errno));
+ return Status::FromErrno();
}
return Status::OK();
}
@@ -123,7 +119,7 @@ Status SockSetTcpNoDelay(int fd, int val) {
Status SockSetTcpKeepalive(int fd, int interval) {
int val = 1;
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1) {
- return Status(Status::NotOK, strerror(errno));
+ return Status::FromErrno();
}
#ifdef __linux__
@@ -134,7 +130,7 @@ Status SockSetTcpKeepalive(int fd, int interval) {
// Send first probe after interval.
val = interval;
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val)) < 0) {
- return Status(Status::NotOK, std::string("setsockopt TCP_KEEPIDLE: ") +
strerror(errno));
+ return {Status::NotOK, fmt::format("setsockopt TCP_KEEPIDLE: {}",
strerror(errno))};
}
// Send next probes after the specified interval. Note that we set the
@@ -143,14 +139,14 @@ Status SockSetTcpKeepalive(int fd, int interval) {
val = interval / 3;
if (val == 0) val = 1;
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &val, sizeof(val)) < 0) {
- return Status(Status::NotOK, std::string("setsockopt TCP_KEEPINTVL: ") +
strerror(errno));
+ return {Status::NotOK, fmt::format("setsockopt TCP_KEEPINTVL: {}",
strerror(errno))};
}
// Consider the socket in error state after three we send three ACK
// probes without getting a reply.
val = 3;
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &val, sizeof(val)) < 0) {
- return Status(Status::NotOK, std::string("setsockopt TCP_KEEPCNT: ") +
strerror(errno));
+ return {Status::NotOK, fmt::format("setsockopt TCP_KEEPCNT: {}",
strerror(errno))};
}
#else
((void)interval); // Avoid unused var warning for non Linux systems.
@@ -540,28 +536,23 @@ std::string StringToHex(const std::string &input) {
return output;
}
+constexpr unsigned long long expTo1024(unsigned n) { return 1ULL << (n * 10); }
+
void BytesToHuman(char *buf, size_t size, uint64_t n) {
- double d;
-
- if (n < 1024) {
- snprintf(buf, size, "%" PRIu64 "B", n);
- } else if (n < (1024 * 1024)) {
- d = static_cast<double>(n) / (1024);
- snprintf(buf, size, "%.2fK", d);
- } else if (n < (1024LL * 1024 * 1024)) {
- d = static_cast<double>(n) / (1024 * 1024);
- snprintf(buf, size, "%.2fM", d);
- } else if (n < (1024LL * 1024 * 1024 * 1024)) {
- d = static_cast<double>(n) / (1024LL * 1024 * 1024);
- snprintf(buf, size, "%.2fG", d);
- } else if (n < (1024LL * 1024 * 1024 * 1024 * 1024)) {
- d = static_cast<double>(n) / (1024LL * 1024 * 1024 * 1024);
- snprintf(buf, size, "%.2fT", d);
- } else if (n < (1024LL * 1024 * 1024 * 1024 * 1024 * 1024)) {
- d = static_cast<double>(n) / (1024LL * 1024 * 1024 * 1024 * 1024);
- snprintf(buf, size, "%.2fP", d);
+ if (n < expTo1024(1)) {
+ fmt::format_to_n(buf, size, "{}B", n);
+ } else if (n < expTo1024(2)) {
+ fmt::format_to_n(buf, size, "{:.2f}K", static_cast<double>(n) /
expTo1024(1));
+ } else if (n < expTo1024(3)) {
+ fmt::format_to_n(buf, size, "{:.2f}M", static_cast<double>(n) /
expTo1024(2));
+ } else if (n < expTo1024(4)) {
+ fmt::format_to_n(buf, size, "{:.2f}G", static_cast<double>(n) /
expTo1024(3));
+ } else if (n < expTo1024(5)) {
+ fmt::format_to_n(buf, size, "{:.2f}T", static_cast<double>(n) /
expTo1024(4));
+ } else if (n < expTo1024(6)) {
+ fmt::format_to_n(buf, size, "{:.2f}P", static_cast<double>(n) /
expTo1024(5));
} else {
- snprintf(buf, size, "%" PRIu64 "B", n);
+ fmt::format_to_n(buf, size, "{}B", n);
}
}
diff --git a/src/config/config.cc b/src/config/config.cc
index 62e8cce0..aa169b28 100644
--- a/src/config/config.cc
+++ b/src/config/config.cc
@@ -29,13 +29,16 @@
#include <cstring>
#include <fstream>
#include <iostream>
+#include <iterator>
#include <limits>
#include <sstream>
+#include <string>
#include <utility>
#include <vector>
#include "config_type.h"
#include "config_util.h"
+#include "fmt/format.h"
#include "parse_util.h"
#include "server/server.h"
#include "server/tls_util.h"
@@ -673,7 +676,7 @@ Status Config::Load(const CLIOptions &opts) {
} else {
path_ = opts.conf_file;
file.open(path_);
- if (!file.is_open()) return Status(Status::NotOK, strerror(errno));
+ if (!file.is_open()) return Status::FromErrno();
in = &file;
}
@@ -682,7 +685,7 @@ Status Config::Load(const CLIOptions &opts) {
while (!in->eof()) {
std::getline(*in, line);
if (auto s = parseConfigFromString(line, line_num); !s) {
- return Status(Status::NotOK, "at line: #L" + std::to_string(line_num)
+ ", err: " + s.Msg());
+ return {Status::NotOK, fmt::format("at line: #L{}, err: {}", line_num,
s.Msg())};
}
line_num++;
}
@@ -694,7 +697,7 @@ Status Config::Load(const CLIOptions &opts) {
for (const auto &opt : opts.cli_options) {
if (Status s = parseConfigFromPair(opt, -1); !s) {
- return Status(Status::NotOK, "CLI config option error: " + s.Msg());
+ return {Status::NotOK, "CLI config option error: " + s.Msg()};
}
}
@@ -704,8 +707,8 @@ Status Config::Load(const CLIOptions &opts) {
if (iter.second->line_number != 0 && iter.second->validate) {
auto s = iter.second->validate(iter.first, iter.second->ToString());
if (!s.IsOK()) {
- return Status(Status::NotOK, "at line: #L" +
std::to_string(iter.second->line_number) + ", " + iter.first +
- " is invalid: " + s.Msg());
+ return {Status::NotOK,
+ fmt::format("at line: #L{}, {} is invalid: {}",
iter.second->line_number, iter.first, s.Msg())};
}
}
}
@@ -714,7 +717,7 @@ Status Config::Load(const CLIOptions &opts) {
if (iter.second->callback) {
auto s = iter.second->callback(nullptr, iter.first,
iter.second->ToString());
if (!s.IsOK()) {
- return Status(Status::NotOK, s.Msg() + " in key '" + iter.first + "'");
+ return {Status::NotOK, fmt::format("{} in key '{}'", s.Msg(),
iter.first)};
}
}
}
@@ -759,7 +762,7 @@ Status Config::Set(Server *svr, std::string key, const
std::string &value) {
Status Config::Rewrite() {
if (path_.empty()) {
- return Status(Status::NotOK, "the server is running without a config
file");
+ return {Status::NotOK, "the server is running without a config file"};
}
std::vector<std::string> lines;
std::map<std::string, std::string> new_config;
@@ -803,21 +806,21 @@ Status Config::Rewrite() {
}
file.close();
- std::ostringstream string_stream;
+ std::string out_buf;
for (const auto &line : lines) {
- string_stream << line << "\n";
+ fmt::format_to(std::back_inserter(out_buf), "{}\n", line);
}
for (const auto &remain : new_config) {
if (remain.second.empty()) continue;
- string_stream << remain.first << " " << remain.second << "\n";
+ fmt::format_to(std::back_inserter(out_buf), "{} {}\n", remain.first,
remain.second);
}
std::string tmp_path = path_ + ".tmp";
remove(tmp_path.data());
std::ofstream output_file(tmp_path, std::ios::out);
- output_file.write(string_stream.str().c_str(), string_stream.str().size());
+ output_file << out_buf;
output_file.close();
if (rename(tmp_path.data(), path_.data()) < 0) {
- return Status(Status::NotOK, std::string("rename file encounter error: ")
+ strerror(errno));
+ return {Status::NotOK, fmt::format("rename file encounter error: {}",
strerror(errno))};
}
return Status::OK();
}
@@ -909,16 +912,16 @@ Status Config::DelNamespace(const std::string &ns) {
return s;
}
}
- return Status(Status::NotOK, "the namespace was not found");
+ return {Status::NotOK, "the namespace was not found"};
}
Status Config::isNamespaceLegal(const std::string &ns) {
if (ns.size() > UINT8_MAX) {
- return Status(Status::NotOK, std::string("size exceed limit ") +
std::to_string(UINT8_MAX));
+ return {Status::NotOK, fmt::format("size exceed limit {}", UINT8_MAX)};
}
char last_char = ns.back();
if (last_char == std::numeric_limits<char>::max()) {
- return Status(Status::NotOK, std::string("namespace contain illegal
letter"));
+ return {Status::NotOK, "namespace contain illegal letter"};
}
return Status::OK();
}
diff --git a/src/server/redis_connection.cc b/src/server/redis_connection.cc
index 1c4b02f0..1cec1317 100644
--- a/src/server/redis_connection.cc
+++ b/src/server/redis_connection.cc
@@ -21,6 +21,8 @@
#include <glog/logging.h>
#include <rocksdb/iostats_context.h>
#include <rocksdb/perf_context.h>
+
+#include "fmt/format.h"
#ifdef ENABLE_OPENSSL
#include <event2/bufferevent_ssl.h>
#endif
@@ -53,12 +55,9 @@ Connection::~Connection() {
}
std::string Connection::ToString() {
- std::ostringstream stream;
- stream << "id=" << id_ << " addr=" << addr_ << " fd=" <<
bufferevent_getfd(bev_) << " name=" << name_
- << " age=" << GetAge() << " idle=" << GetIdleTime() << " flags=" <<
GetFlags() << " namespace=" << ns_
- << " qbuf=" << evbuffer_get_length(Input()) << " obuf=" <<
evbuffer_get_length(Output())
- << " cmd=" << last_cmd_ << "\n";
- return stream.str();
+ return fmt::format("id={} addr={} fd={} name={} age={} idle={} flags={}
namespace={} qbuf={} obuf={} cmd={}\n", id_,
+ addr_, bufferevent_getfd(bev_), name_, GetAge(),
GetIdleTime(), GetFlags(), ns_,
+ evbuffer_get_length(Input()),
evbuffer_get_length(Output()), last_cmd_);
}
void Connection::Close() {
diff --git a/src/server/server.cc b/src/server/server.cc
index 89762260..3944530e 100644
--- a/src/server/server.cc
+++ b/src/server/server.cc
@@ -31,6 +31,7 @@
#include <utility>
#include "config.h"
+#include "fmt/format.h"
#include "redis_connection.h"
#include "redis_request.h"
#include "storage/compaction_checker.h"
@@ -1056,23 +1057,21 @@ void Server::GetInfo(const std::string &ns, const
std::string §ion, std::str
}
std::string Server::GetRocksDBStatsJson() {
- char buf[256];
std::string output;
output.reserve(8 * 1024);
output.append("{");
auto stats = storage_->GetDB()->GetDBOptions().statistics;
for (const auto &iter : rocksdb::TickersNameMap) {
- snprintf(buf, sizeof(buf), "\"%s\":%" PRIu64 ",", iter.second.c_str(),
stats->getTickerCount(iter.first));
- output.append(buf);
+ output.append(fmt::format(R"("{}":{},)", iter.second.c_str(),
stats->getTickerCount(iter.first)));
}
for (const auto &iter : rocksdb::HistogramsNameMap) {
rocksdb::HistogramData hist_data;
stats->histogramData(iter.first, &hist_data);
/* P50 P95 P99 P100 COUNT SUM */
- snprintf(buf, sizeof(buf), "\"%s\":[%f,%f,%f,%f,%" PRIu64 ",%" PRIu64
"],", iter.second.c_str(), hist_data.median,
- hist_data.percentile95, hist_data.percentile99, hist_data.max,
hist_data.count, hist_data.sum);
- output.append(buf);
+ output.append(fmt::format(R"("{}":[{},{},{},{},{},{}])",
iter.second.c_str(), hist_data.median,
+ hist_data.percentile95, hist_data.percentile99,
hist_data.max, hist_data.count,
+ hist_data.sum));
}
output.pop_back();
output.append("}");
@@ -1295,14 +1294,14 @@ void Server::SlowlogPushEntryIfNeeded(const
std::vector<std::string> *args, uint
size_t argc = args->size() > kSlowLogMaxArgc ? kSlowLogMaxArgc :
args->size();
for (size_t i = 0; i < argc; i++) {
if (argc != args->size() && i == argc - 1) {
- entry->args.emplace_back("... (" + std::to_string(args->size() - argc +
1) + " more arguments)");
+ entry->args.emplace_back(fmt::format("... ({} more arguments)",
args->size() - argc + 1));
break;
}
if (args->data()[i].length() <= kSlowLogMaxString) {
entry->args.emplace_back(args->data()[i]);
} else {
- entry->args.emplace_back(args->data()[i].substr(0, kSlowLogMaxString) +
"... (" +
- std::to_string(args->data()[i].length() -
kSlowLogMaxString) + " more bytes)");
+ entry->args.emplace_back(fmt::format("{}... ({} more bytes)",
args->data()[i].substr(0, kSlowLogMaxString),
+ args->data()[i].length() -
kSlowLogMaxString));
}
}
entry->duration = duration;
diff --git a/src/server/worker.cc b/src/server/worker.cc
index f19ec2ae..50caf3ad 100644
--- a/src/server/worker.cc
+++ b/src/server/worker.cc
@@ -23,6 +23,8 @@
#include <event2/util.h>
#include <glog/logging.h>
+#include <string>
+
#ifdef ENABLE_OPENSSL
#include <event2/bufferevent_ssl.h>
#include <openssl/err.h>
@@ -196,7 +198,6 @@ void Worker::newUnixSocketConnection(evconnlistener
*listener, evutil_socket_t f
}
Status Worker::listenTCP(const std::string &host, int port, int backlog) {
- char _port[6];
int af, rv, fd, sock_opt = 1;
if (strchr(host.data(), ':')) {
@@ -204,14 +205,13 @@ Status Worker::listenTCP(const std::string &host, int
port, int backlog) {
} else {
af = AF_INET;
}
- snprintf(_port, sizeof(_port), "%d", port);
struct addrinfo hints, *srv_info, *p;
memset(&hints, 0, sizeof(hints));
hints.ai_family = af;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
- if ((rv = getaddrinfo(host.data(), _port, &hints, &srv_info)) != 0) {
+ if ((rv = getaddrinfo(host.data(), std::to_string(port).c_str(), &hints,
&srv_info)) != 0) {
return Status(Status::NotOK, gai_strerror(rv));
}
diff --git a/src/stats/stats.cc b/src/stats/stats.cc
index 66704677..b3736c43 100644
--- a/src/stats/stats.cc
+++ b/src/stats/stats.cc
@@ -22,6 +22,7 @@
#include <chrono>
+#include "fmt/format.h"
#include "util.h"
Stats::Stats() {
@@ -59,9 +60,8 @@ int64_t Stats::GetMemoryRSS() {
#include "fd_util.h"
int64_t Stats::GetMemoryRSS() {
- char buf[4096], filename[256];
- snprintf(filename, sizeof(filename), "/proc/%d/stat", getpid());
- auto fd = UniqueFD(open(filename, O_RDONLY));
+ char buf[4096];
+ auto fd = UniqueFD(open(fmt::format("/proc/{}/stat", getpid()).c_str(),
O_RDONLY));
if (!fd) return 0;
if (read(*fd, buf, sizeof(buf)) <= 0) {
return 0;
diff --git a/src/storage/scripting.cc b/src/storage/scripting.cc
index 258aa043..fe05e259 100644
--- a/src/storage/scripting.cc
+++ b/src/storage/scripting.cc
@@ -57,6 +57,7 @@
#include <string>
#include "commands/redis_cmd.h"
+#include "fmt/format.h"
#include "rand.h"
#include "server/redis_connection.h"
#include "server/server.h"
@@ -350,15 +351,12 @@ int redisGenericCommand(lua_State *lua, int raise_error) {
return raise_error ? raiseError(lua) : 1;
}
for (j = 0; j < argc; j++) {
- char dbuf[64];
if (lua_type(lua, j + 1) == LUA_TNUMBER) {
lua_Number num = lua_tonumber(lua, j + 1);
- snprintf(dbuf, sizeof(dbuf), "%.17g", static_cast<double>(num));
- args.emplace_back(dbuf);
+ args.emplace_back(fmt::format("{:.17g}", static_cast<double>(num)));
} else {
- const char *obj_s;
- size_t obj_len;
- obj_s = lua_tolstring(lua, j + 1, &obj_len);
+ size_t obj_len = 0;
+ const char *obj_s = lua_tolstring(lua, j + 1, &obj_len);
if (obj_s == nullptr) break; /* no a string */
args.emplace_back(obj_s, obj_len);
}
diff --git a/src/types/redis_stream_base.h b/src/types/redis_stream_base.h
index bc0207e3..725d201a 100644
--- a/src/types/redis_stream_base.h
+++ b/src/types/redis_stream_base.h
@@ -27,6 +27,7 @@
#include <utility>
#include <vector>
+#include "fmt/format.h"
#include "status.h"
namespace Redis {
@@ -66,7 +67,7 @@ struct StreamEntryID {
bool operator==(const StreamEntryID &rhs) const { return ms == rhs.ms && seq
== rhs.seq; }
- std::string ToString() const { return std::to_string(ms) + "-" +
std::to_string(seq); }
+ std::string ToString() const { return fmt::format("{}-{}", ms, seq); }
static StreamEntryID Minimum() { return StreamEntryID{0, 0}; }
static StreamEntryID Maximum() { return StreamEntryID{UINT64_MAX,
UINT64_MAX}; }