mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' of github.com:triAGENS/ArangoDB into devel
This commit is contained in:
commit
6bf1d00d18
|
@ -15,6 +15,8 @@ v1.4
|
|||
v1.3.1 (2013-XX-XX)
|
||||
-------------------
|
||||
|
||||
* issue #530: ReferenceError: ArangoError is not a constructor
|
||||
|
||||
* issue #535: Problem with AQL user functions javascript API
|
||||
|
||||
* set --javascript.app-path for test execution to prevent startup error
|
||||
|
|
|
@ -28,7 +28,11 @@ start () {
|
|||
chown arangodb $PIDDIR
|
||||
|
||||
$DAEMON -c $CONF --pid-file "$PIDFILE" --supervisor $@
|
||||
log_end_msg $?
|
||||
RETVAL=$?
|
||||
|
||||
log_end_msg $RETVAL
|
||||
|
||||
return $RETVAL
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
|
@ -36,25 +40,30 @@ case "$1" in
|
|||
log_daemon_msg "Starting $DESC" "$NAME"
|
||||
|
||||
start
|
||||
exit $?
|
||||
;;
|
||||
|
||||
stop)
|
||||
log_daemon_msg "Stopping $DESC" "$NAME"
|
||||
|
||||
start-stop-daemon --stop --quiet --oknodo --exec $DAEMON --startas $DAEMON
|
||||
log_end_msg $?
|
||||
RETVAL=$?
|
||||
log_end_msg $RETVAL
|
||||
|
||||
test -f $PIDFILE && rm -f $PIDFILE
|
||||
exit $RETVAL
|
||||
;;
|
||||
|
||||
restart)
|
||||
$0 stop
|
||||
sleep 3
|
||||
$0 start
|
||||
exit $?
|
||||
;;
|
||||
|
||||
force-reload)
|
||||
$0 restart
|
||||
exit $?
|
||||
;;
|
||||
|
||||
status)
|
||||
|
@ -65,6 +74,7 @@ case "$1" in
|
|||
log_daemon_msg "Upgrading $DESC" "$NAME"
|
||||
|
||||
start --upgrade
|
||||
exit $?
|
||||
;;
|
||||
|
||||
*)
|
||||
|
|
|
@ -786,6 +786,7 @@ static TRI_aql_node_t* OptimiseLimit (TRI_aql_statement_walker_t* const walker,
|
|||
TRI_aql_node_t* node) {
|
||||
TRI_aql_scope_t* scope;
|
||||
TRI_aql_node_t* limit;
|
||||
aql_optimiser_t* optimiser = (aql_optimiser_t*) walker->_data;
|
||||
int64_t limitValue;
|
||||
|
||||
assert(node);
|
||||
|
@ -794,7 +795,27 @@ static TRI_aql_node_t* OptimiseLimit (TRI_aql_statement_walker_t* const walker,
|
|||
assert(scope);
|
||||
|
||||
limit = TRI_AQL_NODE_MEMBER(node, 1);
|
||||
limitValue = TRI_AQL_NODE_INT(limit);
|
||||
|
||||
if (limit->_type != TRI_AQL_NODE_VALUE) {
|
||||
return node;
|
||||
}
|
||||
|
||||
if (limit->_value._type == TRI_AQL_TYPE_INT) {
|
||||
limitValue = TRI_AQL_NODE_INT(limit);
|
||||
}
|
||||
else if (limit->_value._type == TRI_AQL_TYPE_DOUBLE) {
|
||||
limitValue = (int64_t) TRI_AQL_NODE_DOUBLE(limit);
|
||||
}
|
||||
else if (limit->_value._type == TRI_AQL_TYPE_NULL) {
|
||||
limitValue = 0;
|
||||
}
|
||||
else if (limit->_value._type == TRI_AQL_TYPE_BOOL) {
|
||||
limitValue = (int64_t) TRI_AQL_NODE_BOOL(limit);
|
||||
}
|
||||
else {
|
||||
TRI_SetErrorContextAql(optimiser->_context, TRI_ERROR_QUERY_NUMBER_OUT_OF_RANGE, NULL);
|
||||
return node;
|
||||
}
|
||||
|
||||
// check for the easy case, a limit value of 0, e.g. LIMIT 10, 0
|
||||
if (limitValue == 0) {
|
||||
|
|
|
@ -750,17 +750,20 @@ static int RollbackInsert (TRI_document_collection_t* document,
|
|||
|
||||
static int RollbackUpdate (TRI_document_collection_t* document,
|
||||
TRI_doc_mptr_t* newHeader,
|
||||
TRI_doc_mptr_t* oldHeader) {
|
||||
TRI_doc_mptr_t* oldHeader,
|
||||
bool adjustHeader) {
|
||||
int res;
|
||||
|
||||
assert(newHeader != NULL);
|
||||
assert(oldHeader != NULL);
|
||||
|
||||
|
||||
// ignore any errors we're getting from this
|
||||
DeleteSecondaryIndexes(document, newHeader, true);
|
||||
|
||||
// put back the header into its old position
|
||||
document->_headers->move(document->_headers, newHeader, oldHeader);
|
||||
|
||||
if (adjustHeader) {
|
||||
// put back the header into its old position
|
||||
document->_headers->move(document->_headers, newHeader, oldHeader);
|
||||
}
|
||||
|
||||
*newHeader = *oldHeader;
|
||||
|
||||
|
@ -779,7 +782,8 @@ static int RollbackUpdate (TRI_document_collection_t* document,
|
|||
|
||||
static int RollbackRemove (TRI_document_collection_t* document,
|
||||
TRI_doc_mptr_t* newHeader,
|
||||
TRI_doc_mptr_t* oldHeader) {
|
||||
TRI_doc_mptr_t* oldHeader,
|
||||
bool adjustHeader) {
|
||||
int res;
|
||||
|
||||
// there is no new header
|
||||
|
@ -794,8 +798,10 @@ static int RollbackRemove (TRI_document_collection_t* document,
|
|||
LOG_ERROR("error rolling back remove operation");
|
||||
}
|
||||
|
||||
// put back the header into its old position
|
||||
document->_headers->relink(document->_headers, oldHeader, oldHeader);
|
||||
if (adjustHeader) {
|
||||
// put back the header into its old position
|
||||
document->_headers->relink(document->_headers, oldHeader, oldHeader);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -851,7 +857,7 @@ static int InsertDocument (TRI_transaction_collection_t* trxCollection,
|
|||
TRI_doc_mptr_t* mptr,
|
||||
bool* freeMarker) {
|
||||
TRI_document_collection_t* document;
|
||||
bool written;
|
||||
bool directOperation;
|
||||
int res;
|
||||
|
||||
TRI_ASSERT_MAINTAINER(*freeMarker == true);
|
||||
|
@ -893,8 +899,8 @@ static int InsertDocument (TRI_transaction_collection_t* trxCollection,
|
|||
&marker->base,
|
||||
totalSize,
|
||||
forceSync,
|
||||
&written);
|
||||
if (! written) {
|
||||
&directOperation);
|
||||
if (! directOperation) {
|
||||
*freeMarker = false;
|
||||
}
|
||||
|
||||
|
@ -918,11 +924,13 @@ static int InsertDocument (TRI_transaction_collection_t* trxCollection,
|
|||
idx->postInsert(trxCollection, idx, header);
|
||||
}
|
||||
}
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
else {
|
||||
// something has failed.... now delete from the indexes again
|
||||
RollbackInsert(document, header, NULL);
|
||||
}
|
||||
|
||||
// something has failed.... now delete from the indexes again
|
||||
RollbackInsert(document, header, NULL);
|
||||
TRI_ASSERT_MAINTAINER(*freeMarker == true);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -988,7 +996,7 @@ static int RemoveDocument (TRI_transaction_collection_t* trxCollection,
|
|||
TRI_primary_collection_t* primary;
|
||||
TRI_document_collection_t* document;
|
||||
TRI_doc_mptr_t* header;
|
||||
bool written;
|
||||
bool directOperation;
|
||||
int res;
|
||||
|
||||
TRI_ASSERT_MAINTAINER(*freeMarker == true);
|
||||
|
@ -1048,22 +1056,24 @@ static int RemoveDocument (TRI_transaction_collection_t* trxCollection,
|
|||
&marker->base,
|
||||
totalSize,
|
||||
forceSync,
|
||||
&written);
|
||||
&directOperation);
|
||||
|
||||
if (! written) {
|
||||
if (! directOperation) {
|
||||
*freeMarker = false;
|
||||
}
|
||||
|
||||
if (res == TRI_ERROR_NO_ERROR) {
|
||||
if (written) {
|
||||
if (directOperation) {
|
||||
// release the header pointer
|
||||
document->_headers->release(document->_headers, header);
|
||||
}
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
else {
|
||||
// deletion failed. roll back
|
||||
RollbackRemove(document, NULL, header);
|
||||
}
|
||||
|
||||
// deletion failed. roll back
|
||||
RollbackRemove(document, NULL, header, ! directOperation);
|
||||
TRI_ASSERT_MAINTAINER(*freeMarker == true);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -1153,7 +1163,7 @@ static int UpdateDocument (TRI_transaction_collection_t* trxCollection,
|
|||
TRI_doc_mptr_t* newHeader;
|
||||
TRI_doc_mptr_t oldData;
|
||||
int res;
|
||||
bool written;
|
||||
bool directOperation;
|
||||
|
||||
TRI_ASSERT_MAINTAINER(*freeMarker == true);
|
||||
document = (TRI_document_collection_t*) trxCollection->_collection->_collection;
|
||||
|
@ -1215,23 +1225,25 @@ static int UpdateDocument (TRI_transaction_collection_t* trxCollection,
|
|||
&marker->base,
|
||||
totalSize,
|
||||
forceSync,
|
||||
&written);
|
||||
&directOperation);
|
||||
|
||||
if (! written) {
|
||||
if (! directOperation) {
|
||||
*freeMarker = false;
|
||||
}
|
||||
|
||||
if (res == TRI_ERROR_NO_ERROR) {
|
||||
if (written) {
|
||||
if (directOperation) {
|
||||
document->_headers->moveBack(document->_headers, oldHeader);
|
||||
}
|
||||
|
||||
// write new header into result
|
||||
*mptr = *((TRI_doc_mptr_t*) newHeader);
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
else {
|
||||
RollbackUpdate(document, newHeader, &oldData);
|
||||
}
|
||||
|
||||
RollbackUpdate(document, newHeader, &oldData, ! directOperation);
|
||||
TRI_ASSERT_MAINTAINER(*freeMarker == true);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -2988,10 +3000,10 @@ int TRI_RollbackOperationDocumentCollection (TRI_document_collection_t* document
|
|||
res = RollbackInsert(document, newHeader, NULL);
|
||||
}
|
||||
else if (type == TRI_VOC_DOCUMENT_OPERATION_UPDATE) {
|
||||
res = RollbackUpdate(document, newHeader, oldData);
|
||||
res = RollbackUpdate(document, newHeader, oldData, true);
|
||||
}
|
||||
else if (type == TRI_VOC_DOCUMENT_OPERATION_REMOVE) {
|
||||
res = RollbackRemove(document, NULL, oldHeader);
|
||||
res = RollbackRemove(document, NULL, oldHeader, true);
|
||||
}
|
||||
else {
|
||||
res = TRI_ERROR_INTERNAL;
|
||||
|
@ -3057,6 +3069,10 @@ int TRI_WriteOperationDocumentCollection (TRI_document_collection_t* document,
|
|||
bool waitForSync) {
|
||||
int res;
|
||||
|
||||
TRI_DEBUG_INTENTIONAL_FAIL_IF("TRI_WriteOperationDocumentCollection") {
|
||||
return TRI_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
if (type == TRI_VOC_DOCUMENT_OPERATION_INSERT) {
|
||||
res = WriteInsertMarker(document, (TRI_doc_document_key_marker_t*) marker, newHeader, totalSize, waitForSync);
|
||||
}
|
||||
|
|
|
@ -234,29 +234,38 @@ static void MoveHeader (TRI_headers_t* h,
|
|||
if (old->_prev == NULL) {
|
||||
headers->_begin = header;
|
||||
}
|
||||
else if (headers->_begin == header) {
|
||||
if (header->_next != NULL) {
|
||||
headers->_begin = header->_next;
|
||||
}
|
||||
}
|
||||
|
||||
if (old->_next == NULL) {
|
||||
headers->_end = header;
|
||||
}
|
||||
if (header->_prev != NULL && header->_prev == old->_next) {
|
||||
header->_prev->_next = NULL;
|
||||
headers->_end = header->_prev;
|
||||
else if (headers->_end == header) {
|
||||
if (header->_prev != NULL) {
|
||||
headers->_end = header->_prev;
|
||||
}
|
||||
}
|
||||
else if (header->_next != NULL && header->_next == old->_prev) {
|
||||
header->_next->_prev = NULL;
|
||||
headers->_begin = header->_next;
|
||||
|
||||
if (header->_prev != NULL) {
|
||||
if (header->_prev == old->_next) {
|
||||
header->_prev->_next = NULL;
|
||||
}
|
||||
else {
|
||||
header->_prev->_next = header->_next;
|
||||
}
|
||||
}
|
||||
/*
|
||||
if (headers->_begin == old->_next) {
|
||||
// adjust list start pointer
|
||||
headers->_begin = header;
|
||||
|
||||
if (header->_next != NULL) {
|
||||
if (header->_next == old->_prev) {
|
||||
header->_next->_prev = NULL;
|
||||
}
|
||||
else {
|
||||
header->_next->_prev = header->_prev;
|
||||
}
|
||||
}
|
||||
*/
|
||||
/*
|
||||
if (old->_next == NULL) {
|
||||
// adjust list end pointer
|
||||
headers->_end = header;
|
||||
}
|
||||
*/
|
||||
|
||||
if (old->_prev != NULL) {
|
||||
old->_prev->_next = header;
|
||||
|
@ -273,11 +282,7 @@ static void MoveHeader (TRI_headers_t* h,
|
|||
else {
|
||||
header->_next = NULL;
|
||||
}
|
||||
/*
|
||||
header->_prev = old->_prev;
|
||||
header->_next = old->_next;
|
||||
*/
|
||||
|
||||
|
||||
TRI_ASSERT_MAINTAINER(headers->_begin != NULL);
|
||||
TRI_ASSERT_MAINTAINER(headers->_end != NULL);
|
||||
TRI_ASSERT_MAINTAINER(header->_prev != header);
|
||||
|
|
|
@ -491,12 +491,15 @@ static int AddCollectionOperation (TRI_transaction_collection_t* trxCollection,
|
|||
transaction_operation_t trxOperation;
|
||||
int res;
|
||||
|
||||
TRI_DEBUG_INTENTIONAL_FAIL_IF("AddCollectionOperation-OOM") {
|
||||
return TRI_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if (trxCollection->_operations == NULL) {
|
||||
res = InitCollectionOperations(trxCollection);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
return res;
|
||||
return TRI_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -514,21 +517,23 @@ static int AddCollectionOperation (TRI_transaction_collection_t* trxCollection,
|
|||
}
|
||||
|
||||
res = TRI_PushBackVector(trxCollection->_operations, &trxOperation);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
return TRI_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if (res == TRI_ERROR_NO_ERROR) {
|
||||
if (type == TRI_VOC_DOCUMENT_OPERATION_UPDATE) {
|
||||
TRI_document_collection_t* document = (TRI_document_collection_t*) trxCollection->_collection->_collection;
|
||||
if (type == TRI_VOC_DOCUMENT_OPERATION_UPDATE) {
|
||||
TRI_document_collection_t* document = (TRI_document_collection_t*) trxCollection->_collection->_collection;
|
||||
|
||||
document->_headers->moveBack(document->_headers, oldHeader);
|
||||
}
|
||||
else if (type == TRI_VOC_DOCUMENT_OPERATION_REMOVE) {
|
||||
TRI_document_collection_t* document = (TRI_document_collection_t*) trxCollection->_collection->_collection;
|
||||
document->_headers->moveBack(document->_headers, oldHeader);
|
||||
}
|
||||
else if (type == TRI_VOC_DOCUMENT_OPERATION_REMOVE) {
|
||||
TRI_document_collection_t* document = (TRI_document_collection_t*) trxCollection->_collection->_collection;
|
||||
|
||||
document->_headers->unlink(document->_headers, oldHeader);
|
||||
}
|
||||
document->_headers->unlink(document->_headers, oldHeader);
|
||||
}
|
||||
|
||||
return res;
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1687,7 +1692,7 @@ int TRI_AddOperationCollectionTransaction (TRI_transaction_collection_t* trxColl
|
|||
TRI_df_marker_t* marker,
|
||||
size_t totalSize,
|
||||
bool syncRequested,
|
||||
bool* written) {
|
||||
bool* directOperation) {
|
||||
TRI_transaction_t* trx;
|
||||
TRI_primary_collection_t* primary;
|
||||
int res;
|
||||
|
@ -1699,13 +1704,8 @@ int TRI_AddOperationCollectionTransaction (TRI_transaction_collection_t* trxColl
|
|||
trxCollection->_originalRevision = primary->base._info._tick;
|
||||
}
|
||||
|
||||
// the tick value of a marker must always be greater than the tick value of any other
|
||||
// existing marker in the collection
|
||||
TRI_SetRevisionDocumentCollection((TRI_document_collection_t*) primary, marker->_tick);
|
||||
|
||||
if (trx->_hints & ((TRI_transaction_hint_t) TRI_TRANSACTION_HINT_SINGLE_OPERATION)) {
|
||||
// just one operation in the transaction. we can write the marker directly
|
||||
// TODO: error checking
|
||||
res = TRI_WriteOperationDocumentCollection((TRI_document_collection_t*) primary,
|
||||
type,
|
||||
newHeader,
|
||||
|
@ -1714,14 +1714,22 @@ int TRI_AddOperationCollectionTransaction (TRI_transaction_collection_t* trxColl
|
|||
marker,
|
||||
totalSize,
|
||||
syncRequested || trxCollection->_waitForSync || trx->_waitForSync);
|
||||
*written = true;
|
||||
*directOperation = true;
|
||||
}
|
||||
else {
|
||||
trx->_hasOperations = true;
|
||||
|
||||
res = AddCollectionOperation(trxCollection, type, newHeader, oldHeader, oldData, marker, totalSize);
|
||||
|
||||
*written = false;
|
||||
|
||||
if (res == TRI_ERROR_NO_ERROR) {
|
||||
// if everything went well, this will ensure we don't double free etc. headers
|
||||
*directOperation = false;
|
||||
}
|
||||
else {
|
||||
TRI_ASSERT_MAINTAINER(res == TRI_ERROR_OUT_OF_MEMORY);
|
||||
// if something went wrong, this will ensure that we'll not manipulate headers twice
|
||||
*directOperation = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (syncRequested) {
|
||||
|
@ -1732,6 +1740,14 @@ int TRI_AddOperationCollectionTransaction (TRI_transaction_collection_t* trxColl
|
|||
trx->_waitForSync = true;
|
||||
}
|
||||
|
||||
if (res == TRI_ERROR_NO_ERROR) {
|
||||
// operation succeeded, now update the revision id for the collection
|
||||
|
||||
// the tick value of a marker must always be greater than the tick value of any other
|
||||
// existing marker in the collection
|
||||
TRI_SetRevisionDocumentCollection((TRI_document_collection_t*) primary, marker->_tick);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
@font-face {
|
||||
font-family: 'Droid Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Droid Sans'), local('DroidSans'), url(/_admin/ttf/droidsans.ttf) format('truetype');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Droid Sans';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Droid Sans Bold'), local('DroidSans-Bold'), url(/_admin/ttf/droidsans-bold.ttf) format('truetype');
|
||||
}
|
|
@ -8,7 +8,7 @@
|
|||
<meta name="description" content="ArangoDB Admin Web Interface">
|
||||
<meta name="author" content="Heiko Kernbach">
|
||||
|
||||
<link href='http://fonts.googleapis.com/css?family=Droid+Sans:400,700' rel='stylesheet' type='text/css'/>
|
||||
<link href='css/droidsans.css' rel='stylesheet' type='text/css'/>
|
||||
<link href='css/swagger/hightlight.default.css' media='screen' rel='stylesheet' type='text/css'/>
|
||||
<link href='css/swagger/screen.css' media='screen' rel='stylesheet' type='text/css'/>
|
||||
|
||||
|
@ -132,8 +132,6 @@
|
|||
<script src="js/modules/org/arangodb/arango-collection-common.js"></script>
|
||||
<script src="js/modules/org/arangodb/arango-collection.js"></script>
|
||||
<script src="js/modules/org/arangodb/arango-database.js"></script>
|
||||
<script src="js/modules/org/arangodb/arango-error-common.js"></script>
|
||||
<script src="js/modules/org/arangodb/arango-error.js"></script>
|
||||
<script src="js/modules/org/arangodb/arango-query-cursor.js"></script>
|
||||
<script src="js/modules/org/arangodb/arango-statement-common.js"></script>
|
||||
<script src="js/modules/org/arangodb/arango-statement.js"></script>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*jslint indent: 2, nomen: true, maxlen: 120, vars: true, white: true, plusplus: true, nonpropdel: true, proto: true, regexp: true */
|
||||
/*global require, module, Module, ArangoError, SYS_DOWNLOAD,
|
||||
/*global require, module, Module, ArangoError, 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,
|
||||
SYS_SHA256, SYS_WAIT, SYS_PARSE, SYS_IMPORT_CSV_FILE, SYS_IMPORT_JSON_FILE, SYS_LOG,
|
||||
|
@ -59,15 +60,23 @@
|
|||
/// @brief ArangoError
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
try {
|
||||
// necessary for the web interface
|
||||
if (ArangoError !== undefined) {
|
||||
exports.ArangoError = ArangoError;
|
||||
delete ArangoError;
|
||||
}
|
||||
if (typeof ArangoError !== "undefined") {
|
||||
exports.ArangoError = ArangoError;
|
||||
delete ArangoError;
|
||||
}
|
||||
catch (err) {
|
||||
exports.ArangoError = require("org/arangodb/arango-error").ArangoError;
|
||||
else {
|
||||
exports.ArangoError = function (error) {
|
||||
if (error !== undefined) {
|
||||
this.error = error.error;
|
||||
this.code = error.code;
|
||||
this.errorNum = error.errorNum;
|
||||
this.errorMessage = error.errorMessage;
|
||||
}
|
||||
|
||||
this.message = this.toString();
|
||||
}
|
||||
|
||||
exports.ArangoError.prototype = Error.prototype;
|
||||
}
|
||||
|
||||
exports.ArangoError.prototype._PRINT = function (context) {
|
||||
|
@ -216,6 +225,42 @@
|
|||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief debugSetFailAt
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (typeof SYS_DEBUG_SET_FAILAT !== "undefined") {
|
||||
exports.debugSetFailAt = SYS_DEBUG_SET_FAILAT;
|
||||
delete SYS_DEBUG_SET_FAILAT;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief debugRemoveFailAt
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (typeof SYS_DEBUG_REMOVE_FAILAT !== "undefined") {
|
||||
exports.debugRemoveFailAt = SYS_DEBUG_REMOVE_FAILAT;
|
||||
delete SYS_DEBUG_REMOVE_FAILAT;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief debugClearFailAt
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (typeof SYS_DEBUG_CLEAR_FAILAT !== "undefined") {
|
||||
exports.debugClearFailAt = SYS_DEBUG_CLEAR_FAILAT;
|
||||
delete SYS_DEBUG_CLEAR_FAILAT;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief debugCanUseFailAt
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (typeof SYS_DEBUG_CAN_USE_FAILAT !== "undefined") {
|
||||
exports.debugCanUseFailAt = SYS_DEBUG_CAN_USE_FAILAT;
|
||||
delete SYS_DEBUG_CAN_USE_FAILAT;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief download
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -247,7 +247,7 @@ var unregisterFunctionsGroup = function (group) {
|
|||
/// @fn JSF_aqlfunctions_register
|
||||
/// @brief register an AQL user function
|
||||
///
|
||||
/// @FUN{aqlfunctions.register(@FA{name}, @FA{code}, @FA{isDeterministic}, @FA{testValues})}
|
||||
/// @FUN{aqlfunctions.register(@FA{name}, @FA{code}, @FA{isDeterministic})}
|
||||
///
|
||||
/// Registers an AQL user function, identified by a fully qualified function
|
||||
/// name. The function code in @FA{code} must be specified as a Javascript
|
||||
|
@ -280,7 +280,7 @@ var registerFunction = function (name, code, isDeterministic) {
|
|||
var testCode = "(function() { var callback = " + code + "; return callback; })()";
|
||||
|
||||
try {
|
||||
var res = INTERNAL.executeScript(testCode, undefined, "(user function " + name + ")");
|
||||
var res = internal.executeScript(testCode, undefined, "(user function " + name + ")");
|
||||
}
|
||||
catch (err1) {
|
||||
var err = new ArangoError();
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
module.define("org/arangodb/arango-error-common", function(exports, module) {
|
||||
/*jslint indent: 2, nomen: true, maxlen: 100, sloppy: true, vars: true, white: true, plusplus: true */
|
||||
/*global require */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief ArangoError
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2013 triagens GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Achim Brandt
|
||||
/// @author Dr. Frank Celler
|
||||
/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
var arangodb = require("org/arangodb");
|
||||
|
||||
var ArangoError = require("org/arangodb/arango-error").ArangoError;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- ArangoError
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup ArangoShell
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief prints the object
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ArangoError.prototype._PRINT = function (context) {
|
||||
context.output += this.toString();
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief converts into a string
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ArangoError.prototype.toString = function() {
|
||||
var errorNum = this.errorNum;
|
||||
var errorMessage = this.errorMessage;
|
||||
|
||||
return "[ArangoError " + errorNum + ": " + errorMessage + "]";
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- END-OF-FILE
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @}\\|/\\*jslint"
|
||||
// End:
|
||||
});
|
|
@ -1,78 +0,0 @@
|
|||
module.define("org/arangodb/arango-error", function(exports, module) {
|
||||
/*jslint indent: 2, nomen: true, maxlen: 100, sloppy: true, vars: true, white: true, plusplus: true */
|
||||
/*global require, exports */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief ArangoError
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2013 triagens GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Achim Brandt
|
||||
/// @author Dr. Frank Celler
|
||||
/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
var internal = require("internal");
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- ArangoError
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors and destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup ArangoShell
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief constructor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function ArangoError (error) {
|
||||
if (error !== undefined) {
|
||||
this.error = error.error;
|
||||
this.code = error.code;
|
||||
this.errorNum = error.errorNum;
|
||||
this.errorMessage = error.errorMessage;
|
||||
}
|
||||
}
|
||||
|
||||
exports.ArangoError = ArangoError;
|
||||
|
||||
// must be called after exporting ArangoError
|
||||
require("org/arangodb/arango-error-common");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- END-OF-FILE
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @}\\|/\\*jslint"
|
||||
// End:
|
||||
});
|
|
@ -1,2 +1,2 @@
|
|||
<div class="copy"><p>Copyright 2012 triAGENS GmbH | <a href="#about">About</a></p></div>
|
||||
<div class="copy"><p>Copyright (c) triAGENS GmbH | <a href="#about">About</a></p></div>
|
||||
|
||||
|
|
|
@ -60,8 +60,15 @@ var dashboardView = Backbone.View.extend({
|
|||
$(this.el).html(this.template.text);
|
||||
|
||||
//Client calculated charts
|
||||
self.genCustomCategory("Client calculated charts", "custom", "Customized Charts");
|
||||
self.genCustomChart();
|
||||
self.genCustomCategories();
|
||||
self.genCustomChartDescription(
|
||||
"userTime + systemTime",
|
||||
"custom",
|
||||
"totalTime2",
|
||||
"Total Time (User+System)",
|
||||
"accumulated",
|
||||
"seconds"
|
||||
);
|
||||
|
||||
$.each(this.options.description.models[0].attributes.groups, function () {
|
||||
$('.thumbnails').append(
|
||||
|
@ -98,6 +105,11 @@ var dashboardView = Backbone.View.extend({
|
|||
}
|
||||
return this;
|
||||
},
|
||||
//generate function for all custom categories
|
||||
genCustomCategories: function () {
|
||||
this.genCustomCategory("Client calculated charts", "custom", "Customized Charts");
|
||||
},
|
||||
//generate a custom category
|
||||
genCustomCategory: function(description, group, name) {
|
||||
this.options.description.models[0].attributes.groups.push({
|
||||
"description":description,
|
||||
|
@ -105,22 +117,26 @@ var dashboardView = Backbone.View.extend({
|
|||
"name":name
|
||||
});
|
||||
},
|
||||
genCustomChart: function () {
|
||||
//totalTime
|
||||
//generate a custom description
|
||||
genCustomChartDescription: function (description, group, identifier, name, type, units) {
|
||||
var figure = {
|
||||
"description" : "userTime + systemTime",
|
||||
"group" : "custom",
|
||||
"identifier" : "totalTime2",
|
||||
"name" : "Total Time (User+System)",
|
||||
"type" : "accumulated",
|
||||
"units" : "seconds"
|
||||
"description" : description,
|
||||
"group" : group,
|
||||
"identifier" : identifier,
|
||||
"name" : name,
|
||||
"type" : type,
|
||||
"units" : units
|
||||
};
|
||||
this.options.description.models[0].attributes.figures.push(figure);
|
||||
this.renderFigure(figure);
|
||||
},
|
||||
//calculate customized chart value functions here
|
||||
updateCustomChartValues: function () {
|
||||
this.totalTime2();
|
||||
},
|
||||
|
||||
updateCustomChart: function () {
|
||||
//totalTime
|
||||
//custom chart value calculation for totalTime2
|
||||
totalTime2: function () {
|
||||
var val1 = this.collection.models[0].attributes.system.userTime;
|
||||
var val2 = this.collection.models[0].attributes.system.systemTime;
|
||||
var totalTime2Value = val1+val2;
|
||||
|
@ -283,7 +299,7 @@ var dashboardView = Backbone.View.extend({
|
|||
|
||||
calculateSeries: function (flush) {
|
||||
var self = this;
|
||||
self.updateCustomChart();
|
||||
self.updateCustomChartValues();
|
||||
|
||||
var timeStamp = Math.round(new Date() * 10);
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ var shellView = Backbone.View.extend({
|
|||
var internal = require("internal");
|
||||
var arangodb = require("org/arangodb");
|
||||
var client = require("org/arangodb/arangosh");
|
||||
var header = 'Welcome to arangosh Copyright (c) 2012 triAGENS GmbH.\n';
|
||||
var header = 'Welcome to arangosh Copyright (c) triAGENS GmbH.\n';
|
||||
window.jqconsole = $('#replShell').jqconsole(header, 'JSH> ', "...>");
|
||||
this.executeJs(internal.print(client.HELP));
|
||||
// Abort prompt on Ctrl+Z.
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Swagger UI</title>
|
||||
<link href='http://fonts.googleapis.com/css?family=Droid+Sans:400,700' rel='stylesheet' type='text/css'/>
|
||||
<link href='css/droidsans.css' rel='stylesheet' type='text/css'/>
|
||||
<link href='css/swagger/hightlight.default.css' media='screen' rel='stylesheet' type='text/css'/>
|
||||
<link href='css/swagger/screen.css' media='screen' rel='stylesheet' type='text/css'/>
|
||||
<script src='js/lib/jquery-1.8.0.min.js' type='text/javascript'></script>
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -1,5 +1,6 @@
|
|||
/*jslint indent: 2, nomen: true, maxlen: 120, vars: true, white: true, plusplus: true, nonpropdel: true, proto: true, regexp: true */
|
||||
/*global require, module, Module, ArangoError, SYS_DOWNLOAD,
|
||||
/*global require, module, Module, ArangoError, 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,
|
||||
SYS_SHA256, SYS_WAIT, SYS_PARSE, SYS_IMPORT_CSV_FILE, SYS_IMPORT_JSON_FILE, SYS_LOG,
|
||||
|
@ -59,15 +60,23 @@
|
|||
/// @brief ArangoError
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
try {
|
||||
// necessary for the web interface
|
||||
if (ArangoError !== undefined) {
|
||||
exports.ArangoError = ArangoError;
|
||||
delete ArangoError;
|
||||
}
|
||||
if (typeof ArangoError !== "undefined") {
|
||||
exports.ArangoError = ArangoError;
|
||||
delete ArangoError;
|
||||
}
|
||||
catch (err) {
|
||||
exports.ArangoError = require("org/arangodb/arango-error").ArangoError;
|
||||
else {
|
||||
exports.ArangoError = function (error) {
|
||||
if (error !== undefined) {
|
||||
this.error = error.error;
|
||||
this.code = error.code;
|
||||
this.errorNum = error.errorNum;
|
||||
this.errorMessage = error.errorMessage;
|
||||
}
|
||||
|
||||
this.message = this.toString();
|
||||
}
|
||||
|
||||
exports.ArangoError.prototype = Error.prototype;
|
||||
}
|
||||
|
||||
exports.ArangoError.prototype._PRINT = function (context) {
|
||||
|
@ -216,6 +225,42 @@
|
|||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief debugSetFailAt
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (typeof SYS_DEBUG_SET_FAILAT !== "undefined") {
|
||||
exports.debugSetFailAt = SYS_DEBUG_SET_FAILAT;
|
||||
delete SYS_DEBUG_SET_FAILAT;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief debugRemoveFailAt
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (typeof SYS_DEBUG_REMOVE_FAILAT !== "undefined") {
|
||||
exports.debugRemoveFailAt = SYS_DEBUG_REMOVE_FAILAT;
|
||||
delete SYS_DEBUG_REMOVE_FAILAT;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief debugClearFailAt
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (typeof SYS_DEBUG_CLEAR_FAILAT !== "undefined") {
|
||||
exports.debugClearFailAt = SYS_DEBUG_CLEAR_FAILAT;
|
||||
delete SYS_DEBUG_CLEAR_FAILAT;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief debugCanUseFailAt
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (typeof SYS_DEBUG_CAN_USE_FAILAT !== "undefined") {
|
||||
exports.debugCanUseFailAt = SYS_DEBUG_CAN_USE_FAILAT;
|
||||
delete SYS_DEBUG_CAN_USE_FAILAT;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief download
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -2438,6 +2438,155 @@ function transactionRollbackSuite () {
|
|||
c1.save({ _key: "test" });
|
||||
assertEqual(3, c1.count());
|
||||
assertEqual([ "bar", "baz", "test" ], sortedKeys(c1));
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test: rollback a mixed workload
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testRollbackMixed1 : function () {
|
||||
c1 = db._create(cn1);
|
||||
|
||||
var i;
|
||||
|
||||
for (i = 0; i < 100; ++i) {
|
||||
c1.save({ _key: "key" + i, value: i });
|
||||
}
|
||||
|
||||
var obj = {
|
||||
collections : {
|
||||
write: [ cn1 ]
|
||||
},
|
||||
action : function () {
|
||||
|
||||
for (i = 0; i < 50; ++i) {
|
||||
c1.remove("key" + i);
|
||||
}
|
||||
|
||||
for (i = 50; i < 100; ++i) {
|
||||
c1.update("key" + i, { value: i - 50 });
|
||||
}
|
||||
|
||||
c1.remove("key50");
|
||||
throw "doh!";
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
TRANSACTION(obj);
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
}
|
||||
|
||||
assertEqual(100, c1.count());
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test: rollback a mixed workload
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testRollbackMixed2 : function () {
|
||||
c1 = db._create(cn1);
|
||||
|
||||
c1.save({ _key: "foo" });
|
||||
c1.save({ _key: "bar" });
|
||||
|
||||
var obj = {
|
||||
collections : {
|
||||
write: [ cn1 ]
|
||||
},
|
||||
action : function () {
|
||||
var i;
|
||||
|
||||
for (i = 0; i < 10; ++i) {
|
||||
c1.save({ _key: "key" + i, value: i });
|
||||
}
|
||||
|
||||
for (i = 0; i < 5; ++i) {
|
||||
c1.remove("key" + i);
|
||||
}
|
||||
|
||||
for (i = 5; i < 10; ++i) {
|
||||
c1.update("key" + i, { value: i - 5 });
|
||||
}
|
||||
|
||||
c1.remove("key5");
|
||||
throw "doh!";
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
TRANSACTION(obj);
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
}
|
||||
|
||||
assertEqual(2, c1.count());
|
||||
assertEqual("foo", c1.document("foo")._key);
|
||||
assertEqual("bar", c1.document("bar")._key);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test: rollback a mixed workload
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testRollbackMixed3 : function () {
|
||||
c1 = db._create(cn1);
|
||||
|
||||
c1.save({ _key: "foo" });
|
||||
c1.save({ _key: "bar" });
|
||||
|
||||
var obj = {
|
||||
collections : {
|
||||
write: [ cn1 ]
|
||||
},
|
||||
action : function () {
|
||||
var i;
|
||||
|
||||
for (i = 0; i < 10; ++i) {
|
||||
c1.save({ _key: "key" + i, value: i });
|
||||
}
|
||||
|
||||
for (i = 0; i < 10; ++i) {
|
||||
c1.remove("key" + i);
|
||||
}
|
||||
|
||||
for (i = 0; i < 10; ++i) {
|
||||
c1.save({ _key: "key" + i, value: i });
|
||||
}
|
||||
|
||||
for (i = 0; i < 10; ++i) {
|
||||
c1.update("key" + i, { value: i - 5 });
|
||||
}
|
||||
|
||||
for (i = 0; i < 10; ++i) {
|
||||
c1.update("key" + i, { value: i + 5 });
|
||||
}
|
||||
|
||||
for (i = 0; i < 10; ++i) {
|
||||
c1.remove("key" + i);
|
||||
}
|
||||
|
||||
for (i = 0; i < 10; ++i) {
|
||||
c1.save({ _key: "key" + i, value: i });
|
||||
}
|
||||
|
||||
throw "doh!";
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
TRANSACTION(obj);
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
}
|
||||
|
||||
assertEqual(2, c1.count());
|
||||
assertEqual("foo", c1.document("foo")._key);
|
||||
assertEqual("bar", c1.document("bar")._key);
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -2898,6 +3047,483 @@ function transactionCrossCollectionSuite () {
|
|||
};
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- test suite
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test suite
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function transactionServerFailuresSuite () {
|
||||
var cn = "UnitTestsTransaction";
|
||||
|
||||
var c = null;
|
||||
|
||||
return {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief set up
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
setUp : function () {
|
||||
internal.debugClearFailAt();
|
||||
db._drop(cn);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief tear down
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
tearDown : function () {
|
||||
internal.debugClearFailAt();
|
||||
|
||||
if (c !== null) {
|
||||
c.drop();
|
||||
}
|
||||
|
||||
c = null;
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test: rollback in case of a server-side fail
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testRollbackInsertSingle1 : function () {
|
||||
c = db._create(cn);
|
||||
|
||||
internal.debugSetFailAt("TRI_WriteOperationDocumentCollection");
|
||||
try {
|
||||
c.save({ _key: "foo" });
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
assertEqual(internal.errors.ERROR_INTERNAL.code, err.errorNum);
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test: rollback in case of a server-side fail
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testRollbackInsertSingle2 : function () {
|
||||
c = db._create(cn);
|
||||
|
||||
c.save({ _key: "foo" });
|
||||
internal.debugSetFailAt("TRI_WriteOperationDocumentCollection");
|
||||
try {
|
||||
c.save({ _key: "foo2" });
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
assertEqual(internal.errors.ERROR_INTERNAL.code, err.errorNum);
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test: rollback in case of a server-side fail
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testRollbackInsertMulti1 : function () {
|
||||
c = db._create(cn);
|
||||
c.save({ _key: "baz" });
|
||||
|
||||
var obj = {
|
||||
collections : {
|
||||
write: [ cn ]
|
||||
},
|
||||
action : function () {
|
||||
c.save({ _key: "foo" });
|
||||
internal.debugSetFailAt("AddCollectionOperation-OOM");
|
||||
c.save({ _key: "bar" });
|
||||
fail();
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
TRANSACTION(obj);
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
assertEqual(internal.errors.ERROR_OUT_OF_MEMORY.code, err.errorNum);
|
||||
}
|
||||
|
||||
assertEqual(1, c.count());
|
||||
assertEqual("baz", c.document("baz")._key);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test: rollback in case of a server-side fail
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testRollbackInsertMulti2 : function () {
|
||||
c = db._create(cn);
|
||||
|
||||
var i;
|
||||
for (i = 0; i < 100; ++i) {
|
||||
c.save({ _key: "key" + i });
|
||||
}
|
||||
|
||||
var obj = {
|
||||
collections : {
|
||||
write: [ cn ]
|
||||
},
|
||||
action : function () {
|
||||
for (i = 0; i < 100; ++i) {
|
||||
c.save({ _key: "foo" + i });
|
||||
}
|
||||
internal.debugSetFailAt("AddCollectionOperation-OOM");
|
||||
c.save({ _key: "bar" });
|
||||
fail();
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
TRANSACTION(obj);
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
assertEqual(internal.errors.ERROR_OUT_OF_MEMORY.code, err.errorNum);
|
||||
}
|
||||
|
||||
assertEqual(100, c.count());
|
||||
assertEqual("key0", c.document("key0")._key);
|
||||
assertEqual("key99", c.document("key99")._key);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test: rollback in case of a server-side fail
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testRollbackUpdateSingle1 : function () {
|
||||
c = db._create(cn);
|
||||
|
||||
c.save({ _key: "foo", value: 1 });
|
||||
|
||||
internal.debugSetFailAt("TRI_WriteOperationDocumentCollection");
|
||||
try {
|
||||
c.update("foo", { value: 2 });
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
assertEqual(internal.errors.ERROR_INTERNAL.code, err.errorNum);
|
||||
}
|
||||
|
||||
assertEqual(1, c.count());
|
||||
assertEqual("foo", c.document("foo")._key);
|
||||
assertEqual(1, c.document("foo").value);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test: rollback in case of a server-side fail
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testRollbackUpdateSingle2 : function () {
|
||||
c = db._create(cn);
|
||||
|
||||
c.save({ _key: "foo", value: 1 });
|
||||
c.save({ _key: "bar", value: "a" });
|
||||
|
||||
c.update("foo", { value: 2 });
|
||||
internal.debugSetFailAt("TRI_WriteOperationDocumentCollection");
|
||||
try {
|
||||
c.update("bar", { value: "b" });
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
assertEqual(internal.errors.ERROR_INTERNAL.code, err.errorNum);
|
||||
}
|
||||
|
||||
assertEqual(2, c.count());
|
||||
assertEqual("foo", c.document("foo")._key);
|
||||
assertEqual(2, c.document("foo").value);
|
||||
assertEqual("bar", c.document("bar")._key);
|
||||
assertEqual("a", c.document("bar").value);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test: rollback in case of a server-side fail
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testRollbackUpdateMulti1 : function () {
|
||||
c = db._create(cn);
|
||||
|
||||
c.save({ _key: "foo", value: 1 });
|
||||
c.save({ _key: "bar", value: "a" });
|
||||
|
||||
var obj = {
|
||||
collections : {
|
||||
write: [ cn ]
|
||||
},
|
||||
action : function () {
|
||||
c.update("foo", { value: 2 });
|
||||
internal.debugSetFailAt("AddCollectionOperation-OOM");
|
||||
c.update("bar", { value: "b" });
|
||||
fail();
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
TRANSACTION(obj);
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
assertEqual(internal.errors.ERROR_OUT_OF_MEMORY.code, err.errorNum);
|
||||
}
|
||||
|
||||
assertEqual(2, c.count());
|
||||
assertEqual("foo", c.document("foo")._key);
|
||||
assertEqual(1, c.document("foo").value);
|
||||
assertEqual("bar", c.document("bar")._key);
|
||||
assertEqual("a", c.document("bar").value);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test: rollback in case of a server-side fail
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testRollbackUpdateMulti2 : function () {
|
||||
c = db._create(cn);
|
||||
|
||||
c.save({ _key: "foo", value: 1 });
|
||||
c.save({ _key: "bar", value: "a" });
|
||||
|
||||
var obj = {
|
||||
collections : {
|
||||
write: [ cn ]
|
||||
},
|
||||
action : function () {
|
||||
internal.debugSetFailAt("AddCollectionOperation-OOM");
|
||||
c.update("foo", { value: 2 });
|
||||
fail();
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
TRANSACTION(obj);
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
assertEqual(internal.errors.ERROR_OUT_OF_MEMORY.code, err.errorNum);
|
||||
}
|
||||
|
||||
assertEqual(2, c.count());
|
||||
assertEqual("foo", c.document("foo")._key);
|
||||
assertEqual(1, c.document("foo").value);
|
||||
assertEqual("bar", c.document("bar")._key);
|
||||
assertEqual("a", c.document("bar").value);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test: rollback in case of a server-side fail
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testRollbackRemoveSingle1 : function () {
|
||||
c = db._create(cn);
|
||||
|
||||
c.save({ _key: "foo" });
|
||||
|
||||
internal.debugSetFailAt("TRI_WriteOperationDocumentCollection");
|
||||
try {
|
||||
c.remove("foo");
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
assertEqual(internal.errors.ERROR_INTERNAL.code, err.errorNum);
|
||||
}
|
||||
|
||||
assertEqual(1, c.count());
|
||||
assertEqual("foo", c.document("foo")._key);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test: rollback in case of a server-side fail
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testRollbackRemoveSingle2 : function () {
|
||||
c = db._create(cn);
|
||||
|
||||
c.save({ _key: "foo" });
|
||||
c.save({ _key: "bar" });
|
||||
|
||||
internal.debugSetFailAt("TRI_WriteOperationDocumentCollection");
|
||||
try {
|
||||
c.remove("foo");
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
assertEqual(internal.errors.ERROR_INTERNAL.code, err.errorNum);
|
||||
}
|
||||
|
||||
assertEqual(2, c.count());
|
||||
assertEqual("foo", c.document("foo")._key);
|
||||
assertEqual("bar", c.document("bar")._key);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test: rollback in case of a server-side fail
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testRollbackRemoveMulti1 : function () {
|
||||
c = db._create(cn);
|
||||
|
||||
c.save({ _key: "foo" });
|
||||
c.save({ _key: "bar" });
|
||||
|
||||
var obj = {
|
||||
collections : {
|
||||
write: [ cn ]
|
||||
},
|
||||
action : function () {
|
||||
c.remove("foo");
|
||||
internal.debugSetFailAt("AddCollectionOperation-OOM");
|
||||
c.remove("bar");
|
||||
fail();
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
TRANSACTION(obj);
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
assertEqual(internal.errors.ERROR_OUT_OF_MEMORY.code, err.errorNum);
|
||||
}
|
||||
|
||||
assertEqual(2, c.count());
|
||||
assertEqual("foo", c.document("foo")._key);
|
||||
assertEqual("bar", c.document("bar")._key);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test: rollback in case of a server-side fail
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testRollbackRemoveMulti2 : function () {
|
||||
c = db._create(cn);
|
||||
|
||||
c.save({ _key: "foo" });
|
||||
c.save({ _key: "bar" });
|
||||
|
||||
var obj = {
|
||||
collections : {
|
||||
write: [ cn ]
|
||||
},
|
||||
action : function () {
|
||||
internal.debugSetFailAt("AddCollectionOperation-OOM");
|
||||
c.remove("foo");
|
||||
fail();
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
TRANSACTION(obj);
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
assertEqual(internal.errors.ERROR_OUT_OF_MEMORY.code, err.errorNum);
|
||||
}
|
||||
|
||||
assertEqual(2, c.count());
|
||||
assertEqual("foo", c.document("foo")._key);
|
||||
assertEqual("bar", c.document("bar")._key);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test: rollback in case of a server-side fail
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testRollbackRemoveMixed1 : function () {
|
||||
c = db._create(cn);
|
||||
|
||||
var i;
|
||||
|
||||
for (i = 0; i < 100; ++i) {
|
||||
c.save({ _key: "key" + i, value: i });
|
||||
}
|
||||
|
||||
var obj = {
|
||||
collections : {
|
||||
write: [ cn ]
|
||||
},
|
||||
action : function () {
|
||||
|
||||
for (i = 0; i < 50; ++i) {
|
||||
c.remove("key" + i);
|
||||
}
|
||||
|
||||
for (i = 50; i < 100; ++i) {
|
||||
c.update("key" + i, { value: i - 50 });
|
||||
}
|
||||
|
||||
internal.debugSetFailAt("AddCollectionOperation-OOM");
|
||||
c.remove("key50");
|
||||
fail();
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
TRANSACTION(obj);
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
assertEqual(internal.errors.ERROR_OUT_OF_MEMORY.code, err.errorNum);
|
||||
}
|
||||
|
||||
assertEqual(100, c.count());
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test: rollback in case of a server-side fail
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testRollbackRemoveMixed2 : function () {
|
||||
c = db._create(cn);
|
||||
|
||||
c.save({ _key: "foo" });
|
||||
c.save({ _key: "bar" });
|
||||
|
||||
var obj = {
|
||||
collections : {
|
||||
write: [ cn ]
|
||||
},
|
||||
action : function () {
|
||||
var i;
|
||||
|
||||
for (i = 0; i < 10; ++i) {
|
||||
c.save({ _key: "key" + i, value: i });
|
||||
}
|
||||
|
||||
for (i = 0; i < 5; ++i) {
|
||||
c.remove("key" + i);
|
||||
}
|
||||
|
||||
for (i = 5; i < 10; ++i) {
|
||||
c.update("key" + i, { value: i - 5 });
|
||||
}
|
||||
|
||||
internal.debugSetFailAt("AddCollectionOperation-OOM");
|
||||
c.remove("key5");
|
||||
fail();
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
TRANSACTION(obj);
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
assertEqual(internal.errors.ERROR_OUT_OF_MEMORY.code, err.errorNum);
|
||||
}
|
||||
|
||||
assertEqual(2, c.count());
|
||||
assertEqual("foo", c.document("foo")._key);
|
||||
assertEqual("bar", c.document("bar")._key);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- main
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -2915,6 +3541,11 @@ jsunity.run(transactionRollbackSuite);
|
|||
jsunity.run(transactionCountSuite);
|
||||
jsunity.run(transactionCrossCollectionSuite);
|
||||
|
||||
// only run this test suite if server-side failures are enabled
|
||||
if (internal.debugCanUseFailAt()) {
|
||||
jsunity.run(transactionServerFailuresSuite);
|
||||
}
|
||||
|
||||
return jsunity.done();
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -130,6 +130,7 @@ typedef long suseconds_t;
|
|||
#define TRI_WITHIN_COMMON 1
|
||||
#include "BasicsC/voc-errors.h"
|
||||
#include "BasicsC/error.h"
|
||||
#include "BasicsC/debugging.h"
|
||||
#include "BasicsC/memory.h"
|
||||
#include "BasicsC/mimetypes.h"
|
||||
#include "BasicsC/structures.h"
|
||||
|
|
|
@ -0,0 +1,371 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief debugging helpers
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2004-2013 triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Jan Steemann
|
||||
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "BasicsC/common.h"
|
||||
|
||||
#include "BasicsC/debugging.h"
|
||||
#include "BasicsC/locks.h"
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef TRI_ENABLE_MAINTAINER_MODE
|
||||
|
||||
static char* FailurePoints;
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief a read-write lock for thread-safe access to the failure-points list
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef TRI_ENABLE_MAINTAINER_MODE
|
||||
|
||||
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",
|
||||
/// so we'll be putting the value inside some delimiter: ",foo,")
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef TRI_ENABLE_MAINTAINER_MODE
|
||||
|
||||
static char* MakeValue (char const* value) {
|
||||
char* delimited;
|
||||
|
||||
if (value == NULL || strlen(value) == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
delimited = TRI_Allocate(TRI_CORE_MEM_ZONE, strlen(value) + 3, false);
|
||||
|
||||
if (delimited != NULL) {
|
||||
memcpy(delimited + 1, value, strlen(value));
|
||||
delimited[0] = ',';
|
||||
delimited[strlen(value) + 1] = ',';
|
||||
delimited[strlen(value) + 2] = '\0';
|
||||
}
|
||||
|
||||
return delimited;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Debugging
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check whether we should fail at a specific failure point
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef TRI_ENABLE_MAINTAINER_MODE
|
||||
|
||||
bool TRI_ShouldFailDebugging (char const* value) {
|
||||
char* found;
|
||||
char* checkValue;
|
||||
|
||||
checkValue = MakeValue(value);
|
||||
|
||||
if (checkValue == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TRI_ReadLockReadWriteLock(&FailurePointsLock);
|
||||
|
||||
if (FailurePoints == NULL) {
|
||||
found = NULL;
|
||||
}
|
||||
else {
|
||||
found = strstr(FailurePoints, checkValue);
|
||||
}
|
||||
|
||||
TRI_ReadUnlockReadWriteLock(&FailurePointsLock);
|
||||
|
||||
TRI_Free(TRI_CORE_MEM_ZONE, checkValue);
|
||||
|
||||
return (found != NULL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief add a failure point
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_AddFailurePointDebugging (char const* value) {
|
||||
|
||||
#ifdef TRI_ENABLE_MAINTAINER_MODE
|
||||
|
||||
char* found;
|
||||
char* checkValue;
|
||||
|
||||
checkValue = MakeValue(value);
|
||||
|
||||
if (checkValue == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
TRI_WriteLockReadWriteLock(&FailurePointsLock);
|
||||
|
||||
if (FailurePoints == NULL) {
|
||||
found = NULL;
|
||||
}
|
||||
else {
|
||||
found = strstr(FailurePoints, checkValue);
|
||||
}
|
||||
|
||||
if (found == NULL) {
|
||||
// not yet found. so add it
|
||||
char* copy;
|
||||
size_t n;
|
||||
|
||||
n = strlen(checkValue);
|
||||
|
||||
if (FailurePoints == NULL) {
|
||||
copy = TRI_Allocate(TRI_CORE_MEM_ZONE, n + 1, false);
|
||||
|
||||
if (copy == NULL) {
|
||||
TRI_WriteUnlockReadWriteLock(&FailurePointsLock);
|
||||
TRI_Free(TRI_CORE_MEM_ZONE, checkValue);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(copy, checkValue, n);
|
||||
copy[n] = '\0';
|
||||
}
|
||||
else {
|
||||
copy = TRI_Allocate(TRI_CORE_MEM_ZONE, n + strlen(FailurePoints), false);
|
||||
|
||||
if (copy == NULL) {
|
||||
TRI_WriteUnlockReadWriteLock(&FailurePointsLock);
|
||||
TRI_Free(TRI_CORE_MEM_ZONE, checkValue);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(copy, FailurePoints, strlen(FailurePoints));
|
||||
memcpy(copy + strlen(FailurePoints) - 1, checkValue, n);
|
||||
copy[strlen(FailurePoints) + n - 1] = '\0';
|
||||
}
|
||||
|
||||
FailurePoints = copy;
|
||||
}
|
||||
|
||||
TRI_WriteUnlockReadWriteLock(&FailurePointsLock);
|
||||
TRI_Free(TRI_CORE_MEM_ZONE, checkValue);
|
||||
|
||||
#else
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief remove a failure points
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_RemoveFailurePointDebugging (char const* value) {
|
||||
|
||||
#ifdef TRI_ENABLE_MAINTAINER_MODE
|
||||
|
||||
char* checkValue;
|
||||
|
||||
TRI_WriteLockReadWriteLock(&FailurePointsLock);
|
||||
|
||||
if (FailurePoints == NULL) {
|
||||
TRI_WriteUnlockReadWriteLock(&FailurePointsLock);
|
||||
return;
|
||||
}
|
||||
|
||||
checkValue = MakeValue(value);
|
||||
|
||||
if (checkValue != NULL) {
|
||||
char* found;
|
||||
char* copy;
|
||||
size_t n;
|
||||
|
||||
found = strstr(FailurePoints, checkValue);
|
||||
|
||||
if (found == NULL) {
|
||||
TRI_WriteUnlockReadWriteLock(&FailurePointsLock);
|
||||
TRI_Free(TRI_CORE_MEM_ZONE, checkValue);
|
||||
return;
|
||||
}
|
||||
|
||||
if (strlen(FailurePoints) - strlen(checkValue) <= 2) {
|
||||
TRI_Free(TRI_CORE_MEM_ZONE, FailurePoints);
|
||||
FailurePoints = NULL;
|
||||
|
||||
TRI_WriteUnlockReadWriteLock(&FailurePointsLock);
|
||||
TRI_Free(TRI_CORE_MEM_ZONE, checkValue);
|
||||
return;
|
||||
}
|
||||
|
||||
copy = TRI_Allocate(TRI_CORE_MEM_ZONE, strlen(FailurePoints) - strlen(checkValue) + 2, false);
|
||||
|
||||
if (copy == NULL) {
|
||||
TRI_WriteUnlockReadWriteLock(&FailurePointsLock);
|
||||
TRI_Free(TRI_CORE_MEM_ZONE, checkValue);
|
||||
return;
|
||||
}
|
||||
|
||||
// copy start of string
|
||||
n = found - FailurePoints;
|
||||
memcpy(copy, FailurePoints, n);
|
||||
|
||||
// copy remainder of string
|
||||
memcpy(copy + n, found + strlen(checkValue) - 1, strlen(FailurePoints) - strlen(checkValue) - n + 1);
|
||||
|
||||
copy[strlen(FailurePoints) - strlen(checkValue) + 1] = '\0';
|
||||
TRI_Free(TRI_CORE_MEM_ZONE, FailurePoints);
|
||||
FailurePoints = copy;
|
||||
|
||||
TRI_WriteUnlockReadWriteLock(&FailurePointsLock);
|
||||
TRI_Free(TRI_CORE_MEM_ZONE, checkValue);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief clear all failure points
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_ClearFailurePointsDebugging () {
|
||||
#ifdef TRI_ENABLE_MAINTAINER_MODE
|
||||
|
||||
TRI_WriteLockReadWriteLock(&FailurePointsLock);
|
||||
|
||||
if (FailurePoints != NULL) {
|
||||
TRI_Free(TRI_CORE_MEM_ZONE, FailurePoints);
|
||||
}
|
||||
|
||||
FailurePoints = NULL;
|
||||
|
||||
TRI_WriteUnlockReadWriteLock(&FailurePointsLock);
|
||||
|
||||
#else
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns whether failure point debugging can be used
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_CanUseFailurePointsDebugging () {
|
||||
#ifdef TRI_ENABLE_MAINTAINER_MODE
|
||||
|
||||
return true;
|
||||
|
||||
#else
|
||||
|
||||
return false;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief initialise the debugging
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_InitialiseDebugging () {
|
||||
#ifdef TRI_ENABLE_MAINTAINER_MODE
|
||||
|
||||
FailurePoints = NULL;
|
||||
TRI_InitReadWriteLock(&FailurePointsLock);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief shutdown the debugging
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_ShutdownDebugging () {
|
||||
#ifdef TRI_ENABLE_MAINTAINER_MODE
|
||||
|
||||
if (FailurePoints != NULL) {
|
||||
TRI_Free(TRI_CORE_MEM_ZONE, FailurePoints);
|
||||
}
|
||||
|
||||
FailurePoints = NULL;
|
||||
|
||||
TRI_DestroyReadWriteLock(&FailurePointsLock);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- END-OF-FILE
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}"
|
||||
// End:
|
|
@ -0,0 +1,137 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief debugging helpers
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2004-2013 triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Jan Steemann
|
||||
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TRIAGENS_BASICS_C_DEBUGGING_H
|
||||
#define TRIAGENS_BASICS_C_DEBUGGING_H 1
|
||||
|
||||
#ifndef TRI_WITHIN_COMMON
|
||||
#error use <BasicsC/common.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public defines
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Debugging
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief macro TRI_DEBUG_INTENTIONAL_FAIL_IF
|
||||
/// this macro can be used in maintainer mode to make the server fail at
|
||||
/// certain locations in the C code. The points at which a failure is actually
|
||||
/// triggered can be defined at runtime using TRI_AddFailurePointDebugging().
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef TRI_ENABLE_MAINTAINER_MODE
|
||||
|
||||
#define TRI_DEBUG_INTENTIONAL_FAIL_IF(what) if (TRI_ShouldFailDebugging(what))
|
||||
|
||||
#else
|
||||
|
||||
#define TRI_DEBUG_INTENTIONAL_FAIL_IF(what) if (false)
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Debugging
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check whether we should fail at a failure point
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef TRI_ENABLE_MAINTAINER_MODE
|
||||
|
||||
bool TRI_ShouldFailDebugging (char const*);
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief add a failure point
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_AddFailurePointDebugging (char const*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief remove a failure point
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_RemoveFailurePointDebugging (char const*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief clear all failure points
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_ClearFailurePointsDebugging (void);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns whether failure point debugging can be used
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_CanUseFailurePointsDebugging (void);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief initialise the debugging
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_InitialiseDebugging (void);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief shutdown the debugging
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_ShutdownDebugging (void);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}"
|
||||
// End:
|
|
@ -52,6 +52,7 @@
|
|||
|
||||
void TRI_InitialiseC (int argc, char* argv[]) {
|
||||
TRI_InitialiseMemory();
|
||||
TRI_InitialiseDebugging();
|
||||
TRI_InitialiseMersenneTwister();
|
||||
TRI_InitialiseError();
|
||||
TRI_InitialiseFiles();
|
||||
|
@ -78,6 +79,7 @@ void TRI_ShutdownC () {
|
|||
TRI_ShutdownMimetypes();
|
||||
TRI_ShutdownFiles();
|
||||
TRI_ShutdownError();
|
||||
TRI_ShutdownDebugging();
|
||||
TRI_ShutdownMemory();
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ lib_libarango_a_SOURCES = \
|
|||
lib/BasicsC/associative.c \
|
||||
lib/BasicsC/conversions.c \
|
||||
lib/BasicsC/csv.c \
|
||||
lib/BasicsC/debugging.c \
|
||||
lib/BasicsC/error.c \
|
||||
lib/BasicsC/files.c \
|
||||
lib/BasicsC/hashes.c \
|
||||
|
|
|
@ -1959,6 +1959,92 @@ static v8::Handle<v8::Value> JS_Wait (v8::Arguments const& argv) {
|
|||
return scope.Close(v8::Undefined());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief set a failure point
|
||||
///
|
||||
/// @FUN{internal.debugSetFailAt(@FA{point})}
|
||||
///
|
||||
/// Set a point for an intentional system failure
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static v8::Handle<v8::Value> JS_DebugSetFailAt (v8::Arguments const& argv) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
// extract arguments
|
||||
if (argv.Length() != 1) {
|
||||
TRI_V8_EXCEPTION_USAGE(scope, "debugSetFailAt(<point>)");
|
||||
}
|
||||
|
||||
string point = TRI_ObjectToString(argv[0]);
|
||||
|
||||
TRI_AddFailurePointDebugging(point.c_str());
|
||||
|
||||
return scope.Close(v8::Undefined());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief remove a failure point
|
||||
///
|
||||
/// @FUN{internal.debugRemoveFailAt(@FA{point})}
|
||||
///
|
||||
/// Remove a point for an intentional system failure
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static v8::Handle<v8::Value> JS_DebugRemoveFailAt (v8::Arguments const& argv) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
// extract arguments
|
||||
if (argv.Length() != 1) {
|
||||
TRI_V8_EXCEPTION_USAGE(scope, "debugRemoveFailAt(<point>)");
|
||||
}
|
||||
|
||||
string point = TRI_ObjectToString(argv[0]);
|
||||
|
||||
TRI_RemoveFailurePointDebugging(point.c_str());
|
||||
|
||||
return scope.Close(v8::Undefined());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief clear all failure points
|
||||
///
|
||||
/// @FUN{internal.debugClearFailAt()}
|
||||
///
|
||||
/// Remove all points for intentional system failures
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static v8::Handle<v8::Value> JS_DebugClearFailAt (v8::Arguments const& argv) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
// extract arguments
|
||||
if (argv.Length() != 0) {
|
||||
TRI_V8_EXCEPTION_USAGE(scope, "debugClearFailAt()");
|
||||
}
|
||||
|
||||
TRI_ClearFailurePointsDebugging();
|
||||
|
||||
return scope.Close(v8::Undefined());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns whether failure points can be used
|
||||
///
|
||||
/// @FUN{internal.debugCanUseFailAt()}
|
||||
///
|
||||
/// Returns whether failure points can be be used
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static v8::Handle<v8::Value> JS_DebugCanUseFailAt (v8::Arguments const& argv) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
// extract arguments
|
||||
if (argv.Length() != 0) {
|
||||
TRI_V8_EXCEPTION_USAGE(scope, "debugCanUseFailAt()");
|
||||
}
|
||||
|
||||
return scope.Close(TRI_CanUseFailurePointsDebugging() ? v8::True() : v8::False());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns the current request and connection statistics
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -2481,6 +2567,12 @@ void TRI_InitV8Utils (v8::Handle<v8::Context> context,
|
|||
TRI_AddGlobalFunctionVocbase(context, "SYS_TIME", JS_Time);
|
||||
TRI_AddGlobalFunctionVocbase(context, "SYS_WAIT", JS_Wait);
|
||||
|
||||
// debugging functions
|
||||
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);
|
||||
TRI_AddGlobalFunctionVocbase(context, "SYS_DEBUG_CAN_USE_FAILAT", JS_DebugCanUseFailAt);
|
||||
|
||||
// .............................................................................
|
||||
// create the global variables
|
||||
// .............................................................................
|
||||
|
|
Loading…
Reference in New Issue