1
0
Fork 0

Merge branch 'devel' of github.com:triAGENS/ArangoDB into devel

This commit is contained in:
Frank Celler 2013-11-20 13:50:14 +01:00
commit 01532b024e
9 changed files with 357 additions and 55 deletions

View File

@ -39,6 +39,7 @@
#include "VocBase/marker.h"
#include "VocBase/server.h"
#include "VocBase/vocbase.h"
#include "VocBase/voc-shaper.h"
// -----------------------------------------------------------------------------
// --SECTION-- private constants
@ -563,6 +564,12 @@ static bool Compactifier (TRI_df_marker_t const* marker,
LOG_FATAL_AND_EXIT("cannot write shape marker to compactor file: %s", TRI_last_error());
}
res = TRI_MoveMarkerVocShaper(primary->_shaper, result);
if (res != TRI_ERROR_NO_ERROR) {
LOG_FATAL_AND_EXIT("cannot re-locate shape marker");
}
context->_dfi._numberShapes++;
context->_dfi._sizeShapes += (int64_t) marker->_size;
}
@ -576,6 +583,12 @@ static bool Compactifier (TRI_df_marker_t const* marker,
LOG_FATAL_AND_EXIT("cannot write attribute marker to compactor file: %s", TRI_last_error());
}
res = TRI_MoveMarkerVocShaper(primary->_shaper, result);
if (res != TRI_ERROR_NO_ERROR) {
LOG_FATAL_AND_EXIT("cannot re-locate shape marker");
}
context->_dfi._numberAttributes++;
context->_dfi._sizeAttributes += (int64_t) marker->_size;
}

View File

@ -76,7 +76,6 @@ typedef struct weighted_attribute_s {
TRI_shape_aid_t _aid;
int64_t _weight;
TRI_shaped_json_t _value;
const TRI_shaper_t* _shaper;
}
weighted_attribute_t;
@ -453,7 +452,7 @@ static TRI_shape_aid_t FindAttributeByName (TRI_shaper_t* shaper, char const* na
if (weightedAttribute != NULL) {
weightedAttribute->_aid = markerResult->_aid;
weightedAttribute->_weight = TRI_VOC_UNDEFINED_ATTRIBUTE_WEIGHT;
weightedAttribute->_attribute = (char*)(markerResult) + sizeof(TRI_df_attribute_marker_t);
weightedAttribute->_attribute = TRI_DuplicateStringZ(TRI_UNKNOWN_MEM_ZONE, name);
weightedAttribute->_next = NULL;
// ..........................................................................
@ -740,9 +739,9 @@ static TRI_shape_t const* FindShape (TRI_shaper_t* shaper,
/// @brief compares to weighted attributes
////////////////////////////////////////////////////////////////////////////////
static int attributeWeightCompareFunction (const void* leftItem, const void* rightItem) {
const weighted_attribute_t* l = (const weighted_attribute_t*)(leftItem);
const weighted_attribute_t* r = (const weighted_attribute_t*)(rightItem);
static int AttributeWeightCompareFunction (const void* leftItem, const void* rightItem) {
const weighted_attribute_t* l = (const weighted_attribute_t*) leftItem;
const weighted_attribute_t* r = (const weighted_attribute_t*) rightItem;
if (l->_weight < r->_weight) {
return -1;
@ -760,7 +759,7 @@ static int attributeWeightCompareFunction (const void* leftItem, const void* rig
/// comparisions.
////////////////////////////////////////////////////////////////////////////////
static void freeShapeTypeJsonArrayHelper (weighted_attribute_t** leftWeightedList,
static void FreeShapeTypeJsonArrayHelper (weighted_attribute_t** leftWeightedList,
weighted_attribute_t** rightWeightedList) {
if (*leftWeightedList != NULL) {
TRI_Free(TRI_UNKNOWN_MEM_ZONE, *leftWeightedList);
@ -777,7 +776,7 @@ static void freeShapeTypeJsonArrayHelper (weighted_attribute_t** leftWeightedLis
/// @brief returns the number of entries
////////////////////////////////////////////////////////////////////////////////
static int compareShapeTypeJsonArrayHelper (const TRI_shape_t* shape,
static int CompareShapeTypeJsonArrayHelper (const TRI_shape_t* shape,
const TRI_shaper_t* shaper,
const TRI_shaped_json_t* shapedJson,
weighted_attribute_t** attributeArray) {
@ -847,7 +846,6 @@ static int compareShapeTypeJsonArrayHelper (const TRI_shape_t* shape,
(*attributeArray)[j]._value._sid = sids[j];
(*attributeArray)[j]._value._data.data = shapedJson->_data.data + offsets[j];
(*attributeArray)[j]._value._data.length = offsets[j + 1] - offsets[j];
(*attributeArray)[j]._shaper = shaper;
}
offsets = (const TRI_shape_size_t*)(shapedJson->_data.data);
@ -858,7 +856,6 @@ static int compareShapeTypeJsonArrayHelper (const TRI_shape_t* shape,
(*attributeArray)[jj]._value._sid = sids[jj];
(*attributeArray)[jj]._value._data.data = shapedJson->_data.data + offsets[j];
(*attributeArray)[jj]._value._data.length = offsets[j + 1] - offsets[j];
(*attributeArray)[jj]._shaper = shaper;
}
return (fixedEntries + variableEntries);
@ -1217,6 +1214,12 @@ void TRI_DestroyVocShaper (TRI_shaper_t* s) {
weightedAttribute = (shaper->_weights)._first;
while (weightedAttribute != NULL) {
nextWeightedAttribute = weightedAttribute->_next;
// free attribute name
if (weightedAttribute->_attribute != NULL) {
TRI_Free(TRI_UNKNOWN_MEM_ZONE, weightedAttribute->_attribute);
}
TRI_Free(TRI_UNKNOWN_MEM_ZONE, weightedAttribute);
weightedAttribute = nextWeightedAttribute;
}
@ -1256,6 +1259,61 @@ int TRI_InitVocShaper (TRI_shaper_t* s) {
return InitStep3VocShaper(shaper);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief move a shape marker, called during compaction
////////////////////////////////////////////////////////////////////////////////
int TRI_MoveMarkerVocShaper (TRI_shaper_t* s,
TRI_df_marker_t* marker) {
voc_shaper_t* shaper = (voc_shaper_t*) s;
if (marker->_type == TRI_DF_MARKER_SHAPE) {
char* p = ((char*) marker) + sizeof(TRI_df_shape_marker_t);
TRI_shape_t* l = (TRI_shape_t*) p;
void* f;
// remove the old marker
f = TRI_RemoveKeyAssociativeSynced(&shaper->_shapeIds, &l->_sid);
assert(f != NULL);
// re-insert the marker with the new pointer
f = TRI_InsertKeyAssociativeSynced(&shaper->_shapeIds, &l->_sid, l);
assert(f == NULL);
// same for the shape dictionary
f = TRI_RemoveElementAssociativeSynced(&shaper->_shapeDictionary, l);
assert(f != NULL);
// re-insert
f = TRI_InsertElementAssociativeSynced(&shaper->_shapeDictionary, l);
assert(f == NULL);
}
else if (marker->_type == TRI_DF_MARKER_ATTRIBUTE) {
TRI_df_attribute_marker_t* m = (TRI_df_attribute_marker_t*) marker;
char* p = ((char*) m) + sizeof(TRI_df_attribute_marker_t);
void* f;
// remove attribute by name (p points to new location of name, but names
// are identical in old and new marker)
f = TRI_RemoveKeyAssociativeSynced(&shaper->_attributeNames, p);
assert(f != NULL);
// now re-insert same attribute with adjusted pointer
f = TRI_InsertKeyAssociativeSynced(&shaper->_attributeNames, p, m);
assert(f == NULL);
// same for attribute ids
f = TRI_RemoveKeyAssociativeSynced(&shaper->_attributeIds, &m->_aid);
assert(f != NULL);
// now re-insert same attribute with adjusted pointer
f = TRI_InsertKeyAssociativeSynced(&shaper->_attributeIds, &m->_aid, m);
assert(f == NULL);
}
return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief insert a shape, called when opening a collection
////////////////////////////////////////////////////////////////////////////////
@ -1321,7 +1379,7 @@ int TRI_InsertAttributeVocShaper (TRI_shaper_t* s,
weightedAttribute->_aid = m->_aid;
weightedAttribute->_weight = TRI_VOC_UNDEFINED_ATTRIBUTE_WEIGHT;
weightedAttribute->_attribute = (char*) m + sizeof(TRI_df_attribute_marker_t);
weightedAttribute->_attribute = TRI_DuplicateStringZ(TRI_UNKNOWN_MEM_ZONE, (char*) m + sizeof(TRI_df_attribute_marker_t));
weightedAttribute->_next = NULL;
// ..........................................................................
@ -1849,8 +1907,8 @@ int TRI_CompareShapeTypes (TRI_doc_mptr_t* leftDocument,
// generate the left and right lists.
// ............................................................................
leftNumWeightedList = compareShapeTypeJsonArrayHelper(leftShape, leftShaper, &left, &leftWeightedList);
rightNumWeightedList = compareShapeTypeJsonArrayHelper(rightShape, rightShaper, &right, &rightWeightedList);
leftNumWeightedList = CompareShapeTypeJsonArrayHelper(leftShape, leftShaper, &left, &leftWeightedList);
rightNumWeightedList = CompareShapeTypeJsonArrayHelper(rightShape, rightShaper, &right, &rightWeightedList);
// ............................................................................
// If the left and right both resulted in errors, we return equality for want
@ -1858,7 +1916,7 @@ int TRI_CompareShapeTypes (TRI_doc_mptr_t* leftDocument,
// ............................................................................
if ( (leftNumWeightedList < 0) && (rightNumWeightedList < 0) ) { // probably out of memory error
freeShapeTypeJsonArrayHelper(&leftWeightedList, &rightWeightedList);
FreeShapeTypeJsonArrayHelper(&leftWeightedList, &rightWeightedList);
return 0;
}
@ -1867,7 +1925,7 @@ int TRI_CompareShapeTypes (TRI_doc_mptr_t* leftDocument,
// ............................................................................
if (leftNumWeightedList < 0) { // probably out of memory error
freeShapeTypeJsonArrayHelper(&leftWeightedList, &rightWeightedList);
FreeShapeTypeJsonArrayHelper(&leftWeightedList, &rightWeightedList);
return -1; // attempt to compare as low as possible
}
@ -1876,7 +1934,7 @@ int TRI_CompareShapeTypes (TRI_doc_mptr_t* leftDocument,
// ............................................................................
if (rightNumWeightedList < 0) {
freeShapeTypeJsonArrayHelper(&leftWeightedList, &rightWeightedList);
FreeShapeTypeJsonArrayHelper(&leftWeightedList, &rightWeightedList);
return 1;
}
@ -1885,7 +1943,7 @@ int TRI_CompareShapeTypes (TRI_doc_mptr_t* leftDocument,
// ............................................................................
if ( (leftNumWeightedList == 0) && (rightNumWeightedList == 0) ) {
freeShapeTypeJsonArrayHelper(&leftWeightedList, &rightWeightedList);
FreeShapeTypeJsonArrayHelper(&leftWeightedList, &rightWeightedList);
return 0;
}
@ -1894,7 +1952,7 @@ int TRI_CompareShapeTypes (TRI_doc_mptr_t* leftDocument,
// ............................................................................
if (leftNumWeightedList == 0) {
freeShapeTypeJsonArrayHelper(&leftWeightedList, &rightWeightedList);
FreeShapeTypeJsonArrayHelper(&leftWeightedList, &rightWeightedList);
return -1;
}
@ -1903,7 +1961,7 @@ int TRI_CompareShapeTypes (TRI_doc_mptr_t* leftDocument,
// ............................................................................
if (rightNumWeightedList == 0) {
freeShapeTypeJsonArrayHelper(&leftWeightedList, &rightWeightedList);
FreeShapeTypeJsonArrayHelper(&leftWeightedList, &rightWeightedList);
return 1;
}
@ -1911,8 +1969,8 @@ int TRI_CompareShapeTypes (TRI_doc_mptr_t* leftDocument,
// We now have to sort the left and right weighted list according to attribute weight
// ..............................................................................
qsort(leftWeightedList, leftNumWeightedList, sizeof(weighted_attribute_t), attributeWeightCompareFunction);
qsort(rightWeightedList, rightNumWeightedList, sizeof(weighted_attribute_t), attributeWeightCompareFunction);
qsort(leftWeightedList, leftNumWeightedList, sizeof(weighted_attribute_t), AttributeWeightCompareFunction);
qsort(rightWeightedList, rightNumWeightedList, sizeof(weighted_attribute_t), AttributeWeightCompareFunction);
// ..............................................................................
// check the weight and if equal check the values. Notice that numWeightedList
@ -1970,7 +2028,7 @@ int TRI_CompareShapeTypes (TRI_doc_mptr_t* leftDocument,
// Deallocate any memory for the comparisions and return the result
// ..............................................................................
freeShapeTypeJsonArrayHelper(&leftWeightedList, &rightWeightedList);
FreeShapeTypeJsonArrayHelper(&leftWeightedList, &rightWeightedList);
return result;
}
} // end of switch (rightType)

View File

@ -126,6 +126,13 @@ void TRI_FreeVocShaper (TRI_shaper_t*);
int TRI_InitVocShaper (TRI_shaper_t*);
////////////////////////////////////////////////////////////////////////////////
/// @brief move a shape marker, called during compaction
////////////////////////////////////////////////////////////////////////////////
int TRI_MoveMarkerVocShaper (TRI_shaper_t*,
TRI_df_marker_t*);
////////////////////////////////////////////////////////////////////////////////
/// @brief insert a shape, called when opening a collection
////////////////////////////////////////////////////////////////////////////////

View File

@ -5,7 +5,7 @@
REPLICATION_LOGGER_CONFIGURE, REPLICATION_APPLIER_CONFIGURE, REPLICATION_APPLIER_START,
REPLICATION_APPLIER_STOP, REPLICATION_APPLIER_FORGET, REPLICATION_APPLIER_STATE,
REPLICATION_SYNCHRONISE, REPLICATION_SERVER_ID, CONFIGURE_ENDPOINT, REMOVE_ENDPOINT, LIST_ENDPOINTS,
SYS_BASE64DECODE, SYS_BASE64ENCODE,
SYS_BASE64DECODE, SYS_BASE64ENCODE, SYS_DEBUG_SEGFAULT,
SYS_DEBUG_CAN_USE_FAILAT, SYS_DEBUG_SET_FAILAT, SYS_DEBUG_REMOVE_FAILAT, SYS_DEBUG_CLEAR_FAILAT,
SYS_DOWNLOAD, SYS_EXECUTE, SYS_LOAD, SYS_LOG_LEVEL, SYS_MD5, SYS_OUTPUT, SYS_PROCESS_STATISTICS,
SYS_RAND, SYS_SERVER_STATISTICS, SYS_SPRINTF, SYS_TIME, SYS_START_PAGER, SYS_STOP_PAGER,
@ -375,6 +375,15 @@
delete SYS_BASE64ENCODE;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief debugSegfault
////////////////////////////////////////////////////////////////////////////////
if (typeof SYS_DEBUG_SEGFAULT !== "undefined") {
exports.debugSegfault = SYS_DEBUG_SEGFAULT;
delete SYS_DEBUG_SEGFAULT;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief debugSetFailAt
////////////////////////////////////////////////////////////////////////////////

View File

@ -5,7 +5,7 @@
REPLICATION_LOGGER_CONFIGURE, REPLICATION_APPLIER_CONFIGURE, REPLICATION_APPLIER_START,
REPLICATION_APPLIER_STOP, REPLICATION_APPLIER_FORGET, REPLICATION_APPLIER_STATE,
REPLICATION_SYNCHRONISE, REPLICATION_SERVER_ID, CONFIGURE_ENDPOINT, REMOVE_ENDPOINT, LIST_ENDPOINTS,
SYS_BASE64DECODE, SYS_BASE64ENCODE,
SYS_BASE64DECODE, SYS_BASE64ENCODE, SYS_DEBUG_SEGFAULT,
SYS_DEBUG_CAN_USE_FAILAT, SYS_DEBUG_SET_FAILAT, SYS_DEBUG_REMOVE_FAILAT, SYS_DEBUG_CLEAR_FAILAT,
SYS_DOWNLOAD, SYS_EXECUTE, SYS_LOAD, SYS_LOG_LEVEL, SYS_MD5, SYS_OUTPUT, SYS_PROCESS_STATISTICS,
SYS_RAND, SYS_SERVER_STATISTICS, SYS_SPRINTF, SYS_TIME, SYS_START_PAGER, SYS_STOP_PAGER,
@ -375,6 +375,15 @@
delete SYS_BASE64ENCODE;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief debugSegfault
////////////////////////////////////////////////////////////////////////////////
if (typeof SYS_DEBUG_SEGFAULT !== "undefined") {
exports.debugSegfault = SYS_DEBUG_SEGFAULT;
delete SYS_DEBUG_SEGFAULT;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief debugSetFailAt
////////////////////////////////////////////////////////////////////////////////

View File

@ -41,6 +41,194 @@ function CompactionSuite () {
return {
////////////////////////////////////////////////////////////////////////////////
/// @brief test shapes
////////////////////////////////////////////////////////////////////////////////
testShapes1 : function () {
var cn = "example";
internal.db._drop(cn);
var c1 = internal.db._create(cn, { "journalSize" : 1048576 });
var i;
// prefill with "trash"
for (i = 0; i < 1000; ++i) {
c1.save({ _key: "test" + i });
}
// this accesses all documents, and creates shape accessors for all of them
c1.toArray();
c1.truncate();
c1.rotate();
// create lots of different shapes
for (i = 0; i < 100; ++i) {
var doc = { _key: "test" + i };
doc["number" + i] = i;
doc["string" + i] = "test" + i;
doc["bool" + i] = (i % 2 == 0);
c1.save(doc);
}
// make sure compaction moves the shapes
c1.rotate();
internal.wait(5);
c1.truncate();
internal.wait(5);
for (i = 0; i < 100; ++i) {
var doc = { _key: "test" + i };
doc["number" + i] = i + 1;
doc["string" + i] = "test" + (i + 1);
doc["bool" + i] = (i % 2 != 0);
c1.save(doc);
}
for (i = 0; i < 100; ++i) {
var doc = c1.document("test" + i);
assertTrue(doc.hasOwnProperty("number" + i));
assertTrue(doc.hasOwnProperty("string" + i));
assertTrue(doc.hasOwnProperty("bool" + i));
assertEqual(i + 1, doc["number" + i]);
assertEqual("test" + (i + 1), doc["string" + i]);
assertEqual(i % 2 != 0, doc["bool" + i]);
}
internal.db._drop(cn);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test shapes
////////////////////////////////////////////////////////////////////////////////
testShapes2 : function () {
var cn = "example";
internal.db._drop(cn);
var c1 = internal.db._create(cn, { "journalSize" : 1048576 });
var i;
// prefill with "trash"
for (i = 0; i < 1000; ++i) {
c1.save({ _key: "test" + i });
}
c1.truncate();
c1.rotate();
// create lots of different shapes
for (i = 0; i < 100; ++i) {
var doc = { _key: "test" + i };
doc["number" + i] = i;
doc["string" + i] = "test" + i;
doc["bool" + i] = (i % 2 == 0);
c1.save(doc);
}
c1.save({ _key: "foo", name: { first: "foo", last: "bar" } });
c1.save({ _key: "bar", name: { first: "bar", last: "baz", middle: "foo" }, age: 22 });
// remove most of the shapes
for (i = 0; i < 100; ++i) {
c1.remove("test" + i);
}
// make sure compaction moves the shapes
c1.rotate();
internal.wait(5);
var doc = c1.document("foo");
assertTrue(doc.hasOwnProperty("name"));
assertFalse(doc.hasOwnProperty("age"));
assertEqual({ first: "foo", last: "bar" }, doc.name);
doc = c1.document("bar");
assertTrue(doc.hasOwnProperty("name"));
assertTrue(doc.hasOwnProperty("age"));
assertEqual({ first: "bar", last: "baz", middle: "foo" }, doc.name);
assertEqual(22, doc.age);
internal.db._drop(cn);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test shapes
////////////////////////////////////////////////////////////////////////////////
testShapesUnloadReload : function () {
var cn = "example";
internal.db._drop(cn);
var c1 = internal.db._create(cn, { "journalSize" : 1048576 });
var i;
// create lots of different shapes
for (i = 0; i < 100; ++i) {
var doc = { _key: "test" + i };
doc["number" + i] = i;
doc["string" + i] = "test" + i;
doc["bool" + i] = (i % 2 == 0);
c1.save(doc);
}
c1.save({ _key: "foo", name: { first: "foo", last: "bar" } });
c1.save({ _key: "bar", name: { first: "bar", last: "baz", middle: "foo" }, age: 22 });
// this accesses all documents, and creates shape accessors for all of them
c1.toArray();
// remove most of the shapes
for (i = 0; i < 100; ++i) {
c1.remove("test" + i);
}
// make sure compaction moves the shapes
c1.rotate();
internal.wait(5);
// unload the collection
c1.unload();
c1 = null;
internal.wait(5);
c1 = internal.db._collection(cn);
// check if documents are still there
var doc = c1.document("foo");
assertTrue(doc.hasOwnProperty("name"));
assertFalse(doc.hasOwnProperty("age"));
assertEqual({ first: "foo", last: "bar" }, doc.name);
doc = c1.document("bar");
assertTrue(doc.hasOwnProperty("name"));
assertTrue(doc.hasOwnProperty("age"));
assertEqual({ first: "bar", last: "baz", middle: "foo" }, doc.name);
assertEqual(22, doc.age);
// create docs with already existing shapes
for (i = 0; i < 100; ++i) {
var doc = { _key: "test" + i };
doc["number" + i] = i;
doc["string" + i] = "test" + i;
doc["bool" + i] = (i % 2 == 0);
c1.save(doc);
}
// check if the documents work
for (i = 0; i < 100; ++i) {
var doc = c1.document("test" + i);
assertTrue(doc.hasOwnProperty("number" + i));
assertTrue(doc.hasOwnProperty("string" + i));
assertTrue(doc.hasOwnProperty("bool" + i));
assertEqual(i, doc["number" + i]);
assertEqual("test" + i, doc["string" + i]);
assertEqual(i % 2 == 0, doc["bool" + i]);
}
internal.db._drop(cn);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test journals
////////////////////////////////////////////////////////////////////////////////
@ -48,7 +236,7 @@ function CompactionSuite () {
testJournals : function () {
var cn = "example";
internal.db._drop(cn);
var c1 = internal.db._create(cn, { "journalSize" : 1048576 } );
var c1 = internal.db._create(cn, { "journalSize" : 1048576 });
// empty collection
var fig = c1.figures();
@ -232,7 +420,7 @@ function CompactionSuite () {
}
internal.db._drop(cn);
var c1 = internal.db._create(cn, { "journalSize" : 1048576, "doCompact" : false } );
var c1 = internal.db._create(cn, { "journalSize" : 1048576, "doCompact" : false });
for (var i = 0; i < n; ++i) {
c1.save({ _key: "test" + i, value : i, payload : payload });
@ -310,7 +498,7 @@ function CompactionSuite () {
}
internal.db._drop(cn);
var c1 = internal.db._create(cn, { "journalSize" : 1048576 } );
var c1 = internal.db._create(cn, { "journalSize" : 1048576 });
for (var i = 0; i < n; ++i) {
c1.save({ _key: "test" + i, value : i, payload : payload });
@ -430,7 +618,7 @@ function CompactionSuite () {
}
internal.db._drop(cn);
var c1 = internal.db._create(cn, { "journalSize" : 1048576 } );
var c1 = internal.db._create(cn, { "journalSize" : 1048576 });
for (var i = 0; i < n; ++i) {
c1.save({ value : i, payload : payload });

View File

@ -34,11 +34,6 @@
// --SECTION-- private variables
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Debugging
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief a global string containing the currently registered failure points
/// the string is a comma-separated list of point names
@ -60,19 +55,10 @@ TRI_read_write_lock_t FailurePointsLock;
#endif
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- private functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Debugging
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief make a delimited value from a string, so we can unambigiously
/// search for it (e.g. searching for just "foo" would find "foo" and "foobar",
@ -102,19 +88,23 @@ static char* MakeValue (char const* value) {
#endif
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Debugging
/// @{
/// @brief cause a segmentation violation
////////////////////////////////////////////////////////////////////////////////
void TRI_SegfaultDebugging (char const* message) {
#ifdef TRI_ENABLE_MAINTAINER_MODE
fprintf(stderr, "causing intentional segfault: %s\n", message);
*((char*) -1) = '!';
#endif
}
////////////////////////////////////////////////////////////////////////////////
/// @brief check whether we should fail at a specific failure point
////////////////////////////////////////////////////////////////////////////////
@ -357,10 +347,6 @@ void TRI_ShutdownDebugging () {
#endif
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE
// -----------------------------------------------------------------------------

View File

@ -75,6 +75,12 @@ extern "C" {
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief cause a segmentation violation
////////////////////////////////////////////////////////////////////////////////
void TRI_SegfaultDebugging (char const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief check whether we should fail at a failure point
////////////////////////////////////////////////////////////////////////////////

View File

@ -2180,6 +2180,31 @@ static v8::Handle<v8::Value> JS_Wait (v8::Arguments const& argv) {
return scope.Close(v8::Undefined());
}
////////////////////////////////////////////////////////////////////////////////
/// @brief intentionally cause a segfault
///
/// @FUN{internal.debugSegfault(@FA{message})}
///
/// intentionally cause a segmentation violation
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> JS_DebugSegfault (v8::Arguments const& argv) {
v8::HandleScope scope;
// extract arguments
if (argv.Length() != 1) {
TRI_V8_EXCEPTION_USAGE(scope, "debugSegfault(<message>)");
}
const string message = TRI_ObjectToString(argv[0]);
TRI_SegfaultDebugging(message.c_str());
// we may get here if we are in non-maintainer mode
return scope.Close(v8::Undefined());
}
////////////////////////////////////////////////////////////////////////////////
/// @brief set a failure point
///
@ -2820,6 +2845,7 @@ void TRI_InitV8Utils (v8::Handle<v8::Context> context,
TRI_AddGlobalFunctionVocbase(context, "SYS_WAIT", JS_Wait);
// debugging functions
TRI_AddGlobalFunctionVocbase(context, "SYS_DEBUG_SEGFAULT", JS_DebugSegfault);
TRI_AddGlobalFunctionVocbase(context, "SYS_DEBUG_SET_FAILAT", JS_DebugSetFailAt);
TRI_AddGlobalFunctionVocbase(context, "SYS_DEBUG_REMOVE_FAILAT", JS_DebugRemoveFailAt);
TRI_AddGlobalFunctionVocbase(context, "SYS_DEBUG_CLEAR_FAILAT", JS_DebugClearFailAt);