diff --git a/CHANGELOG b/CHANGELOG index c4be44dffa..5199e1a32d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,10 @@ v1.2.alpha (XXXX-XX-XX) ----------------------- +* calls to db.collection.figures() and /_api/collection//figures now + additionally return the number of shapes used in the collection in the + extra attribute "shapes.count" + * added experimental AQL TREE() function to return a hierchical result from a traversal. the function name, signature, and behavior are likely to change later. diff --git a/Documentation/Examples/api-collection-get-collection-figures b/Documentation/Examples/api-collection-get-collection-figures index 71d17fe8c6..1dde022ee9 100644 --- a/Documentation/Examples/api-collection-get-collection-figures +++ b/Documentation/Examples/api-collection-get-collection-figures @@ -22,7 +22,10 @@ content-type: application/json "dead": { "size": 2384, "count": 149 - } + }, + "shapes": { + "count": 59 + }, }, "waitForSync": true, "isVolatile": false, diff --git a/Documentation/Examples/shell_collection-figures b/Documentation/Examples/shell_collection-figures index 695a77aeaa..965ff99518 100644 --- a/Documentation/Examples/shell_collection-figures +++ b/Documentation/Examples/shell_collection-figures @@ -1,2 +1,3 @@ arango> db.demo.figures() -{ "numberDatafiles" : 1, "numberAlive" : 1, "numberDead" : 1, "sizeAlive" : 24, "sizeDead" : 24, "numberDeletion" : 1 } +{ "alive" : { "count" : 1000, "size" : 45000 }, "dead" : { "count" : 0, "size" : 0, "deletion" : 0 }, "datafiles" : { "count" : 0, "fileSize" : 0 }, "journals" : { "count" : 1, "fileSize" : 33554432 }, "shapes" : { "count" : 7 } } + diff --git a/UnitTests/HttpInterface/api-collection-spec.rb b/UnitTests/HttpInterface/api-collection-spec.rb index b0d1f6141d..b106e53a59 100644 --- a/UnitTests/HttpInterface/api-collection-spec.rb +++ b/UnitTests/HttpInterface/api-collection-spec.rb @@ -259,9 +259,74 @@ describe ArangoDB do doc.parsed_response['name'].should eq(@cn) doc.parsed_response['status'].should eq(3) doc.parsed_response['count'].should be_kind_of(Integer) + doc.parsed_response['count'].should eq(0) + doc.parsed_response['figures']['dead']['count'].should be_kind_of(Integer) + doc.parsed_response['figures']['dead']['count'].should eq(0) doc.parsed_response['figures']['alive']['count'].should be_kind_of(Integer) - doc.parsed_response['count'].should eq(doc.parsed_response['figures']['alive']['count']) + doc.parsed_response['figures']['alive']['count'].should eq(0) + doc.parsed_response['figures']['shapes']['count'].should be_kind_of(Integer) + doc.parsed_response['figures']['shapes']['count'].should eq(6) doc.parsed_response['journalSize'].should be_kind_of(Integer) + + # create a few documents, this should increase counts and number of shapes + (0...10).each{|i| + body = "{ \"test\" : " + i.to_s + " }" + doc = ArangoDB.log_post("#{prefix}-get-collection-figures", "/_api/document/?collection=" + @cn, :body => body) + } + + doc = ArangoDB.log_get("#{prefix}-get-collection-figures", cmd) + doc.code.should eq(200) + doc.headers['content-type'].should eq("application/json; charset=utf-8") + doc.parsed_response['error'].should eq(false) + doc.parsed_response['code'].should eq(200) + doc.parsed_response['count'].should be_kind_of(Integer) + doc.parsed_response['count'].should eq(10) + doc.parsed_response['figures']['dead']['count'].should be_kind_of(Integer) + doc.parsed_response['figures']['dead']['count'].should eq(0) + doc.parsed_response['figures']['alive']['count'].should be_kind_of(Integer) + doc.parsed_response['figures']['alive']['count'].should eq(10) + doc.parsed_response['figures']['shapes']['count'].should be_kind_of(Integer) + doc.parsed_response['figures']['shapes']['count'].should eq(7) + + # create a few different documents, this should increase counts and number of shapes + (0...10).each{|i| + body = "{ \"test" + i.to_s + "\" : 1 }" + doc = ArangoDB.log_post("#{prefix}-get-collection-figures", "/_api/document/?collection=" + @cn, :body => body) + } + + doc = ArangoDB.log_get("#{prefix}-get-collection-figures", cmd) + doc.code.should eq(200) + doc.headers['content-type'].should eq("application/json; charset=utf-8") + doc.parsed_response['error'].should eq(false) + doc.parsed_response['code'].should eq(200) + doc.parsed_response['count'].should be_kind_of(Integer) + doc.parsed_response['count'].should eq(20) + doc.parsed_response['figures']['dead']['count'].should be_kind_of(Integer) + doc.parsed_response['figures']['dead']['count'].should eq(0) + doc.parsed_response['figures']['alive']['count'].should be_kind_of(Integer) + doc.parsed_response['figures']['alive']['count'].should eq(20) + doc.parsed_response['figures']['shapes']['count'].should be_kind_of(Integer) + doc.parsed_response['figures']['shapes']['count'].should eq(17) + + # delete a few documents, this should change counts + body = "{ \"collection\" : \"" + @cn + "\", \"example\": { \"test\" : 5 } }" + doc = ArangoDB.log_put("#{prefix}-get-collection-figures", "/_api/simple/remove-by-example", :body => body) + body = "{ \"collection\" : \"" + @cn + "\", \"example\": { \"test3\" : 1 } }" + doc = ArangoDB.log_put("#{prefix}-get-collection-figures", "/_api/simple/remove-by-example", :body => body) + + doc = ArangoDB.log_get("#{prefix}-get-collection-figures", cmd) + doc.code.should eq(200) + doc.headers['content-type'].should eq("application/json; charset=utf-8") + doc.parsed_response['error'].should eq(false) + doc.parsed_response['code'].should eq(200) + doc.parsed_response['count'].should be_kind_of(Integer) + doc.parsed_response['count'].should eq(18) + doc.parsed_response['figures']['dead']['count'].should be_kind_of(Integer) + doc.parsed_response['figures']['dead']['count'].should eq(2) + doc.parsed_response['figures']['alive']['count'].should be_kind_of(Integer) + doc.parsed_response['figures']['alive']['count'].should eq(18) + doc.parsed_response['figures']['shapes']['count'].should be_kind_of(Integer) + doc.parsed_response['figures']['shapes']['count'].should eq(17) end # get revision id diff --git a/arangod/V8Server/v8-vocbase.cpp b/arangod/V8Server/v8-vocbase.cpp index cbeea02bd4..8091474676 100644 --- a/arangod/V8Server/v8-vocbase.cpp +++ b/arangod/V8Server/v8-vocbase.cpp @@ -4283,6 +4283,8 @@ static v8::Handle JS_LookupFulltextIndexVocbaseCol (v8::Arguments con /// - @LIT{datafiles.fileSize}: The total filesize of the active datafiles. /// - @LIT{journals.count}: The number of journal files. /// - @LIT{journals.fileSize}: The total filesize of the journal files. +/// - @LIT{shapes.count}: The total number of shapes used in the collection +/// (this includes shapes that are not in use anymore) /// /// @EXAMPLES /// @@ -4352,6 +4354,11 @@ static v8::Handle JS_FiguresVocbaseCol (v8::Arguments const& argv) { js->Set(v8::String::New("count"), v8::Number::New(info->_numberJournalfiles)); js->Set(v8::String::New("fileSize"), v8::Number::New(info->_journalfileSize)); + // shape info + v8::Handle shapes = v8::Object::New(); + result->Set(v8::String::New("shapes"), shapes); + shapes->Set(v8::String::New("count"), v8::Number::New(info->_numberShapes)); + TRI_Free(TRI_UNKNOWN_MEM_ZONE, info); return scope.Close(result); diff --git a/arangod/VocBase/primary-collection.c b/arangod/VocBase/primary-collection.c index 7dea26edb9..84c8002418 100644 --- a/arangod/VocBase/primary-collection.c +++ b/arangod/VocBase/primary-collection.c @@ -389,6 +389,8 @@ static TRI_doc_collection_info_t* Figures (TRI_primary_collection_t* primary) { info->_journalfileSize += df->_maximalSize; ++info->_numberJournalfiles; } + + info->_numberShapes = (TRI_voc_ssize_t) primary->_shaper->numShapes(primary->_shaper); primary->endRead(primary); diff --git a/arangod/VocBase/primary-collection.h b/arangod/VocBase/primary-collection.h index 16e1d28536..cec93c5eb1 100644 --- a/arangod/VocBase/primary-collection.h +++ b/arangod/VocBase/primary-collection.h @@ -172,6 +172,8 @@ typedef struct TRI_doc_collection_info_s { TRI_voc_ssize_t _numberDeletion; TRI_voc_ssize_t _datafileSize; TRI_voc_ssize_t _journalfileSize; + + TRI_voc_ssize_t _numberShapes; } TRI_doc_collection_info_t; diff --git a/arangod/VocBase/voc-shaper.c b/arangod/VocBase/voc-shaper.c index 9a338ab400..46a8359f11 100644 --- a/arangod/VocBase/voc-shaper.c +++ b/arangod/VocBase/voc-shaper.c @@ -526,7 +526,6 @@ static int64_t LookupAttributeWeight (TRI_shaper_t* shaper, TRI_shape_aid_t aid) return item->_weight; } - //////////////////////////////////////////////////////////////////////////////// /// @brief hashes the shapes //////////////////////////////////////////////////////////////////////////////// @@ -620,6 +619,20 @@ static TRI_shape_t const* FindShape (TRI_shaper_t* shaper, TRI_shape_t* shape) { TRI_UnlockMutex(&s->_shapeLock); return l; } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief return the number of shapes +//////////////////////////////////////////////////////////////////////////////// + +static size_t NumShapes (TRI_shaper_t* shaper) { + voc_shaper_t* s; + size_t n; + + s = (voc_shaper_t*) shaper; + n = (size_t) TRI_GetLengthAssociativeSynced(&s->_shapeIds); + + return n; +} //////////////////////////////////////////////////////////////////////////////// /// @brief hashes the shape id @@ -824,6 +837,7 @@ static void InitVocShaper (voc_shaper_t* shaper, TRI_shape_collection_t* collect shaper->base.lookupAttributeId = LookupAttributeId; shaper->base.findShape = FindShape; shaper->base.lookupShapeId = LookupShapeId; + shaper->base.numShapes = NumShapes; TRI_InitAssociativeSynced(&shaper->_attributeNames, TRI_UNKNOWN_MEM_ZONE, diff --git a/html/admin/js/modules/org/arangodb/arango-database.js b/html/admin/js/modules/org/arangodb/arango-database.js index 836b8b4fc2..88149ffc4f 100644 --- a/html/admin/js/modules/org/arangodb/arango-database.js +++ b/html/admin/js/modules/org/arangodb/arango-database.js @@ -60,7 +60,7 @@ function ArangoDatabase (connection) { // private function to store a collection in both "db" and "edges" at the // same time - this.registerCollection = function (name, obj) { + this._registerCollection = function (name, obj) { // store the collection in our own list this[name] = obj; @@ -238,7 +238,7 @@ ArangoDatabase.prototype._collections = function () { // continue; // } var collection = new this._collectionConstructor(this, collections[i]); - this.registerCollection(collection._name, collection); + this._registerCollection(collection._name, collection); result.push(collection); } @@ -277,7 +277,7 @@ ArangoDatabase.prototype._collection = function (id) { var name = requestResult.name; if (name !== undefined) { - this.registerCollection(name, new this._collectionConstructor(this, requestResult)); + this._registerCollection(name, new this._collectionConstructor(this, requestResult)); return this[name]; } @@ -330,7 +330,7 @@ ArangoDatabase.prototype._create = function (name, properties, type) { var nname = requestResult.name; if (nname !== undefined) { - this.registerCollection(nname, new this._collectionConstructor(this, requestResult)); + this._registerCollection(nname, new this._collectionConstructor(this, requestResult)); return this[nname]; } diff --git a/js/actions/system/api-collection.js b/js/actions/system/api-collection.js index 2d99ade515..7d8f74a9f3 100644 --- a/js/actions/system/api-collection.js +++ b/js/actions/system/api-collection.js @@ -336,6 +336,9 @@ function get_api_collections (req, res) { /// - @LIT{figures.journals.count}: The number of journal files. /// - @LIT{figures.journals.fileSize}: The total filesize of journal files. /// +/// - @LIT{figures.shapes.count}: The total number of shapes used in the +/// collection (this includes shapes that are not in use anymore) +/// /// - @LIT{journalSize}: The maximal size of the journal in bytes. /// /// Note: the filesizes of shapes and compactor files are not reported. diff --git a/lib/BasicsC/associative.c b/lib/BasicsC/associative.c index ebf27ff0e7..7aadeb4faf 100644 --- a/lib/BasicsC/associative.c +++ b/lib/BasicsC/associative.c @@ -1499,6 +1499,20 @@ void* TRI_RemoveKeyAssociativeSynced (TRI_associative_synced_t* array, TRI_WriteUnlockReadWriteLock(&array->_lock); return old; } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief get the number of elements from the array +//////////////////////////////////////////////////////////////////////////////// + +size_t TRI_GetLengthAssociativeSynced (TRI_associative_synced_t* const array) { + uint32_t result; + + TRI_ReadLockReadWriteLock(&array->_lock); + result = array->_nrUsed; + TRI_ReadUnlockReadWriteLock(&array->_lock); + + return (size_t) result; +} //////////////////////////////////////////////////////////////////////////////// /// @} diff --git a/lib/BasicsC/associative.h b/lib/BasicsC/associative.h index b9b9c0de78..10e843efb3 100644 --- a/lib/BasicsC/associative.h +++ b/lib/BasicsC/associative.h @@ -492,6 +492,12 @@ void* TRI_RemoveElementAssociativeSynced (TRI_associative_synced_t*, void const* void* TRI_RemoveKeyAssociativeSynced (TRI_associative_synced_t*, void const* key); +//////////////////////////////////////////////////////////////////////////////// +/// @brief get the number of elements from the array +//////////////////////////////////////////////////////////////////////////////// + +size_t TRI_GetLengthAssociativeSynced (TRI_associative_synced_t* const); + //////////////////////////////////////////////////////////////////////////////// /// @} //////////////////////////////////////////////////////////////////////////////// diff --git a/lib/ShapedJson/json-shaper.h b/lib/ShapedJson/json-shaper.h index 551b24eb3c..572f888b0a 100644 --- a/lib/ShapedJson/json-shaper.h +++ b/lib/ShapedJson/json-shaper.h @@ -70,6 +70,7 @@ typedef struct TRI_shaper_s { int64_t (*lookupAttributeWeight) (struct TRI_shaper_s*, TRI_shape_aid_t); TRI_shape_path_t const* (*lookupAttributePathByPid) (struct TRI_shaper_s*, TRI_shape_pid_t); TRI_shape_pid_t (*findAttributePathByName) (struct TRI_shaper_s*, char const*); + size_t (*numShapes) (struct TRI_shaper_s*); TRI_associative_synced_t _attributePathsByName; TRI_associative_synced_t _attributePathsByPid;