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 &section, 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}; }

Reply via email to