mirror of https://gitee.com/bigwinds/arangodb
started rewrite of rest interface
This commit is contained in:
parent
360b7f96fd
commit
c64f76b701
|
@ -100,7 +100,7 @@ static void StringifyJson (TRI_string_buffer_t* buffer, TRI_json_t const* object
|
|||
}
|
||||
|
||||
StringifyJson(buffer, TRI_AtVector(&object->_value._objects, i), true);
|
||||
TRI_AppendStringStringBuffer(buffer, ":");
|
||||
TRI_AppendCharStringBuffer(buffer, ':');
|
||||
StringifyJson(buffer, TRI_AtVector(&object->_value._objects, i + 1), true);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
#! avocsh
|
||||
|
||||
var console = require("console");
|
||||
var name = "demo";
|
||||
|
||||
var collection = db[name];
|
||||
|
||||
collection.drop(name);
|
||||
|
||||
collection.save({ hallo : "world" });
|
||||
|
||||
collection.save({ world : "hallo" });
|
||||
|
||||
collection.save({ name : "Hugo",
|
||||
firstName : "Egon",
|
||||
address : {
|
||||
street : "Neue Strasse",
|
||||
city : "Hier" },
|
||||
hobbies : [ "swimming", "programming" ]});
|
|
@ -0,0 +1,16 @@
|
|||
#! avocsh
|
||||
|
||||
var console = require("console");
|
||||
var name = "five";
|
||||
|
||||
var collection = db[name];
|
||||
|
||||
collection.drop(name);
|
||||
collection.ensureUniqueConstraint("a");
|
||||
collection.ensureUniqueConstraint("b");
|
||||
|
||||
collection.save({ a : 1, b : "One" });
|
||||
collection.save({ a : 2, b : "Two" });
|
||||
collection.save({ a : 3, b : "Three" });
|
||||
collection.save({ a : 4, b : "Four" });
|
||||
collection.save({ a : 5, b : "Five" });
|
|
@ -0,0 +1,22 @@
|
|||
#! avocsh
|
||||
|
||||
var console = require("console");
|
||||
var name = "geo";
|
||||
|
||||
var collection = db[name];
|
||||
|
||||
collection.drop(name);
|
||||
|
||||
db.geo.ensureGeoIndex("home");
|
||||
db.geo.ensureGeoIndex("work.l", "work.b");
|
||||
|
||||
for (i = -90; i <= 90; i += 10) {
|
||||
for (j = -180; j <= 180; j += 10) {
|
||||
db.geo.save({
|
||||
name : "Name/" + i + "/" + j,
|
||||
home : [ i, j ],
|
||||
work : { b : i, l : j }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
HTTP/1.1 404 Bad Request
|
||||
...
|
||||
|
||||
{"error":true,"code":404,"errorNum":41404,"errorMessage":"Key value pair not found"}
|
|
@ -0,0 +1,4 @@
|
|||
HTTP/1.1 200 OK
|
||||
...
|
||||
|
||||
{"removed":true,"error":false,"code":202}
|
|
@ -0,0 +1,2 @@
|
|||
DELETE /_api/key/example_collection/example_key1 HTTP/1.1
|
||||
Host: localhost:9000
|
|
@ -0,0 +1,4 @@
|
|||
HTTP/1.1 404 Bad Request
|
||||
...
|
||||
|
||||
{"error":true,"code":404,"errorNum":41404,"errorMessage":"Key value pair not found"}
|
|
@ -0,0 +1,7 @@
|
|||
HTTP/1.1 200 OK
|
||||
x-voc-created: 2010-09-15T09:35:01Z
|
||||
x-voc-expires: 2011-09-29T08:00:00Z
|
||||
x-voc-extended: {"option1":35,"option2":"x"}
|
||||
...
|
||||
|
||||
13
|
|
@ -0,0 +1,2 @@
|
|||
GET /_api/key/example_collection/example_key1 HTTP/1.1
|
||||
Host: localhost:9000
|
|
@ -0,0 +1,4 @@
|
|||
HTTP/1.1 404 Bad Request
|
||||
...
|
||||
|
||||
{"error":true,"code":404,"errorNum":41404,"errorMessage":"Collection not found"}
|
|
@ -0,0 +1,4 @@
|
|||
HTTP/1.1 200 OK
|
||||
...
|
||||
|
||||
["example_keyboard","example_keystone"]
|
|
@ -0,0 +1,2 @@
|
|||
GET /_api/keys/example_collection/example_key HTTP/1.1
|
||||
Host: localhost:9000
|
|
@ -0,0 +1,7 @@
|
|||
HTTP/1.1 404 Bad Request
|
||||
content-type: application/json
|
||||
connection: Keep-Alive
|
||||
server: triagens GmbH High-Performance HTTP Server
|
||||
content-length: 75
|
||||
|
||||
{"error":true,"code":404,"errorNum":41304,"errorMessage":"Use PUT to change value"}
|
|
@ -0,0 +1,7 @@
|
|||
HTTP/1.1 201 Created
|
||||
connection: Keep-Alive
|
||||
content-type: application/json
|
||||
server: triagens GmbH High-Performance HTTP Server
|
||||
content-length: 62
|
||||
|
||||
{"saved":true,"_id":"155630:9500735","error":false,"code":201}
|
|
@ -0,0 +1,7 @@
|
|||
POST /_api/key/example_collection/example_key1 HTTP/1.1
|
||||
Host: localhost:9000
|
||||
x-voc-expires: 2011-09-29T08:00:00Z
|
||||
x-voc-extended: {"option1":35,"option2":"x"}
|
||||
Content-Length: 2
|
||||
|
||||
12
|
|
@ -0,0 +1,4 @@
|
|||
HTTP/1.1 404 Bad Request
|
||||
...
|
||||
|
||||
{"error":true,"code":404,"errorNum":41404,"errorMessage":"Key value pair not found"}
|
|
@ -0,0 +1,7 @@
|
|||
HTTP/1.1 202 Accepted
|
||||
connection: Keep-Alive
|
||||
content-type: application/json
|
||||
server: triagens GmbH High-Performance HTTP Server
|
||||
content-length: 41
|
||||
|
||||
{"changed":true,"error":false,"code":202}
|
|
@ -0,0 +1,7 @@
|
|||
PUT /_api/key/example_collection/example_key1 HTTP/1.1
|
||||
Host: localhost:9000
|
||||
x-voc-expires: 2011-09-29T08:00:00Z
|
||||
x-voc-extended: {"option1":35,"option2":"x"}
|
||||
Content-Length: 2
|
||||
|
||||
13
|
|
@ -0,0 +1,29 @@
|
|||
avocsh> db.demo.all();
|
||||
[
|
||||
{
|
||||
_id : "161039/4323870",
|
||||
_rev : 4323870,
|
||||
name : "Hugo",
|
||||
firstName : "Egon",
|
||||
address : {
|
||||
city : "Hier",
|
||||
street : "Neue Strasse"
|
||||
},
|
||||
hobbies : [
|
||||
"swimming",
|
||||
"programming"
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
_id : "161039/4192798",
|
||||
_rev : 4192798,
|
||||
hallo : "world"
|
||||
},
|
||||
|
||||
{
|
||||
_id : "161039/4258334",
|
||||
_rev : 4258334,
|
||||
world : "hallo"
|
||||
}
|
||||
]
|
|
@ -0,0 +1,37 @@
|
|||
avocsh> db.five.all();
|
||||
[
|
||||
{
|
||||
_id : "138663/2631399",
|
||||
_rev : 2631399,
|
||||
a : 2,
|
||||
b : "Two"
|
||||
},
|
||||
|
||||
{
|
||||
_id : "138663/2828007",
|
||||
_rev : 2828007,
|
||||
a : 5,
|
||||
b : "Five"
|
||||
},
|
||||
|
||||
{
|
||||
_id : "138663/2696935",
|
||||
_rev : 2696935,
|
||||
a : 3,
|
||||
b : "Three"
|
||||
},
|
||||
|
||||
{
|
||||
_id : "138663/2565863",
|
||||
_rev : 2565863,
|
||||
a : 1,
|
||||
b : "One"
|
||||
},
|
||||
|
||||
{
|
||||
_id : "138663/2762471",
|
||||
_rev : 2762471,
|
||||
a : 4,
|
||||
b : "Four"
|
||||
}
|
||||
]
|
|
@ -0,0 +1,44 @@
|
|||
[
|
||||
{
|
||||
_id : "154092/301894631",
|
||||
_rev : 301894631,
|
||||
work : {
|
||||
b : -70,
|
||||
l : -30
|
||||
},
|
||||
name : "Name/-70/-30",
|
||||
home : [
|
||||
-70,
|
||||
-30
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
_id : "154092/305433575",
|
||||
_rev : 305433575,
|
||||
work : {
|
||||
b : -60,
|
||||
l : 140
|
||||
},
|
||||
name : "Name/-60/140",
|
||||
home : [
|
||||
-60,
|
||||
140
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
_id : "154092/314215399",
|
||||
_rev : 314215399,
|
||||
work : {
|
||||
b : -20,
|
||||
l : 0
|
||||
},
|
||||
name : "Name/-20/0",
|
||||
home : [
|
||||
-20,
|
||||
0
|
||||
]
|
||||
},
|
||||
...
|
||||
]
|
|
@ -206,7 +206,7 @@ ALIASES += CMDOPT{1}="<tt><b>\1</b></tt>"
|
|||
ALIASES += CA{1}="<var>\1</var>"
|
||||
ALIASES += CO{1}="<tt>\1</tt>"
|
||||
ALIASES += REST{1}="<tt><b>\1</b></tt>"
|
||||
ALIASES += GE{1}="<tt><b>\1</b></tt>"
|
||||
ALIASES += GE{1}="<b>\1</b>"
|
||||
ALIASES += EXAMPLES="<b>Examples</b><br>"
|
||||
|
||||
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
|
||||
|
@ -689,7 +689,8 @@ EXCLUDE_SYMBOLS =
|
|||
EXAMPLE_PATH = \
|
||||
@srcdir@/Doxygen/Examples.AvocadoDB \
|
||||
@srcdir@/Doxygen/Examples.Durham \
|
||||
@srcdir@/Doxygen/Examples.Fyn
|
||||
@srcdir@/Doxygen/Examples.Fyn \
|
||||
@srcdir@/Demos/Scripts
|
||||
|
||||
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
|
||||
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
|
||||
|
|
|
@ -124,9 +124,6 @@ static bool isEqualJsonJson (const TRI_json_t* left, const TRI_json_t* right) {
|
|||
|
||||
|
||||
static bool isEqualShapedJsonShapedJson (const TRI_shaped_json_t* left, const TRI_shaped_json_t* right) {
|
||||
|
||||
int result;
|
||||
|
||||
if (left == NULL && right == NULL) {
|
||||
return true;
|
||||
}
|
||||
|
@ -478,7 +475,6 @@ static bool isMultiEqualElementElement (struct TRI_multi_array_s* multiArray,
|
|||
void* leftElement, void* rightElement) {
|
||||
HashIndexElement* hLeftElement = (HashIndexElement*)(leftElement);
|
||||
HashIndexElement* hRightElement = (HashIndexElement*)(rightElement);
|
||||
int result;
|
||||
|
||||
if (leftElement == NULL || rightElement == NULL) {
|
||||
return false;
|
||||
|
@ -495,7 +491,6 @@ static bool isMultiEqualKeyElement (struct TRI_multi_array_s* multiArray,
|
|||
void* leftElement, void* rightElement) {
|
||||
HashIndexElement* hLeftElement = (HashIndexElement*)(leftElement);
|
||||
HashIndexElement* hRightElement = (HashIndexElement*)(rightElement);
|
||||
int result;
|
||||
size_t j;
|
||||
|
||||
if (leftElement == NULL || rightElement == NULL) {
|
||||
|
|
|
@ -440,8 +440,6 @@ static void OutputMachine (string const& text, LoggerData::Info const& info) {
|
|||
}
|
||||
}
|
||||
|
||||
line.appendChar('\0');
|
||||
|
||||
TRI_RawLog(info._level, info._severity, line.c_str(), line.length() - 1);
|
||||
|
||||
line.free();
|
||||
|
|
|
@ -139,7 +139,7 @@ avocado_SOURCES = \
|
|||
QL/parser.c \
|
||||
QL/tokens.c \
|
||||
RestHandler/RestActionHandler.cpp \
|
||||
RestHandler/RestCollectionHandler.cpp \
|
||||
RestHandler/RestDocumentHandler.cpp \
|
||||
RestHandler/RestVocbaseBaseHandler.cpp \
|
||||
RestServer/ActionDispatcherThread.cpp \
|
||||
RestServer/AvocadoHttpServer.cpp \
|
||||
|
@ -294,6 +294,7 @@ WIKI = \
|
|||
Doxygen/xml/CommandLineScheduler.md \
|
||||
Doxygen/xml/Compiling.md \
|
||||
Doxygen/xml/DefineAction.md \
|
||||
Doxygen/xml/ExamplesSetup.md \
|
||||
Doxygen/xml/Glossary.md \
|
||||
Doxygen/xml/Graphs.md \
|
||||
Doxygen/xml/HttpInterface.md \
|
||||
|
|
11
Makefile.in
11
Makefile.in
|
@ -241,7 +241,7 @@ am_avocado_OBJECTS = Admin/ApplicationAdminServer.$(OBJEXT) \
|
|||
QL/formatter.$(OBJEXT) QL/optimize.$(OBJEXT) \
|
||||
QL/parser.$(OBJEXT) QL/tokens.$(OBJEXT) \
|
||||
RestHandler/RestActionHandler.$(OBJEXT) \
|
||||
RestHandler/RestCollectionHandler.$(OBJEXT) \
|
||||
RestHandler/RestDocumentHandler.$(OBJEXT) \
|
||||
RestHandler/RestVocbaseBaseHandler.$(OBJEXT) \
|
||||
RestServer/ActionDispatcherThread.$(OBJEXT) \
|
||||
RestServer/AvocadoHttpServer.$(OBJEXT) \
|
||||
|
@ -687,7 +687,7 @@ avocado_SOURCES = \
|
|||
QL/parser.c \
|
||||
QL/tokens.c \
|
||||
RestHandler/RestActionHandler.cpp \
|
||||
RestHandler/RestCollectionHandler.cpp \
|
||||
RestHandler/RestDocumentHandler.cpp \
|
||||
RestHandler/RestVocbaseBaseHandler.cpp \
|
||||
RestServer/ActionDispatcherThread.cpp \
|
||||
RestServer/AvocadoHttpServer.cpp \
|
||||
|
@ -823,6 +823,7 @@ WIKI = \
|
|||
Doxygen/xml/CommandLineScheduler.md \
|
||||
Doxygen/xml/Compiling.md \
|
||||
Doxygen/xml/DefineAction.md \
|
||||
Doxygen/xml/ExamplesSetup.md \
|
||||
Doxygen/xml/Glossary.md \
|
||||
Doxygen/xml/Graphs.md \
|
||||
Doxygen/xml/HttpInterface.md \
|
||||
|
@ -1426,7 +1427,7 @@ RestHandler/$(DEPDIR)/$(am__dirstamp):
|
|||
@: > RestHandler/$(DEPDIR)/$(am__dirstamp)
|
||||
RestHandler/RestActionHandler.$(OBJEXT): RestHandler/$(am__dirstamp) \
|
||||
RestHandler/$(DEPDIR)/$(am__dirstamp)
|
||||
RestHandler/RestCollectionHandler.$(OBJEXT): \
|
||||
RestHandler/RestDocumentHandler.$(OBJEXT): \
|
||||
RestHandler/$(am__dirstamp) \
|
||||
RestHandler/$(DEPDIR)/$(am__dirstamp)
|
||||
RestHandler/RestVocbaseBaseHandler.$(OBJEXT): \
|
||||
|
@ -1713,7 +1714,7 @@ mostlyclean-compile:
|
|||
-rm -f Rest/SslInterface.$(OBJEXT)
|
||||
-rm -f Rest/Url.$(OBJEXT)
|
||||
-rm -f RestHandler/RestActionHandler.$(OBJEXT)
|
||||
-rm -f RestHandler/RestCollectionHandler.$(OBJEXT)
|
||||
-rm -f RestHandler/RestDocumentHandler.$(OBJEXT)
|
||||
-rm -f RestHandler/RestVocbaseBaseHandler.$(OBJEXT)
|
||||
-rm -f RestServer/ActionDispatcherThread.$(OBJEXT)
|
||||
-rm -f RestServer/AvocadoHttpServer.$(OBJEXT)
|
||||
|
@ -1910,7 +1911,7 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@Rest/$(DEPDIR)/SslInterface.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@Rest/$(DEPDIR)/Url.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@RestHandler/$(DEPDIR)/RestActionHandler.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@RestHandler/$(DEPDIR)/RestCollectionHandler.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@RestHandler/$(DEPDIR)/RestDocumentHandler.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@RestHandler/$(DEPDIR)/RestVocbaseBaseHandler.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@RestServer/$(DEPDIR)/ActionDispatcherThread.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@RestServer/$(DEPDIR)/AvocadoHttpServer.Po@am__quote@
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
/// @author Copyright 2010-2012, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RestCollectionHandler.h"
|
||||
#include "RestDocumentHandler.h"
|
||||
|
||||
#include "Basics/StringUtils.h"
|
||||
#include "BasicsC/string-buffer.h"
|
||||
|
@ -51,7 +51,7 @@ using namespace triagens::avocado;
|
|||
/// @brief constructor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
RestCollectionHandler::RestCollectionHandler (HttpRequest* request, TRI_vocbase_t* vocbase)
|
||||
RestDocumentHandler::RestDocumentHandler (HttpRequest* request, TRI_vocbase_t* vocbase)
|
||||
: RestVocbaseBaseHandler(request, vocbase) {
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ RestCollectionHandler::RestCollectionHandler (HttpRequest* request, TRI_vocbase_
|
|||
/// {@inheritDoc}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool RestCollectionHandler::isDirect () {
|
||||
bool RestDocumentHandler::isDirect () {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -80,7 +80,7 @@ bool RestCollectionHandler::isDirect () {
|
|||
/// {@inheritDoc}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
string const& RestCollectionHandler::queue () {
|
||||
string const& RestDocumentHandler::queue () {
|
||||
static string const client = "CLIENT";
|
||||
|
||||
return client;
|
||||
|
@ -90,7 +90,7 @@ string const& RestCollectionHandler::queue () {
|
|||
/// {@inheritDoc}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
HttpHandler::status_e RestCollectionHandler::execute () {
|
||||
HttpHandler::status_e RestDocumentHandler::execute () {
|
||||
|
||||
// extract the sub-request type
|
||||
HttpRequest::HttpRequestType type = request->requestType();
|
||||
|
@ -160,7 +160,7 @@ HttpHandler::status_e RestCollectionHandler::execute () {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief creates a document
|
||||
///
|
||||
/// @REST{POST /collection/@FA{collection-identifier}}
|
||||
/// @REST{POST /document?collection=@FA{collection-identifier}}
|
||||
///
|
||||
/// Creates a new document in the collection identified by the
|
||||
/// @FA{collection-identifier}. A JSON representation of the document must be
|
||||
|
@ -168,21 +168,27 @@ HttpHandler::status_e RestCollectionHandler::execute () {
|
|||
///
|
||||
/// If the document was created successfully, then a @LIT{HTTP 201} is returned
|
||||
/// and the "Location" header contains the path to the newly created
|
||||
/// document. The "ETag" header field contains the revision of the newly created
|
||||
/// document.
|
||||
/// document. The "ETag" header field contains the revision of the document.
|
||||
///
|
||||
/// The body of the response contains a JSON object with the same information.
|
||||
/// The attribute @LIT{_id} contains the document handle of the newly created
|
||||
/// document, the attribute @LIT{_rev} contains the document revision.
|
||||
///
|
||||
/// If the collection parameter @LIT{waitForSync} is @LIT{false}, then a
|
||||
/// @LIT{HTTP 202} is returned in order to indicate that the document has been
|
||||
/// accepted but not yet stored.
|
||||
///
|
||||
/// If the @FA{collection-identifier} is unknown, then a @LIT{HTTP 404} is
|
||||
/// returned.
|
||||
/// returned and the body of the response contains an error document.
|
||||
///
|
||||
/// If the body does not contain a valid JSON representation of an document,
|
||||
/// then a @LIT{HTTP 400} is returned.
|
||||
/// then a @LIT{HTTP 400} is returned and the body of the response contains
|
||||
/// an error document.
|
||||
///
|
||||
/// Instead of a @FA{collection-identifier}, a collection name can be
|
||||
/// given.
|
||||
/// @REST{POST /document?collection=@FA{collection-identifier}&createCollection=@FA{create}}
|
||||
///
|
||||
/// Instead of a @FA{collection-identifier}, a collection name can be used. If
|
||||
/// @FA{create} is true, then the collection is created if it does not exists.
|
||||
///
|
||||
/// @EXAMPLES
|
||||
///
|
||||
|
@ -203,7 +209,7 @@ HttpHandler::status_e RestCollectionHandler::execute () {
|
|||
/// @verbinclude rest6
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool RestCollectionHandler::createDocument () {
|
||||
bool RestDocumentHandler::createDocument () {
|
||||
vector<string> const& suffix = request->suffix();
|
||||
|
||||
if (suffix.size() != 1) {
|
||||
|
@ -277,16 +283,16 @@ bool RestCollectionHandler::createDocument () {
|
|||
/// Either readSingleDocument or readAllDocuments.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool RestCollectionHandler::readDocument () {
|
||||
bool RestDocumentHandler::readDocument () {
|
||||
switch (request->suffix().size()) {
|
||||
case 1:
|
||||
case 0:
|
||||
return readAllDocuments();
|
||||
|
||||
case 2:
|
||||
case 1:
|
||||
return readSingleDocument(true);
|
||||
|
||||
default:
|
||||
generateError(HttpResponse::BAD, "superfluous identifier");
|
||||
generateError(HttpResponse::BAD, "expecting URI /document/<document-handle>");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -294,26 +300,18 @@ bool RestCollectionHandler::readDocument () {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief reads a single document
|
||||
///
|
||||
/// @REST{GET /collection/@FA{collection-identifier}/@FA{document-identifier}}
|
||||
/// @REST{GET /document/@FA{document-handle}}
|
||||
///
|
||||
/// Returns the document identified by @FA{document-identifier} from the
|
||||
/// collection identified by @FA{collection-identifier}.
|
||||
/// Returns the document identified by @FA{document-handle}. The returned
|
||||
/// document contains two special attributes: @LIT{_id} containing the document
|
||||
/// handle and @LIT{_rev} containing the revision.
|
||||
///
|
||||
/// If the document exists, then a @LIT{HTTP 200} is returned and the JSON
|
||||
/// representation of the document is the body of the response.
|
||||
///
|
||||
/// If the collection identifier points to a non-existing collection, then a
|
||||
/// If the @FA{document-handle} points to a non-existing document, then a
|
||||
/// @LIT{HTTP 404} is returned and the body contains an error document.
|
||||
///
|
||||
/// If the document identifier points to a non-existing document, then a
|
||||
/// @LIT{HTTP 404} is returned and the body contains an error document.
|
||||
///
|
||||
/// Instead of a @FA{document-identifier}, a document reference can be given. A
|
||||
/// @LIT{HTTP 400} is returned, if there is a mismatch between the
|
||||
/// @FA{collection-identifier} and the @FA{document-reference}.
|
||||
///
|
||||
/// Instead of a @FA{collection-identifier}, a collection name can be given.
|
||||
///
|
||||
/// @EXAMPLES
|
||||
///
|
||||
/// Use a collection and document identfier:
|
||||
|
@ -333,19 +331,21 @@ bool RestCollectionHandler::readDocument () {
|
|||
/// @verbinclude rest17
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool RestCollectionHandler::readSingleDocument (bool generateBody) {
|
||||
bool RestDocumentHandler::readSingleDocument (bool generateBody) {
|
||||
vector<string> const& suffix = request->suffix();
|
||||
|
||||
// find and load collection given by name oder identifier
|
||||
bool ok = findCollection(suffix[0]) && loadCollection();
|
||||
// split the document reference
|
||||
string cid;
|
||||
string did;
|
||||
|
||||
bool ok = splitDocumentReference(suffix[0], cid, did);
|
||||
|
||||
if (! ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// split the document reference
|
||||
string did;
|
||||
ok = splitDocumentReference(suffix[1], did);
|
||||
// find and load collection given by name oder identifier
|
||||
bool ok = findCollection(cid) && loadCollection();
|
||||
|
||||
if (! ok) {
|
||||
return false;
|
||||
|
@ -366,7 +366,7 @@ bool RestCollectionHandler::readSingleDocument (bool generateBody) {
|
|||
// .............................................................................
|
||||
|
||||
if (document == 0) {
|
||||
generateDocumentNotFound(suffix[0], did);
|
||||
generateDocumentNotFound(suffix[0]);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -377,10 +377,10 @@ bool RestCollectionHandler::readSingleDocument (bool generateBody) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief reads all documents
|
||||
///
|
||||
/// @REST{GET /collection/@FA{collection-identifier}}
|
||||
/// @REST{GET /document?collection=@FA{collection-identifier}}
|
||||
///
|
||||
/// Returns the URI for all documents from the collection identified by
|
||||
/// @FA{collection-identifier}.
|
||||
/// Returns a list of all URI for all documents from the collection identified
|
||||
/// by @FA{collection-identifier}.
|
||||
///
|
||||
/// Instead of a @FA{collection-identifier}, a collection name can be given.
|
||||
///
|
||||
|
@ -389,7 +389,7 @@ bool RestCollectionHandler::readSingleDocument (bool generateBody) {
|
|||
/// @verbinclude rest20
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool RestCollectionHandler::readAllDocuments () {
|
||||
bool RestDocumentHandler::readAllDocuments () {
|
||||
vector<string> const& suffix = request->suffix();
|
||||
|
||||
// find and load collection given by name oder identifier
|
||||
|
@ -470,48 +470,64 @@ bool RestCollectionHandler::readAllDocuments () {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief reads a single document head
|
||||
///
|
||||
/// @REST{HEAD /collection/@FA{collection-identifier}/@FA{document-identifier}}
|
||||
/// @REST{HEAD /document/@FA{document-handle}}
|
||||
///
|
||||
/// Like @FN{GET}, but does not return the body.
|
||||
/// Like @FN{GET}, but only returns the header fields and not the body. You
|
||||
/// can use this call to get the current revision of a document or check if
|
||||
/// the document was deleted.
|
||||
///
|
||||
/// @EXAMPLES
|
||||
///
|
||||
/// @verbinclude rest19
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool RestCollectionHandler::checkDocument () {
|
||||
return readSingleDocument(false);
|
||||
bool RestDocumentHandler::checkDocument () {
|
||||
if (suffix.size() != 1) {
|
||||
generateError(HttpResponse::BAD, "expecting URI /document/<document-handle>");
|
||||
return false;
|
||||
}
|
||||
|
||||
return readDocument(false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief updates a document
|
||||
///
|
||||
/// @REST{PUT /collection/@FA{collection-identifier}/@FA{document-identifier}}
|
||||
/// @REST{PUT /document/@FA{document-handle}}
|
||||
///
|
||||
/// Updates the document identified by @FA{document-identifier} in the
|
||||
/// collection identified by @FA{collection-identifier}. If the document exists
|
||||
/// and could be updated, then a @LIT{HTTP 201} is returned and the "ETag"
|
||||
/// header field contains the new revision of the document.
|
||||
/// Updates the document identified by @FA{document-handle}. If the document exists
|
||||
/// and can be updated, then a @LIT{HTTP 201} is returned and the "ETag" header
|
||||
/// field contains the new revision of the document.
|
||||
///
|
||||
/// If the document does not exists, then a @LIT{HTTP 404} is returned.
|
||||
/// Note the updated document passed in the body of the request normally also
|
||||
/// contains the @FA{document-handle} in the attribute @LIT{_id} and the
|
||||
/// revision in @LIT{_rev}. These attributes, however, are ignored. Only the URI
|
||||
/// and the "ETag" header are relevant in order to avoid confusion when using
|
||||
/// proxies.
|
||||
///
|
||||
/// If an etag is supplied in the "ETag" field, then the AvocadoDB checks that
|
||||
/// the revision of the document is equal to the etag. If there is a mismatch,
|
||||
/// then a @LIT{HTTP 409} conflict is returned and no update is performed.
|
||||
/// The body of the response contains a JSON object with the information about
|
||||
/// the handle and the revision. The attribute @LIT{_id} contains the known
|
||||
/// @FA{document-handle} of the updated document, the attribute @LIT{_rev}
|
||||
/// contains the new document revision.
|
||||
///
|
||||
/// Instead of a @FA{document-identifier}, a document reference can be given.
|
||||
/// If the document does not exists, then a @LIT{HTTP 404} is returned and the
|
||||
/// body of the response contains an error document.
|
||||
///
|
||||
/// Instead of a @FA{collection-identifier}, a collection name can be given.
|
||||
/// If an etag is supplied in the "If-Match" header field, then the AvocadoDB
|
||||
/// checks that the revision of the document is equal to the etag. If there is a
|
||||
/// mismatch, then a @LIT{HTTP 409} conflict is returned and no update is
|
||||
/// performed.
|
||||
///
|
||||
/// @REST{PUT /collection/@FA{collection-identifier}/@FA{document-identifier}?policy=@FA{policy}}
|
||||
/// @REST{PUT /document/@FA{document-handle}?policy=@FA{policy}}
|
||||
///
|
||||
/// As before, if @FA{policy} is @LIT{error}. If @FA{policy} is @LIT{last},
|
||||
/// then the last write will win.
|
||||
///
|
||||
/// @REST{PUT /collection/@FA{collection-identifier}/@FA{document-identifier}?_rev=@FA{etag}}
|
||||
/// @REST{PUT /document/@FA{collection-identifier}/@FA{document-identifier}?rev=@FA{etag}}
|
||||
///
|
||||
/// You can also supply the etag using the parameter "_rev" instead of an "ETag"
|
||||
/// header.
|
||||
/// You can also supply the etag using the parameter @LIT{rev} instead of an "ETag"
|
||||
/// header. You must never supply both the "ETag" header and the @LIT{rev}
|
||||
/// parameter.
|
||||
///
|
||||
/// @EXAMPLES
|
||||
///
|
||||
|
@ -536,7 +552,7 @@ bool RestCollectionHandler::checkDocument () {
|
|||
/// @verbinclude rest11
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool RestCollectionHandler::updateDocument () {
|
||||
bool RestDocumentHandler::updateDocument () {
|
||||
vector<string> const& suffix = request->suffix();
|
||||
|
||||
// find and load collection given by name oder identifier
|
||||
|
@ -615,31 +631,35 @@ bool RestCollectionHandler::updateDocument () {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief deletes a document
|
||||
///
|
||||
/// @REST{DELETE /collection/@FA{collection-identifier}/@FA{document-identifier}}
|
||||
/// @REST{DELETE /document/@FA{document-handle}}
|
||||
///
|
||||
/// Deletes the document identified by @FA{document-identifier} from the
|
||||
/// collection identified by @FA{collection-identifier}. If the document exists
|
||||
/// and could be deleted, then a @LIT{HTTP 204} is returned.
|
||||
/// Deletes the document identified by @FA{document-handle} from the collection
|
||||
/// identified by @FA{collection-identifier}. If the document exists and could
|
||||
/// be deleted, then a @LIT{HTTP 204} is returned.
|
||||
///
|
||||
/// If the document does not exists, then a @LIT{HTTP 404} is returned.
|
||||
/// The body of the response contains a JSON object with the information about
|
||||
/// the handle and the revision. The attribute @LIT{_id} contains the known
|
||||
/// @FA{document-handle} of the updated document, the attribute @LIT{_rev}
|
||||
/// contains the known document revision.
|
||||
///
|
||||
/// If an etag is supplied in the "ETag" field, then the AvocadoDB checks that
|
||||
/// the revision of the document is equal to the etag. If there is a mismatch,
|
||||
/// then a @LIT{HTTP 409} conflict is returned and no delete is performed.
|
||||
/// If the document does not exists, then a @LIT{HTTP 404} is returned and the
|
||||
/// body of the response contains an error document.
|
||||
///
|
||||
/// Instead of a @FA{document-identifier}, a document reference can be given.
|
||||
/// If an etag is supplied in the "If-Match" field, then the AvocadoDB checks
|
||||
/// that the revision of the document is equal to the tag. If there is a
|
||||
/// mismatch, then a @LIT{HTTP 409} conflict is returned and no delete is
|
||||
/// performed.
|
||||
///
|
||||
/// Instead of a @FA{collection-identifier}, a collection name can be given.
|
||||
///
|
||||
/// @REST{DELETE /collection/@FA{collection-identifier}/@FA{document-identifier}?policy=@FA{policy}}
|
||||
/// @REST{DELETE /document/@FA{document-handle}?policy=@FA{policy}}
|
||||
///
|
||||
/// As before, if @FA{policy} is @LIT{error}. If @FA{policy} is @LIT{last}, then
|
||||
/// the last write will win.
|
||||
///
|
||||
/// @REST{DELETE /collection/@FA{collection-identifier}/@FA{document-identifier}? _rev=@FA{etag}}
|
||||
/// @REST{DELETE /document/@FA{document-handle}?rev=@FA{etag}}
|
||||
///
|
||||
/// You can also supply the etag using the parameter "_rev" instead of an "ETag"
|
||||
/// header.
|
||||
/// You can also supply the etag using the parameter @LIT{rev} instead of an "ETag"
|
||||
/// header. You must never supply both the "ETag" header and the @LIT{rev}
|
||||
/// parameter.
|
||||
///
|
||||
/// @EXAMPLES
|
||||
///
|
||||
|
@ -656,7 +676,7 @@ bool RestCollectionHandler::updateDocument () {
|
|||
/// @verbinclude rest12
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool RestCollectionHandler::deleteDocument () {
|
||||
bool RestDocumentHandler::deleteDocument () {
|
||||
vector<string> suffix = request->suffix();
|
||||
|
||||
// find and load collection given by name oder identifier
|
|
@ -31,7 +31,7 @@
|
|||
#include "RestHandler/RestVocbaseBaseHandler.h"
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- RestCollectionHandler
|
||||
// --SECTION-- RestDocumentHandler
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -46,7 +46,7 @@ namespace triagens {
|
|||
/// @brief collection request handler
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class RestCollectionHandler : public RestVocbaseBaseHandler {
|
||||
class RestDocumentHandler : public RestVocbaseBaseHandler {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
|
@ -67,7 +67,7 @@ namespace triagens {
|
|||
/// @brief constructor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
RestCollectionHandler (rest::HttpRequest* request, struct TRI_vocbase_s* vocbase);
|
||||
RestDocumentHandler (rest::HttpRequest* request, struct TRI_vocbase_s* vocbase);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
|
@ -73,7 +73,7 @@ LoggerData::Extra const RestVocbaseBaseHandler::RES_FAIL;
|
|||
/// @brief document path
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
string RestVocbaseBaseHandler::DOCUMENT_PATH = "/collection";
|
||||
string RestVocbaseBaseHandler::DOCUMENT_PATH = "/document";
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief collection path
|
||||
|
@ -220,17 +220,20 @@ void RestVocbaseBaseHandler::generateDocument (TRI_doc_mptr_t const* document,
|
|||
TRI_string_buffer_t buffer;
|
||||
|
||||
if (generateDocument) {
|
||||
string id = StringUtils::itoa(_documentCollection->base._cid) + ":" + StringUtils::itoa(document->_did);
|
||||
string id = StringUtils::itoa(_documentCollection->base._cid) + TRI_DOCUMENT_HANDLE_SEPARATOR_STR + StringUtils::itoa(document->_did);
|
||||
|
||||
TRI_json_t augmented;
|
||||
|
||||
TRI_InitArrayJson(&augmented);
|
||||
|
||||
TRI_json_t* _id = TRI_CreateStringCopyJson(id.c_str());
|
||||
TRI_json_t* _rev = TRI_CreateNumberJson(document->_rid);
|
||||
|
||||
if (_id) {
|
||||
TRI_Insert2ArrayJson(&augmented, "_id", _id);
|
||||
}
|
||||
|
||||
TRI_json_t* _rev = TRI_CreateNumberJson(document->_rid);
|
||||
|
||||
if (_rev) {
|
||||
TRI_Insert2ArrayJson(&augmented, "_rev", _rev);
|
||||
}
|
||||
|
@ -266,7 +269,7 @@ void RestVocbaseBaseHandler::generateDocument (TRI_doc_mptr_t const* document,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool RestVocbaseBaseHandler::splitDocumentReference (string const& name, string& did) {
|
||||
vector<string> doc = StringUtils::split(name, ":");
|
||||
vector<string> doc = StringUtils::split(name, TRI_DOCUMENT_HANDLE_SEPARATOR_STR);
|
||||
|
||||
switch (doc.size()) {
|
||||
case 1:
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
#include "Logger/Logger.h"
|
||||
#include "Rest/Initialise.h"
|
||||
#include "RestHandler/RestActionHandler.h"
|
||||
#include "RestHandler/RestCollectionHandler.h"
|
||||
#include "RestHandler/RestDocumentHandler.h"
|
||||
#include "RestServer/ActionDispatcherThread.h"
|
||||
#include "RestServer/AvocadoHttpServer.h"
|
||||
#include "V8/JSLoader.h"
|
||||
|
@ -548,7 +548,7 @@ int AvocadoServer::startupServer () {
|
|||
|
||||
_applicationAdminServer->addBasicHandlers(factory);
|
||||
|
||||
factory->addPrefixHandler(RestVocbaseBaseHandler::DOCUMENT_PATH, RestHandlerCreator<RestCollectionHandler>::createData<TRI_vocbase_t*>, _vocbase);
|
||||
factory->addPrefixHandler(RestVocbaseBaseHandler::DOCUMENT_PATH, RestHandlerCreator<RestDocumentHandler>::createData<TRI_vocbase_t*>, _vocbase);
|
||||
factory->addPrefixHandler("/", RestHandlerCreator<RestActionHandler>::createData<TRI_vocbase_t*>, _vocbase);
|
||||
|
||||
_httpServer = _applicationHttpServer->buildServer(new AvocadoHttpServer(scheduler, dispatcher), factory, ports);
|
||||
|
@ -567,7 +567,7 @@ int AvocadoServer::startupServer () {
|
|||
_applicationAdminServer->addBasicHandlers(adminFactory);
|
||||
_applicationAdminServer->addHandlers(adminFactory, "/admin");
|
||||
|
||||
adminFactory->addPrefixHandler(RestVocbaseBaseHandler::DOCUMENT_PATH, RestHandlerCreator<RestCollectionHandler>::createData<TRI_vocbase_t*>, _vocbase);
|
||||
adminFactory->addPrefixHandler(RestVocbaseBaseHandler::DOCUMENT_PATH, RestHandlerCreator<RestDocumentHandler>::createData<TRI_vocbase_t*>, _vocbase);
|
||||
adminFactory->addPrefixHandler("/", RestHandlerCreator<RestActionHandler>::createData<TRI_vocbase_t*>, _vocbase);
|
||||
|
||||
_adminHttpServer = _applicationHttpServer->buildServer(adminFactory, adminPorts);
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief over the wire protocol
|
||||
///
|
||||
/// @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 ExamplesSetup Preparing the Examples
|
||||
///
|
||||
/// All examples in the manuals assume that you have created the following
|
||||
/// collections:
|
||||
///
|
||||
/// - demo
|
||||
/// - five
|
||||
/// - geo
|
||||
///
|
||||
/// Some of the examples may destroy the collection. In that case you can
|
||||
/// use one of the following script to restore the collection.
|
||||
///
|
||||
/// @LIT{examples.js}: A JavaScript script usable within the AvocadoDB shell to
|
||||
/// regenerate the above collections.
|
||||
///
|
||||
/// @LIT{examples.sh}: A shell script using curl to setup the collections. The
|
||||
/// script works without any additional client, but will not be able to detect
|
||||
/// any errors.
|
||||
///
|
||||
/// @section ExamplesSetupDemo Collection "Demo"
|
||||
////////////////////////////////////////////////
|
||||
///
|
||||
/// @verbinclude demo1
|
||||
///
|
||||
/// was generated by
|
||||
///
|
||||
/// @verbinclude demo.js
|
||||
///
|
||||
/// @section ExamplesSetupFive Collection "five"
|
||||
////////////////////////////////////////////////
|
||||
///
|
||||
/// The collection "five" has a unique constraint on the attribute @LIT{a},
|
||||
/// and a second unique constraint on the attribute @LIT{b}.
|
||||
///
|
||||
/// @verbinclude five1
|
||||
///
|
||||
/// was generated by
|
||||
///
|
||||
/// @verbinclude five.js
|
||||
///
|
||||
/// @section ExamplesSetupGeo Collection "geo"
|
||||
//////////////////////////////////////////////
|
||||
///
|
||||
/// The collection "geo" has two geo fields, one @LIT{home} being a list with
|
||||
/// two elements, one @LIT{work} being an hash array with latitude @LIT{b} and
|
||||
/// longitude @LIT{l}.
|
||||
///
|
||||
/// @verbinclude geojs1
|
||||
///
|
||||
/// was generated by
|
||||
///
|
||||
/// @verbinclude geo.js
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Local Variables:
|
||||
// mode: c++
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @\\}\\)"
|
||||
// End:
|
|
@ -29,8 +29,13 @@
|
|||
/// @page Glossary
|
||||
///
|
||||
/// @copydoc GlossaryCollectionIdentifier
|
||||
///
|
||||
/// @copydoc GlossaryDocument
|
||||
///
|
||||
/// @copydoc GlossaryDocumentHandle
|
||||
/// @cooydoc GlossaryDocumentIdentifier
|
||||
///
|
||||
/// @copydoc GlossaryDocumentIdentifier
|
||||
///
|
||||
/// @copydoc GlossaryDocumentRevision
|
||||
///
|
||||
/// @page GlossaryCollectionIdentifier
|
||||
|
@ -38,6 +43,11 @@
|
|||
/// @GE{Collection Identifier}: A collection identifier identifies a collection
|
||||
/// in a database. It is an integer and is unique within the database.
|
||||
///
|
||||
/// @page GlossaryDocument
|
||||
///
|
||||
/// @GE{Document}: Documents in AvocadoDB are JSON objects. These objects can be
|
||||
/// nested (to any depth) and may contains lists.
|
||||
///
|
||||
/// @page GlossaryDocumentHandle
|
||||
///
|
||||
/// @GE{Document Handle}: A document handle uniquely identifies a document in
|
||||
|
@ -47,7 +57,7 @@
|
|||
/// @page GlossaryDocumentIdentifier
|
||||
///
|
||||
/// @GE{Document Identifier}: A document identifier identifies a document in a
|
||||
/// database. It is an integer and is unique within the collection of the
|
||||
/// given collection. It is an integer and is unique within the collection of the
|
||||
/// document.
|
||||
///
|
||||
/// @page GlossaryDocumentRevision
|
||||
|
|
|
@ -0,0 +1,208 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief statements and cursors
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2010-2012 triagens GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Achim Brandt
|
||||
/// @author Copyright 2012, triagens GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @page Key-Value REST Interface for storing key-value pairs
|
||||
///
|
||||
/// @section Key-ValueCreate Create a new key-value pair in the data store.
|
||||
///
|
||||
/// Creates a new key-value pair with the given key, the data passed in content
|
||||
/// and optional attributes passed in the header.
|
||||
/// If a key-value pair with the same key exists in the data store, the request
|
||||
/// returns an error.
|
||||
///
|
||||
/// @anchor Key-ValuePost
|
||||
/// @REST{POST /_api/key/@FA{collection-name}/@FA{key}}
|
||||
///
|
||||
/// Optional Attributes:
|
||||
/// - @LIT{x-voc-expires} Expiry-date for this key-value pair.
|
||||
/// - @LIT{x-voc-extended} A JSON-object of one or more attributes to be attached
|
||||
/// to the key-value pair.
|
||||
/// - TODO @LIT{binary data}
|
||||
///
|
||||
/// If the document was created successfully, then a @LIT{HTTP 201} is returned.
|
||||
///
|
||||
/// If the @FA{collection-name} is unknown, then a @LIT{HTTP 404} is
|
||||
/// returned.
|
||||
///
|
||||
/// If the @FA{key} is used, then a @LIT{HTTP 404} is returned.
|
||||
///
|
||||
/// @EXAMPLES
|
||||
///
|
||||
/// Create a key-value pair
|
||||
///
|
||||
/// @verbinclude key-value_post-key-request
|
||||
///
|
||||
/// Response (Success)
|
||||
///
|
||||
/// @verbinclude key-value_post-key-ok
|
||||
///
|
||||
/// Response (Failure)
|
||||
///
|
||||
/// @verbinclude key-value_post-key-bad
|
||||
///
|
||||
///
|
||||
///
|
||||
/// @section Key-ValueChange Creates or changes the value for a given key.
|
||||
///
|
||||
/// Sets the value associated with key to the new data passed in content.
|
||||
///
|
||||
/// @anchor Key-ValuePut
|
||||
/// @REST{PUT /_api/key/@FA{collection-name}/@FA{key}}
|
||||
///
|
||||
/// Optional parameter:
|
||||
/// - @LIT{?create=1} When set to 1 database will create keys if they do not
|
||||
/// exist. When set to 0 (default) it will return an error if a key does not
|
||||
/// exist.
|
||||
///
|
||||
/// If the document was updated successfully, then a @LIT{HTTP 202} is returned.
|
||||
///
|
||||
/// If the @FA{collection-name} is unknown, then a @LIT{HTTP 404} is
|
||||
/// returned.
|
||||
///
|
||||
/// If the @FA{key} is not found and @LIT{?create=0}, then a @LIT{HTTP 404} is
|
||||
/// returned.
|
||||
///
|
||||
/// @EXAMPLES
|
||||
///
|
||||
/// Update a key-value pair
|
||||
///
|
||||
/// @verbinclude key-value_put-key-request
|
||||
///
|
||||
/// Response (Success)
|
||||
///
|
||||
/// @verbinclude key-value_put-key-ok
|
||||
///
|
||||
/// Response (Failure)
|
||||
///
|
||||
/// @verbinclude key-value_put-key-bad
|
||||
///
|
||||
///
|
||||
///
|
||||
/// @section Key-ValueReturn Returns the value associated with a given key.
|
||||
///
|
||||
/// Returns the value associated with the key in content. The Attributes of
|
||||
/// the key-value pair are returned in the header.
|
||||
///
|
||||
/// @anchor Key-ValueGet
|
||||
/// @REST{GET /_api/key/@FA{collection-name}/@FA{key}}
|
||||
///
|
||||
/// If the document was found, then a @LIT{HTTP 200} is returned.
|
||||
///
|
||||
/// If the @FA{collection-name} is unknown, then a @LIT{HTTP 404} is
|
||||
/// returned.
|
||||
///
|
||||
/// If the @FA{key} is not found, then a @LIT{HTTP 404} is returned.
|
||||
///
|
||||
/// @EXAMPLES
|
||||
///
|
||||
/// Get a key-value pair
|
||||
///
|
||||
/// @verbinclude key-value_get-key-request
|
||||
///
|
||||
/// Response (Success) with attributes
|
||||
///
|
||||
/// @verbinclude key-value_get-key-ok
|
||||
///
|
||||
/// Response (Failure)
|
||||
///
|
||||
/// @verbinclude key-value_get-key-bad
|
||||
///
|
||||
///
|
||||
///
|
||||
/// @section Key-ValueRemove This function deletes a key-value pair from the data store.
|
||||
///
|
||||
/// Deletes the key-value pair with key from the store.
|
||||
/// Deletions cannot be undone!
|
||||
///
|
||||
/// @anchor Key-ValueDelete
|
||||
/// @REST{DELETE /_api/key/@FA{collection-name}/@FA{key}}
|
||||
///
|
||||
/// This function does not support any header parameters.
|
||||
///
|
||||
/// If the document was found and deleted, then a @LIT{HTTP 200} is returned.
|
||||
///
|
||||
/// If the @FA{collection-name} is unknown, then a @LIT{HTTP 404} is
|
||||
/// returned.
|
||||
///
|
||||
/// If the @FA{key} is not found, then a @LIT{HTTP 404} is returned.
|
||||
///
|
||||
/// @EXAMPLES
|
||||
///
|
||||
/// Delete a key-value pair
|
||||
///
|
||||
/// @verbinclude key-value_delete-key-request
|
||||
///
|
||||
/// Response (Success)
|
||||
///
|
||||
/// @verbinclude key-value_delete-key-ok
|
||||
///
|
||||
/// Response (Failure)
|
||||
///
|
||||
/// @verbinclude key-value_delete-key-bad
|
||||
///
|
||||
///
|
||||
///
|
||||
/// @section Key-ValueLookup This function returns all keys matching a given prefix.
|
||||
///
|
||||
/// Retrieves all values that begin with key and returns them as a JSON-array in
|
||||
/// content.
|
||||
///
|
||||
/// @anchor Key-ValueSearch
|
||||
/// @REST{GET /_api/keys/@FA{collection-name}/@FA{prefix}}
|
||||
///
|
||||
/// @FA{prefix} (=beginning of word) to search for. Note that any /-characters
|
||||
/// contained in key are considered part of the key and have no special meaning.
|
||||
///
|
||||
/// TODO Optional parameter:
|
||||
/// - @LIT{?filter=Filter Expression} Return only those keys that match the given
|
||||
/// filter expression (have certain attributes). Please note that the filter
|
||||
/// expression has to be URL-encoded
|
||||
///
|
||||
/// If the @FA{collection-name} is unknown, then a @LIT{HTTP 404} is
|
||||
/// returned.
|
||||
///
|
||||
/// @EXAMPLES
|
||||
///
|
||||
/// Find keys by prefix
|
||||
///
|
||||
/// @verbinclude key-value_get-keys-request
|
||||
///
|
||||
/// Response (Success)
|
||||
///
|
||||
/// @verbinclude key-value_get-keys-ok
|
||||
///
|
||||
/// Response (Failure)
|
||||
///
|
||||
/// @verbinclude key-value_get-keys-bad
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
|
||||
// End:
|
|
@ -33,12 +33,12 @@
|
|||
/// <ol>
|
||||
/// <li>Documents
|
||||
/// <ol>
|
||||
/// <li>@ref RestCollectionCreate "POST /collection/@FA{collection-identifier}"</li>
|
||||
/// <li>@ref RestCollectionRead "GET /collection/@FA{collection-identifier}/@FA{document-identifier}"</li>
|
||||
/// <li>@ref RestCollectionReadAll "GET /collection/@FA{collection-identifier}"</li>
|
||||
/// <li>@ref RestCollectionUpdate "PUT /collection/@FA{collection-identifier}/@FA{document-identifier}"</li>
|
||||
/// <li>@ref RestCollectionDelete "DELETE /collection/@FA{collection-identifier}/@FA{document-identifier}"</li>
|
||||
/// <li>@ref RestCollectionHead "HEAD /collection/@FA{collection-identifier}/@FA{document-identifier}"</li>
|
||||
/// <li>@ref RestDocumentRead "GET /document/@FA{document-handle}"</li>
|
||||
/// <li>@ref RestDocumentCreate "POST /document/collection=@FA{collection-identifier}"</li>
|
||||
/// <li>@ref RestDocumentUpdate "PUT /document/@FA{document-handle}"</li>
|
||||
/// <li>@ref RestDocumentDelete "DELETE /document/@FA{document-handle}"</li>
|
||||
/// <li>@ref RestDocumentHead "HEAD /document/@FA{document-handle}"</li>
|
||||
/// <li>@ref RestDocumentReadAll "GET /document/collection=@FA{collection-identifier}"</li>
|
||||
/// </ol>
|
||||
/// </li>
|
||||
/// <li>@ref OTWPSimpleQueries
|
||||
|
@ -57,6 +57,15 @@
|
|||
/// <li>@ref RestQueryPost "POST /_api/query"</li>
|
||||
/// </ol>
|
||||
/// </li>
|
||||
/// <li>@ref Key-Value
|
||||
/// <ol>
|
||||
/// <li>@ref Key-ValuePost "POST /_api/key/@FA{collection-name}/@FA{key}"</li>
|
||||
/// <li>@ref Key-ValuePut "PUT /_api/key/@FA{collection-name}/@FA{key}"</li>
|
||||
/// <li>@ref Key-ValueGet "GET /_api/key/@FA{collection-name}/@FA{key}"</li>
|
||||
/// <li>@ref Key-ValueDelete "DELETE /_api/key/@FA{collection-name}/@FA{key}"</li>
|
||||
/// <li>@ref Key-ValueSearch "GET /_api/keys/@FA{collection-name}/@FA{prefix}"</li>
|
||||
/// </ol>
|
||||
/// </li>
|
||||
/// </ol>
|
||||
/// </li>
|
||||
/// <li>@ref OTWPDatabase
|
||||
|
|
|
@ -29,25 +29,44 @@
|
|||
/// @page RestDocumentTOC
|
||||
///
|
||||
/// <ol>
|
||||
/// <li>@ref RestCollectionCreate "POST /collection/@FA{collection-identifier}"</li>
|
||||
/// <li>@ref RestCollectionRead "GET /collection/@FA{collection-identifier}/@FA{document-identifier}"</li>
|
||||
/// <li>@ref RestCollectionReadAll "GET /collection/@FA{collection-identifier}"</li>
|
||||
/// <li>@ref RestCollectionUpdate "PUT /collection/@FA{collection-identifier}/@FA{document-identifier}"</li>
|
||||
/// <li>@ref RestCollectionDelete "DELETE /collection/@FA{collection-identifier}/@FA{document-identifier}"</li>
|
||||
/// <li>@ref RestCollectionHead "HEAD /collection/@FA{collection-identifier}/@FA{document-identifier}"</li>
|
||||
/// <li>@ref RestDocumentIntro</li>
|
||||
/// <li>@ref RestDocumentResource</li>
|
||||
/// <li>@ref RestDocumentHttp
|
||||
/// <ol>
|
||||
/// <li>@ref RestDocumentRead "GET /document/@FA{document-handle}"</li>
|
||||
/// <li>@ref RestDocumentCreate "POST /document/collection=@FA{collection-identifier}"</li>
|
||||
/// <li>@ref RestDocumentUpdate "PUT /document/@FA{document-handle}"</li>
|
||||
/// <li>@ref RestDocumentDelete "DELETE /document/@FA{document-handle}"</li>
|
||||
/// <li>@ref RestDocumentHead "HEAD /document/@FA{document-handle}"</li>
|
||||
/// <li>@ref RestDocumentReadAll "GET /document/collection=@FA{collection-identifier}"</li>
|
||||
/// </ol>
|
||||
/// </li>
|
||||
/// </ol>
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @page RestDocument REST Interface for Documents
|
||||
///
|
||||
/// Documents in AvocadoDB are JSON objects. The objects can be nested to any
|
||||
/// depth and can contains lists, for example:
|
||||
/// This is an introduction to AvocadoDB's REST interface to documents.
|
||||
///
|
||||
/// <hr>
|
||||
/// @copydoc RestDocumentTOC
|
||||
/// <hr>
|
||||
///
|
||||
/// @section RestDocumentIntro Documents, Identifiers, Handles
|
||||
//////////////////////////////////////////////////////////////
|
||||
///
|
||||
/// @copydoc GlossaryDocument
|
||||
///
|
||||
/// For example:
|
||||
///
|
||||
/// @verbinclude document1
|
||||
///
|
||||
/// All documents contain two special fields, the document handle in @LIT{_id}
|
||||
/// and the document revision in @LIT{_rev}.
|
||||
/// and the etag aka document revision in @LIT{_rev}.
|
||||
///
|
||||
/// All examples in the document assume that you have created some example
|
||||
/// collections, see @ref ExamplesSetup.
|
||||
///
|
||||
/// @copydoc GlossaryDocumentHandle
|
||||
///
|
||||
|
@ -59,36 +78,56 @@
|
|||
///
|
||||
/// The basic operations (create, read, update, delete) for documents are mapped
|
||||
/// to the standard HTTP methods (POST, GET, PUT, DELETE). An identifier for the
|
||||
/// document revision is returned in the "ETag" field. If you modify a document,
|
||||
/// you can use the "ETag" field to detect conflicts. The revision of a document
|
||||
/// can be checking using the HTTP method HEAD.
|
||||
/// document revision is returned in the "ETag" header field. If you modify a
|
||||
/// document, you can use the "If-Match" field to detect conflicts. The revision
|
||||
/// of a document can be checking using the HTTP method HEAD.
|
||||
///
|
||||
/// <hr>
|
||||
/// @copydoc RestDocumentTOC
|
||||
/// @section RestDocumentResource Address and ETag of an Document
|
||||
/////////////////////////////////////////////////////////////////
|
||||
///
|
||||
/// All documents in AvocadoDB have a document handle. This handle uniquely
|
||||
/// defines a document and is managed by AvocadoDB. Assume that the document
|
||||
/// handle, which is stored in the @LIT{_id} field of the document, is
|
||||
/// @LIT{7254820/362549736}, then the HTTP URI of that document is:
|
||||
///
|
||||
/// @LIT{http://localhost:8529/document/7254820/362549736}
|
||||
///
|
||||
/// Each document also has a document revision or etag with is returned
|
||||
/// in the "ETag" header field when requesting a document.
|
||||
///
|
||||
/// If you obtain a document using @LIT{GET} and you want to check if a
|
||||
/// newer revision is available, then you can use the "If-None-Match"
|
||||
/// header. If the document is unchanged, a @LIT{HTTP 412} is returned.
|
||||
///
|
||||
/// If you want to update or delete a document, then you can use the
|
||||
/// "If-Match" header. If the document has changed, then the
|
||||
/// operation is aborted and a @LIT{HTTP 409} is returned.
|
||||
///
|
||||
/// @section RestDocumentHttp Working with Documents using REST
|
||||
///////////////////////////////////////////////////////////////
|
||||
///
|
||||
/// @anchor RestDocumentRead
|
||||
/// @copydetails triagens::avocado::RestDocumentHandler::readSingleDocument
|
||||
/// <hr>
|
||||
///
|
||||
/// @anchor RestCollectionCreate
|
||||
/// @copydetails triagens::avocado::RestCollectionHandler::createDocument
|
||||
/// @anchor RestDocumentCreate
|
||||
/// @copydetails triagens::avocado::RestDocumentHandler::createDocument
|
||||
/// <hr>
|
||||
///
|
||||
/// @anchor RestCollectionRead
|
||||
/// @copydetails triagens::avocado::RestCollectionHandler::readSingleDocument
|
||||
/// @anchor RestDocumentUpdate
|
||||
/// @copydetails triagens::avocado::RestDocumentHandler::updateDocument
|
||||
/// <hr>
|
||||
///
|
||||
/// @anchor RestCollectionReadAll
|
||||
/// @copydetails triagens::avocado::RestCollectionHandler::readAllDocuments
|
||||
/// @anchor RestDocumentDelete
|
||||
/// @copydetails triagens::avocado::RestDocumentHandler::deleteDocument
|
||||
/// <hr>
|
||||
///
|
||||
/// @anchor RestCollectionUpdate
|
||||
/// @copydetails triagens::avocado::RestCollectionHandler::updateDocument
|
||||
/// @anchor RestDocumentHead
|
||||
/// @copydetails triagens::avocado::RestDocumentHandler::checkDocument
|
||||
/// <hr>
|
||||
///
|
||||
/// @anchor RestCollectionDelete
|
||||
/// @copydetails triagens::avocado::RestCollectionHandler::deleteDocument
|
||||
/// <hr>
|
||||
///
|
||||
/// @anchor RestCollectionHead
|
||||
/// @copydetails triagens::avocado::RestCollectionHandler::checkDocument
|
||||
/// @anchor RestDocumentReadAll
|
||||
/// @copydetails triagens::avocado::RestDocumentHandler::readAllDocuments
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Local Variables:
|
||||
|
|
|
@ -194,10 +194,10 @@ namespace triagens {
|
|||
return contentLength;
|
||||
}
|
||||
|
||||
toRead -= _readBufferSize;
|
||||
|
||||
stream.write(_readBuffer, _readBufferSize);
|
||||
_readBufferSize = 0;
|
||||
|
||||
toRead -= _readBufferSize;
|
||||
}
|
||||
|
||||
size_t len = 0;
|
||||
|
@ -216,14 +216,11 @@ namespace triagens {
|
|||
len += len_read;
|
||||
runtime = now() - start;
|
||||
}
|
||||
|
||||
//buffer[len] = '\0';
|
||||
|
||||
stream.write(buffer, len);
|
||||
|
||||
free(buffer);
|
||||
|
||||
return len;
|
||||
return (contentLength - toRead + len);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -714,8 +714,6 @@ bool TRI_InsertKeySkipList (TRI_skiplist_t* skiplist, void* key, void* element,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void* TRI_LeftLookupByKeySkipList (TRI_skiplist_t* skiplist, void* key) {
|
||||
|
||||
int32_t level;
|
||||
int32_t currentLevel;
|
||||
TRI_skiplist_node_t* currentNode;
|
||||
TRI_skiplist_node_t* nextNode;
|
||||
|
@ -839,7 +837,7 @@ void* TRI_LeftLookupByKeySkipList (TRI_skiplist_t* skiplist, void* key) {
|
|||
|
||||
|
||||
|
||||
END:
|
||||
// END:
|
||||
|
||||
assert(false); // there is no way we can be here
|
||||
return NULL;
|
||||
|
@ -862,8 +860,6 @@ void* TRI_LookupByElementSkipList (TRI_skiplist_t* skiplist, void* element) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void* TRI_LookupByKeySkipList (TRI_skiplist_t* skiplist, void* key) {
|
||||
|
||||
int32_t level;
|
||||
int32_t currentLevel;
|
||||
TRI_skiplist_node_t* currentNode;
|
||||
TRI_skiplist_node_t* nextNode;
|
||||
|
@ -979,7 +975,7 @@ void* TRI_LookupByKeySkipList (TRI_skiplist_t* skiplist, void* key) {
|
|||
|
||||
|
||||
|
||||
END:
|
||||
// END:
|
||||
|
||||
assert(false); // there is no way we can be here
|
||||
return NULL;
|
||||
|
@ -1184,8 +1180,6 @@ bool TRI_RemoveKeySkipList (TRI_skiplist_t* skiplist, void* key, void* old) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void* TRI_RightLookupByKeySkipList (TRI_skiplist_t* skiplist, void* key) {
|
||||
|
||||
int32_t level;
|
||||
int32_t currentLevel;
|
||||
TRI_skiplist_node_t* currentNode;
|
||||
TRI_skiplist_node_t* prevNode;
|
||||
|
@ -1312,7 +1306,7 @@ void* TRI_RightLookupByKeySkipList (TRI_skiplist_t* skiplist, void* key) {
|
|||
|
||||
|
||||
|
||||
END:
|
||||
// END:
|
||||
|
||||
assert(false); // there is no way we can be here
|
||||
return NULL;
|
||||
|
@ -1526,8 +1520,6 @@ void* TRI_EndNodeSkipListMulti(TRI_skiplist_multi_t* skiplist) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void* TRI_LeftLookupByKeySkipListMulti(TRI_skiplist_multi_t* skiplist, void* key) {
|
||||
|
||||
int32_t level;
|
||||
int32_t currentLevel;
|
||||
TRI_skiplist_node_t* currentNode;
|
||||
TRI_skiplist_node_t* nextNode;
|
||||
|
@ -1647,7 +1639,7 @@ void* TRI_LeftLookupByKeySkipListMulti(TRI_skiplist_multi_t* skiplist, void* key
|
|||
|
||||
|
||||
|
||||
END:
|
||||
// END:
|
||||
|
||||
assert(false); // there is no way we can be here
|
||||
return NULL;
|
||||
|
@ -2115,8 +2107,6 @@ bool TRI_RemoveKeySkipListMulti(TRI_skiplist_multi_t* skiplist, void* key, void*
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void* TRI_RightLookupByKeySkipListMulti(TRI_skiplist_multi_t* skiplist, void* key) {
|
||||
|
||||
int32_t level;
|
||||
int32_t currentLevel;
|
||||
TRI_skiplist_node_t* currentNode;
|
||||
TRI_skiplist_node_t* prevNode;
|
||||
|
@ -2234,7 +2224,7 @@ void* TRI_RightLookupByKeySkipListMulti(TRI_skiplist_multi_t* skiplist, void* ke
|
|||
|
||||
|
||||
|
||||
END:
|
||||
// END:
|
||||
|
||||
assert(false); // there is no way we can be here
|
||||
return NULL;
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "BasicsC/string-buffer.h"
|
||||
#include "BasicsC/strings.h"
|
||||
#include "ShapedJson/shaped-json.h"
|
||||
#include "VocBase/vocbase.h"
|
||||
|
||||
#include "V8/v8-json.h"
|
||||
#include "V8/v8-utils.h"
|
||||
|
@ -1171,7 +1172,7 @@ v8::Handle<v8::Value> TRI_ObjectReference (TRI_voc_cid_t cid, TRI_voc_did_t did)
|
|||
|
||||
TRI_InitStringBuffer(&buffer);
|
||||
TRI_AppendUInt64StringBuffer(&buffer, cid);
|
||||
TRI_AppendStringStringBuffer(&buffer, ":");
|
||||
TRI_AppendCharStringBuffer(&buffer, TRI_DOCUMENT_HANDLE_SEPARATOR_CHR);
|
||||
TRI_AppendUInt64StringBuffer(&buffer, did);
|
||||
|
||||
v8::Handle<v8::String> ref = v8::String::New(buffer._buffer);
|
||||
|
@ -1198,7 +1199,7 @@ bool TRI_IdentifiersObjectReference (v8::Handle<v8::Value> value, TRI_voc_cid_t&
|
|||
|
||||
string v = TRI_ObjectToString(value);
|
||||
|
||||
vector<string> doc = StringUtils::split(v, ":");
|
||||
vector<string> doc = StringUtils::split(v, TRI_DOCUMENT_HANDLE_SEPARATOR_STR);
|
||||
|
||||
switch (doc.size()) {
|
||||
case 1:
|
||||
|
@ -1380,6 +1381,40 @@ char TRI_ObjectToCharacter (v8::Handle<v8::Value> value, bool& error) {
|
|||
return (*sep)[0];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief converts an V8 object to an int64_t
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int64_t TRI_ObjectToInt64 (v8::Handle<v8::Value> value) {
|
||||
if (value->IsNumber()) {
|
||||
return (int64_t) value->ToNumber()->Value();
|
||||
}
|
||||
|
||||
if (value->IsNumberObject()) {
|
||||
v8::Handle<v8::NumberObject> no = v8::Handle<v8::NumberObject>::Cast(value);
|
||||
return (int64_t) no->NumberValue();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief converts an V8 object to a uint64_t
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
uint64_t TRI_ObjectToUInt64 (v8::Handle<v8::Value> value) {
|
||||
if (value->IsNumber()) {
|
||||
return (uint64_t) value->ToNumber()->Value();
|
||||
}
|
||||
|
||||
if (value->IsNumberObject()) {
|
||||
v8::Handle<v8::NumberObject> no = v8::Handle<v8::NumberObject>::Cast(value);
|
||||
return (uint64_t) no->NumberValue();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief converts an V8 object to a double
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
12
V8/v8-conv.h
12
V8/v8-conv.h
|
@ -83,6 +83,18 @@ std::string TRI_ObjectToString (v8::Handle<v8::Value>);
|
|||
|
||||
char TRI_ObjectToCharacter (v8::Handle<v8::Value>, bool& error);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief converts an V8 object to an int64_t
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int64_t TRI_ObjectToInt64 (v8::Handle<v8::Value>);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief converts an V8 object to a uint64_t
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
uint64_t TRI_ObjectToUInt64 (v8::Handle<v8::Value>);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief converts an V8 object to a double
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -63,7 +63,6 @@ typedef struct TRI_v8_global_s {
|
|||
|
||||
TRI_v8_global_s ()
|
||||
: JSFluentQueries(),
|
||||
JSQueryTemplates(),
|
||||
JSQueryCursors(),
|
||||
JSQueries(), // DEPRECATED
|
||||
JSCursors(), // DEPRECATED
|
||||
|
@ -75,7 +74,6 @@ typedef struct TRI_v8_global_s {
|
|||
EdgesTempl(),
|
||||
EdgesColTempl(),
|
||||
FluentQueryTempl(),
|
||||
QueryTemplateTempl(),
|
||||
QueryCursorTempl(),
|
||||
QueryErrorTempl(),
|
||||
QueryTempl(), // DEPRECATED
|
||||
|
@ -105,12 +103,6 @@ typedef struct TRI_v8_global_s {
|
|||
|
||||
std::map< void*, v8::Persistent<v8::Value> > JSFluentQueries;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief template mapping for weak pointers
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::map< void*, v8::Persistent<v8::Value> > JSQueryTemplates;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief cursor mapping for weak pointers
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -202,12 +194,6 @@ typedef struct TRI_v8_global_s {
|
|||
|
||||
v8::Persistent<v8::ObjectTemplate> FluentQueryTempl;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief query template template
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
v8::Persistent<v8::ObjectTemplate> QueryTemplateTempl;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief cursor template
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -443,10 +429,6 @@ typedef struct TRI_v8_global_s {
|
|||
// --SECTION-- REGULAR EXPRESSIONS
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup V8Globals
|
||||
/// @{
|
||||
|
|
1063
V8/v8-vocbase.cpp
1063
V8/v8-vocbase.cpp
File diff suppressed because it is too large
Load Diff
|
@ -471,10 +471,7 @@ static void CleanupShadows (TRI_vocbase_t* const vocbase) {
|
|||
LOG_TRACE("cleaning shadows");
|
||||
|
||||
// clean unused cursors
|
||||
TRI_CleanupShadowData(vocbase->_cursors, SHADOW_CURSOR_MAX_AGE);
|
||||
|
||||
// clean unused statements
|
||||
// TRI_CleanupShadowDocuments(vocbase->_statements, SHADOW_STATEMENT_MAX_AGE);
|
||||
TRI_CleanupShadowData(vocbase->_cursors, SHADOW_CURSOR_MAX_AGE, false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -365,122 +365,7 @@ TRI_bind_parameter_t* TRI_CreateBindParameter (const char* name,
|
|||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- query template
|
||||
// -----------------------------------------------------------------------------
|
||||
/*
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief decrease the refcount of a template
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_DecreaseRefCountQueryTemplate (TRI_query_template_t* const template_) {
|
||||
assert(template_);
|
||||
// assert(template_->_shadow);
|
||||
|
||||
TRI_LockQueryTemplate(template_);
|
||||
// TRI_DecreaseRefCountShadowData(template_->_vocbase->_templates,
|
||||
// template_->_shadow->_id);
|
||||
|
||||
TRI_UnlockQueryTemplate(template_);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief increase the refcount of a template
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_IncreaseRefCountQueryTemplate (TRI_query_template_t* const template_) {
|
||||
assert(template_);
|
||||
// assert(template_->_shadow);
|
||||
|
||||
TRI_LockQueryTemplate(template_);
|
||||
// TRI_IncreaseRefCountShadowData(template_->_vocbase->_templates,
|
||||
// template_->_shadow->_id);
|
||||
|
||||
TRI_UnlockQueryTemplate(template_);
|
||||
}
|
||||
*/
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief exclusively lock a query template
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_LockQueryTemplate (TRI_query_template_t* const template_) {
|
||||
assert(template_);
|
||||
|
||||
TRI_LockMutex(&template_->_lock);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief unlock a query template
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_UnlockQueryTemplate (TRI_query_template_t* const template_) {
|
||||
assert(template_);
|
||||
|
||||
TRI_UnlockMutex(&template_->_lock);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Free a template based on its shadow
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/*
|
||||
void TRI_FreeShadowQueryTemplate (TRI_shadow_document_store_t* store,
|
||||
TRI_shadow_document_t* shadow) {
|
||||
TRI_query_template_t* template_ = (TRI_query_template_t*) shadow->_base->_data;
|
||||
|
||||
if (!template_) {
|
||||
return;
|
||||
}
|
||||
|
||||
TRI_FreeQueryTemplate(template_);
|
||||
}
|
||||
*/
|
||||
/*
|
||||
// TODO: move to own file
|
||||
void* TRI_CreateShadowQueryTemplate (TRI_shadow_document_store_t* store, TRI_doc_collection_t* collection, TRI_doc_mptr_t const* document) {
|
||||
TRI_json_t* json;
|
||||
TRI_json_t* query;
|
||||
char* queryString;
|
||||
|
||||
LOG_DEBUG("creating shadow for %lu", (unsigned long) document->_did);
|
||||
|
||||
json = TRI_JsonShapedJson(collection->_shaper, &document->_document);
|
||||
if (!json) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
query = TRI_LookupArrayJson(json, "query");
|
||||
if (!query) {
|
||||
// TODO: fix this
|
||||
// TRI_FreeJson(json);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (query->_type != TRI_JSON_STRING || !query->_value._string.data) {
|
||||
// TODO: fix this
|
||||
// TRI_FreeJson(json);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
queryString = query->_value._string.data;
|
||||
assert(queryString);
|
||||
|
||||
|
||||
|
||||
// TODO: fix this
|
||||
// TRI_FreeJson(json);
|
||||
|
||||
// TODO: fix
|
||||
return NULL;
|
||||
}
|
||||
bool TRI_VerifyShadowQueryTemplate (TRI_shadow_document_store_t* store, TRI_doc_collection_t* collection, TRI_doc_mptr_t const* document, void* shadow) {
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create shadow data store for templates
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_shadow_document_store_t* TRI_CreateShadowsQueryTemplate (void) {
|
||||
return TRI_CreateShadowDocumentStore(&TRI_CreateShadowQueryTemplate, &TRI_VerifyShadowQueryTemplate, &TRI_FreeShadowQueryTemplate);
|
||||
}
|
||||
*/
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Initialize the structs contained in a query template and perform
|
||||
/// some basic optimizations and type detections
|
||||
|
@ -528,8 +413,7 @@ bool TRI_AddBindParameterQueryTemplate (TRI_query_template_t* const template_,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_query_template_t* TRI_CreateQueryTemplate (const char* queryString,
|
||||
const TRI_vocbase_t* const vocbase,
|
||||
const TRI_query_template_type_e type) {
|
||||
const TRI_vocbase_t* const vocbase) {
|
||||
TRI_query_template_t* template_;
|
||||
|
||||
assert(queryString);
|
||||
|
@ -553,9 +437,6 @@ TRI_query_template_t* TRI_CreateQueryTemplate (const char* queryString,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
template_->_type = type;;
|
||||
template_->_shadow = NULL;
|
||||
|
||||
template_->_vocbase = (TRI_vocbase_t*) vocbase;
|
||||
TRI_InitQueryError(&template_->_error);
|
||||
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
#include <BasicsC/json.h>
|
||||
|
||||
#include "VocBase/vocbase.h"
|
||||
#include "VocBase/shadow-data.h"
|
||||
#include "VocBase/query-node.h"
|
||||
#include "VocBase/query-error.h"
|
||||
|
||||
|
@ -120,24 +119,6 @@ TRI_bind_parameter_t* TRI_CreateBindParameter (const char*, const TRI_json_t*);
|
|||
// --SECTION-- query template
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief query template types
|
||||
///
|
||||
/// There are two types of templates:
|
||||
/// - QUERY_TEMPLATE_TRANSIENT: these templates only exist for one query and are
|
||||
/// disposed automatically when the query execution is finished
|
||||
/// - QUERY_TEMPLATE_PERSISTENT: these templates are created on the server and
|
||||
/// can be shared for multiple executions. they are disposed automatically
|
||||
/// if they are not referenced anymore and have not been used for a certain
|
||||
/// period of time (garbage collection)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef enum {
|
||||
QUERY_TEMPLATE_TRANSIENT,
|
||||
QUERY_TEMPLATE_PERSISTENT
|
||||
}
|
||||
TRI_query_template_type_e;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief lexer state
|
||||
///
|
||||
|
@ -173,8 +154,6 @@ TRI_query_parser_t;
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct TRI_query_template_s {
|
||||
TRI_query_template_type_e _type;
|
||||
TRI_shadow_document_t* _shadow;
|
||||
TRI_vocbase_t* _vocbase;
|
||||
char* _queryString;
|
||||
QL_ast_query_t* _query;
|
||||
|
@ -192,47 +171,6 @@ typedef struct TRI_query_template_s {
|
|||
}
|
||||
TRI_query_template_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Free a template based on its shadow
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_FreeShadowQueryTemplate (TRI_shadow_document_store_t*,
|
||||
TRI_shadow_document_t*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief decrease the refcount of a template
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_DecreaseRefCountQueryTemplate (TRI_query_template_t* const);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief increase the refcount of a template
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_IncreaseRefCountQueryTemplate (TRI_query_template_t* const);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief exclusively lock a query template
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_LockQueryTemplate (TRI_query_template_t* const);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief unlock a query template
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_UnlockQueryTemplate (TRI_query_template_t* const);
|
||||
|
||||
// TODO: move to own file
|
||||
void* TRI_CreateShadowQueryTemplate (TRI_shadow_document_store_t*, TRI_doc_collection_t*, TRI_doc_mptr_t const*);
|
||||
bool TRI_VerifyShadowQueryTemplate (TRI_shadow_document_store_t*, TRI_doc_collection_t*, TRI_doc_mptr_t const*, void*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create shadow data store for templates
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_shadow_document_store_t* TRI_CreateShadowsQueryTemplate (void);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Initialize the structs contained in a query template and perform
|
||||
/// some basic optimizations and type detections
|
||||
|
@ -252,8 +190,7 @@ bool TRI_AddBindParameterQueryTemplate (TRI_query_template_t* const,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_query_template_t* TRI_CreateQueryTemplate (const char*,
|
||||
const TRI_vocbase_t* const,
|
||||
const TRI_query_template_type_e);
|
||||
const TRI_vocbase_t* const);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Free a query template
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
|
||||
#include "VocBase/query-cursor.h"
|
||||
#include "VocBase/query-context.h"
|
||||
#include "VocBase/shadow-data.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase
|
||||
|
@ -85,7 +84,7 @@ static bool HasCountQueryCursor (const TRI_query_cursor_t* const cursor) {
|
|||
/// @brief returns the maximum number of results per transfer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static uint32_t GetMaxQueryCursor (const TRI_query_cursor_t* const cursor) {
|
||||
static uint32_t GetBatchSizeQueryCursor (const TRI_query_cursor_t* const cursor) {
|
||||
return cursor->_batchSize;
|
||||
}
|
||||
|
||||
|
@ -93,7 +92,7 @@ static uint32_t GetMaxQueryCursor (const TRI_query_cursor_t* const cursor) {
|
|||
/// @brief frees a cursor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void FreeQueryCursor (TRI_query_cursor_t* cursor) {
|
||||
void TRI_FreeQueryCursor (TRI_query_cursor_t* cursor) {
|
||||
assert(cursor->_functionCode);
|
||||
TRI_Free(cursor->_functionCode);
|
||||
|
||||
|
@ -136,7 +135,6 @@ TRI_query_cursor_t* TRI_CreateQueryCursor (TRI_query_instance_t* const instance,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
cursor->_shadow = NULL;
|
||||
cursor->_hasCount = doCount;
|
||||
cursor->_batchSize = batchSize;
|
||||
cursor->_deleted = false;
|
||||
|
@ -148,8 +146,8 @@ TRI_query_cursor_t* TRI_CreateQueryCursor (TRI_query_instance_t* const instance,
|
|||
cursor->next = NextQueryCursor;
|
||||
cursor->hasNext = HasNextQueryCursor;
|
||||
cursor->hasCount = HasCountQueryCursor;
|
||||
cursor->getMax = GetMaxQueryCursor;
|
||||
cursor->free = FreeQueryCursor;
|
||||
cursor->getBatchSize = GetBatchSizeQueryCursor;
|
||||
cursor->free = TRI_FreeQueryCursor;
|
||||
|
||||
TRI_InitMutex(&cursor->_lock);
|
||||
TRI_InitVectorPointer(&cursor->_containers);
|
||||
|
@ -157,27 +155,11 @@ TRI_query_cursor_t* TRI_CreateQueryCursor (TRI_query_instance_t* const instance,
|
|||
return cursor;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Free a cursor based on its shadow
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_FreeShadowQueryCursor (TRI_shadow_store_t* store, TRI_shadow_t* shadow) {
|
||||
TRI_query_cursor_t* cursor = (TRI_query_cursor_t*) shadow->_data;
|
||||
|
||||
if (!cursor) {
|
||||
return;
|
||||
}
|
||||
|
||||
FreeQueryCursor(cursor);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief exclusively lock a query cursor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_LockQueryCursor (TRI_query_cursor_t* const cursor) {
|
||||
assert(cursor);
|
||||
|
||||
TRI_LockMutex(&cursor->_lock);
|
||||
}
|
||||
|
||||
|
@ -191,6 +173,16 @@ void TRI_UnlockQueryCursor (TRI_query_cursor_t* const cursor) {
|
|||
TRI_UnlockMutex(&cursor->_lock);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Free a cursor based on its shadow data pointer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_FreeShadowQueryCursor (void* data) {
|
||||
TRI_query_cursor_t* cursor = (TRI_query_cursor_t*) data;
|
||||
|
||||
TRI_FreeQueryCursor(cursor);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create shadow data store for cursors
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -48,7 +48,6 @@ extern "C" {
|
|||
|
||||
typedef struct TRI_query_cursor_s {
|
||||
TRI_vocbase_t* _vocbase;
|
||||
TRI_shadow_t* _shadow;
|
||||
char* _functionCode;
|
||||
bool _hasCount;
|
||||
uint32_t _batchSize;
|
||||
|
@ -64,11 +63,17 @@ typedef struct TRI_query_cursor_s {
|
|||
TRI_rc_result_t* (*next)(struct TRI_query_cursor_s* const);
|
||||
bool (*hasNext)(const struct TRI_query_cursor_s* const);
|
||||
bool (*hasCount)(const struct TRI_query_cursor_s* const);
|
||||
uint32_t (*getMax)(const struct TRI_query_cursor_s* const);
|
||||
uint32_t (*getBatchSize)(const struct TRI_query_cursor_s* const);
|
||||
}
|
||||
TRI_query_cursor_t;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief frees a cursor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_FreeQueryCursor (TRI_query_cursor_t*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a cursor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -78,12 +83,6 @@ TRI_query_cursor_t* TRI_CreateQueryCursor (TRI_query_instance_t* const,
|
|||
const bool,
|
||||
const uint32_t);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Free a cursor based on its shadow
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_FreeShadowQueryCursor (TRI_shadow_store_t*, TRI_shadow_t*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief exclusively lock a query cursor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -96,6 +95,12 @@ void TRI_LockQueryCursor (TRI_query_cursor_t* const);
|
|||
|
||||
void TRI_UnlockQueryCursor (TRI_query_cursor_t* const);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Free a cursor based on its data pointer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_FreeShadowQueryCursor (void*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create shadow data store for cursors
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -54,7 +54,7 @@ static inline void UpdateTimestampShadow (TRI_shadow_t* const shadow) {
|
|||
/// @brief init a shadow data structure
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static TRI_shadow_t* CreateShadow (const void* const element) {
|
||||
static TRI_shadow_t* CreateShadow (const void* const data) {
|
||||
TRI_shadow_t* shadow = (TRI_shadow_t*) TRI_Allocate(sizeof(TRI_shadow_t));
|
||||
|
||||
if (!shadow) {
|
||||
|
@ -62,33 +62,81 @@ static TRI_shadow_t* CreateShadow (const void* const element) {
|
|||
}
|
||||
|
||||
shadow->_rc = 1;
|
||||
shadow->_data = (void*) element;
|
||||
shadow->_data = (void*) data;
|
||||
shadow->_id = TRI_NewTickVocBase();
|
||||
shadow->_deleted = false;
|
||||
shadow->_type = SHADOW_TRANSIENT;
|
||||
|
||||
UpdateTimestampShadow(shadow);
|
||||
|
||||
LOG_TRACE("created shadow %p with data ptr %p and id %lu",
|
||||
shadow,
|
||||
data,
|
||||
(unsigned long) shadow->_id);
|
||||
|
||||
return shadow;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief hashes an element
|
||||
/// @brief hashes an element in the ids index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static uint64_t HashShadowElement (TRI_associative_pointer_t* array, void const* e) {
|
||||
static uint64_t HashKeyId (TRI_associative_pointer_t* array, void const* k) {
|
||||
TRI_shadow_id key = *((TRI_shadow_id*) k);
|
||||
|
||||
return (uint64_t) key;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief hashes an element in the ids index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static uint64_t HashElementId (TRI_associative_pointer_t* array, void const* e) {
|
||||
TRI_shadow_t const* element = e;
|
||||
|
||||
return element->_id;
|
||||
return (uint64_t) element->_id;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief tests if two elements are equal
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool EqualShadowElement (TRI_associative_pointer_t* array, void const* l, void const* r) {
|
||||
TRI_shadow_t const* left = l;
|
||||
TRI_shadow_t const* right = r;
|
||||
static bool EqualKeyId (TRI_associative_pointer_t* array, void const* k, void const* e) {
|
||||
TRI_shadow_t const* element = e;
|
||||
TRI_shadow_id key = *((TRI_shadow_id*) k);
|
||||
|
||||
return left->_id == right->_id;
|
||||
return (key == element->_id);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief hashes an element in the pointers index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static uint64_t HashKeyData (TRI_associative_pointer_t* array, void const* k) {
|
||||
uint64_t key = 0;
|
||||
|
||||
key = (uint64_t) k;
|
||||
return key;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief hashes an element in the pointers index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static uint64_t HashElementData (TRI_associative_pointer_t* array, void const* e) {
|
||||
TRI_shadow_t const* element = e;
|
||||
|
||||
return (uint64_t) element->_data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief tests if two elements are equal
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool EqualKeyData (TRI_associative_pointer_t* array, void const* k, void const* e) {
|
||||
TRI_shadow_t const* element = e;
|
||||
|
||||
return ((uint64_t) k == (uint64_t) element->_data);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -108,16 +156,22 @@ static bool EqualShadowElement (TRI_associative_pointer_t* array, void const* l,
|
|||
/// @brief creates a shadow data storage
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_shadow_store_t* TRI_CreateShadowStore (void (*destroy) (TRI_shadow_store_t*, TRI_shadow_t*)) {
|
||||
TRI_shadow_store_t* TRI_CreateShadowStore (void (*destroy) (void*)) {
|
||||
TRI_shadow_store_t* store =
|
||||
(TRI_shadow_store_t*) TRI_Allocate(sizeof(TRI_shadow_store_t));
|
||||
|
||||
if (store) {
|
||||
TRI_InitAssociativePointer(&store->_index,
|
||||
NULL,
|
||||
HashShadowElement,
|
||||
NULL,
|
||||
EqualShadowElement);
|
||||
TRI_InitAssociativePointer(&store->_ids,
|
||||
HashKeyId,
|
||||
HashElementId,
|
||||
EqualKeyId,
|
||||
NULL);
|
||||
|
||||
TRI_InitAssociativePointer(&store->_pointers,
|
||||
HashKeyData,
|
||||
HashElementData,
|
||||
EqualKeyData,
|
||||
NULL);
|
||||
|
||||
store->destroyShadow = destroy;
|
||||
|
||||
|
@ -129,50 +183,22 @@ TRI_shadow_store_t* TRI_CreateShadowStore (void (*destroy) (TRI_shadow_store_t*,
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destroys a shadow data storage
|
||||
///
|
||||
/// Note: all remaining shadows will be destroyed
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_FreeShadowStore (TRI_shadow_store_t* const store) {
|
||||
assert(store);
|
||||
|
||||
// force deletion of all remaining shadows
|
||||
TRI_CleanupShadowData(store, 0, true);
|
||||
|
||||
TRI_DestroyMutex(&store->_lock);
|
||||
TRI_DestroyAssociativePointer(&store->_index);
|
||||
TRI_DestroyAssociativePointer(&store->_ids);
|
||||
TRI_DestroyAssociativePointer(&store->_pointers);
|
||||
TRI_Free(store);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Update the refcount of a shadow data element (increase or decrease)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool UpdateRefCountShadowData (TRI_shadow_store_t* const store,
|
||||
const TRI_shadow_id id,
|
||||
const bool increase) {
|
||||
TRI_shadow_t* shadow;
|
||||
TRI_shadow_t search;
|
||||
union { TRI_shadow_t* s; TRI_shadow_t const* c; } cnv;
|
||||
|
||||
assert(store);
|
||||
|
||||
TRI_LockMutex(&store->_lock);
|
||||
|
||||
search._id = id;
|
||||
cnv.c = (TRI_shadow_t*) TRI_LookupByElementAssociativePointer(&store->_index,
|
||||
&search);
|
||||
shadow = cnv.s;
|
||||
|
||||
if (shadow) {
|
||||
if (increase) {
|
||||
++shadow->_rc;
|
||||
}
|
||||
else {
|
||||
--shadow->_rc;
|
||||
}
|
||||
}
|
||||
|
||||
TRI_UnlockMutex(&store->_lock);
|
||||
|
||||
return (shadow != NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -187,10 +213,304 @@ static bool UpdateRefCountShadowData (TRI_shadow_store_t* const store,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief enumerate all shadows and remove them if expired
|
||||
/// @brief look up a shadow in the index using its data pointer and return
|
||||
/// its id
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_shadow_id TRI_GetIdDataShadowData (TRI_shadow_store_t* const store,
|
||||
const void* const data) {
|
||||
TRI_shadow_t* shadow;
|
||||
TRI_shadow_id id = 0;
|
||||
|
||||
assert(store);
|
||||
|
||||
if (data) {
|
||||
TRI_LockMutex(&store->_lock);
|
||||
shadow = (TRI_shadow_t*) TRI_LookupByKeyAssociativePointer(&store->_pointers, data);
|
||||
|
||||
if (shadow && !shadow->_deleted) {
|
||||
id = shadow->_id;
|
||||
UpdateTimestampShadow(shadow);
|
||||
}
|
||||
|
||||
TRI_UnlockMutex(&store->_lock);
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief look up a shadow in the index using its data pointer
|
||||
///
|
||||
/// If the shadow is found, this will return the data pointer, NULL otherwise.
|
||||
/// When the shadow is found, its refcount will also be increased by one
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void* TRI_BeginUsageDataShadowData (TRI_shadow_store_t* const store,
|
||||
const void* const data) {
|
||||
TRI_shadow_t* shadow;
|
||||
|
||||
assert(store);
|
||||
|
||||
if (!data) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TRI_LockMutex(&store->_lock);
|
||||
shadow = (TRI_shadow_t*) TRI_LookupByKeyAssociativePointer(&store->_pointers, data);
|
||||
|
||||
if (shadow && !shadow->_deleted) {
|
||||
LOG_TRACE("increasing refcount for shadow %p with data ptr %p and id %lu",
|
||||
shadow,
|
||||
shadow->_data,
|
||||
(unsigned long) shadow->_id);
|
||||
|
||||
++shadow->_rc;
|
||||
UpdateTimestampShadow(shadow);
|
||||
TRI_UnlockMutex(&store->_lock);
|
||||
return shadow->_data;
|
||||
}
|
||||
|
||||
TRI_UnlockMutex(&store->_lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief look up a shadow in the index using its id
|
||||
///
|
||||
/// If the shadow is found, this will return the data pointer, NULL otherwise.
|
||||
/// When the shadow is found, its refcount will also be increased by one
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void* TRI_BeginUsageIdShadowData (TRI_shadow_store_t* const store,
|
||||
const TRI_shadow_id id) {
|
||||
TRI_shadow_t* shadow;
|
||||
|
||||
assert(store);
|
||||
|
||||
TRI_LockMutex(&store->_lock);
|
||||
shadow = (TRI_shadow_t*) TRI_LookupByKeyAssociativePointer(&store->_ids, (void const*) &id);
|
||||
|
||||
if (shadow && !shadow->_deleted) {
|
||||
LOG_TRACE("increasing refcount for shadow %p with data ptr %p and id %lu",
|
||||
shadow,
|
||||
shadow->_data,
|
||||
(unsigned long) shadow->_id);
|
||||
|
||||
++shadow->_rc;
|
||||
UpdateTimestampShadow(shadow);
|
||||
TRI_UnlockMutex(&store->_lock);
|
||||
return shadow->_data;
|
||||
}
|
||||
|
||||
TRI_UnlockMutex(&store->_lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief look up a shadow in the index using its data pointer
|
||||
///
|
||||
/// If the shadow is found, its refcount will be decreased by one.
|
||||
/// If the refcount is 0 and the shadow is of type SHADOW_TRANSIENT, the shadow
|
||||
/// object will be destroyed.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_EndUsageDataShadowData (TRI_shadow_store_t* const store,
|
||||
const void* const data) {
|
||||
TRI_shadow_t* shadow;
|
||||
|
||||
assert(store);
|
||||
|
||||
TRI_LockMutex(&store->_lock);
|
||||
shadow = (TRI_shadow_t*) TRI_LookupByKeyAssociativePointer(&store->_pointers, data);
|
||||
|
||||
if (shadow && !shadow->_deleted) {
|
||||
LOG_TRACE("decreasing refcount for shadow %p with data ptr %p and id %lu",
|
||||
shadow,
|
||||
shadow->_data,
|
||||
(unsigned long) shadow->_id);
|
||||
|
||||
if (--shadow->_rc <= 0 && shadow->_type == SHADOW_TRANSIENT) {
|
||||
LOG_TRACE("deleting shadow %p", shadow);
|
||||
|
||||
TRI_RemoveKeyAssociativePointer(&store->_ids, &shadow->_id);
|
||||
TRI_RemoveKeyAssociativePointer(&store->_pointers, data);
|
||||
store->destroyShadow(shadow->_data);
|
||||
TRI_Free(shadow);
|
||||
}
|
||||
}
|
||||
|
||||
TRI_UnlockMutex(&store->_lock);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief look up a shadow in the index using its id
|
||||
///
|
||||
/// If the shadow is found, its refcount will be decreased by one.
|
||||
/// If the refcount is 0 and the shadow is of type SHADOW_TRANSIENT, the shadow
|
||||
/// object will be destroyed.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_EndUsageIdShadowData (TRI_shadow_store_t* const store,
|
||||
const TRI_shadow_id id) {
|
||||
TRI_shadow_t* shadow;
|
||||
|
||||
assert(store);
|
||||
|
||||
TRI_LockMutex(&store->_lock);
|
||||
shadow = (TRI_shadow_t*) TRI_LookupByKeyAssociativePointer(&store->_ids, &id);
|
||||
|
||||
if (shadow && !shadow->_deleted) {
|
||||
LOG_TRACE("decreasing refcount for shadow %p with data ptr %p and id %lu",
|
||||
shadow,
|
||||
shadow->_data,
|
||||
(unsigned long) shadow->_id);
|
||||
|
||||
if (--shadow->_rc <= 0 && shadow->_type == SHADOW_TRANSIENT) {
|
||||
LOG_TRACE("deleting shadow %p", shadow);
|
||||
|
||||
TRI_RemoveKeyAssociativePointer(&store->_ids, &id);
|
||||
TRI_RemoveKeyAssociativePointer(&store->_pointers, shadow->_data);
|
||||
store->destroyShadow(shadow->_data);
|
||||
TRI_Free(shadow);
|
||||
}
|
||||
}
|
||||
|
||||
TRI_UnlockMutex(&store->_lock);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief set the persistence flag for a shadow using its data pointer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_PersistDataShadowData (TRI_shadow_store_t* const store,
|
||||
const void* const data) {
|
||||
TRI_shadow_t* shadow;
|
||||
bool result = false;
|
||||
|
||||
assert(store);
|
||||
|
||||
TRI_LockMutex(&store->_lock);
|
||||
shadow = (TRI_shadow_t*) TRI_LookupByKeyAssociativePointer(&store->_pointers, data);
|
||||
|
||||
if (shadow && !shadow->_deleted) {
|
||||
LOG_TRACE("persisting shadow %p with data ptr %p and id %lu",
|
||||
shadow,
|
||||
shadow->_data,
|
||||
(unsigned long) shadow->_id);
|
||||
|
||||
shadow->_type = SHADOW_PERSISTENT;
|
||||
UpdateTimestampShadow(shadow);
|
||||
result = true;
|
||||
}
|
||||
|
||||
TRI_UnlockMutex(&store->_lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief set the persistence flag for a shadow using its id
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_PersistIdShadowData (TRI_shadow_store_t* const store,
|
||||
const TRI_shadow_id id) {
|
||||
TRI_shadow_t* shadow;
|
||||
bool result = false;
|
||||
|
||||
assert(store);
|
||||
|
||||
TRI_LockMutex(&store->_lock);
|
||||
shadow = (TRI_shadow_t*) TRI_LookupByKeyAssociativePointer(&store->_ids, &id);
|
||||
|
||||
if (shadow && !shadow->_deleted) {
|
||||
LOG_TRACE("persisting shadow %p with data ptr %p and id %lu",
|
||||
shadow,
|
||||
shadow->_data,
|
||||
(unsigned long) shadow->_id);
|
||||
|
||||
shadow->_type = SHADOW_PERSISTENT;
|
||||
UpdateTimestampShadow(shadow);
|
||||
result = true;
|
||||
}
|
||||
|
||||
TRI_UnlockMutex(&store->_lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief set the deleted flag for a shadow using its data pointer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_DeleteDataShadowData (TRI_shadow_store_t* const store,
|
||||
const void* const data) {
|
||||
TRI_shadow_t* shadow;
|
||||
bool found = false;
|
||||
|
||||
assert(store);
|
||||
|
||||
if (data) {
|
||||
TRI_LockMutex(&store->_lock);
|
||||
shadow = (TRI_shadow_t*) TRI_LookupByKeyAssociativePointer(&store->_pointers, data);
|
||||
|
||||
if (shadow && !shadow->_deleted) {
|
||||
LOG_TRACE("setting deleted flag for shadow %p with data ptr %p and id %lu",
|
||||
shadow,
|
||||
shadow->_data,
|
||||
(unsigned long) shadow->_id);
|
||||
|
||||
shadow->_deleted = true;
|
||||
found = true;
|
||||
}
|
||||
|
||||
TRI_UnlockMutex(&store->_lock);
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief set the deleted flag for a shadow using its id
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_DeleteIdShadowData (TRI_shadow_store_t* const store,
|
||||
const TRI_shadow_id id) {
|
||||
TRI_shadow_t* shadow;
|
||||
bool found = false;
|
||||
|
||||
assert(store);
|
||||
|
||||
TRI_LockMutex(&store->_lock);
|
||||
shadow = (TRI_shadow_t*) TRI_LookupByKeyAssociativePointer(&store->_ids, &id);
|
||||
|
||||
if (shadow && !shadow->_deleted) {
|
||||
LOG_TRACE("setting deleted flag for shadow %p with data ptr %p and id %lu",
|
||||
shadow,
|
||||
shadow->_data,
|
||||
(unsigned long) shadow->_id);
|
||||
|
||||
shadow->_deleted = true;
|
||||
found = true;
|
||||
}
|
||||
|
||||
TRI_UnlockMutex(&store->_lock);
|
||||
return found;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief enumerate all shadows and remove them if
|
||||
/// - their refcount is 0 and they are transient
|
||||
/// - their refcount is 0 and they are expired
|
||||
/// - the force flag is set
|
||||
///
|
||||
/// The max age must be specified in seconds. The max age is ignored if the
|
||||
/// force flag is set. In this case all remaining shadows will be deleted
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_CleanupShadowData (TRI_shadow_store_t* const store, const double maxAge) {
|
||||
void TRI_CleanupShadowData (TRI_shadow_store_t* const store,
|
||||
const double maxAge,
|
||||
const bool force) {
|
||||
double compareStamp = TRI_microtime() - maxAge; // age must be specified in secs
|
||||
size_t deleteCount = 0;
|
||||
|
||||
|
@ -199,28 +519,34 @@ void TRI_CleanupShadowData (TRI_shadow_store_t* const store, const double maxAge
|
|||
|
||||
// loop until there's nothing to delete or
|
||||
// we have deleted SHADOW_MAX_DELETE elements
|
||||
while (deleteCount++ < SHADOW_MAX_DELETE) {
|
||||
while (deleteCount++ < SHADOW_MAX_DELETE || force) {
|
||||
bool deleted = false;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < store->_index._nrAlloc; i++) {
|
||||
for (i = 0; i < store->_ids._nrAlloc; i++) {
|
||||
// enum all shadows
|
||||
TRI_shadow_t* shadow = (TRI_shadow_t*) store->_index._table[i];
|
||||
TRI_shadow_t* shadow = (TRI_shadow_t*) store->_ids._table[i];
|
||||
if (!shadow) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// check if shadow is unused and expired
|
||||
if (shadow->_rc <= 1 && shadow->_timestamp < compareStamp) {
|
||||
LOG_DEBUG("cleaning expired shadow %p", shadow);
|
||||
TRI_RemoveElementAssociativePointer(&store->_index, shadow);
|
||||
store->destroyShadow(store, shadow);
|
||||
TRI_Free(shadow);
|
||||
if (shadow->_rc < 1 || force) {
|
||||
if (shadow->_type == SHADOW_TRANSIENT ||
|
||||
shadow->_timestamp < compareStamp ||
|
||||
force) {
|
||||
LOG_TRACE("cleaning expired shadow %p", shadow);
|
||||
|
||||
deleted = true;
|
||||
// the remove might reposition elements in the container.
|
||||
// therefore break here and start iteration anew
|
||||
break;
|
||||
TRI_RemoveKeyAssociativePointer(&store->_ids, &shadow->_id);
|
||||
TRI_RemoveKeyAssociativePointer(&store->_pointers, shadow->_data);
|
||||
store->destroyShadow(shadow->_data);
|
||||
TRI_Free(shadow);
|
||||
|
||||
deleted = true;
|
||||
// the remove might reposition elements in the container.
|
||||
// therefore break here and start iteration anew
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -234,70 +560,33 @@ void TRI_CleanupShadowData (TRI_shadow_store_t* const store, const double maxAge
|
|||
TRI_UnlockMutex(&store->_lock);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief looks up a shadow by id and decreases its refcount if it exists
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_DecreaseRefCountShadowData (TRI_shadow_store_t* const store,
|
||||
const TRI_shadow_id id) {
|
||||
return UpdateRefCountShadowData(store, id, false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief looks up a shadow by id and increases its refcount if it exists
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_IncreaseRefCountShadowData (TRI_shadow_store_t* const store,
|
||||
const TRI_shadow_id id) {
|
||||
return UpdateRefCountShadowData(store, id, true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief looks up a shadow by id
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_shadow_t* TRI_FindShadowData (TRI_shadow_store_t* const store,
|
||||
const TRI_shadow_id id) {
|
||||
TRI_shadow_t* shadow;
|
||||
TRI_shadow_t search;
|
||||
union { TRI_shadow_t* s; TRI_shadow_t const* c; } cnv;
|
||||
|
||||
LOG_INFO("trying to find shadow %lu", (unsigned long) id);
|
||||
assert(store);
|
||||
|
||||
TRI_LockMutex(&store->_lock);
|
||||
|
||||
search._id = id;
|
||||
cnv.c = (TRI_shadow_t*) TRI_LookupByElementAssociativePointer(&store->_index,
|
||||
&search);
|
||||
shadow = cnv.s;
|
||||
|
||||
if (shadow) {
|
||||
++shadow->_rc;
|
||||
UpdateTimestampShadow(shadow);
|
||||
}
|
||||
|
||||
TRI_UnlockMutex(&store->_lock);
|
||||
|
||||
// might be NULL if shadow not found
|
||||
return shadow;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief store a new shadow in the store
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_shadow_t* TRI_StoreShadowData (TRI_shadow_store_t* const store,
|
||||
const void* const element) {
|
||||
const void* const data) {
|
||||
TRI_shadow_t* shadow;
|
||||
|
||||
assert(store);
|
||||
|
||||
shadow = CreateShadow(element);
|
||||
LOG_INFO("inserting shadow %lu", (unsigned long) shadow->_id);
|
||||
shadow = CreateShadow(data);
|
||||
if (shadow) {
|
||||
LOG_TRACE("storing shadow %p with data ptr %p and id %lu",
|
||||
shadow,
|
||||
shadow->_data,
|
||||
(unsigned long) shadow->_id);
|
||||
|
||||
TRI_LockMutex(&store->_lock);
|
||||
TRI_InsertElementAssociativePointer(&store->_index, shadow, true);
|
||||
if (TRI_InsertKeyAssociativePointer(&store->_ids, &shadow->_id, shadow, false)) {
|
||||
// duplicate entry
|
||||
LOG_INFO("storing shadow failed");
|
||||
TRI_UnlockMutex(&store->_lock);
|
||||
TRI_Free(shadow);
|
||||
return NULL;
|
||||
}
|
||||
TRI_InsertKeyAssociativePointer(&store->_pointers, data, shadow, false);
|
||||
|
||||
TRI_UnlockMutex(&store->_lock);
|
||||
}
|
||||
|
||||
|
@ -305,61 +594,15 @@ TRI_shadow_t* TRI_StoreShadowData (TRI_shadow_store_t* const store,
|
|||
return shadow;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief decrease the refcount of a shadow without deleting it
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int64_t TRI_DecreaseRefcountShadowData (TRI_shadow_store_t* const store,
|
||||
TRI_shadow_t* const shadow) {
|
||||
int64_t result;
|
||||
|
||||
assert(shadow);
|
||||
|
||||
TRI_LockMutex(&store->_lock);
|
||||
|
||||
// release the element
|
||||
result = --shadow->_rc;
|
||||
|
||||
TRI_UnlockMutex(&store->_lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief releases shadow data
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_ReleaseShadowData (TRI_shadow_store_t* const store, TRI_shadow_t* shadow) {
|
||||
bool result;
|
||||
|
||||
assert(shadow);
|
||||
|
||||
TRI_LockMutex(&store->_lock);
|
||||
|
||||
// release the element
|
||||
--shadow->_rc;
|
||||
|
||||
// need to destroy the element
|
||||
if (shadow->_rc < 1) {
|
||||
LOG_INFO("releasing shadow %lu", (unsigned long) shadow->_id);
|
||||
TRI_RemoveElementAssociativePointer(&store->_index, shadow);
|
||||
store->destroyShadow(store, shadow);
|
||||
TRI_Free(shadow);
|
||||
result = true; // object was destroyed
|
||||
}
|
||||
else {
|
||||
result = false; // object was not destroyed
|
||||
}
|
||||
|
||||
TRI_UnlockMutex(&store->_lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- UNUSED AND UNTESTED CODE FOLLOWS
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- SHADOW DOCUMENTS
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -675,10 +918,10 @@ void TRI_CleanupShadowDocuments (TRI_shadow_document_store_t* const store, const
|
|||
// release lock
|
||||
TRI_UnlockMutex(&store->_base->_lock);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
|
|
|
@ -71,6 +71,21 @@ extern "C" {
|
|||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief typedef for shadow types
|
||||
///
|
||||
/// Shadows are first created with the SHADOW_TRANSIENT type. This means that
|
||||
/// the shadow will exist only temporarily and will be destroyed when the
|
||||
/// refcount gets back to 0. Shadows of type SHADOW_PERSISTENT will remain in
|
||||
/// the shadow store even with a refcount of 0 until their ttl is over.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef enum {
|
||||
SHADOW_TRANSIENT = 1,
|
||||
SHADOW_PERSISTENT = 2
|
||||
}
|
||||
TRI_shadow_type_e;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief typedef for shadow ids
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -82,10 +97,12 @@ typedef TRI_voc_tick_t TRI_shadow_id;
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct TRI_shadow_s {
|
||||
TRI_shadow_id _id;
|
||||
int64_t _rc; // refcount
|
||||
double _timestamp; // creation timestamp
|
||||
void* _data;
|
||||
TRI_shadow_id _id;
|
||||
int64_t _rc; // refcount
|
||||
double _timestamp; // creation timestamp
|
||||
void* _data; // pointer to data
|
||||
bool _deleted; // deleted flag
|
||||
TRI_shadow_type_e _type; // transient or persistent
|
||||
}
|
||||
TRI_shadow_t;
|
||||
|
||||
|
@ -95,9 +112,10 @@ TRI_shadow_t;
|
|||
|
||||
typedef struct TRI_shadow_store_s {
|
||||
TRI_mutex_t _lock;
|
||||
TRI_associative_pointer_t _index;
|
||||
TRI_associative_pointer_t _ids; // ids
|
||||
TRI_associative_pointer_t _pointers; // data pointers
|
||||
|
||||
void (*destroyShadow) (struct TRI_shadow_store_s*, TRI_shadow_t*);
|
||||
void (*destroyShadow) (void*);
|
||||
}
|
||||
TRI_shadow_store_t;
|
||||
|
||||
|
@ -118,10 +136,12 @@ TRI_shadow_store_t;
|
|||
/// @brief creates a shadow data storage
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_shadow_store_t* TRI_CreateShadowStore (void (*destroy) (TRI_shadow_store_t*, TRI_shadow_t*));
|
||||
TRI_shadow_store_t* TRI_CreateShadowStore (void (*destroy) (void*));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destroys a shadow data storage
|
||||
///
|
||||
/// Note: all remaining shadows will be destroyed
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_FreeShadowStore (TRI_shadow_store_t* const store);
|
||||
|
@ -140,54 +160,103 @@ void TRI_FreeShadowStore (TRI_shadow_store_t* const store);
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief enumerate all shadows and remove them if expired
|
||||
/// @brief look up a shadow in the index using its data pointer and return
|
||||
/// its id
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_shadow_id TRI_GetIdDataShadowData (TRI_shadow_store_t* const,
|
||||
const void* const);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief look up a shadow in the index using its data pointer
|
||||
///
|
||||
/// If the shadow is found, this will return the data pointer, NULL otherwise.
|
||||
/// When the shadow is found, its refcount will also be increased by one
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void* TRI_BeginUsageDataShadowData (TRI_shadow_store_t* const, const void* const);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief look up a shadow in the index using its id
|
||||
///
|
||||
/// If the shadow is found, this will return the data pointer, NULL otherwise.
|
||||
/// When the shadow is found, its refcount will also be increased by one
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void* TRI_BeginUsageIdShadowData (TRI_shadow_store_t* const, const TRI_shadow_id);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief look up a shadow in the index using its data pointer
|
||||
///
|
||||
/// If the shadow is found, its refcount will be decreased by one.
|
||||
/// If the refcount is 0 and the shadow is of type SHADOW_TRANSIENT, the shadow
|
||||
/// object will be destroyed.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_EndUsageDataShadowData (TRI_shadow_store_t* const, const void* const);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief look up a shadow in the index using its id
|
||||
///
|
||||
/// If the shadow is found, its refcount will be decreased by one.
|
||||
/// If the refcount is 0 and the shadow is of type SHADOW_TRANSIENT, the shadow
|
||||
/// object will be destroyed.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_EndUsageIdShadowData (TRI_shadow_store_t* const, const TRI_shadow_id);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief set the persistence flag for a shadow using its data pointer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_PersistDataShadowData (TRI_shadow_store_t* const, const void* const);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief set the persistence flag for a shadow using its id
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_PersistIdShadowData (TRI_shadow_store_t* const, const TRI_shadow_id);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief set the deleted flag for a shadow using its data pointer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_DeleteDataShadowData (TRI_shadow_store_t* const, const void* const);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief set the deleted flag for a shadow using its id
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_DeleteIdShadowData (TRI_shadow_store_t* const, const TRI_shadow_id);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief enumerate all shadows and remove them if
|
||||
/// - their refcount is 0 and they are transient
|
||||
/// - their refcount is 0 and they are expired
|
||||
/// - the force flag is set
|
||||
///
|
||||
/// The max age must be specified in seconds
|
||||
/// The max age must be specified in seconds. The max age is ignored if the
|
||||
/// force flag is set. In this case all remaining shadows will be deleted
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_CleanupShadowData (TRI_shadow_store_t* const, const double);
|
||||
void TRI_CleanupShadowData (TRI_shadow_store_t* const, const double, const bool);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief looks up a shadow by id and decreases its refcount if it exists
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_DecreaseRefCountShadowData (TRI_shadow_store_t* const, const TRI_shadow_id);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief looks up a shadow by id and increases its refcount if it exists
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_IncreaseRefCountShadowData (TRI_shadow_store_t* const, const TRI_shadow_id);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief looks up shadow data
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_shadow_t* TRI_FindShadowData (TRI_shadow_store_t* const, const TRI_shadow_id);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief stores shadow data
|
||||
/// @brief store a new shadow in the store
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_shadow_t* TRI_StoreShadowData (TRI_shadow_store_t* const,
|
||||
const void* const);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief decrease the refcount of a shadow without deleting it
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int64_t TRI_DecreaseRefcountShadowData (TRI_shadow_store_t* const, TRI_shadow_t* const);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief releases shadow data
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_ReleaseShadowData (TRI_shadow_store_t* const, TRI_shadow_t*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- UNUSED AND UNTESTED CODE FOLLOWS
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- SHADOW DOCUMENTS
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -282,7 +351,7 @@ void TRI_CleanupShadowDocuments (TRI_shadow_document_store_t* const, const doubl
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1244,7 +1244,6 @@ static bool OpenIndexIterator (char const* filename, void* data) {
|
|||
lat = TRI_LookupArrayJson(json, "latitude");
|
||||
lon = TRI_LookupArrayJson(json, "longitude");
|
||||
gjs = TRI_LookupArrayJson(json, "geoJson");
|
||||
iid = 0;
|
||||
geoJson = false;
|
||||
|
||||
if (gjs != NULL && gjs->_type == TRI_JSON_BOOLEAN) {
|
||||
|
|
|
@ -450,14 +450,6 @@ TRI_vocbase_t* TRI_OpenVocBase (char const* path) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// set up shadow data stores for queries
|
||||
/* vocbase->_statements = TRI_CreateShadowsQueryTemplate();
|
||||
if (!vocbase->_statements) {
|
||||
TRI_Free(vocbase);
|
||||
LOG_ERROR("out of memory when opening vocbase");
|
||||
return NULL;
|
||||
}
|
||||
*/
|
||||
vocbase->_cursors = TRI_CreateShadowsQueryCursor();
|
||||
if (!vocbase->_cursors) {
|
||||
TRI_FreeShadowStore(vocbase->_cursors);
|
||||
|
@ -470,7 +462,6 @@ TRI_vocbase_t* TRI_OpenVocBase (char const* path) {
|
|||
vocbase->_path = TRI_DuplicateString(path);
|
||||
|
||||
if (!vocbase->_path) {
|
||||
// TRI_FreeShadowDocumentStore(vocbase->_statements);
|
||||
TRI_FreeShadowStore(vocbase->_cursors);
|
||||
TRI_Free(vocbase);
|
||||
LOG_ERROR("out of memory when opening vocbase");
|
||||
|
@ -528,12 +519,7 @@ void TRI_CloseVocBase (TRI_vocbase_t* vocbase) {
|
|||
// cursors
|
||||
TRI_FreeShadowStore(vocbase->_cursors);
|
||||
}
|
||||
/*
|
||||
if (vocbase->_statements) {
|
||||
// statements
|
||||
TRI_FreeShadowDocumentStore(vocbase->_statements);
|
||||
}
|
||||
*/
|
||||
|
||||
TRI_DestroyLockFile(vocbase->_lockFile);
|
||||
TRI_FreeString(vocbase->_lockFile);
|
||||
}
|
||||
|
|
|
@ -72,6 +72,18 @@ extern size_t PageSize;
|
|||
|
||||
#define DEFAULT_MAXIMAL_SIZE (1024 * 1024 * 128)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief document handle separator as character
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define TRI_DOCUMENT_HANDLE_SEPARATOR_CHR '/'
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief document handle separator as string
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define TRI_DOCUMENT_HANDLE_SEPARATOR_STR "/"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -89,7 +89,6 @@ function postCursor(req, res) {
|
|||
}
|
||||
|
||||
try {
|
||||
var cursor;
|
||||
var json = JSON.parse(req.requestBody);
|
||||
|
||||
if (!json || !(json instanceof Object)) {
|
||||
|
@ -97,18 +96,9 @@ function postCursor(req, res) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (json._id != undefined) {
|
||||
/*
|
||||
cursor = AQL_STORED_STATEMENT(db,
|
||||
json._id,
|
||||
json.bindVars,
|
||||
(json.count != undefined ? json.count : false),
|
||||
(json.batchSize != undefined ? json.batchSize : 1000));
|
||||
*/
|
||||
}
|
||||
else if (json.query != undefined) {
|
||||
cursor = AQL_STATEMENT(db,
|
||||
json.query,
|
||||
var cursor;
|
||||
if (json.query != undefined) {
|
||||
cursor = AQL_STATEMENT(json.query,
|
||||
json.bindVars,
|
||||
(json.count != undefined ? json.count : false),
|
||||
(json.batchSize != undefined ? json.batchSize : 1000));
|
||||
|
@ -145,7 +135,7 @@ function putCursor(req, res) {
|
|||
|
||||
try {
|
||||
var cursorId = decodeURIComponent(req.suffix[0]);
|
||||
var cursor = AQL_CURSOR(db, cursorId);
|
||||
var cursor = AQL_CURSOR(cursorId);
|
||||
if (!(cursor instanceof AvocadoQueryCursor)) {
|
||||
throw "cursor not found";
|
||||
}
|
||||
|
@ -170,7 +160,7 @@ function deleteCursor(req, res) {
|
|||
|
||||
try {
|
||||
var cursorId = decodeURIComponent(req.suffix[0]);
|
||||
var cursor = AQL_CURSOR(db, cursorId);
|
||||
var cursor = AQL_CURSOR(cursorId);
|
||||
if (!(cursor instanceof AvocadoQueryCursor)) {
|
||||
throw "cursor not found";
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ function postQuery(req, res) {
|
|||
return;
|
||||
}
|
||||
|
||||
var result = AQL_PARSE(db, json.query);
|
||||
var result = AQL_PARSE(json.query);
|
||||
if (result instanceof AvocadoQueryError) {
|
||||
actions.actionResultError (req, res, 404, result.code, result.message);
|
||||
return;
|
||||
|
|
|
@ -42,11 +42,32 @@ var simple = require("simple-query");
|
|||
// --SECTION-- private functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
function formatTimeStamp (timestamp) {
|
||||
var d = new Date(timestamp * 1000);
|
||||
|
||||
var year = d.getUTCFullYear();
|
||||
var month = d.getUTCMonth() + 1;
|
||||
var date = d.getUTCDate();
|
||||
|
||||
if (month < 10) month = "0" + month;
|
||||
if (date < 10) hour = "0" + date;
|
||||
|
||||
var hour = d.getUTCHours();
|
||||
var minutes = d.getUTCMinutes();
|
||||
var seconds = d.getUTCSeconds();
|
||||
|
||||
if (hour < 10) hour = "0" + hour;
|
||||
if (minutes < 10) minutes = "0" + minutes;
|
||||
if (seconds < 10) seconds = "0" + seconds;
|
||||
|
||||
return year + "-" + month + "-" + date + "T" + hour + ":" + minutes + ":" + seconds + "Z";
|
||||
}
|
||||
|
||||
function buildDocumentFromReq(req) {
|
||||
|
||||
// Example requests:
|
||||
// Header:
|
||||
// POST /_api/key/example_collection/example_key1
|
||||
// POST /_api/key/example_collection/example_key1 HTTP/1.1
|
||||
// Host: localhost:9000
|
||||
// x-voc-expires: 2011-09-29T08:00:00Z
|
||||
// x-voc-extended: {"option1":35,"option2":"x"}
|
||||
|
@ -67,8 +88,9 @@ function buildDocumentFromReq(req) {
|
|||
}
|
||||
|
||||
if (req.headers["x-voc-expires"] != undefined) {
|
||||
// TODO check value
|
||||
doc["x-voc-expires"] = req.headers["x-voc-expires"];
|
||||
var d = new Date(req.headers["x-voc-expires"]);
|
||||
// store time stamp as double
|
||||
doc["x-voc-expires"] = d.getTime() / 1000;
|
||||
}
|
||||
|
||||
if (req.headers["x-voc-extended"] != undefined) {
|
||||
|
@ -78,6 +100,7 @@ function buildDocumentFromReq(req) {
|
|||
}
|
||||
}
|
||||
|
||||
// store time stamp as double
|
||||
doc["x-voc-created"] = internal.time();
|
||||
|
||||
return doc;
|
||||
|
@ -97,9 +120,14 @@ function postKeyValue(req, res) {
|
|||
try {
|
||||
var collection = req.suffix[0];
|
||||
|
||||
if (db._collection(collection) == null) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotModified, "Collection not found.");
|
||||
return;
|
||||
}
|
||||
|
||||
var doc = buildDocumentFromReq(req);
|
||||
|
||||
var s = db[collection].select({ "key" : doc.key });
|
||||
var s = db[collection].byExample({"key" : doc.key});
|
||||
s.execute();
|
||||
|
||||
if (s._countTotal != 0) {
|
||||
|
@ -115,7 +143,7 @@ function postKeyValue(req, res) {
|
|||
}
|
||||
}
|
||||
catch (e) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotModified, "Key value pair not created.");
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotModified, "Key value pair not created. " + e.message);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,36 +153,59 @@ function postKeyValue(req, res) {
|
|||
|
||||
function putKeyValue(req, res) {
|
||||
if (req.suffix.length < 2) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotFound, "Key value pair not found");
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotModified, "Key value pair not found");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
var collection = req.suffix[0];
|
||||
|
||||
if (db._collection(collection) == null) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotModified, "Collection not found.");
|
||||
return;
|
||||
}
|
||||
|
||||
var doc = buildDocumentFromReq(req);
|
||||
|
||||
var s = db[collection].select({ "key" : doc.key });
|
||||
var s = db[collection].byExample({"key" : doc.key});
|
||||
s.execute();
|
||||
|
||||
if (s._countTotal < 1) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotFound, "Key value pair not found");
|
||||
if (req.parameters["create"] == 1) {
|
||||
var id = db[collection].save(doc);
|
||||
var result = {
|
||||
"saved" : true,
|
||||
"_id" : id
|
||||
}
|
||||
actions.actionResultOK(req, res, 201, result);
|
||||
return;
|
||||
}
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotModified, "Key value pair not found");
|
||||
}
|
||||
else if (s._countTotal > 1) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotFound, "Key value pair not found. Wrong key?");
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotModified, "Key value pair not found. Wrong key?");
|
||||
}
|
||||
else {
|
||||
// get _id
|
||||
var id = s._execution._documents[0]._id;
|
||||
|
||||
// save x-voc-created
|
||||
var created = s._execution._documents[0]["x-voc-created"];
|
||||
if (created != undefined) {
|
||||
doc["x-voc-created"] = created;
|
||||
}
|
||||
|
||||
// replace the document
|
||||
if (db[collection].replace(id, doc)) {
|
||||
actions.actionResultOK(req, res, 202, { "changed" : true });
|
||||
actions.actionResultOK(req, res, 202, {"changed" : true});
|
||||
}
|
||||
else {
|
||||
actions.actionResultError(req, res, 404, actions.keyValueNotFound, "Value not changed");
|
||||
actions.actionResultError(req, res, 404, actions.keyValueNotModified, "Value not changed");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotFound, "Key value pair not found");
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotModified, "Key value pair not found. " + e.message);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,40 +215,45 @@ function putKeyValue(req, res) {
|
|||
|
||||
function deleteKeyValue(req, res) {
|
||||
if (req.suffix.length < 2) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotFound, "Key value pair not found");
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotModified, "Key value pair not found");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
var collection = req.suffix[0];
|
||||
|
||||
if (db._collection(collection) == null) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotModified, "Collection not found.");
|
||||
return;
|
||||
}
|
||||
|
||||
var key = req.suffix[1];
|
||||
|
||||
for (var i = 2; i < req.suffix.length; ++i) {
|
||||
key += "/" + req.suffix[i];
|
||||
}
|
||||
|
||||
var s = db[collection].select({ "key" : key });
|
||||
var s = db[collection].byExample({"key" : key});
|
||||
s.execute();
|
||||
|
||||
if (s._countTotal < 1) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotFound, "Key value pair not found");
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotModified, "Key value pair not found");
|
||||
}
|
||||
else if (s._countTotal > 1) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotFound, "Key value pair not found. Wrong key?");
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotModified, "Key value pair not found. Wrong key?");
|
||||
}
|
||||
else {
|
||||
var id = s._execution._documents[0]._id;
|
||||
if (db[collection].delete(id)) {
|
||||
actions.actionResultOK(req, res, 202, { "removed" : true });
|
||||
actions.actionResultOK(req, res, 202, {"removed" : true});
|
||||
}
|
||||
else {
|
||||
actions.actionResultError(req, res, 404, actions.keyValueNotFound, "Value not removed");
|
||||
actions.actionResultError(req, res, 404, actions.keyValueNotModified, "Value not removed");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotFound, "Key value pair not found");
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotModified, "Key value pair not found. " + e.message);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -214,13 +270,18 @@ function getKeyValue(req, res) {
|
|||
try {
|
||||
var collection = req.suffix[0];
|
||||
|
||||
if (db._collection(collection) == null) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotFound, "Collection not found.");
|
||||
return;
|
||||
}
|
||||
|
||||
var key = req.suffix[1];
|
||||
|
||||
for (var i = 2; i < req.suffix.length; ++i) {
|
||||
key += "/" + req.suffix[i];
|
||||
}
|
||||
|
||||
var s = db[collection].select({ "key" : key });
|
||||
var s = db[collection].byExample({"key" : key});
|
||||
s.execute();
|
||||
|
||||
if (s._countTotal < 1) {
|
||||
|
@ -233,20 +294,23 @@ function getKeyValue(req, res) {
|
|||
var headers = {};
|
||||
|
||||
if (s._execution._documents[0]["x-voc-expires"] != undefined) {
|
||||
headers["x-voc-expires"] = s._execution._documents[0]["x-voc-expires"];
|
||||
// format timestamp
|
||||
headers["x-voc-expires"] = formatTimeStamp(s._execution._documents[0]["x-voc-expires"]);
|
||||
}
|
||||
if (s._execution._documents[0]["x-voc-extended"] != undefined) {
|
||||
// serialize header value
|
||||
headers["x-voc-extended"] = JSON.stringify(s._execution._documents[0]["x-voc-extended"]);
|
||||
}
|
||||
if (s._execution._documents[0]["x-voc-created"] != undefined) {
|
||||
headers["x-voc-created"] = s._execution._documents[0]["x-voc-created"];
|
||||
// format timestamp
|
||||
headers["x-voc-created"] = formatTimeStamp(s._execution._documents[0]["x-voc-created"]);
|
||||
}
|
||||
|
||||
actions.actionResultOK(req, res, 200, s._execution._documents[0].value, headers);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotFound, "Key value pair not found");
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotFound, "Key value pair not found. " + e.message);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -255,7 +319,7 @@ function getKeyValue(req, res) {
|
|||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief cursor actions gateway
|
||||
/// @brief key value pair actions gateway
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
actions.defineHttp({
|
||||
|
@ -264,19 +328,19 @@ actions.defineHttp({
|
|||
|
||||
callback : function (req, res) {
|
||||
switch (req.requestType) {
|
||||
case ("POST") :
|
||||
case ("POST") :
|
||||
postKeyValue(req, res);
|
||||
break;
|
||||
|
||||
case ("GET") :
|
||||
case ("GET") :
|
||||
getKeyValue(req, res);
|
||||
break;
|
||||
|
||||
case ("PUT") :
|
||||
case ("PUT") :
|
||||
putKeyValue(req, res);
|
||||
break;
|
||||
|
||||
case ("DELETE") :
|
||||
case ("DELETE") :
|
||||
deleteKeyValue(req, res);
|
||||
break;
|
||||
|
||||
|
@ -286,6 +350,94 @@ actions.defineHttp({
|
|||
}
|
||||
});
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup AvocadoAPI
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief key value pair search
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function searchKeyValue(req, res) {
|
||||
if (req.suffix.length < 2) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotFound, "Key value pairs not found.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
var collection = req.suffix[0];
|
||||
|
||||
if (db._collection(collection) == null) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotFound, "Collection not found.");
|
||||
return;
|
||||
}
|
||||
|
||||
var prefix = req.suffix[1];
|
||||
|
||||
for (var i = 2; i < req.suffix.length; ++i) {
|
||||
prefix += "/" + req.suffix[i];
|
||||
}
|
||||
|
||||
//
|
||||
// TODO: build a query which selects the keys
|
||||
//
|
||||
|
||||
var query = "select f from " + collection + " f ";
|
||||
var bindVars = {};
|
||||
var cursor = AQL_STATEMENT(db,
|
||||
query,
|
||||
bindVars,
|
||||
false,
|
||||
1000);
|
||||
result = [];
|
||||
while (cursor.hasNext() ) {
|
||||
var doc = cursor.next();
|
||||
if (doc["key"] != undefined && doc["key"].indexOf(prefix) === 0) {
|
||||
result.push(doc["key"]);
|
||||
}
|
||||
}
|
||||
|
||||
actions.actionResult (req, res, 200, result);
|
||||
}
|
||||
catch (e) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotFound, "Key value pairs not found. " + e.message);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- initialiser
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief key value pair actions gateway
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
actions.defineHttp({
|
||||
url : "_api/keys",
|
||||
context : "api",
|
||||
|
||||
callback : function (req, res) {
|
||||
switch (req.requestType) {
|
||||
case ("GET") :
|
||||
searchKeyValue(req, res);
|
||||
break;
|
||||
|
||||
default:
|
||||
actions.actionResultUnsupported(req, res);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -26,27 +26,6 @@ static string JS_server_server =
|
|||
"/// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"/// @page JSModuleAvocadoTOC\n"
|
||||
"///\n"
|
||||
"/// <ol>\n"
|
||||
"/// <li>@ref JSModuleAvocadoDefineHttpSystemAction \"avocado.defineHttpSystemAction\"</li>\n"
|
||||
"/// </ol>\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"/// @page JSModuleAvocado Module \"avocado\"\n"
|
||||
"///\n"
|
||||
"/// The following functions are used avocadoly.\n"
|
||||
"///\n"
|
||||
"/// <hr>\n"
|
||||
"/// @copydoc JSModuleAvocadoTOC\n"
|
||||
"/// <hr>\n"
|
||||
"///\n"
|
||||
"/// @anchor JSModuleAvocadoDefineHttpSystemAction\n"
|
||||
"/// @copydetails JS_DefineSystemAction\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"// -----------------------------------------------------------------------------\n"
|
||||
"// --SECTION-- Module \"internal\"\n"
|
||||
"// -----------------------------------------------------------------------------\n"
|
||||
|
@ -79,31 +58,6 @@ static string JS_server_server =
|
|||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"// -----------------------------------------------------------------------------\n"
|
||||
"// --SECTION-- Module \"avocado\"\n"
|
||||
"// -----------------------------------------------------------------------------\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"/// @addtogroup V8ModuleAvocado\n"
|
||||
"/// @{\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"/// @brief avocado module\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"ModuleCache[\"/avocado\"] = new Module(\"/avocado\");\n"
|
||||
"\n"
|
||||
"if (typeof defineSystemAction == \"function\") {\n"
|
||||
" ModuleCache[\"/avocado\"].exports.defineHttpSystemAction = defineSystemAction;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"avocado = ModuleCache[\"/avocado\"].exports;\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"/// @}\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"// -----------------------------------------------------------------------------\n"
|
||||
"// --SECTION-- Module \"simple-query\"\n"
|
||||
"// -----------------------------------------------------------------------------\n"
|
||||
"\n"
|
||||
|
@ -124,7 +78,7 @@ static string JS_server_server =
|
|||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"// -----------------------------------------------------------------------------\n"
|
||||
"// --SECTION-- PRINT\n"
|
||||
"// --SECTION-- ShapedJson\n"
|
||||
"// -----------------------------------------------------------------------------\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
|
@ -149,6 +103,75 @@ static string JS_server_server =
|
|||
"/// @}\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"// -----------------------------------------------------------------------------\n"
|
||||
"// --SECTION-- AvocadoDatabase\n"
|
||||
"// -----------------------------------------------------------------------------\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"/// @addtogroup V8Shell\n"
|
||||
"/// @{\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"/// @brief drops a collection\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"AvocadoDatabase.prototype._drop = function(name) {\n"
|
||||
" var collection = name;\n"
|
||||
"\n"
|
||||
" if (typeof name === \"string\") {\n"
|
||||
" collection = db[name];\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" // new born collection\n"
|
||||
" if (collection.status() == 1) {\n"
|
||||
" return;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" // drop all indexes\n"
|
||||
" var idx = collection.getIndexes();\n"
|
||||
"\n"
|
||||
" for (var i = 0; i < idx.length; ++i) {\n"
|
||||
" collection.dropIndex(idx[i].iid);\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" // delete all documents\n"
|
||||
" var all = collection.all();\n"
|
||||
"\n"
|
||||
" while (all.hasNext()) {\n"
|
||||
" var ref = all.nextRef();\n"
|
||||
"\n"
|
||||
" collection.delete(ref);\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"AvocadoEdges.prototype._drop = AvocadoDatabase._drop;\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"/// @}\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"// -----------------------------------------------------------------------------\n"
|
||||
"// --SECTION-- AvocadoCollection\n"
|
||||
"// -----------------------------------------------------------------------------\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"/// @addtogroup V8Shell\n"
|
||||
"/// @{\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"/// @brief drops a collection\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"AvocadoCollection.prototype.drop = function() {\n"
|
||||
" db._drop(this);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"/// @}\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"// Local Variables:\n"
|
||||
"// mode: outline-minor\n"
|
||||
"// outline-regexp: \"^\\\\(/// @brief\\\\|/// @addtogroup\\\\|// --SECTION--\\\\|/// @page\\\\|/// @}\\\\)\"\n"
|
||||
|
|
|
@ -786,7 +786,7 @@ SimpleQueryByExample.prototype.execute = function () {
|
|||
}
|
||||
}
|
||||
|
||||
var cursor = AQL_STATEMENT(db, queryString, undefined);
|
||||
var cursor = AQL_STATEMENT(queryString, undefined);
|
||||
if (cursor instanceof AvocadoQueryError) {
|
||||
throw cursor.message;
|
||||
}
|
||||
|
|
|
@ -25,27 +25,6 @@
|
|||
/// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @page JSModuleAvocadoTOC
|
||||
///
|
||||
/// <ol>
|
||||
/// <li>@ref JSModuleAvocadoDefineHttpSystemAction "avocado.defineHttpSystemAction"</li>
|
||||
/// </ol>
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @page JSModuleAvocado Module "avocado"
|
||||
///
|
||||
/// The following functions are used avocadoly.
|
||||
///
|
||||
/// <hr>
|
||||
/// @copydoc JSModuleAvocadoTOC
|
||||
/// <hr>
|
||||
///
|
||||
/// @anchor JSModuleAvocadoDefineHttpSystemAction
|
||||
/// @copydetails JS_DefineSystemAction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- Module "internal"
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -77,31 +56,6 @@ else {
|
|||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- Module "avocado"
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup V8ModuleAvocado
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief avocado module
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ModuleCache["/avocado"] = new Module("/avocado");
|
||||
|
||||
if (typeof defineSystemAction == "function") {
|
||||
ModuleCache["/avocado"].exports.defineHttpSystemAction = defineSystemAction;
|
||||
}
|
||||
|
||||
avocado = ModuleCache["/avocado"].exports;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- Module "simple-query"
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -123,7 +77,7 @@ catch (err) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- PRINT
|
||||
// --SECTION-- ShapedJson
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -148,6 +102,75 @@ ShapedJson.prototype._PRINT = function(seen, path, names) {
|
|||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- AvocadoDatabase
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup V8Shell
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief drops a collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AvocadoDatabase.prototype._drop = function(name) {
|
||||
var collection = name;
|
||||
|
||||
if (typeof name === "string") {
|
||||
collection = db[name];
|
||||
}
|
||||
|
||||
// new born collection
|
||||
if (collection.status() == 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// drop all indexes
|
||||
var idx = collection.getIndexes();
|
||||
|
||||
for (var i = 0; i < idx.length; ++i) {
|
||||
collection.dropIndex(idx[i].iid);
|
||||
}
|
||||
|
||||
// delete all documents
|
||||
var all = collection.all();
|
||||
|
||||
while (all.hasNext()) {
|
||||
var ref = all.nextRef();
|
||||
|
||||
collection.delete(ref);
|
||||
}
|
||||
}
|
||||
|
||||
AvocadoEdges.prototype._drop = AvocadoDatabase._drop;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- AvocadoCollection
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup V8Shell
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief drops a collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AvocadoCollection.prototype.drop = function() {
|
||||
db._drop(this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)"
|
||||
|
|
|
@ -60,7 +60,7 @@ function aqlBindParametersTestSuite () {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function executeQuery (query, bindParameters) {
|
||||
var cursor = AQL_STATEMENT(db, query, bindParameters);
|
||||
var cursor = AQL_STATEMENT(query, bindParameters);
|
||||
assertFalse(cursor instanceof AvocadoQueryError);
|
||||
return cursor;
|
||||
}
|
||||
|
|
|
@ -111,7 +111,7 @@ function aqlJoinsTestSuite () {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function executeQuery (query) {
|
||||
var cursor = AQL_STATEMENT(db, query, undefined);
|
||||
var cursor = AQL_STATEMENT(query, undefined);
|
||||
assertFalse(cursor instanceof AvocadoQueryError);
|
||||
return cursor;
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ function aqlKeywordsTestSuite () {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function executeQuery (query, expectError) {
|
||||
var cursor = AQL_STATEMENT(db, query, undefined);
|
||||
var cursor = AQL_STATEMENT(query, undefined);
|
||||
if (expectError) {
|
||||
assertTrue(cursor instanceof AvocadoQueryError);
|
||||
return null;
|
||||
|
|
|
@ -60,7 +60,7 @@ function aqlSimpleTestSuite () {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function executeQuery (query) {
|
||||
var cursor = AQL_STATEMENT(db, query, undefined);
|
||||
var cursor = AQL_STATEMENT(query, undefined);
|
||||
if (cursor instanceof AvocadoQueryError) {
|
||||
print(query, cursor.message);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue