Merge branch 'release-6.0'
This commit is contained in:
commit
920fd3fe97
|
@ -18,7 +18,7 @@ setup(name="foundationdb",
|
|||
classifiers=[
|
||||
'Development Status :: 5 - Production/Stable',
|
||||
'Intended Audience :: Developers',
|
||||
'License :: OSI Approved :: Apache v2 License',
|
||||
'License :: OSI Approved :: Apache Software License',
|
||||
'Operating System :: MacOS :: MacOS X',
|
||||
'Operating System :: Microsoft :: Windows',
|
||||
'Operating System :: POSIX :: Linux',
|
||||
|
|
|
@ -1251,6 +1251,7 @@ ACTOR Future<Version> timeKeeperVersionFromDatetime(std::string datetime, Databa
|
|||
loop {
|
||||
try {
|
||||
tr->setOption(FDBTransactionOptions::ACCESS_SYSTEM_KEYS);
|
||||
tr->setOption(FDBTransactionOptions::LOCK_AWARE);
|
||||
state std::vector<std::pair<int64_t, Version>> results = wait( versionMap.getRange(tr, 0, time, 1, false, true) );
|
||||
if (results.size() != 1) {
|
||||
// No key less than time was found in the database
|
||||
|
|
|
@ -310,7 +310,7 @@ static JsonString machineStatusFetcher(WorkerEvents mMetrics, vector<std::pair<W
|
|||
std::string machineId = event.getValue("MachineID");
|
||||
|
||||
// If this machine ID does not already exist in the machineMap, add it
|
||||
if (!machineMap.isPresent(machineId)) {
|
||||
if (machineJsonMap.count(machineId) == 0) {
|
||||
statusObj["machine_id"] = machineId;
|
||||
|
||||
if (dcIds.count(it->first)){
|
||||
|
@ -587,14 +587,12 @@ ACTOR static Future<JsonString> processStatusFetcher(
|
|||
|
||||
state std::vector<std::pair<TLogInterface, TraceEventFields>>::iterator log;
|
||||
state Version maxTLogVersion = 0;
|
||||
state Version tLogVersion = 0;
|
||||
|
||||
// Get largest TLog version
|
||||
for(log = tLogs.begin(); log != tLogs.end(); ++log) {
|
||||
Version tLogVersion = 0;
|
||||
JsonString const& roleStatus = roles.addRole( "log", log->first, log->second, &tLogVersion );
|
||||
if (roleStatus.isPresent("data_version")) {
|
||||
maxTLogVersion = std::max(maxTLogVersion, tLogVersion);
|
||||
}
|
||||
maxTLogVersion = std::max(maxTLogVersion, tLogVersion);
|
||||
wait(yield());
|
||||
}
|
||||
|
||||
|
@ -880,8 +878,9 @@ ACTOR static Future<JsonString> recoveryStateStatusFetcher(std::pair<WorkerInter
|
|||
}
|
||||
|
||||
// If recovery status name is not know, status is incomplete
|
||||
if (!message.isPresent("name"))
|
||||
if (message.empty()) {
|
||||
incomplete_reasons->insert("Recovery Status unavailable.");
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
@ -951,10 +950,13 @@ ACTOR static Future<double> doCommitProbe(Future<double> grvProbe, Transaction *
|
|||
}
|
||||
}
|
||||
|
||||
ACTOR static Future<Void> doProbe(Future<double> probe, int timeoutSeconds, const char* prefix, const char* description, JsonString *probeObj, JsonStringArray *messages, std::set<std::string> *incomplete_reasons) {
|
||||
ACTOR static Future<Void> doProbe(Future<double> probe, int timeoutSeconds, const char* prefix, const char* description, JsonString *probeObj, JsonStringArray *messages, std::set<std::string> *incomplete_reasons, bool *isAvailable = nullptr) {
|
||||
choose {
|
||||
when(ErrorOr<double> result = wait(errorOr(probe))) {
|
||||
if(result.isError()) {
|
||||
if(isAvailable != nullptr) {
|
||||
*isAvailable = false;
|
||||
}
|
||||
incomplete_reasons->insert(format("Unable to retrieve latency probe information (%s: %s).", description, result.getError().what()));
|
||||
}
|
||||
else {
|
||||
|
@ -962,6 +964,9 @@ ACTOR static Future<Void> doProbe(Future<double> probe, int timeoutSeconds, cons
|
|||
}
|
||||
}
|
||||
when(wait(delay(timeoutSeconds))) {
|
||||
if(isAvailable != nullptr) {
|
||||
*isAvailable = false;
|
||||
}
|
||||
messages->push_back(JsonString::makeMessage(format("%s_probe_timeout", prefix).c_str(), format("Unable to %s after %d seconds.", description, timeoutSeconds).c_str()));
|
||||
}
|
||||
}
|
||||
|
@ -969,7 +974,7 @@ ACTOR static Future<Void> doProbe(Future<double> probe, int timeoutSeconds, cons
|
|||
return Void();
|
||||
}
|
||||
|
||||
ACTOR static Future<JsonString> latencyProbeFetcher(Database cx, JsonStringArray *messages, std::set<std::string> *incomplete_reasons) {
|
||||
ACTOR static Future<JsonString> latencyProbeFetcher(Database cx, JsonStringArray *messages, std::set<std::string> *incomplete_reasons, bool *isAvailable) {
|
||||
state Transaction trImmediate(cx);
|
||||
state Transaction trDefault(cx);
|
||||
state Transaction trBatch(cx);
|
||||
|
@ -988,11 +993,11 @@ ACTOR static Future<JsonString> latencyProbeFetcher(Database cx, JsonStringArray
|
|||
int timeoutSeconds = 5;
|
||||
|
||||
std::vector<Future<Void>> probes;
|
||||
probes.push_back(doProbe(immediateGrvProbe, timeoutSeconds, "immediate_priority_transaction_start", "start immediate priority transaction", &statusObj, messages, incomplete_reasons));
|
||||
probes.push_back(doProbe(immediateGrvProbe, timeoutSeconds, "immediate_priority_transaction_start", "start immediate priority transaction", &statusObj, messages, incomplete_reasons, isAvailable));
|
||||
probes.push_back(doProbe(defaultGrvProbe, timeoutSeconds, "transaction_start", "start default priority transaction", &statusObj, messages, incomplete_reasons));
|
||||
probes.push_back(doProbe(batchGrvProbe, timeoutSeconds, "batch_priority_transaction_start", "start batch priority transaction", &statusObj, messages, incomplete_reasons));
|
||||
probes.push_back(doProbe(readProbe, timeoutSeconds, "read", "read", &statusObj, messages, incomplete_reasons));
|
||||
probes.push_back(doProbe(commitProbe, timeoutSeconds, "commit", "commit", &statusObj, messages, incomplete_reasons));
|
||||
probes.push_back(doProbe(readProbe, timeoutSeconds, "read", "read", &statusObj, messages, incomplete_reasons, isAvailable));
|
||||
probes.push_back(doProbe(commitProbe, timeoutSeconds, "commit", "commit", &statusObj, messages, incomplete_reasons, isAvailable));
|
||||
|
||||
wait(waitForAll(probes));
|
||||
}
|
||||
|
@ -1688,7 +1693,7 @@ ACTOR Future<JsonString> layerStatusFetcher(Database cx, JsonStringArray *messag
|
|||
|
||||
json.cleanOps();
|
||||
JsonString statusObj = result.toJsonString();
|
||||
TraceEvent("LayerStatusFetcher").detail("Duration", now()-tStart).detail("StatusSize",statusObj.getLength()).detail("StatusNameTotal",statusObj.getNameTotal());
|
||||
TraceEvent("LayerStatusFetcher").detail("Duration", now()-tStart).detail("StatusSize",statusObj.getLength());
|
||||
return statusObj;
|
||||
}
|
||||
|
||||
|
@ -1746,7 +1751,9 @@ ACTOR Future<StatusReply> clusterGetStatus(
|
|||
std::vector<NetworkAddress> incompatibleConnections,
|
||||
Version datacenterVersionDifference )
|
||||
{
|
||||
state double tStart = now();
|
||||
// since we no longer offer multi-database support, all databases must be named DB
|
||||
state std::string dbName = "DB";
|
||||
state double tStart = timer();
|
||||
|
||||
// Check if master worker is present
|
||||
state JsonStringArray messages;
|
||||
|
@ -1828,7 +1835,7 @@ ACTOR Future<StatusReply> clusterGetStatus(
|
|||
state Optional<DatabaseConfiguration> configuration;
|
||||
state Optional<bool> fullReplication;
|
||||
|
||||
if(!(recoveryStateStatus.isPresent("name") && statusCode == RecoveryStatus::configuration_missing)) {
|
||||
if(statusCode != RecoveryStatus::configuration_missing) {
|
||||
std::pair<Optional<DatabaseConfiguration>,Optional<bool>> loadResults = wait(loadConfiguration(cx, &messages, &status_incomplete_reasons));
|
||||
configuration = loadResults.first;
|
||||
fullReplication = loadResults.second;
|
||||
|
@ -1842,9 +1849,10 @@ ACTOR Future<StatusReply> clusterGetStatus(
|
|||
|
||||
if (configuration.present()){
|
||||
// Do the latency probe by itself to avoid interference from other status activities
|
||||
JsonString latencyProbeResults = wait(latencyProbeFetcher(cx, &messages, &status_incomplete_reasons));
|
||||
state bool isAvailable = true;
|
||||
JsonString latencyProbeResults = wait(latencyProbeFetcher(cx, &messages, &status_incomplete_reasons, &isAvailable));
|
||||
|
||||
statusObj["database_available"] = latencyProbeResults.isPresent("immediate_priority_transaction_start_seconds") && latencyProbeResults.isPresent("read_seconds") && latencyProbeResults.isPresent("commit_seconds");
|
||||
statusObj["database_available"] = isAvailable;
|
||||
if (!latencyProbeResults.empty()) {
|
||||
statusObj["latency_probe"] = latencyProbeResults;
|
||||
}
|
||||
|
@ -1970,8 +1978,7 @@ ACTOR Future<StatusReply> clusterGetStatus(
|
|||
statusObj["cluster_controller_timestamp"] = clusterTime;
|
||||
}
|
||||
|
||||
TraceEvent("ClusterGetStatus").detail("Duration", now()-tStart)
|
||||
.detail("StatusSize",statusObj.getLength()) .detail("StatusNameTotal",statusObj.getNameTotal());
|
||||
TraceEvent("ClusterGetStatus").detail("Duration", timer()-tStart).detail("StatusSize",statusObj.getLength());
|
||||
|
||||
return StatusReply(statusObj);
|
||||
} catch( Error&e ) {
|
||||
|
@ -2005,12 +2012,6 @@ TEST_CASE("status/json/jsonstring") {
|
|||
ASSERT(jsonString1.equals(jsonString4));
|
||||
ASSERT(jsonString4.equals(jsonString1));
|
||||
|
||||
// Check presence of top level keys
|
||||
ASSERT(jsonString1.isPresent("_valid"));
|
||||
ASSERT(jsonString1.isPresent("error"));
|
||||
ASSERT(!jsonString1.isPresent("configurationMissing"));
|
||||
ASSERT(jsonString1.getNameTotal() == 2);
|
||||
|
||||
// Check empty
|
||||
ASSERT(!jsonString1.empty());
|
||||
ASSERT(JsonString().empty());
|
||||
|
@ -2027,12 +2028,6 @@ TEST_CASE("status/json/jsonstring") {
|
|||
testObj["pi"] = 3.14159;
|
||||
jsonObj["piobj"] = testObj;
|
||||
|
||||
// Check presence of top level keys
|
||||
ASSERT(jsonObj.isPresent("count"));
|
||||
ASSERT(testObj.isPresent("pi"));
|
||||
ASSERT(!jsonObj.isPresent("pi"));
|
||||
ASSERT(jsonObj.getNameTotal() == 3);
|
||||
|
||||
testObj.clear();
|
||||
testObj["val1"] = 7.9;
|
||||
testObj["val2"] = 34;
|
||||
|
|
|
@ -6,62 +6,58 @@
|
|||
|
||||
std::string format( const char* form, ... );
|
||||
|
||||
JsonString::JsonString() : _jsonText(), _keyNames() {
|
||||
JsonString::JsonString() : hasKey(false) {
|
||||
}
|
||||
JsonString::JsonString( const JsonString& jsonString) : _jsonText(jsonString._jsonText), _keyNames(jsonString._keyNames) {
|
||||
JsonString::JsonString( const JsonString& jsonString) : _jsonText(jsonString._jsonText), hasKey(jsonString.hasKey) {
|
||||
}
|
||||
JsonString::JsonString( const JsonStringArray& jsonArray) : _jsonText(), _keyNames() {
|
||||
JsonString::JsonString( const JsonStringArray& jsonArray) : hasKey(false) {
|
||||
append(jsonArray);
|
||||
}
|
||||
|
||||
JsonString::JsonString( const std::string& value ) : _jsonText(), _keyNames() {
|
||||
JsonString::JsonString( const std::string& value ) : hasKey(false) {
|
||||
append(value);
|
||||
}
|
||||
JsonString::JsonString( const char* value ) : _jsonText(), _keyNames() {
|
||||
JsonString::JsonString( const char* value ) : hasKey(false) {
|
||||
append(value);
|
||||
}
|
||||
|
||||
JsonString::JsonString( const std::string& name, const std::string& value ) : _jsonText(), _keyNames() {
|
||||
JsonString::JsonString( const std::string& name, const std::string& value ) : hasKey(false) {
|
||||
append(name, value);
|
||||
}
|
||||
JsonString::JsonString( const std::string& name, const char* value ) : _jsonText(), _keyNames() {
|
||||
JsonString::JsonString( const std::string& name, const char* value ) : hasKey(false) {
|
||||
append(name, value);
|
||||
}
|
||||
JsonString::JsonString( const std::string& name, double value ) : _jsonText(), _keyNames() {
|
||||
JsonString::JsonString( const std::string& name, double value ) : hasKey(false) {
|
||||
append(name, value);
|
||||
}
|
||||
JsonString::JsonString( const std::string& name, long int value ) : _jsonText(), _keyNames() {
|
||||
JsonString::JsonString( const std::string& name, long int value ) : hasKey(false) {
|
||||
append(name, value);
|
||||
}
|
||||
JsonString::JsonString( const std::string& name, long unsigned int value ) : _jsonText(), _keyNames() {
|
||||
JsonString::JsonString( const std::string& name, long unsigned int value ) : hasKey(false) {
|
||||
append(name, value);
|
||||
}
|
||||
JsonString::JsonString( const std::string& name, long long int value ) : _jsonText(), _keyNames() {
|
||||
JsonString::JsonString( const std::string& name, long long int value ) : hasKey(false) {
|
||||
append(name, value);
|
||||
}
|
||||
JsonString::JsonString( const std::string& name, long long unsigned int value ) : _jsonText(), _keyNames() {
|
||||
JsonString::JsonString( const std::string& name, long long unsigned int value ) : hasKey(false) {
|
||||
append(name, value);
|
||||
}
|
||||
JsonString::JsonString( const std::string& name, int value ) : _jsonText(), _keyNames() {
|
||||
JsonString::JsonString( const std::string& name, int value ) : hasKey(false) {
|
||||
append(name, value);
|
||||
}
|
||||
JsonString::JsonString( const std::string& name, unsigned value ) : _jsonText(), _keyNames() {
|
||||
JsonString::JsonString( const std::string& name, unsigned value ) : hasKey(false) {
|
||||
append(name, value);
|
||||
}
|
||||
JsonString::JsonString( const std::string& name, bool value ) : _jsonText(), _keyNames() {
|
||||
JsonString::JsonString( const std::string& name, bool value ) : hasKey(false) {
|
||||
append(name, value);
|
||||
}
|
||||
JsonString::JsonString( const std::string& name, const JsonString& value ) : _jsonText(), _keyNames() {
|
||||
JsonString::JsonString( const std::string& name, const JsonString& value ) : hasKey(false) {
|
||||
append(name, value);
|
||||
}
|
||||
JsonString::JsonString( const std::string& name, const JsonStringArray& value ) : _jsonText(), _keyNames() {
|
||||
JsonString::JsonString( const std::string& name, const JsonStringArray& value ) : hasKey(false) {
|
||||
append(name, value);
|
||||
}
|
||||
|
||||
bool JsonString::isPresent(const std::string& name) const {
|
||||
return (_keyNames.find(name) != _keyNames.end());
|
||||
}
|
||||
|
||||
JsonString JsonString::makeMessage(const char *name, const char *description) {
|
||||
JsonString out;
|
||||
out["name"] = name;
|
||||
|
@ -69,15 +65,8 @@ JsonString JsonString::makeMessage(const char *name, const char *description) {
|
|||
return out;
|
||||
}
|
||||
|
||||
void JsonString::hashName( const std::string& name) {
|
||||
if (isPresent(name)) {
|
||||
TraceEvent(g_network && g_network->isSimulated() ? SevError : SevWarnAlways, "JsonError").detail("KeyPresent", name).backtrace();
|
||||
}
|
||||
_keyNames.insert(name);
|
||||
}
|
||||
|
||||
JsonString& JsonString::appendImpl( const std::string& name, const std::string& value, bool quote ) {
|
||||
hashName(name);
|
||||
hasKey = true;
|
||||
_jsonText += (_jsonText.empty() ? "\"" : ",\n \"") + name + (quote ? "\": \"" : "\": ") + value;
|
||||
if (quote)
|
||||
_jsonText += "\"";
|
||||
|
@ -154,12 +143,12 @@ JsonString& JsonString::append( const std::string& name, bool value ) {
|
|||
return appendImpl(name, stringify(value), false);
|
||||
}
|
||||
JsonString& JsonString::append( const std::string& name, const JsonString& value ) {
|
||||
hashName(name);
|
||||
hasKey = true;
|
||||
_jsonText += (_jsonText.empty() ? "\"" : ",\n \"") + name + "\": { " + value._jsonText + " }";
|
||||
return *this;
|
||||
}
|
||||
JsonString& JsonString::append( const std::string& name, const JsonStringArray& values ) {
|
||||
hashName(name);
|
||||
hasKey = true;
|
||||
_jsonText += (_jsonText.empty() ? "\"" : ",\n \"") + name + "\": [ ";
|
||||
size_t counter = 0;
|
||||
for (auto const& value : values) {
|
||||
|
@ -208,7 +197,9 @@ JsonString& JsonString::append( const JsonString& value ) {
|
|||
if (!_jsonText.empty())
|
||||
_jsonText += ",\n ";
|
||||
_jsonText += value._jsonText;
|
||||
_keyNames.insert(value._keyNames.begin(), value._keyNames.end());
|
||||
if(value.hasKey) {
|
||||
hasKey = true;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
@ -226,34 +217,31 @@ JsonString& JsonString::append( const JsonStringArray& values ) {
|
|||
}
|
||||
|
||||
JsonString& JsonString::clear() {
|
||||
_keyNames.clear();
|
||||
_jsonText.clear();
|
||||
hasKey = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool JsonString::empty() const {
|
||||
bool JsonString::empty() const {
|
||||
return _jsonText.empty();
|
||||
}
|
||||
|
||||
const std::string& JsonString::getJsonText() const {
|
||||
const std::string& JsonString::getJsonText() const {
|
||||
return _jsonText;
|
||||
}
|
||||
|
||||
size_t JsonString::getLength() const {
|
||||
return _jsonText.length() + ((!empty() && _keyNames.empty()) ? 0 : 2);
|
||||
}
|
||||
size_t JsonString::getNameTotal() const {
|
||||
return _keyNames.size();
|
||||
size_t JsonString::getLength() const {
|
||||
return _jsonText.length() + ((!empty() && !hasKey) ? 0 : 4);
|
||||
}
|
||||
|
||||
std::string JsonString::getJson() const {
|
||||
std::string JsonString::getJson() const {
|
||||
// If not empty with no names (only values), don't add brackets because prob in an array
|
||||
return (!empty() && _keyNames.empty()) ? _jsonText : ("{ " + _jsonText + " }");
|
||||
return (!empty() && !hasKey) ? _jsonText : ("{ " + _jsonText + " }");
|
||||
}
|
||||
|
||||
JsonString& JsonString::copy( const JsonString& jsonString ) {
|
||||
_jsonText = jsonString._jsonText;
|
||||
_keyNames = jsonString._keyNames;
|
||||
hasKey = jsonString.hasKey;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -262,27 +250,14 @@ JsonString& JsonString::operator=( const JsonString& jsonString ) {
|
|||
}
|
||||
|
||||
//TODO: Populate key names member
|
||||
void JsonString::setJson(const std::string& jsonText) {
|
||||
_keyNames.clear();
|
||||
void JsonString::setJson(const std::string& jsonText) {
|
||||
_jsonText = jsonText;
|
||||
}
|
||||
JsonString& JsonString::swapJsonText(std::string& jsonText) {
|
||||
_keyNames.clear();
|
||||
_jsonText.swap(jsonText);
|
||||
return *this;
|
||||
}
|
||||
|
||||
JsonStringSetter& JsonString::operator[]( const std::string& name ) {
|
||||
JsonStringSetter* stringSetter = new JsonStringSetter(*this, name);
|
||||
return *stringSetter;
|
||||
}
|
||||
|
||||
JsonStringSetter& JsonString::operator[]( const char* name ) {
|
||||
std::string textName(name);
|
||||
JsonStringSetter* stringSetter = new JsonStringSetter(*this, textName);
|
||||
return *stringSetter;
|
||||
}
|
||||
|
||||
int JsonString::compare( const JsonString& jsonString ) const {
|
||||
return jsonString._jsonText.compare(_jsonText);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
#define JSONSTRING_H
|
||||
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
class JsonString;
|
||||
|
@ -59,9 +58,8 @@ class JsonString {
|
|||
JsonString& append( bool value );
|
||||
JsonString& append( const JsonString& value );
|
||||
|
||||
|
||||
JsonStringSetter& operator[]( const std::string& name );
|
||||
JsonStringSetter& operator[]( const char* name );
|
||||
JsonStringSetter operator[]( const std::string& name );
|
||||
JsonStringSetter operator[]( const char* name );
|
||||
|
||||
int compare( const JsonString& jsonString ) const;
|
||||
bool equals( const JsonString& jsonString ) const;
|
||||
|
@ -71,41 +69,36 @@ class JsonString {
|
|||
JsonString& copy( const JsonString& jsonString );
|
||||
JsonString& operator=( const JsonString& jsonString );
|
||||
|
||||
std::string getJson() const;
|
||||
void setJson(const std::string& jsonText);
|
||||
JsonString& swapJsonText(std::string& jsonText);
|
||||
std::string getJson() const;
|
||||
void setJson(const std::string& jsonText);
|
||||
JsonString& swapJsonText(std::string& jsonText);
|
||||
|
||||
size_t getLength() const;
|
||||
size_t getNameTotal() const;
|
||||
size_t getLength() const;
|
||||
|
||||
JsonString& clear();
|
||||
bool empty() const;
|
||||
|
||||
bool isPresent(const std::string& name) const;
|
||||
|
||||
bool empty() const;
|
||||
static JsonString makeMessage(const char *name, const char *description);
|
||||
|
||||
protected:
|
||||
void hashName( const std::string& name);
|
||||
JsonString& appendImpl( const std::string& name, const std::string& value, bool quote);
|
||||
JsonString& appendImpl( const std::string& value, bool quote);
|
||||
|
||||
static std::string stringify(const char* value);
|
||||
static std::string stringify(double value);
|
||||
static std::string stringify(long int value);
|
||||
static std::string stringify(long unsigned int value);
|
||||
static std::string stringify(long long int value);
|
||||
static std::string stringify(long long unsigned int value);
|
||||
static std::string stringify(int value);
|
||||
static std::string stringify(unsigned value);
|
||||
static std::string stringify(bool value);
|
||||
static std::string stringify(const char* value);
|
||||
static std::string stringify(double value);
|
||||
static std::string stringify(long int value);
|
||||
static std::string stringify(long unsigned int value);
|
||||
static std::string stringify(long long int value);
|
||||
static std::string stringify(long long unsigned int value);
|
||||
static std::string stringify(int value);
|
||||
static std::string stringify(unsigned value);
|
||||
static std::string stringify(bool value);
|
||||
|
||||
protected:
|
||||
std::string _jsonText;
|
||||
std::unordered_set<std::string> _keyNames;
|
||||
std::string _jsonText;
|
||||
bool hasKey;
|
||||
|
||||
// Uneditted text
|
||||
const std::string& getJsonText() const;
|
||||
const std::string& getJsonText() const;
|
||||
};
|
||||
|
||||
// Make protected because no virtual destructor
|
||||
|
@ -140,8 +133,16 @@ class JsonStringSetter {
|
|||
}
|
||||
|
||||
protected:
|
||||
JsonString& _jsonString;
|
||||
std::string _name;
|
||||
JsonString& _jsonString;
|
||||
std::string _name;
|
||||
};
|
||||
|
||||
inline JsonStringSetter JsonString::operator[]( const std::string& name ) {
|
||||
return JsonStringSetter(*this, name);
|
||||
}
|
||||
|
||||
inline JsonStringSetter JsonString::operator[]( const char* name ) {
|
||||
return JsonStringSetter(*this, name);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue