mirror of https://gitee.com/bigwinds/arangodb
fixed saving
This commit is contained in:
parent
2a9d071627
commit
adae2e7c67
|
@ -259,7 +259,6 @@ add_executable(${BIN_ARANGOD}
|
|||
VocBase/ExampleMatcher.cpp
|
||||
VocBase/Graphs.cpp
|
||||
VocBase/KeyGenerator.cpp
|
||||
VocBase/Legends.cpp
|
||||
VocBase/Shaper.cpp
|
||||
VocBase/Traverser.cpp
|
||||
VocBase/VocShaper.cpp
|
||||
|
|
|
@ -1923,6 +1923,7 @@ static void JS_InsertVocbaseVPack(
|
|||
auto transactionContext = std::make_shared<V8TransactionContext>(collection->_vocbase, true);
|
||||
|
||||
SingleCollectionTransaction trx(transactionContext, collection->_cid, TRI_TRANSACTION_WRITE);
|
||||
trx.addHint(TRI_TRANSACTION_HINT_SINGLE_OPERATION, false);
|
||||
|
||||
res = trx.begin();
|
||||
|
||||
|
|
|
@ -1,334 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// 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 "Legends.h"
|
||||
|
||||
using namespace arangodb;
|
||||
using namespace arangodb::basics;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Data format of a legend in memory:
|
||||
///
|
||||
/// Rough overview description:
|
||||
///
|
||||
/// - attribute-ID table
|
||||
/// - shape table
|
||||
/// - attribute-ID string data
|
||||
/// - padding to achieve 8-byte alignment
|
||||
/// - shape data
|
||||
/// - padding to achieve 8-byte alignment
|
||||
///
|
||||
/// Description of the attribute-ID table (actual binary types in
|
||||
/// [square brackets]):
|
||||
///
|
||||
/// - number of entries [TRI_shape_size_t]
|
||||
/// - each entry consists of:
|
||||
///
|
||||
/// - attribute ID (aid) [TRI_shape_aid_t]
|
||||
/// - offset to string value, measured from the beginning of the legend
|
||||
/// [TRI_shape_size_t]
|
||||
///
|
||||
/// The entries in the attribute-ID table are sorted by ascending order of
|
||||
/// shape IDs to allow for binary search if needed.
|
||||
///
|
||||
/// Description of the shape table:
|
||||
///
|
||||
/// - number of entries [TRI_shape_size_t]
|
||||
/// - each entry consists of:
|
||||
///
|
||||
/// - shape ID (sid) [TRI_shape_sid_t]
|
||||
/// - offset to shape data, measured from the beginning of the legend
|
||||
/// [TRI_shape_size_t]
|
||||
/// - size in bytes of the shape data for this shape ID [TRI_shape_size_t]
|
||||
///
|
||||
/// The entries in the shape table are sorted by ascending order of
|
||||
/// shape IDs to allow for binary search if needed.
|
||||
///
|
||||
/// The strings for the attribute IDs are stored one after another, each
|
||||
/// including a terminating zero byte. At the end of the string data follow
|
||||
/// zero bytes to pad to a total length that is divisible by 8.
|
||||
///
|
||||
/// The actual entries of the shape data is stored one after another. Alignment
|
||||
/// for each entry is automatically given by the length of the shape data. At
|
||||
/// the end there is padding to make the length of the total legend divisible
|
||||
/// by 8.
|
||||
///
|
||||
/// Note that the builtin shapes are never dumped and that proper legends
|
||||
/// contain all attribute IDs
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief clear all data to build a new legend, keep shaper
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void JsonLegend::clear() {
|
||||
_have_attribute.clear();
|
||||
_attribs.clear();
|
||||
_att_data.clear();
|
||||
_have_shape.clear();
|
||||
_shapes.clear();
|
||||
_shape_data.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief add an attribute ID to the legend
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int JsonLegend::addAttributeId(TRI_shape_aid_t aid) {
|
||||
auto it = _have_attribute.find(aid);
|
||||
|
||||
if (it != _have_attribute.end()) {
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
char const* p = _shaper->lookupAttributeId(aid);
|
||||
|
||||
if (nullptr == p) {
|
||||
return TRI_ERROR_AID_NOT_FOUND;
|
||||
}
|
||||
|
||||
_have_attribute.insert(it, aid);
|
||||
size_t len = strlen(p);
|
||||
_attribs.emplace_back(aid, _att_data.length());
|
||||
_att_data.appendText(p, len + 1); // including the zero byte
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief add a shape to the legend
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int JsonLegend::addShape(TRI_shape_sid_t sid, char const* data, uint32_t len) {
|
||||
// data and len must always be given, because in general we might have
|
||||
// to sniff recursively into the subobjects. :-(
|
||||
int res = TRI_ERROR_NO_ERROR;
|
||||
|
||||
TRI_ASSERT(data != nullptr);
|
||||
|
||||
TRI_shape_t const* shape = nullptr;
|
||||
|
||||
// First the trivial cases:
|
||||
if (sid < Shaper::firstCustomShapeId()) {
|
||||
shape = Shaper::lookupSidBasicShape(sid);
|
||||
|
||||
TRI_ASSERT(shape != nullptr);
|
||||
} else {
|
||||
shape = _shaper->lookupShapeId(sid);
|
||||
|
||||
if (nullptr == shape) {
|
||||
return TRI_ERROR_LEGEND_INCOMPLETE;
|
||||
}
|
||||
|
||||
auto it = _have_shape.find(sid);
|
||||
|
||||
if (it == _have_shape.end()) {
|
||||
_have_shape.insert(it, sid);
|
||||
Shape sh(sid, _shape_data.length(), shape->_size);
|
||||
_shapes.push_back(sh);
|
||||
_shape_data.appendText(reinterpret_cast<char const*>(shape),
|
||||
static_cast<size_t>(shape->_size));
|
||||
}
|
||||
}
|
||||
|
||||
// Now we have to add all attribute IDs and all shapes used by this
|
||||
// one recursively, note that the data of this object is in a
|
||||
// consistent state, such that we can call ourselves recursively.
|
||||
|
||||
if (shape->_type == TRI_SHAPE_HOMOGENEOUS_SIZED_LIST) {
|
||||
// Handle a homogeneous list with equal size entries. Note that
|
||||
// this does not imply that no subobject contains any array or
|
||||
// inhomogeneous list, because they could be lists that have the
|
||||
// same size by sheer coincidence. Therefore we have to visit them
|
||||
// all recursively. :-(
|
||||
auto shape_spec =
|
||||
reinterpret_cast<TRI_homogeneous_sized_list_shape_t const*>(shape);
|
||||
auto len = reinterpret_cast<TRI_shape_length_list_t const*>(data);
|
||||
auto ptr = reinterpret_cast<char const*>(len + 1);
|
||||
res = TRI_ERROR_NO_ERROR; // just in case the length is 0
|
||||
TRI_shape_length_list_t i;
|
||||
for (i = 0; i < *len; i++) {
|
||||
res = addShape(shape_spec->_sidEntry, ptr,
|
||||
static_cast<uint32_t>(shape_spec->_sizeEntry));
|
||||
ptr += shape_spec->_sizeEntry;
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (shape->_type == TRI_SHAPE_HOMOGENEOUS_LIST) {
|
||||
// Handle a homogeneous list: Only one sid, but the subobjects can
|
||||
// contain inhomogeneous lists.
|
||||
auto shape_spec =
|
||||
reinterpret_cast<TRI_homogeneous_list_shape_t const*>(shape);
|
||||
res = TRI_ERROR_NO_ERROR; // just in case the length is 0
|
||||
auto len = reinterpret_cast<TRI_shape_length_list_t const*>(data);
|
||||
auto offsets = reinterpret_cast<TRI_shape_size_t const*>(len + 1);
|
||||
TRI_shape_length_list_t i;
|
||||
for (i = 0; i < *len; i++) {
|
||||
res = addShape(shape_spec->_sidEntry, data + offsets[i],
|
||||
static_cast<uint32_t>(offsets[i + 1] - offsets[i]));
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (shape->_type == TRI_SHAPE_LIST) {
|
||||
// Handle an inhomogeneous list:
|
||||
// We have to scan recursively all entries of the list since they
|
||||
// contain sids in the data area.
|
||||
res = TRI_ERROR_NO_ERROR; // just in case the length is 0
|
||||
auto len = reinterpret_cast<TRI_shape_length_list_t const*>(data);
|
||||
auto sids = reinterpret_cast<TRI_shape_sid_t const*>(len + 1);
|
||||
auto offsets = reinterpret_cast<TRI_shape_size_t const*>(sids + *len);
|
||||
TRI_shape_length_list_t i;
|
||||
|
||||
for (i = 0; i < *len; i++) {
|
||||
res = addShape(sids[i], data + offsets[i],
|
||||
static_cast<uint32_t>(offsets[i + 1] - offsets[i]));
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (shape->_type == TRI_SHAPE_ARRAY) {
|
||||
// Handle an array:
|
||||
// Distinguish between fixed size subobjects and variable size
|
||||
// subobjects. The fixed ones cannot contain inhomogeneous lists.
|
||||
auto shape_spec = reinterpret_cast<TRI_array_shape_t const*>(shape);
|
||||
auto sids = reinterpret_cast<TRI_shape_sid_t const*>(shape_spec + 1);
|
||||
auto aids = reinterpret_cast<TRI_shape_aid_t const*>(
|
||||
sids + (shape_spec->_fixedEntries + shape_spec->_variableEntries));
|
||||
auto offsetsF = reinterpret_cast<TRI_shape_size_t const*>(
|
||||
aids + (shape_spec->_fixedEntries + shape_spec->_variableEntries));
|
||||
auto offsetsV = reinterpret_cast<TRI_shape_size_t const*>(data);
|
||||
|
||||
TRI_shape_size_t i;
|
||||
for (i = 0;
|
||||
res == TRI_ERROR_NO_ERROR &&
|
||||
i < shape_spec->_fixedEntries + shape_spec->_variableEntries;
|
||||
i++) {
|
||||
res = addAttributeId(aids[i]);
|
||||
}
|
||||
for (i = 0; res == TRI_ERROR_NO_ERROR && i < shape_spec->_fixedEntries;
|
||||
i++) {
|
||||
// Fixed size subdocs cannot have inhomogeneous lists as subdocs:
|
||||
res = addShape(sids[i], data + offsetsF[i],
|
||||
static_cast<uint32_t>(offsetsF[i + 1] - offsetsF[i]));
|
||||
}
|
||||
for (i = 0; res == TRI_ERROR_NO_ERROR && i < shape_spec->_variableEntries;
|
||||
i++) {
|
||||
addShape(sids[i + shape_spec->_fixedEntries], data + offsetsV[i],
|
||||
static_cast<uint32_t>(offsetsV[i + 1] - offsetsV[i]));
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief round a value to the next multiple of 8
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static inline TRI_shape_size_t roundup8(TRI_shape_size_t x) {
|
||||
return (x + 7) - ((x + 7) & 7);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get the total size in bytes of the legend
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
size_t JsonLegend::getSize() const {
|
||||
// Add string pool size and shape pool size and add space for header
|
||||
// and tables in bytes.
|
||||
return sizeof(TRI_shape_size_t) // number of aids
|
||||
+ sizeof(AttributeId) * _attribs.size() // aid entries
|
||||
+ sizeof(TRI_shape_size_t) // number of sids
|
||||
+ sizeof(Shape) * _shapes.size() // sid entries
|
||||
+ static_cast<size_t>(
|
||||
roundup8(_att_data.length())) // string data, padded
|
||||
+
|
||||
static_cast<size_t>(
|
||||
roundup8(_shape_data.length())); // shape data, padded
|
||||
}
|
||||
|
||||
JsonLegend::AttributeComparerClass JsonLegend::AttributeComparerObject;
|
||||
JsonLegend::ShapeComparerClass JsonLegend::ShapeComparerObject;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief dump the legend to the buffer pointed to by buf
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void JsonLegend::dump(void* buf) {
|
||||
// Dump the resulting legend to a given buffer.
|
||||
|
||||
// First sort the aids in ascending order:
|
||||
sort(_attribs.begin(), _attribs.end(), AttributeComparerObject);
|
||||
|
||||
// Then sort the sids in ascending order:
|
||||
sort(_shapes.begin(), _shapes.end(), ShapeComparerObject);
|
||||
|
||||
// Total length of table data to add to offsets:
|
||||
TRI_shape_size_t socle =
|
||||
sizeof(TRI_shape_size_t) + sizeof(AttributeId) * _attribs.size() +
|
||||
sizeof(TRI_shape_size_t) + sizeof(Shape) * _shapes.size();
|
||||
|
||||
// Attribute ID table:
|
||||
TRI_shape_size_t* p = reinterpret_cast<TRI_shape_size_t*>(buf);
|
||||
*p++ = _attribs.size();
|
||||
AttributeId* a = reinterpret_cast<AttributeId*>(p);
|
||||
for (size_t i = 0; i < _attribs.size(); i++) {
|
||||
_attribs[i].offset += socle;
|
||||
*a++ = _attribs[i];
|
||||
_attribs[i].offset -= socle;
|
||||
}
|
||||
|
||||
// Add the length of the string data to socle for second table:
|
||||
size_t const attDataLength = _att_data.length();
|
||||
socle += roundup8(attDataLength);
|
||||
|
||||
// shape table:
|
||||
size_t const n = _shapes.size();
|
||||
p = reinterpret_cast<TRI_shape_size_t*>(a);
|
||||
*p++ = n;
|
||||
Shape* s = reinterpret_cast<Shape*>(p);
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
_shapes[i].offset += socle;
|
||||
*s++ = _shapes[i];
|
||||
_shapes[i].offset -= socle;
|
||||
}
|
||||
|
||||
// Attribute ID string data:
|
||||
char* c = reinterpret_cast<char*>(s);
|
||||
memcpy(c, _att_data.c_str(), attDataLength);
|
||||
TRI_shape_size_t i = roundup8(attDataLength);
|
||||
if (i > attDataLength) {
|
||||
memset(c + attDataLength, 0, static_cast<size_t>(i) - attDataLength);
|
||||
}
|
||||
c += i;
|
||||
|
||||
// Shape data:
|
||||
size_t const shapeDataLength = _shape_data.length();
|
||||
memcpy(c, _shape_data.c_str(), shapeDataLength);
|
||||
i = roundup8(shapeDataLength);
|
||||
if (i > shapeDataLength) {
|
||||
memset(c + shapeDataLength, 0, static_cast<size_t>(i) - shapeDataLength);
|
||||
}
|
||||
}
|
|
@ -1,284 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// 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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ARANGOD_VOC_BASE_LEGENDS_H
|
||||
#define ARANGOD_VOC_BASE_LEGENDS_H 1
|
||||
|
||||
#include "Basics/Common.h"
|
||||
#include "Basics/structures.h"
|
||||
#include "Basics/StringBuffer.h"
|
||||
#include "VocBase/shaped-json.h"
|
||||
#include "VocBase/Shaper.h"
|
||||
|
||||
namespace arangodb {
|
||||
namespace basics {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief one entry in the table of attribute IDs
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct AttributeId {
|
||||
TRI_shape_aid_t aid;
|
||||
TRI_shape_size_t offset;
|
||||
|
||||
AttributeId(TRI_shape_aid_t a, TRI_shape_size_t o) : aid(a), offset(o) {}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief one entry in the table of shapes
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct Shape {
|
||||
TRI_shape_sid_t sid;
|
||||
TRI_shape_size_t offset;
|
||||
TRI_shape_size_t size;
|
||||
|
||||
Shape(TRI_shape_sid_t sid, TRI_shape_size_t o, TRI_shape_size_t siz)
|
||||
: sid(sid), offset(o), size(siz) {}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a legend for one or more shaped json objects
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class JsonLegend {
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief disable default constructor because we need a shaper
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
JsonLegend() = delete;
|
||||
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief constructor, taking a shaper
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
explicit JsonLegend(Shaper* shaper)
|
||||
: _shaper(shaper),
|
||||
_att_data(TRI_UNKNOWN_MEM_ZONE),
|
||||
_shape_data(TRI_UNKNOWN_MEM_ZONE) {}
|
||||
|
||||
~JsonLegend() {}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief clear all data and register a new shaper
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void reset(Shaper* shaper) {
|
||||
clear();
|
||||
_shaper = shaper;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief clear all data to build a new legend, keep shaper
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void clear();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief add an attribute ID to the legend
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int addAttributeId(TRI_shape_aid_t aid);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief add a shape to the legend
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int addShape(TRI_shaped_json_t const* sh_json) {
|
||||
return addShape(sh_json->_sid, sh_json->_data.data, sh_json->_data.length);
|
||||
}
|
||||
|
||||
int addShape(TRI_shape_sid_t sid, TRI_blob_t const* blob) {
|
||||
return addShape(sid, blob->data, blob->length);
|
||||
}
|
||||
|
||||
int addShape(TRI_shape_sid_t sid, char const* data, uint32_t len);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get the total size in bytes of the legend
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
size_t getSize() const;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief dump the legend to the buffer pointed to by buf
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void dump(void* buf);
|
||||
|
||||
private:
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief the underlying shaper
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Shaper* _shaper;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief used to sort attribute ID table by attribute ID
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static struct AttributeComparerClass {
|
||||
bool operator()(AttributeId const& a, AttributeId const& b) {
|
||||
return a.aid < b.aid;
|
||||
}
|
||||
} AttributeComparerObject;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief used to sort shapes by shape ID
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static struct ShapeComparerClass {
|
||||
bool operator()(Shape const& a, Shape const& b) { return a.sid < b.sid; }
|
||||
} ShapeComparerObject;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief remember which aids we already have
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::unordered_set<TRI_shape_aid_t> _have_attribute;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief table of attribute IDs
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::vector<AttributeId> _attribs;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief here we collect the string data for the attributes
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
StringBuffer _att_data;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief remember which sids we already have
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::unordered_set<TRI_shape_sid_t> _have_shape;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief table of shapes
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::vector<Shape> _shapes;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief here we collect the actual shape data
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
StringBuffer _shape_data;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief a class to read a legend
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class LegendReader : public Shaper {
|
||||
// This inherits from Shaper, note however, that at least
|
||||
// for the time being it only implements lookupAttributeId and
|
||||
// lookupShapeId.
|
||||
|
||||
char const* _legend;
|
||||
TRI_shape_size_t _numberAttributes;
|
||||
AttributeId const* _aids;
|
||||
TRI_shape_size_t _numberShapes;
|
||||
Shape const* _shapes;
|
||||
|
||||
public:
|
||||
explicit LegendReader(char const* l) : Shaper(), _legend(l) {
|
||||
auto p = reinterpret_cast<TRI_shape_size_t const*>(l);
|
||||
_numberAttributes = *p++;
|
||||
_aids = reinterpret_cast<AttributeId const*>(p);
|
||||
p = reinterpret_cast<TRI_shape_size_t const*>(_aids + _numberAttributes);
|
||||
_numberShapes = *p++;
|
||||
_shapes = reinterpret_cast<Shape const*>(p);
|
||||
}
|
||||
|
||||
~LegendReader() {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
char const* lookupAttributeId(TRI_shape_aid_t aid) override final {
|
||||
// binary search in AttributeIds
|
||||
TRI_shape_size_t low = 0;
|
||||
TRI_shape_size_t high = _numberAttributes;
|
||||
TRI_shape_size_t mid;
|
||||
|
||||
while (low < high) {
|
||||
// at the beginning of the loop we always have:
|
||||
// 0 <= low < high <= _numberAttributes
|
||||
// thus 0 <= mid < _numberAttributes, so access is allowed
|
||||
// and for ind (index of element to be found):
|
||||
// low <= ind <= high
|
||||
// Once low == high, we have either found it or found nothing
|
||||
mid = (low + high) / 2;
|
||||
if (_aids[mid].aid < aid) {
|
||||
low = mid + 1;
|
||||
} else { // Note: aids[mid].aid == aid possible,
|
||||
// thus ind == high possible as well
|
||||
high = mid;
|
||||
}
|
||||
}
|
||||
if (low == high && high < _numberAttributes && _aids[low].aid == aid) {
|
||||
return _legend + _aids[low].offset;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TRI_shape_t const* lookupShapeId(TRI_shape_sid_t sid) override final {
|
||||
// Is it a builtin basic one?
|
||||
if (sid < Shaper::firstCustomShapeId()) {
|
||||
return Shaper::lookupSidBasicShape(sid);
|
||||
}
|
||||
|
||||
// binary search in Shapes
|
||||
TRI_shape_size_t low = 0;
|
||||
TRI_shape_size_t high = _numberShapes;
|
||||
TRI_shape_size_t mid;
|
||||
|
||||
while (low < high) {
|
||||
// at the beginning of the loop we always have:
|
||||
// 0 <= low < high <= _numberShapes
|
||||
// thus 0 <= mid < _numberShapes, so access is allowed
|
||||
// and for ind (index of element to be found):
|
||||
// low <= ind <= high
|
||||
// Once low == high, we have either found it or found nothing
|
||||
mid = (low + high) / 2;
|
||||
if (_shapes[mid].sid < sid) {
|
||||
low = mid + 1;
|
||||
} else { // Note: _shapes[mid].sid == sid possible,
|
||||
// thus ind == high possible as well
|
||||
high = mid;
|
||||
}
|
||||
}
|
||||
if (low == high && high < _numberShapes && _shapes[low].sid == sid) {
|
||||
return reinterpret_cast<TRI_shape_t const*>(_legend +
|
||||
_shapes[low].offset);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -409,7 +409,7 @@ static bool CheckCollection(TRI_collection_t* collection, bool ignoreErrors) {
|
|||
char* ptr = datafile->_data;
|
||||
|
||||
// skip the datafile header
|
||||
ptr += TRI_DF_ALIGN_BLOCK(sizeof(TRI_df_header_marker_t));
|
||||
ptr += AlignedSize<size_t>(sizeof(TRI_df_header_marker_t));
|
||||
cm = (TRI_col_header_marker_t*)ptr;
|
||||
|
||||
if (cm->base._type != TRI_COL_MARKER_HEADER) {
|
||||
|
|
|
@ -172,14 +172,6 @@ struct compaction_info_t {
|
|||
bool _keepDeletions;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return a marker's size
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static inline int64_t AlignedSize(TRI_df_marker_t const* marker) {
|
||||
return static_cast<int64_t>(TRI_DF_ALIGN_BLOCK(marker->_size));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief creates a compactor file, based on a datafile
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -412,7 +404,7 @@ static bool Compactifier(TRI_df_marker_t const* marker, void* data,
|
|||
if (deleted) {
|
||||
// found a dead document
|
||||
context->_dfi.numberDead++;
|
||||
context->_dfi.sizeDead += AlignedSize(marker);
|
||||
context->_dfi.sizeDead += AlignedMarkerSize<int64_t>(marker);
|
||||
LOG_TOPIC(TRACE, Logger::COMPACTOR) << "found a stale document: " << key;
|
||||
return true;
|
||||
}
|
||||
|
@ -441,7 +433,7 @@ static bool Compactifier(TRI_df_marker_t const* marker, void* data,
|
|||
}
|
||||
|
||||
context->_dfi.numberAlive++;
|
||||
context->_dfi.sizeAlive += AlignedSize(marker);
|
||||
context->_dfi.sizeAlive += AlignedMarkerSize<int64_t>(marker);
|
||||
}
|
||||
|
||||
// deletions
|
||||
|
@ -564,13 +556,13 @@ static bool CalculateSize(TRI_df_marker_t const* marker, void* data,
|
|||
}
|
||||
|
||||
context->_keepDeletions = true;
|
||||
context->_targetSize += AlignedSize(marker);
|
||||
context->_targetSize += AlignedMarkerSize<int64_t>(marker);
|
||||
}
|
||||
|
||||
// deletions
|
||||
else if (marker->_type == TRI_DOC_MARKER_KEY_DELETION &&
|
||||
context->_keepDeletions) {
|
||||
context->_targetSize += AlignedSize(marker);
|
||||
context->_targetSize += AlignedMarkerSize<int64_t>(marker);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -543,7 +543,7 @@ static TRI_df_scan_t ScanDatafile(TRI_datafile_t const* datafile) {
|
|||
|
||||
entry._position = (TRI_voc_size_t)(ptr - datafile->_data);
|
||||
entry._size = marker->_size;
|
||||
entry._realSize = TRI_DF_ALIGN_BLOCK(marker->_size);
|
||||
entry._realSize = AlignedMarkerSize<size_t>(marker);
|
||||
entry._tick = marker->_tick;
|
||||
entry._type = marker->_type;
|
||||
entry._status = 1;
|
||||
|
@ -630,7 +630,7 @@ static TRI_df_scan_t ScanDatafile(TRI_datafile_t const* datafile) {
|
|||
|
||||
TRI_PushBackVector(&scan._entries, &entry);
|
||||
|
||||
size = TRI_DF_ALIGN_BLOCK(marker->_size);
|
||||
size = AlignedMarkerSize<size_t>(marker);
|
||||
currentSize += (TRI_voc_size_t)size;
|
||||
|
||||
if (marker->_type == TRI_DF_MARKER_FOOTER) {
|
||||
|
@ -758,8 +758,8 @@ static bool TryRepairDatafile(TRI_datafile_t* datafile) {
|
|||
}
|
||||
}
|
||||
|
||||
size_t size = TRI_DF_ALIGN_BLOCK(marker->_size);
|
||||
currentSize += (TRI_voc_size_t)size;
|
||||
size_t size = AlignedMarkerSize<TRI_voc_size_t>(marker);
|
||||
currentSize += size;
|
||||
|
||||
if (marker->_type == TRI_DF_MARKER_FOOTER) {
|
||||
return true;
|
||||
|
@ -975,8 +975,8 @@ static bool CheckDatafile(TRI_datafile_t* datafile, bool ignoreFailures) {
|
|||
maxTick = marker->_tick;
|
||||
}
|
||||
|
||||
size_t size = TRI_DF_ALIGN_BLOCK(marker->_size);
|
||||
currentSize += (TRI_voc_size_t)size;
|
||||
size_t size = AlignedMarkerSize<size_t>(marker);
|
||||
currentSize += size;
|
||||
|
||||
if (marker->_type == TRI_DF_MARKER_FOOTER) {
|
||||
LOG(DEBUG) << "found footer, reached end of datafile '" << datafile->getName(datafile) << "', current size " << currentSize;
|
||||
|
@ -1537,7 +1537,7 @@ int TRI_ReserveElementDatafile(TRI_datafile_t* datafile, TRI_voc_size_t size,
|
|||
TRI_df_marker_t** position,
|
||||
TRI_voc_size_t maximalJournalSize) {
|
||||
*position = nullptr;
|
||||
size = TRI_DF_ALIGN_BLOCK(size);
|
||||
size = AlignedSize<TRI_voc_size_t>(size);
|
||||
|
||||
if (datafile->_state != TRI_DF_STATE_WRITE) {
|
||||
if (datafile->_state == TRI_DF_STATE_READ) {
|
||||
|
@ -1723,8 +1723,7 @@ bool TRI_IterateDatafile(TRI_datafile_t* datafile,
|
|||
}
|
||||
|
||||
while (ptr < end) {
|
||||
TRI_df_marker_t const* marker =
|
||||
reinterpret_cast<TRI_df_marker_t const*>(ptr);
|
||||
auto const* marker = reinterpret_cast<TRI_df_marker_t const*>(ptr);
|
||||
|
||||
if (marker->_size == 0) {
|
||||
return true;
|
||||
|
@ -1737,8 +1736,7 @@ bool TRI_IterateDatafile(TRI_datafile_t* datafile,
|
|||
return false;
|
||||
}
|
||||
|
||||
size_t size = TRI_DF_ALIGN_BLOCK(marker->_size);
|
||||
ptr += size;
|
||||
ptr += AlignedMarkerSize<size_t>(marker);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -89,13 +89,7 @@ struct TRI_datafile_t;
|
|||
/// @brief datafile version
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define TRI_DF_VERSION (1)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief alignment in datafile blocks
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define TRI_DF_BLOCK_ALIGNMENT (8)
|
||||
#define TRI_DF_VERSION (2)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief maximum size of a single marker (in bytes)
|
||||
|
@ -546,12 +540,23 @@ char const* TRI_NameMarkerDatafile(TRI_df_marker_t const*);
|
|||
void TRI_InitMarkerDatafile(char*, TRI_df_marker_type_e, TRI_voc_size_t);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief aligns in datafile blocks
|
||||
/// @brief returns the 8-byte aligned size for the value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define TRI_DF_ALIGN_BLOCK(a) \
|
||||
((((a) + TRI_DF_BLOCK_ALIGNMENT - 1) / TRI_DF_BLOCK_ALIGNMENT) * \
|
||||
TRI_DF_BLOCK_ALIGNMENT)
|
||||
template <typename T>
|
||||
static inline T AlignedSize(T value) {
|
||||
return (value + 7) - ((value + 7) & 7);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns the 8-byte aligned size for the marker
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename T>
|
||||
static inline T AlignedMarkerSize(TRI_df_marker_t const* marker) {
|
||||
size_t value = marker->_size;
|
||||
return static_cast<T>((value + 7) - ((value + 7) & 7));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns the marker-specific offset to the vpack payload
|
||||
|
|
|
@ -817,11 +817,11 @@ static int OpenIteratorHandleDocumentMarker(TRI_df_marker_t const* marker,
|
|||
TRI_document_collection_t* document = state->_document;
|
||||
arangodb::Transaction* trx = state->_trx;
|
||||
|
||||
VPackSlice const slice(reinterpret_cast<char const*>(marker + sizeof(arangodb::wal::vpack_document_marker_t)));
|
||||
VPackSlice const slice(reinterpret_cast<char const*>(marker) + VPackOffset(TRI_WAL_MARKER_VPACK_DOCUMENT));
|
||||
VPackSlice const keySlice = slice.get(TRI_VOC_ATTRIBUTE_KEY);
|
||||
std::string const key(keySlice.copyString());
|
||||
TRI_voc_rid_t const rid = std::stoull(slice.get(TRI_VOC_ATTRIBUTE_REV).copyString());
|
||||
|
||||
|
||||
SetRevision(document, rid, false);
|
||||
document->_keyGenerator->track(key);
|
||||
|
||||
|
@ -858,7 +858,7 @@ static int OpenIteratorHandleDocumentMarker(TRI_df_marker_t const* marker,
|
|||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
document->_masterPointers.release(header, true); // ONLY IN OPENITERATOR
|
||||
LOG(ERR) << "inserting document into indexes failed with error: " << TRI_errno_string(res);
|
||||
LOG(ERR) << "inserting document into primary index failed with error: " << TRI_errno_string(res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -867,7 +867,7 @@ static int OpenIteratorHandleDocumentMarker(TRI_df_marker_t const* marker,
|
|||
|
||||
// update the datafile info
|
||||
state->_dfi->numberAlive++;
|
||||
state->_dfi->sizeAlive += (int64_t)TRI_DF_ALIGN_BLOCK(marker->_size);
|
||||
state->_dfi->sizeAlive += AlignedMarkerSize<int64_t>(marker);
|
||||
}
|
||||
|
||||
// it is an update, but only if found has a smaller revision identifier
|
||||
|
@ -877,9 +877,9 @@ static int OpenIteratorHandleDocumentMarker(TRI_df_marker_t const* marker,
|
|||
TRI_doc_mptr_t oldData = *found;
|
||||
|
||||
// update the header info
|
||||
found->_rid = rid;
|
||||
found->_fid = fid;
|
||||
found->setDataPtr(marker);
|
||||
found->_rid = rid;
|
||||
|
||||
document->_masterPointers.moveBack(found, &oldData); // ONLY IN OPENITERATOR
|
||||
|
||||
|
@ -892,17 +892,16 @@ static int OpenIteratorHandleDocumentMarker(TRI_df_marker_t const* marker,
|
|||
}
|
||||
|
||||
if (oldData.getDataPtr() != nullptr) {
|
||||
int64_t size = (int64_t)((TRI_df_marker_t const*)oldData.getDataPtr())
|
||||
->_size; // ONLY IN OPENITERATOR, PROTECTED by RUNTIME
|
||||
int64_t size = static_cast<int64_t>(oldData.getMarkerPtr()->_size);
|
||||
|
||||
dfi->numberAlive--;
|
||||
dfi->sizeAlive -= TRI_DF_ALIGN_BLOCK(size);
|
||||
dfi->sizeAlive -= AlignedSize<int64_t>(size);
|
||||
dfi->numberDead++;
|
||||
dfi->sizeDead += TRI_DF_ALIGN_BLOCK(size);
|
||||
dfi->sizeDead += AlignedSize<int64_t>(size);
|
||||
}
|
||||
|
||||
state->_dfi->numberAlive++;
|
||||
state->_dfi->sizeAlive += (int64_t)TRI_DF_ALIGN_BLOCK(marker->_size);
|
||||
state->_dfi->sizeAlive += AlignedMarkerSize<int64_t>(marker);
|
||||
}
|
||||
|
||||
// it is a stale update
|
||||
|
@ -910,9 +909,7 @@ static int OpenIteratorHandleDocumentMarker(TRI_df_marker_t const* marker,
|
|||
TRI_ASSERT(found->getDataPtr() != nullptr);
|
||||
|
||||
state->_dfi->numberDead++;
|
||||
state->_dfi->sizeDead += (int64_t)TRI_DF_ALIGN_BLOCK(
|
||||
((TRI_df_marker_t*)found->getDataPtr())
|
||||
->_size); // ONLY IN OPENITERATOR, PROTECTED by RUNTIME
|
||||
state->_dfi->sizeDead += AlignedSize<int64_t>(found->getMarkerPtr()->_size);
|
||||
}
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
|
@ -928,11 +925,11 @@ static int OpenIteratorHandleDeletionMarker(TRI_df_marker_t const* marker,
|
|||
TRI_document_collection_t* document = state->_document;
|
||||
arangodb::Transaction* trx = state->_trx;
|
||||
|
||||
VPackSlice const slice(reinterpret_cast<char const*>(marker + sizeof(arangodb::wal::vpack_remove_marker_t)));
|
||||
VPackSlice const slice(reinterpret_cast<char const*>(marker) + VPackOffset(TRI_WAL_MARKER_VPACK_REMOVE));
|
||||
VPackSlice const keySlice = slice.get(TRI_VOC_ATTRIBUTE_KEY);
|
||||
std::string const key(keySlice.copyString());
|
||||
TRI_voc_rid_t const rid = std::stoull(slice.get(TRI_VOC_ATTRIBUTE_REV).copyString());
|
||||
|
||||
|
||||
SetRevision(document, rid, false);
|
||||
document->_keyGenerator->track(key);
|
||||
|
||||
|
@ -966,16 +963,14 @@ static int OpenIteratorHandleDeletionMarker(TRI_df_marker_t const* marker,
|
|||
dfi = FindDatafileStats(state, found->_fid);
|
||||
}
|
||||
|
||||
TRI_ASSERT(found->getDataPtr() !=
|
||||
nullptr); // ONLY IN OPENITERATOR, PROTECTED by RUNTIME
|
||||
TRI_ASSERT(found->getDataPtr() != nullptr);
|
||||
|
||||
int64_t size = (int64_t)((TRI_df_marker_t*)found->getDataPtr())
|
||||
->_size; // ONLY IN OPENITERATOR, PROTECTED by RUNTIME
|
||||
int64_t size = AlignedSize<int64_t>(found->getMarkerPtr()->_size);
|
||||
|
||||
dfi->numberAlive--;
|
||||
dfi->sizeAlive -= TRI_DF_ALIGN_BLOCK(size);
|
||||
dfi->sizeAlive -= AlignedSize<int64_t>(size);
|
||||
dfi->numberDead++;
|
||||
dfi->sizeDead += TRI_DF_ALIGN_BLOCK(size);
|
||||
dfi->sizeDead += AlignedSize<int64_t>(size);
|
||||
state->_dfi->numberDeletions++;
|
||||
|
||||
DeletePrimaryIndex(trx, document, found, false);
|
||||
|
@ -1000,8 +995,6 @@ static bool OpenIterator(TRI_df_marker_t const* marker, void* data,
|
|||
|
||||
int res;
|
||||
|
||||
LOG(INFO) << "scanning " << TRI_NameMarkerDatafile(marker);
|
||||
|
||||
if (marker->_type == TRI_WAL_MARKER_VPACK_DOCUMENT) {
|
||||
res = OpenIteratorHandleDocumentMarker(marker, datafile,
|
||||
static_cast<open_iterator_state_t*>(data));
|
||||
|
|
|
@ -90,6 +90,14 @@ struct TRI_doc_mptr_t {
|
|||
_dataptr = that._dataptr;
|
||||
_hash = that._hash;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return a pointer to the beginning of the marker
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline struct TRI_df_marker_t const* getMarkerPtr() const {
|
||||
return static_cast<TRI_df_marker_t const*>(_dataptr);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return a pointer to the beginning of the marker
|
||||
|
|
|
@ -41,12 +41,12 @@ static inline size_t GetBlockSize(size_t blockNumber) {
|
|||
|
||||
if (blockNumber < 8) {
|
||||
// use a small block size in the beginning to save memory
|
||||
return (size_t)(BLOCK_SIZE_UNIT << blockNumber);
|
||||
return static_cast<size_t>(BLOCK_SIZE_UNIT << blockNumber);
|
||||
}
|
||||
|
||||
// use a block size of 32768
|
||||
// this will use 32768 * sizeof(TRI_doc_mptr_t) bytes, i.e. 1.5 MB
|
||||
return (size_t)(BLOCK_SIZE_UNIT << 8);
|
||||
return static_cast<size_t>(BLOCK_SIZE_UNIT << 8);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -99,15 +99,11 @@ void TRI_headers_t::moveBack(TRI_doc_mptr_t* header, TRI_doc_mptr_t const* old)
|
|||
TRI_ASSERT(old->getDataPtr() !=
|
||||
nullptr); // ONLY IN HEADERS, PROTECTED by RUNTIME
|
||||
|
||||
int64_t newSize =
|
||||
(int64_t)(((TRI_df_marker_t*)header->getDataPtr())
|
||||
->_size); // ONLY IN HEADERS, PROTECTED by RUNTIME
|
||||
int64_t oldSize =
|
||||
(int64_t)(((TRI_df_marker_t*)old->getDataPtr())
|
||||
->_size); // ONLY IN HEADERS, PROTECTED by RUNTIME
|
||||
int64_t newSize = static_cast<int64_t>(header->getMarkerPtr()->_size);
|
||||
int64_t oldSize = static_cast<int64_t>(old->getMarkerPtr()->_size);
|
||||
|
||||
// we must adjust the size of the collection
|
||||
_totalSize += (TRI_DF_ALIGN_BLOCK(newSize) - TRI_DF_ALIGN_BLOCK(oldSize));
|
||||
_totalSize += (AlignedSize<int64_t>(newSize) - AlignedSize<int64_t>(oldSize));
|
||||
|
||||
TRI_ASSERT(_totalSize > 0);
|
||||
}
|
||||
|
@ -123,26 +119,19 @@ void TRI_headers_t::move(TRI_doc_mptr_t* header, TRI_doc_mptr_t const* old) {
|
|||
}
|
||||
|
||||
TRI_ASSERT(_nrAllocated > 0);
|
||||
TRI_ASSERT(header->getDataPtr() !=
|
||||
nullptr); // ONLY IN HEADERS, PROTECTED by RUNTIME
|
||||
TRI_ASSERT(((TRI_df_marker_t*)header->getDataPtr())->_size >
|
||||
0); // ONLY IN HEADERS, PROTECTED by RUNTIME
|
||||
TRI_ASSERT(header->getDataPtr() != nullptr);
|
||||
TRI_ASSERT(header->getMarkerPtr()->_size > 0);
|
||||
TRI_ASSERT(old != nullptr);
|
||||
TRI_ASSERT(old->getDataPtr() !=
|
||||
nullptr); // ONLY IN HEADERS, PROTECTED by RUNTIME
|
||||
TRI_ASSERT(old->getDataPtr() != nullptr);
|
||||
|
||||
int64_t newSize =
|
||||
(int64_t)(((TRI_df_marker_t*)header->getDataPtr())
|
||||
->_size); // ONLY IN HEADERS, PROTECTED by RUNTIME
|
||||
int64_t oldSize =
|
||||
(int64_t)(((TRI_df_marker_t*)old->getDataPtr())
|
||||
->_size); // ONLY IN HEADERS, PROTECTED by RUNTIME
|
||||
int64_t newSize = static_cast<int64_t>(header->getMarkerPtr()->_size);
|
||||
int64_t oldSize = static_cast<int64_t>(old->getMarkerPtr()->_size);
|
||||
|
||||
// Please note the following: This operation is only used to revert an
|
||||
// update operation. The "new" document is removed again and the "old"
|
||||
// one is used once more. Therefore, the signs in the following statement
|
||||
// are actually OK:
|
||||
_totalSize -= (TRI_DF_ALIGN_BLOCK(newSize) - TRI_DF_ALIGN_BLOCK(oldSize));
|
||||
_totalSize -= (AlignedSize<int64_t>(newSize) - AlignedSize<int64_t>(oldSize));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -151,16 +140,14 @@ void TRI_headers_t::move(TRI_doc_mptr_t* header, TRI_doc_mptr_t const* old) {
|
|||
|
||||
void TRI_headers_t::unlink(TRI_doc_mptr_t* header) {
|
||||
TRI_ASSERT(header != nullptr);
|
||||
TRI_ASSERT(header->getDataPtr() !=
|
||||
nullptr); // ONLY IN HEADERS, PROTECTED by RUNTIME
|
||||
TRI_ASSERT(header->getDataPtr() != nullptr);
|
||||
|
||||
int64_t size = (int64_t)((TRI_df_marker_t*)header->getDataPtr())
|
||||
->_size; // ONLY IN HEADERS, PROTECTED by RUNTIME
|
||||
int64_t size = static_cast<int64_t>(header->getMarkerPtr()->_size);
|
||||
TRI_ASSERT(size > 0);
|
||||
|
||||
TRI_ASSERT(_nrLinked > 0);
|
||||
_nrLinked--;
|
||||
_totalSize -= TRI_DF_ALIGN_BLOCK(size);
|
||||
_totalSize -= AlignedSize<int64_t>(size);
|
||||
|
||||
if (_nrLinked == 0) {
|
||||
TRI_ASSERT(_totalSize == 0);
|
||||
|
@ -179,16 +166,13 @@ void TRI_headers_t::relink(TRI_doc_mptr_t* header, TRI_doc_mptr_t const* old) {
|
|||
return;
|
||||
}
|
||||
|
||||
TRI_ASSERT(header->getDataPtr() !=
|
||||
nullptr); // ONLY IN HEADERS, PROTECTED by RUNTIME
|
||||
|
||||
int64_t size = (int64_t)((TRI_df_marker_t*)header->getDataPtr())
|
||||
->_size; // ONLY IN HEADERS, PROTECTED by RUNTIME
|
||||
TRI_ASSERT(header->getDataPtr() != nullptr);
|
||||
int64_t size = static_cast<int64_t>(header->getMarkerPtr()->_size);
|
||||
TRI_ASSERT(size > 0);
|
||||
|
||||
this->move(header, old);
|
||||
_nrLinked++;
|
||||
_totalSize += TRI_DF_ALIGN_BLOCK(size);
|
||||
_totalSize += AlignedSize<int64_t>(size);
|
||||
TRI_ASSERT(_totalSize > 0);
|
||||
}
|
||||
|
||||
|
@ -245,7 +229,7 @@ TRI_doc_mptr_t* TRI_headers_t::request(size_t size) {
|
|||
|
||||
_nrAllocated++;
|
||||
_nrLinked++;
|
||||
_totalSize += (int64_t)TRI_DF_ALIGN_BLOCK(size);
|
||||
_totalSize += AlignedSize<int64_t>(size);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -294,7 +278,6 @@ void TRI_headers_t::release(TRI_doc_mptr_t* header, bool unlinkHeader) {
|
|||
void TRI_headers_t::adjustTotalSize(int64_t oldSize, int64_t newSize) {
|
||||
// oldSize = size of marker in WAL
|
||||
// newSize = size of marker in datafile
|
||||
|
||||
_totalSize -= (TRI_DF_ALIGN_BLOCK(oldSize) - TRI_DF_ALIGN_BLOCK(newSize));
|
||||
_totalSize -= (AlignedSize<int64_t>(oldSize) - AlignedSize<int64_t>(newSize));
|
||||
}
|
||||
|
||||
|
|
|
@ -867,7 +867,7 @@ static int DumpCollection(TRI_replication_dump_t* dump,
|
|||
break;
|
||||
}
|
||||
|
||||
ptr += TRI_DF_ALIGN_BLOCK(marker->_size);
|
||||
ptr += AlignedMarkerSize<size_t>(marker);
|
||||
|
||||
if (marker->_type == TRI_DF_MARKER_BLANK) {
|
||||
// fully ignore these marker types. they don't need to be replicated,
|
||||
|
@ -1051,7 +1051,7 @@ int TRI_DumpLogReplication(
|
|||
break;
|
||||
}
|
||||
|
||||
ptr += TRI_DF_ALIGN_BLOCK(marker->_size);
|
||||
ptr += AlignedMarkerSize<size_t>(marker);
|
||||
|
||||
// get the marker's tick and check whether we should include it
|
||||
TRI_voc_tick_t foundTick = marker->_tick;
|
||||
|
@ -1180,7 +1180,7 @@ int TRI_DetermineOpenTransactionsReplication(TRI_replication_dump_t* dump,
|
|||
break;
|
||||
}
|
||||
|
||||
ptr += TRI_DF_ALIGN_BLOCK(marker->_size);
|
||||
ptr += AlignedMarkerSize<size_t>(marker);
|
||||
|
||||
// get the marker's tick and check whether we should include it
|
||||
TRI_voc_tick_t foundTick = marker->_tick;
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#include "Basics/tri-strings.h"
|
||||
#include "Basics/vector.h"
|
||||
#include "Basics/VelocyPackHelper.h"
|
||||
#include "VocBase/Legends.h"
|
||||
#include "VocBase/VocShaper.h"
|
||||
|
||||
// #define DEBUG_JSON_SHAPER 1
|
||||
|
@ -2592,6 +2591,3 @@ void TRI_PrintShapeValues(TRI_shape_value_t* values, size_t n) {
|
|||
|
||||
template bool TRI_StringifyArrayShapedJson<VocShaper>(
|
||||
VocShaper*, struct TRI_string_buffer_t*, TRI_shaped_json_t const*, bool);
|
||||
template bool TRI_StringifyArrayShapedJson<arangodb::basics::LegendReader>(
|
||||
arangodb::basics::LegendReader*, struct TRI_string_buffer_t*,
|
||||
TRI_shaped_json_t const*, bool);
|
||||
|
|
|
@ -208,11 +208,10 @@ static void FreeOperations(TRI_transaction_t* trx) {
|
|||
auto it2 = stats.find(fid);
|
||||
|
||||
if (it2 == stats.end()) {
|
||||
stats.emplace(fid,
|
||||
std::make_pair(1, TRI_DF_ALIGN_BLOCK(marker->_size)));
|
||||
stats.emplace(fid, std::make_pair(1, AlignedMarkerSize<int64_t>(marker)));
|
||||
} else {
|
||||
(*it2).second.first++;
|
||||
(*it2).second.second += TRI_DF_ALIGN_BLOCK(marker->_size);
|
||||
(*it2).second.second += AlignedMarkerSize<int64_t>(marker);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1141,8 +1140,7 @@ int TRI_AddOperationTransaction(TRI_transaction_t* trx,
|
|||
TRI_df_marker_t const* marker = static_cast<TRI_df_marker_t const*>(
|
||||
operation.oldHeader.getDataPtr()); // PROTECTED by trx from above
|
||||
document->_datafileStatistics.increaseDead(
|
||||
operation.oldHeader._fid, 1,
|
||||
static_cast<int64_t>(TRI_DF_ALIGN_BLOCK(marker->_size)));
|
||||
operation.oldHeader._fid, 1, AlignedMarkerSize<int64_t>(marker));
|
||||
}
|
||||
} else {
|
||||
// operation is buffered and might be rolled back
|
||||
|
|
|
@ -163,12 +163,12 @@ static bool ScanMarker(TRI_df_marker_t const* marker, void* data,
|
|||
case TRI_DF_MARKER_PROLOGUE: {
|
||||
auto const* m = reinterpret_cast<TRI_df_prologue_marker_t const*>(marker);
|
||||
state->resetCollection(m->_databaseId, m->_collectionId);
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
|
||||
case TRI_WAL_MARKER_VPACK_DOCUMENT: {
|
||||
TRI_voc_tick_t databaseId = state->lastDatabaseId;
|
||||
TRI_voc_cid_t collectionId = state->lastCollectionId;
|
||||
TRI_voc_tick_t const databaseId = state->lastDatabaseId;
|
||||
TRI_voc_cid_t const collectionId = state->lastCollectionId;
|
||||
TRI_ASSERT(databaseId > 0);
|
||||
TRI_ASSERT(collectionId > 0);
|
||||
|
||||
|
@ -196,8 +196,8 @@ static bool ScanMarker(TRI_df_marker_t const* marker, void* data,
|
|||
}
|
||||
|
||||
case TRI_WAL_MARKER_VPACK_REMOVE: {
|
||||
TRI_voc_tick_t databaseId = state->lastDatabaseId;
|
||||
TRI_voc_cid_t collectionId = state->lastCollectionId;
|
||||
TRI_voc_tick_t const databaseId = state->lastDatabaseId;
|
||||
TRI_voc_cid_t const collectionId = state->lastCollectionId;
|
||||
TRI_ASSERT(databaseId > 0);
|
||||
TRI_ASSERT(collectionId > 0);
|
||||
|
||||
|
@ -231,7 +231,7 @@ static bool ScanMarker(TRI_df_marker_t const* marker, void* data,
|
|||
|
||||
case TRI_WAL_MARKER_VPACK_ABORT_TRANSACTION: {
|
||||
VPackSlice const slice(p + sizeof(TRI_df_marker_t));
|
||||
TRI_voc_tid_t tid = NumericValue<TRI_voc_tid_t>(slice, "tid");
|
||||
TRI_voc_tid_t const tid = NumericValue<TRI_voc_tid_t>(slice, "tid");
|
||||
|
||||
// note which abort markers we found
|
||||
state->handledTransactions.emplace(tid);
|
||||
|
@ -240,42 +240,42 @@ static bool ScanMarker(TRI_df_marker_t const* marker, void* data,
|
|||
|
||||
case TRI_WAL_MARKER_CREATE_COLLECTION: {
|
||||
VPackSlice const slice(p + sizeof(TRI_df_marker_t));
|
||||
TRI_voc_tid_t cid = NumericValue<TRI_voc_cid_t>(slice, "cid");
|
||||
TRI_voc_tid_t const collectionId = NumericValue<TRI_voc_cid_t>(slice, "cid");
|
||||
// note that the collection is now considered not dropped
|
||||
state->droppedCollections.erase(cid);
|
||||
state->droppedCollections.erase(collectionId);
|
||||
break;
|
||||
}
|
||||
|
||||
case TRI_WAL_MARKER_DROP_COLLECTION: {
|
||||
VPackSlice const slice(p + sizeof(TRI_df_marker_t));
|
||||
TRI_voc_tid_t cid = NumericValue<TRI_voc_cid_t>(slice, "cid");
|
||||
TRI_voc_tid_t const collectionId = NumericValue<TRI_voc_cid_t>(slice, "cid");
|
||||
// note that the collection was dropped and doesn't need to be collected
|
||||
state->droppedCollections.emplace(cid);
|
||||
state->structuralOperations.erase(cid);
|
||||
state->documentOperations.erase(cid);
|
||||
state->operationsCount.erase(cid);
|
||||
state->collections.erase(cid);
|
||||
state->droppedCollections.emplace(collectionId);
|
||||
state->structuralOperations.erase(collectionId);
|
||||
state->documentOperations.erase(collectionId);
|
||||
state->operationsCount.erase(collectionId);
|
||||
state->collections.erase(collectionId);
|
||||
break;
|
||||
}
|
||||
|
||||
case TRI_WAL_MARKER_CREATE_DATABASE: {
|
||||
VPackSlice const slice(p + sizeof(TRI_df_marker_t));
|
||||
TRI_voc_tick_t id = NumericValue<TRI_voc_tick_t>(slice, "database");
|
||||
TRI_voc_tick_t database = NumericValue<TRI_voc_tick_t>(slice, "database");
|
||||
// note that the database is now considered not dropped
|
||||
state->droppedDatabases.erase(id);
|
||||
state->droppedDatabases.erase(database);
|
||||
break;
|
||||
}
|
||||
|
||||
case TRI_WAL_MARKER_DROP_DATABASE: {
|
||||
VPackSlice const slice(p + sizeof(TRI_df_marker_t));
|
||||
TRI_voc_tick_t id = NumericValue<TRI_voc_tick_t>(slice, "database");
|
||||
TRI_voc_tick_t database = NumericValue<TRI_voc_tick_t>(slice, "database");
|
||||
// note that the database was dropped and doesn't need to be collected
|
||||
state->droppedDatabases.emplace(id);
|
||||
state->droppedDatabases.emplace(database);
|
||||
|
||||
// find all collections for the same database and erase their state, too
|
||||
for (auto it = state->collections.begin(); it != state->collections.end();
|
||||
/* no hoisting */) {
|
||||
if ((*it).second == id) {
|
||||
if ((*it).second == database) {
|
||||
state->droppedCollections.emplace((*it).first);
|
||||
state->structuralOperations.erase((*it).first);
|
||||
state->documentOperations.erase((*it).first);
|
||||
|
@ -305,7 +305,7 @@ static bool ScanMarker(TRI_df_marker_t const* marker, void* data,
|
|||
case TRI_DF_MARKER_FOOTER: {
|
||||
// new datafile or end of datafile. forget state!
|
||||
state->resetCollection();
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
|
@ -699,12 +699,12 @@ void CollectorThread::processCollectionMarker(
|
|||
// somebody inserted a new revision of the document or the revision
|
||||
// was already moved by the compactor
|
||||
dfi.numberDead++;
|
||||
dfi.sizeDead += (int64_t)TRI_DF_ALIGN_BLOCK(datafileMarkerSize);
|
||||
dfi.sizeDead += AlignedSize<int64_t>(datafileMarkerSize);
|
||||
} else {
|
||||
// update size info
|
||||
document->_masterPointers.adjustTotalSize(
|
||||
TRI_DF_ALIGN_BLOCK(walMarker->_size),
|
||||
TRI_DF_ALIGN_BLOCK(datafileMarkerSize));
|
||||
AlignedSize<int64_t>(walMarker->_size),
|
||||
AlignedSize<int64_t>(datafileMarkerSize));
|
||||
|
||||
// we can safely update the master pointer's dataptr value
|
||||
found->setDataPtr(
|
||||
|
@ -712,7 +712,7 @@ void CollectorThread::processCollectionMarker(
|
|||
found->_fid = fid;
|
||||
|
||||
dfi.numberAlive++;
|
||||
dfi.sizeAlive += (int64_t)TRI_DF_ALIGN_BLOCK(datafileMarkerSize);
|
||||
dfi.sizeAlive += AlignedSize<int64_t>(datafileMarkerSize);
|
||||
}
|
||||
} else if (walMarker->_type == TRI_WAL_MARKER_VPACK_REMOVE) {
|
||||
auto& dfi = createDfi(cache, fid);
|
||||
|
@ -729,7 +729,7 @@ void CollectorThread::processCollectionMarker(
|
|||
if (found != nullptr && found->_rid > revisionId) {
|
||||
// somebody re-created the document with a newer revision
|
||||
dfi.numberDead++;
|
||||
dfi.sizeDead += (int64_t)TRI_DF_ALIGN_BLOCK(datafileMarkerSize);
|
||||
dfi.sizeDead += AlignedSize<int64_t>(datafileMarkerSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1219,7 +1219,7 @@ char* CollectorThread::nextFreeMarkerPosition(
|
|||
TRI_document_collection_t* document, TRI_voc_tick_t tick,
|
||||
TRI_df_marker_type_e type, TRI_voc_size_t size, CollectorCache* cache) {
|
||||
TRI_collection_t* collection = document;
|
||||
size = TRI_DF_ALIGN_BLOCK(size);
|
||||
size = AlignedSize<TRI_voc_size_t>(size);
|
||||
|
||||
char* dst = nullptr;
|
||||
TRI_datafile_t* datafile = nullptr;
|
||||
|
|
|
@ -152,7 +152,7 @@ int Logfile::judge(std::string const& filename) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char* Logfile::reserve(size_t size) {
|
||||
size = TRI_DF_ALIGN_BLOCK(size);
|
||||
size = AlignedSize<size_t>(size);
|
||||
|
||||
char* result = _df->_next;
|
||||
|
||||
|
|
|
@ -150,10 +150,6 @@ class Marker {
|
|||
|
||||
inline TRI_voc_fid_t fid() const { return _fid; }
|
||||
|
||||
static inline size_t alignedSize(size_t size) {
|
||||
return TRI_DF_ALIGN_BLOCK(size);
|
||||
}
|
||||
|
||||
inline void* mem() const { return static_cast<void*>(_buffer); }
|
||||
|
||||
inline char* begin() const { return _buffer; }
|
||||
|
|
|
@ -131,7 +131,7 @@ SlotInfo Slots::nextUnused(TRI_voc_tick_t databaseId, TRI_voc_cid_t collectionId
|
|||
static size_t const PrologueSize = sizeof(TRI_df_prologue_marker_t);
|
||||
|
||||
// we need to use the aligned size for writing
|
||||
uint32_t alignedSize = TRI_DF_ALIGN_BLOCK(size);
|
||||
uint32_t alignedSize = AlignedSize<uint32_t>(size);
|
||||
int iterations = 0;
|
||||
bool hasWaited = false;
|
||||
bool mustWritePrologue = false;
|
||||
|
@ -231,7 +231,7 @@ SlotInfo Slots::nextUnused(TRI_voc_tick_t databaseId, TRI_voc_cid_t collectionId
|
|||
// write prologue...
|
||||
|
||||
// hand out the prologue slot and directly fill it
|
||||
int res = writePrologue(slot, databaseId, collectionId);
|
||||
int res = writePrologue(slot, mem, databaseId, collectionId);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
return SlotInfo(res);
|
||||
|
@ -589,12 +589,10 @@ int Slots::writeHeader(Slot* slot) {
|
|||
TRI_df_header_marker_t header = _logfile->getHeaderMarker();
|
||||
size_t const size = header.base._size;
|
||||
|
||||
TRI_df_marker_t* mem =
|
||||
reinterpret_cast<TRI_df_marker_t*>(_logfile->reserve(size));
|
||||
auto* mem = static_cast<void*>(_logfile->reserve(size));
|
||||
TRI_ASSERT(mem != nullptr);
|
||||
|
||||
slot->setUsed(static_cast<void*>(mem), static_cast<uint32_t>(size),
|
||||
_logfile->id(), handout());
|
||||
slot->setUsed(mem, static_cast<uint32_t>(size), _logfile->id(), handout());
|
||||
slot->fill(&header.base, size);
|
||||
slot->setReturned(false); // no sync
|
||||
|
||||
|
@ -609,16 +607,13 @@ int Slots::writeHeader(Slot* slot) {
|
|||
/// @brief write a prologue marker
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int Slots::writePrologue(Slot* slot, TRI_voc_tick_t databaseId, TRI_voc_cid_t collectionId) {
|
||||
TRI_df_header_marker_t header = _logfile->getHeaderMarker();
|
||||
int Slots::writePrologue(Slot* slot, void* mem, TRI_voc_tick_t databaseId, TRI_voc_cid_t collectionId) {
|
||||
TRI_df_prologue_marker_t header = _logfile->getPrologueMarker(databaseId, collectionId);
|
||||
size_t const size = header.base._size;
|
||||
|
||||
TRI_df_marker_t* mem =
|
||||
reinterpret_cast<TRI_df_marker_t*>(_logfile->reserve(size));
|
||||
TRI_ASSERT(mem != nullptr);
|
||||
|
||||
slot->setUsed(static_cast<void*>(mem), static_cast<uint32_t>(size),
|
||||
_logfile->id(), handout());
|
||||
slot->setUsed(mem, static_cast<uint32_t>(size), _logfile->id(), handout());
|
||||
slot->fill(&header.base, size);
|
||||
slot->setReturned(false); // no sync
|
||||
|
||||
|
@ -635,12 +630,10 @@ int Slots::writeFooter(Slot* slot) {
|
|||
TRI_df_footer_marker_t footer = _logfile->getFooterMarker();
|
||||
size_t const size = footer.base._size;
|
||||
|
||||
TRI_df_marker_t* mem =
|
||||
reinterpret_cast<TRI_df_marker_t*>(_logfile->reserve(size));
|
||||
auto* mem = static_cast<void*>(_logfile->reserve(size));
|
||||
TRI_ASSERT(mem != nullptr);
|
||||
|
||||
slot->setUsed(static_cast<void*>(mem), static_cast<uint32_t>(size),
|
||||
_logfile->id(), handout());
|
||||
slot->setUsed(mem, static_cast<uint32_t>(size), _logfile->id(), handout());
|
||||
slot->fill(&footer.base, size);
|
||||
slot->setReturned(true); // sync
|
||||
|
||||
|
|
|
@ -165,7 +165,7 @@ class Slots {
|
|||
/// @brief writes a prologue for a document/remove marker
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int writePrologue(Slot*, TRI_voc_tick_t, TRI_voc_cid_t);
|
||||
int writePrologue(Slot*, void*, TRI_voc_tick_t, TRI_voc_cid_t);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief write a footer marker
|
||||
|
|
Loading…
Reference in New Issue