mirror of https://gitee.com/bigwinds/arangodb
Use hybrid logical clock for _rev entries.
This commit is contained in:
parent
dacb54d56f
commit
7fe9fcc00e
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#include "v8-vocbaseprivate.h"
|
#include "v8-vocbaseprivate.h"
|
||||||
#include "Basics/conversions.h"
|
#include "Basics/conversions.h"
|
||||||
|
#include "Basics/HybridLogicalClock.h"
|
||||||
#include "VocBase/KeyGenerator.h"
|
#include "VocBase/KeyGenerator.h"
|
||||||
#include "V8/v8-conv.h"
|
#include "V8/v8-conv.h"
|
||||||
|
|
||||||
|
@ -109,64 +110,6 @@ static bool ParseDocumentHandle(v8::Handle<v8::Value> const arg,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief parse document or document handle from a v8 value (string | object)
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
bool ExtractDocumentHandle(v8::Isolate* isolate,
|
|
||||||
v8::Handle<v8::Value> const val,
|
|
||||||
std::string& collectionName,
|
|
||||||
std::unique_ptr<char[]>& key, TRI_voc_rid_t& rid) {
|
|
||||||
// reset the collection identifier and the revision
|
|
||||||
TRI_ASSERT(collectionName.empty());
|
|
||||||
rid = 0;
|
|
||||||
|
|
||||||
// extract the document identifier and revision from a string
|
|
||||||
if (val->IsString()) {
|
|
||||||
return ParseDocumentHandle(val, collectionName, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
// extract the document identifier and revision from a document object
|
|
||||||
if (val->IsObject()) {
|
|
||||||
TRI_GET_GLOBALS();
|
|
||||||
|
|
||||||
v8::Handle<v8::Object> obj = val->ToObject();
|
|
||||||
TRI_GET_GLOBAL_STRING(_IdKey);
|
|
||||||
TRI_GET_GLOBAL_STRING(_KeyKey);
|
|
||||||
if (obj->HasRealNamedProperty(_IdKey)) {
|
|
||||||
v8::Handle<v8::Value> didVal = obj->Get(_IdKey);
|
|
||||||
|
|
||||||
if (!ParseDocumentHandle(didVal, collectionName, key)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else if (obj->HasRealNamedProperty(_KeyKey)) {
|
|
||||||
v8::Handle<v8::Value> didVal = obj->Get(_KeyKey);
|
|
||||||
|
|
||||||
if (!ParseDocumentHandle(didVal, collectionName, key)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
TRI_GET_GLOBAL_STRING(_RevKey);
|
|
||||||
if (!obj->HasRealNamedProperty(_RevKey)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
rid = TRI_ObjectToUInt64(obj->Get(_RevKey), true);
|
|
||||||
|
|
||||||
if (rid == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// unknown value type. give up
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief parse document or document handle from a v8 value (string | object)
|
/// @brief parse document or document handle from a v8 value (string | object)
|
||||||
/// Note that the builder must already be open with an object and that it
|
/// Note that the builder must already be open with an object and that it
|
||||||
|
@ -234,14 +177,19 @@ bool ExtractDocumentHandle(v8::Isolate* isolate,
|
||||||
if (!obj->HasRealNamedProperty(_RevKey)) {
|
if (!obj->HasRealNamedProperty(_RevKey)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
uint64_t rid = 0;
|
v8::Handle<v8::Value> revObj = obj->Get(_RevKey);
|
||||||
|
if (!revObj->IsString()) {
|
||||||
rid = TRI_ObjectToUInt64(obj->Get(_RevKey), true);
|
return true;
|
||||||
|
}
|
||||||
|
v8::String::Utf8Value str(revObj);
|
||||||
|
uint64_t rid
|
||||||
|
= HybridLogicalClock::decodeTimeStamp(std::string(*str, str.length()));
|
||||||
|
|
||||||
if (rid == 0) {
|
if (rid == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
builder.add(StaticStrings::RevString, VPackValue(std::to_string(rid)));
|
builder.add(StaticStrings::RevString, VPackValue(
|
||||||
|
HybridLogicalClock::encodeTimeStamp(rid)));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,15 +76,6 @@ TRI_vocbase_t* GetContextVocBase(v8::Isolate* isolate);
|
||||||
|
|
||||||
v8::Handle<v8::Value> V8TickId(v8::Isolate* isolate, TRI_voc_tick_t tick);
|
v8::Handle<v8::Value> V8TickId(v8::Isolate* isolate, TRI_voc_tick_t tick);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief parse document or document handle from a v8 value (string | object)
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
bool ExtractDocumentHandle(v8::Isolate* isolate,
|
|
||||||
v8::Handle<v8::Value> const val,
|
|
||||||
std::string& collectionName,
|
|
||||||
std::unique_ptr<char[]>& key, TRI_voc_rid_t& rid);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief parse document or document handle from a v8 value (string | object)
|
/// @brief parse document or document handle from a v8 value (string | object)
|
||||||
/// Note that the builder must already be open with an object and will remain
|
/// Note that the builder must already be open with an object and will remain
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include "Basics/conversions.h"
|
#include "Basics/conversions.h"
|
||||||
#include "Basics/Exceptions.h"
|
#include "Basics/Exceptions.h"
|
||||||
#include "Basics/FileUtils.h"
|
#include "Basics/FileUtils.h"
|
||||||
|
#include "Basics/HybridLogicalClock.h"
|
||||||
#include "Basics/Timers.h"
|
#include "Basics/Timers.h"
|
||||||
#include "Basics/files.h"
|
#include "Basics/files.h"
|
||||||
#include "Basics/tri-strings.h"
|
#include "Basics/tri-strings.h"
|
||||||
|
@ -3383,7 +3384,7 @@ int TRI_document_collection_t::update(Transaction* trx,
|
||||||
// make sure our local tick is at least as high as the remote tick
|
// make sure our local tick is at least as high as the remote tick
|
||||||
TRI_UpdateTickServer(revisionId);
|
TRI_UpdateTickServer(revisionId);
|
||||||
} else {
|
} else {
|
||||||
revisionId = TRI_NewTickServer();
|
revisionId = TRI_HybridLogicalClock();
|
||||||
}
|
}
|
||||||
|
|
||||||
VPackSlice key = newSlice.get(StaticStrings::KeyString);
|
VPackSlice key = newSlice.get(StaticStrings::KeyString);
|
||||||
|
@ -3439,8 +3440,8 @@ int TRI_document_collection_t::update(Transaction* trx,
|
||||||
if (options.recoveryMarker == nullptr) {
|
if (options.recoveryMarker == nullptr) {
|
||||||
mergeObjectsForUpdate(
|
mergeObjectsForUpdate(
|
||||||
trx, VPackSlice(oldHeader->vpack()), newSlice, isEdgeCollection,
|
trx, VPackSlice(oldHeader->vpack()), newSlice, isEdgeCollection,
|
||||||
std::to_string(revisionId), options.mergeObjects, options.keepNull,
|
HybridLogicalClock::encodeTimeStamp(revisionId),
|
||||||
*builder.get());
|
options.mergeObjects, options.keepNull, *builder.get());
|
||||||
|
|
||||||
if (ServerState::isDBServer(trx->serverRole())) {
|
if (ServerState::isDBServer(trx->serverRole())) {
|
||||||
// Need to check that no sharding keys have changed:
|
// Need to check that no sharding keys have changed:
|
||||||
|
@ -3534,13 +3535,11 @@ int TRI_document_collection_t::replace(Transaction* trx,
|
||||||
if (!oldRev.isString()) {
|
if (!oldRev.isString()) {
|
||||||
return TRI_ERROR_ARANGO_DOCUMENT_REV_BAD;
|
return TRI_ERROR_ARANGO_DOCUMENT_REV_BAD;
|
||||||
}
|
}
|
||||||
VPackValueLength length;
|
revisionId = HybridLogicalClock::decodeTimeStamp(oldRev.copyString());
|
||||||
char const* p = oldRev.getString(length);
|
|
||||||
revisionId = arangodb::basics::StringUtils::uint64(p, static_cast<size_t>(length));
|
|
||||||
// make sure our local tick is at least as high as the remote tick
|
// make sure our local tick is at least as high as the remote tick
|
||||||
TRI_UpdateTickServer(revisionId);
|
TRI_UpdateTickServer(revisionId);
|
||||||
} else {
|
} else {
|
||||||
revisionId = TRI_NewTickServer();
|
revisionId = TRI_HybridLogicalClock();
|
||||||
}
|
}
|
||||||
|
|
||||||
int res;
|
int res;
|
||||||
|
@ -3586,7 +3585,9 @@ int TRI_document_collection_t::replace(Transaction* trx,
|
||||||
TransactionBuilderLeaser builder(trx);
|
TransactionBuilderLeaser builder(trx);
|
||||||
newObjectForReplace(
|
newObjectForReplace(
|
||||||
trx, VPackSlice(oldHeader->vpack()),
|
trx, VPackSlice(oldHeader->vpack()),
|
||||||
newSlice, fromSlice, toSlice, isEdgeCollection, std::to_string(revisionId), *builder.get());
|
newSlice, fromSlice, toSlice, isEdgeCollection,
|
||||||
|
HybridLogicalClock::encodeTimeStamp(revisionId),
|
||||||
|
*builder.get());
|
||||||
|
|
||||||
if (ServerState::isDBServer(trx->serverRole())) {
|
if (ServerState::isDBServer(trx->serverRole())) {
|
||||||
// Need to check that no sharding keys have changed:
|
// Need to check that no sharding keys have changed:
|
||||||
|
@ -3651,16 +3652,14 @@ int TRI_document_collection_t::remove(arangodb::Transaction* trx,
|
||||||
if (options.isRestore) {
|
if (options.isRestore) {
|
||||||
VPackSlice oldRev = TRI_ExtractRevisionIdAsSlice(slice);
|
VPackSlice oldRev = TRI_ExtractRevisionIdAsSlice(slice);
|
||||||
if (!oldRev.isString()) {
|
if (!oldRev.isString()) {
|
||||||
revisionId = TRI_NewTickServer();
|
revisionId = TRI_HybridLogicalClock();
|
||||||
} else {
|
} else {
|
||||||
VPackValueLength length;
|
revisionId = HybridLogicalClock::decodeTimeStamp(oldRev.copyString());
|
||||||
char const* p = oldRev.getString(length);
|
|
||||||
revisionId = arangodb::basics::StringUtils::uint64(p, static_cast<size_t>(length));
|
|
||||||
// make sure our local tick is at least as high as the remote tick
|
// make sure our local tick is at least as high as the remote tick
|
||||||
TRI_UpdateTickServer(revisionId);
|
TRI_UpdateTickServer(revisionId);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
revisionId = TRI_NewTickServer();
|
revisionId = TRI_HybridLogicalClock();
|
||||||
}
|
}
|
||||||
|
|
||||||
TransactionBuilderLeaser builder(trx);
|
TransactionBuilderLeaser builder(trx);
|
||||||
|
@ -4124,8 +4123,8 @@ int TRI_document_collection_t::newObjectForInsert(
|
||||||
VPackSlice s = value.get(StaticStrings::KeyString);
|
VPackSlice s = value.get(StaticStrings::KeyString);
|
||||||
if (s.isNone()) {
|
if (s.isNone()) {
|
||||||
TRI_ASSERT(!isRestore); // need key in case of restore
|
TRI_ASSERT(!isRestore); // need key in case of restore
|
||||||
newRev = TRI_NewTickServer();
|
newRev = TRI_HybridLogicalClock();
|
||||||
std::string keyString = _keyGenerator->generate(newRev);
|
std::string keyString = _keyGenerator->generate(TRI_NewTickServer());
|
||||||
if (keyString.empty()) {
|
if (keyString.empty()) {
|
||||||
return TRI_ERROR_ARANGO_OUT_OF_KEYS;
|
return TRI_ERROR_ARANGO_OUT_OF_KEYS;
|
||||||
}
|
}
|
||||||
|
@ -4180,9 +4179,9 @@ int TRI_document_collection_t::newObjectForInsert(
|
||||||
newRevSt = oldRev.copyString();
|
newRevSt = oldRev.copyString();
|
||||||
} else {
|
} else {
|
||||||
if (newRev == 0) {
|
if (newRev == 0) {
|
||||||
newRev = TRI_NewTickServer();
|
newRev = TRI_HybridLogicalClock();
|
||||||
}
|
}
|
||||||
newRevSt = std::to_string(newRev);
|
newRevSt = HybridLogicalClock::encodeTimeStamp(newRev);
|
||||||
}
|
}
|
||||||
builder.add(StaticStrings::RevString, VPackValue(newRevSt));
|
builder.add(StaticStrings::RevString, VPackValue(newRevSt));
|
||||||
|
|
||||||
|
|
|
@ -2071,11 +2071,17 @@ TRI_voc_tick_t TRI_NewTickServer() { return ++CurrentTick; }
|
||||||
/// @brief create a new tick, using a hybrid logical clock
|
/// @brief create a new tick, using a hybrid logical clock
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
TRI_voc_tick_t TRI_NewTickServerHLC(void) {
|
TRI_voc_tick_t TRI_HybridLogicalClock(void) {
|
||||||
return hybridLogicalClock.getTimeStamp();
|
return hybridLogicalClock.getTimeStamp();
|
||||||
}
|
}
|
||||||
|
|
||||||
TRI_voc_tick_t TRI_NewTickServerHLC(TRI_voc_tick_t received) {
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief create a new tick, using a hybrid logical clock, this variant
|
||||||
|
/// is supposed to be called when a time stamp is received in network
|
||||||
|
/// communications.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
TRI_voc_tick_t TRI_HybridLogicalClock(TRI_voc_tick_t received) {
|
||||||
return hybridLogicalClock.getTimeStamp(received);
|
return hybridLogicalClock.getTimeStamp(received);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -254,8 +254,15 @@ TRI_voc_tick_t TRI_NewTickServer(void);
|
||||||
/// @brief create a new tick, using a hybrid logical clock
|
/// @brief create a new tick, using a hybrid logical clock
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
TRI_voc_tick_t TRI_NewTickServerHLC(void);
|
TRI_voc_tick_t TRI_HybridLogicalClock(void);
|
||||||
TRI_voc_tick_t TRI_NewTickServerHLC(TRI_voc_tick_t received);
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief create a new tick, using a hybrid logical clock, this variant
|
||||||
|
/// is supposed to be called when a time stamp is received in network
|
||||||
|
/// communications.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
TRI_voc_tick_t TRI_HybridLogicalClock(TRI_voc_tick_t received);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief updates the tick counter, with lock
|
/// @brief updates the tick counter, with lock
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "Aql/QueryList.h"
|
#include "Aql/QueryList.h"
|
||||||
#include "Basics/Exceptions.h"
|
#include "Basics/Exceptions.h"
|
||||||
#include "Basics/FileUtils.h"
|
#include "Basics/FileUtils.h"
|
||||||
|
#include "Basics/HybridLogicalClock.h"
|
||||||
#include "Basics/StaticStrings.h"
|
#include "Basics/StaticStrings.h"
|
||||||
#include "Basics/StringRef.h"
|
#include "Basics/StringRef.h"
|
||||||
#include "Basics/VelocyPackHelper.h"
|
#include "Basics/VelocyPackHelper.h"
|
||||||
|
@ -2291,9 +2292,7 @@ TRI_voc_rid_t TRI_ExtractRevisionId(VPackSlice slice) {
|
||||||
|
|
||||||
VPackSlice r(slice.get(StaticStrings::RevString));
|
VPackSlice r(slice.get(StaticStrings::RevString));
|
||||||
if (r.isString()) {
|
if (r.isString()) {
|
||||||
VPackValueLength length;
|
return HybridLogicalClock::decodeTimeStamp(r.copyString());
|
||||||
char const* p = r.getString(length);
|
|
||||||
return arangodb::basics::StringUtils::uint64(p, static_cast<size_t>(length));
|
|
||||||
}
|
}
|
||||||
if (r.isInteger()) {
|
if (r.isInteger()) {
|
||||||
return r.getNumber<TRI_voc_rid_t>();
|
return r.getNumber<TRI_voc_rid_t>();
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// DISCLAIMER
|
||||||
|
///
|
||||||
|
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
|
||||||
|
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
|
||||||
|
///
|
||||||
|
/// 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
|
||||||
|
///
|
||||||
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
///
|
||||||
|
/// 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.
|
||||||
|
///
|
||||||
|
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||||
|
///
|
||||||
|
/// @author Max Neunhoeffer
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "Basics/HybridLogicalClock.h"
|
||||||
|
|
||||||
|
char arangodb::basics::HybridLogicalClock::encodeTable[65]
|
||||||
|
= "-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz";
|
||||||
|
|
||||||
|
char arangodb::basics::HybridLogicalClock::decodeTable[256]
|
||||||
|
= {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 0 - 15
|
||||||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 16 - 31
|
||||||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0,-1,-1, // 32 - 47
|
||||||
|
1, 2, 3, 4, 5, 6, 7, 8, 9,10,-1,-1,-1,-1,-1,-1, // 48 - 63
|
||||||
|
-1,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25, // 64 - 79
|
||||||
|
26,27,28,29,30,31,32,33,34,35,36,-1,-1,-1,-1,37, // 80 - 95
|
||||||
|
-1,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52, // 96 - 111
|
||||||
|
53,54,55,56,57,58,59,60,61,62,63,-1,-1,-1,-1,-1, // 112 - 127
|
||||||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 128 - 143
|
||||||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 144 - 159
|
||||||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 160 - 175
|
||||||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 176 - 191
|
||||||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 192 - 207
|
||||||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 208 - 223
|
||||||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 224 - 239
|
||||||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}; // 240 - 255
|
|
@ -24,8 +24,13 @@
|
||||||
#ifndef ARANGODB_BASICS_HYBRID_LOGICAL_CLOCK_H
|
#ifndef ARANGODB_BASICS_HYBRID_LOGICAL_CLOCK_H
|
||||||
#define ARANGODB_BASICS_HYBRID_LOGICAL_CLOCK_H 1
|
#define ARANGODB_BASICS_HYBRID_LOGICAL_CLOCK_H 1
|
||||||
|
|
||||||
|
#include "Basics/Common.h"
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
|
namespace arangodb {
|
||||||
|
namespace basics {
|
||||||
|
|
||||||
class HybridLogicalClock {
|
class HybridLogicalClock {
|
||||||
std::chrono::high_resolution_clock clock;
|
std::chrono::high_resolution_clock clock;
|
||||||
std::atomic<uint64_t> lastTimeStamp;
|
std::atomic<uint64_t> lastTimeStamp;
|
||||||
|
@ -87,6 +92,25 @@ class HybridLogicalClock {
|
||||||
return newTimeStamp;
|
return newTimeStamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string encodeTimeStamp(uint64_t t) {
|
||||||
|
std::string r(11, '\x00');
|
||||||
|
size_t pos = 11;
|
||||||
|
while (t > 0) {
|
||||||
|
r[--pos] = encodeTable[static_cast<uint8_t>(t & 0x3ful)];
|
||||||
|
t >>= 6;
|
||||||
|
}
|
||||||
|
return r.substr(pos, 11-pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t decodeTimeStamp(std::string const& s) {
|
||||||
|
uint64_t r = 0;
|
||||||
|
for (size_t i = 0; i < s.size(); i++) {
|
||||||
|
r = (r << 6) |
|
||||||
|
static_cast<uint8_t>(decodeTable[static_cast<uint8_t>(s[i])]);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Helper to get the physical time in milliseconds since the epoch:
|
// Helper to get the physical time in milliseconds since the epoch:
|
||||||
uint64_t getPhysicalTime() {
|
uint64_t getPhysicalTime() {
|
||||||
|
@ -108,6 +132,13 @@ class HybridLogicalClock {
|
||||||
return (time << 20) | count;
|
return (time << 20) | count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char encodeTable[65];
|
||||||
|
|
||||||
|
static char decodeTable[256];
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}; // namespace basics
|
||||||
|
}; // namespace arangodb
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -140,6 +140,7 @@ add_library(${LIB_ARANGO} STATIC
|
||||||
Basics/DataProtector.cpp
|
Basics/DataProtector.cpp
|
||||||
Basics/Exceptions.cpp
|
Basics/Exceptions.cpp
|
||||||
Basics/FileUtils.cpp
|
Basics/FileUtils.cpp
|
||||||
|
Basics/HybridLogicalClock.cpp
|
||||||
Basics/JsonHelper.cpp
|
Basics/JsonHelper.cpp
|
||||||
Basics/Mutex.cpp
|
Basics/Mutex.cpp
|
||||||
Basics/MutexLocker.cpp
|
Basics/MutexLocker.cpp
|
||||||
|
|
Loading…
Reference in New Issue