1
0
Fork 0

fixed a memleak in /_api/replication/dump

This commit is contained in:
Jan Steemann 2013-08-29 11:46:33 +02:00
parent eb2dee447c
commit e72c6ab20c
6 changed files with 96 additions and 45 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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;
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////