fix: status would generate invalid json

This commit is contained in:
Evan Tschannen 2018-09-07 18:26:05 -07:00
parent 953f67009d
commit d3c8d7ab4e
9 changed files with 135 additions and 59 deletions

View File

@ -27,7 +27,7 @@
#include "Status.h"
#include "ClientDBInfo.h"
#include "ClientWorkerInterface.h"
#include "flow/JsonString.h"
#include "JsonString.h"
struct ClusterInterface {
RequestStream< struct OpenDatabaseRequest > openDatabase;

162
flow/JsonString.cpp → fdbclient/JsonString.cpp Executable file → Normal file
View File

@ -1,11 +1,45 @@
#include "JsonString.h"
#include "Hash3.h"
#include <iostream>
#include "Trace.h"
#include "flow.h"
std::string format( const char* form, ... );
bool shouldEscape(char c) {
switch( c ) {
case '"':
case '\\':
case '\b':
case '\f':
case '\n':
case '\r':
case '\t':
return true;
default:
return false;
}
}
void escape( const std::string& in, std::string& out ) {
bool needsEscaping = false;
for (int i = 0; i<in.size(); i++) {
if (shouldEscape(in[i])) {
needsEscaping = true;
break;
}
}
if(!needsEscaping) {
out += in;
return;
}
for (int i = 0; i<in.size(); i++) {
if (shouldEscape(in[i])) {
out += '\\';
}
out += in[i];
}
}
JsonString::JsonString() : hasKey(false) {
}
JsonString::JsonString( const JsonString& jsonString) : _jsonText(jsonString._jsonText), hasKey(jsonString.hasKey) {
@ -21,6 +55,12 @@ JsonString::JsonString( const char* value ) : hasKey(false) {
append(value);
}
JsonString::JsonString( const json_spirit::mObject& value ) : hasKey(false) {
_jsonText = json_spirit::write_string(json_spirit::mValue(value));
_jsonText = _jsonText.substr(1,_jsonText.size()-2); //remove outer {}
hasKey = !_jsonText.empty();
}
JsonString::JsonString( const std::string& name, const std::string& value ) : hasKey(false) {
append(name, value);
}
@ -66,19 +106,33 @@ JsonString JsonString::makeMessage(const char *name, const char *description) {
}
JsonString& JsonString::appendImpl( const std::string& name, const std::string& value, bool quote ) {
_jsonText.reserve(_jsonText.size() + name.size() + (quote ? (2*value.size() + 6) : (value.size() + 4)));
hasKey = true;
_jsonText += (_jsonText.empty() ? "\"" : ",\n \"") + name + (quote ? "\": \"" : "\": ") + value;
if (quote)
if(!_jsonText.empty()) {
_jsonText += ',';
}
_jsonText += '"';
_jsonText += name;
_jsonText += "\":";
if (quote) {
_jsonText += "\"";
escape(value, _jsonText);
_jsonText += "\"";
} else {
_jsonText += value;
}
return *this;
}
JsonString& JsonString::appendImpl( const std::string& value, bool quote ) {
if (quote) {
_jsonText += (_jsonText.empty() ? "\"" : ", \"") + value + "\"";
_jsonText.reserve(_jsonText.size() + (quote ? (2*value.size() + 3) : value.size()));
if(!_jsonText.empty()) {
_jsonText += ',';
}
else {
if (_jsonText.empty())
_jsonText += ", ";
if (quote) {
_jsonText += "\"";
escape(value, _jsonText);
_jsonText += "\"";
} else {
_jsonText += value;
}
return *this;
@ -143,21 +197,40 @@ 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 ) {
_jsonText.reserve(_jsonText.size() + name.size() + value._jsonText.size() + 6);
hasKey = true;
_jsonText += (_jsonText.empty() ? "\"" : ",\n \"") + name + "\": { " + value._jsonText + " }";
if(!_jsonText.empty()) {
_jsonText += ',';
}
_jsonText += '\"';
_jsonText += name;
_jsonText += "\":{";
_jsonText += value._jsonText;
_jsonText += '}';
return *this;
}
JsonString& JsonString::append( const std::string& name, const JsonStringArray& values ) {
hasKey = true;
_jsonText += (_jsonText.empty() ? "\"" : ",\n \"") + name + "\": [ ";
size_t counter = 0;
int valueBytes = 0;
for (auto const& value : values) {
if (counter)
_jsonText += ",\n ";
_jsonText += value.getJson();
counter ++;
valueBytes += value.getLength();
}
_jsonText += " ]";
_jsonText.reserve(_jsonText.size() + name.size() + values.size() + valueBytes + 6);
hasKey = true;
if(!_jsonText.empty()) {
_jsonText += ',';
}
_jsonText += '"';
_jsonText += name;
_jsonText += "\":[";
bool first = true;
for (auto const& value : values) {
if (!first) {
_jsonText += ',';
}
_jsonText += value.getJson();
first = false;
}
_jsonText += ']';
return *this;
}
@ -194,8 +267,10 @@ JsonString& JsonString::append( bool value ) {
JsonString& JsonString::append( const JsonString& value ) {
// Only do something, if not empty
if (!value.empty()) {
if (!_jsonText.empty())
_jsonText += ",\n ";
_jsonText.reserve(_jsonText.size() + value._jsonText.size() + 1);
if (!_jsonText.empty()) {
_jsonText += ',';
}
_jsonText += value._jsonText;
if(value.hasKey) {
hasKey = true;
@ -204,15 +279,24 @@ JsonString& JsonString::append( const JsonString& value ) {
return *this;
}
JsonString& JsonString::append( const JsonStringArray& values ) {
_jsonText += _jsonText.empty() ? "[ " : ",\n [ ";
size_t counter = 0;
int valueBytes = 0;
for (auto const& value : values) {
if (counter)
_jsonText += ",\n ";
_jsonText += value.getJson();
counter ++;
valueBytes += value.getLength();
}
_jsonText += " ]";
_jsonText.reserve(_jsonText.size() + values.size() + valueBytes + 3);
if (!_jsonText.empty()) {
_jsonText += ',';
}
_jsonText += '[';
bool first = true;
for (auto const& value : values) {
if (!first) {
_jsonText += ',';
}
_jsonText += value.getJson();
first = false;
}
_jsonText += ']';
return *this;
}
@ -231,12 +315,21 @@ const std::string& JsonString::getJsonText() const {
}
size_t JsonString::getLength() const {
return _jsonText.length() + ((!empty() && !hasKey) ? 0 : 4);
return _jsonText.length() + ((!empty() && !hasKey) ? 0 : 2);
}
std::string JsonString::getJson() const {
// If not empty with no names (only values), don't add brackets because prob in an array
return (!empty() && !hasKey) ? _jsonText : ("{ " + _jsonText + " }");
if (!empty() && !hasKey) {
return _jsonText;
} else {
std::string result;
result.reserve(_jsonText.size() + 2);
result += '{';
result += _jsonText;
result += '}';
return result;
}
}
JsonString& JsonString::copy( const JsonString& jsonString ) {
@ -249,15 +342,6 @@ JsonString& JsonString::operator=( const JsonString& jsonString ) {
return copy(jsonString);
}
//TODO: Populate key names member
void JsonString::setJson(const std::string& jsonText) {
_jsonText = jsonText;
}
JsonString& JsonString::swapJsonText(std::string& jsonText) {
_jsonText.swap(jsonText);
return *this;
}
int JsonString::compare( const JsonString& jsonString ) const {
return jsonString._jsonText.compare(_jsonText);
}

7
flow/JsonString.h → fdbclient/JsonString.h Executable file → Normal file
View File

@ -4,6 +4,9 @@
#include <string>
#include <vector>
#include "flow/flow.h"
#include "flow/Trace.h"
#include "fdbrpc/JSONDoc.h"
class JsonString;
class JsonStringArray;
@ -17,6 +20,7 @@ class JsonString {
explicit JsonString( const JsonStringArray& jsonArray);
explicit JsonString( const char* value ); // Used to define values (used in an Array)
explicit JsonString( const std::string& value ); // Used to define values (used in an Array)
explicit JsonString( const json_spirit::mObject& value );
JsonString( const std::string& name, const char* value );
JsonString( const std::string& name, const std::string& value );
@ -70,9 +74,6 @@ class JsonString {
JsonString& operator=( const JsonString& jsonString );
std::string getJson() const;
void setJson(const std::string& jsonText);
JsonString& swapJsonText(std::string& jsonText);
size_t getLength() const;
JsonString& clear();

View File

@ -1405,8 +1405,9 @@ json_spirit::Value_type normJSONType(json_spirit::Value_type type) {
}
void schemaCoverage( std::string const& spath, bool covered ) {
static std::set<std::string> coveredSchemaPaths;
if (coveredSchemaPaths.insert(spath).second) {
static std::map<bool, std::set<std::string>> coveredSchemaPaths;
if( coveredSchemaPaths[covered].insert(spath).second ) {
TraceEvent ev(SevInfo, "CodeCoverage");
ev.detail("File", "documentation/StatusSchema.json/" + spath).detail("Line", 0);
if (!covered)

View File

@ -1,7 +0,0 @@
#include "flow/flow.h"
#include "Status.h"
JsonString StatusObject::toJsonString() const {
std::string jsonText = json_spirit::write_string(json_spirit::mValue(*this));
return JsonString().swapJsonText(jsonText);
}

View File

@ -22,7 +22,6 @@
#define FDBCLIENT_STATUS_H
#include "../fdbrpc/JSONDoc.h"
#include "../flow/JsonString.h"
struct StatusObject : json_spirit::mObject {
typedef json_spirit::mObject Map;
@ -30,7 +29,6 @@ struct StatusObject : json_spirit::mObject {
StatusObject() {}
StatusObject(json_spirit::mObject const& o) : json_spirit::mObject(o) {}
JsonString toJsonString() const;
};
template <class Ar>

View File

@ -81,6 +81,7 @@
<ClInclude Include="WriteMap.h" />
<ClInclude Include="Subspace.h" />
<ClInclude Include="Tuple.h" />
<ClInclude Include="JsonString.h" />
</ItemGroup>
<ItemGroup>
<ActorCompiler Include="FailureMonitorClient.actor.cpp" />
@ -98,13 +99,13 @@
<ActorCompiler Include="MultiVersionTransaction.actor.cpp" />
<ClCompile Include="RYWIterator.cpp" />
<ActorCompiler Include="StatusClient.actor.cpp" />
<ClCompile Include="Status.cpp" />
<ClCompile Include="Schemas.cpp" />
<ClCompile Include="SystemData.cpp" />
<ActorCompiler Include="ThreadSafeTransaction.actor.cpp" />
<ActorCompiler Include="TaskBucket.actor.cpp" />
<ClCompile Include="Subspace.cpp" />
<ClCompile Include="Tuple.cpp" />
<ClCompile Include="JsonString.cpp" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGUID>{E2939DAA-238E-4970-96C4-4C57980F93BD}</ProjectGUID>

View File

@ -1075,7 +1075,7 @@ static JsonString configurationFetcher(Optional<DatabaseConfiguration> conf, Ser
try {
if(conf.present()) {
DatabaseConfiguration configuration = conf.get();
statusObj = configuration.toJSON().toJsonString();
statusObj = JsonString( configuration.toJSON() );
JsonStringArray excludedServersArr;
std::set<AddressExclusion> excludedServers = configuration.getExcludedServers();
@ -1692,7 +1692,7 @@ ACTOR Future<JsonString> layerStatusFetcher(Database cx, JsonStringArray *messag
}
json.cleanOps();
JsonString statusObj = result.toJsonString();
JsonString statusObj = JsonString( result );
TraceEvent("LayerStatusFetcher").detail("Duration", now()-tStart).detail("StatusSize",statusObj.getLength());
return statusObj;
}

View File

@ -45,7 +45,6 @@
<ClCompile Include="UnitTest.cpp" />
<ClCompile Include="version.cpp" />
<ClCompile Include="SignalSafeUnwind.cpp" />
<ClCompile Include="JsonString.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="CompressedInt.h" />
@ -89,7 +88,6 @@
<ClInclude Include="ThreadSafeQueue.h" />
<ClInclude Include="Trace.h" />
<ClInclude Include="SignalSafeUnwind.h" />
<ClInclude Include="JsonString.h" />
<ClInclude Include="UnitTest.h" />
<ActorCompiler Include="ThreadHelper.actor.h">
<EnableCompile>false</EnableCompile>