Merge branch 'master' of https://github.com/apple/foundationdb into fix-revert-4929

This commit is contained in:
Xiaoxi Wang 2021-06-14 23:51:31 +00:00
commit e5ae0ce36b
22 changed files with 84 additions and 73 deletions

View File

@ -51,9 +51,10 @@ namespace SummarizeTest
bool traceToStdout = false;
try
{
string joshuaSeed = System.Environment.GetEnvironmentVariable("JOSHUA_SEED");
byte[] seed = new byte[4];
new System.Security.Cryptography.RNGCryptoServiceProvider().GetBytes(seed);
random = new Random(new BinaryReader(new MemoryStream(seed)).ReadInt32());
random = new Random(joshuaSeed != null ? Convert.ToInt32(Int64.Parse(joshuaSeed) % 2147483648) : new BinaryReader(new MemoryStream(seed)).ReadInt32());
if (args.Length < 1)
return UsageMessage();

View File

@ -541,13 +541,17 @@ Applications must provide error handling and an appropriate retry loop around th
|snapshot|
.. function:: FDBFuture* fdb_transaction_get_estimated_range_size_bytes( FDBTransaction* tr, uint8_t const* begin_key_name, int begin_key_name_length, uint8_t const* end_key_name, int end_key_name_length)
Returns an estimated byte size of the key range.
.. note:: The estimated size is calculated based on the sampling done by FDB server. The sampling algorithm works roughly in this way: the larger the key-value pair is, the more likely it would be sampled and the more accurate its sampled size would be. And due to that reason it is recommended to use this API to query against large ranges for accuracy considerations. For a rough reference, if the returned size is larger than 3MB, one can consider the size to be accurate.
|future-return0| the estimated size of the key range given. |future-return1| call :func:`fdb_future_get_int64()` to extract the size, |future-return2|
.. function:: FDBFuture* fdb_transaction_get_range_split_points( FDBTransaction* tr, uint8_t const* begin_key_name, int begin_key_name_length, uint8_t const* end_key_name, int end_key_name_length, int64_t chunk_size)
Returns a list of keys that can split the given range into (roughly) equally sized chunks based on ``chunk_size``.
.. note:: The returned split points contain the start key and end key of the given range
|future-return0| the list of split points. |future-return1| call :func:`fdb_future_get_key_array()` to extract the array, |future-return2|

View File

@ -800,6 +800,7 @@ Transaction misc functions
.. method:: Transaction.get_estimated_range_size_bytes(begin_key, end_key)
Gets the estimated byte size of the given key range. Returns a :class:`FutureInt64`.
.. note:: The estimated size is calculated based on the sampling done by FDB server. The sampling algorithm works roughly in this way: the larger the key-value pair is, the more likely it would be sampled and the more accurate its sampled size would be. And due to that reason it is recommended to use this API to query against large ranges for accuracy considerations. For a rough reference, if the returned size is larger than 3MB, one can consider the size to be accurate.
.. method:: Transaction.get_range_split_points(self, begin_key, end_key, chunk_size)
@ -807,15 +808,11 @@ Transaction misc functions
Gets a list of keys that can split the given range into (roughly) equally sized chunks based on ``chunk_size``. Returns a :class:`FutureKeyArray`.
.. note:: The returned split points contain the start key and end key of the given range
.. _api-python-transaction-options:
Transaction misc functions
--------------------------
.. method:: Transaction.get_approximate_size()
|transaction-get-approximate-size-blurb|. Returns a :class:`FutureInt64`.
|transaction-get-approximate-size-blurb| Returns a :class:`FutureInt64`.
.. _api-python-transaction-options:
Transaction options
-------------------

View File

@ -744,6 +744,7 @@ Transaction misc functions
.. method:: Transaction.get_estimated_range_size_bytes(begin_key, end_key) -> Int64Future
Gets the estimated byte size of the given key range. Returns a :class:`Int64Future`.
.. note:: The estimated size is calculated based on the sampling done by FDB server. The sampling algorithm works roughly in this way: the larger the key-value pair is, the more likely it would be sampled and the more accurate its sampled size would be. And due to that reason it is recommended to use this API to query against large ranges for accuracy considerations. For a rough reference, if the returned size is larger than 3MB, one can consider the size to be accurate.
.. method:: Transaction.get_range_split_points(begin_key, end_key, chunk_size) -> FutureKeyArray
@ -753,7 +754,7 @@ Transaction misc functions
.. method:: Transaction.get_approximate_size() -> Int64Future
|transaction-get-approximate-size-blurb|. Returns a :class:`Int64Future`.
|transaction-get-approximate-size-blurb| Returns a :class:`Int64Future`.
Transaction options
-------------------

View File

@ -10,12 +10,14 @@ Release Notes
Features
--------
* Added a new API in all bindings that can be used to get a list of split points that will split the given range into (roughly) equally sized chunks. `(PR #3394) <https://github.com/apple/foundationdb/pull/3394>`_
* Added support for writing backup files directly to Azure blob storage. This is not yet performance tested on large-scale clusters. `(PR #3961) <https://github.com/apple/foundationdb/pull/3961>`_
Performance
-----------
* Improved Deque copy performance. `(PR #3197) <https://github.com/apple/foundationdb/pull/3197>`_
* Increased performance of dr_agent when copying the mutation log. The ``COPY_LOG_BLOCK_SIZE``, ``COPY_LOG_BLOCKS_PER_TASK``, ``COPY_LOG_PREFETCH_BLOCKS``, ``COPY_LOG_READ_AHEAD_BYTES`` and ``COPY_LOG_TASK_DURATION_NANOS`` knobs can be set. `(PR #3436) <https://github.com/apple/foundationdb/pull/3436>`_
* Added multiple new microbenchmarks for PromiseStream, Reference, IRandom, and timer, as well as support for benchmarking actors. `(PR #3590) <https://github.com/apple/foundationdb/pull/3590>`_
* Use xxhash3 for SQLite page checksums. `(PR #4075) <https://github.com/apple/foundationdb/pull/4075>`_
* Reduced the number of connections required by the multi-version client when loading external clients. When connecting to 7.0 clusters, only one connection with version 6.2 or larger will be used. With older clusters, at most two connections with version 6.2 or larger will be used. Clients older than version 6.2 will continue to create an additional connection each. `(PR #4667) <https://github.com/apple/foundationdb/pull/4667>`_
* Reduce CPU overhead of load balancing on client processes. `(PR #4561) <https://github.com/apple/foundationdb/pull/4561>`_
@ -31,6 +33,7 @@ Fixes
Status
------
* Added limiting metrics (limiting_storage_durability_lag and limiting_storage_queue) to health metrics. `(PR #4067) <https://github.com/apple/foundationdb/pull/4067>`_
* Added ``commit_batching_window_size`` to the proxy roles section of status to record statistics about commit batching window size on each proxy. `(PR #4735) <https://github.com/apple/foundationdb/pull/4735>`_
* Added ``cluster.bounce_impact`` section to status to report if there will be any extra effects when bouncing the cluster, and if so, the reason for those effects. `(PR #4770) <https://github.com/apple/foundationdb/pull/4770>`_
* Added ``fetched_versions`` to the storage metrics section of status to report how fast a storage server is catching up in versions. `(PR #4770) <https://github.com/apple/foundationdb/pull/4770>`_
@ -41,15 +44,17 @@ Bindings
--------
* Python: The function ``get_estimated_range_size_bytes`` will now throw an error if the ``begin_key`` or ``end_key`` is ``None``. `(PR #3394) <https://github.com/apple/foundationdb/pull/3394>`_
* C: Added a function, ``fdb_database_reboot_worker``, to reboot or suspend the specified process. `(PR #4094) <https://github.com/apple/foundationdb/pull/4094>`_
* C: Added a function, ``fdb_database_force_recovery_with_data_loss``, to force the database to recover into the given datacenter. `(PR #4420) <https://github.com/apple/foundationdb/pull/4220>`_
* C: Added a function, ``fdb_database_create_snapshot``, to create a snapshot of the database. `(PR #4241) <https://github.com/apple/foundationdb/pull/4241>`_
* C: Added a function, ``fdb_database_force_recovery_with_data_loss``, to force the database to recover into the given datacenter. `(PR #4220) <https://github.com/apple/foundationdb/pull/4220>`_
* C: Added a function, ``fdb_database_create_snapshot``, to create a snapshot of the database. `(PR #4241) <https://github.com/apple/foundationdb/pull/4241/files>`_
* C: Added ``fdb_database_get_main_thread_busyness`` function to report how busy a client's main thread is. `(PR #4504) <https://github.com/apple/foundationdb/pull/4504>`_
* Java: Added ``Database.getMainThreadBusyness`` function to report how busy a client's main thread is. `(PR #4564) <https://github.com/apple/foundationdb/pull/4564>`_
* Java: Added ``Database.getMainThreadBusyness`` function to report how busy a client's main thread is. `(PR #4564) <https://github.com/apple/foundationdb/pull/4564>`_
Other Changes
-------------
* When ``fdbmonitor`` dies, all of its child processes are now killed. `(PR #3841) <https://github.com/apple/foundationdb/pull/3841>`_
* The ``foundationdb`` service installed by the RPM packages will now automatically restart ``fdbmonitor`` after 60 seconds when it fails. `(PR #3841) <https://github.com/apple/foundationdb/pull/3841>`_
* Capture output of forked snapshot processes in trace events. `(PR #4254) <https://github.com/apple/foundationdb/pull/4254/files>`_
* Add ErrorKind field to Severity 40 trace events. `(PR #4741) <https://github.com/apple/foundationdb/pull/4741/files>`_
Earlier release notes
---------------------

View File

@ -548,11 +548,11 @@ bool DatabaseConfiguration::setInternal(KeyRef key, ValueRef value) {
return true; // All of the above options currently require recovery to take effect
}
inline static KeyValueRef* lower_bound(VectorRef<KeyValueRef>& config, KeyRef const& key) {
static KeyValueRef* lower_bound(VectorRef<KeyValueRef>& config, KeyRef const& key) {
return std::lower_bound(config.begin(), config.end(), KeyValueRef(key, ValueRef()), KeyValueRef::OrderByKey());
}
inline static KeyValueRef const* lower_bound(VectorRef<KeyValueRef> const& config, KeyRef const& key) {
return lower_bound(const_cast<VectorRef<KeyValueRef>&>(config), key);
static KeyValueRef const* lower_bound(VectorRef<KeyValueRef> const& config, KeyRef const& key) {
return std::lower_bound(config.begin(), config.end(), KeyValueRef(key, ValueRef()), KeyValueRef::OrderByKey());
}
void DatabaseConfiguration::applyMutation(MutationRef m) {
@ -664,7 +664,7 @@ void DatabaseConfiguration::fromKeyValues(Standalone<VectorRef<KeyValueRef>> raw
}
bool DatabaseConfiguration::isOverridden(std::string key) const {
key = configKeysPrefix.toString() + key;
key = configKeysPrefix.toString() + std::move(key);
if (mutableConfiguration.present()) {
return mutableConfiguration.get().find(key) != mutableConfiguration.get().end();

View File

@ -168,6 +168,7 @@ struct HealthMetricsApiWorkload : TestWorkload {
traceDiskUsage.detail(format("Storage-%s", ss.first.toString().c_str()), storageStats.diskUsage);
}
TraceEvent traceTLogQueue("TLogQueue");
traceTLogQueue.setMaxEventLength(10000);
for (const auto& ss : healthMetrics.tLogQueue) {
self->detailedWorstTLogQueue = std::max(self->detailedWorstTLogQueue, ss.second);
traceTLogQueue.detail(format("TLog-%s", ss.first.toString().c_str()), ss.second);

View File

@ -49,7 +49,7 @@
struct IssuesListImpl {
IssuesListImpl() {}
void addIssue(std::string issue) {
void addIssue(std::string const& issue) {
MutexHolder h(mutex);
issues.insert(issue);
}
@ -61,7 +61,7 @@ struct IssuesListImpl {
}
}
void resolveIssue(std::string issue) {
void resolveIssue(std::string const& issue) {
MutexHolder h(mutex);
issues.erase(issue);
}
@ -73,23 +73,23 @@ private:
IssuesList::IssuesList() : impl(std::make_unique<IssuesListImpl>()) {}
IssuesList::~IssuesList() = default;
void IssuesList::addIssue(std::string issue) {
void IssuesList::addIssue(std::string const& issue) {
impl->addIssue(issue);
}
void IssuesList::retrieveIssues(std::set<std::string>& out) const {
impl->retrieveIssues(out);
}
void IssuesList::resolveIssue(std::string issue) {
void IssuesList::resolveIssue(std::string const& issue) {
impl->resolveIssue(issue);
}
FileTraceLogWriter::FileTraceLogWriter(std::string directory,
std::string processName,
std::string basename,
std::string extension,
FileTraceLogWriter::FileTraceLogWriter(std::string const& directory,
std::string const& processName,
std::string const& basename,
std::string const& extension,
uint64_t maxLogsSize,
std::function<void()> onError,
Reference<ITraceLogIssuesReporter> issues)
std::function<void()> const& onError,
Reference<ITraceLogIssuesReporter> const& issues)
: directory(directory), processName(processName), basename(basename), extension(extension), maxLogsSize(maxLogsSize),
traceFileFD(-1), index(0), onError(onError), issues(issues) {}

View File

@ -32,11 +32,11 @@ struct IssuesListImpl;
struct IssuesList final : ITraceLogIssuesReporter, ThreadSafeReferenceCounted<IssuesList> {
IssuesList();
~IssuesList() override;
void addIssue(std::string issue) override;
void addIssue(std::string const& issue) override;
void retrieveIssues(std::set<std::string>& out) const override;
void resolveIssue(std::string issue) override;
void resolveIssue(std::string const& issue) override;
void addref() override { ThreadSafeReferenceCounted<IssuesList>::addref(); }
void delref() override { ThreadSafeReferenceCounted<IssuesList>::delref(); }
@ -62,13 +62,13 @@ private:
void write(const char* str, size_t size);
public:
FileTraceLogWriter(std::string directory,
std::string processName,
std::string basename,
std::string extension,
FileTraceLogWriter(std::string const& directory,
std::string const& processName,
std::string const& basename,
std::string const& extension,
uint64_t maxLogsSize,
std::function<void()> onError,
Reference<ITraceLogIssuesReporter> issues);
std::function<void()> const& onError,
Reference<ITraceLogIssuesReporter> const& issues);
void addref() override;
void delref() override;

View File

@ -77,7 +77,7 @@ void HistogramRegistry::unregisterHistogram(Histogram* h) {
ASSERT(count == 1);
}
Histogram* HistogramRegistry::lookupHistogram(std::string name) {
Histogram* HistogramRegistry::lookupHistogram(std::string const& name) {
auto h = histograms.find(name);
if (h == histograms.end()) {
return nullptr;

View File

@ -39,7 +39,7 @@ class HistogramRegistry {
public:
void registerHistogram(Histogram* h);
void unregisterHistogram(Histogram* h);
Histogram* lookupHistogram(std::string name);
Histogram* lookupHistogram(std::string const& name);
void logReport();
private:
@ -63,7 +63,7 @@ public:
private:
static const std::unordered_map<Unit, std::string> UnitToStringMapper;
Histogram(std::string group, std::string op, Unit unit, HistogramRegistry& registry)
Histogram(std::string const& group, std::string const& op, Unit unit, HistogramRegistry& registry)
: group(group), op(op), unit(unit), registry(registry), ReferenceCounted<Histogram>() {
ASSERT(UnitToStringMapper.find(unit) != UnitToStringMapper.end());
@ -71,7 +71,7 @@ private:
clear();
}
static std::string generateName(std::string group, std::string op) { return group + ":" + op; }
static std::string generateName(std::string const& group, std::string const& op) { return group + ":" + op; }
public:
~Histogram() { registry.unregisterHistogram(this); }
@ -125,7 +125,7 @@ public:
}
void writeToLog();
std::string name() { return generateName(this->group, this->op); }
std::string name() const { return generateName(this->group, this->op); }
std::string const group;
std::string const op;

View File

@ -51,8 +51,8 @@ struct ITraceLogFormatter {
struct ITraceLogIssuesReporter {
virtual ~ITraceLogIssuesReporter();
virtual void addIssue(std::string issue) = 0;
virtual void resolveIssue(std::string issue) = 0;
virtual void addIssue(std::string const& issue) = 0;
virtual void resolveIssue(std::string const& issue) = 0;
virtual void retrieveIssues(std::set<std::string>& out) const = 0;

View File

@ -1482,7 +1482,7 @@ void initPdhStrings(SystemStatisticsState* state, std::string dataFolder) {
}
#endif
SystemStatistics getSystemStatistics(std::string dataFolder,
SystemStatistics getSystemStatistics(std::string const& dataFolder,
const IPAddress* ip,
SystemStatisticsState** statState,
bool logDetails) {
@ -2640,7 +2640,7 @@ Future<vector<std::string>> listDirectoriesAsync(std::string const& directory) {
return findFiles(directory, "", true /* directoryOnly */, true);
}
void findFilesRecursively(std::string path, std::vector<std::string>& out) {
void findFilesRecursively(std::string const& path, std::vector<std::string>& out) {
// Add files to output, prefixing path
std::vector<std::string> files = platform::listFiles(path);
for (auto const& f : files)

View File

@ -232,7 +232,7 @@ struct SystemStatisticsState;
struct IPAddress;
SystemStatistics getSystemStatistics(std::string dataFolder,
SystemStatistics getSystemStatistics(std::string const& dataFolder,
const IPAddress* ip,
SystemStatisticsState** statState,
bool logDetails);
@ -369,7 +369,7 @@ std::vector<std::string> listFiles(std::string const& directory, std::string con
// returns directory names relative to directory
std::vector<std::string> listDirectories(std::string const& directory);
void findFilesRecursively(std::string path, std::vector<std::string>& out);
void findFilesRecursively(std::string const& path, std::vector<std::string>& out);
// Tag the given file as "temporary", i.e. not really needing commits to disk
void makeTemporary(const char* filename);

View File

@ -61,7 +61,7 @@ SystemStatistics getSystemStatistics() {
.detail("ApproximateUnusedMemory" #size, FastAllocator<size>::getApproximateMemoryUnused()) \
.detail("ActiveThreads" #size, FastAllocator<size>::getActiveThreads())
SystemStatistics customSystemMonitor(std::string eventName, StatisticsState* statState, bool machineMetrics) {
SystemStatistics customSystemMonitor(std::string const& eventName, StatisticsState* statState, bool machineMetrics) {
const IPAddress ipAddr = machineState.ip.present() ? machineState.ip.get() : IPAddress();
SystemStatistics currentStats = getSystemStatistics(
machineState.folder.present() ? machineState.folder.get() : "", &ipAddr, &statState->systemState, true);

View File

@ -36,11 +36,11 @@ struct SystemMonitorMachineState {
SystemMonitorMachineState() : monitorStartTime(0) {}
explicit SystemMonitorMachineState(const IPAddress& ip) : ip(ip), monitorStartTime(0) {}
SystemMonitorMachineState(std::string folder,
Optional<Standalone<StringRef>> dcId,
Optional<Standalone<StringRef>> zoneId,
Optional<Standalone<StringRef>> machineId,
const IPAddress& ip)
SystemMonitorMachineState(std::string const& folder,
Optional<Standalone<StringRef>> const& dcId,
Optional<Standalone<StringRef>> const& zoneId,
Optional<Standalone<StringRef>> const& machineId,
IPAddress const& ip)
: folder(folder), dcId(dcId), zoneId(zoneId), machineId(machineId), ip(ip), monitorStartTime(0) {}
};
@ -148,7 +148,9 @@ struct StatisticsState {
};
void systemMonitor();
SystemStatistics customSystemMonitor(std::string eventName, StatisticsState* statState, bool machineMetrics = false);
SystemStatistics customSystemMonitor(std::string const& eventName,
StatisticsState* statState,
bool machineMetrics = false);
SystemStatistics getSystemStatistics();
#endif /* FLOW_SYSTEM_MONITOR_H */

View File

@ -503,7 +503,7 @@ public:
}
}
void addRole(std::string role) {
void addRole(std::string const& role) {
MutexHolder holder(mutex);
RoleInfo& r = mutateRoleInfo();
@ -511,7 +511,7 @@ public:
r.refreshRolesString();
}
void removeRole(std::string role) {
void removeRole(std::string const& role) {
MutexHolder holder(mutex);
RoleInfo& r = mutateRoleInfo();
@ -557,13 +557,13 @@ NetworkAddress getAddressIndex() {
}
// This does not check for simulation, and as such is not safe for external callers
void clearPrefix_internal(std::map<std::string, TraceEventFields>& data, std::string prefix) {
void clearPrefix_internal(std::map<std::string, TraceEventFields>& data, std::string const& prefix) {
auto first = data.lower_bound(prefix);
auto last = data.lower_bound(strinc(prefix).toString());
data.erase(first, last);
}
void LatestEventCache::clear(std::string prefix) {
void LatestEventCache::clear(std::string const& prefix) {
clearPrefix_internal(latest[getAddressIndex()], prefix);
}
@ -575,7 +575,7 @@ void LatestEventCache::set(std::string tag, const TraceEventFields& contents) {
latest[getAddressIndex()][tag] = contents;
}
TraceEventFields LatestEventCache::get(std::string tag) {
TraceEventFields LatestEventCache::get(std::string const& tag) {
return latest[getAddressIndex()][tag];
}
@ -757,11 +757,11 @@ bool traceFileIsOpen() {
return g_traceLog.isOpen();
}
void addTraceRole(std::string role) {
void addTraceRole(std::string const& role) {
g_traceLog.addRole(role);
}
void removeTraceRole(std::string role) {
void removeTraceRole(std::string const& role) {
g_traceLog.removeRole(role);
}

View File

@ -519,11 +519,11 @@ struct TraceInterval {
struct LatestEventCache {
public:
void set(std::string tag, const TraceEventFields& fields);
TraceEventFields get(std::string tag);
TraceEventFields get(std::string const& tag);
std::vector<TraceEventFields> getAll();
std::vector<TraceEventFields> getAllUnsafe();
void clear(std::string prefix);
void clear(std::string const& prefix);
void clear();
// Latest error tracking only tracks errors when called from the main thread. Other errors are silently ignored.
@ -577,8 +577,8 @@ bool selectTraceClockSource(std::string source);
// Returns true iff source is recognized.
bool validateTraceClockSource(std::string source);
void addTraceRole(std::string role);
void removeTraceRole(std::string role);
void addTraceRole(std::string const& role);
void removeTraceRole(std::string const& role);
void retrieveTraceLogIssues(std::set<std::string>& out);
void setTraceLogGroup(const std::string& role);
template <class T>

View File

@ -93,7 +93,7 @@ std::string UID::shortString() const {
void detectFailureAfter(int const& address, double const& delay);
Optional<uint64_t> parse_with_suffix(std::string toparse, std::string default_unit) {
Optional<uint64_t> parse_with_suffix(std::string const& toparse, std::string const& default_unit) {
char* endptr;
uint64_t ret = strtoull(toparse.c_str(), &endptr, 10);
@ -144,7 +144,7 @@ Optional<uint64_t> parse_with_suffix(std::string toparse, std::string default_un
// m - minutes
// h - hours
// d - days
Optional<uint64_t> parseDuration(std::string str, std::string defaultUnit) {
Optional<uint64_t> parseDuration(std::string const& str, std::string const& defaultUnit) {
char* endptr;
uint64_t ret = strtoull(str.c_str(), &endptr, 10);
@ -284,7 +284,7 @@ std::vector<double> P_BUGGIFIED_SECTION_FIRES{ .25, .25 };
double P_EXPENSIVE_VALIDATION = .05;
int getSBVar(std::string file, int line, BuggifyType type) {
int getSBVar(std::string const& file, int line, BuggifyType type) {
if (!buggifyActivated[int(type)])
return 0;

View File

@ -72,7 +72,7 @@ extern double P_EXPENSIVE_VALIDATION;
enum class BuggifyType : uint8_t { General = 0, Client };
bool isBuggifyEnabled(BuggifyType type);
void clearBuggifySections(BuggifyType type);
int getSBVar(std::string file, int line, BuggifyType);
int getSBVar(std::string const& file, int line, BuggifyType);
void enableBuggify(bool enabled,
BuggifyType type); // Currently controls buggification and (randomized) expensive validation
bool validationIsEnabled(BuggifyType type);
@ -83,8 +83,8 @@ bool validationIsEnabled(BuggifyType type);
#define EXPENSIVE_VALIDATION \
(validationIsEnabled(BuggifyType::General) && deterministicRandom()->random01() < P_EXPENSIVE_VALIDATION)
extern Optional<uint64_t> parse_with_suffix(std::string toparse, std::string default_unit = "");
extern Optional<uint64_t> parseDuration(std::string str, std::string defaultUnit = "");
extern Optional<uint64_t> parse_with_suffix(std::string const& toparse, std::string const& default_unit = "");
extern Optional<uint64_t> parseDuration(std::string const& str, std::string const& defaultUnit = "");
extern std::string format(const char* form, ...);
// On success, returns the number of characters written. On failure, returns a negative number.

View File

@ -46,7 +46,7 @@ std::string IPAddress::toString() const {
}
}
Optional<IPAddress> IPAddress::parse(std::string str) {
Optional<IPAddress> IPAddress::parse(std::string const& str) {
try {
auto addr = boost::asio::ip::address::from_string(str);
return addr.is_v6() ? IPAddress(addr.to_v6().to_bytes()) : IPAddress(addr.to_v4().to_ulong());

View File

@ -150,7 +150,7 @@ public:
const IPAddressStore& toV6() const { return std::get<IPAddressStore>(addr); }
std::string toString() const;
static Optional<IPAddress> parse(std::string str);
static Optional<IPAddress> parse(std::string const& str);
bool operator==(const IPAddress& addr) const;
bool operator!=(const IPAddress& addr) const;