mirror of https://gitee.com/bigwinds/arangodb
exclude failed operations from dump
This commit is contained in:
parent
750682053c
commit
f4b62f78d3
|
@ -804,6 +804,80 @@ static bool StringifyMarkerReplication (TRI_string_buffer_t* buffer,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief check if a transaction id is contained in the list of failed
|
||||||
|
/// transactions
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static bool InFailedList (TRI_vector_t const* list, TRI_voc_tid_t search) {
|
||||||
|
size_t n;
|
||||||
|
|
||||||
|
assert(list != NULL);
|
||||||
|
|
||||||
|
n = list->_length;
|
||||||
|
|
||||||
|
// decide how to search based on size of list
|
||||||
|
if (n == 0) {
|
||||||
|
// simple case: list is empty
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (n < 16) {
|
||||||
|
// list is small: use a linear search
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < n; ++i) {
|
||||||
|
TRI_voc_tid_t* tid = tid = TRI_AtVector(list, i);
|
||||||
|
|
||||||
|
if (*tid == search) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
// list is somewhat bigger, use a binary search
|
||||||
|
size_t l = 0;
|
||||||
|
size_t r = (size_t) (n - 1);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
// determine midpoint
|
||||||
|
TRI_voc_tid_t* tid;
|
||||||
|
size_t m;
|
||||||
|
|
||||||
|
m = l + ((r - l) / 2);
|
||||||
|
tid = TRI_AtVector(list, m);
|
||||||
|
|
||||||
|
if (*tid == search) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*tid > search) {
|
||||||
|
if (m == 0) {
|
||||||
|
// we must abort because the following subtraction would
|
||||||
|
// make the size_t underflow
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = m - 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
l = m + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r < l) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// we should never get here
|
||||||
|
assert(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief dump data from a collection
|
/// @brief dump data from a collection
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -814,39 +888,85 @@ static int DumpCollection (TRI_replication_dump_t* dump,
|
||||||
TRI_voc_tick_t tickMax,
|
TRI_voc_tick_t tickMax,
|
||||||
uint64_t chunkSize) {
|
uint64_t chunkSize) {
|
||||||
TRI_vector_t datafiles;
|
TRI_vector_t datafiles;
|
||||||
|
TRI_document_collection_t* document;
|
||||||
TRI_string_buffer_t* buffer;
|
TRI_string_buffer_t* buffer;
|
||||||
TRI_voc_tick_t firstFoundTick;
|
TRI_voc_tick_t firstFoundTick;
|
||||||
TRI_voc_tick_t lastFoundTick;
|
TRI_voc_tick_t lastFoundTick;
|
||||||
|
TRI_voc_tid_t lastTid;
|
||||||
size_t i;
|
size_t i;
|
||||||
int res;
|
int res;
|
||||||
bool hasMore;
|
bool hasMore;
|
||||||
|
bool ignoreMarkers;
|
||||||
|
|
||||||
|
LOG_TRACE("dumping collection %llu, tick range %llu - %llu, chunk size %llu",
|
||||||
|
(unsigned long long) primary->base._info._cid,
|
||||||
|
(unsigned long long) tickMin,
|
||||||
|
(unsigned long long) tickMax,
|
||||||
|
(unsigned long long) chunkSize);
|
||||||
|
|
||||||
buffer = dump->_buffer;
|
buffer = dump->_buffer;
|
||||||
datafiles = GetRangeDatafiles(primary, tickMin, tickMax);
|
datafiles = GetRangeDatafiles(primary, tickMin, tickMax);
|
||||||
|
document = (TRI_document_collection_t*) primary;
|
||||||
hasMore = false;
|
|
||||||
|
// setup some iteration state
|
||||||
firstFoundTick = 0;
|
firstFoundTick = 0;
|
||||||
lastFoundTick = 0;
|
lastFoundTick = 0;
|
||||||
|
lastTid = 0;
|
||||||
res = TRI_ERROR_NO_ERROR;
|
res = TRI_ERROR_NO_ERROR;
|
||||||
|
hasMore = true;
|
||||||
|
ignoreMarkers = false;
|
||||||
|
|
||||||
for (i = 0; i < datafiles._length; ++i) {
|
for (i = 0; i < datafiles._length; ++i) {
|
||||||
df_entry_t* e = (df_entry_t*) TRI_AtVector(&datafiles, i);
|
df_entry_t* e = (df_entry_t*) TRI_AtVector(&datafiles, i);
|
||||||
TRI_datafile_t* datafile = e->_data;
|
TRI_datafile_t* datafile = e->_data;
|
||||||
char* ptr;
|
TRI_vector_t* failedList;
|
||||||
char* end;
|
char const* ptr;
|
||||||
|
char const* end;
|
||||||
|
|
||||||
|
failedList = NULL;
|
||||||
|
|
||||||
// we are reading from a journal that might be modified in parallel
|
// we are reading from a journal that might be modified in parallel
|
||||||
// so we must read-lock it
|
// so we must read-lock it
|
||||||
if (e->_isJournal) {
|
if (e->_isJournal) {
|
||||||
TRI_READ_LOCK_DOCUMENTS_INDEXES_PRIMARY_COLLECTION(primary);
|
TRI_READ_LOCK_DOCUMENTS_INDEXES_PRIMARY_COLLECTION(primary);
|
||||||
|
|
||||||
|
if (document->_failedTransactions._length > 0) {
|
||||||
|
// there are failed transactions. just reference them
|
||||||
|
failedList = &document->_failedTransactions;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
assert(datafile->_isSealed);
|
||||||
|
|
||||||
|
TRI_READ_LOCK_DOCUMENTS_INDEXES_PRIMARY_COLLECTION(primary);
|
||||||
|
|
||||||
|
if (document->_failedTransactions._length > 0) {
|
||||||
|
// there are failed transactions. copy the list of ids
|
||||||
|
failedList = TRI_CopyVector(TRI_UNKNOWN_MEM_ZONE, &document->_failedTransactions);
|
||||||
|
|
||||||
|
if (failedList == NULL) {
|
||||||
|
res = TRI_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TRI_READ_UNLOCK_DOCUMENTS_INDEXES_PRIMARY_COLLECTION(primary);
|
||||||
|
}
|
||||||
|
|
||||||
ptr = datafile->_data;
|
ptr = datafile->_data;
|
||||||
end = ptr + datafile->_currentSize;
|
|
||||||
|
if (res == TRI_ERROR_NO_ERROR) {
|
||||||
|
// no error so far. start iterating
|
||||||
|
end = ptr + datafile->_currentSize;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// some error occurred. don't iterate
|
||||||
|
end = ptr;
|
||||||
|
}
|
||||||
|
|
||||||
while (ptr < end) {
|
while (ptr < end) {
|
||||||
TRI_df_marker_t* marker = (TRI_df_marker_t*) ptr;
|
TRI_df_marker_t* marker = (TRI_df_marker_t*) ptr;
|
||||||
TRI_voc_tick_t foundTick;
|
TRI_voc_tick_t foundTick;
|
||||||
|
TRI_voc_tid_t tid;
|
||||||
|
|
||||||
if (marker->_size == 0 || marker->_type <= TRI_MARKER_MIN) {
|
if (marker->_size == 0 || marker->_type <= TRI_MARKER_MIN) {
|
||||||
// end of datafile
|
// end of datafile
|
||||||
|
@ -875,15 +995,43 @@ static int DumpCollection (TRI_replication_dump_t* dump,
|
||||||
goto NEXT_DF;
|
goto NEXT_DF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// note the last tick we processed
|
// note the last tick we processed
|
||||||
if (firstFoundTick == 0) {
|
if (firstFoundTick == 0) {
|
||||||
firstFoundTick = foundTick;
|
firstFoundTick = foundTick;
|
||||||
}
|
}
|
||||||
lastFoundTick = foundTick;
|
lastFoundTick = foundTick;
|
||||||
|
|
||||||
// TODO: check if marker is part of an aborted transaction
|
|
||||||
if (! StringifyMarkerReplication(buffer, (TRI_document_collection_t*) primary, marker)) {
|
// handle aborted/unfinished transactions
|
||||||
|
|
||||||
|
if (failedList == NULL) {
|
||||||
|
// there are no failed transactions
|
||||||
|
ignoreMarkers = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// get transaction id of marker
|
||||||
|
if (marker->_type == TRI_DOC_MARKER_KEY_DELETION) {
|
||||||
|
tid = ((TRI_doc_deletion_key_marker_t const*) marker)->_tid;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
tid = ((TRI_doc_document_key_marker_t const*) marker)->_tid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if marker is from an aborted transaction
|
||||||
|
if (tid > 0) {
|
||||||
|
if (tid != lastTid) {
|
||||||
|
ignoreMarkers = InFailedList(failedList, tid);
|
||||||
|
}
|
||||||
|
|
||||||
|
lastTid = tid;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ignoreMarkers) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! StringifyMarkerReplication(buffer, document, marker)) {
|
||||||
res = TRI_ERROR_INTERNAL;
|
res = TRI_ERROR_INTERNAL;
|
||||||
|
|
||||||
goto NEXT_DF;
|
goto NEXT_DF;
|
||||||
|
@ -902,6 +1050,12 @@ NEXT_DF:
|
||||||
// read-unlock the journal
|
// read-unlock the journal
|
||||||
TRI_READ_UNLOCK_DOCUMENTS_INDEXES_PRIMARY_COLLECTION(primary);
|
TRI_READ_UNLOCK_DOCUMENTS_INDEXES_PRIMARY_COLLECTION(primary);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
// free our copy of the failed list
|
||||||
|
if (failedList != NULL) {
|
||||||
|
TRI_FreeVector(TRI_UNKNOWN_MEM_ZONE, failedList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (res != TRI_ERROR_NO_ERROR || ! hasMore) {
|
if (res != TRI_ERROR_NO_ERROR || ! hasMore) {
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue