1
0
Fork 0

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

This commit is contained in:
Frank Celler 2013-01-17 10:30:48 +01:00
commit 632b9bc430
17 changed files with 479 additions and 226 deletions

View File

@ -685,7 +685,7 @@ v1.0.beta1 (2012-07-29)
- tcp://[host]:port or http@tcp://[host]:port (HTTP over IPv6) - tcp://[host]:port or http@tcp://[host]:port (HTTP over IPv6)
- ssl://host:port or http@tcp://host:port (HTTP over SSL-encrypted IPv4) - ssl://host:port or http@tcp://host:port (HTTP over SSL-encrypted IPv4)
- ssl://[host]:port or http@tcp://[host]:port (HTTP over SSL-encrypted IPv6) - ssl://[host]:port or http@tcp://[host]:port (HTTP over SSL-encrypted IPv6)
- unix://path/to/socket or http@unix:///path/to/socket (HTTP over UNIX socket) - unix:///path/to/socket or http@unix:///path/to/socket (HTTP over UNIX socket)
If no port is specified, the default port of 8529 will be used. If no port is specified, the default port of 8529 will be used.

View File

@ -8,7 +8,3 @@ arango> db.five.all().toArray();
arango> db.five.all().limit(2).toArray(); arango> db.five.all().limit(2).toArray();
[ { _id : 159896:1798296, _rev : 1798296, doc : 3 }, [ { _id : 159896:1798296, _rev : 1798296, doc : 3 },
{ _id : 159896:1732760, _rev : 1732760, doc : 2 } ] { _id : 159896:1732760, _rev : 1732760, doc : 2 } ]
arango> db.five.all().limit(-2);
[ { _id : 159896:1667224, _rev : 1667224, doc : 1 },
{ _id : 159896:1929368, _rev : 1929368, doc : 5 } ]

View File

@ -253,7 +253,7 @@ following specification syntax:
- `tcp://[host]:port (HTTP over IPv6)` - `tcp://[host]:port (HTTP over IPv6)`
- `ssl://host:port (HTTP over SSL-encrypted IPv4)` - `ssl://host:port (HTTP over SSL-encrypted IPv4)`
- `ssl://[host]:port (HTTP over SSL-encrypted IPv6)` - `ssl://[host]:port (HTTP over SSL-encrypted IPv6)`
- `unix://path/to/socket (HTTP over Unix domain socket)` - `unix:///path/to/socket (HTTP over Unix domain socket)`
### TCP endpoints ### TCP endpoints

View File

@ -105,7 +105,7 @@ following endpoint specification sytnax is currently supported:
- `tcp://[host]:port` (HTTP over IPv6) - `tcp://[host]:port` (HTTP over IPv6)
- `ssl://host:port` (HTTP over SSL-encrypted IPv4) - `ssl://host:port` (HTTP over SSL-encrypted IPv4)
- `ssl://[host]:port` (HTTP over SSL-encrypted IPv6) - `ssl://[host]:port` (HTTP over SSL-encrypted IPv6)
- `unix://path/to/socket` (HTTP over UNIX socket) - `unix:///path/to/socket` (HTTP over UNIX socket)
An example value for the option is `--server.endpoint An example value for the option is `--server.endpoint
tcp://127.0.0.1:8529`. This will make the server listen to requests tcp://127.0.0.1:8529`. This will make the server listen to requests

View File

@ -207,6 +207,7 @@ SHELL_COMMON = @top_srcdir@/js/common/tests/shell-document.js \
@top_srcdir@/js/common/tests/shell-edge.js \ @top_srcdir@/js/common/tests/shell-edge.js \
@top_srcdir@/js/common/tests/shell-database.js \ @top_srcdir@/js/common/tests/shell-database.js \
@top_srcdir@/js/common/tests/shell-collection.js \ @top_srcdir@/js/common/tests/shell-collection.js \
@top_srcdir@/js/common/tests/shell-collection-volatile.js \
@top_srcdir@/js/common/tests/shell-compactor.js \ @top_srcdir@/js/common/tests/shell-compactor.js \
@top_srcdir@/js/common/tests/shell-graph-traversal.js \ @top_srcdir@/js/common/tests/shell-graph-traversal.js \
@top_srcdir@/js/common/tests/shell-simple-query.js \ @top_srcdir@/js/common/tests/shell-simple-query.js \

View File

@ -1031,6 +1031,7 @@ static v8::Handle<v8::Value> SaveEdgeCol (SingleCollectionWriteTransaction<Embed
const bool forceSync = ExtractForceSync(argv, 4); const bool forceSync = ExtractForceSync(argv, 4);
TRI_document_edge_t edge; TRI_document_edge_t edge;
// the following values are defaults that will be overridden below
edge._fromCid = trx->cid(); edge._fromCid = trx->cid();
edge._toCid = trx->cid(); edge._toCid = trx->cid();
edge._fromKey = 0; edge._fromKey = 0;
@ -6119,15 +6120,15 @@ v8::Handle<v8::Value> TRI_ParseDocumentOrDocumentHandle (TRI_vocbase_t* vocbase,
// use the collection // use the collection
int res = TRI_UseCollectionVocBase(vocbase, col); int res = TRI_UseCollectionVocBase(vocbase, col);
if (res == TRI_ERROR_NO_ERROR && col->_collection == 0) {
res = TRI_ERROR_INTERNAL;
}
if (res != TRI_ERROR_NO_ERROR) { if (res != TRI_ERROR_NO_ERROR) {
return scope.Close(TRI_CreateErrorObject(res, "cannot use/load collection", true)); return scope.Close(TRI_CreateErrorObject(res, "cannot use/load collection", true));
} }
} }
if (col->_collection == 0) {
return scope.Close(TRI_CreateErrorObject(TRI_ERROR_INTERNAL, "cannot use/load collection"));
}
collection = col; collection = col;
} }

View File

@ -54,7 +54,7 @@
static void InitCollection (TRI_vocbase_t* vocbase, static void InitCollection (TRI_vocbase_t* vocbase,
TRI_collection_t* collection, TRI_collection_t* collection,
char* directory, char* directory,
TRI_col_info_t* info) { const TRI_col_info_t* const info) {
assert(collection); assert(collection);
memset(collection, 0, sizeof(TRI_collection_t)); memset(collection, 0, sizeof(TRI_collection_t));
@ -510,7 +510,7 @@ void TRI_InitCollectionInfo (TRI_vocbase_t* vocbase,
/// @brief copy a collection info block /// @brief copy a collection info block
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void TRI_CopyCollectionInfo (TRI_col_info_t* dst, TRI_col_info_t* src) { void TRI_CopyCollectionInfo (TRI_col_info_t* dst, const TRI_col_info_t* const src) {
assert(dst); assert(dst);
memset(dst, 0, sizeof(TRI_col_info_t)); memset(dst, 0, sizeof(TRI_col_info_t));
@ -545,6 +545,63 @@ void TRI_FreeCollectionInfoOptions (TRI_col_info_t* parameter) {
} }
} }
////////////////////////////////////////////////////////////////////////////////
/// @brief get the full directory name for a collection
///
/// it is the caller's responsibility to check if the returned string is NULL
/// and to free it if not.
////////////////////////////////////////////////////////////////////////////////
char* TRI_GetDirectoryCollection (char const* path,
const TRI_col_info_t* const parameter) {
char* filename;
assert(path);
assert(parameter);
// shape collections use just the name, e.g. path/SHAPES
if (parameter->_type == TRI_COL_TYPE_SHAPE) {
filename = TRI_Concatenate2File(path, parameter->_name);
}
// other collections use the collection identifier
else if (TRI_IS_DOCUMENT_COLLECTION(parameter->_type)) {
char* tmp1;
char* tmp2;
tmp1 = TRI_StringUInt64(parameter->_cid);
if (tmp1 == NULL) {
TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
return NULL;
}
tmp2 = TRI_Concatenate2String("collection-", tmp1);
if (tmp2 == NULL) {
TRI_FreeString(TRI_CORE_MEM_ZONE, tmp1);
TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
return NULL;
}
filename = TRI_Concatenate2File(path, tmp2);
TRI_FreeString(TRI_CORE_MEM_ZONE, tmp1);
TRI_FreeString(TRI_CORE_MEM_ZONE, tmp2);
}
// oops, unknown collection type
else {
TRI_set_errno(TRI_ERROR_ARANGO_UNKNOWN_COLLECTION_TYPE);
return NULL;
}
if (filename == NULL) {
TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
}
// might be NULL
return filename;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief creates a new collection /// @brief creates a new collection
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -552,9 +609,8 @@ void TRI_FreeCollectionInfoOptions (TRI_col_info_t* parameter) {
TRI_collection_t* TRI_CreateCollection (TRI_vocbase_t* vocbase, TRI_collection_t* TRI_CreateCollection (TRI_vocbase_t* vocbase,
TRI_collection_t* collection, TRI_collection_t* collection,
char const* path, char const* path,
TRI_col_info_t* parameter) { const TRI_col_info_t* const parameter) {
char* filename; char* filename;
int res;
// sanity check // sanity check
if (sizeof(TRI_df_header_marker_t) + sizeof(TRI_df_footer_marker_t) > parameter->_maximalSize) { if (sizeof(TRI_df_header_marker_t) + sizeof(TRI_df_footer_marker_t) > parameter->_maximalSize) {
@ -576,58 +632,10 @@ TRI_collection_t* TRI_CreateCollection (TRI_vocbase_t* vocbase,
return NULL; return NULL;
} }
// shape collection use the name
if (parameter->_type == TRI_COL_TYPE_SHAPE) { filename = TRI_GetDirectoryCollection(path, parameter);
filename = TRI_Concatenate2File(path, parameter->_name);
if (filename == NULL) { if (filename == NULL) {
LOG_ERROR("cannot create collection '%s'", TRI_last_error());
LOG_ERROR("cannot create collection '%s', out of memory", path);
return NULL;
}
}
// simple collection use the collection identifier
else if (TRI_IS_DOCUMENT_COLLECTION(parameter->_type)) {
char* tmp1;
char* tmp2;
tmp1 = TRI_StringUInt64(parameter->_cid);
if (tmp1 == NULL) {
LOG_ERROR("cannot create collection '%s', out of memory", path);
return NULL;
}
tmp2 = TRI_Concatenate2String("collection-", tmp1);
if (tmp2 == NULL) {
TRI_FreeString(TRI_CORE_MEM_ZONE, tmp1);
LOG_ERROR("cannot create collection '%s', out of memory", path);
return NULL;
}
filename = TRI_Concatenate2File(path, tmp2);
if (filename == NULL) {
TRI_FreeString(TRI_CORE_MEM_ZONE, tmp1);
TRI_FreeString(TRI_CORE_MEM_ZONE, tmp2);
LOG_ERROR("cannot create collection '%s', out of memory", path);
return NULL;
}
TRI_FreeString(TRI_CORE_MEM_ZONE, tmp2);
TRI_FreeString(TRI_CORE_MEM_ZONE, tmp1);
}
// uups
else {
TRI_set_errno(TRI_ERROR_ARANGO_UNKNOWN_COLLECTION_TYPE);
LOG_ERROR("cannot create collection '%s' in '%s': unknown type '%d'",
parameter->_name,
path,
(unsigned int) parameter->_type);
return NULL; return NULL;
} }
@ -635,7 +643,7 @@ TRI_collection_t* TRI_CreateCollection (TRI_vocbase_t* vocbase,
if (TRI_ExistsFile(filename)) { if (TRI_ExistsFile(filename)) {
TRI_set_errno(TRI_ERROR_ARANGO_COLLECTION_DIRECTORY_ALREADY_EXISTS); TRI_set_errno(TRI_ERROR_ARANGO_COLLECTION_DIRECTORY_ALREADY_EXISTS);
LOG_ERROR("cannot create collection '%s' in '%s', filename already exists", LOG_ERROR("cannot create collection '%s' in '%s', directory already exists",
parameter->_name, filename); parameter->_name, filename);
TRI_FreeString(TRI_CORE_MEM_ZONE, filename); TRI_FreeString(TRI_CORE_MEM_ZONE, filename);
@ -656,16 +664,6 @@ TRI_collection_t* TRI_CreateCollection (TRI_vocbase_t* vocbase,
return NULL; return NULL;
} }
// save the parameter block (within create, no need to lock)
res = TRI_SaveCollectionInfo(filename, parameter);
if (res != TRI_ERROR_NO_ERROR) {
LOG_ERROR("cannot save collection parameter '%s': '%s'", filename, TRI_last_error());
TRI_FreeString(TRI_CORE_MEM_ZONE, filename);
return NULL;
}
// create collection structure // create collection structure
if (collection == NULL) { if (collection == NULL) {
collection = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_collection_t), false); collection = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_collection_t), false);
@ -678,11 +676,12 @@ TRI_collection_t* TRI_CreateCollection (TRI_vocbase_t* vocbase,
} }
} }
// we are passing filename to this struct, so we must not free it if you use the struct later
InitCollection(vocbase, collection, filename, parameter); InitCollection(vocbase, collection, filename, parameter);
/* PANAIA: 1) the parameter file if it exists must be removed /* PANAIA: 1) the parameter file if it exists must be removed
2) if collection 2) if collection
*/ */
// return collection
return collection; return collection;
} }
@ -839,7 +838,7 @@ int TRI_LoadCollectionInfo (char const* path, TRI_col_info_t* parameter) {
/// function. /// function.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
int TRI_SaveCollectionInfo (char const* path, TRI_col_info_t* info) { int TRI_SaveCollectionInfo (char const* path, const TRI_col_info_t* const info) {
TRI_json_t* json; TRI_json_t* json;
char* filename; char* filename;
bool ok; bool ok;

View File

@ -283,7 +283,7 @@ void TRI_InitCollectionInfo (TRI_vocbase_t*,
/// @brief copy a collection info block /// @brief copy a collection info block
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void TRI_CopyCollectionInfo (TRI_col_info_t*, TRI_col_info_t*); void TRI_CopyCollectionInfo (TRI_col_info_t*, const TRI_col_info_t* const);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief free a collection info block /// @brief free a collection info block
@ -291,6 +291,15 @@ void TRI_CopyCollectionInfo (TRI_col_info_t*, TRI_col_info_t*);
void TRI_FreeCollectionInfoOptions (TRI_col_info_t*); void TRI_FreeCollectionInfoOptions (TRI_col_info_t*);
////////////////////////////////////////////////////////////////////////////////
/// @brief get the full directory name for a collection
///
/// it is the caller's responsibility to check if the returned string is NULL
/// and to free it if not.
////////////////////////////////////////////////////////////////////////////////
char* TRI_GetDirectoryCollection (char const*, const TRI_col_info_t* const);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief creates a new collection /// @brief creates a new collection
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -298,7 +307,7 @@ void TRI_FreeCollectionInfoOptions (TRI_col_info_t*);
TRI_collection_t* TRI_CreateCollection (TRI_vocbase_t*, TRI_collection_t* TRI_CreateCollection (TRI_vocbase_t*,
TRI_collection_t*, TRI_collection_t*,
char const*, char const*,
TRI_col_info_t*); const TRI_col_info_t* const);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief frees the memory allocated, but does not free the pointer /// @brief frees the memory allocated, but does not free the pointer
@ -337,7 +346,7 @@ int TRI_LoadCollectionInfo (char const*, TRI_col_info_t*);
/// @brief saves a parameter info block to file /// @brief saves a parameter info block to file
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
int TRI_SaveCollectionInfo (char const*, TRI_col_info_t*); int TRI_SaveCollectionInfo (char const*, const TRI_col_info_t* const);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief updates the parameter info block /// @brief updates the parameter info block

View File

@ -1895,6 +1895,7 @@ TRI_document_collection_t* TRI_CreateDocumentCollection (TRI_vocbase_t* vocbase,
TRI_collection_t* collection; TRI_collection_t* collection;
TRI_shaper_t* shaper; TRI_shaper_t* shaper;
TRI_document_collection_t* document; TRI_document_collection_t* document;
int res;
bool waitForSync; bool waitForSync;
bool isVolatile; bool isVolatile;
@ -1949,6 +1950,18 @@ TRI_document_collection_t* TRI_CreateDocumentCollection (TRI_vocbase_t* vocbase,
return NULL; return NULL;
} }
// save the parameter block (within create, no need to lock)
res = TRI_SaveCollectionInfo(collection->_directory, parameter);
if (res != TRI_ERROR_NO_ERROR) {
LOG_ERROR("cannot save collection parameters in directory '%s': '%s'", collection->_directory, TRI_last_error());
TRI_CloseCollection(collection);
TRI_FreeCollection(collection); // will free document
return NULL;
}
return document; return document;
} }

View File

@ -920,6 +920,7 @@ TRI_shaper_t* TRI_CreateVocShaper (TRI_vocbase_t* vocbase,
voc_shaper_t* shaper; voc_shaper_t* shaper;
TRI_shape_collection_t* collection; TRI_shape_collection_t* collection;
TRI_col_info_t parameter; TRI_col_info_t parameter;
int res;
bool ok; bool ok;
TRI_InitCollectionInfo(vocbase, &parameter, name, TRI_COL_TYPE_SHAPE, SHAPER_DATAFILE_SIZE, 0); TRI_InitCollectionInfo(vocbase, &parameter, name, TRI_COL_TYPE_SHAPE, SHAPER_DATAFILE_SIZE, 0);
@ -952,6 +953,13 @@ TRI_shaper_t* TRI_CreateVocShaper (TRI_vocbase_t* vocbase,
return NULL; return NULL;
} }
res = TRI_SaveCollectionInfo(collection->base._directory, &parameter);
if (res != TRI_ERROR_NO_ERROR) {
LOG_ERROR("cannot save collection parameters in directory '%s': '%s'", collection->base._directory, TRI_last_error());
TRI_FreeVocShaper(&shaper->base);
return NULL;
}
// and return // and return
return &shaper->base; return &shaper->base;
} }

View File

@ -1452,7 +1452,6 @@ TRI_vocbase_col_t* TRI_CreateCollectionVocBase (TRI_vocbase_t* vocbase,
assert(parameter); assert(parameter);
name = parameter->_name; name = parameter->_name;
// check that the name does not contain any strange characters // check that the name does not contain any strange characters
if (! TRI_IsAllowedCollectionName(parameter->_isSystem, name)) { if (! TRI_IsAllowedCollectionName(parameter->_isSystem, name)) {
TRI_set_errno(TRI_ERROR_ARANGO_ILLEGAL_NAME); TRI_set_errno(TRI_ERROR_ARANGO_ILLEGAL_NAME);
@ -1644,7 +1643,7 @@ int TRI_DropCollectionVocBase (TRI_vocbase_t* vocbase, TRI_vocbase_col_t* collec
} }
// remove dangling .json.tmp file if it exists // remove dangling .json.tmp file if it exists
tmpFile = TRI_Concatenate4String(collection->_path, "/", TRI_COL_PARAMETER_FILE, ".tmp"); tmpFile = TRI_Concatenate4String(collection->_path, TRI_DIR_SEPARATOR_STR, TRI_COL_PARAMETER_FILE, ".tmp");
if (tmpFile != NULL) { if (tmpFile != NULL) {
if (TRI_ExistsFile(tmpFile)) { if (TRI_ExistsFile(tmpFile)) {
TRI_UnlinkFile(tmpFile); TRI_UnlinkFile(tmpFile);

View File

@ -792,6 +792,7 @@ function CombineFilters (filters, config, vertex, path) {
} }
result = result.concat(tmp); result = result.concat(tmp);
}); });
return result; return result;
} }

View File

@ -0,0 +1,188 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief test the collection interface w/ volatile collections
///
/// @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 internal = require("internal");
// -----------------------------------------------------------------------------
// --SECTION-- collection methods
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// --SECTION-- volatile collections
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief test suite: volatile collections
////////////////////////////////////////////////////////////////////////////////
function CollectionVolatileSuite () {
var ERRORS = require("internal").errors;
var cn = "UnittestsVolatileCollection";
return {
////////////////////////////////////////////////////////////////////////////////
/// @brief set up
////////////////////////////////////////////////////////////////////////////////
setUp : function () {
internal.db._drop(cn);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief tear down
////////////////////////////////////////////////////////////////////////////////
tearDown : function () {
internal.db._drop(cn);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief create a volatile collection
////////////////////////////////////////////////////////////////////////////////
testCreation1 : function () {
var c = internal.db._create(cn, { isVolatile : true, waitForSync : false });
assertEqual(cn, c.name());
assertEqual(true, c.properties().isVolatile);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief create a volatile collection
////////////////////////////////////////////////////////////////////////////////
testCreation2 : function () {
var c = internal.db._create(cn, { isVolatile : true });
assertEqual(cn, c.name());
assertEqual(true, c.properties().isVolatile);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief create w/ error
////////////////////////////////////////////////////////////////////////////////
testCreationError : function () {
try {
// cannot set isVolatile and waitForSync at the same time
var c = internal.db._create(cn, { isVolatile : true, waitForSync : true });
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_BAD_PARAMETER.code, err.errorNum);
}
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test property change
////////////////////////////////////////////////////////////////////////////////
testPropertyChange : function () {
var c = internal.db._create(cn, { isVolatile : true, waitForSync : false });
try {
// cannot set isVolatile and waitForSync at the same time
c.properties({ waitForSync : true });
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_BAD_PARAMETER.code, err.errorNum);
}
},
////////////////////////////////////////////////////////////////////////////////
/// @brief load/unload
////////////////////////////////////////////////////////////////////////////////
testLoadUnload : function () {
var c = internal.db._create(cn, { isVolatile : true });
assertEqual(cn, c.name());
assertEqual(true, c.properties().isVolatile);
c.unload();
internal.wait(4);
assertEqual(true, c.properties().isVolatile);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief data storage
////////////////////////////////////////////////////////////////////////////////
testStorage : function () {
var c = internal.db._create(cn, { isVolatile : true });
assertEqual(true, c.properties().isVolatile);
c.save({"test": true});
assertEqual(1, c.count());
c.unload();
internal.wait(4);
assertEqual(true, c.properties().isVolatile);
assertEqual(0, c.count());
},
////////////////////////////////////////////////////////////////////////////////
/// @brief data storage
////////////////////////////////////////////////////////////////////////////////
testStorageMany : function () {
var c = internal.db._create(cn, { isVolatile : true, journalSize: 1024 * 1024 });
assertEqual(true, c.properties().isVolatile);
for (var i = 0; i < 10000; ++i) {
c.save({"test": true, "foo" : "bar"});
}
assertEqual(10000, c.count());
c.unload();
internal.wait(4);
assertEqual(true, c.properties().isVolatile);
assertEqual(0, c.count());
}
};
}
// -----------------------------------------------------------------------------
// --SECTION-- main
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief executes the test suites
////////////////////////////////////////////////////////////////////////////////
jsunity.run(CollectionVolatileSuite);
return jsunity.done();
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)"
// End:

View File

@ -776,143 +776,6 @@ function CollectionSuite () {
}; };
} }
// -----------------------------------------------------------------------------
// --SECTION-- volatile collections
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief test suite: volatile collections
////////////////////////////////////////////////////////////////////////////////
function CollectionVolatileSuite () {
var ERRORS = require("internal").errors;
var cn = "UnittestsVolatileCollection";
return {
////////////////////////////////////////////////////////////////////////////////
/// @brief set up
////////////////////////////////////////////////////////////////////////////////
setUp : function () {
internal.db._drop(cn);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief tear down
////////////////////////////////////////////////////////////////////////////////
tearDown : function () {
internal.db._drop(cn);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief create a volatile collection
////////////////////////////////////////////////////////////////////////////////
testCreation1 : function () {
var c = internal.db._create(cn, { isVolatile : true, waitForSync : false });
assertEqual(cn, c.name());
assertEqual(true, c.properties().isVolatile);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief create a volatile collection
////////////////////////////////////////////////////////////////////////////////
testCreation2 : function () {
var c = internal.db._create(cn, { isVolatile : true });
assertEqual(cn, c.name());
assertEqual(true, c.properties().isVolatile);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief create w/ error
////////////////////////////////////////////////////////////////////////////////
testCreationError : function () {
try {
// cannot set isVolatile and waitForSync at the same time
var c = internal.db._create(cn, { isVolatile : true, waitForSync : true });
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_BAD_PARAMETER.code, err.errorNum);
}
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test property change
////////////////////////////////////////////////////////////////////////////////
testPropertyChange : function () {
var c = internal.db._create(cn, { isVolatile : true, waitForSync : false });
try {
// cannot set isVolatile and waitForSync at the same time
c.properties({ waitForSync : true });
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_BAD_PARAMETER.code, err.errorNum);
}
},
////////////////////////////////////////////////////////////////////////////////
/// @brief load/unload
////////////////////////////////////////////////////////////////////////////////
testLoadUnload : function () {
var c = internal.db._create(cn, { isVolatile : true });
assertEqual(cn, c.name());
assertEqual(true, c.properties().isVolatile);
c.unload();
internal.wait(4);
assertEqual(true, c.properties().isVolatile);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief data storage
////////////////////////////////////////////////////////////////////////////////
testStorage : function () {
var c = internal.db._create(cn, { isVolatile : true });
assertEqual(true, c.properties().isVolatile);
c.save({"test": true});
assertEqual(1, c.count());
c.unload();
internal.wait(4);
assertEqual(true, c.properties().isVolatile);
assertEqual(0, c.count());
},
////////////////////////////////////////////////////////////////////////////////
/// @brief data storage
////////////////////////////////////////////////////////////////////////////////
testStorageMany : function () {
var c = internal.db._create(cn, { isVolatile : true, journalSize: 1024 * 1024 });
assertEqual(true, c.properties().isVolatile);
for (var i = 0; i < 10000; ++i) {
c.save({"test": true, "foo" : "bar"});
}
assertEqual(10000, c.count());
c.unload();
internal.wait(4);
assertEqual(true, c.properties().isVolatile);
assertEqual(0, c.count());
}
};
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- vocbase methods // --SECTION-- vocbase methods
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -1134,7 +997,6 @@ function CollectionDbSuite () {
jsunity.run(CollectionSuiteErrorHandling); jsunity.run(CollectionSuiteErrorHandling);
jsunity.run(CollectionSuite); jsunity.run(CollectionSuite);
jsunity.run(CollectionVolatileSuite);
jsunity.run(CollectionDbSuite); jsunity.run(CollectionDbSuite);
return jsunity.done(); return jsunity.done();

View File

@ -160,6 +160,125 @@ function CollectionEdgeSuite () {
internal.wait(0.0); internal.wait(0.0);
}, },
////////////////////////////////////////////////////////////////////////////////
/// @brief create an edge referring to a vertex documents by keys
////////////////////////////////////////////////////////////////////////////////
testSaveEdgeKeys : function () {
var k1 = vertex.save({ _key: "vx1", vx: 1 });
var k2 = vertex.save({ _key: "vx2", vx: 2 });
var k3 = vertex.save({ _key: "vx3", vx: 3 });
var d1 = vertex.document(k1._key);
assertEqual("vx1", k1._key);
assertEqual(vn + "/vx1", k1._id);
assertEqual("vx1", d1._key);
assertEqual(1, d1.vx);
assertEqual(vn + "/vx1", d1._id);
var d2 = vertex.document(k2._key);
assertEqual("vx2", k2._key);
assertEqual(vn + "/vx2", k2._id);
assertEqual("vx2", d2._key);
assertEqual(2, d2.vx);
assertEqual(vn + "/vx2", d2._id);
var d3 = vertex.document(vn + "/vx3");
assertEqual("vx3", k3._key);
assertEqual(vn + "/vx3", k3._id);
assertEqual("vx3", d3._key);
assertEqual(3, d3.vx);
assertEqual(vn + "/vx3", d3._id);
var e1 = edge.save(vn + "/vx1", vn + "/vx2", { _key: "ex1", connect: "vx1->vx2" });
var e2 = edge.save(vn + "/vx2", vn + "/vx1", { _key: "ex2", connect: "vx2->vx1" });
var e3 = edge.save(vn + "/vx3", vn + "/vx1", { _key: "ex3", connect: "vx3->vx1" });
d1 = edge.document("ex1");
assertEqual("ex1", d1._key);
assertEqual(en + "/ex1", d1._id);
assertEqual(vn + "/vx1", d1._from);
assertEqual(vn + "/vx2", d1._to);
assertEqual("vx1->vx2", d1.connect);
assertEqual("ex1", e1._key);
assertEqual(en + "/ex1", e1._id);
d2 = edge.document("ex2");
assertEqual("ex2", d2._key);
assertEqual(en + "/ex2", d2._id);
assertEqual(vn + "/vx2", d2._from);
assertEqual(vn + "/vx1", d2._to);
assertEqual("vx2->vx1", d2.connect);
assertEqual("ex2", e2._key);
assertEqual(en + "/ex2", e2._id);
d3 = edge.document(en + "/ex3");
assertEqual("ex3", d3._key);
assertEqual(en + "/ex3", d3._id);
assertEqual(vn + "/vx3", d3._from);
assertEqual(vn + "/vx1", d3._to);
assertEqual("vx3->vx1", d3.connect);
assertEqual("ex3", e3._key);
assertEqual(en + "/ex3", e3._id);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief create an edge referring to an unloaded vertex collection
////////////////////////////////////////////////////////////////////////////////
testSaveEdgeUnloaded : function () {
var k1 = vertex.save({ _key: "vx1", vx: 1 });
var k2 = vertex.save({ _key: "vx2", vx: 2 });
assertEqual("vx1", k1._key);
assertEqual(vn + "/vx1", k1._id);
assertEqual("vx2", k2._key);
assertEqual(vn + "/vx2", k2._id);
vertex.unload();
edge.unload();
console.log("waiting for collections to unload");
internal.wait(4);
var e1 = edge.save(vn + "/vx1", vn + "/vx2", { _key: "ex1", connect: "vx1->vx2" });
var e2 = edge.save(vn + "/vx2", vn + "/vx1", { _key: "ex2", connect: "vx2->vx1" });
vertex.unload();
edge.unload();
console.log("waiting for collections to unload");
internal.wait(4);
var e3 = edge.save(k1, k2, { _key: "ex3", connect: "vx1->vx2" });
d1 = edge.document("ex1");
assertEqual("ex1", d1._key);
assertEqual(en + "/ex1", d1._id);
assertEqual(vn + "/vx1", d1._from);
assertEqual(vn + "/vx2", d1._to);
assertEqual("vx1->vx2", d1.connect);
assertEqual("ex1", e1._key);
assertEqual(en + "/ex1", e1._id);
d2 = edge.document("ex2");
assertEqual("ex2", d2._key);
assertEqual(en + "/ex2", d2._id);
assertEqual(vn + "/vx2", d2._from);
assertEqual(vn + "/vx1", d2._to);
assertEqual("vx2->vx1", d2.connect);
assertEqual("ex2", e2._key);
assertEqual(en + "/ex2", e2._id);
d3 = edge.document("ex3");
assertEqual("ex3", d3._key);
assertEqual(en + "/ex3", d3._id);
assertEqual(vn + "/vx1", d3._from);
assertEqual(vn + "/vx2", d3._to);
assertEqual("vx1->vx2", d3.connect);
assertEqual("ex3", e3._key);
assertEqual(en + "/ex3", e3._id);
},
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief create an edge /// @brief create an edge
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -2347,6 +2347,23 @@ function AHUACATL_GRAPH_TRAVERSE () {
AHUACATL_THROW(internal.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH, "TRAVERSE"); AHUACATL_THROW(internal.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH, "TRAVERSE");
} }
if (params.maxDepth <= 0) {
// we need to have at least SOME limit to prevent endless iteration
params.maxDepth = 1024;
}
// prepare an array of filters
var filter = [ ];
if (params.minDepth != undefined) {
filter.push(traversal.MinDepthFilter);
}
if (params.maxDepth != undefined) {
filter.push(traversal.MaxDepthFilter);
}
if (filter.length == 0) {
filter.push(traversal.VisitAllFilter);
}
var config = { var config = {
datasource: traversal.CollectionDatasourceFactory(edgeCollection), datasource: traversal.CollectionDatasourceFactory(edgeCollection),
strategy: validate(params.strategy, { strategy: validate(params.strategy, {
@ -2364,7 +2381,7 @@ function AHUACATL_GRAPH_TRAVERSE () {
trackPaths: params.paths || false, trackPaths: params.paths || false,
visitor: AHUACATL_TRAVERSE_VISITOR, visitor: AHUACATL_TRAVERSE_VISITOR,
maxDepth: params.maxDepth, maxDepth: params.maxDepth,
filter: params.maxDepth != undefined ? traversal.MaxDepthFilter : traversal.VisitAllFilter, filter: filter,
uniqueness: { uniqueness: {
vertices: validate(params.uniqueness && params.uniqueness.vertices, { vertices: validate(params.uniqueness && params.uniqueness.vertices, {
'none': traversal.Traverser.UNIQUE_NONE, 'none': traversal.Traverser.UNIQUE_NONE,

View File

@ -330,6 +330,27 @@ function ahuacatlQueryTraverseTestSuite () {
db._drop(en); db._drop(en);
}, },
////////////////////////////////////////////////////////////////////////////////
/// @brief test min-depth filtering
////////////////////////////////////////////////////////////////////////////////
testTraversalDepthFirstMin : function () {
var config = {
strategy: "depthfirst",
order: "preorder",
itemOrder: "forward",
minDepth: 1,
uniqueness: {
vertices: "global"
},
_sort: true
};
var actual = executeQuery("FOR p IN TRAVERSE(@@v, @@e, '" + vn + "/A', 'outbound', " + JSON.stringify(config) + ") RETURN p.vertex._key", { "@v" : vn, "@e" : en }).getRows();
assertEqual([ "A", "B", "C", "D" ], actual);
},
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief test max-depth filtering /// @brief test max-depth filtering
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -366,6 +387,25 @@ function ahuacatlQueryTraverseTestSuite () {
assertEqual([ "A", "B", "C", "A", "D", "C", "A" ], actual); assertEqual([ "A", "B", "C", "A", "D", "C", "A" ], actual);
}, },
////////////////////////////////////////////////////////////////////////////////
/// @brief test min-/max-depth filtering
////////////////////////////////////////////////////////////////////////////////
testTraversalDepthFirstMinMax : function () {
var config = {
strategy: "depthfirst",
order: "preorder",
itemOrder: "forward",
minDepth: 1,
maxDepth: 3,
_sort: true
};
var actual = executeQuery("FOR p IN TRAVERSE(@@v, @@e, '" + vn + "/A', 'outbound', " + JSON.stringify(config) + ") RETURN p.vertex._key", { "@v" : vn, "@e" : en }).getRows();
assertEqual([ "A", "B", "C", "A", "D", "C", "A" ], actual);
},
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief test max-depth filtering /// @brief test max-depth filtering
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////