2017-05-26 04:48:44 +08:00
|
|
|
/*
|
|
|
|
* Status.h
|
|
|
|
*
|
|
|
|
* This source file is part of the FoundationDB open source project
|
|
|
|
*
|
|
|
|
* Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
|
2018-02-22 02:25:11 +08:00
|
|
|
*
|
2017-05-26 04:48:44 +08:00
|
|
|
* Licensed 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
|
2018-02-22 02:25:11 +08:00
|
|
|
*
|
2017-05-26 04:48:44 +08:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2018-02-22 02:25:11 +08:00
|
|
|
*
|
2017-05-26 04:48:44 +08:00
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef FDBCLIENT_STATUS_H
|
|
|
|
#define FDBCLIENT_STATUS_H
|
|
|
|
|
2018-10-27 04:49:42 +08:00
|
|
|
#include "fdbclient/JSONDoc.h"
|
2017-05-26 04:48:44 +08:00
|
|
|
|
2018-09-08 22:15:28 +08:00
|
|
|
// Reads the entire string s as a JSON value
|
|
|
|
// Throws if no value can be parsed or if s contains data after the first JSON value
|
|
|
|
// Trailing whitespace in s is allowed
|
2021-03-11 02:06:03 +08:00
|
|
|
json_spirit::mValue readJSONStrictly(const std::string& s);
|
2018-09-08 22:15:28 +08:00
|
|
|
|
2017-05-26 04:48:44 +08:00
|
|
|
struct StatusObject : json_spirit::mObject {
|
|
|
|
typedef json_spirit::mObject Map;
|
|
|
|
typedef json_spirit::mArray Array;
|
|
|
|
|
|
|
|
StatusObject() {}
|
|
|
|
StatusObject(json_spirit::mObject const& o) : json_spirit::mObject(o) {}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class Ar>
|
|
|
|
void load(Ar& ar, StatusObject& statusObj) {
|
|
|
|
std::string value;
|
|
|
|
int32_t length;
|
|
|
|
ar >> length;
|
|
|
|
value.resize(length);
|
2021-03-11 02:06:03 +08:00
|
|
|
ar.serializeBytes(&value[0], (int)value.length());
|
2017-05-26 04:48:44 +08:00
|
|
|
json_spirit::mValue mv;
|
2021-03-11 02:06:03 +08:00
|
|
|
json_spirit::read_string(value, mv);
|
2017-05-26 04:48:44 +08:00
|
|
|
statusObj = StatusObject(mv.get_obj());
|
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
ASSERT(ar.protocolVersion().isValid());
|
2017-05-26 04:48:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class Ar>
|
|
|
|
void save(Ar& ar, StatusObject const& statusObj) {
|
|
|
|
std::string value = json_spirit::write_string(json_spirit::mValue(statusObj));
|
|
|
|
ar << (int32_t)value.length();
|
2021-03-11 02:06:03 +08:00
|
|
|
ar.serializeBytes((void*)&value[0], (int)value.length());
|
|
|
|
ASSERT(ar.protocolVersion().isValid());
|
2017-05-26 04:48:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
struct StatusArray : json_spirit::mArray {
|
|
|
|
StatusArray() {}
|
2021-03-11 02:06:03 +08:00
|
|
|
StatusArray(json_spirit::mArray const& o) : json_spirit::mArray(o.begin(), o.end()) {}
|
2017-05-26 04:48:44 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct StatusValue : json_spirit::mValue {
|
|
|
|
StatusValue() {}
|
|
|
|
StatusValue(json_spirit::mValue const& o) : json_spirit::mValue(o) {}
|
|
|
|
};
|
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
inline StatusObject makeMessage(const char* name, const char* description) {
|
2017-05-26 04:48:44 +08:00
|
|
|
StatusObject out;
|
|
|
|
out["name"] = name;
|
|
|
|
out["description"] = description;
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Typedef to cover older code that was written when this class was only a reader and called StatusObjectReader
|
|
|
|
typedef JSONDoc StatusObjectReader;
|
|
|
|
|
2018-08-31 16:21:24 +08:00
|
|
|
// Template specialization for get<JSONDoc> because is convenient to get() an
|
2017-05-26 04:48:44 +08:00
|
|
|
// element from an object directly into a JSONDoc to have a handle to that sub-doc.
|
2021-03-11 02:06:03 +08:00
|
|
|
template <>
|
|
|
|
inline bool JSONDoc::get<JSONDoc>(const std::string path, StatusObjectReader& out, bool split) {
|
2017-05-26 04:48:44 +08:00
|
|
|
bool r = has(path, split);
|
|
|
|
if (r)
|
|
|
|
out = pLast->get_obj();
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
// Takes an object by reference so make usage look clean and avoid the client doing object["messages"] which will create
|
|
|
|
// the key.
|
2019-06-21 00:29:01 +08:00
|
|
|
inline bool findMessagesByName(StatusObjectReader object, std::set<std::string> to_find) {
|
2017-05-26 04:48:44 +08:00
|
|
|
|
|
|
|
if (!object.has("messages") || object.last().type() != json_spirit::array_type)
|
|
|
|
return false;
|
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
StatusObject::Array const& messages = object.last().get_array();
|
2017-05-26 04:48:44 +08:00
|
|
|
|
|
|
|
// Iterate over message array and look up each name in to_find.
|
|
|
|
// Not using StatusObjectReader here because it would throw if an i in messages is NOT an mObject
|
2021-03-11 02:06:03 +08:00
|
|
|
for (auto i : messages) {
|
2017-05-26 04:48:44 +08:00
|
|
|
// Since we are looking for a positive match, any exceptions thrown when trying to read
|
|
|
|
// the object in the messages array will be perceived as not-a-match and therefore ignored.
|
2021-03-11 02:06:03 +08:00
|
|
|
try {
|
2017-05-26 04:48:44 +08:00
|
|
|
if (to_find.count(i.get_obj().at("name").get_str()))
|
|
|
|
return true;
|
2021-03-11 02:06:03 +08:00
|
|
|
} catch (std::exception&) {
|
2017-05-26 04:48:44 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|