1
0
Fork 0

better dfdb diagnostics

This commit is contained in:
Jan Steemann 2015-05-19 23:12:36 +02:00
parent cdc11a9961
commit db9e9d7c47
4 changed files with 129 additions and 16 deletions

View File

@ -4294,8 +4294,9 @@ static void JS_DatafileScanVocbaseCol (const v8::FunctionCallbackInfo<v8::Value>
v8::Handle<v8::Array> entries = v8::Array::New(isolate);
result->Set(TRI_V8_ASCII_STRING("entries"), entries);
for (size_t i = 0; i < TRI_LengthVector(&scan._entries); ++i) {
TRI_df_scan_entry_t* entry = (TRI_df_scan_entry_t*) TRI_AtVector(&scan._entries, i);
size_t const n = TRI_LengthVector(&scan._entries);
for (size_t i = 0; i < n; ++i) {
auto entry = static_cast<TRI_df_scan_entry_t const*>(TRI_AddressVector(&scan._entries, i));
v8::Handle<v8::Object> o = v8::Object::New(isolate);
@ -4306,6 +4307,10 @@ static void JS_DatafileScanVocbaseCol (const v8::FunctionCallbackInfo<v8::Value>
o->Set(TRI_V8_ASCII_STRING("type"), v8::Number::New(isolate, (int) entry->_type));
o->Set(TRI_V8_ASCII_STRING("status"), v8::Number::New(isolate, (int) entry->_status));
if (entry->_diagnosis != nullptr) {
o->Set(TRI_V8_ASCII_STRING("diagnosis"), TRI_V8_ASCII_STRING(entry->_diagnosis));
}
entries->Set((uint32_t) i, o);
}

View File

@ -134,6 +134,74 @@ static int TruncateDatafile (TRI_datafile_t* const datafile, const off_t length)
return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief diagnoses a marker
////////////////////////////////////////////////////////////////////////////////
static std::string DiagnoseMarker (TRI_df_marker_t const* marker,
char const* end) {
std::ostringstream result;
if (marker == nullptr) {
result << "marker is undefined. should not happen";
return result.str();
}
// check marker type
TRI_df_marker_type_t type = marker->_type;
if (type <= (TRI_df_marker_type_t) TRI_MARKER_MIN) {
// marker type is less than minimum allowed type value
result << "marker type value (" << static_cast<int>(type) << ") is wrong. expecting value higher than " << TRI_MARKER_MIN;
return result.str();
}
if (type >= (TRI_df_marker_type_t) TRI_MARKER_MAX) {
// marker type is greater than maximum allowed type value
result << "marker type value (" << static_cast<int>(type) << ") is wrong. expecting value less than " << TRI_MARKER_MAX;
return result.str();
}
if (marker->_size >= (TRI_voc_size_t) TRI_MARKER_MAXIMAL_SIZE) {
// a single marker bigger than 256 MB seems unreasonable
// note: this is an arbitrary limit
result << "marker size value (" << marker->_size << ") is wrong. expecting value less than " << TRI_MARKER_MAXIMAL_SIZE;
return result.str();
}
TRI_voc_size_t zero = 0;
off_t o = offsetof(TRI_df_marker_t, _crc);
size_t n = sizeof(TRI_voc_crc_t);
char const* ptr = (char const*) marker;
if (marker->_size < sizeof(TRI_df_marker_t)) {
result << "marker size is too small (" << marker->_size << "). expecting at least " << sizeof(TRI_df_marker_t) << " bytes";
return result.str();
}
if (reinterpret_cast<char const*>(marker) + marker->_size > end) {
result << "marker size is beyond end of datafile";
return result.str();
}
TRI_voc_crc_t crc = TRI_InitialCrc32();
crc = TRI_BlockCrc32(crc, ptr, o);
crc = TRI_BlockCrc32(crc, (char*) &zero, n);
crc = TRI_BlockCrc32(crc, ptr + o + n, marker->_size - o - n);
crc = TRI_FinalCrc32(crc);
if (marker->_crc == crc) {
result << "crc checksum is correct";
}
else {
result << "crc checksum (hex " << std::hex << marker->_crc << ") is wrong. expecting (hex " << std::hex << crc << ")";
}
return result.str();
}
////////////////////////////////////////////////////////////////////////////////
/// @brief checks a CRC of a marker
////////////////////////////////////////////////////////////////////////////////
@ -456,7 +524,7 @@ static TRI_df_scan_t ScanDatafile (TRI_datafile_t const* datafile) {
end = datafile->_data + datafile->_currentSize;
currentSize = 0;
TRI_InitVector(&scan._entries, TRI_CORE_MEM_ZONE, sizeof(TRI_df_scan_entry_t));
TRI_InitVector2(&scan._entries, TRI_CORE_MEM_ZONE, sizeof(TRI_df_scan_entry_t), 1024);
scan._currentSize = datafile->_currentSize;
scan._maximalSize = datafile->_maximalSize;
@ -475,12 +543,13 @@ static TRI_df_scan_t ScanDatafile (TRI_datafile_t const* datafile) {
memset(&entry, 0, sizeof(entry));
entry._position = (TRI_voc_size_t) (ptr - datafile->_data);
entry._size = marker->_size;
entry._realSize = TRI_DF_ALIGN_BLOCK(marker->_size);
entry._tick = marker->_tick;
entry._type = marker->_type;
entry._status = 1;
entry._position = (TRI_voc_size_t) (ptr - datafile->_data);
entry._size = marker->_size;
entry._realSize = TRI_DF_ALIGN_BLOCK(marker->_size);
entry._tick = marker->_tick;
entry._type = marker->_type;
entry._status = 1;
entry._diagnosis = nullptr;
if (marker->_size == 0 && marker->_crc == 0 && marker->_type == 0 && marker->_tick == 0) {
entry._status = 2;
@ -506,6 +575,9 @@ static TRI_df_scan_t ScanDatafile (TRI_datafile_t const* datafile) {
if (marker->_size < sizeof(TRI_df_marker_t)) {
entry._status = 4;
auto&& diagnosis = DiagnoseMarker(marker, end);
entry._diagnosis = TRI_DuplicateString2Z(TRI_UNKNOWN_MEM_ZONE, diagnosis.c_str(), diagnosis.size());
scan._endPosition = currentSize;
scan._status = 3;
@ -516,6 +588,9 @@ static TRI_df_scan_t ScanDatafile (TRI_datafile_t const* datafile) {
if (! TRI_IsValidMarkerDatafile(marker)) {
entry._status = 4;
auto&& diagnosis = DiagnoseMarker(marker, end);
entry._diagnosis = TRI_DuplicateString2Z(TRI_UNKNOWN_MEM_ZONE, diagnosis.c_str(), diagnosis.size());
scan._endPosition = currentSize;
scan._status = 3;
@ -527,6 +602,10 @@ static TRI_df_scan_t ScanDatafile (TRI_datafile_t const* datafile) {
if (! ok) {
entry._status = 5;
auto&& diagnosis = DiagnoseMarker(marker, end);
entry._diagnosis = TRI_DuplicateString2Z(TRI_UNKNOWN_MEM_ZONE, diagnosis.c_str(), diagnosis.size());
scan._status = 4;
}
@ -1888,6 +1967,16 @@ TRI_df_scan_t TRI_ScanDatafile (char const* path) {
////////////////////////////////////////////////////////////////////////////////
void TRI_DestroyDatafileScan (TRI_df_scan_t* scan) {
size_t const n = TRI_LengthVector(&scan->_entries);
for (size_t i = 0; i < n; ++i) {
auto entry = static_cast<TRI_df_scan_entry_t*>(TRI_AtVector(&scan->_entries, i));
if (entry != nullptr && entry->_diagnosis != nullptr) {
TRI_FreeString(TRI_UNKNOWN_MEM_ZONE, entry->_diagnosis);
}
}
TRI_DestroyVector(&scan->_entries);
}

View File

@ -235,14 +235,15 @@ TRI_df_scan_t;
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_df_scan_entry_s {
TRI_voc_size_t _position;
TRI_voc_size_t _size;
TRI_voc_size_t _realSize;
TRI_voc_tick_t _tick;
TRI_voc_size_t _position;
TRI_voc_size_t _size;
TRI_voc_size_t _realSize;
TRI_voc_tick_t _tick;
TRI_df_marker_type_t _type;
uint32_t _status;
uint32_t _status;
char* _diagnosis;
}
TRI_df_scan_entry_t;

View File

@ -193,7 +193,8 @@ function PrintEntries (entries, amount) {
function DeepCheckDatafile (collection, type, datafile, scan) {
var entries = scan.entries;
var lastGood = 0;
var diagnosis = "";
var lastGood, firstBad;
var lastGoodPos = 0;
var stillGood = true;
@ -208,11 +209,28 @@ function DeepCheckDatafile (collection, type, datafile, scan) {
}
else {
stillGood = false;
diagnosis = entry.diagnosis || "";
firstBad = entry;
break;
}
}
if (! stillGood) {
printf(" Last good position: %d\n", lastGood.position + lastGood.realSize);
printf(" Last good marker: start: %d (hex %s), length: %d (hex %s)\n",
lastGood.position,
lastGood.position.toString(16),
lastGood.realSize,
lastGood.realSize.toString(16));
printf(" First bad marker: start: %d (hex %s), length: %d (hex %s)\n",
firstBad.position,
firstBad.position.toString(16),
firstBad.realSize,
firstBad.realSize.toString(16));
if (diagnosis) {
printf(" Diagnosis: %s\n", diagnosis);
}
printf("\n");
QueryWipeDatafile(collection, type, datafile, scan, lastGoodPos);