double VelocyPackHelper::toDouble(VPackSlice const& slice, bool& failed) { TRI_ASSERT(!slice.isNone()); failed = false; switch (slice.type()) { case VPackValueType::None: case VPackValueType::Null: return 0.0; case VPackValueType::Bool: return (slice.getBoolean() ? 1.0 : 0.0); case VPackValueType::Double: case VPackValueType::Int: case VPackValueType::UInt: case VPackValueType::SmallInt: return slice.getNumericValue<double>(); case VPackValueType::String: { std::string tmp(slice.copyString()); try { // try converting string to number return std::stod(tmp); } catch (...) { if (tmp.empty()) { return 0.0; } // conversion failed } break; } case VPackValueType::Array: { VPackValueLength const n = slice.length(); if (n == 0) { return 0.0; } else if (n == 1) { return VelocyPackHelper::toDouble(slice.at(0).resolveExternal(), failed); } break; } case VPackValueType::External: { return VelocyPackHelper::toDouble(slice.resolveExternal(), failed); } case VPackValueType::Illegal: case VPackValueType::Object: case VPackValueType::UTCDate: case VPackValueType::MinKey: case VPackValueType::MaxKey: case VPackValueType::Binary: case VPackValueType::BCD: case VPackValueType::Custom: break; } failed = true; return 0.0; }
int VelocyPackHelper::compare(VPackSlice lhs, VPackSlice rhs, bool useUTF8, VPackOptions const* options, VPackSlice const* lhsBase, VPackSlice const* rhsBase) { { // will resolve externals... int lWeight = TypeWeight(lhs); int rWeight = TypeWeight(rhs); if (lWeight < rWeight) { return -1; } if (lWeight > rWeight) { return 1; } TRI_ASSERT(lWeight == rWeight); } lhs = lhs.resolveExternal(); // follow externals rhs = rhs.resolveExternal(); // follow externals // lhs and rhs have equal weights if (lhs.isNone() || rhs.isNone()) { // either lhs or rhs is none. we cannot be sure here that both are // nones. // there can also exist the situation that lhs is a none and rhs is a // null value // (or vice versa). Anyway, the compare value is the same for both, return 0; } auto lhsType = lhs.type(); switch (lhsType) { case VPackValueType::Illegal: case VPackValueType::MinKey: case VPackValueType::MaxKey: case VPackValueType::None: case VPackValueType::Null: return 0; case VPackValueType::Bool: { bool left = lhs.getBoolean(); bool right = rhs.getBoolean(); if (left == right) { return 0; } if (!left && right) { return -1; } return 1; } case VPackValueType::Double: case VPackValueType::Int: case VPackValueType::UInt: case VPackValueType::SmallInt: { return compareNumberValues(lhsType, lhs, rhs); } case VPackValueType::Custom: case VPackValueType::String: { std::string lhsString; VPackValueLength nl; char const* left; if (lhs.isCustom()) { if (lhsBase == nullptr || options == nullptr || options->customTypeHandler == nullptr) { THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "Could not extract custom attribute."); } lhsString.assign(options->customTypeHandler->toString(lhs, options, *lhsBase)); left = lhsString.c_str(); nl = lhsString.size(); } else { left = lhs.getString(nl); } TRI_ASSERT(left != nullptr); std::string rhsString; VPackValueLength nr; char const* right; if (rhs.isCustom()) { if (rhsBase == nullptr || options == nullptr || options->customTypeHandler == nullptr) { THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "Could not extract custom attribute."); } rhsString.assign(options->customTypeHandler->toString(rhs, options, *rhsBase)); right = rhsString.c_str(); nr = rhsString.size(); } else { right = rhs.getString(nr); } TRI_ASSERT(right != nullptr); int res; if (useUTF8) { res = TRI_compare_utf8(left, static_cast<size_t>(nl), right, static_cast<size_t>(nr)); } else { size_t len = static_cast<size_t>(nl < nr ? nl : nr); res = memcmp(left, right, len); } if (res < 0) { return -1; } if (res > 0) { return 1; } // res == 0 if (nl == nr) { return 0; } // res == 0, but different string lengths return nl < nr ? -1 : 1; } case VPackValueType::Array: { VPackValueLength const nl = lhs.length(); VPackValueLength const nr = rhs.length(); VPackValueLength const n = (std::max)(nr, nl); for (VPackValueLength i = 0; i < n; ++i) { VPackSlice lhsValue; if (i < nl) { lhsValue = lhs.at(i).resolveExternal(); } VPackSlice rhsValue; if (i < nr) { rhsValue = rhs.at(i).resolveExternal(); } int result = compare(lhsValue, rhsValue, useUTF8, options, &lhs, &rhs); if (result != 0) { return result; } } return 0; } case VPackValueType::Object: { std::set<std::string, AttributeSorterUTF8> keys; VPackCollection::keys(lhs, keys); VPackCollection::keys(rhs, keys); for (auto const& key : keys) { VPackSlice lhsValue = lhs.get(key).resolveExternal(); if (lhsValue.isNone()) { // not present => null lhsValue = VPackSlice::nullSlice(); } VPackSlice rhsValue = rhs.get(key).resolveExternal(); if (rhsValue.isNone()) { // not present => null rhsValue = VPackSlice::nullSlice(); } int result = compare(lhsValue, rhsValue, useUTF8, options, &lhs, &rhs); if (result != 0) { return result; } } return 0; } default: // Contains all other ValueTypes of VelocyPack. // They are not used in ArangoDB so this cannot occur TRI_ASSERT(false); return 0; } }
void RestWalHandler::flush() { std::shared_ptr<VPackBuilder> parsedRequest; VPackSlice slice; try { slice = _request->payload(); } catch (...) { generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER, "invalid body value. expecting object"); return; } if (!slice.isObject() && !slice.isNone()) { generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER, "invalid body value. expecting object"); } bool waitForSync = false; bool waitForCollector = false; if (slice.isObject()) { // got a request body VPackSlice value = slice.get("waitForSync"); if (value.isString()) { waitForSync = (value.copyString() == "true"); } else if (value.isBoolean()) { waitForSync = value.getBoolean(); } value = slice.get("waitForCollector"); if (value.isString()) { waitForCollector = (value.copyString() == "true"); } else if (value.isBoolean()) { waitForCollector = value.getBoolean(); } } else { // no request body bool found; { std::string const& v = _request->value("waitForSync", found); if (found) { waitForSync = (v == "1" || v == "true"); } } { std::string const& v = _request->value("waitForCollector", found); if (found) { waitForCollector = (v == "1" || v == "true"); } } } int res; if (ServerState::instance()->isCoordinator()) { res = flushWalOnAllDBServers(waitForSync, waitForCollector); } else { res = arangodb::wal::LogfileManager::instance()->flush( waitForSync, waitForCollector, false); } if (res != TRI_ERROR_NO_ERROR) { THROW_ARANGO_EXCEPTION(res); } generateResult(rest::ResponseCode::OK, basics::VelocyPackHelper::EmptyObjectValue()); }