diff --git a/CHANGELOG b/CHANGELOG index c12b717e6f..6e37bb14bd 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,8 @@ v1.2.alpha (XXXX-XX-XX) ----------------------- +* added collection.revision() method to determine whether a collection has changed + * issue #346: adaptively determine NUMBER_HEADERS_PER_BLOCK * issue #338: arangosh cursor positioning problems diff --git a/Documentation/Examples/shell-read-document b/Documentation/Examples/shell-read-document deleted file mode 100644 index 4057328c7b..0000000000 --- a/Documentation/Examples/shell-read-document +++ /dev/null @@ -1,2 +0,0 @@ -arango> db.example.document("1432124/2873916"); -{ "_id" : "1432124/2873916", "_rev" : 2873916, "Hallo" : "World" } diff --git a/Documentation/Examples/shell-read-document-bad-handle b/Documentation/Examples/shell-read-document-bad-handle deleted file mode 100644 index f228fb18ad..0000000000 --- a/Documentation/Examples/shell-read-document-bad-handle +++ /dev/null @@ -1,5 +0,0 @@ -arango> db.example.document("12345"); -JavaScript exception in file '(arango)' at 1,12: - [ArangoError 10: bad parameter: must be a document identifier] -!db.example.document("12345"); -! ^ diff --git a/Documentation/Examples/shell-read-document-not-found b/Documentation/Examples/shell-read-document-not-found deleted file mode 100644 index 2846b2582c..0000000000 --- a/Documentation/Examples/shell-read-document-not-found +++ /dev/null @@ -1,5 +0,0 @@ -arango> db.example.document("1432124/123456"); -JavaScript exception in file '(arango)' at 1,12: - [ArangoError 1202: document not found: document not found] -!db.example.document("1432124/123456"); -! ^ diff --git a/Documentation/Examples/shell_collection-truncate b/Documentation/Examples/shell_collection-truncate deleted file mode 100644 index e179ee9b0c..0000000000 --- a/Documentation/Examples/shell_collection-truncate +++ /dev/null @@ -1,9 +0,0 @@ -arango> col = db.examples; -[ArangoCollection 91022, "examples" (status new born)] -arango> col.save({ "Hallo" : "World" }); -{ "_id" : "91022/1532814", "_rev" : 1532814 } -arango> col.count(); -1 -arango> col.truncate(); -arango> col.count(); -0 diff --git a/Documentation/Examples/shell_index-read b/Documentation/Examples/shell_index-read deleted file mode 100644 index 80269b42b9..0000000000 --- a/Documentation/Examples/shell_index-read +++ /dev/null @@ -1,4 +0,0 @@ -arango> db.example.getIndexes().map(function(x) { return x.id; }); -["93013/0"] -arango> db.example.index("93013/0"); -{ "id" : "93013/0", "type" : "primary", "fields" : ["_id"] } diff --git a/Documentation/Examples/shell_remove-document b/Documentation/Examples/shell_remove-document deleted file mode 100644 index 490042aa9d..0000000000 --- a/Documentation/Examples/shell_remove-document +++ /dev/null @@ -1,10 +0,0 @@ -arango> a1 = db.example.save({ a : 1 }); -{ "_id" : "116308/3449537", "_rev" : 3449537 } -arango> db.example.document(a1); -{ "_id" : "116308/3449537", "_rev" : 3449537, "a" : 1 } -arango> db.example.delete(a1); -true -arango> db.example.document(a1); -JavaScript exception in file '(arango)' at 1,12: [ArangoError 1202: document not found: document not found] -!db.example.document(a1); -! ^ diff --git a/Documentation/Examples/shell_remove-document-conflict b/Documentation/Examples/shell_remove-document-conflict deleted file mode 100644 index 97416b82a7..0000000000 --- a/Documentation/Examples/shell_remove-document-conflict +++ /dev/null @@ -1,14 +0,0 @@ -arango> a1 = db.example.save({ a : 1 }); -{ "_id" : "116308/3857139", "_rev" : 3857139 } -arango> a2 = db.example.replace(a1, { a : 2 }); -{ "_id" : "116308/3857139", "_rev" : 3922675, "_oldRev" : 3857139 } -arango> db.example.delete(a1); -JavaScript exception in file '(arango)' at 1,18: [ArangoError 1200: conflict: cannot delete document] -!db.example.delete(a1); -! ^ -arango> db.example.delete(a1, true); -true -arango> db.example.document(a1); -JavaScript exception in file '(arango)' at 1,12: [ArangoError 1202: document not found: document not found] -!db.example.document(a1); -! ^ diff --git a/Documentation/Examples/shell_remove-document-conflict-db b/Documentation/Examples/shell_remove-document-conflict-db deleted file mode 100644 index bd81f78077..0000000000 --- a/Documentation/Examples/shell_remove-document-conflict-db +++ /dev/null @@ -1,14 +0,0 @@ -arango> a1 = db.example.save({ a : 1 }); -{ "_id" : "116308/4042634", "_rev" : 4042634 } -arango> a2 = db._replace(a1, { a : 2 }); -{ "_id" : "116308/4042634", "_rev" : 4108170, "_oldRev" : 4042634 } -arango> db._delete(a1); -JavaScript exception in file '(arango)' at 1,4: [ArangoError 1200: conflict: cannot delete document] -!db._delete(a1); -! ^ -arango> db._delete(a1, true); -true -arango> db._document(a1); -JavaScript exception in file '(arango)' at 1,4: [ArangoError 1202: document not found: document not found] -!db._document(a1); -! ^ diff --git a/Documentation/Examples/shell_remove-document-db b/Documentation/Examples/shell_remove-document-db deleted file mode 100644 index 3ff4ff0647..0000000000 --- a/Documentation/Examples/shell_remove-document-db +++ /dev/null @@ -1,10 +0,0 @@ -arango> a1 = db.example.save({ a : 1 }); -{ "_id" : "116308/4214943", "_rev" : 4214943 } -arango> db._delete(a1); -true -arango> db._delete(a1); -JavaScript exception in file '(arango)' at 1,4: [ArangoError 1202: document not found: cannot delete document] -!db._delete(a1); -! ^ -arango> db._delete(a1, true); -false diff --git a/Documentation/Makefile.files b/Documentation/Makefile.files index 7415cff4ed..f0b0e91c2f 100644 --- a/Documentation/Makefile.files +++ b/Documentation/Makefile.files @@ -28,7 +28,8 @@ DOXYGEN = \ Doxygen/js/actions/system/api-simple.c \ Doxygen/js/actions/system/api-system.c \ Doxygen/js/common/bootstrap/modules.c \ - Doxygen/js/common/bootstrap/print.c \ + Doxygen/js/common/bootstrap/module-console.c \ + Doxygen/js/common/bootstrap/module-fs.c \ Doxygen/js/common/modules/graph.c \ Doxygen/js/common/modules/jsunity.c \ Doxygen/js/common/modules/simple-query-basics.c \ @@ -36,6 +37,7 @@ DOXYGEN = \ Doxygen/js/common/modules/users.c \ Doxygen/js/server/modules/org/arangodb/actions.c \ Doxygen/js/server/modules/simple-query.c \ + Doxygen/js/server/ArangoCollection.c \ Doxygen/js/server/server.c ################################################################################ diff --git a/Documentation/RefManual/JSModuleFs.md b/Documentation/RefManual/JSModuleFs.md new file mode 100644 index 0000000000..3ba84428af --- /dev/null +++ b/Documentation/RefManual/JSModuleFs.md @@ -0,0 +1,22 @@ +Module "fs" {#JSModuleFs} +========================= + +@EMBEDTOC{JSModuleFsTOC} + +The implementation follows the CommonJS specification +@EXTREF{http://wiki.commonjs.org/wiki/Filesystem/A/0,Filesystem/A/0}. + +@anchor JSModuleFsExists +@copydetails JS_Exists + +@anchor JSModuleFsIsDirectory +@copydetails JS_IsDirectory + +@anchor JSModuleFsListTree +@copydetails JS_ListTree + +@anchor JSModuleFsMove +@copydetails JS_Move + +@anchor JSModuleFsRemove +@copydetails JS_Remove diff --git a/Documentation/RefManual/JSModuleFsTOC.md b/Documentation/RefManual/JSModuleFsTOC.md new file mode 100644 index 0000000000..ff11db990c --- /dev/null +++ b/Documentation/RefManual/JSModuleFsTOC.md @@ -0,0 +1,9 @@ +TOC {#JSModuleFsTOC} +==================== + +- @ref JSModuleFs + - @ref JSModuleFsExists "fs.exists" + - @ref JSModuleFsIsDirectory "fs.isDirectory" + - @ref JSModuleFsListTree "fs.listTree" + - @ref JSModuleFsMove "fs.move" + - @ref JSModuleFsRemove "fs.remove" diff --git a/Documentation/UserManual/Actions.md b/Documentation/UserManual/Actions.md index 75bcdf8cab..0757d3a51d 100644 --- a/Documentation/UserManual/Actions.md +++ b/Documentation/UserManual/Actions.md @@ -305,7 +305,7 @@ A Simple Action {#UserManualActionsContentAction} The simplest dynamic action is: - { action: { controller: "org/arangodb/actions", do: "echoRequest" } } + { action: { do: "org/arangodb/actions/echoRequest" } } It is not possible to store functions directly in the routing table, but you can call functions defined in modules. In the above example the function can be @@ -324,7 +324,7 @@ For example arangosh> db._routing.save({ ........> url: "/hello/echo", - ........> action: { controller: "org/arangodb/actions", do: "echoRequest" } }); + ........> action: { do: "org/arangodb/actions/echoRequest" } }); Reload the routing and check @@ -645,3 +645,99 @@ should win in this case: ........> ] ........> }); +Application Deployment {#UserManualActionsApplicationDeployment} +================================================================ + +Using single routes or @ref UserManualActionsAdvancedBundles "bundles" can be +become a bit messy in large applications. Therefore a deployment tool exists +inside _arangosh_ to simplify the task. This tool was inspired by the ArangoDB +deployment tool `https://github.com/kaerus/arangodep` written in node.js by +kaerus. + +An application is a bunch of routes, static pages stored in collections, and +small scriptlets stored modules. + +In order to create an application, chose a suitable name, e. g. reverse domain +name plus the application name and call `createApp`: + + arangosh> var deploy = require("org/arangodb/deploy"); + arangosh> var app = deploy.createApp("org.example.simple"); + +Normally content will either be stored in collections or dynamically +calculated. But sometimes it is convenient to store the content directly in the +routing table, e. g. to deliver a version number. + + arangosh> app.mountStaticContent("/version", { + ........> version: "1.2.3", major: 1, minor: 2, patch: 3 }); + [ArangoApp "org.example.simple" at ""] + +Save the application + + arangosh> app.save(); + [ArangoApp "org.example.simple" at ""] + +and use the browser to check the result + + http://localhost:8529/version + +You can also specify the content-type + + arangosh> app.mountStaticContent("/author", + ........> "Frank Celler", + ........> "text/plain").save(); + [ArangoApp "org.example.simple" at ""] + +and check at + + http://localhost:8529/author + +If you have more than one application, putting version under `/` might lead to +conflicts. It is therefore possible to use a common prefix for the application. + + arangosh> app.setPrefix("/example").save(); + [ArangoApp "org.example.simple" at "/example"] + +Now check + + http://localhost:8529/example/version + http://localhost:8529/example/author + +Deploying Static Pages {#UserManualActionsDeployingStaticPages} +--------------------------------------------------------------- + +Most of the time, static html pages and JavaScript content will be delivered by +your web-server. But sometimes it is convenient to deliver these directly from +within ArangoDB. For example, to provide a small admin interface for you +application. + +Assume that all data is stored underneath a directory "/tmp/example" and we want +to store the content in a collection "org_example_simple_content". + +First connect the url path to the collection. + + arangosh> app.mountStaticPages("/static", "org_example_simple_content").save(); + [ArangoApp "org.example.simple" at "/example"] + +Next create a file `index.html` at `/tmp/example/index.html". + + + + Hallo World! + + + +Create the collection and upload this into the collection + + arangosh> require("org/arangodb").db._createDocumentCollection("org_example_simple_content"); + [ArangoCollection 224910918055, "org_example_simple_content" (type document, status loaded)] + + arangosh> app.uploadStaticPages("/static", "/tmp/example"); + imported '/index.html' of type 'text/html; charset=utf-8' + [ArangoApp "org.example.simple" at "/example"] + +Check the index file + + http://localhost:8529/example/static/index.html + + + diff --git a/Documentation/UserManual/ActionsTOC.md b/Documentation/UserManual/ActionsTOC.md index e1b6b3fc50..bcf1183738 100644 --- a/Documentation/UserManual/ActionsTOC.md +++ b/Documentation/UserManual/ActionsTOC.md @@ -25,3 +25,5 @@ TOC {#UserManualActionsTOC} - @ref UserManualActionsAdvancedRedirects - @ref UserManualActionsAdvancedBundles - @ref UserManualActionsAdvancedMiddleware + - @ref UserManualActionsApplicationDeployment + - @ref UserManualActionsDeployingStaticPages diff --git a/Documentation/UserManual/HandlingDocuments.md b/Documentation/UserManual/HandlingDocuments.md new file mode 100644 index 0000000000..25509a3508 --- /dev/null +++ b/Documentation/UserManual/HandlingDocuments.md @@ -0,0 +1,120 @@ +Handling Documents {#ShellDocument} +=================================== + +@NAVIGATE_ShellDocument +@EMBEDTOC{ShellDocumentTOC} + +This is an introduction to ArangoDB's interface for documents and how handle +documents from the JavaScript shell _arangosh_. For other languages see +the corresponding language API. + +Documents, Identifiers, Handles {#ShellDocumentIntro} +===================================================== + +@copydoc GlossaryDocument + +For example: + + { + "_id" : "demo/2345678", + "_rev" : "3456789", + "_key" : "2345678", + "firstName" : "Hugo", + "lastName" : "Schlonz", + "address" : { + "street" : "Strasse 1", + "city" : "Hier" + }, + "hobbies" : [ + "swimming", + "biking", + "programming" + ] + } + +All documents contain special attributes: the document handle in `_id`, the +document's unique key in `_key` and and the etag aka document revision in +`_rev`. The value of the `_key` attribute can be specified by the user when +creating a document. `_id` and `_key` values are immutable once the document +has been created. The `_rev` value is maintained by ArangoDB autonomously. + +@copydoc GlossaryDocumentHandle + +@copydoc GlossaryDocumentIdentifier + +@copydoc GlossaryDocumentRevision + +@copydoc GlossaryDocumentEtag + +Address and ETag of an Document {#ShellDocumentResource} +======================================================== + +All documents in ArangoDB have a document handle. This handle uniquely defines a +document and is managed by ArangoDB. The interface allows you to access the +documents of a collection as: + + db.@FA{collection}.documet(@FA{document-handle}) + +For example: Assume that the document handle, which is stored in the `_id` field +of the document, is `demo/362549` and the document lives in a collection +named @FA{demo}, then that document can be accessed as: + + db.demo.document("demo/362549736") + +Because the document handle is unique within the database, you +can leave out the @FA{collection} and use the shortcut: + + db._document("demo/362549736") + +Each document also has a document revision or etag with is returned in the +`_rev` field when requesting a document. The document's key is returned in the +`_key` attribute. + +@CLEARPAGE +Working with Documents {#ShellDocumentShell} +============================================ + +Collection Methods {#ShellDocumentCollectionMethods} +---------------------------------------------------- + +@anchor ShellDocumentRead +@copydetails JS_DocumentVocbaseCol + +@CLEARPAGE +@anchor ShellDocumentCreate +@copydetails JS_SaveVocbaseCol + +@CLEARPAGE +@anchor ShellDocumentReplace +@copydetails JS_ReplaceVocbaseCol + +@CLEARPAGE +@anchor ShellDocumentUpdate +@copydetails JS_UpdateVocbaseCol + +@CLEARPAGE +@anchor ShellDocumentRemove +@copydetails JS_RemoveVocbaseCol + +@CLEARPAGE +@anchor ShellDocumentRemoveByExample +@copydetails JSF_ArangoCollection_prototype_removeByExample + +@CLEARPAGE +Database Methods {#ShellDocumentDatabaseMethods} +------------------------------------------------ + +@anchor ShellDocumentDbRead +@copydetails JS_DocumentVocbase + +@CLEARPAGE +@anchor ShellDocumentDbReplace +@copydetails JS_ReplaceVocbase + +@CLEARPAGE +@anchor ShellDocumentDbUpdate +@copydetails JS_UpdateVocbase + +@CLEARPAGE +@anchor ShellDocumentDbRemove +@copydetails JS_RemoveVocbase diff --git a/Documentation/UserManual/HandlingDocumentsTOC.md b/Documentation/UserManual/HandlingDocumentsTOC.md new file mode 100644 index 0000000000..4ef454d5a2 --- /dev/null +++ b/Documentation/UserManual/HandlingDocumentsTOC.md @@ -0,0 +1,19 @@ +TOC {#ShellDocumentTOC} +======================= + +- @ref ShellDocument + - @ref ShellDocumentIntro + - @ref ShellDocumentResource + - @ref ShellDocumentShell + - @ref ShellDocumentCollectionMethods + - @ref ShellDocumentRead "collection.document" + - @ref ShellDocumentCreate "collection.save" + - @ref ShellDocumentReplace "collection.replace" + - @ref ShellDocumentUpdate "collection.update" + - @ref ShellDocumentRemove "collection.remove" + - @ref ShellDocumentRemoveByExample "collection.removeByExample" + - @ref ShellDocumentDatabaseMethods + - @ref ShellDocumentDbRead "db._document" + - @ref ShellDocumentDbReplace "db._replace" + - @ref ShellDocumentDbUpdate "db._update" + - @ref ShellDocumentDbRemove "db._remove" diff --git a/Documentation/arango.template.in b/Documentation/arango.template.in index 21b4c13f70..24193428a9 100644 --- a/Documentation/arango.template.in +++ b/Documentation/arango.template.in @@ -197,26 +197,26 @@ TAB_SIZE = 8 # function definition ALIASES = \ - "FUN{1}=@latexonly\functionsignature{@endlatexonly@htmlonly
@endhtmlonly@xmlonly XMLMISSING @endxmlonly\1@latexonly}@endlatexonly@htmlonly
@endhtmlonly@xmlonly XMLMISSING @endxmlonly" \ - "FUN{2}=@latexonly\functionsignature{@endlatexonly@htmlonly
@endhtmlonly@xmlonly XMLMISSING @endxmlonly\1, \2@latexonly}@endlatexonly@htmlonly
@endhtmlonly@xmlonly XMLMISSING @endxmlonly" \ - "FUN{3}=@latexonly\functionsignature{@endlatexonly@htmlonly
@endhtmlonly@xmlonly XMLMISSING @endxmlonly\1, \2, \3@latexonly}@endlatexonly@htmlonly
@endhtmlonly@xmlonly XMLMISSING @endxmlonly" \ - "FUN{4}=@latexonly\functionsignature{@endlatexonly@htmlonly
@endhtmlonly@xmlonly XMLMISSING @endxmlonly\1, \2, \3, \4@latexonly}@endlatexonly@htmlonly
@endhtmlonly@xmlonly XMLMISSING @endxmlonly" \ - "FUN{5}=@latexonly\functionsignature{@endlatexonly@htmlonly
@endhtmlonly@xmlonly XMLMISSING @endxmlonly\1, \2, \3, \4, \5@latexonly}@endlatexonly@htmlonly
@endhtmlonly@xmlonly XMLMISSING @endxmlonly" \ - "FUN{6}=@latexonly\functionsignature{@endlatexonly@htmlonly
@endhtmlonly@xmlonly XMLMISSING @endxmlonly\1, \2, \3, \4, \5, \6@latexonly}@endlatexonly@htmlonly
@endhtmlonly@xmlonly XMLMISSING @endxmlonly" \ - "FUN{7}=@latexonly\functionsignature{@endlatexonly@htmlonly
@endhtmlonly@xmlonly XMLMISSING @endxmlonly\1, \2, \3, \4, \5, \6, \7@latexonly}@endlatexonly@htmlonly
@endhtmlonly@xmlonly XMLMISSING @endxmlonly" \ - "FA{1}=@latexonly\functionargument{@endlatexonly@htmlonly@endhtmlonly@xmlonly XMLMISSING @endxmlonly\1@latexonly}@endlatexonly@htmlonly@endhtmlonly@xmlonly XMLMISSING @endxmlonly" \ - "FN{1}=@latexonly\functionname{@endlatexonly@htmlonly@endhtmlonly@xmlonly XMLMISSING @endxmlonly\1@latexonly}@endlatexonly@htmlonly@endhtmlonly@xmlonly XMLMISSING @endxmlonly" + "FUN{1}=@latexonly\functionsignature{@endlatexonly@htmlonly
@endhtmlonly@xmlonly @endxmlonly\1@latexonly}@endlatexonly@htmlonly
@endhtmlonly@xmlonly @endxmlonly" \ + "FUN{2}=@latexonly\functionsignature{@endlatexonly@htmlonly
@endhtmlonly@xmlonly @endxmlonly\1, \2@latexonly}@endlatexonly@htmlonly
@endhtmlonly@xmlonly @endxmlonly" \ + "FUN{3}=@latexonly\functionsignature{@endlatexonly@htmlonly
@endhtmlonly@xmlonly @endxmlonly\1, \2, \3@latexonly}@endlatexonly@htmlonly
@endhtmlonly@xmlonly @endxmlonly" \ + "FUN{4}=@latexonly\functionsignature{@endlatexonly@htmlonly
@endhtmlonly@xmlonly @endxmlonly\1, \2, \3, \4@latexonly}@endlatexonly@htmlonly
@endhtmlonly@xmlonly @endxmlonly" \ + "FUN{5}=@latexonly\functionsignature{@endlatexonly@htmlonly
@endhtmlonly@xmlonly @endxmlonly\1, \2, \3, \4, \5@latexonly}@endlatexonly@htmlonly
@endhtmlonly@xmlonly @endxmlonly" \ + "FUN{6}=@latexonly\functionsignature{@endlatexonly@htmlonly
@endhtmlonly@xmlonly @endxmlonly\1, \2, \3, \4, \5, \6@latexonly}@endlatexonly@htmlonly
@endhtmlonly@xmlonly @endxmlonly" \ + "FUN{7}=@latexonly\functionsignature{@endlatexonly@htmlonly
@endhtmlonly@xmlonly @endxmlonly\1, \2, \3, \4, \5, \6, \7@latexonly}@endlatexonly@htmlonly
@endhtmlonly@xmlonly @endxmlonly" \ + "FA{1}=@latexonly\functionargument{@endlatexonly@htmlonly@endhtmlonly@xmlonly @endxmlonly\1@latexonly}@endlatexonly@htmlonly@endhtmlonly@xmlonly @endxmlonly" \ + "FN{1}=@latexonly\functionname{@endlatexonly@htmlonly@endhtmlonly@xmlonly @endxmlonly\1@latexonly}@endlatexonly@htmlonly@endhtmlonly@xmlonly @endxmlonly" # command line option ALIASES += \ - "CMDOPT{1}=@latexonly\commandlineoption{@endlatexonly@htmlonly
@endhtmlonly@xmlonly XMLMISSING @endxmlonly\1@latexonly}@endlatexonly@htmlonly
@endhtmlonly@xmlonly XMLMISSING @endxmlonly" \ - "CA{1}=@latexonly\commandlineargument{@endlatexonly@htmlonly@endhtmlonly@xmlonly XMLMISSING @endxmlonly\1@latexonly}@endlatexonly@htmlonly@endhtmlonly@xmlonly XMLMISSING @endxmlonly" \ - "CO{1}=@latexonly\commandoption{@endlatexon\@htmlonly@endhtmlonly@xmlonly XMLMISSING @endxmlonly\1@latexonly}@endlatexonly@htmlonly@endhtmlonly@xmlonly XMLMISSING @endxmlonly" + "CMDOPT{1}=@latexonly\commandlineoption{@endlatexonly@htmlonly
@endhtmlonly@xmlonly @endxmlonly\1@latexonly}@endlatexonly@htmlonly
@endhtmlonly@xmlonly @endxmlonly" \ + "CA{1}=@latexonly\commandlineargument{@endlatexonly@htmlonly@endhtmlonly@xmlonly @endxmlonly\1@latexonly}@endlatexonly@htmlonly@endhtmlonly@xmlonly @endxmlonly" \ + "CO{1}=@latexonly\commandoption{@endlatexonly@htmlonly@endhtmlonly@xmlonly @endxmlonly\1@latexonly}@endlatexonly@htmlonly@endhtmlonly@xmlonly @endxmlonly" # rest calls ALIASES += \ - "RESTHEADER{2}=@latexonly\restheader{@endlatexonly@htmlonly
@endhtmlonly@xmlonly XMLMISSING @endxmlonly\1@latexonly,@endlatexonly@htmlonly
(@endhtmlonly@xmlonly XMLMISSING @endxmlonly\2@latexonly}@endlatexonly@htmlonly)
@endhtmlonly@xmlonly XMLMISSING @endxmlonly" \ - "REST{1}=@latexonly\restcall{@endlatexonly@htmlonly
@endhtmlonly@xmlonly XMLMISSING @endxmlonly\1@latexonly}@endlatexonly@htmlonly
@endhtmlonly@xmlonly XMLMISSING @endxmlonly" + "RESTHEADER{2}=@latexonly\restheader{@endlatexonly@htmlonly
@endhtmlonly@xmlonly @endxmlonly\1@latexonly,@endlatexonly@htmlonly
(@endhtmlonly@xmlonly @endxmlonly\2@latexonly}@endlatexonly@htmlonly)
@endhtmlonly@xmlonly @endxmlonly" \ + "REST{1}=@latexonly\restcall{@endlatexonly@htmlonly
@endhtmlonly@xmlonly @endxmlonly\1@latexonly}@endlatexonly@htmlonly
@endhtmlonly@xmlonly @endxmlonly" # navigation ALIASES += \ @@ -227,7 +227,7 @@ ALIASES += \ # glossary ALIASES += \ - "GE{1}=@latexonly\glossaryentry{@endlatexonly@htmlonly@endhtmlonly@xmlonly XMLMISSING @endxmlonly\1@latexonly}@endlatexonly@htmlonly@endhtmlonly@xmlonly XMLMISSING @endxmlonly" + "GE{1}=@latexonly\glossaryentry{@endlatexonly@htmlonly@endhtmlonly@xmlonly @endxmlonly\1@latexonly}@endlatexonly@htmlonly@endhtmlonly@xmlonly @endxmlonly" # examples ALIASES += \ @@ -723,7 +723,8 @@ WARN_LOGFILE = INPUT = @srcdir@/Documentation/DbaManual \ @srcdir@/Documentation/InstallationManual \ @srcdir@/Documentation/Manual \ - @srcdir@/Documentation/UserManual \ + @srcdir@/Documentation/RefManual \ + @srcdir@/Documentation/UserManual \ @srcdir@/Doxygen/js \ @srcdir@/arangod \ @srcdir@/lib diff --git a/Makefile.am b/Makefile.am index 3161a009cd..52517c8b4c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -324,8 +324,7 @@ clean-local: built-sources: \ build_posix.h \ - @top_srcdir@/js/common/bootstrap/errors.js \ - $(JAVASCRIPT_HEADER) + @top_srcdir@/js/common/bootstrap/errors.js ################################################################################ ### @brief tags file diff --git a/Makefile.files b/Makefile.files index 0ea02ef88a..f5ff1d4074 100644 --- a/Makefile.files +++ b/Makefile.files @@ -4,22 +4,6 @@ ## --SECTION-- JAVASCRIPT ## ----------------------------------------------------------------------------- -################################################################################ -### @brief JavaScript source code as header -################################################################################ - -JAVASCRIPT_HEADER = \ - js/common/bootstrap/js-errors.h \ - js/common/bootstrap/js-modules.h \ - js/common/bootstrap/js-monkeypatches.h \ - js/common/bootstrap/js-print.h \ - js/client/js-client.h \ - js/server/js-server.h \ - js/server/js-version-check.h \ - js/server/js-ahuacatl.h - -BUILT_SOURCES += $(JAVASCRIPT_HEADER) - ################################################################################ ### @brief JavaScript modules for browser ################################################################################ diff --git a/UnitTests/HttpInterface/api-http-spec.rb b/UnitTests/HttpInterface/api-http-spec.rb index dbc5c74fbf..c5c5117b8e 100644 --- a/UnitTests/HttpInterface/api-http-spec.rb +++ b/UnitTests/HttpInterface/api-http-spec.rb @@ -58,7 +58,7 @@ describe ArangoDB do # create collection with one document @cid = ArangoDB.create_collection(cn) - cmd = "/_api/document?collection=#{@cid}" + cmd = "/_api/document?collection=#{cn}" body = "{ \"Hello\" : \"World\" }" doc = ArangoDB.log_post("#{prefix}", cmd, :body => body) diff --git a/arangod/Ahuacatl/ahuacatl-functions.c b/arangod/Ahuacatl/ahuacatl-functions.c index fcea6edcc0..4720d0cddd 100644 --- a/arangod/Ahuacatl/ahuacatl-functions.c +++ b/arangod/Ahuacatl/ahuacatl-functions.c @@ -374,6 +374,7 @@ static void OptimisePaths (const TRI_aql_node_t* const fcallNode, len = strlen(lookFor); } else { + // "any" will not be optimised lookFor = NULL; len = 0; } @@ -395,6 +396,110 @@ static void OptimisePaths (const TRI_aql_node_t* const fcallNode, hint = (TRI_aql_collection_hint_t*) (TRI_AQL_NODE_DATA(vertexCollection)); hint->_ranges = TRI_AddAccessAql(context, hint->_ranges, fieldAccess); } + + if (args->_members._length <= 4 && + TRI_EqualString(name, ".edges.LENGTH()")) { + // length restriction, can only be applied if length parameters are not already set + TRI_aql_node_t* argNode; + TRI_json_t* value; + double minValue = 0.0; + double maxValue = 0.0; + bool useMin = false; + bool useMax = false; + + if (fieldAccess->_type == TRI_AQL_ACCESS_EXACT) { + value = fieldAccess->_value._value; + + if (value != NULL && value->_type == TRI_JSON_NUMBER) { + // LENGTH(p.edges) == const + minValue = maxValue = value->_value._number; + useMin = useMax = true; + } + } + else if (fieldAccess->_type == TRI_AQL_ACCESS_RANGE_SINGLE) { + value = fieldAccess->_value._singleRange._value; + + if (value != NULL && value->_type == TRI_JSON_NUMBER) { + // LENGTH(p.edges) operator const + if (fieldAccess->_value._singleRange._type == TRI_AQL_RANGE_LOWER_INCLUDED) { + minValue = value->_value._number; + useMin = true; + } + else if (fieldAccess->_value._singleRange._type == TRI_AQL_RANGE_UPPER_INCLUDED) { + maxValue = value->_value._number; + useMax = true; + } + else if (fieldAccess->_value._singleRange._type == TRI_AQL_RANGE_LOWER_EXCLUDED) { + if ((double) ((int) value->_value._number) == value->_value._number) { + minValue = value->_value._number + 1.0; + useMin = true; + } + } + else if (fieldAccess->_value._singleRange._type == TRI_AQL_RANGE_UPPER_EXCLUDED) { + if ((double) ((int) value->_value._number) == value->_value._number) { + maxValue = value->_value._number - 1.0; + useMax = true; + } + } + } + } + else if (fieldAccess->_type == TRI_AQL_ACCESS_RANGE_DOUBLE) { + // LENGTH(p.edges) > const && LENGTH(p.edges) < const + value = fieldAccess->_value._between._lower._value; + + if (value != NULL && value->_type == TRI_JSON_NUMBER) { + if (fieldAccess->_value._between._lower._type == TRI_AQL_RANGE_LOWER_INCLUDED) { + minValue = value->_value._number; + useMin = true; + } + else if (fieldAccess->_value._between._lower._type == TRI_AQL_RANGE_LOWER_EXCLUDED) { + if ((double) ((int) value->_value._number) == value->_value._number) { + minValue = value->_value._number + 1.0; + useMin = true; + } + } + } + + value = fieldAccess->_value._between._upper._value; + + if (value != NULL && value->_type == TRI_JSON_NUMBER) { + if (fieldAccess->_value._between._upper._type == TRI_AQL_RANGE_UPPER_INCLUDED) { + maxValue = value->_value._number; + useMax = true; + } + else if (fieldAccess->_value._between._upper._type == TRI_AQL_RANGE_UPPER_EXCLUDED) { + if ((double) ((int) value->_value._number) == value->_value._number) { + maxValue = value->_value._number - 1.0; + useMax = true; + } + } + } + } + + if (useMin || useMax) { + // minLength and maxLength are parameters 5 & 6 + // add as many null value nodes as are missing + while (args->_members._length < 4) { + argNode = TRI_CreateNodeValueNullAql(context); + if (argNode) { + TRI_PushBackVectorPointer(&args->_members, (void*) argNode); + } + } + + // add min and max values to the function call argument list + argNode = TRI_CreateNodeValueIntAql(context, useMin ? (int64_t) minValue : (int64_t) 0); + if (argNode) { + // min value node + TRI_PushBackVectorPointer(&args->_members, (void*) argNode); + + argNode = TRI_CreateNodeValueIntAql(context, useMax ? (int64_t) maxValue : (int64_t) (1024 * 1024)); + if (argNode) { + // max value node + TRI_PushBackVectorPointer(&args->_members, (void*) argNode); + } + } + } + } } //////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/Documentation/api-collection.dox b/arangod/Documentation/api-collection.dox index 755eb441fd..9a961b5b9b 100644 --- a/arangod/Documentation/api-collection.dox +++ b/arangod/Documentation/api-collection.dox @@ -119,37 +119,37 @@ /////////////////////////////////////////////////////////////////////////// /// /// @anchor HttpCollectionCreate -/// @copydetails JSF_POST_api_collection +/// @copydetails JSF_post_api_collection /// /// @anchor HttpCollectionDelete -/// @copydetails JSF_DELETE_api_collection +/// @copydetails JSF_delete_api_collection /// /// @anchor HttpCollectionTruncate -/// @copydetails JSF_PUT_api_collection_truncate +/// @copydetails JSF_put_api_collection_truncate /// /// @subsection HttpCollectionReading Getting Information about a Collection //////////////////////////////////////////////////////////////////////////// /// /// @anchor HttpCollectionRead -/// @copydetails JSF_GET_api_collection +/// @copydetails JSF_get_api_collection /// /// @anchor HttpCollectionReadAll -/// @copydetails JSF_GET_api_collections +/// @copydetails JSF_get_api_collections /// /// @subsection HttpCollectionChanging Modifying a Collection ///////////////////////////////////////////////////////////// /// /// @anchor HttpCollectionLoad -/// @copydetails JSF_PUT_api_collection_load +/// @copydetails JSF_put_api_collection_load /// /// @anchor HttpCollectionUnload -/// @copydetails JSF_PUT_api_collection_unload +/// @copydetails JSF_put_api_collection_unload /// /// @anchor HttpCollectionProperties -/// @copydetails JSF_PUT_api_collection_properties +/// @copydetails JSF_put_api_collection_properties /// /// @anchor HttpCollectionRename -/// @copydetails JSF_PUT_api_collection_rename +/// @copydetails JSF_put_api_collection_rename //////////////////////////////////////////////////////////////////////////////// // Local Variables: diff --git a/arangod/Documentation/module-fs.dox b/arangod/Documentation/module-fs.dox deleted file mode 100644 index e61a9dc2b8..0000000000 --- a/arangod/Documentation/module-fs.dox +++ /dev/null @@ -1,53 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -/// @brief module "fs" -/// -/// @file -/// -/// DISCLAIMER -/// -/// Copyright 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 Dr. Frank Celler -/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -/// @page JSModuleFsTOC -/// -///
    -///
  1. @ref JSModuleFsExists "fs.exists"
  2. -///
-//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -/// @page JSModuleFs Module "fs" -/// -/// The implementation follows the CommonJS specification -/// Filesystem/A/0. -/// -///
-/// @copydoc JSModuleFsTOC -///
-/// -/// @anchor JSModuleFsExists -/// @copydetails JS_Exists -//////////////////////////////////////////////////////////////////////////////// - -// Local Variables: -// mode: outline-minor -// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @\\}\\)" -// End: diff --git a/arangod/Documentation/shell-document.dox b/arangod/Documentation/shell-document.dox deleted file mode 100644 index 9357d51d04..0000000000 --- a/arangod/Documentation/shell-document.dox +++ /dev/null @@ -1,186 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -/// @brief arango shell -/// -/// @file -/// -/// DISCLAIMER -/// -/// Copyright 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 Dr. Frank Celler -/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany -//////////////////////////////////////////////////////////////////////////////// - -// ----------------------------------------------------------------------------- -// --SECTION-- HANDLING DOCUMENTS -// ----------------------------------------------------------------------------- - -//////////////////////////////////////////////////////////////////////////////// -/// @page ShellDocumentTOC -/// -/// -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -/// @page ShellDocumentCallsTOC -/// -/// -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -/// @page ShellDocument Handling Documents -/// -/// @NAVIGATE_ShellDocument -/// -/// This is an introduction to ArangoDB's interface for documents and how handle -/// documents from the JavaScript shell @LIT{arangosh}. For other languages see -/// the corresponding language API. -/// -/// @EMBEDTOC{ShellDocumentTOC} -/// -/// @section ShellDocumentIntro Documents, Identifiers, Handles -/////////////////////////////////////////////////////////////// -/// -/// @copydoc GlossaryDocument -/// -/// For example: -/// -/// @verbinclude document1 -/// -/// All documents contain special attributes: the document handle in @LIT{_id}, -/// the document's unique key in @LIT{_key} and and the etag aka document -/// revision in @LIT{_rev}. The value of the @LIT{_key} attribute can be -/// specified by the user when creating a document. -/// @LIT{_id} and @LIT{_key} values are immutable once the document has been -/// created. The @LIT{_rev} value is maintained by ArangoDB autonomously. -/// -/// @copydoc GlossaryDocumentHandle -/// -/// @copydoc GlossaryDocumentKey -/// -/// @copydoc GlossaryDocumentRevision -/// -/// @copydoc GlossaryDocumentEtag -/// -/// @section ShellDocumentResource Address and ETag of an Document -////////////////////////////////////////////////////////////////// -/// -/// All documents in ArangoDB have a document handle. This handle uniquely -/// defines a document and is managed by ArangoDB. The interface allows -/// you to access the documents of a collection as: -/// -/// @LIT{db.@FA{collection}.documet(@FA{document-handle})} -/// -/// For example: Assume that the document handle, which is stored in -/// the @LIT{_id} attribute of the document, is @LIT{demo/362549736} -/// and the document lives in a collection named @FA{demo}, then -/// that document can be accessed as: -/// -/// @LIT{db.demo.document("demo/362549736")} -/// -/// Because the document handle is unique within the database, you -/// can leave out the @FA{collection} and use the shortcut: -/// -/// @LIT{db._document("demo/362549736")} -/// -/// Each document also has a document revision or etag with is returned -/// in the @LIT{_rev} attribute when requesting a document. The document's -/// key is returned in the @LIT{_key} attribute. -/// -/// @CLEARPAGE -/// @section ShellDocumentShell Working with Documents -////////////////////////////////////////////////////// -/// -/// @subsection ShellDocumentCollectionMethods Collection Methods -///////////////////////////////////////////////////////////////// -/// -/// @anchor ShellDocumentRead -/// @copydetails JS_DocumentVocbaseCol -/// -/// @CLEARPAGE -/// @anchor ShellDocumentCreate -/// @copydetails JS_SaveVocbaseCol -/// -/// @CLEARPAGE -/// @anchor ShellDocumentReplace -/// @copydetails JS_ReplaceVocbaseCol -/// -/// @CLEARPAGE -/// @anchor ShellDocumentUpdate -/// @copydetails JS_UpdateVocbaseCol -/// -/// @CLEARPAGE -/// @anchor ShellDocumentDelete -/// @copydetails JS_RemoveVocbaseCol -/// -/// @CLEARPAGE -/// @subsection ShellDocumentDatabaseMethods Database Methods -///////////////////////////////////////////////////////////// -/// -/// @anchor ShellDocumentDbRead -/// @copydetails JS_DocumentVocbase -/// -/// @CLEARPAGE -/// @anchor ShellDocumentDbReplace -/// @copydetails JS_ReplaceVocbase -/// -/// @CLEARPAGE -/// @anchor ShellDocumentDbUpdate -/// @copydetails JS_UpdateVocbase -/// -/// @CLEARPAGE -/// @anchor ShellDocumentDbDelete -/// @copydetails JS_RemoveVocbase -//////////////////////////////////////////////////////////////////////////////// - -// ----------------------------------------------------------------------------- -// --SECTION-- END-OF-FILE -// ----------------------------------------------------------------------------- - -// Local Variables: -// mode: c++ -// mode: outline-minor -// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @\\}\\)" -// End: diff --git a/arangod/Documentation/simple-queries.dox b/arangod/Documentation/simple-queries.dox index ec6b954704..0daacccff3 100644 --- a/arangod/Documentation/simple-queries.dox +++ b/arangod/Documentation/simple-queries.dox @@ -1,5 +1,5 @@ //////////////////////////////////////////////////////////////////////////////// -/// @brief installation guide +/// @brief simple queries /// /// @file /// diff --git a/arangod/RestHandler/RestDocumentHandler.cpp b/arangod/RestHandler/RestDocumentHandler.cpp index 4c957838d6..f692dc1807 100644 --- a/arangod/RestHandler/RestDocumentHandler.cpp +++ b/arangod/RestHandler/RestDocumentHandler.cpp @@ -280,7 +280,7 @@ bool RestDocumentHandler::createDocument () { } // find and load collection given by name or identifier - SelfContainedWriteTransaction trx(_vocbase, collection, getCollectionType(), create); + SelfContainedWriteTransaction trx(_vocbase, collection, create, getCollectionType()); // ............................................................................. // inside write transaction @@ -402,7 +402,7 @@ bool RestDocumentHandler::readSingleDocument (bool generateBody) { string key = suffix[1]; // find and load collection given by name or identifier - SingleCollectionReadOnlyTransaction > trx(_vocbase, collection, getCollectionType()); + SingleCollectionReadOnlyTransaction > trx(_vocbase, collection); // ............................................................................. // inside read transaction @@ -486,7 +486,7 @@ bool RestDocumentHandler::readAllDocuments () { string collection = _request->value("collection", found); // find and load collection given by name or identifier - SingleCollectionReadOnlyTransaction > trx(_vocbase, collection, getCollectionType()); + SingleCollectionReadOnlyTransaction > trx(_vocbase, collection); vector ids; @@ -757,7 +757,7 @@ bool RestDocumentHandler::modifyDocument (bool isPatch) { TRI_doc_update_policy_e policy = extractUpdatePolicy(); // find and load collection given by name or identifier - SelfContainedWriteTransaction trx(_vocbase, collection, getCollectionType(), false); + SelfContainedWriteTransaction trx(_vocbase, collection); TRI_doc_mptr_t* document = 0; TRI_voc_rid_t rid = 0; @@ -918,7 +918,7 @@ bool RestDocumentHandler::deleteDocument () { } // find and load collection given by name or identifier - SelfContainedWriteTransaction trx(_vocbase, collection, getCollectionType(), false); + SelfContainedWriteTransaction trx(_vocbase, collection); TRI_voc_rid_t rid = 0; // ............................................................................. diff --git a/arangod/RestHandler/RestEdgeHandler.cpp b/arangod/RestHandler/RestEdgeHandler.cpp index 8a8c3045d8..406db4e1ed 100644 --- a/arangod/RestHandler/RestEdgeHandler.cpp +++ b/arangod/RestHandler/RestEdgeHandler.cpp @@ -163,7 +163,7 @@ bool RestEdgeHandler::createDocument () { } // find and load collection given by name or identifier - SelfContainedWriteTransaction trx(_vocbase, collection, getCollectionType(), create); + SelfContainedWriteTransaction trx(_vocbase, collection, create, getCollectionType()); // ............................................................................. // inside write transaction diff --git a/arangod/RestHandler/RestImportHandler.cpp b/arangod/RestHandler/RestImportHandler.cpp index 0ed02fae6f..599a510ff8 100644 --- a/arangod/RestHandler/RestImportHandler.cpp +++ b/arangod/RestHandler/RestImportHandler.cpp @@ -205,7 +205,7 @@ bool RestImportHandler::createByDocumentsLines () { bool create = found ? StringUtils::boolean(valueStr) : false; // find and load collection given by name or identifier - ImportTransaction > trx(_vocbase, collection, TRI_COL_TYPE_DOCUMENT, create); + ImportTransaction > trx(_vocbase, collection, create, TRI_COL_TYPE_DOCUMENT); // ............................................................................. // inside write transaction @@ -350,7 +350,7 @@ bool RestImportHandler::createByDocumentsList () { bool create = found ? StringUtils::boolean(valueStr) : false; // find and load collection given by name or identifier - ImportTransaction > trx(_vocbase, collection, TRI_COL_TYPE_DOCUMENT, create); + ImportTransaction > trx(_vocbase, collection, create, TRI_COL_TYPE_DOCUMENT); // ............................................................................. // inside write transaction @@ -498,7 +498,7 @@ bool RestImportHandler::createByKeyValueList () { } // find and load collection given by name or identifier - ImportTransaction > trx(_vocbase, collection, TRI_COL_TYPE_DOCUMENT, create); + ImportTransaction > trx(_vocbase, collection, create, TRI_COL_TYPE_DOCUMENT); // ............................................................................. // inside write transaction diff --git a/arangod/RestServer/ArangoServer.cpp b/arangod/RestServer/ArangoServer.cpp index 6e415b2a97..87fabf6eb2 100644 --- a/arangod/RestServer/ArangoServer.cpp +++ b/arangod/RestServer/ArangoServer.cpp @@ -953,7 +953,7 @@ mrb_value MR_ArangoDatabase_Collection (mrb_state* mrb, mrb_value self) { // looking at "mruby.h" I assume that is the way to unwrap the pointer rdata = (struct RData*) mrb_object(self); vocbase = (TRI_vocbase_t*) rdata->data; - collection = TRI_FindCollectionByNameVocBase(vocbase, name, false); + collection = TRI_LookupCollectionByNameVocBase(vocbase, name); if (collection == NULL) { printf("unknown collection (TODO raise error)\n"); diff --git a/arangod/Utils/AqlTransaction.h b/arangod/Utils/AqlTransaction.h index 5906938d56..7aeadde8c8 100644 --- a/arangod/Utils/AqlTransaction.h +++ b/arangod/Utils/AqlTransaction.h @@ -64,7 +64,7 @@ namespace triagens { if (_trx != 0) { if (_trx->_status == TRI_TRANSACTION_RUNNING) { // auto abort - abort(); + this->abort(); } TRI_FreeTransaction(_trx); diff --git a/arangod/Utils/ImportTransaction.h b/arangod/Utils/ImportTransaction.h index ed29cca845..de72b83d87 100644 --- a/arangod/Utils/ImportTransaction.h +++ b/arangod/Utils/ImportTransaction.h @@ -62,10 +62,10 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// ImportTransaction (TRI_vocbase_t* const vocbase, - const string& collectionName, - const TRI_col_type_e collectionType, - const bool createCollection) : - SingleCollectionWriteTransaction(vocbase, collectionName, collectionType, createCollection, "ImportTransaction") { + const string& name, + const bool create, + const TRI_col_type_e createType) : + SingleCollectionWriteTransaction(vocbase, name, create, createType) { } //////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/Utils/SelfContainedWriteTransaction.h b/arangod/Utils/SelfContainedWriteTransaction.h index c7e0ccd1a3..34c6b7497b 100644 --- a/arangod/Utils/SelfContainedWriteTransaction.h +++ b/arangod/Utils/SelfContainedWriteTransaction.h @@ -64,10 +64,35 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// SelfContainedWriteTransaction (TRI_vocbase_t* const vocbase, - const string& collectionName, - const TRI_col_type_e collectionType, - const bool createCollection) : - SingleCollectionWriteTransaction, 1>(vocbase, collectionName, collectionType, createCollection, "SelfContainedWriteTransaction") { + const string& name) : + SingleCollectionWriteTransaction, 1>(vocbase, name) { + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief create the transaction, using a collection object +/// +/// A self contained write transaction operates on a single collection and may +/// execute at most one write operation +//////////////////////////////////////////////////////////////////////////////// + + SelfContainedWriteTransaction (TRI_vocbase_t* const vocbase, + const string& name, + const TRI_col_type_e createType) : + SingleCollectionWriteTransaction, 1>(vocbase, name, createType) { + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief create the transaction, using a collection object +/// +/// A self contained write transaction operates on a single collection and may +/// execute at most one write operation +//////////////////////////////////////////////////////////////////////////////// + + SelfContainedWriteTransaction (TRI_vocbase_t* const vocbase, + const string& name, + const bool create, + const TRI_col_type_e createType) : + SingleCollectionWriteTransaction, 1>(vocbase, name, create, createType) { } //////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/Utils/SingleCollectionReadOnlyTransaction.h b/arangod/Utils/SingleCollectionReadOnlyTransaction.h index d0c368da01..c37b2dc40e 100644 --- a/arangod/Utils/SingleCollectionReadOnlyTransaction.h +++ b/arangod/Utils/SingleCollectionReadOnlyTransaction.h @@ -62,9 +62,8 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// SingleCollectionReadOnlyTransaction (TRI_vocbase_t* const vocbase, - const string& collectionName, - const TRI_col_type_e collectionType) : - SingleCollectionTransaction(vocbase, collectionName, collectionType, false, "SingleCollectionReadOnlyTransaction", TRI_TRANSACTION_READ) { + const string& name) : + SingleCollectionTransaction(vocbase, name, TRI_TRANSACTION_READ) { } //////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/Utils/SingleCollectionTransaction.h b/arangod/Utils/SingleCollectionTransaction.h index 70e011307b..fdad5e2d2c 100644 --- a/arangod/Utils/SingleCollectionTransaction.h +++ b/arangod/Utils/SingleCollectionTransaction.h @@ -71,16 +71,29 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// SingleCollectionTransaction (TRI_vocbase_t* const vocbase, - const string& collectionName, - const TRI_col_type_e collectionType, - const bool createCollection, - const string& trxName, - const TRI_transaction_type_e type) : - Transaction(vocbase, trxName), - _collectionName(collectionName), - _collectionType(collectionType), - _createCollection(createCollection), - _type(type), + const string& name, + const TRI_transaction_type_e accessType) : + Transaction(vocbase, new TransactionCollectionsList(vocbase, name, accessType)), + _name(name), + _collection(0) { + } + + SingleCollectionTransaction (TRI_vocbase_t* const vocbase, + const string& name, + const TRI_transaction_type_e accessType, + const TRI_col_type_e createType) : + Transaction(vocbase, new TransactionCollectionsList(vocbase, name, accessType, createType)), + _name(name), + _collection(0) { + } + + SingleCollectionTransaction (TRI_vocbase_t* const vocbase, + const string& name, + const TRI_transaction_type_e accessType, + const bool create, + const TRI_col_type_e createType) : + Transaction(vocbase, new TransactionCollectionsList(vocbase, name, accessType, create, createType)), + _name(name), _collection(0) { } @@ -89,103 +102,6 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// virtual ~SingleCollectionTransaction () { - if (! this->isEmbedded()) { - if (this->_trx != 0) { - if (this->status() == TRI_TRANSACTION_RUNNING) { - // auto abort - this->abort(); - } - } - - releaseCollection(); - } - } - -//////////////////////////////////////////////////////////////////////////////// -/// @} -//////////////////////////////////////////////////////////////////////////////// - -// ----------------------------------------------------------------------------- -// --SECTION-- virtual protected functions -// ----------------------------------------------------------------------------- - -//////////////////////////////////////////////////////////////////////////////// -/// @addtogroup ArangoDB -/// @{ -//////////////////////////////////////////////////////////////////////////////// - - protected: - -//////////////////////////////////////////////////////////////////////////////// -/// @brief use the underlying collection -//////////////////////////////////////////////////////////////////////////////// - - int useCollections () { - if (_collection != 0) { - // we already used this collectino, nothing to do - return TRI_ERROR_NO_ERROR; - } - - if (_collectionName.empty()) { - // name is empty. cannot open the collection - return TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND; - } - - // open or create the collection - if (isdigit(_collectionName[0])) { - TRI_voc_cid_t id = triagens::basics::StringUtils::uint64(_collectionName); - - _collection = TRI_LookupCollectionByIdVocBase(this->_vocbase, id); - } - else { - if (_collectionType == TRI_COL_TYPE_DOCUMENT) { - _collection = TRI_FindDocumentCollectionByNameVocBase(this->_vocbase, _collectionName.c_str(), _createCollection); - } - else if (_collectionType == TRI_COL_TYPE_EDGE) { - _collection = TRI_FindEdgeCollectionByNameVocBase(this->_vocbase, _collectionName.c_str(), _createCollection); - } - } - - if (_collection == 0) { - // collection not found - return TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND; - } - - int res = TRI_UseCollectionVocBase(this->_vocbase, const_cast(_collection)); - - if (res != TRI_ERROR_NO_ERROR) { - _collection = 0; - - return res; - } - - LOGGER_TRACE << "using collection " << _collectionName; - assert(_collection->_collection != 0); - - return TRI_ERROR_NO_ERROR; - } - -//////////////////////////////////////////////////////////////////////////////// -/// @brief add all collections to the transaction (only one) -//////////////////////////////////////////////////////////////////////////////// - - int addCollections () { - if (this->isEmbedded()) { - assert(_collection == 0); - - _collection = TRI_CheckCollectionTransaction(this->_trx, _collectionName.c_str(), type()); - if (_collection == 0) { - return TRI_ERROR_TRANSACTION_UNREGISTERED_COLLECTION; - } - - return TRI_ERROR_NO_ERROR; - } - else { - assert(_collection != 0); - - int res = TRI_AddCollectionTransaction(this->_trx, _collectionName.c_str(), type(), _collection); - return res; - } } //////////////////////////////////////////////////////////////////////////////// @@ -207,8 +123,8 @@ namespace triagens { /// @brief return the name of the underlying collection //////////////////////////////////////////////////////////////////////////////// - inline string collectionName () { - return _collectionName; + const string collectionName () const { + return _name; } //////////////////////////////////////////////////////////////////////////////// @@ -216,6 +132,12 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// inline TRI_primary_collection_t* primaryCollection () { + if (_collection == 0) { + const vector collections = this->_collections->getCollections(); + _collection = TRI_GetCollectionTransaction(this->_trx, collections[0]->getName().c_str()); + } + + assert(_collection != 0); assert(_collection->_collection != 0); return _collection->_collection; } @@ -240,7 +162,11 @@ namespace triagens { /// @brief get the underlying collection's id //////////////////////////////////////////////////////////////////////////////// - inline TRI_voc_cid_t cid () const { + inline TRI_voc_cid_t cid () { + if (_collection == 0) { + _collection = TRI_GetCollectionTransaction(this->_trx, this->collectionName().c_str()); + } + assert(_collection != 0); return _collection->_cid; } @@ -283,43 +209,6 @@ namespace triagens { /// @} //////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -/// @addtogroup ArangoDB -/// @{ -//////////////////////////////////////////////////////////////////////////////// - -// ----------------------------------------------------------------------------- -// --SECTION-- private functions -// ----------------------------------------------------------------------------- - - private: - -//////////////////////////////////////////////////////////////////////////////// -/// @brief release the underlying collection -//////////////////////////////////////////////////////////////////////////////// - - int releaseCollection () { - // unuse underlying collection - if (_collection != 0) { - TRI_ReleaseCollectionVocBase(this->_vocbase, _collection); - _collection = 0; - } - - return TRI_ERROR_NO_ERROR; - } - -//////////////////////////////////////////////////////////////////////////////// -/// @brief get the transaction type -//////////////////////////////////////////////////////////////////////////////// - - inline TRI_transaction_type_e type () const { - return _type; - } - -//////////////////////////////////////////////////////////////////////////////// -/// @} -//////////////////////////////////////////////////////////////////////////////// - // ----------------------------------------------------------------------------- // --SECTION-- private variables // ----------------------------------------------------------------------------- @@ -332,28 +221,10 @@ namespace triagens { private: //////////////////////////////////////////////////////////////////////////////// -/// @brief name of the collection that is worked on +/// @brief name of the collection used //////////////////////////////////////////////////////////////////////////////// - const string _collectionName; - -//////////////////////////////////////////////////////////////////////////////// -/// @brief the type of the collection -//////////////////////////////////////////////////////////////////////////////// - - const TRI_col_type_e _collectionType; - -//////////////////////////////////////////////////////////////////////////////// -/// @brief whether or not to create the collection -//////////////////////////////////////////////////////////////////////////////// - - const bool _createCollection; - -//////////////////////////////////////////////////////////////////////////////// -/// @brief transaction type (READ | WRITE) -//////////////////////////////////////////////////////////////////////////////// - - const TRI_transaction_type_e _type; + string _name; //////////////////////////////////////////////////////////////////////////////// /// @brief data structure for the single collection used diff --git a/arangod/Utils/SingleCollectionWriteTransaction.h b/arangod/Utils/SingleCollectionWriteTransaction.h index 4b22430fad..e0ae41bd39 100644 --- a/arangod/Utils/SingleCollectionWriteTransaction.h +++ b/arangod/Utils/SingleCollectionWriteTransaction.h @@ -70,11 +70,33 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// SingleCollectionWriteTransaction (TRI_vocbase_t* const vocbase, - const string& collectionName, - const TRI_col_type_e collectionType, - const bool createCollection, - const string& trxName) : - SingleCollectionTransaction(vocbase, collectionName, collectionType, createCollection, trxName, TRI_TRANSACTION_WRITE), + const string& name) : + SingleCollectionTransaction(vocbase, name, TRI_TRANSACTION_WRITE), + _numWrites(0), + _synchronous(false) { + + if (N == 1) { + this->addHint(TRI_TRANSACTION_HINT_SINGLE_OPERATION); + } + } + + SingleCollectionWriteTransaction (TRI_vocbase_t* const vocbase, + const string& name, + const TRI_col_type_e createType) : + SingleCollectionTransaction(vocbase, name, TRI_TRANSACTION_WRITE, createType), + _numWrites(0), + _synchronous(false) { + + if (N == 1) { + this->addHint(TRI_TRANSACTION_HINT_SINGLE_OPERATION); + } + } + + SingleCollectionWriteTransaction (TRI_vocbase_t* const vocbase, + const string& name, + const bool create, + const TRI_col_type_e createType) : + SingleCollectionTransaction(vocbase, name, TRI_TRANSACTION_WRITE, create, createType), _numWrites(0), _synchronous(false) { diff --git a/arangod/Utils/Transaction.h b/arangod/Utils/Transaction.h index 1996b2ebe2..a350813bc6 100644 --- a/arangod/Utils/Transaction.h +++ b/arangod/Utils/Transaction.h @@ -35,13 +35,24 @@ #include "Logger/Logger.h" #include "Utils/CollectionReadLock.h" #include "Utils/CollectionWriteLock.h" +#include "Utils/TransactionCollectionsList.h" +#include "Utils/TransactionCollection.h" + +#if TRI_ENABLE_TRX +//#define TRX_LOG LOGGER_INFO << __FUNCTION__ << ":" << __LINE__ << " " +#define TRX_LOG if (false) std::cout +#else +#define TRX_LOG if (false) std::cout +#endif + namespace triagens { namespace arango { - + // ----------------------------------------------------------------------------- // --SECTION-- class Transaction // ----------------------------------------------------------------------------- + template class Transaction : public T { @@ -79,22 +90,27 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// Transaction (TRI_vocbase_t* const vocbase, - const string& trxName) : + TransactionCollectionsList* collections) : T(), _vocbase(vocbase), - _trxName(trxName), + _collections(collections), _hints(0), _setupError(TRI_ERROR_NO_ERROR) { - assert(_vocbase != 0); - int res = createTransaction(); - if (res != TRI_ERROR_NO_ERROR) { - this->_setupError = res; + assert(_vocbase != 0); + + TRX_LOG << "creating transaction"; + + int res = _collections->getError(); + if (res == TRI_ERROR_NO_ERROR) { + res = createTransaction(); } -#ifdef TRI_ENABLE_TRX -// LOGGER_INFO << "created transaction " << this->_trxName; -#endif + if (res != TRI_ERROR_NO_ERROR) { + // setting up the transaction failed + TRX_LOG << "creating transaction failed"; + this->_setupError = res; + } } //////////////////////////////////////////////////////////////////////////////// @@ -102,11 +118,17 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// virtual ~Transaction () { - freeTransaction(); - -#ifdef TRI_ENABLE_TRX -// LOGGER_INFO << "destroyed transaction " << this->_trxName; -#endif + TRX_LOG << "destroying transaction"; + + if (this->_trx != 0 && ! this->isEmbedded()) { + if (this->status() == TRI_TRANSACTION_RUNNING) { + // auto abort + this->abort(); + } + freeTransaction(); + } + + delete _collections; } //////////////////////////////////////////////////////////////////////////////// @@ -129,6 +151,7 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// int begin () { + TRX_LOG << "beginning transaction"; if (this->_setupError != TRI_ERROR_NO_ERROR) { return this->_setupError; } @@ -140,25 +163,23 @@ namespace triagens { int res; if (this->isEmbedded()) { - res = addCollections(); + res = this->checkCollections(); return res; } + // ! this->isEmbedded() + if (status() != TRI_TRANSACTION_CREATED) { return TRI_ERROR_TRANSACTION_INVALID_STATE; } // register usage of the underlying collections - res = useCollections(); - if (res != TRI_ERROR_NO_ERROR) { - return res; - } - - res = addCollections(); + res = this->addCollections(); if (res != TRI_ERROR_NO_ERROR) { return res; } + TRX_LOG << "calling transaction start"; return TRI_StartTransaction(this->_trx, _hints); } @@ -167,21 +188,28 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// int commit () { - if (this->_trx == 0 || status() != TRI_TRANSACTION_RUNNING) { - // not created or not running + TRX_LOG << "committing transaction"; + + if (this->_trx == 0 || this->status() != TRI_TRANSACTION_RUNNING) { + // transaction not created or not running return TRI_ERROR_TRANSACTION_INVALID_STATE; } if (this->isEmbedded()) { + // return instantly if the transaction is embedded return TRI_ERROR_NO_ERROR; } int res; - + if (this->_trx->_type == TRI_TRANSACTION_READ) { + // a read transaction just finishes + TRX_LOG << "commit - finishing read transaction"; res = TRI_FinishTransaction(this->_trx); } else { + // a write transaction commits + TRX_LOG << "commit - committing write transaction"; res = TRI_CommitTransaction(this->_trx); } @@ -193,12 +221,13 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// int abort () { + TRX_LOG << "aborting transaction"; if (this->_trx == 0) { // transaction not created return TRI_ERROR_TRANSACTION_INVALID_STATE; } - if (status() != TRI_TRANSACTION_RUNNING) { + if (this->status() != TRI_TRANSACTION_RUNNING) { return TRI_ERROR_TRANSACTION_INVALID_STATE; } @@ -217,14 +246,14 @@ namespace triagens { return TRI_ERROR_TRANSACTION_INVALID_STATE; } - if (status() != TRI_TRANSACTION_RUNNING) { + if (this->status() != TRI_TRANSACTION_RUNNING) { return TRI_ERROR_TRANSACTION_INVALID_STATE; } int res; if (errorNumber == TRI_ERROR_NO_ERROR) { // there was no previous error, so we'll commit - res = commit(); + res = this->commit(); } else { // there was a previous error, so we'll abort @@ -236,14 +265,6 @@ namespace triagens { return res; } -//////////////////////////////////////////////////////////////////////////////// -/// @brief return the name of the transaction -//////////////////////////////////////////////////////////////////////////////// - - inline string name () const { - return this->_trxName; - } - //////////////////////////////////////////////////////////////////////////////// /// @brief get the "vocbase" //////////////////////////////////////////////////////////////////////////////// @@ -574,33 +595,6 @@ namespace triagens { /// @} //////////////////////////////////////////////////////////////////////////////// -// ----------------------------------------------------------------------------- -// --SECTION-- virtual protected methods -// ----------------------------------------------------------------------------- - -//////////////////////////////////////////////////////////////////////////////// -/// @addtogroup ArangoDB -/// @{ -//////////////////////////////////////////////////////////////////////////////// - - protected: - -//////////////////////////////////////////////////////////////////////////////// -/// @brief use all collection -//////////////////////////////////////////////////////////////////////////////// - - virtual int useCollections () = 0; - -//////////////////////////////////////////////////////////////////////////////// -/// @brief add all collections to the transaction -//////////////////////////////////////////////////////////////////////////////// - - virtual int addCollections () = 0; - -//////////////////////////////////////////////////////////////////////////////// -/// @} -//////////////////////////////////////////////////////////////////////////////// - // ----------------------------------------------------------------------------- // --SECTION-- private methods // ----------------------------------------------------------------------------- @@ -612,6 +606,64 @@ namespace triagens { private: +//////////////////////////////////////////////////////////////////////////////// +/// @brief check all collections to the transaction +/// +/// this method is called in case the transaction is embedded. its purpose is +/// to validate if all collections have been previously registered in the +/// current transaction +//////////////////////////////////////////////////////////////////////////////// + + int checkCollections () { + assert(this->isEmbedded()); + + TRX_LOG << "checking collections"; + + const vector& collections = _collections->getCollections(); + + for (size_t i = 0; i < collections.size(); ++i) { + TransactionCollection* c = collections[i]; + TRI_vocbase_col_t* collection = TRI_CheckCollectionTransaction(this->_trx, c->getName().c_str(), c->getAccessType()); + + if (collection == 0) { + return TRI_ERROR_TRANSACTION_UNREGISTERED_COLLECTION; + } + } + + return TRI_ERROR_NO_ERROR; + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief add all collections to the transaction +/// +/// this method is called in case the transaction is not embedded. its purpose is +/// to validate if all collections have been previously registered in the +/// current transaction +//////////////////////////////////////////////////////////////////////////////// + + int addCollections () { + assert(! this->isEmbedded()); + + TRX_LOG << "adding collections"; + + const vector& collections = _collections->getCollections(); + + for (size_t i = 0; i < collections.size(); ++i) { + TransactionCollection* c = collections[i]; + + TRX_LOG << "adding collection " << c->getName(); + int res = TRI_AddCollectionTransaction(this->_trx, c->getName().c_str(), c->getAccessType()); + + if (res != TRI_ERROR_NO_ERROR) { + return res; + } + } + + TRX_LOG << "all collections added"; + + return TRI_ERROR_NO_ERROR; + } + //////////////////////////////////////////////////////////////////////////////// /// @brief create transaction //////////////////////////////////////////////////////////////////////////////// @@ -622,12 +674,20 @@ namespace triagens { return TRI_ERROR_TRANSACTION_NESTED; } + TRX_LOG << "creating embedded transaction"; this->_trx = this->getParent(); + if (this->_trx == 0) { + TRX_LOG << "creating embedded transaction failed"; + return TRI_ERROR_TRANSACTION_INVALID_STATE; + } + return TRI_ERROR_NO_ERROR; } + TRX_LOG << "creating standalone transaction"; this->_trx = TRI_CreateTransaction(_vocbase->_transactionContext, TRI_TRANSACTION_READ_REPEATABLE); + if (this->_trx == 0) { return TRI_ERROR_OUT_OF_MEMORY; } @@ -642,9 +702,9 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// int freeTransaction () { - if (this->isEmbedded()) { - return TRI_ERROR_NO_ERROR; - } + assert(! this->isEmbedded()); + + TRX_LOG << "freeing standalone transaction"; if (this->_trx != 0) { this->unregisterTransaction(); @@ -677,6 +737,12 @@ namespace triagens { TRI_vocbase_t* const _vocbase; +//////////////////////////////////////////////////////////////////////////////// +/// @brief the collections participating in the transaction +//////////////////////////////////////////////////////////////////////////////// + + TransactionCollectionsList* _collections; + //////////////////////////////////////////////////////////////////////////////// /// @} //////////////////////////////////////////////////////////////////////////////// @@ -692,12 +758,6 @@ namespace triagens { private: -//////////////////////////////////////////////////////////////////////////////// -/// @brief transaction name -//////////////////////////////////////////////////////////////////////////////// - - string _trxName; - //////////////////////////////////////////////////////////////////////////////// /// @brief transaction hints //////////////////////////////////////////////////////////////////////////////// @@ -709,7 +769,7 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// int _setupError; - + //////////////////////////////////////////////////////////////////////////////// /// @} //////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/Utils/TransactionCollection.h b/arangod/Utils/TransactionCollection.h new file mode 100644 index 0000000000..938bfc722a --- /dev/null +++ b/arangod/Utils/TransactionCollection.h @@ -0,0 +1,101 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief transaction collection wrapper +/// +/// @file +/// +/// DISCLAIMER +/// +/// Copyright 2004-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 2011-2012, triAGENS GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +#ifndef TRIAGENS_UTILS_TRANSACTION_COLLECTION_H +#define TRIAGENS_UTILS_TRANSACTION_COLLECTION_H 1 + +#include "Basics/Common.h" + +#include "VocBase/collection.h" +#include "VocBase/transaction.h" + +namespace triagens { + namespace arango { + + class TransactionCollection { + + private: + TransactionCollection (const TransactionCollection&); + TransactionCollection& operator= (const TransactionCollection&); + + public: + TransactionCollection (const string& name, TRI_transaction_type_e accessType) : + _name(name), + _accessType(accessType), + _createType(TRI_COL_TYPE_DOCUMENT), + _create(false) { + } + + TransactionCollection (const string& name, TRI_col_type_e createType) : + _name(name), + _accessType(TRI_TRANSACTION_WRITE), + _createType(TRI_COL_TYPE_DOCUMENT), + _create(true) { + } + + ~TransactionCollection () { + } + + inline const string getName () const { + return _name; + } + + inline TRI_transaction_type_e getAccessType () const { + return _accessType; + } + + inline void setAccessType (TRI_transaction_type_e accessType) { + _accessType = accessType; + } + + inline bool getCreateFlag () const { + return _create; + } + + inline TRI_col_type_e getCreateType () const { + return _createType; + } + + private: + string _name; + + TRI_transaction_type_e _accessType; + + TRI_col_type_e _createType; + + bool _create; + }; + + } +} + +#endif + +// Local Variables: +// mode: outline-minor +// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}\\)" +// End: diff --git a/arangod/Utils/TransactionCollectionsList.h b/arangod/Utils/TransactionCollectionsList.h new file mode 100644 index 0000000000..78e7f66615 --- /dev/null +++ b/arangod/Utils/TransactionCollectionsList.h @@ -0,0 +1,195 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief transaction collections list +/// +/// @file +/// +/// DISCLAIMER +/// +/// Copyright 2004-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 2011-2012, triAGENS GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +#ifndef TRIAGENS_UTILS_TRANSACTION_COLLECTION_LIST_H +#define TRIAGENS_UTILS_TRANSACTION_COLLECTION_LIST_H 1 + +#include "Basics/Common.h" + +#include "VocBase/collection.h" +#include "VocBase/transaction.h" +#include "VocBase/vocbase.h" + +#include "Utils/TransactionCollection.h" + + +namespace triagens { + namespace arango { + + class TransactionCollectionsList { + typedef map ListType; + + private: + TransactionCollectionsList& operator= (const TransactionCollectionsList&); + TransactionCollectionsList (const TransactionCollectionsList&); + + public: + TransactionCollectionsList () : + _collections() { + } + + TransactionCollectionsList (TRI_vocbase_t* const vocbase, + const string& name, + TRI_transaction_type_e accessType) : + _vocbase(vocbase), + _collections(), + _error(TRI_ERROR_NO_ERROR) { + addCollection(name, accessType, false); + } + + TransactionCollectionsList (TRI_vocbase_t* const vocbase, + const string& name, + TRI_transaction_type_e accessType, + const TRI_col_type_e createType) : + _vocbase(vocbase), + _collections(), + _error(TRI_ERROR_NO_ERROR) { + addCollection(name, accessType, true, createType); + } + + TransactionCollectionsList (TRI_vocbase_t* const vocbase, + const string& name, + TRI_transaction_type_e accessType, + const bool create, + const TRI_col_type_e createType) : + _vocbase(vocbase), + _collections(), + _error(TRI_ERROR_NO_ERROR) { + addCollection(name, accessType, create, createType); + } + + TransactionCollectionsList (TRI_vocbase_t* const vocbase, + const vector& readCollections, + const vector& writeCollections) : + _vocbase(vocbase), + _collections() { + for (size_t i = 0; i < readCollections.size(); ++i) { + addCollection(readCollections[i], TRI_TRANSACTION_READ, false); + } + + for (size_t i = 0; i < writeCollections.size(); ++i) { + addCollection(writeCollections[i], TRI_TRANSACTION_WRITE, false); + } + } + + ~TransactionCollectionsList () { + ListType::iterator it; + + for (it = _collections.begin(); it != _collections.end(); ++it) { + delete (*it).second; + } + + _collections.clear(); + } + + inline int getError () const { + return _error; + } + + const vector getCollections () { + ListType::iterator it; + vector collections; + + for (it = _collections.begin(); it != _collections.end(); ++it) { + collections.push_back((*it).second); + } + + return collections; + } + + void addCollection (const string& name, + TRI_transaction_type_e type, + bool create, + TRI_col_type_e createType = TRI_COL_TYPE_DOCUMENT) { + ListType::iterator it; + string realName; + + if (name.empty()) { + _error = TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND; + return; + } + + if (isdigit(name[0])) { + // name is passed as a string with the collection id + + // look up the collection name for the id + TRI_voc_cid_t id = triagens::basics::StringUtils::uint64(name); + + char* n = TRI_GetCollectionNameByIdVocBase(_vocbase, id); + if (n == 0) { + _error = TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND; + return; + } + + realName = string(n); + TRI_Free(TRI_UNKNOWN_MEM_ZONE, n); + } + else { + // name is passed as a "real" name + realName = name; + } + + it = _collections.find(realName); + if (it != _collections.end()) { + TransactionCollection* c = (*it).second; + + if (type == TRI_TRANSACTION_WRITE && type != c->getAccessType()) { + // upgrade the type + c->setAccessType(type); + } + } + else { + + // check whether the collection exists. if not, create it + if (( create && TRI_FindCollectionByNameOrBearVocBase(_vocbase, realName.c_str(), createType) == NULL) || + (! create && TRI_LookupCollectionByNameVocBase(_vocbase, realName.c_str()) == NULL)) { + _error = TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND; + return; + } + + _collections[realName] = new TransactionCollection(realName, type); + } + } + + private: + TRI_vocbase_t* _vocbase; + + ListType _collections; + + int _error; + + }; + + } +} + +#endif + +// Local Variables: +// mode: outline-minor +// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}\\)" +// End: diff --git a/arangod/Utils/UserTransaction.h b/arangod/Utils/UserTransaction.h index 84f0cbb544..750688f83b 100644 --- a/arangod/Utils/UserTransaction.h +++ b/arangod/Utils/UserTransaction.h @@ -61,9 +61,7 @@ namespace triagens { UserTransaction (TRI_vocbase_t* const vocbase, const vector& readCollections, const vector& writeCollections) : - Transaction(vocbase, "UserTransaction"), - _readCollections(readCollections), - _writeCollections(writeCollections) { + Transaction(vocbase, new TransactionCollectionsList(vocbase, readCollections, writeCollections)) { } //////////////////////////////////////////////////////////////////////////////// @@ -71,99 +69,8 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// ~UserTransaction () { - if (this->_trx != 0) { - if (this->status() == TRI_TRANSACTION_RUNNING) { - // auto abort - this->abort(); - } - } } -//////////////////////////////////////////////////////////////////////////////// -/// @} -//////////////////////////////////////////////////////////////////////////////// - -// ----------------------------------------------------------------------------- -// --SECTION-- virtual protected functions -// ----------------------------------------------------------------------------- - -//////////////////////////////////////////////////////////////////////////////// -/// @addtogroup ArangoDB -/// @{ -//////////////////////////////////////////////////////////////////////////////// - - protected: - -//////////////////////////////////////////////////////////////////////////////// -/// @brief use all collections -/// this is a no op, as using is done when trx is started -//////////////////////////////////////////////////////////////////////////////// - - int useCollections () { - return TRI_ERROR_NO_ERROR; - } - -//////////////////////////////////////////////////////////////////////////////// -/// @brief release all collections in use -/// this is a no op, as releasing is done when trx is finished -//////////////////////////////////////////////////////////////////////////////// - - int releaseCollections () { - return TRI_ERROR_NO_ERROR; - } - -//////////////////////////////////////////////////////////////////////////////// -/// @brief add all collections to the transaction -//////////////////////////////////////////////////////////////////////////////// - - int addCollections () { - int res; - size_t i; - - for (i = 0; i < _readCollections.size(); ++i) { - res = TRI_AddCollectionTransaction(this->_trx, _readCollections[i].c_str(), TRI_TRANSACTION_READ, 0); - if (res != TRI_ERROR_NO_ERROR) { - return res; - } - } - - for (i = 0; i < _writeCollections.size(); ++i) { - res = TRI_AddCollectionTransaction(this->_trx, _writeCollections[i].c_str(), TRI_TRANSACTION_WRITE, 0); - if (res != TRI_ERROR_NO_ERROR) { - return res; - } - } - - return TRI_ERROR_NO_ERROR; - } - -//////////////////////////////////////////////////////////////////////////////// -/// @} -//////////////////////////////////////////////////////////////////////////////// - -// ----------------------------------------------------------------------------- -// --SECTION-- private variables -// ----------------------------------------------------------------------------- - -//////////////////////////////////////////////////////////////////////////////// -/// @addtogroup ArangoDB -/// @{ -//////////////////////////////////////////////////////////////////////////////// - - private: - -//////////////////////////////////////////////////////////////////////////////// -/// @brief collections that are opened in read mode -//////////////////////////////////////////////////////////////////////////////// - - vector _readCollections; - -//////////////////////////////////////////////////////////////////////////////// -/// @brief collections that are opened in write mode -//////////////////////////////////////////////////////////////////////////////// - - vector _writeCollections; - //////////////////////////////////////////////////////////////////////////////// /// @} //////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/V8Server/ApplicationV8.cpp b/arangod/V8Server/ApplicationV8.cpp index b9010dc83c..8e0e56eb94 100644 --- a/arangod/V8Server/ApplicationV8.cpp +++ b/arangod/V8Server/ApplicationV8.cpp @@ -640,15 +640,18 @@ void ApplicationV8::stop () { //////////////////////////////////////////////////////////////////////////////// bool ApplicationV8::prepareV8Instance (const size_t i) { - static char const* files[] = { "common/bootstrap/modules.js", - "common/bootstrap/monkeypatches.js", - "common/bootstrap/print.js", - "common/bootstrap/errors.js", - "server/ahuacatl.js", - "server/server.js", - "server/ArangoCollection.js", - "server/ArangoStructure.js" - }; + vector files; + + files.push_back("common/bootstrap/modules.js"); + files.push_back("common/bootstrap/module-internal.js"); + files.push_back("common/bootstrap/module-fs.js"); + files.push_back("common/bootstrap/module-console.js"); + files.push_back("common/bootstrap/monkeypatches.js"); + files.push_back("common/bootstrap/errors.js"); + files.push_back("server/ahuacatl.js"); + files.push_back("server/server.js"); + files.push_back("server/ArangoCollection.js"); + files.push_back("server/ArangoStructure.js"); LOGGER_TRACE << "initialising V8 context #" << i; @@ -687,7 +690,7 @@ bool ApplicationV8::prepareV8Instance (const size_t i) { TRI_InitV8Shell(context->_context); // load all init files - for (size_t j = 0; j < sizeof(files) / sizeof(files[0]); ++j) { + for (size_t j = 0; j < files.size(); ++j) { bool ok = _startupLoader.loadScript(context->_context, files[j]); if (! ok) { diff --git a/arangod/V8Server/v8-actions.cpp b/arangod/V8Server/v8-actions.cpp index 025faf20d1..f34d7d820a 100644 --- a/arangod/V8Server/v8-actions.cpp +++ b/arangod/V8Server/v8-actions.cpp @@ -416,7 +416,7 @@ static HttpResponse* ExecuteActionVocbase (TRI_vocbase_t* vocbase, collection = TRI_LookupCollectionByIdVocBase(vocbase, TRI_UInt64String(v.c_str())); } else { - collection = TRI_FindCollectionByNameVocBase(vocbase, v.c_str(), false); + collection = TRI_LookupCollectionByNameVocBase(vocbase, v.c_str()); } if (collection != 0) { @@ -428,7 +428,7 @@ static HttpResponse* ExecuteActionVocbase (TRI_vocbase_t* vocbase, } case TRI_ACT_COLLECTION_NAME: { - TRI_vocbase_col_t const* collection = TRI_FindCollectionByNameVocBase(vocbase, v.c_str(), false); + TRI_vocbase_col_t const* collection = TRI_LookupCollectionByNameVocBase(vocbase, v.c_str()); if (collection != 0) { valuesObject->Set(v8::String::New(k.c_str()), TRI_WrapCollection(collection)); diff --git a/arangod/V8Server/v8-query.cpp b/arangod/V8Server/v8-query.cpp index c383c9f250..1034e9dbc9 100644 --- a/arangod/V8Server/v8-query.cpp +++ b/arangod/V8Server/v8-query.cpp @@ -1741,7 +1741,7 @@ static v8::Handle JS_AllQuery (v8::Arguments const& argv) { uint32_t total = 0; vector docs; - SingleCollectionReadOnlyTransaction > trx(col->_vocbase, col->_name, (TRI_col_type_e) col->_type); + SingleCollectionReadOnlyTransaction > trx(col->_vocbase, col->_name); int res = trx.begin(); if (res != TRI_ERROR_NO_ERROR) { diff --git a/arangod/V8Server/v8-vocbase.cpp b/arangod/V8Server/v8-vocbase.cpp index dee0e000dd..a1fd4971e6 100644 --- a/arangod/V8Server/v8-vocbase.cpp +++ b/arangod/V8Server/v8-vocbase.cpp @@ -764,7 +764,7 @@ static v8::Handle DocumentVocbaseCol (const bool useCollection, assert(key); - SingleCollectionReadOnlyTransaction > trx(col->_vocbase, col->_name, (TRI_col_type_e) col->_type); + SingleCollectionReadOnlyTransaction > trx(col->_vocbase, col->_name); int res = trx.begin(); if (res != TRI_ERROR_NO_ERROR) { return scope.Close(v8::ThrowException(TRI_CreateErrorObject(res, "cannot fetch document", true))); @@ -849,7 +849,7 @@ static v8::Handle ReplaceVocbaseCol (const bool useCollection, assert(key); - SingleCollectionWriteTransaction, 1> trx(col->_vocbase, col->_name, (TRI_col_type_e) col->_type, false, "ReplaceVocbase"); + SingleCollectionWriteTransaction, 1> trx(col->_vocbase, col->_name); int res = trx.begin(); if (res != TRI_ERROR_NO_ERROR) { return scope.Close(v8::ThrowException(TRI_CreateErrorObject(res, "cannot replace document", true))); @@ -903,11 +903,11 @@ static v8::Handle ReplaceVocbaseCol (const bool useCollection, /// above. The optional @FA{waitForSync} parameter can be used to force /// synchronisation of the document creation operation to disk even in case /// that the @LIT{waitForSync} flag had been disabled for the entire collection. -/// Thus, the @FA{waitForSync} URL parameter can be used to force synchronisation +/// Thus, the @FA{waitForSync} parameter can be used to force synchronisation /// of just specific operations. To use this, set the @FA{waitForSync} parameter /// to @LIT{true}. If the @FA{waitForSync} parameter is not specified or set to /// @LIT{false}, then the collection's default @LIT{waitForSync} behavior is -/// applied. The @FA{waitForSync} URL parameter cannot be used to disable +/// applied. The @FA{waitForSync} parameter cannot be used to disable /// synchronisation for collections that have a default @LIT{waitForSync} value /// of @LIT{true}. /// @@ -984,11 +984,11 @@ static v8::Handle SaveVocbaseCol (SingleCollectionWriteTransaction UpdateVocbaseCol (const bool useCollection, } - SingleCollectionWriteTransaction, 1> trx(col->_vocbase, col->_name, (TRI_col_type_e) col->_type, false, "UpdateVocbase"); + SingleCollectionWriteTransaction, 1> trx(col->_vocbase, col->_name); int res = trx.begin(); if (res != TRI_ERROR_NO_ERROR) { return scope.Close(v8::ThrowException(TRI_CreateErrorObject(res, "cannot update document", true))); @@ -1256,7 +1256,7 @@ static v8::Handle RemoveVocbaseCol (const bool useCollection, assert(key); - SingleCollectionWriteTransaction, 1> trx(col->_vocbase, col->_name, (TRI_col_type_e) col->_type, false, "DeleteVocbase"); + SingleCollectionWriteTransaction, 1> trx(col->_vocbase, col->_name); int res = trx.begin(); if (res != TRI_ERROR_NO_ERROR) { return scope.Close(v8::ThrowException(TRI_CreateErrorObject(res, "cannot delete document", true))); @@ -3311,10 +3311,7 @@ static v8::Handle JS_DatafilesVocbaseCol (v8::Arguments const& argv) /// An error is thrown if there @LIT{_rev} does not longer match the current /// revision of the document. /// -/// An error is thrown if the document does not exist. -/// -/// The document must be part of the @FA{collection}; otherwise, an error -/// is thrown. +/// An error is also thrown if the document does not exist. /// /// @FUN{@FA{collection}.document(@FA{document-handle})} /// @@ -3325,15 +3322,30 @@ static v8::Handle JS_DatafilesVocbaseCol (v8::Arguments const& argv) /// /// Returns the document for a document-handle: /// -/// @TINYEXAMPLE{shell-read-document,read document from a collection} +/// @code +/// arango> db.example.document("1432124/2873916"); +/// { "_id" : "1432124/2873916", "_rev" : 2873916, "Hallo" : "World" } +/// @endcode /// /// An error is raised if the document is unknown: /// -/// @TINYEXAMPLE{shell-read-document-not-found,unknown handle} +/// @code +/// arango> db.example.document("1432124/123456"); +/// JavaScript exception in file '(arango)' at 1,12: +/// [ArangoError 1202: document not found: document not found] +/// !db.example.document("1432124/123456"); +/// ! ^ +/// @endcode /// /// An error is raised if the handle is invalid: /// -/// @TINYEXAMPLE{shell-read-document-bad-handle,invalid handle} +/// @code +/// arango> db.example.document("12345"); +/// JavaScript exception in file '(arango)' at 1,12: +/// [ArangoError 10: bad parameter: must be a document identifier] +/// !db.example.document("12345"); +/// ! ^ +/// @endcode //////////////////////////////////////////////////////////////////////////////// static v8::Handle JS_DocumentVocbaseCol (v8::Arguments const& argv) { @@ -4462,6 +4474,7 @@ static v8::Handle JS_NameVocbaseCol (v8::Arguments const& argv) { return scope.Close(v8::ThrowException(v8::String::New("illegal collection pointer"))); } + // TODO: protect this against race conditions (parallel rename operation) return scope.Close(v8::String::New(collection->_name)); } @@ -4624,29 +4637,29 @@ static v8::Handle JS_PropertiesVocbaseCol (v8::Arguments const& argv) } //////////////////////////////////////////////////////////////////////////////// -/// @brief deletes a document +/// @brief removes a document /// /// @FUN{@FA{collection}.remove(@FA{document})} /// -/// Deletes a document. If there is revision mismatch, then an error is thrown. +/// Removes a document. If there is revision mismatch, then an error is thrown. /// /// @FUN{@FA{collection}.remove(@FA{document}, true)} /// -/// Deletes a document. If there is revision mismatch, then mismatch -/// is ignored and document is deleted. The function returns -/// @LIT{true} if the document existed and was deleted. It returns -/// @LIT{false}, if the document was already deleted. +/// Removes a document. If there is revision mismatch, then mismatch is ignored +/// and document is deleted. The function returns @LIT{true} if the document +/// existed and was deleted. It returns @LIT{false}, if the document was already +/// deleted. /// /// @FUN{@FA{collection}.remove(@FA{document}, true, @FA{waitForSync})} /// -/// The optional @FA{waitForSync} parameter can be used to force -/// synchronisation of the document deletion operation to disk even in case -/// that the @LIT{waitForSync} flag had been disabled for the entire collection. -/// Thus, the @FA{waitForSync} URL parameter can be used to force synchronisation -/// of just specific operations. To use this, set the @FA{waitForSync} parameter -/// to @LIT{true}. If the @FA{waitForSync} parameter is not specified or set to -/// @LIT{false}, then the collection's default @LIT{waitForSync} behavior is -/// applied. The @FA{waitForSync} URL parameter cannot be used to disable +/// The optional @FA{waitForSync} parameter can be used to force synchronisation +/// of the document deletion operation to disk even in case that the +/// @LIT{waitForSync} flag had been disabled for the entire collection. Thus, +/// the @FA{waitForSync} parameter can be used to force synchronisation of just +/// specific operations. To use this, set the @FA{waitForSync} parameter to +/// @LIT{true}. If the @FA{waitForSync} parameter is not specified or set to +/// @LIT{false}, then the collection's default @LIT{waitForSync} behavior is +/// applied. The @FA{waitForSync} parameter cannot be used to disable /// synchronisation for collections that have a default @LIT{waitForSync} value /// of @LIT{true}. /// @@ -4657,13 +4670,39 @@ static v8::Handle JS_PropertiesVocbaseCol (v8::Arguments const& argv) /// /// @EXAMPLES /// -/// Delete a document: +/// Remove a document: /// -/// @TINYEXAMPLE{shell_remove-document,delete a document} +/// @code +/// arango> a1 = db.example.save({ a : 1 }); +/// { "_id" : "116308/3449537", "_rev" : 3449537 } +/// arango> db.example.document(a1); +/// { "_id" : "116308/3449537", "_rev" : 3449537, "a" : 1 } +/// arango> db.example.remove(a1); +/// true +/// arango> db.example.document(a1); +/// JavaScript exception in file '(arango)' at 1,12: [ArangoError 1202: document not found: document not found] +/// !db.example.document(a1); +/// ! ^ +/// @endcode /// -/// Delete a document with a conflict: +/// Remove a document with a conflict: /// -/// @TINYEXAMPLE{shell_remove-document-conflict,delete a document} +/// @code +/// arango> a1 = db.example.save({ a : 1 }); +/// { "_id" : "116308/3857139", "_rev" : 3857139 } +/// arango> a2 = db.example.replace(a1, { a : 2 }); +/// { "_id" : "116308/3857139", "_rev" : 3922675, "_oldRev" : 3857139 } +/// arango> db.example.remove(a1); +/// JavaScript exception in file '(arango)' at 1,18: [ArangoError 1200: conflict: cannot remove document] +/// !db.example.remove(a1); +/// ! ^ +/// arango> db.example.remove(a1, true); +/// true +/// arango> db.example.document(a1); +/// JavaScript exception in file '(arango)' at 1,12: [ArangoError 1202: document not found: document not found] +/// !db.example.document(a1); +/// ! ^ +/// @endcode //////////////////////////////////////////////////////////////////////////////// static v8::Handle JS_RemoveVocbaseCol (v8::Arguments const& argv) { @@ -4743,11 +4782,11 @@ static v8::Handle JS_RenameVocbaseCol (v8::Arguments const& argv) { /// The optional @FA{waitForSync} parameter can be used to force /// synchronisation of the document replacement operation to disk even in case /// that the @LIT{waitForSync} flag had been disabled for the entire collection. -/// Thus, the @FA{waitForSync} URL parameter can be used to force synchronisation +/// Thus, the @FA{waitForSync} parameter can be used to force synchronisation /// of just specific operations. To use this, set the @FA{waitForSync} parameter /// to @LIT{true}. If the @FA{waitForSync} parameter is not specified or set to /// @LIT{false}, then the collection's default @LIT{waitForSync} behavior is -/// applied. The @FA{waitForSync} URL parameter cannot be used to disable +/// applied. The @FA{waitForSync} parameter cannot be used to disable /// synchronisation for collections that have a default @LIT{waitForSync} value /// of @LIT{true}. /// @@ -4789,11 +4828,11 @@ static v8::Handle JS_ReplaceVocbaseCol (v8::Arguments const& argv) { /// The optional @FA{waitForSync} parameter can be used to force /// synchronisation of the document update operation to disk even in case /// that the @LIT{waitForSync} flag had been disabled for the entire collection. -/// Thus, the @FA{waitForSync} URL parameter can be used to force synchronisation +/// Thus, the @FA{waitForSync} parameter can be used to force synchronisation /// of just specific operations. To use this, set the @FA{waitForSync} parameter /// to @LIT{true}. If the @FA{waitForSync} parameter is not specified or set to /// @LIT{false}, then the collection's default @LIT{waitForSync} behavior is -/// applied. The @FA{waitForSync} URL parameter cannot be used to disable +/// applied. The @FA{waitForSync} parameter cannot be used to disable /// synchronisation for collections that have a default @LIT{waitForSync} value /// of @LIT{true}. /// @@ -4854,7 +4893,7 @@ static v8::Handle JS_SaveVocbaseCol (v8::Arguments const& argv) { return scope.Close(v8::ThrowException(TRI_CreateErrorObject(TRI_ERROR_INTERNAL))); } - SingleCollectionWriteTransaction, 1> trx(col->_vocbase, col->_name, (TRI_col_type_e) col->_type, false, "SaveVocbase"); + SingleCollectionWriteTransaction, 1> trx(col->_vocbase, col->_name); int res = trx.begin(); if (res != TRI_ERROR_NO_ERROR) { @@ -4946,6 +4985,37 @@ static v8::Handle JS_StatusVocbaseCol (v8::Arguments const& argv) { return scope.Close(v8::Number::New((int) status)); } +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns the revision id of a collection +/// the revision id is updated when the document data in a collection changes +//////////////////////////////////////////////////////////////////////////////// + +static v8::Handle JS_RevisionVocbaseCol (v8::Arguments const& argv) { + v8::HandleScope scope; + + v8::Handle err; + TRI_vocbase_col_t const* collection = UseCollection(argv.Holder(), &err); + + if (collection == 0) { + return scope.Close(v8::ThrowException(err)); + } + + TRI_primary_collection_t* primary = collection->_collection; + + if (! TRI_IS_DOCUMENT_COLLECTION(collection->_type)) { + TRI_ReleaseCollection(collection); + return scope.Close(v8::ThrowException(TRI_CreateErrorObject(TRI_ERROR_INTERNAL, "unknown collection type"))); + } + + primary->beginRead(primary); + TRI_voc_rid_t rid = primary->base._info._rid; + primary->endRead(primary); + + TRI_ReleaseCollection(collection); + + return scope.Close(v8::Number::New(rid)); +} + //////////////////////////////////////////////////////////////////////////////// /// @brief truncates a collection //////////////////////////////////////////////////////////////////////////////// @@ -4960,7 +5030,7 @@ static v8::Handle JS_TruncateVocbaseCol (v8::Arguments const& argv) { return scope.Close(v8::ThrowException(TRI_CreateErrorObject(TRI_ERROR_INTERNAL))); } - SingleCollectionWriteTransaction, UINT64_MAX> trx(col->_vocbase, col->_name, (TRI_col_type_e) col->_type, false, "TruncateVocbase"); + SingleCollectionWriteTransaction, UINT64_MAX> trx(col->_vocbase, col->_name); int res = trx.begin(); if (res != TRI_ERROR_NO_ERROR) { return scope.Close(v8::ThrowException(TRI_CreateErrorObject(res, "cannot truncate collection", true))); @@ -5160,12 +5230,7 @@ static v8::Handle MapGetVocBase (v8::Local name, // look up the value if it exists TRI_vocbase_col_t const* collection; - if (collectionType == TRI_COL_TYPE_EDGE) { - collection = TRI_FindEdgeCollectionByNameVocBase(vocbase, key.c_str(), true); - } - else { - collection = TRI_FindDocumentCollectionByNameVocBase(vocbase, key.c_str(), true); - } + collection = TRI_FindCollectionByNameOrBearVocBase(vocbase, key.c_str(), (TRI_col_type_t) collectionType); // if the key is not present return an empty handle as signal if (collection == 0) { @@ -5247,7 +5312,7 @@ static v8::Handle JS_CollectionVocbase (v8::Arguments const& argv) { else { string name = TRI_ObjectToString(val); - collection = TRI_FindCollectionByNameVocBase(vocbase, name.c_str(), false); + collection = TRI_LookupCollectionByNameVocBase(vocbase, name.c_str()); } if (collection == 0) { @@ -5345,7 +5410,7 @@ static v8::Handle JS_CompletionsVocbase (v8::Arguments const& argv) { /// /// @FUN{db._create(@FA{collection-name}, @FA{properties})} /// -/// @FA{properties} must be an object, with the following attribues: +/// @FA{properties} must be an object with the following attributes: /// /// - @LIT{waitForSync} (optional, default @LIT{false}): If @LIT{true} creating /// a document will only return after the data was synced to disk. @@ -5415,7 +5480,7 @@ static v8::Handle JS_CreateDocumentCollectionVocbase (v8::Arguments c /// /// @FUN{db._createEdgeCollection(@FA{collection-name}, @FA{properties})} /// -/// @FA{properties} must be an object, with the following attribues: +/// @FA{properties} must be an object with the following attributes: /// /// - @LIT{waitForSync} (optional, default @LIT{false}): If @LIT{true} creating /// a document will only return after the data was synced to disk. @@ -5435,46 +5500,72 @@ static v8::Handle JS_CreateEdgeCollectionVocbase (v8::Arguments const } //////////////////////////////////////////////////////////////////////////////// -/// @brief deletes a document +/// @brief removes a document /// /// @FUN{@FA{db}._remove(@FA{document})} /// -/// Deletes a document. If there is revision mismatch, then an error is thrown. +/// Removes a document. If there is revision mismatch, then an error is thrown. /// /// @FUN{@FA{db}._remove(@FA{document}, true)} /// -/// Deletes a document. If there is revision mismatch, then mismatch -/// is ignored and document is deleted. The function returns -/// @LIT{true} if the document existed and was deleted. It returns -/// @LIT{false}, if the document was already deleted. +/// Removes a document. If there is revision mismatch, then mismatch is ignored +/// and document is deleted. The function returns @LIT{true} if the document +/// existed and was deleted. It returns @LIT{false}, if the document was already +/// deleted. /// /// @FUN{@FA{db}._remove(@FA{document}, true, @FA{waitForSync})} /// -/// The optional @FA{waitForSync} parameter can be used to force -/// synchronisation of the document deletion operation to disk even in case -/// that the @LIT{waitForSync} flag had been disabled for the entire collection. -/// Thus, the @FA{waitForSync} URL parameter can be used to force synchronisation -/// of just specific operations. To use this, set the @FA{waitForSync} parameter -/// to @LIT{true}. If the @FA{waitForSync} parameter is not specified or set to -/// @LIT{false}, then the collection's default @LIT{waitForSync} behavior is -/// applied. The @FA{waitForSync} URL parameter cannot be used to disable +/// The optional @FA{waitForSync} parameter can be used to force synchronisation +/// of the document deletion operation to disk even in case that the +/// @LIT{waitForSync} flag had been disabled for the entire collection. Thus, +/// the @FA{waitForSync} parameter can be used to force synchronisation of just +/// specific operations. To use this, set the @FA{waitForSync} parameter to +/// @LIT{true}. If the @FA{waitForSync} parameter is not specified or set to +/// @LIT{false}, then the collection's default @LIT{waitForSync} behavior is +/// applied. The @FA{waitForSync} parameter cannot be used to disable /// synchronisation for collections that have a default @LIT{waitForSync} value /// of @LIT{true}. /// /// @FUN{@FA{db}._remove(@FA{document-handle}, @FA{data})} /// -/// As before. Instead of document a @FA{document-handle} can be passed as -/// first argument. +/// As before. Instead of document a @FA{document-handle} can be passed as first +/// argument. /// /// @EXAMPLES /// -/// Delete a document: +/// Remove a document: /// -/// @TINYEXAMPLE{shell_remove-document-db,delete a document} +/// @code +/// arango> a1 = db.example.save({ a : 1 }); +/// { "_id" : "116308/4214943", "_rev" : 4214943 } +/// arango> db._remove(a1); +/// true +/// arango> db._remove(a1); +/// JavaScript exception in file '(arango)' at 1,4: [ArangoError 1202: document not found: cannot remove document] +/// !db._remove(a1); +/// ! ^ +/// arango> db._remove(a1, true); +/// false +/// @endcode /// -/// Delete a document with a conflict: +/// Remove a document with a conflict: /// -/// @TINYEXAMPLE{shell_remove-document-conflict-db,delete a document} +/// @code +/// arango> a1 = db.example.save({ a : 1 }); +/// { "_id" : "116308/4042634", "_rev" : 4042634 } +/// arango> a2 = db._replace(a1, { a : 2 }); +/// { "_id" : "116308/4042634", "_rev" : 4108170, "_oldRev" : 4042634 } +/// arango> db._delete(a1); +/// JavaScript exception in file '(arango)' at 1,4: [ArangoError 1200: conflict: cannot delete document] +/// !db._delete(a1); +/// ! ^ +/// arango> db._delete(a1, true); +/// true +/// arango> db._document(a1); +/// JavaScript exception in file '(arango)' at 1,4: [ArangoError 1202: document not found: document not found] +/// !db._document(a1); +/// ! ^ +/// @endcode //////////////////////////////////////////////////////////////////////////////// static v8::Handle JS_RemoveVocbase (v8::Arguments const& argv) { @@ -5534,11 +5625,11 @@ static v8::Handle JS_DocumentVocbase (v8::Arguments const& argv) { /// The optional @FA{waitForSync} parameter can be used to force /// synchronisation of the document replacement operation to disk even in case /// that the @LIT{waitForSync} flag had been disabled for the entire collection. -/// Thus, the @FA{waitForSync} URL parameter can be used to force synchronisation +/// Thus, the @FA{waitForSync} parameter can be used to force synchronisation /// of just specific operations. To use this, set the @FA{waitForSync} parameter /// to @LIT{true}. If the @FA{waitForSync} parameter is not specified or set to /// @LIT{false}, then the collection's default @LIT{waitForSync} behavior is -/// applied. The @FA{waitForSync} URL parameter cannot be used to disable +/// applied. The @FA{waitForSync} parameter cannot be used to disable /// synchronisation for collections that have a default @LIT{waitForSync} value /// of @LIT{true}. /// @@ -5576,11 +5667,11 @@ static v8::Handle JS_ReplaceVocbase (v8::Arguments const& argv) { /// The optional @FA{waitForSync} parameter can be used to force /// synchronisation of the document update operation to disk even in case /// that the @LIT{waitForSync} flag had been disabled for the entire collection. -/// Thus, the @FA{waitForSync} URL parameter can be used to force synchronisation +/// Thus, the @FA{waitForSync} parameter can be used to force synchronisation /// of just specific operations. To use this, set the @FA{waitForSync} parameter /// to @LIT{true}. If the @FA{waitForSync} parameter is not specified or set to /// @LIT{false}, then the collection's default @LIT{waitForSync} behavior is -/// applied. The @FA{waitForSync} URL parameter cannot be used to disable +/// applied. The @FA{waitForSync} parameter cannot be used to disable /// synchronisation for collections that have a default @LIT{waitForSync} value /// of @LIT{true}. /// @@ -6209,6 +6300,7 @@ v8::Handle TRI_WrapShapedJson (TRI_vocbase_col_t const* collection, // store the document reference TRI_voc_rid_t rid = document->_rid; + // TODO: protect this against race conditions (parallel rename) result->Set(v8g->DidKey, DocumentId(collection->_name, document->_key), v8::ReadOnly); result->Set(v8g->RevKey, v8::Number::New(rid), v8::ReadOnly); result->Set(v8g->KeyKey, v8::String::New(document->_key), v8::ReadOnly); @@ -6440,6 +6532,7 @@ TRI_v8_global_t* TRI_InitV8VocBridge (v8::Handle context, TRI_AddMethodVocbase(rt, "name", JS_NameVocbaseCol); TRI_AddMethodVocbase(rt, "properties", JS_PropertiesVocbaseCol); TRI_AddMethodVocbase(rt, "remove", JS_RemoveVocbaseCol); + TRI_AddMethodVocbase(rt, "revision", JS_RevisionVocbaseCol); TRI_AddMethodVocbase(rt, "rename", JS_RenameVocbaseCol); TRI_AddMethodVocbase(rt, "setAttribute", JS_SetAttributeVocbaseCol, true); TRI_AddMethodVocbase(rt, "status", JS_StatusVocbaseCol); diff --git a/arangod/VocBase/collection.c b/arangod/VocBase/collection.c index e8fe55957f..c05b2ca8c1 100644 --- a/arangod/VocBase/collection.c +++ b/arangod/VocBase/collection.c @@ -482,14 +482,15 @@ void TRI_InitCollectionInfo (TRI_vocbase_t* vocbase, assert(parameter); memset(parameter, 0, sizeof(TRI_col_info_t)); - parameter->_version = TRI_COL_VERSION; - parameter->_type = type; - parameter->_cid = 0; + parameter->_version = TRI_COL_VERSION; + parameter->_type = type; + parameter->_cid = 0; + parameter->_rid = 0; - parameter->_deleted = false; - parameter->_isVolatile = false; - parameter->_isSystem = false; - parameter->_maximalSize = (maximalSize / PageSize) * PageSize; + parameter->_deleted = false; + parameter->_isVolatile = false; + parameter->_isSystem = false; + parameter->_maximalSize = (maximalSize / PageSize) * PageSize; if (parameter->_maximalSize == 0 && maximalSize != 0) { parameter->_maximalSize = PageSize; } @@ -501,7 +502,7 @@ void TRI_InitCollectionInfo (TRI_vocbase_t* vocbase, parameter->_options = options; } else { - parameter->_options = 0; + parameter->_options = NULL; } } @@ -513,13 +514,14 @@ void TRI_CopyCollectionInfo (TRI_col_info_t* dst, TRI_col_info_t* src) { assert(dst); memset(dst, 0, sizeof(TRI_col_info_t)); - dst->_version = src->_version; - dst->_type = src->_type; - dst->_cid = src->_cid; + dst->_version = src->_version; + dst->_type = src->_type; + dst->_cid = src->_cid; + dst->_rid = src->_rid; - dst->_deleted = src->_deleted; - dst->_isSystem = src->_isSystem; - dst->_isVolatile = src->_isVolatile; + dst->_deleted = src->_deleted; + dst->_isSystem = src->_isSystem; + dst->_isVolatile = src->_isVolatile; dst->_maximalSize = src->_maximalSize; TRI_CopyString(dst->_name, src->_name, sizeof(dst->_name)); dst->_waitForSync = src->_waitForSync; @@ -528,7 +530,7 @@ void TRI_CopyCollectionInfo (TRI_col_info_t* dst, TRI_col_info_t* src) { dst->_options = TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, src->_options); } else { - dst->_options = 0; + dst->_options = NULL; } } @@ -539,7 +541,7 @@ void TRI_CopyCollectionInfo (TRI_col_info_t* dst, TRI_col_info_t* src) { void TRI_FreeCollectionInfoOptions (TRI_col_info_t* parameter) { if (parameter->_options) { TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, parameter->_options); - parameter->_options = 0; + parameter->_options = NULL; } } diff --git a/arangod/VocBase/collection.h b/arangod/VocBase/collection.h index 8fa5970d15..d244c1b10d 100644 --- a/arangod/VocBase/collection.h +++ b/arangod/VocBase/collection.h @@ -218,10 +218,11 @@ typedef struct TRI_col_info_s { TRI_col_version_t _version; // collection version TRI_col_type_e _type; // collection type TRI_voc_cid_t _cid; // collection identifier - struct TRI_json_s* _options; // optional collection options + TRI_voc_rid_t _rid; // last revision id TRI_voc_size_t _maximalSize; // maximal size of memory mapped file char _name[TRI_COL_PATH_LENGTH]; // name of the collection + struct TRI_json_s* _options; // optional collection options // flags bool _deleted : 1; // if true, collection has been deleted @@ -250,7 +251,7 @@ typedef struct TRI_collection_s { TRI_vector_pointer_t _datafiles; // all datafiles TRI_vector_pointer_t _journals; // all journals TRI_vector_pointer_t _compactors; // all compactor files - TRI_vector_string_t _indexFiles; // all index filenames + TRI_vector_string_t _indexFiles; // all index filenames } TRI_collection_t; diff --git a/arangod/VocBase/document-collection.c b/arangod/VocBase/document-collection.c index ccca35e9df..7f320770c3 100644 --- a/arangod/VocBase/document-collection.c +++ b/arangod/VocBase/document-collection.c @@ -143,6 +143,19 @@ static bool IsVisible (TRI_doc_mptr_t const* header, return (header != NULL && header->_validTo == 0); } +//////////////////////////////////////////////////////////////////////////////// +/// @brief set the collection revision id with the marker's tick value +//////////////////////////////////////////////////////////////////////////////// + +static void CollectionRevisionUpdate (TRI_document_collection_t* document, + const TRI_df_marker_t* const marker) { + TRI_col_info_t* info = &document->base.base._info; + + if (marker->_tick > info->_rid) { + info->_rid = marker->_tick; + } +} + //////////////////////////////////////////////////////////////////////////////// /// @} //////////////////////////////////////////////////////////////////////////////// @@ -295,6 +308,8 @@ static int WriteElement (TRI_document_collection_t* document, return res; } + CollectionRevisionUpdate(document, marker); + TRI_LOCK_JOURNAL_ENTRIES_DOC_COLLECTION(document); journal->_written = ((char*) result) + marker->_size; @@ -1437,6 +1452,8 @@ static bool OpenIterator (TRI_df_marker_t const* marker, void* data, TRI_datafil primary = &collection->base; + CollectionRevisionUpdate(collection, marker); + // new or updated document if (marker->_type == TRI_DOC_MARKER_KEY_EDGE || marker->_type == TRI_DOC_MARKER_KEY_DOCUMENT) { diff --git a/arangod/VocBase/transaction.c b/arangod/VocBase/transaction.c index 677f14e578..229d6f9f33 100644 --- a/arangod/VocBase/transaction.c +++ b/arangod/VocBase/transaction.c @@ -505,8 +505,7 @@ void TRI_DumpTransactionContext (TRI_transaction_context_t* const context) { //////////////////////////////////////////////////////////////////////////////// static TRI_transaction_collection_t* CreateCollection (const char* const name, - const TRI_transaction_type_e type, - TRI_vocbase_col_t* initialiser) { + const TRI_transaction_type_e type) { TRI_transaction_collection_t* collection; collection = (TRI_transaction_collection_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_transaction_collection_t), false); @@ -525,10 +524,9 @@ static TRI_transaction_collection_t* CreateCollection (const char* const name, // initialise collection properties collection->_type = type; - collection->_collection = initialiser; + collection->_collection = NULL; collection->_globalInstance = NULL; collection->_locked = false; - collection->_externalLock = (initialiser != NULL); // initialise private copy of write transactions list InitTransactionList(&collection->_writeTransactions); @@ -595,10 +593,8 @@ static int AcquireCollectionLocks (TRI_transaction_t* const trx) { for (i = 0; i < n; ++i) { TRI_transaction_collection_t* collection; - collection = TRI_AtVectorPointer(&trx->_collections, i); - if (! collection->_externalLock) { - collection->_collection = TRI_UseCollectionByNameVocBase(trx->_context->_vocbase, collection->_name); - } + collection = (TRI_transaction_collection_t*) TRI_AtVectorPointer(&trx->_collections, i); + collection->_collection = TRI_UseCollectionByNameVocBase(trx->_context->_vocbase, collection->_name); if (collection->_collection == NULL) { return TRI_errno(); @@ -655,9 +651,7 @@ static int ReleaseCollectionLocks (TRI_transaction_t* const trx) { } // unuse collection - if (! collection->_externalLock) { - TRI_ReleaseCollectionVocBase(trx->_context->_vocbase, collection->_collection); - } + TRI_ReleaseCollectionVocBase(trx->_context->_vocbase, collection->_collection); collection->_collection = NULL; } @@ -1091,8 +1085,7 @@ TRI_vocbase_col_t* TRI_CheckCollectionTransaction (TRI_transaction_t* const trx, int TRI_AddCollectionTransaction (TRI_transaction_t* const trx, const char* const name, - const TRI_transaction_type_e type, - TRI_vocbase_col_t* initialiser) { + const TRI_transaction_type_e type) { TRI_transaction_collection_t* collection; size_t i, n; @@ -1116,7 +1109,7 @@ int TRI_AddCollectionTransaction (TRI_transaction_t* const trx, if (res < 0) { // collection is not contained in vector - collection = CreateCollection(name, type, initialiser); + collection = CreateCollection(name, type); if (collection == NULL) { // out of memory return TRI_ERROR_OUT_OF_MEMORY; @@ -1139,7 +1132,7 @@ int TRI_AddCollectionTransaction (TRI_transaction_t* const trx, } // collection was not contained. now insert it - collection = CreateCollection(name, type, initialiser); + collection = CreateCollection(name, type); if (collection == NULL) { // out of memory return TRI_ERROR_OUT_OF_MEMORY; @@ -1240,6 +1233,30 @@ int TRI_FinishTransaction (TRI_transaction_t* const trx) { return res; } +//////////////////////////////////////////////////////////////////////////////// +/// @brief get the pointer to a collection after it has been initialised +//////////////////////////////////////////////////////////////////////////////// + +TRI_vocbase_col_t* TRI_GetCollectionTransaction (const TRI_transaction_t* const trx, + const char* const name) { + size_t i, n; + + assert(trx->_status == TRI_TRANSACTION_RUNNING); + + n = trx->_collections._length; + + // process collections in forward order + for (i = 0; i < n; ++i) { + TRI_transaction_collection_t* collection; + + collection = (TRI_transaction_collection_t*) TRI_AtVectorPointer(&trx->_collections, i); + if (TRI_EqualString(name, collection->_name)) { + return collection->_collection; + } + } + return NULL; +} + //////////////////////////////////////////////////////////////////////////////// /// @} //////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/VocBase/transaction.h b/arangod/VocBase/transaction.h index f44338809f..2d4253fabf 100644 --- a/arangod/VocBase/transaction.h +++ b/arangod/VocBase/transaction.h @@ -283,7 +283,6 @@ typedef struct TRI_transaction_collection_s { struct TRI_vocbase_col_s* _collection; // vocbase collection pointer TRI_transaction_collection_global_t* _globalInstance; // pointer to the global instance of the collection in the trx system bool _locked; // lock flag (used for write-transactions) - bool _externalLock; // flag whether collection was locked externally } TRI_transaction_collection_t; @@ -395,8 +394,7 @@ struct TRI_vocbase_col_s* TRI_CheckCollectionTransaction (TRI_transaction_t* con int TRI_AddCollectionTransaction (TRI_transaction_t* const, const char* const, - const TRI_transaction_type_e, - struct TRI_vocbase_col_s*); + const TRI_transaction_type_e); //////////////////////////////////////////////////////////////////////////////// /// @brief start a transaction @@ -422,6 +420,13 @@ int TRI_AbortTransaction (TRI_transaction_t* const); int TRI_FinishTransaction (TRI_transaction_t* const); +//////////////////////////////////////////////////////////////////////////////// +/// @brief get the pointer to a collection after it has been initialised +//////////////////////////////////////////////////////////////////////////////// + +struct TRI_vocbase_col_s* TRI_GetCollectionTransaction (const TRI_transaction_t* const, + const char* const); + //////////////////////////////////////////////////////////////////////////////// /// @} //////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/VocBase/vocbase.c b/arangod/VocBase/vocbase.c index 9025912b73..a92cd04748 100644 --- a/arangod/VocBase/vocbase.c +++ b/arangod/VocBase/vocbase.c @@ -815,7 +815,6 @@ static int ManifestCollectionVocBase (TRI_vocbase_t* vocbase, TRI_vocbase_col_t* static TRI_vocbase_col_t* FindCollectionByNameVocBase (TRI_vocbase_t* vocbase, char const* name, - bool bear, TRI_col_type_e type) { union { void const* v; TRI_vocbase_col_t* c; } found; @@ -827,15 +826,9 @@ static TRI_vocbase_col_t* FindCollectionByNameVocBase (TRI_vocbase_t* vocbase, return found.c; } - if (! bear) { - TRI_set_errno(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND); - return NULL; - } - return BearCollectionVocBase(vocbase, name, type); } - //////////////////////////////////////////////////////////////////////////////// /// @brief loads an existing (document) collection /// @@ -1372,6 +1365,32 @@ TRI_vector_pointer_t TRI_CollectionsVocBase (TRI_vocbase_t* vocbase) { return result; } +//////////////////////////////////////////////////////////////////////////////// +/// @brief get a collection name by a collection id +/// +/// the name is fetched under a lock to make this thread-safe. returns NULL if +/// the collection does not exist +/// it is the caller's responsibility to free the name returned +//////////////////////////////////////////////////////////////////////////////// + +char* TRI_GetCollectionNameByIdVocBase (TRI_vocbase_t* vocbase, + const TRI_voc_cid_t id) { + union { void const* v; TRI_vocbase_col_t* c; } found; + char* name; + + TRI_READ_LOCK_COLLECTIONS_VOCBASE(vocbase); + found.v = TRI_LookupByKeyAssociativePointer(&vocbase->_collectionsById, &id); + if (found.v == NULL) { + name = NULL; + } + else { + name = TRI_DuplicateStringZ(TRI_UNKNOWN_MEM_ZONE, found.c->_name); + } + TRI_READ_UNLOCK_COLLECTIONS_VOCBASE(vocbase); + + return name; +} + //////////////////////////////////////////////////////////////////////////////// /// @brief looks up a (document) collection by name //////////////////////////////////////////////////////////////////////////////// @@ -1401,27 +1420,13 @@ TRI_vocbase_col_t* TRI_LookupCollectionByIdVocBase (TRI_vocbase_t* vocbase, TRI_ } //////////////////////////////////////////////////////////////////////////////// -/// @brief finds a collection by name +/// @brief finds a collection by name, optionally creates it //////////////////////////////////////////////////////////////////////////////// -TRI_vocbase_col_t* TRI_FindCollectionByNameVocBase (TRI_vocbase_t* vocbase, char const* name, bool bear) { - return TRI_FindDocumentCollectionByNameVocBase(vocbase, name, bear); -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief finds a primary collection by name -//////////////////////////////////////////////////////////////////////////////// - -TRI_vocbase_col_t* TRI_FindDocumentCollectionByNameVocBase (TRI_vocbase_t* vocbase, char const* name, bool bear) { - return FindCollectionByNameVocBase(vocbase, name, bear, TRI_COL_TYPE_DOCUMENT); -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief finds an edge collection by name -//////////////////////////////////////////////////////////////////////////////// - -TRI_vocbase_col_t* TRI_FindEdgeCollectionByNameVocBase (TRI_vocbase_t* vocbase, char const* name, bool bear) { - return FindCollectionByNameVocBase(vocbase, name, bear, TRI_COL_TYPE_EDGE); +TRI_vocbase_col_t* TRI_FindCollectionByNameOrBearVocBase (TRI_vocbase_t* vocbase, + char const* name, + const TRI_col_type_t type) { + return FindCollectionByNameVocBase(vocbase, name, (TRI_col_type_e) type); } //////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/VocBase/vocbase.h b/arangod/VocBase/vocbase.h index 971a1be6ce..540cbd97e7 100644 --- a/arangod/VocBase/vocbase.h +++ b/arangod/VocBase/vocbase.h @@ -505,6 +505,16 @@ void TRI_DestroyVocBase (TRI_vocbase_t*); TRI_vector_pointer_t TRI_CollectionsVocBase (TRI_vocbase_t*); +//////////////////////////////////////////////////////////////////////////////// +/// @brief get a collection name by a collection id +/// +/// the name is fetched under a lock to make this thread-safe. returns NULL if +/// the collection does not exist +/// it is the caller's responsibility to free the name returned +//////////////////////////////////////////////////////////////////////////////// + +char* TRI_GetCollectionNameByIdVocBase (TRI_vocbase_t*, const TRI_voc_cid_t); + //////////////////////////////////////////////////////////////////////////////// /// @brief looks up a (document) collection by name //////////////////////////////////////////////////////////////////////////////// @@ -518,22 +528,12 @@ TRI_vocbase_col_t* TRI_LookupCollectionByNameVocBase (TRI_vocbase_t*, char const TRI_vocbase_col_t* TRI_LookupCollectionByIdVocBase (TRI_vocbase_t*, TRI_voc_cid_t); //////////////////////////////////////////////////////////////////////////////// -/// @brief finds a collection by name +/// @brief finds a collection by name or creates it //////////////////////////////////////////////////////////////////////////////// -TRI_vocbase_col_t* TRI_FindCollectionByNameVocBase (TRI_vocbase_t*, char const*, bool bear); - -//////////////////////////////////////////////////////////////////////////////// -/// @brief finds a primary collection by name -//////////////////////////////////////////////////////////////////////////////// - -TRI_vocbase_col_t* TRI_FindDocumentCollectionByNameVocBase (TRI_vocbase_t*, char const*, bool bear); - -//////////////////////////////////////////////////////////////////////////////// -/// @brief finds an edge collection by name -//////////////////////////////////////////////////////////////////////////////// - -TRI_vocbase_col_t* TRI_FindEdgeCollectionByNameVocBase (TRI_vocbase_t*, char const*, bool bear); +TRI_vocbase_col_t* TRI_FindCollectionByNameOrBearVocBase (TRI_vocbase_t*, + char const*, + const TRI_col_type_t); //////////////////////////////////////////////////////////////////////////////// /// @brief creates a new (document) collection from parameter set diff --git a/arangosh/V8Client/arangosh.cpp b/arangosh/V8Client/arangosh.cpp index 0fcf37b8a7..cf032a4426 100644 --- a/arangosh/V8Client/arangosh.cpp +++ b/arangosh/V8Client/arangosh.cpp @@ -62,12 +62,6 @@ using namespace triagens::httpclient; using namespace triagens::v8client; using namespace triagens::arango; -#include "js/common/bootstrap/js-print.h" -#include "js/common/bootstrap/js-modules.h" -#include "js/common/bootstrap/js-monkeypatches.h" -#include "js/common/bootstrap/js-errors.h" -#include "js/client/js-client.h" - // ----------------------------------------------------------------------------- // --SECTION-- private variables // ----------------------------------------------------------------------------- @@ -1341,30 +1335,33 @@ int main (int argc, char* argv[]) { // load java script from js/bootstrap/*.h files if (StartupPath.empty()) { - StartupLoader.defineScript("common/bootstrap/modules.js", JS_common_bootstrap_modules); - StartupLoader.defineScript("common/bootstrap/monkeypatches.js", JS_common_bootstrap_monkeypatches); - StartupLoader.defineScript("common/bootstrap/print.js", JS_common_bootstrap_print); - StartupLoader.defineScript("common/bootstrap/errors.js", JS_common_bootstrap_errors); - StartupLoader.defineScript("client/client.js", JS_client_client); - } - else { - LOGGER_DEBUG << "using JavaScript startup files at '" << StartupPath << "'"; - StartupLoader.setDirectory(StartupPath); + LOGGER_FATAL << "no 'javascript.startup-directory' has been supplied, giving up"; + TRI_FlushLogging(); + exit(EXIT_FAILURE); } + LOGGER_DEBUG << "using JavaScript startup files at '" << StartupPath << "'"; + StartupLoader.setDirectory(StartupPath); + context->Global()->Set(v8::String::New("ARANGO_QUIET"), v8::Boolean::New(BaseClient.quiet()), v8::ReadOnly); context->Global()->Set(v8::String::New("VALGRIND"), v8::Boolean::New((RUNNING_ON_VALGRIND) > 0)); // load all init files - char const* files[] = { - "common/bootstrap/modules.js", - "common/bootstrap/monkeypatches.js", - "common/bootstrap/print.js", - "common/bootstrap/errors.js", - "client/client.js" - }; + vector files; + + files.push_back("common/bootstrap/modules.js"); + files.push_back("common/bootstrap/module-internal.js"); + files.push_back("common/bootstrap/module-fs.js"); + files.push_back("common/bootstrap/module-console.js"); + + if (JsLint.empty()) { + files.push_back("common/bootstrap/monkeypatches.js"); + } + + files.push_back("common/bootstrap/errors.js"); + files.push_back("client/client.js"); - for (size_t i = 0; i < sizeof(files) / sizeof(files[0]); ++i) { + for (size_t i = 0; i < files.size(); ++i) { bool ok = StartupLoader.loadScript(context, files[i]); if (ok) { diff --git a/config/js2c.sh b/config/js2c.sh deleted file mode 100755 index 5604c0ad7d..0000000000 --- a/config/js2c.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -NAME=`echo $1 | sed -e 's:^\(.*/\)*js/\(.*\)\.js$:\2:' | tr "/-" "__"` - -#cat $1 \ -# | sed -e 's:\(["\]\):\\\1:g' \ -# | awk 'BEGIN {print "static string JS_'$NAME' = string(\"\") " } { print " + \"" $0 "\\n\"" } END { print ";"}' - -cat $1 \ - | sed -e 's:\(["\]\):\\\1:g' \ - | awk 'BEGIN {print "const char* JS_'$NAME'[] = {" } { print " \"" $0 "\"," } END { print " \"//__end__\"\n};"}' - diff --git a/etc/arangodb/arangosh.conf.in b/etc/arangodb/arangosh.conf.in index 8499d72ef7..b2b6e744a6 100644 --- a/etc/arangodb/arangosh.conf.in +++ b/etc/arangodb/arangosh.conf.in @@ -2,4 +2,5 @@ endpoint = tcp://localhost:8529 [javascript] +startup-directory = @PKGDATADIR@/js modules-path = @PKGDATADIR@/js/client/modules;@PKGDATADIR@/js/common/modules diff --git a/etc/relative/arangosh.conf b/etc/relative/arangosh.conf index 3668d48d26..b54f1069f4 100644 --- a/etc/relative/arangosh.conf +++ b/etc/relative/arangosh.conf @@ -1,2 +1,3 @@ [javascript] +startup-directory = ./js modules-path = ./js/client/modules;./js/common/modules diff --git a/html/admin/index.html b/html/admin/index.html index 66f72ebe13..786bc80e9b 100644 --- a/html/admin/index.html +++ b/html/admin/index.html @@ -27,13 +27,14 @@ - - - + + + + - +