1
0
Fork 0

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

This commit is contained in:
gschwab 2014-03-14 08:50:09 +01:00
commit fe596f98d6
23 changed files with 558 additions and 163 deletions

View File

@ -1,12 +1,17 @@
v2.1.0 (XXXX-XX-XX)
-------------------
* don't requeue identical context methods in V8 threads in case a method is
already registered
* removed arangod command line option `--database.remove-on-compacted`
v2.0.1 (XXXX-XX-XX)
-------------------
* fixed display of missing error messages and codes in arangosh
* when creating a collection via the web interface, the collection type was always
"document", regardless of the user's choice

View File

@ -363,6 +363,7 @@ SHELL_COMMON = \
@top_srcdir@/js/common/tests/shell-document.js \
@top_srcdir@/js/common/tests/shell-download.js \
@top_srcdir@/js/common/tests/shell-edge.js \
@top_srcdir@/js/common/tests/shell-errors.js \
@top_srcdir@/js/common/tests/shell-fs.js \
@top_srcdir@/js/common/tests/shell-graph-traversal.js \
@top_srcdir@/js/common/tests/shell-graph-algorithms.js \

View File

@ -60,6 +60,32 @@ using namespace triagens::arango;
using namespace triagens::rest;
using namespace std;
// -----------------------------------------------------------------------------
// --SECTION-- class GlobalContextMethods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief initialise code for pre-defined actions
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief reload the routing cache
////////////////////////////////////////////////////////////////////////////////
std::string const GlobalContextMethods::CodeReloadRouting = "require(\"org/arangodb/actions\").reloadRouting()";
////////////////////////////////////////////////////////////////////////////////
/// @brief flush the modules cache
////////////////////////////////////////////////////////////////////////////////
std::string const GlobalContextMethods::CodeFlushModuleCache = "require(\"internal\").flushModuleCache()";
////////////////////////////////////////////////////////////////////////////////
/// @brief reload AQL functions
////////////////////////////////////////////////////////////////////////////////
std::string const GlobalContextMethods::CodeReloadAql = "try { require(\"org/arangodb/ahuacatl\").reload(); } catch (err) { }";
////////////////////////////////////////////////////////////////////////////////
/// @brief we'll store deprecated config option values in here
////////////////////////////////////////////////////////////////////////////////
@ -128,10 +154,25 @@ namespace {
/// @brief adds a global method
////////////////////////////////////////////////////////////////////////////////
void ApplicationV8::V8Context::addGlobalContextMethod (string const& method) {
MUTEX_LOCKER(_globalMethodsLock);
bool ApplicationV8::V8Context::addGlobalContextMethod (string const& method) {
GlobalContextMethods::MethodType type = GlobalContextMethods::getType(method);
_globalMethods.push_back(method);
if (type == GlobalContextMethods::TYPE_UNKNOWN) {
return false;
}
MUTEX_LOCKER(_globalMethodsLock);
for (size_t i = 0; i < _globalMethods.size(); ++i) {
if (_globalMethods[i] == type) {
// action is already registered. no need to register it again
return true;
}
}
// insert action into vector
_globalMethods.push_back(type);
return true;
}
////////////////////////////////////////////////////////////////////////////////
@ -141,7 +182,7 @@ void ApplicationV8::V8Context::addGlobalContextMethod (string const& method) {
void ApplicationV8::V8Context::handleGlobalContextMethods () {
v8::HandleScope scope;
vector<string> copy;
vector<GlobalContextMethods::MethodType> copy;
{
// we need to copy the vector of functions so we do not need to hold the
@ -153,13 +194,14 @@ void ApplicationV8::V8Context::handleGlobalContextMethods () {
_globalMethods.clear();
}
for (vector<string>::const_iterator i = copy.begin(); i != copy.end(); ++i) {
string const& func = *i;
for (vector<GlobalContextMethods::MethodType>::const_iterator i = copy.begin(); i != copy.end(); ++i) {
GlobalContextMethods::MethodType const type = *i;
string const func = GlobalContextMethods::getCode(type);
LOG_DEBUG("executing global context methods '%s' for context %d", func.c_str(), (int) _id);
TRI_ExecuteJavaScriptString(_context,
v8::String::New(func.c_str()),
v8::String::New(func.c_str(), func.size()),
v8::String::New("global context method"),
false);
}
@ -366,10 +408,16 @@ void ApplicationV8::exitContext (V8Context* context) {
/// @brief adds a global context functions to be executed asap
////////////////////////////////////////////////////////////////////////////////
void ApplicationV8::addGlobalContextMethod (string const& method) {
bool ApplicationV8::addGlobalContextMethod (string const& method) {
bool result = true;
for (size_t i = 0; i < _nrInstances; ++i) {
_contexts[i]->addGlobalContextMethod(method);
if (! _contexts[i]->addGlobalContextMethod(method)) {
result = false;
}
}
return result;
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -55,12 +55,76 @@ namespace triagens {
class ApplicationScheduler;
}
namespace arango {
// -----------------------------------------------------------------------------
// --SECTION-- class GlobalContextMethods
// -----------------------------------------------------------------------------
class GlobalContextMethods {
public:
////////////////////////////////////////////////////////////////////////////////
/// @brief method type
////////////////////////////////////////////////////////////////////////////////
enum MethodType {
TYPE_UNKNOWN = 0,
TYPE_RELOAD_ROUTING,
TYPE_FLUSH_MODULE_CACHE,
TYPE_RELOAD_AQL
};
////////////////////////////////////////////////////////////////////////////////
/// @brief get a method type number from a type string
////////////////////////////////////////////////////////////////////////////////
static MethodType getType (std::string const& type) {
if (type == "reloadRouting") {
return TYPE_RELOAD_ROUTING;
}
if (type == "flushModuleCache") {
return TYPE_FLUSH_MODULE_CACHE;
}
if (type == "reloadAql") {
return TYPE_RELOAD_AQL;
}
return TYPE_UNKNOWN;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief get code for a method
////////////////////////////////////////////////////////////////////////////////
static std::string const getCode (MethodType type) {
switch (type) {
case TYPE_RELOAD_ROUTING:
return CodeReloadRouting;
case TYPE_FLUSH_MODULE_CACHE:
return CodeFlushModuleCache;
case TYPE_RELOAD_AQL:
return CodeReloadAql;
case TYPE_UNKNOWN:
default:
return "";
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief static strings with the code for each method
////////////////////////////////////////////////////////////////////////////////
static std::string const CodeReloadRouting;
static std::string const CodeFlushModuleCache;
static std::string const CodeReloadAql;
};
// -----------------------------------------------------------------------------
// --SECTION-- class ApplicationV8
// -----------------------------------------------------------------------------
namespace arango {
////////////////////////////////////////////////////////////////////////////////
/// @brief application simple user and session management feature
////////////////////////////////////////////////////////////////////////////////
@ -112,7 +176,7 @@ namespace triagens {
/// Caller must hold the _contextCondition.
////////////////////////////////////////////////////////////////////////////////
void addGlobalContextMethod (string const&);
bool addGlobalContextMethod (string const&);
////////////////////////////////////////////////////////////////////////////////
/// @brief executes all global methods
@ -132,7 +196,7 @@ namespace triagens {
/// @brief open global methods
////////////////////////////////////////////////////////////////////////////////
std::vector<std::string> _globalMethods;
std::vector<GlobalContextMethods::MethodType> _globalMethods;
////////////////////////////////////////////////////////////////////////////////
/// @brief number of requests since last GC of the context
@ -230,7 +294,7 @@ namespace triagens {
/// @brief adds a global context functions to be executed asap
////////////////////////////////////////////////////////////////////////////////
void addGlobalContextMethod (string const&);
bool addGlobalContextMethod (string const&);
////////////////////////////////////////////////////////////////////////////////
/// @brief runs the garbage collection

View File

@ -784,7 +784,7 @@ static v8::Handle<v8::Value> JS_ExecuteGlobalContextFunction (v8::Arguments cons
v8::HandleScope scope;
if (argv.Length() != 1) {
TRI_V8_EXCEPTION_USAGE(scope, "executeGlobalContextFunction(<function-definition>)");
TRI_V8_EXCEPTION_USAGE(scope, "executeGlobalContextFunction(<function-type>)");
}
// extract the action name
@ -794,10 +794,12 @@ static v8::Handle<v8::Value> JS_ExecuteGlobalContextFunction (v8::Arguments cons
TRI_V8_TYPE_ERROR(scope, "<definition> must be a UTF-8 function definition");
}
string def = *utf8def;
string const def = *utf8def;
// and pass it to the V8 contexts
GlobalV8Dealer->addGlobalContextMethod(def);
if (! GlobalV8Dealer->addGlobalContextMethod(def)) {
TRI_V8_EXCEPTION_MESSAGE(scope, TRI_ERROR_INTERNAL, "invalid action definition");
}
return scope.Close(v8::Undefined());
}

View File

@ -2013,7 +2013,7 @@ static v8::Handle<v8::Value> JS_ByExampleQuery (v8::Arguments const& argv) {
size_t total = filtered._length;
size_t count = 0;
bool error = false;
if (0 < total) {
size_t s;
size_t e;

View File

@ -6076,6 +6076,7 @@ static v8::Handle<v8::Value> JS_DatafileScanVocbaseCol (v8::Arguments const& arg
result->Set(v8::String::New("endPosition"), v8::Number::New(scan._endPosition));
result->Set(v8::String::New("numberMarkers"), v8::Number::New(scan._numberMarkers));
result->Set(v8::String::New("status"), v8::Number::New(scan._status));
result->Set(v8::String::New("isSealed"), v8::Boolean::New(scan._isSealed));
v8::Handle<v8::Array> entries = v8::Array::New();
result->Set(v8::String::New("entries"), entries);
@ -10460,7 +10461,7 @@ void TRI_V8ReloadRouting (v8::Handle<v8::Context> context) {
v8::HandleScope scope;
TRI_ExecuteJavaScriptString(context,
v8::String::New("require('internal').executeGlobalContextFunction('require(\\'org/arangodb/actions\\').reloadRouting()')"),
v8::String::New("require('internal').executeGlobalContextFunction('reloadRouting')"),
v8::String::New("reload routing"),
false);
}

View File

@ -31,6 +31,7 @@
#include "datafile.h"
#include "BasicsC/conversions.h"
#include "BasicsC/hashes.h"
#include "BasicsC/logging.h"
#include "BasicsC/memory-map.h"
@ -421,6 +422,7 @@ static TRI_df_scan_t ScanDatafile (TRI_datafile_t const* datafile) {
scan._maximalSize = datafile->_maximalSize;
scan._numberMarkers = 0;
scan._status = 1;
scan._isSealed = false; // assume false
if (datafile->_currentSize == 0) {
end = datafile->_data + datafile->_maximalSize;
@ -494,6 +496,7 @@ static TRI_df_scan_t ScanDatafile (TRI_datafile_t const* datafile) {
if (marker->_type == TRI_DF_MARKER_FOOTER) {
scan._endPosition = currentSize;
scan._isSealed = true;
return scan;
}
@ -1712,6 +1715,7 @@ TRI_df_scan_t TRI_ScanDatafile (char const* path) {
TRI_InitVector(&scan._entries, TRI_CORE_MEM_ZONE, sizeof(TRI_df_scan_entry_t));
scan._status = 5;
scan._isSealed = false;
}
return scan;

View File

@ -214,6 +214,7 @@ typedef struct TRI_df_scan_s {
TRI_vector_t _entries;
uint32_t _status;
bool _isSealed;
}
TRI_df_scan_t;

View File

@ -803,7 +803,7 @@ static int OpenDatabases (TRI_server_t* server,
databaseName,
&defaults,
isUpgrade,
server->_wasShutdownCleanly);
! server->_wasShutdownCleanly);
TRI_FreeString(TRI_CORE_MEM_ZONE, databaseName);
@ -1863,6 +1863,7 @@ int TRI_StartServer (TRI_server_t* server,
return TRI_ERROR_INTERNAL;
}
server->_wasShutdownCleanly = (res == TRI_ERROR_NO_ERROR);

View File

@ -1104,7 +1104,7 @@ static int LoadCollectionVocBase (TRI_vocbase_t* vocbase,
// release the lock on the collection temporarily
// this will allow other threads to check the collection's
// status while it is loading (loading may take a long time because of
// disk activity)
// disk activity, index creation etc.)
TRI_WRITE_UNLOCK_STATUS_VOCBASE_COL(collection);
document = TRI_OpenDocumentCollection(vocbase, collection->_path);

View File

@ -5,6 +5,10 @@ directory= @LOCALSTATEDIR@/lib/arangodb
# maximal-journal-size=33554432
# remove-on-drop=true
[server]
# set number of threads to 1 so we don't have concurrency
threads = 1
[javascript]
startup-directory = @PKGDATADIR@/js
app-path = @LOCALSTATEDIR@/lib/arangodb-apps

View File

@ -7,6 +7,8 @@ no-upgrade = true
[server]
disable-authentication = true
# set number of threads to 1 so we don't have concurrency
threads = 1
[javascript]
startup-directory = ./js

View File

@ -219,7 +219,7 @@ actions.defineHttp({
prefix : false,
callback : function (req, res) {
internal.executeGlobalContextFunction("require(\"org/arangodb/actions\").reloadRouting()");
internal.executeGlobalContextFunction("reloadRouting");
console.warn("about to flush the routing cache");
actions.resultOk(req, res, actions.HTTP_OK);
}
@ -263,7 +263,7 @@ actions.defineHttp({
prefix : false,
callback : function (req, res) {
internal.executeGlobalContextFunction("require(\"internal\").flushModuleCache()");
internal.executeGlobalContextFunction("flushModuleCache");
console.warn("about to flush the modules cache");
actions.resultOk(req, res, actions.HTTP_OK);
}

View File

@ -82,20 +82,19 @@
this.message = this.toString();
};
exports.ArangoError.prototype = new Error(); //Error.prototype;
exports.ArangoError.prototype._PRINT = function (context) {
context.output += this.toString();
};
exports.ArangoError.prototype = new Error();
}
exports.ArangoError.prototype._PRINT = function (context) {
context.output += this.toString();
};
exports.ArangoError.prototype.toString = function() {
var errorNum = this.errorNum;
var errorMessage = this.errorMessage || this.message;
exports.ArangoError.prototype.toString = function() {
var errorNum = this.errorNum;
var errorMessage = this.errorMessage || this.message;
return "[ArangoError " + errorNum + ": " + errorMessage + "]";
};
}
return "[ArangoError " + errorNum + ": " + errorMessage + "]";
};
////////////////////////////////////////////////////////////////////////////////
/// @brief SleepAndRequeue

View File

@ -82,20 +82,19 @@
this.message = this.toString();
};
exports.ArangoError.prototype = new Error(); //Error.prototype;
exports.ArangoError.prototype._PRINT = function (context) {
context.output += this.toString();
};
exports.ArangoError.prototype = new Error();
}
exports.ArangoError.prototype._PRINT = function (context) {
context.output += this.toString();
};
exports.ArangoError.prototype.toString = function() {
var errorNum = this.errorNum;
var errorMessage = this.errorMessage || this.message;
exports.ArangoError.prototype.toString = function() {
var errorNum = this.errorNum;
var errorMessage = this.errorMessage || this.message;
return "[ArangoError " + errorNum + ": " + errorMessage + "]";
};
}
return "[ArangoError " + errorNum + ": " + errorMessage + "]";
};
////////////////////////////////////////////////////////////////////////////////
/// @brief SleepAndRequeue

View File

@ -0,0 +1,196 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief test the error codes
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2012 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 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
var jsunity = require("jsunity");
var arangodb = require("org/arangodb");
var ArangoError = require("org/arangodb").ArangoError;
var ERRORS = arangodb.errors;
// -----------------------------------------------------------------------------
// --SECTION-- errors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief test suite
////////////////////////////////////////////////////////////////////////////////
function ErrorsSuite () {
var throwError = function (code, message) {
var err = new ArangoError();
err.errorNum = code;
err.errorMessage = message;
throw err;
};
return {
setUp : function () {
},
tearDown : function () {
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test built-in error
////////////////////////////////////////////////////////////////////////////////
testBuiltIn : function () {
try {
throw "foo";
fail();
}
catch (err) {
assertFalse(err instanceof ArangoError);
assertEqual("string", typeof err);
assertEqual("foo", err);
}
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test built-in error
////////////////////////////////////////////////////////////////////////////////
testTypeErrorBuiltIn : function () {
try {
throw new TypeError("invalid type!");
fail();
}
catch (err) {
assertFalse(err instanceof ArangoError);
assertEqual("invalid type!", err.message);
}
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test struct
////////////////////////////////////////////////////////////////////////////////
testArangoErrorStruct : function () {
try {
throwError(1, "the foxx");
fail();
}
catch (err) {
assertTrue(err.hasOwnProperty("errorNum"));
assertTrue(err.hasOwnProperty("errorMessage"));
assertTrue(err.hasOwnProperty("error"));
assertEqual("number", typeof err.errorNum);
assertEqual("string", typeof err.errorMessage);
assertEqual("boolean", typeof err.error);
assertEqual(1, err.errorNum);
assertEqual("the foxx", err.errorMessage);
assertTrue(err.error);
assertTrue(err instanceof ArangoError);
}
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test a custom code
////////////////////////////////////////////////////////////////////////////////
testArangoErrorCustom : function () {
try {
throwError(12345, "myerrormessage");
fail();
}
catch (err) {
assertEqual(12345, err.errorNum);
assertEqual("myerrormessage", err.errorMessage);
}
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test a custom message
////////////////////////////////////////////////////////////////////////////////
testArangoErrorMessage : function () {
try {
throwError(ERRORS.ERROR_ARANGO_DOCUMENT_TYPE_INVALID.code, ERRORS.ERROR_ARANGO_DOCUMENT_TYPE_INVALID.message);
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_ARANGO_DOCUMENT_TYPE_INVALID.code, err.errorNum);
assertEqual(ERRORS.ERROR_ARANGO_DOCUMENT_TYPE_INVALID.message, err.errorMessage);
}
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test to string
////////////////////////////////////////////////////////////////////////////////
testArangoToString1 : function () {
var e = ERRORS.ERROR_ARANGO_DOCUMENT_TYPE_INVALID;
try {
throwError(e.code, e.message);
fail();
}
catch (err) {
assertEqual("[ArangoError " + e.code + ": " + e.message + "]", err.toString());
}
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test to string
////////////////////////////////////////////////////////////////////////////////
testArangoToString2 : function () {
var e = ERRORS.ERROR_ARANGO_DOCUMENT_NOT_FOUND;
try {
throwError(e.code, e.message + ": did not find document");
fail();
}
catch (err) {
assertEqual("[ArangoError " + e.code + ": " + e.message + ": did not find document]", err.toString());
}
}
};
}
// -----------------------------------------------------------------------------
// --SECTION-- main
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief executes the test suite
////////////////////////////////////////////////////////////////////////////////
jsunity.run(ErrorsSuite);
return jsunity.done();
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)"
// End:

View File

@ -61,34 +61,52 @@ function WipeDatafile (collection, type, datafile, lastGoodPos) {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief checks a journal
/// @brief queries user to wipe a datafile
////////////////////////////////////////////////////////////////////////////////
function DeepCheckJournal (collection, type, datafile, scan, lastGoodPos) {
function QueryWipeDatafile (collection, type, datafile, scan, lastGoodPos) {
var entries = scan.entries;
if (entries.length == 0) {
printf("WARNING: The journal is empty. Even the header is missing. Going\n");
printf(" to remove the datafile.\n");
if (type === "journal" || type === "compactor") {
printf("WARNING: The journal is empty. Even the header is missing. Going\n");
printf(" to remove the file.\n");
}
else {
printf("WARNING: The datafile is empty. Even the header is missing. Going\n");
printf(" to remove the datafile. This should never happen. Datafiles\n");
printf(" are append-only. Make sure your hard disk does not contain\n");
printf(" any hardware errors.\n");
}
printf("\n");
RemoveDatafile(collection, type, datafile);
return;
}
if (entries.length === lastGoodPos + 3 && entries[lastGoodPos + 2].status === 2) {
printf("WARNING: The journal was not closed properly, the last entry is corrupted.\n");
printf(" This might happen ArangoDB was killed and the last entry was not\n");
printf(" fully written to disk. Going to remove the last entry.\n");
printf("\n");
var ask = true;
if (type === "journal") {
if (entries.length === lastGoodPos + 3 && entries[lastGoodPos + 2].status === 2) {
printf("WARNING: The journal was not closed properly, the last entry is corrupted.\n");
printf(" This might happen ArangoDB was killed and the last entry was not\n");
printf(" fully written to disk. Going to remove the last entry.\n");
ask = false;
}
else {
printf("WARNING: The journal was not closed properly, the last entries are corrupted.\n");
printf(" This might happen ArangoDB was killed and the last entries were not\n");
printf(" fully written to disk.\n");
}
}
else {
printf("WARNING: The journal was not closed properly, the last entries is corrupted.\n");
printf(" This might happen ArangoDB was killed and the last entries were not\n");
printf(" fully written to disk.\n");
printf("\n");
printf("WARNING: The datafile contains corrupt entries. This should never happen.\n");
printf(" Datafiles are append-only. Make sure your hard disk does not contain\n");
printf(" any hardware errors.\n");
}
printf("\n");
if (ask) {
printf("Wipe the last entries (Y/N)? ");
var line = console.getline();
@ -104,57 +122,34 @@ function DeepCheckJournal (collection, type, datafile, scan, lastGoodPos) {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief checks a datafile
/// @brief prints details about entries
////////////////////////////////////////////////////////////////////////////////
function DeepCheckDatafile (collection, type, datafile, scan, lastGoodPos) {
var entries = scan.entries;
function PrintEntries (entries, amount) {
var start, end;
if (entries.length == 0) {
printf("WARNING: The datafile is empty. Even the header is missing. Going\n");
printf(" to remove the datafile. This should never happen. Datafiles\n");
printf(" are append-only. Make sure your hard disk does not contain\n");
printf(" any hardware errors.\n");
printf("\n");
if (amount > 0) {
start = 0;
end = amount;
if (end > entries.length) {
end = entries.length;
}
}
else {
start = entries.length + amount - 1;
if (start < 0) {
return;
}
if (start < Math.abs(amount)) {
return;
}
RemoveDatafile(collection, type, datafile);
return;
end = entries.length;
}
printf("WARNING: The datafile contains corrupt entries. This should never happen.\n");
printf(" Datafiles are append-only. Make sure your hard disk does not contain\n");
printf(" any hardware errors.\n");
printf("\n");
printf("Wipe the last entries (Y/N)? ");
var line = console.getline();
if (line !== "yes" && line !== "YES" && line !== "y" && line !== "Y") {
printf("ABORTING\n");
return;
}
var entry = entries[lastGoodPos];
WipeDatafile(collection, type, datafile, entry.position + entry.size);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief checks a datafile deeply
////////////////////////////////////////////////////////////////////////////////
function DeepCheckDatafile (collection, type, datafile, scan) {
var entries = scan.entries;
printf("Entries\n");
var lastGood = 0;
var lastGoodPos = 0;
var stillGood = true;
for (var i = 0; i < entries.length; ++i) {
for (var i = start; i < end; ++i) {
var entry = entries[i];
var s = "unknown";
switch (entry.status) {
@ -165,7 +160,31 @@ function DeepCheckDatafile (collection, type, datafile, scan) {
case 5: s = "FAILED (crc mismatch)"; break;
}
printf(" %d: status %s type %d size %d\n", i, s, entry.type, entry.size);
printf(" %d: status %s type %d size %d, tick %s\n", i, s, entry.type, entry.size, entry.tick);
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief checks a datafile deeply
////////////////////////////////////////////////////////////////////////////////
function DeepCheckDatafile (collection, type, datafile, scan, details) {
var entries = scan.entries;
printf("Entries\n");
var lastGood = 0;
var lastGoodPos = 0;
var stillGood = true;
if (details) {
// print details
PrintEntries(entries, 10);
PrintEntries(entries, -10);
}
for (var i = 0; i < entries.length; ++i) {
var entry = entries[i];
if (entry.status === 1 || entry.status === 2) {
if (stillGood) {
@ -182,12 +201,7 @@ function DeepCheckDatafile (collection, type, datafile, scan) {
printf(" Last good position: %d\n", lastGood.position + lastGood.size);
printf("\n");
if (type === "journal" || type === "compactor") {
DeepCheckJournal(collection, type, datafile, scan, lastGoodPos);
}
else {
DeepCheckDatafile(collection, type, datafile, scan, lastGoodPos);
}
QueryWipeDatafile(collection, type, datafile, scan, lastGoodPos);
}
printf("\n");
@ -197,7 +211,7 @@ function DeepCheckDatafile (collection, type, datafile, scan) {
/// @brief checks a datafile
////////////////////////////////////////////////////////////////////////////////
function CheckDatafile (collection, type, datafile, issues) {
function CheckDatafile (collection, type, datafile, issues, details) {
printf("Datafile\n");
printf(" path: %s\n", datafile);
printf(" type: %s\n", type);
@ -208,6 +222,8 @@ function CheckDatafile (collection, type, datafile, issues) {
printf(" maximal size: %d\n", scan.maximalSize);
printf(" total used: %d\n", scan.endPosition);
printf(" # of entries: %d\n", scan.numberMarkers);
printf(" status: %d\n", scan.status);
printf(" isSealed: %s\n", scan.isSealed ? "yes" : "no");
// set default value to unknown
var statusMessage = "UNKNOWN (" + scan.status + ")";
@ -217,9 +233,12 @@ function CheckDatafile (collection, type, datafile, issues) {
case 1:
statusMessage = "OK";
color = internal.COLORS.COLOR_GREEN;
if (! scan.isSealed && type === "datafile") {
color = internal.COLORS.COLOR_YELLOW;
}
break;
case 1:
case 2:
statusMessage = "NOT OK (reached empty marker)";
color = internal.COLORS.COLOR_RED;
break;
@ -296,7 +315,7 @@ function CheckDatafile (collection, type, datafile, issues) {
return;
}
if (scan.entries.length == 2 && scan.entries[1].type !== 2000) {
if (scan.entries.length === 2 && scan.entries[1].type !== 2000) {
// asserting a TRI_COL_MARKER_HEADER as second marker
statusMessage = "datafile contains no collection header marker at pos #1!";
color = internal.COLORS.COLOR_YELLOW;
@ -316,19 +335,40 @@ function CheckDatafile (collection, type, datafile, issues) {
RemoveDatafile(collection, type, datafile);
return;
}
if (type !== "journal" && scan.entries.length === 3 && scan.entries[2].type === 0) {
// got the two initial header markers but nothing else...
statusMessage = "datafile is empty but not sealed";
color = internal.COLORS.COLOR_YELLOW;
if (scan.status === 1) {
issues.push({
collection: collection.name(),
path: datafile,
type: type,
status: scan.status,
message: statusMessage,
color: color
});
printf(color);
printf("WARNING: %s\n", statusMessage);
printf(internal.COLORS.COLOR_RESET);
RemoveDatafile(collection, type, datafile);
return;
}
DeepCheckDatafile(collection, type, datafile, scan);
if (scan.status === 1 && scan.isSealed) {
return;
}
DeepCheckDatafile(collection, type, datafile, scan, details);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief checks a collection
////////////////////////////////////////////////////////////////////////////////
function CheckCollection (collection, issues) {
function CheckCollection (collection, issues, details) {
printf("Database\n");
printf(" name: %s\n", internal.db._name());
printf(" path: %s\n", internal.db._path());
@ -348,15 +388,15 @@ function CheckCollection (collection, issues) {
printf("\n");
for (var i = 0; i < datafiles.journals.length; ++i) {
CheckDatafile(collection, "journal", datafiles.journals[i], issues);
CheckDatafile(collection, "journal", datafiles.journals[i], issues, details);
}
for (var i = 0; i < datafiles.datafiles.length; ++i) {
CheckDatafile(collection, "datafiles", datafiles.datafiles[i], issues);
CheckDatafile(collection, "datafile", datafiles.datafiles[i], issues, details);
}
for (var i = 0; i < datafiles.compactors.length; ++i) {
CheckDatafile(collection, "compactor", datafiles.compactors[i], issues);
CheckDatafile(collection, "compactor", datafiles.compactors[i], issues, details);
}
}
@ -378,7 +418,7 @@ function main (argv) {
return 0;
};
printf("%s\n", " ___ _ __ _ _ ___ ___ ___ ");
printf("%s\n", " / \\__ _| |_ __ _ / _(_) | ___ / \\/ __\\ / _ \\");
printf("%s\n", " / /\\ / _` | __/ _` | |_| | |/ _ \\ / /\\ /__\\// / /_\\/");
@ -398,9 +438,11 @@ function main (argv) {
printf(" %d: %s\n", i, databases[i]);
}
var line;
printf("Database to check: ");
while (true) {
var line = console.getline();
line = console.getline();
if (line == "") {
printf("Exiting. Please wait.\n");
@ -445,7 +487,7 @@ function main (argv) {
var a = [];
while (true) {
var line = console.getline();
line = console.getline();
if (line == "") {
printf("Exiting. Please wait.\n");
@ -471,6 +513,23 @@ function main (argv) {
}
}
}
printf("\n");
printf("Prints details (yes/no)? ");
var details = false;
while (true) {
line = console.getline();
if (line === "") {
printf("Exiting. Please wait.\n");
return;
}
if (line === "yes" || line === "YES" || line === "y" || line === "Y") {
details = true;
}
break;
}
var issues = [ ];
@ -496,7 +555,7 @@ function main (argv) {
printf("\n");
CheckCollection(collection, issues);
CheckCollection(collection, issues, details);
}

View File

@ -189,7 +189,7 @@
}
else {
internal.reloadAqlFunctions = function () {
internal.executeGlobalContextFunction("try { require(\"org/arangodb/ahuacatl\").reload(); } catch (err) { }");
internal.executeGlobalContextFunction("reloadAql");
require("org/arangodb/ahuacatl").reload();
};
}

View File

@ -957,7 +957,7 @@ exports.mount = function (appId, mount, options) {
}
if (typeof options.reload === "undefined" || options.reload === true) {
executeGlobalContextFunction("require(\"org/arangodb/actions\").reloadRouting()");
executeGlobalContextFunction("reloadRouting");
}
return { appId: app._id, mountId: doc._key, mount: mount };
@ -1048,7 +1048,7 @@ exports.unmount = function (mount) {
getStorage().remove(doc);
executeGlobalContextFunction("require(\"org/arangodb/actions\").reloadRouting()");
executeGlobalContextFunction("reloadRouting");
return { appId: doc.app, mount: doc.mount, options: doc.options };
};
@ -1104,7 +1104,7 @@ exports.purge = function (key) {
// remove the app
getStorage().remove(doc);
executeGlobalContextFunction("require(\"org/arangodb/actions\").reloadRouting()");
executeGlobalContextFunction("reloadRouting");
// we can be sure this is a database-specific app and no system app
var path = fs.join(module.appPath(), doc.path);
@ -1215,45 +1215,55 @@ exports.devTeardown = function (filename) {
exports.appRoutes = function () {
'use strict';
var aal = getStorage();
var find = aal.byExample({ type: "mount", active: true });
var routes = [];
return arangodb.db._executeTransaction({
collections: {
read: [ aal.name() ]
},
params: {
aal : aal
},
action: function (params) {
var find = params.aal.byExample({ type: "mount", active: true });
while (find.hasNext()) {
var doc = find.next();
var routes = [];
var appId = doc.app;
var mount = doc.mount;
var options = doc.options || { };
while (find.hasNext()) {
var doc = find.next();
var appId = doc.app;
var mount = doc.mount;
var options = doc.options || { };
try {
var app = module.createApp(appId, options || {});
try {
var app = module.createApp(appId, options || {});
if (app === null) {
throw new Error("Cannot find application '" + appId + "'");
if (app === null) {
throw new Error("Cannot find application '" + appId + "'");
}
var r = routingAalApp(app, mount, options);
if (r === null) {
throw new Error("Cannot compute the routing table for foxx application '"
+ app._id + "', check the log file for errors!");
}
routes.push(r);
if (!developmentMode) {
console.log("Mounted foxx app '%s' on '%s'", appId, mount);
}
}
catch (err) {
console.error("Cannot mount foxx app '%s': %s", appId, String(err.stack || err));
}
}
var r = routingAalApp(app, mount, options);
if (r === null) {
throw new Error("Cannot compute the routing table for foxx application '"
+ app._id + "', check the log file for errors!");
}
routes.push(r);
if (!developmentMode) {
console.log("Mounted foxx app '%s' on '%s'", appId, mount);
}
return routes;
}
catch (err) {
console.error("Cannot mount foxx app '%s': %s", appId, String(err.stack || err));
}
}
return routes;
});
};
////////////////////////////////////////////////////////////////////////////////

View File

@ -511,7 +511,7 @@ static int GenerateMessage (char* buffer,
m += n;
// .............................................................................
// check if we must disply the line number
// check if we must display the line number
// .............................................................................
sln = ShowLineNumber;

View File

@ -98,10 +98,9 @@ namespace triagens {
}
case Handler::HANDLER_FAILED:
default:
return Job::status_t(Job::JOB_FAILED);
}
return Job::status_t(Job::JOB_FAILED);
}
status_e status;

View File

@ -2275,7 +2275,7 @@ static v8::Handle<v8::Value> JS_Wait (v8::Arguments const& argv) {
if (gc) {
// wait with gc
v8::V8::LowMemoryNotification();
while(! v8::V8::IdleNotification()) {
while (! v8::V8::IdleNotification()) {
}
size_t i = 0;