mirror of https://gitee.com/bigwinds/arangodb
fixed a memleak in /_api/replication/dump
This commit is contained in:
parent
eb2dee447c
commit
e72c6ab20c
|
@ -177,30 +177,6 @@ int InitialSyncer::run (string& errorMsg) {
|
|||
return res;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief comparator to sort collections
|
||||
/// sort order is by collection type first (vertices before edges, this is
|
||||
/// because edges depend on vertices being there), then name
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int InitialSyncer::sortCollections (const void* l, const void* r) {
|
||||
TRI_json_t const* left = JsonHelper::getArrayElement((TRI_json_t const*) l, "parameters");
|
||||
TRI_json_t const* right = JsonHelper::getArrayElement((TRI_json_t const*) r, "parameters");
|
||||
|
||||
int leftType = JsonHelper::getNumericValue<int>(left, "type", (int) TRI_COL_TYPE_DOCUMENT);
|
||||
int rightType = JsonHelper::getNumericValue<int>(right, "type", (int) TRI_COL_TYPE_DOCUMENT);
|
||||
|
||||
|
||||
if (leftType != rightType) {
|
||||
return leftType - rightType;
|
||||
}
|
||||
|
||||
string leftName = JsonHelper::getStringValue(left, "name", "");
|
||||
string rightName = JsonHelper::getStringValue(right, "name", "");
|
||||
|
||||
return strcmp(leftName.c_str(), rightName.c_str());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -652,13 +628,6 @@ int InitialSyncer::handleInventoryResponse (TRI_json_t const* json,
|
|||
return TRI_ERROR_REPLICATION_INVALID_RESPONSE;
|
||||
}
|
||||
|
||||
const size_t n = collections->_value._objects._length;
|
||||
|
||||
if (n > 1) {
|
||||
// sort by collection type (vertices before edges), then name
|
||||
qsort(collections->_value._objects._buffer, n, sizeof(TRI_json_t), &sortCollections);
|
||||
}
|
||||
|
||||
int res;
|
||||
|
||||
// STEP 1: validate collection declarations from master
|
||||
|
|
|
@ -253,6 +253,30 @@ BAD_CALL:
|
|||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief comparator to sort collections
|
||||
/// sort order is by collection type first (vertices before edges, this is
|
||||
/// because edges depend on vertices being there), then name
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int RestReplicationHandler::sortCollections (const void* l,
|
||||
const void* r) {
|
||||
TRI_json_t const* left = JsonHelper::getArrayElement((TRI_json_t const*) l, "parameters");
|
||||
TRI_json_t const* right = JsonHelper::getArrayElement((TRI_json_t const*) r, "parameters");
|
||||
|
||||
int leftType = JsonHelper::getNumericValue<int>(left, "type", (int) TRI_COL_TYPE_DOCUMENT);
|
||||
int rightType = JsonHelper::getNumericValue<int>(right, "type", (int) TRI_COL_TYPE_DOCUMENT);
|
||||
|
||||
if (leftType != rightType) {
|
||||
return leftType - rightType;
|
||||
}
|
||||
|
||||
string leftName = JsonHelper::getStringValue(left, "name", "");
|
||||
string rightName = JsonHelper::getStringValue(right, "name", "");
|
||||
|
||||
return strcasecmp(leftName.c_str(), rightName.c_str());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief filter a collection based on collection attributes
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1036,7 +1060,8 @@ void RestReplicationHandler::handleCommandLoggerFollow () {
|
|||
|
||||
if (length > 0) {
|
||||
// transfer ownership of the buffer contents
|
||||
_response->body().appendText(TRI_BeginStringBuffer(dump._buffer), length);
|
||||
_response->body().set(dump._buffer);
|
||||
|
||||
// avoid double freeing
|
||||
TRI_StealStringBuffer(dump._buffer);
|
||||
}
|
||||
|
@ -1070,6 +1095,8 @@ void RestReplicationHandler::handleCommandLoggerFollow () {
|
|||
/// - `indexes`: a list of the indexes of a the collection. Primary indexes and edges indexes
|
||||
/// are not included in this list.
|
||||
///
|
||||
/// `tick`: the system-wide tick value at the start of the dump
|
||||
///
|
||||
/// The `state` attribute contains the current state of the replication logger. It
|
||||
/// contains the following sub-attributes:
|
||||
///
|
||||
|
@ -1176,6 +1203,17 @@ void RestReplicationHandler::handleCommandInventory () {
|
|||
return;
|
||||
}
|
||||
|
||||
assert(JsonHelper::isList(collections));
|
||||
|
||||
// sort collections by type, then name
|
||||
const size_t n = collections->_value._objects._length;
|
||||
|
||||
if (n > 1) {
|
||||
// sort by collection type (vertices before edges), then name
|
||||
qsort(collections->_value._objects._buffer, n, sizeof(TRI_json_t), &sortCollections);
|
||||
}
|
||||
|
||||
|
||||
TRI_replication_logger_state_t state;
|
||||
|
||||
int res = TRI_StateReplicationLogger(_vocbase->_replicationLogger, &state);
|
||||
|
@ -1190,10 +1228,13 @@ void RestReplicationHandler::handleCommandInventory () {
|
|||
TRI_json_t json;
|
||||
|
||||
TRI_InitArrayJson(TRI_CORE_MEM_ZONE, &json);
|
||||
|
||||
char* tickString = TRI_StringUInt64(tick);
|
||||
|
||||
// add collections data
|
||||
TRI_Insert3ArrayJson(TRI_CORE_MEM_ZONE, &json, "collections", collections);
|
||||
TRI_Insert3ArrayJson(TRI_CORE_MEM_ZONE, &json, "state", TRI_JsonStateReplicationLogger(&state));
|
||||
TRI_Insert3ArrayJson(TRI_CORE_MEM_ZONE, &json, "tick", TRI_CreateStringJson(TRI_CORE_MEM_ZONE, tickString));
|
||||
|
||||
generateResult(&json);
|
||||
TRI_DestroyJson(TRI_CORE_MEM_ZONE, &json);
|
||||
|
@ -1218,6 +1259,9 @@ void RestReplicationHandler::handleCommandInventory () {
|
|||
/// @RESTQUERYPARAM{chunkSize,number,optional}
|
||||
/// Approximate maximum size of the returned result.
|
||||
///
|
||||
/// @RESTQUERYPARAM{ticks,boolean,optional}
|
||||
/// Whether or not to include tick values in the dump. Default value is `true`.
|
||||
///
|
||||
/// @RESTDESCRIPTION
|
||||
/// Returns the data from the collection for the requested range.
|
||||
///
|
||||
|
@ -1336,16 +1380,20 @@ void RestReplicationHandler::handleCommandDump () {
|
|||
// determine start tick for dump
|
||||
TRI_voc_tick_t tickStart = 0;
|
||||
TRI_voc_tick_t tickEnd = (TRI_voc_tick_t) UINT64_MAX;
|
||||
bool withTicks = true;
|
||||
|
||||
bool found;
|
||||
char const* value;
|
||||
|
||||
value = _request->value("from", found);
|
||||
|
||||
if (found) {
|
||||
tickStart = (TRI_voc_tick_t) StringUtils::uint64(value);
|
||||
}
|
||||
|
||||
// determine end tick for dump
|
||||
value = _request->value("to", found);
|
||||
|
||||
if (found) {
|
||||
tickEnd = (TRI_voc_tick_t) StringUtils::uint64(value);
|
||||
}
|
||||
|
@ -1356,6 +1404,12 @@ void RestReplicationHandler::handleCommandDump () {
|
|||
"invalid from/to values");
|
||||
return;
|
||||
}
|
||||
|
||||
value = _request->value("ticks", found);
|
||||
|
||||
if (found) {
|
||||
withTicks = StringUtils::boolean(value);
|
||||
}
|
||||
|
||||
const uint64_t chunkSize = determineChunkSize();
|
||||
|
||||
|
@ -1391,7 +1445,7 @@ void RestReplicationHandler::handleCommandDump () {
|
|||
return;
|
||||
}
|
||||
|
||||
int res = TRI_DumpCollectionReplication(&dump, col, tickStart, tickEnd, chunkSize);
|
||||
int res = TRI_DumpCollectionReplication(&dump, col, tickStart, tickEnd, chunkSize, withTicks);
|
||||
|
||||
TRI_ReleaseCollectionVocBase(_vocbase, col);
|
||||
|
||||
|
@ -1418,7 +1472,8 @@ void RestReplicationHandler::handleCommandDump () {
|
|||
StringUtils::itoa(dump._lastFoundTick));
|
||||
|
||||
// transfer ownership of the buffer contents
|
||||
_response->body().appendText(TRI_BeginStringBuffer(dump._buffer), length);
|
||||
_response->body().set(dump._buffer);
|
||||
|
||||
// avoid double freeing
|
||||
TRI_StealStringBuffer(dump._buffer);
|
||||
}
|
||||
|
|
|
@ -132,10 +132,13 @@ namespace triagens {
|
|||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief exclude a collection from replication?
|
||||
/// @brief comparator to sort collections
|
||||
/// sort order is by collection type first (vertices before edges, this is
|
||||
/// because edges depend on vertices being there), then name
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool excludeCollection (const char*);
|
||||
static int sortCollections (const void*,
|
||||
const void*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief filter a collection based on collection attributes
|
||||
|
|
|
@ -226,7 +226,8 @@ static TRI_vector_t GetRangeDatafiles (TRI_primary_collection_t* primary,
|
|||
|
||||
static bool StringifyMarkerDump (TRI_string_buffer_t* buffer,
|
||||
TRI_document_collection_t* document,
|
||||
TRI_df_marker_t const* marker) {
|
||||
TRI_df_marker_t const* marker,
|
||||
bool withTick) {
|
||||
TRI_replication_operation_e type;
|
||||
TRI_voc_key_t key;
|
||||
TRI_voc_rid_t rid;
|
||||
|
@ -257,10 +258,15 @@ static bool StringifyMarkerDump (TRI_string_buffer_t* buffer,
|
|||
return false;
|
||||
}
|
||||
|
||||
APPEND_STRING(buffer, "{\"tick\":\"");
|
||||
APPEND_UINT64(buffer, (uint64_t) marker->_tick);
|
||||
if (withTick) {
|
||||
APPEND_STRING(buffer, "{\"tick\":\"");
|
||||
APPEND_UINT64(buffer, (uint64_t) marker->_tick);
|
||||
APPEND_STRING(buffer, "\",\"type\":");
|
||||
}
|
||||
else {
|
||||
APPEND_STRING(buffer, "{\"type\":");
|
||||
}
|
||||
|
||||
APPEND_STRING(buffer, "\",\"type\":");
|
||||
APPEND_UINT64(buffer, (uint64_t) type);
|
||||
APPEND_STRING(buffer, ",\"key\":\"");
|
||||
// key is user-defined, but does not need escaping
|
||||
|
@ -547,7 +553,8 @@ static int DumpCollection (TRI_replication_dump_t* dump,
|
|||
TRI_primary_collection_t* primary,
|
||||
TRI_voc_tick_t dataMin,
|
||||
TRI_voc_tick_t dataMax,
|
||||
uint64_t chunkSize) {
|
||||
uint64_t chunkSize,
|
||||
bool withTicks) {
|
||||
TRI_vector_t datafiles;
|
||||
TRI_document_collection_t* document;
|
||||
TRI_string_buffer_t* buffer;
|
||||
|
@ -703,7 +710,7 @@ static int DumpCollection (TRI_replication_dump_t* dump,
|
|||
}
|
||||
|
||||
|
||||
if (! StringifyMarkerDump(buffer, document, marker)) {
|
||||
if (! StringifyMarkerDump(buffer, document, marker, withTicks)) {
|
||||
res = TRI_ERROR_INTERNAL;
|
||||
|
||||
goto NEXT_DF;
|
||||
|
@ -941,7 +948,8 @@ int TRI_DumpCollectionReplication (TRI_replication_dump_t* dump,
|
|||
TRI_vocbase_col_t* col,
|
||||
TRI_voc_tick_t dataMin,
|
||||
TRI_voc_tick_t dataMax,
|
||||
uint64_t chunkSize) {
|
||||
uint64_t chunkSize,
|
||||
bool withTicks) {
|
||||
TRI_primary_collection_t* primary;
|
||||
TRI_barrier_t* b;
|
||||
int res;
|
||||
|
@ -961,7 +969,7 @@ int TRI_DumpCollectionReplication (TRI_replication_dump_t* dump,
|
|||
// block compaction
|
||||
TRI_ReadLockReadWriteLock(&primary->_compactionLock);
|
||||
|
||||
res = DumpCollection(dump, primary, dataMin, dataMax, chunkSize);
|
||||
res = DumpCollection(dump, primary, dataMin, dataMax, chunkSize, withTicks);
|
||||
|
||||
TRI_ReadUnlockReadWriteLock(&primary->_compactionLock);
|
||||
|
||||
|
|
|
@ -96,7 +96,8 @@ int TRI_DumpCollectionReplication (TRI_replication_dump_t*,
|
|||
struct TRI_vocbase_col_s*,
|
||||
TRI_voc_tick_t,
|
||||
TRI_voc_tick_t,
|
||||
uint64_t);
|
||||
uint64_t,
|
||||
bool);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief dump data from the replication log
|
||||
|
|
|
@ -351,6 +351,21 @@ namespace triagens {
|
|||
return *this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief set the buffer content
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void set (TRI_string_buffer_t const* other) {
|
||||
if (_buffer._buffer != 0) {
|
||||
TRI_Free(_buffer._memoryZone, _buffer._buffer);
|
||||
}
|
||||
|
||||
_buffer._memoryZone = other->_memoryZone;
|
||||
_buffer._buffer = other->_buffer;
|
||||
_buffer._current = other->_current;
|
||||
_buffer._len = other->_len;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
Loading…
Reference in New Issue