mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel'
This commit is contained in:
commit
a8558a1c67
|
@ -202,6 +202,8 @@ ALIASES += FN{1}="<tt>\1</tt>"
|
|||
ALIASES += VAR{1}="<tt>\1</tt>"
|
||||
ALIASES += LIT{1}="<tt>\1</tt>"
|
||||
ALIASES += CODE{1}="<tt>\1</tt>"
|
||||
ALIASES += CODE{2}="<tt>\1, \2</tt>"
|
||||
ALIASES += CODE{3}="<tt>\1, \2, \3</tt>"
|
||||
ALIASES += CMDOPT{1}="<tt><b>\1</b></tt>"
|
||||
ALIASES += CA{1}="<var>\1</var>"
|
||||
ALIASES += CO{1}="<tt>\1</tt>"
|
||||
|
|
|
@ -368,10 +368,8 @@ HashIndex* HashIndex_new() {
|
|||
int HashIndex_add(HashIndex* hashIndex, HashIndexElement* element) {
|
||||
bool result;
|
||||
result = TRI_InsertElementAssociativeArray(hashIndex->assocArray.uniqueArray, element, false);
|
||||
if (result) {
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
|
||||
return result ? TRI_ERROR_NO_ERROR : TRI_ERROR_AVOCADO_UNIQUE_CONSTRAINT_VIOLATED;
|
||||
}
|
||||
|
||||
|
||||
|
@ -413,11 +411,11 @@ int HashIndex_insert(HashIndex* hashIndex, HashIndexElement* element) {
|
|||
// Removes an entry from the associative array
|
||||
// ...............................................................................
|
||||
|
||||
bool HashIndex_remove(HashIndex* hashIndex, HashIndexElement* element) {
|
||||
int HashIndex_remove(HashIndex* hashIndex, HashIndexElement* element) {
|
||||
bool result;
|
||||
|
||||
result = TRI_RemoveElementAssociativeArray(hashIndex->assocArray.uniqueArray, element, NULL);
|
||||
return result;
|
||||
return result ? TRI_ERROR_NO_ERROR : TRI_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -426,10 +424,10 @@ bool HashIndex_remove(HashIndex* hashIndex, HashIndexElement* element) {
|
|||
// then adds the afterElement
|
||||
// ...............................................................................
|
||||
|
||||
bool HashIndex_update(HashIndex* hashIndex, const HashIndexElement* beforeElement,
|
||||
int HashIndex_update(HashIndex* hashIndex, const HashIndexElement* beforeElement,
|
||||
const HashIndexElement* afterElement) {
|
||||
assert(false);
|
||||
return false;
|
||||
return TRI_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -640,10 +638,10 @@ int MultiHashIndex_insert(HashIndex* hashIndex, HashIndexElement* element) {
|
|||
// Removes an entry from the associative array
|
||||
// ...............................................................................
|
||||
|
||||
bool MultiHashIndex_remove(HashIndex* hashIndex, HashIndexElement* element) {
|
||||
int MultiHashIndex_remove(HashIndex* hashIndex, HashIndexElement* element) {
|
||||
bool result;
|
||||
result = TRI_RemoveElementMultiArray(hashIndex->assocArray.nonUniqueArray, element, NULL);
|
||||
return result;
|
||||
return result ? TRI_ERROR_NO_ERROR : TRI_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -652,8 +650,8 @@ bool MultiHashIndex_remove(HashIndex* hashIndex, HashIndexElement* element) {
|
|||
// then adds the afterElement
|
||||
// ...............................................................................
|
||||
|
||||
bool MultiHashIndex_update(HashIndex* hashIndex, HashIndexElement* beforeElement,
|
||||
int MultiHashIndex_update(HashIndex* hashIndex, HashIndexElement* beforeElement,
|
||||
HashIndexElement* afterElement) {
|
||||
assert(false);
|
||||
return false;
|
||||
return TRI_ERROR_INTERNAL;
|
||||
}
|
||||
|
|
|
@ -35,6 +35,9 @@
|
|||
/// @author Copyright 2011, triagens GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TRI_HASH_INDEX_H
|
||||
#define TRI_HASH_INDEX_H 1
|
||||
|
||||
#include <BasicsC/common.h>
|
||||
#include <BasicsC/associative.h>
|
||||
#include <BasicsC/associative-multi.h>
|
||||
|
@ -82,9 +85,9 @@ HashIndexElements* HashIndex_find (HashIndex*, HashIndexElement*);
|
|||
|
||||
int HashIndex_insert (HashIndex*, HashIndexElement*);
|
||||
|
||||
bool HashIndex_remove (HashIndex*, HashIndexElement*);
|
||||
int HashIndex_remove (HashIndex*, HashIndexElement*);
|
||||
|
||||
bool HashIndex_update (HashIndex*, const HashIndexElement*, const HashIndexElement*);
|
||||
int HashIndex_update (HashIndex*, const HashIndexElement*, const HashIndexElement*);
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -102,6 +105,8 @@ HashIndexElements* MultiHashIndex_find (HashIndex*, HashIndexElement*);
|
|||
|
||||
int MultiHashIndex_insert (HashIndex*, HashIndexElement*);
|
||||
|
||||
bool MultiHashIndex_remove (HashIndex*, HashIndexElement*);
|
||||
int MultiHashIndex_remove (HashIndex*, HashIndexElement*);
|
||||
|
||||
bool MultiHashIndex_update (HashIndex*, HashIndexElement*, HashIndexElement*);
|
||||
int MultiHashIndex_update (HashIndex*, HashIndexElement*, HashIndexElement*);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -316,7 +316,7 @@ void AvocadoServer::buildApplicationServer () {
|
|||
map<string, ProgramOptionsDescription> additional;
|
||||
|
||||
additional[ApplicationServer::OPTIONS_CMDLINE]
|
||||
("shell", "do not start as server, start in shell mode instead")
|
||||
("console", "do not start as server, start an emergency console instead")
|
||||
;
|
||||
|
||||
additional[ApplicationServer::OPTIONS_CMDLINE + ":help-extended"]
|
||||
|
@ -459,7 +459,7 @@ void AvocadoServer::buildApplicationServer () {
|
|||
// in shell mode ignore the rest
|
||||
// .............................................................................
|
||||
|
||||
if (_applicationServer->programOptions().has("shell")) {
|
||||
if (_applicationServer->programOptions().has("console")) {
|
||||
executeShell();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
|
|
@ -46,7 +46,8 @@
|
|||
/// @page GlossaryDocument
|
||||
///
|
||||
/// @GE{Document}: Documents in AvocadoDB are JSON objects. These objects can be
|
||||
/// nested (to any depth) and may contains lists.
|
||||
/// nested (to any depth) and may contains lists. Each document is unique identified
|
||||
/// by its document handle.
|
||||
///
|
||||
/// @page GlossaryDocumentHandle
|
||||
///
|
||||
|
|
|
@ -86,9 +86,14 @@
|
|||
/////////////////////////////////////////////////////////////////
|
||||
///
|
||||
/// 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:
|
||||
/// defines a document and is managed by AvocadoDB. All documents are
|
||||
/// found under the URI
|
||||
///
|
||||
/// @LIT{document/@FA{document-handle}}
|
||||
///
|
||||
/// For exmaple: Assume that the document handle, which is stored in
|
||||
/// the @LIT{_id} field of the document, is @LIT{7254820/362549736},
|
||||
/// then the URL of that document is:
|
||||
///
|
||||
/// @LIT{http://localhost:8529/document/7254820/362549736}
|
||||
///
|
||||
|
|
|
@ -2025,7 +2025,7 @@ static v8::Handle<v8::Value> JS_SkiplistSelectAql (v8::Arguments const& argv) {
|
|||
if (idx == NULL) {
|
||||
return scope.Close(v8::ThrowException(v8::String::New("invalid index in where statement")));
|
||||
}
|
||||
if (! CheckWhereSkiplistOperators(idx->_shapeList->_length, slWhere->_operator)) {
|
||||
if (! CheckWhereSkiplistOperators(idx->_paths._length, slWhere->_operator)) {
|
||||
return scope.Close(v8::ThrowException(v8::String::New("One or more operators has invalid number of attributes")));
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ static bool CreateJournal (TRI_blob_collection_t* collection) {
|
|||
TRI_datafile_t* journal;
|
||||
TRI_df_marker_t* position;
|
||||
bool ok;
|
||||
int res;
|
||||
char* filename;
|
||||
char* jname;
|
||||
char* number;
|
||||
|
@ -95,9 +96,9 @@ static bool CreateJournal (TRI_blob_collection_t* collection) {
|
|||
TRI_FreeString(filename);
|
||||
|
||||
// create a collection header
|
||||
ok = TRI_ReserveElementDatafile(journal, sizeof(TRI_col_header_marker_t), &position);
|
||||
res = TRI_ReserveElementDatafile(journal, sizeof(TRI_col_header_marker_t), &position);
|
||||
|
||||
if (! ok) {
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
TRI_FreeDatafile(journal);
|
||||
|
||||
LOG_ERROR("cannot create document header in journal '%s': %s",
|
||||
|
@ -117,9 +118,10 @@ static bool CreateJournal (TRI_blob_collection_t* collection) {
|
|||
cm._cid = collection->base._cid;
|
||||
|
||||
TRI_FillCrcMarkerDatafile(&cm.base, sizeof(cm), 0, 0);
|
||||
ok = TRI_WriteElementDatafile(journal, position, &cm.base, sizeof(cm), 0, 0, true);
|
||||
|
||||
if (! ok) {
|
||||
res = TRI_WriteElementDatafile(journal, position, &cm.base, sizeof(cm), 0, 0, true);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
TRI_FreeDatafile(journal);
|
||||
|
||||
LOG_ERROR("cannot create document header in journal '%s': %s",
|
||||
|
@ -202,6 +204,7 @@ static TRI_datafile_t* SelectJournal (TRI_blob_collection_t* collection,
|
|||
TRI_df_marker_t** result) {
|
||||
TRI_datafile_t* datafile;
|
||||
bool ok;
|
||||
int res;
|
||||
size_t n;
|
||||
|
||||
// need to create a new journal?
|
||||
|
@ -220,9 +223,9 @@ static TRI_datafile_t* SelectJournal (TRI_blob_collection_t* collection,
|
|||
datafile = collection->base._journals._buffer[0];
|
||||
|
||||
// try to reserve space
|
||||
ok = TRI_ReserveElementDatafile(datafile, size, result);
|
||||
res = TRI_ReserveElementDatafile(datafile, size, result);
|
||||
|
||||
while (! ok && TRI_errno() == TRI_ERROR_AVOCADO_DATAFILE_FULL) {
|
||||
while (res == TRI_ERROR_AVOCADO_DATAFILE_FULL) {
|
||||
ok = CloseJournal(collection, datafile);
|
||||
|
||||
if (! ok) {
|
||||
|
@ -238,10 +241,10 @@ static TRI_datafile_t* SelectJournal (TRI_blob_collection_t* collection,
|
|||
|
||||
datafile = collection->base._journals._buffer[0];
|
||||
|
||||
ok = TRI_ReserveElementDatafile(datafile, size, result);
|
||||
res = TRI_ReserveElementDatafile(datafile, size, result);
|
||||
}
|
||||
|
||||
if (! ok) {
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
collection->base._state = TRI_COL_STATE_WRITE_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
|
@ -254,22 +257,22 @@ static TRI_datafile_t* SelectJournal (TRI_blob_collection_t* collection,
|
|||
/// @brief writes an element to a given position
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool WriteElement (TRI_blob_collection_t* collection,
|
||||
TRI_datafile_t* journal,
|
||||
TRI_df_marker_t* position,
|
||||
TRI_df_marker_t* marker,
|
||||
TRI_voc_size_t markerSize,
|
||||
static int WriteElement (TRI_blob_collection_t* collection,
|
||||
TRI_datafile_t* journal,
|
||||
TRI_df_marker_t* position,
|
||||
TRI_df_marker_t* marker,
|
||||
TRI_voc_size_t markerSize,
|
||||
void const* body,
|
||||
size_t bodySize) {
|
||||
bool ok;
|
||||
size_t bodySize) {
|
||||
int res;
|
||||
|
||||
ok = TRI_WriteElementDatafile(journal, position, marker, markerSize, body, bodySize, true);
|
||||
res = TRI_WriteElementDatafile(journal, position, marker, markerSize, body, bodySize, true);
|
||||
|
||||
if (! ok) {
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
collection->base._state = TRI_COL_STATE_WRITE_ERROR;
|
||||
}
|
||||
|
||||
return ok;
|
||||
return res;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -357,14 +360,14 @@ void TRI_FreeBlobCollection (TRI_blob_collection_t* collection) {
|
|||
/// @brief writes an element splitted into marker and body to file
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_WriteBlobCollection (TRI_blob_collection_t* collection,
|
||||
TRI_df_marker_t* marker,
|
||||
TRI_voc_size_t markerSize,
|
||||
void const* body,
|
||||
TRI_voc_size_t bodySize,
|
||||
TRI_df_marker_t** result) {
|
||||
int TRI_WriteBlobCollection (TRI_blob_collection_t* collection,
|
||||
TRI_df_marker_t* marker,
|
||||
TRI_voc_size_t markerSize,
|
||||
void const* body,
|
||||
TRI_voc_size_t bodySize,
|
||||
TRI_df_marker_t** result) {
|
||||
TRI_datafile_t* journal;
|
||||
bool ok;
|
||||
int res;
|
||||
|
||||
// generate a new tick
|
||||
marker->_tick = TRI_NewTickVocBase();
|
||||
|
@ -394,12 +397,12 @@ bool TRI_WriteBlobCollection (TRI_blob_collection_t* collection,
|
|||
}
|
||||
|
||||
// and write marker and blob
|
||||
ok = WriteElement(collection, journal, *result, marker, markerSize, body, bodySize);
|
||||
res = WriteElement(collection, journal, *result, marker, markerSize, body, bodySize);
|
||||
|
||||
// release lock on collection
|
||||
TRI_UnlockMutex(&collection->_lock);
|
||||
|
||||
return ok;
|
||||
return res;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -117,12 +117,12 @@ void TRI_FreeBlobCollection (TRI_blob_collection_t* collection);
|
|||
/// @brief writes an element splitted into marker and body to file
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_WriteBlobCollection (TRI_blob_collection_t* collection,
|
||||
TRI_df_marker_t* marker,
|
||||
TRI_voc_size_t markerSize,
|
||||
void const* body,
|
||||
TRI_voc_size_t bodySize,
|
||||
TRI_df_marker_t** result);
|
||||
int TRI_WriteBlobCollection (TRI_blob_collection_t* collection,
|
||||
TRI_df_marker_t* marker,
|
||||
TRI_voc_size_t markerSize,
|
||||
void const* body,
|
||||
TRI_voc_size_t bodySize,
|
||||
TRI_df_marker_t** result);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief opens an existing collection
|
||||
|
|
|
@ -112,10 +112,10 @@ static TRI_datafile_t* SelectCompactor (TRI_sim_collection_t* collection,
|
|||
/// @brief write document to file
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool CopyDocument (TRI_sim_collection_t* collection,
|
||||
TRI_df_marker_t const* marker,
|
||||
TRI_df_marker_t** result,
|
||||
TRI_voc_fid_t* fid) {
|
||||
static int CopyDocument (TRI_sim_collection_t* collection,
|
||||
TRI_df_marker_t const* marker,
|
||||
TRI_df_marker_t** result,
|
||||
TRI_voc_fid_t* fid) {
|
||||
TRI_datafile_t* journal;
|
||||
TRI_voc_size_t total;
|
||||
|
||||
|
@ -140,6 +140,10 @@ static bool CopyDocument (TRI_sim_collection_t* collection,
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief callback to delete datafile
|
||||
///
|
||||
/// Note that a datafile pointer is never freed. The state of the datafile
|
||||
/// will be switch to TRI_DF_STATE_CLOSED - but the datafile pointer is
|
||||
/// still valid.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void RemoveDatafileCallback (TRI_datafile_t* datafile, void* data) {
|
||||
|
@ -189,7 +193,7 @@ static bool Compactifier (TRI_df_marker_t const* marker, void* data, TRI_datafil
|
|||
TRI_doc_mptr_t const* found;
|
||||
TRI_sim_collection_t* collection;
|
||||
TRI_voc_fid_t fid;
|
||||
bool ok;
|
||||
int res;
|
||||
union { TRI_doc_mptr_t const* c; TRI_doc_mptr_t* v; } cnv;
|
||||
|
||||
collection = data;
|
||||
|
@ -226,9 +230,9 @@ static bool Compactifier (TRI_df_marker_t const* marker, void* data, TRI_datafil
|
|||
TRI_ReadUnlockReadWriteLock(&collection->_lock);
|
||||
|
||||
// write to compactor files
|
||||
ok = CopyDocument(collection, marker, &result, &fid);
|
||||
res = CopyDocument(collection, marker, &result, &fid);
|
||||
|
||||
if (! ok) {
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
LOG_FATAL("cannot write compactor file: ", TRI_last_error());
|
||||
return false;
|
||||
}
|
||||
|
@ -269,9 +273,9 @@ static bool Compactifier (TRI_df_marker_t const* marker, void* data, TRI_datafil
|
|||
// TODO: remove TRI_doc_deletion_marker_t from file
|
||||
|
||||
// write to compactor files
|
||||
ok = CopyDocument(collection, marker, &result, &fid);
|
||||
res = CopyDocument(collection, marker, &result, &fid);
|
||||
|
||||
if (! ok) {
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
LOG_FATAL("cannot write compactor file: ", TRI_last_error());
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -340,9 +340,9 @@ TRI_datafile_t* TRI_CreateDatafile (char const* filename, TRI_voc_size_t maximal
|
|||
TRI_df_header_marker_t header;
|
||||
TRI_df_marker_t* position;
|
||||
TRI_voc_tick_t tick;
|
||||
bool ok;
|
||||
char zero;
|
||||
int fd;
|
||||
int result;
|
||||
off_t offset;
|
||||
ssize_t res;
|
||||
void* data;
|
||||
|
@ -355,7 +355,6 @@ TRI_datafile_t* TRI_CreateDatafile (char const* filename, TRI_voc_size_t maximal
|
|||
TRI_set_errno(TRI_ERROR_AVOCADO_MAXIMAL_SIZE_TOO_SMALL);
|
||||
|
||||
LOG_ERROR("cannot create datafile '%s', maximal size '%u' is too small", filename, (unsigned int) maximalSize);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -366,7 +365,6 @@ TRI_datafile_t* TRI_CreateDatafile (char const* filename, TRI_voc_size_t maximal
|
|||
TRI_set_errno(TRI_ERROR_SYS_ERROR);
|
||||
|
||||
LOG_ERROR("cannot create datafile '%s': '%s'", filename, TRI_last_error());
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -378,7 +376,6 @@ TRI_datafile_t* TRI_CreateDatafile (char const* filename, TRI_voc_size_t maximal
|
|||
close(fd);
|
||||
|
||||
LOG_ERROR("cannot seek in datafile '%s': '%s'", filename, TRI_last_error());
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -390,7 +387,6 @@ TRI_datafile_t* TRI_CreateDatafile (char const* filename, TRI_voc_size_t maximal
|
|||
close(fd);
|
||||
|
||||
LOG_ERROR("cannot create sparse datafile '%s': '%s'", filename, TRI_last_error());
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -402,7 +398,6 @@ TRI_datafile_t* TRI_CreateDatafile (char const* filename, TRI_voc_size_t maximal
|
|||
close(fd);
|
||||
|
||||
LOG_ERROR("cannot memory map file '%s': '%s'", filename, TRI_last_error());
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -411,8 +406,13 @@ TRI_datafile_t* TRI_CreateDatafile (char const* filename, TRI_voc_size_t maximal
|
|||
|
||||
// create datafile structure
|
||||
datafile = TRI_Allocate(sizeof(TRI_datafile_t));
|
||||
if (!datafile) {
|
||||
// TODO: FIXME
|
||||
|
||||
if (datafile == NULL) {
|
||||
TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
|
||||
close(fd);
|
||||
|
||||
LOG_ERROR("out-of-memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
InitDatafile(datafile,
|
||||
|
@ -440,13 +440,13 @@ TRI_datafile_t* TRI_CreateDatafile (char const* filename, TRI_voc_size_t maximal
|
|||
TRI_FillCrcMarkerDatafile(&header.base, sizeof(TRI_df_header_marker_t), 0, 0);
|
||||
|
||||
// reserve space and write header to file
|
||||
ok = TRI_ReserveElementDatafile(datafile, header.base._size, &position);
|
||||
result = TRI_ReserveElementDatafile(datafile, header.base._size, &position);
|
||||
|
||||
if (ok) {
|
||||
ok = TRI_WriteElementDatafile(datafile, position, &header.base, header.base._size, 0, 0, true);
|
||||
if (result == TRI_ERROR_NO_ERROR) {
|
||||
result = TRI_WriteElementDatafile(datafile, position, &header.base, header.base._size, 0, 0, true);
|
||||
}
|
||||
|
||||
if (! ok) {
|
||||
if (result != TRI_ERROR_NO_ERROR) {
|
||||
LOG_ERROR("cannot write header to datafile '%s'",
|
||||
filename);
|
||||
|
||||
|
@ -555,23 +555,20 @@ void TRI_FillCrcMarkerDatafile (TRI_df_marker_t* marker,
|
|||
/// @brief reserves room for an element, advances the pointer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_ReserveElementDatafile (TRI_datafile_t* datafile,
|
||||
TRI_voc_size_t size,
|
||||
TRI_df_marker_t** position) {
|
||||
int TRI_ReserveElementDatafile (TRI_datafile_t* datafile,
|
||||
TRI_voc_size_t size,
|
||||
TRI_df_marker_t** position) {
|
||||
*position = 0;
|
||||
size = ((size + TRI_DF_BLOCK_ALIGN - 1) / TRI_DF_BLOCK_ALIGN) * TRI_DF_BLOCK_ALIGN;
|
||||
|
||||
if (datafile->_state != TRI_DF_STATE_WRITE) {
|
||||
if (datafile->_state == TRI_DF_STATE_READ) {
|
||||
TRI_set_errno(TRI_ERROR_AVOCADO_READ_ONLY);
|
||||
|
||||
LOG_ERROR("cannot reserve marker, datafile is read-only");
|
||||
|
||||
return false;
|
||||
return TRI_set_errno(TRI_ERROR_AVOCADO_READ_ONLY);
|
||||
}
|
||||
|
||||
TRI_set_errno(TRI_ERROR_AVOCADO_ILLEGAL_STATE);
|
||||
return false;
|
||||
return TRI_set_errno(TRI_ERROR_AVOCADO_ILLEGAL_STATE);
|
||||
}
|
||||
|
||||
// add the marker, leave enough room for the footer
|
||||
|
@ -581,7 +578,7 @@ bool TRI_ReserveElementDatafile (TRI_datafile_t* datafile,
|
|||
|
||||
LOG_TRACE("cannot write marker, not enough space");
|
||||
|
||||
return false;
|
||||
return datafile->_lastError;
|
||||
}
|
||||
|
||||
*position = (TRI_df_marker_t*) datafile->_next;
|
||||
|
@ -589,20 +586,20 @@ bool TRI_ReserveElementDatafile (TRI_datafile_t* datafile,
|
|||
datafile->_next += size;
|
||||
datafile->_currentSize += size;
|
||||
|
||||
return true;
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief writes a marker and body to the datafile
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_WriteElementDatafile (TRI_datafile_t* datafile,
|
||||
void* position,
|
||||
TRI_df_marker_t const* marker,
|
||||
TRI_voc_size_t markerSize,
|
||||
void const* body,
|
||||
TRI_voc_size_t bodySize,
|
||||
bool forceSync) {
|
||||
int TRI_WriteElementDatafile (TRI_datafile_t* datafile,
|
||||
void* position,
|
||||
TRI_df_marker_t const* marker,
|
||||
TRI_voc_size_t markerSize,
|
||||
void const* body,
|
||||
TRI_voc_size_t bodySize,
|
||||
bool forceSync) {
|
||||
TRI_voc_size_t size;
|
||||
|
||||
size = markerSize + bodySize;
|
||||
|
@ -615,15 +612,12 @@ bool TRI_WriteElementDatafile (TRI_datafile_t* datafile,
|
|||
|
||||
if (datafile->_state != TRI_DF_STATE_WRITE) {
|
||||
if (datafile->_state == TRI_DF_STATE_READ) {
|
||||
TRI_set_errno(TRI_ERROR_AVOCADO_READ_ONLY);
|
||||
|
||||
LOG_ERROR("cannot write marker, datafile is read-only");
|
||||
|
||||
return false;
|
||||
return TRI_set_errno(TRI_ERROR_AVOCADO_READ_ONLY);
|
||||
}
|
||||
|
||||
TRI_set_errno(TRI_ERROR_AVOCADO_ILLEGAL_STATE);
|
||||
return false;
|
||||
return TRI_set_errno(TRI_ERROR_AVOCADO_ILLEGAL_STATE);
|
||||
}
|
||||
|
||||
memcpy(position, marker, markerSize);
|
||||
|
@ -649,14 +643,14 @@ bool TRI_WriteElementDatafile (TRI_datafile_t* datafile,
|
|||
|
||||
LOG_ERROR("msync failed with: %s", TRI_last_error());
|
||||
|
||||
return false;
|
||||
return datafile->_lastError;
|
||||
}
|
||||
else {
|
||||
LOG_TRACE("msync succeeded %p, size %lu", position, (unsigned long) size);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -849,6 +843,7 @@ bool TRI_SealDatafile (TRI_datafile_t* datafile) {
|
|||
TRI_df_footer_marker_t footer;
|
||||
TRI_df_marker_t* position;
|
||||
bool ok;
|
||||
int res;
|
||||
|
||||
if (datafile->_state == TRI_DF_STATE_READ) {
|
||||
TRI_set_errno(TRI_ERROR_AVOCADO_READ_ONLY);
|
||||
|
@ -877,13 +872,14 @@ bool TRI_SealDatafile (TRI_datafile_t* datafile) {
|
|||
|
||||
// reserve space and write footer to file
|
||||
datafile->_footerSize = 0;
|
||||
ok = TRI_ReserveElementDatafile(datafile, footer.base._size, &position);
|
||||
|
||||
if (ok) {
|
||||
ok = TRI_WriteElementDatafile(datafile, position, &footer.base, footer.base._size, 0, 0, true);
|
||||
res = TRI_ReserveElementDatafile(datafile, footer.base._size, &position);
|
||||
|
||||
if (res == TRI_ERROR_NO_ERROR) {
|
||||
res = TRI_WriteElementDatafile(datafile, position, &footer.base, footer.base._size, 0, 0, true);
|
||||
}
|
||||
|
||||
if (! ok) {
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -912,8 +908,6 @@ bool TRI_SealDatafile (TRI_datafile_t* datafile) {
|
|||
|
||||
// truncate datafile
|
||||
if (ok) {
|
||||
int res;
|
||||
|
||||
res = ftruncate(datafile->_fd, datafile->_currentSize);
|
||||
|
||||
if (res < 0) {
|
||||
|
@ -925,7 +919,7 @@ bool TRI_SealDatafile (TRI_datafile_t* datafile) {
|
|||
datafile->_state = TRI_DF_STATE_READ;
|
||||
}
|
||||
|
||||
return ok;
|
||||
return ok ? TRI_ERROR_NO_ERROR : datafile->_lastError;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -431,15 +431,15 @@ void TRI_FillCrcMarkerDatafile (TRI_df_marker_t* marker,
|
|||
/// @brief reserves room for an element, advances the pointer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_ReserveElementDatafile (TRI_datafile_t* datafile,
|
||||
TRI_voc_size_t size,
|
||||
TRI_df_marker_t** position);
|
||||
int TRI_ReserveElementDatafile (TRI_datafile_t* datafile,
|
||||
TRI_voc_size_t size,
|
||||
TRI_df_marker_t** position);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief writes a marker and body to the datafile
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_WriteElementDatafile (TRI_datafile_t*,
|
||||
int TRI_WriteElementDatafile (TRI_datafile_t*,
|
||||
void* position,
|
||||
TRI_df_marker_t const* marker,
|
||||
TRI_voc_size_t markerSize,
|
||||
|
|
|
@ -212,6 +212,7 @@ TRI_datafile_t* CreateJournalDocCollection (TRI_doc_collection_t* collection, bo
|
|||
TRI_datafile_t* journal;
|
||||
TRI_df_marker_t* position;
|
||||
bool ok;
|
||||
int res;
|
||||
char* filename;
|
||||
char* jname;
|
||||
char* number;
|
||||
|
@ -288,9 +289,9 @@ TRI_datafile_t* CreateJournalDocCollection (TRI_doc_collection_t* collection, bo
|
|||
TRI_FreeString(filename);
|
||||
|
||||
// create a collection header
|
||||
ok = TRI_ReserveElementDatafile(journal, sizeof(TRI_col_header_marker_t), &position);
|
||||
res = TRI_ReserveElementDatafile(journal, sizeof(TRI_col_header_marker_t), &position);
|
||||
|
||||
if (! ok) {
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
collection->base._lastError = journal->_lastError;
|
||||
TRI_FreeDatafile(journal);
|
||||
|
||||
|
@ -308,9 +309,10 @@ TRI_datafile_t* CreateJournalDocCollection (TRI_doc_collection_t* collection, bo
|
|||
cm._cid = collection->base._cid;
|
||||
|
||||
TRI_FillCrcMarkerDatafile(&cm.base, sizeof(cm), 0, 0);
|
||||
ok = TRI_WriteElementDatafile(journal, position, &cm.base, sizeof(cm), 0, 0, true);
|
||||
|
||||
if (! ok) {
|
||||
res = TRI_WriteElementDatafile(journal, position, &cm.base, sizeof(cm), 0, 0, true);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
collection->base._lastError = journal->_lastError;
|
||||
TRI_FreeDatafile(journal);
|
||||
|
||||
|
|
811
VocBase/index.c
811
VocBase/index.c
File diff suppressed because it is too large
Load Diff
|
@ -5,7 +5,7 @@
|
|||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2010-2011 triagens GmbH, Cologne, Germany
|
||||
/// Copyright 2011-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.
|
||||
|
@ -22,7 +22,7 @@
|
|||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Dr. Frank Celler
|
||||
/// @author Copyright 2011, triAGENS GmbH, Cologne, Germany
|
||||
/// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TRIAGENS_DURHAM_VOC_BASE_INDEX_H
|
||||
|
@ -89,19 +89,6 @@ typedef enum {
|
|||
}
|
||||
TRI_index_geo_variant_e;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief index definition struct as used by the query optimizer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct TRI_index_definition_s {
|
||||
TRI_idx_iid_t _iid;
|
||||
TRI_idx_type_e _type;
|
||||
TRI_vector_string_t* _fields;
|
||||
bool _isUnique;
|
||||
TRI_index_geo_variant_e _geoVariant;
|
||||
}
|
||||
TRI_index_definition_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief index base class
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -111,9 +98,12 @@ typedef struct TRI_index_s {
|
|||
TRI_idx_type_e _type;
|
||||
struct TRI_doc_collection_s* _collection;
|
||||
|
||||
bool (*insert) (struct TRI_index_s*, struct TRI_doc_mptr_s const*);
|
||||
bool (*remove) (struct TRI_index_s*, struct TRI_doc_mptr_s const*);
|
||||
bool (*update) (struct TRI_index_s*, struct TRI_doc_mptr_s const*, struct TRI_shaped_json_s const*);
|
||||
bool _unique;
|
||||
TRI_vector_string_t _fields;
|
||||
|
||||
int (*insert) (struct TRI_index_s*, struct TRI_doc_mptr_s const*);
|
||||
int (*remove) (struct TRI_index_s*, struct TRI_doc_mptr_s const*);
|
||||
int (*update) (struct TRI_index_s*, struct TRI_doc_mptr_s const*, struct TRI_shaped_json_s const*);
|
||||
TRI_json_t* (*json) (struct TRI_index_s*, struct TRI_doc_collection_s*);
|
||||
}
|
||||
TRI_index_t;
|
||||
|
@ -124,6 +114,7 @@ TRI_index_t;
|
|||
|
||||
typedef struct TRI_geo_index_s {
|
||||
TRI_index_t base;
|
||||
TRI_index_geo_variant_e _variant;
|
||||
|
||||
GeoIndex* _geoIndex;
|
||||
|
||||
|
@ -135,7 +126,6 @@ typedef struct TRI_geo_index_s {
|
|||
}
|
||||
TRI_geo_index_t;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief hash index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -143,11 +133,10 @@ TRI_geo_index_t;
|
|||
typedef struct TRI_hash_index_s {
|
||||
TRI_index_t base;
|
||||
|
||||
HashIndex* _hashIndex; // effectively the associative array
|
||||
TRI_vector_t* _shapeList; // a list of shape pid which identifies the fields of the index
|
||||
bool _unique;
|
||||
} TRI_hash_index_t;
|
||||
|
||||
HashIndex* _hashIndex; // effectively the associative array
|
||||
TRI_vector_t _paths; // a list of shape pid which identifies the fields of the index
|
||||
}
|
||||
TRI_hash_index_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief skiplist index
|
||||
|
@ -156,10 +145,10 @@ typedef struct TRI_hash_index_s {
|
|||
typedef struct TRI_skiplist_index_s {
|
||||
TRI_index_t base;
|
||||
|
||||
SkiplistIndex* _skiplistIndex; // effectively the skiplist
|
||||
TRI_vector_t* _shapeList; // a list of shape pid which identifies the fields of the index
|
||||
bool _unique;
|
||||
} TRI_skiplist_index_t;
|
||||
SkiplistIndex* _skiplistIndex; // effectively the skiplist
|
||||
TRI_vector_t _paths; // a list of shape pid which identifies the fields of the index
|
||||
}
|
||||
TRI_skiplist_index_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
|
@ -182,7 +171,7 @@ typedef struct TRI_skiplist_index_s {
|
|||
/// @brief removes an index file
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_RemoveIndex (struct TRI_doc_collection_s* collection, TRI_index_t* idx);
|
||||
bool TRI_RemoveIndexFile (struct TRI_doc_collection_s* collection, TRI_index_t* idx);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief saves an index
|
||||
|
@ -196,37 +185,11 @@ bool TRI_SaveIndex (struct TRI_doc_collection_s*, TRI_index_t*);
|
|||
|
||||
TRI_index_t* TRI_LookupIndex (struct TRI_doc_collection_s*, TRI_idx_iid_t);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief free an existing index definition
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_FreeIndexDefinition (TRI_index_definition_t*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief free an existing index definitions vector
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_FreeIndexDefinitions (TRI_vector_pointer_t*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief gets name of index type
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char* TRI_GetTypeNameIndex (const TRI_index_definition_t* const);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief gets the definitions of all index files for a collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_vector_pointer_t* TRI_GetCollectionIndexes (const TRI_vocbase_t* vocbase,
|
||||
const char* collectionName);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief gets the names of all index files for a collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_vector_string_t TRI_GetCollectionIndexFiles (const TRI_vocbase_t* vocbase,
|
||||
const char* collectionName);
|
||||
char const* TRI_TypeNameIndex (const TRI_index_t* const);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
|
@ -254,6 +217,7 @@ TRI_vector_string_t TRI_GetCollectionIndexFiles (const TRI_vocbase_t* vocbase,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_index_t* TRI_CreateGeoIndex (struct TRI_doc_collection_s*,
|
||||
char const* locationName,
|
||||
TRI_shape_pid_t,
|
||||
bool geoJson);
|
||||
|
||||
|
@ -262,7 +226,9 @@ TRI_index_t* TRI_CreateGeoIndex (struct TRI_doc_collection_s*,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_index_t* TRI_CreateGeoIndex2 (struct TRI_doc_collection_s*,
|
||||
char const* latitudeName,
|
||||
TRI_shape_pid_t,
|
||||
char const* longitudeName,
|
||||
TRI_shape_pid_t);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -333,7 +299,8 @@ GeoCoordinates* TRI_NearestGeoIndex (TRI_index_t*,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_index_t* TRI_CreateHashIndex (struct TRI_doc_collection_s*,
|
||||
TRI_vector_t* shapeList,
|
||||
TRI_vector_pointer_t* fields,
|
||||
TRI_vector_t* paths,
|
||||
bool unique);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -392,7 +359,8 @@ TRI_skiplist_iterator_t* TRI_LookupSkiplistIndex (TRI_index_t*, TRI_sl_operator_
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_index_t* TRI_CreateSkiplistIndex (struct TRI_doc_collection_s*,
|
||||
TRI_vector_t* shapeList,
|
||||
TRI_vector_pointer_t* fields,
|
||||
TRI_vector_t* paths,
|
||||
bool unique);
|
||||
|
||||
|
||||
|
|
|
@ -25,10 +25,11 @@
|
|||
/// @author Copyright 2012, triagens GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <BasicsC/logging.h>
|
||||
#include <BasicsC/string-buffer.h>
|
||||
#include "query-join-execute.h"
|
||||
|
||||
#include "VocBase/query-join-execute.h"
|
||||
#include "BasicsC/logging.h"
|
||||
#include "BasicsC/string-buffer.h"
|
||||
#include "BasicsC/strings.h"
|
||||
#include "VocBase/query-join.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -40,25 +41,25 @@
|
|||
/// @brief log information about the used index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void LogIndexString(const TRI_index_definition_t* const indexDefinition,
|
||||
const char* const collectionName) {
|
||||
|
||||
static void LogIndexString(TRI_index_t const* idx,
|
||||
char const* collectionName) {
|
||||
TRI_string_buffer_t* buffer = TRI_CreateStringBuffer();
|
||||
size_t i;
|
||||
|
||||
if (!buffer) {
|
||||
if (buffer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < indexDefinition->_fields->_length; i++) {
|
||||
for (i = 0; i < idx->_fields._length; i++) {
|
||||
if (i > 0) {
|
||||
TRI_AppendStringStringBuffer(buffer, ", ");
|
||||
}
|
||||
TRI_AppendStringStringBuffer(buffer, indexDefinition->_fields->_buffer[i]);
|
||||
|
||||
TRI_AppendStringStringBuffer(buffer, idx->_fields._buffer[i]);
|
||||
}
|
||||
|
||||
LOG_DEBUG("using %s index (%s) for '%s'",
|
||||
TRI_GetTypeNameIndex(indexDefinition),
|
||||
TRI_TypeNameIndex(idx),
|
||||
buffer->_buffer,
|
||||
collectionName);
|
||||
|
||||
|
@ -74,6 +75,9 @@ static TRI_data_feeder_t* DetermineGeoIndexUsageX (const TRI_vocbase_t* vocbase,
|
|||
const TRI_select_join_t* join,
|
||||
const size_t level,
|
||||
const TRI_join_part_t* part) {
|
||||
assert(false);
|
||||
|
||||
#if 0
|
||||
TRI_vector_pointer_t* indexDefinitions;
|
||||
TRI_index_definition_t* indexDefinition;
|
||||
TRI_data_feeder_t* feeder = NULL;
|
||||
|
@ -125,6 +129,7 @@ static TRI_data_feeder_t* DetermineGeoIndexUsageX (const TRI_vocbase_t* vocbase,
|
|||
TRI_FreeIndexDefinitions(indexDefinitions);
|
||||
|
||||
return feeder;
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -135,6 +140,9 @@ static TRI_data_feeder_t* DetermineIndexUsageX (const TRI_vocbase_t* vocbase,
|
|||
const TRI_select_join_t* join,
|
||||
const size_t level,
|
||||
const TRI_join_part_t* part) {
|
||||
assert(false);
|
||||
|
||||
#if 0
|
||||
TRI_vector_pointer_t* indexDefinitions;
|
||||
TRI_index_definition_t* indexDefinition;
|
||||
TRI_data_feeder_t* feeder = NULL;
|
||||
|
@ -310,50 +318,51 @@ EXIT2:
|
|||
}
|
||||
|
||||
return feeder;
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Determine which geo indexes to use in a query
|
||||
/// @brief determines which geo indexes to use in a query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static TRI_data_feeder_t* DetermineGeoIndexUsage (TRI_query_instance_t* const instance,
|
||||
const size_t level,
|
||||
const TRI_join_part_t* part) {
|
||||
TRI_vector_pointer_t* indexDefinitions;
|
||||
TRI_vector_pointer_t* indexes;
|
||||
TRI_data_feeder_t* feeder = NULL;
|
||||
size_t i;
|
||||
|
||||
assert(part->_geoRestriction);
|
||||
|
||||
indexDefinitions = TRI_GetCollectionIndexes(instance->_template->_vocbase,
|
||||
part->_collectionName);
|
||||
if (!indexDefinitions) {
|
||||
TRI_RegisterErrorQueryInstance(instance, TRI_ERROR_OUT_OF_MEMORY, NULL);
|
||||
if (part->_collection->base._type != TRI_COL_TYPE_SIMPLE_DOCUMENT) {
|
||||
TRI_RegisterErrorQueryInstance(instance,
|
||||
TRI_ERROR_AVOCADO_UNKNOWN_COLLECTION_TYPE,
|
||||
part->_alias);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
indexes = & ((TRI_sim_collection_t*) part->_collection)->_indexes;
|
||||
|
||||
// enum all indexes
|
||||
for (i = 0; i < indexDefinitions->_length; i++) {
|
||||
TRI_index_definition_t* indexDefinition;
|
||||
for (i = 0; i < indexes->_length; i++) {
|
||||
TRI_index_t* idx;
|
||||
|
||||
indexDefinition = (TRI_index_definition_t*) indexDefinitions->_buffer[i];
|
||||
idx = (TRI_index_t*) indexes->_buffer[i];
|
||||
|
||||
if (indexDefinition->_type != TRI_IDX_TYPE_GEO_INDEX) {
|
||||
if (idx->_type != TRI_IDX_TYPE_GEO_INDEX) {
|
||||
// ignore all indexes except geo indexes here
|
||||
continue;
|
||||
}
|
||||
|
||||
if (indexDefinition->_fields->_length != 2) {
|
||||
if (idx->_fields._length != 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(indexDefinition->_fields->_buffer[0],
|
||||
part->_geoRestriction->_compareLat._field) != 0) {
|
||||
if (! TRI_EqualString(idx->_fields._buffer[0], part->_geoRestriction->_compareLat._field)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(indexDefinition->_fields->_buffer[1],
|
||||
part->_geoRestriction->_compareLon._field) != 0) {
|
||||
if (! TRI_EqualString(idx->_fields._buffer[1], part->_geoRestriction->_compareLon._field)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -361,16 +370,14 @@ static TRI_data_feeder_t* DetermineGeoIndexUsage (TRI_query_instance_t* const in
|
|||
TRI_CreateDataFeederGeoLookup(instance,
|
||||
(TRI_doc_collection_t*) part->_collection,
|
||||
level,
|
||||
indexDefinition->_iid,
|
||||
idx->_iid,
|
||||
part->_geoRestriction);
|
||||
|
||||
LogIndexString(indexDefinition, part->_alias);
|
||||
LogIndexString(idx, part->_alias);
|
||||
break;
|
||||
}
|
||||
|
||||
TRI_FreeIndexDefinitions(indexDefinitions);
|
||||
|
||||
if (!feeder) {
|
||||
if (feeder == NULL) {
|
||||
TRI_RegisterErrorQueryInstance(instance,
|
||||
TRI_ERROR_QUERY_GEO_INDEX_MISSING,
|
||||
part->_alias);
|
||||
|
@ -386,7 +393,7 @@ static TRI_data_feeder_t* DetermineGeoIndexUsage (TRI_query_instance_t* const in
|
|||
static TRI_data_feeder_t* DetermineIndexUsage (TRI_query_instance_t* const instance,
|
||||
const size_t level,
|
||||
const TRI_join_part_t* part) {
|
||||
TRI_vector_pointer_t* indexDefinitions;
|
||||
TRI_vector_pointer_t* indexes;
|
||||
TRI_data_feeder_t* feeder = NULL;
|
||||
size_t i;
|
||||
|
||||
|
@ -400,21 +407,24 @@ static TRI_data_feeder_t* DetermineIndexUsage (TRI_query_instance_t* const insta
|
|||
size_t numConsts;
|
||||
|
||||
TRI_InitVectorPointer(&matches);
|
||||
indexDefinitions = TRI_GetCollectionIndexes(instance->_template->_vocbase,
|
||||
part->_collectionName);
|
||||
|
||||
if (!indexDefinitions) {
|
||||
TRI_RegisterErrorQueryInstance(instance, TRI_ERROR_OUT_OF_MEMORY, NULL);
|
||||
goto EXIT2;
|
||||
if (part->_collection->base._type != TRI_COL_TYPE_SIMPLE_DOCUMENT) {
|
||||
TRI_RegisterErrorQueryInstance(instance,
|
||||
TRI_ERROR_AVOCADO_UNKNOWN_COLLECTION_TYPE,
|
||||
part->_alias);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
indexes = & ((TRI_sim_collection_t*) part->_collection)->_indexes;
|
||||
|
||||
// enum all indexes
|
||||
for (i = 0; i < indexDefinitions->_length; i++) {
|
||||
TRI_index_definition_t* indexDefinition;
|
||||
for (i = 0; i < indexes->_length; i++) {
|
||||
TRI_index_t* idx;
|
||||
size_t j;
|
||||
|
||||
indexDefinition = (TRI_index_definition_t*) indexDefinitions->_buffer[i];
|
||||
if (indexDefinition->_type == TRI_IDX_TYPE_GEO_INDEX) {
|
||||
idx = (TRI_index_t*) indexes->_buffer[i];
|
||||
|
||||
if (idx->_type == TRI_IDX_TYPE_GEO_INDEX) {
|
||||
// ignore all geo indexes here
|
||||
continue;
|
||||
}
|
||||
|
@ -424,11 +434,13 @@ static TRI_data_feeder_t* DetermineIndexUsage (TRI_query_instance_t* const insta
|
|||
TRI_DestroyVectorPointer(&matches);
|
||||
TRI_InitVectorPointer(&matches);
|
||||
}
|
||||
|
||||
numFields = 0;
|
||||
numConsts = 0;
|
||||
|
||||
numFieldsDefined = indexDefinition->_fields->_length;
|
||||
for (j = 0 ; j < numFieldsDefined; j++) {
|
||||
numFieldsDefined = idx->_fields._length;
|
||||
|
||||
for (j = 0; j < numFieldsDefined; j++) {
|
||||
size_t k;
|
||||
|
||||
// enumerate all fields from the index definition and
|
||||
|
@ -437,6 +449,7 @@ static TRI_data_feeder_t* DetermineIndexUsage (TRI_query_instance_t* const insta
|
|||
QL_optimize_range_t* range;
|
||||
|
||||
range = (QL_optimize_range_t*) part->_ranges->_buffer[k];
|
||||
|
||||
if (!range) {
|
||||
continue;
|
||||
}
|
||||
|
@ -446,18 +459,17 @@ static TRI_data_feeder_t* DetermineIndexUsage (TRI_query_instance_t* const insta
|
|||
assert(part->_alias);
|
||||
|
||||
// check if collection name matches
|
||||
if (strcmp(range->_collection, part->_alias) != 0) {
|
||||
if (! TRI_EqualString(range->_collection, part->_alias)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// check if field names match
|
||||
if (strcmp(indexDefinition->_fields->_buffer[j],
|
||||
range->_field) != 0) {
|
||||
if (! TRI_EqualString(idx->_fields._buffer[j], range->_field)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (indexDefinition->_type == TRI_IDX_TYPE_PRIMARY_INDEX ||
|
||||
indexDefinition->_type == TRI_IDX_TYPE_HASH_INDEX) {
|
||||
if (idx->_type == TRI_IDX_TYPE_PRIMARY_INDEX ||
|
||||
idx->_type == TRI_IDX_TYPE_HASH_INDEX) {
|
||||
// check if index can be used
|
||||
// (primary and hash index only support equality comparisons)
|
||||
if (range->_minStatus == RANGE_VALUE_INFINITE ||
|
||||
|
@ -504,7 +516,7 @@ static TRI_data_feeder_t* DetermineIndexUsage (TRI_query_instance_t* const insta
|
|||
// we have found as many matches as defined in the index definition
|
||||
// that means the index is fully covered in the condition
|
||||
|
||||
if (indexDefinition->_type == TRI_IDX_TYPE_PRIMARY_INDEX) {
|
||||
if (idx->_type == TRI_IDX_TYPE_PRIMARY_INDEX) {
|
||||
// use the collection's primary index
|
||||
if (feeder) {
|
||||
// free any other feeder previously set up
|
||||
|
@ -519,7 +531,7 @@ static TRI_data_feeder_t* DetermineIndexUsage (TRI_query_instance_t* const insta
|
|||
if (feeder) {
|
||||
// we always exit if we can use the primary index
|
||||
// the primary index guarantees uniqueness
|
||||
LogIndexString(indexDefinition, part->_alias);
|
||||
LogIndexString(idx, part->_alias);
|
||||
goto EXIT;
|
||||
}
|
||||
}
|
||||
|
@ -528,33 +540,33 @@ static TRI_data_feeder_t* DetermineIndexUsage (TRI_query_instance_t* const insta
|
|||
// if the index found contains more fields than the one we previously found,
|
||||
// we use the new one
|
||||
// (assumption: the more fields index, the less selective is the index)
|
||||
if (indexDefinition->_type == TRI_IDX_TYPE_HASH_INDEX ||
|
||||
indexDefinition->_type == TRI_IDX_TYPE_SKIPLIST_INDEX) {
|
||||
if (idx->_type == TRI_IDX_TYPE_HASH_INDEX ||
|
||||
idx->_type == TRI_IDX_TYPE_SKIPLIST_INDEX) {
|
||||
// use a hash index defined for the collection
|
||||
if (feeder) {
|
||||
// free any other feeder previously set up
|
||||
feeder->free(feeder);
|
||||
}
|
||||
|
||||
if (indexDefinition->_type == TRI_IDX_TYPE_SKIPLIST_INDEX) {
|
||||
if (idx->_type == TRI_IDX_TYPE_SKIPLIST_INDEX) {
|
||||
feeder =
|
||||
TRI_CreateDataFeederSkiplistLookup(instance,
|
||||
(TRI_doc_collection_t*) part->_collection,
|
||||
level,
|
||||
indexDefinition->_iid,
|
||||
idx->_iid,
|
||||
TRI_CopyVectorPointer(&matches));
|
||||
|
||||
LogIndexString(indexDefinition, part->_alias);
|
||||
LogIndexString(idx, part->_alias);
|
||||
}
|
||||
else {
|
||||
feeder =
|
||||
TRI_CreateDataFeederHashLookup(instance,
|
||||
(TRI_doc_collection_t*) part->_collection,
|
||||
level,
|
||||
indexDefinition->_iid,
|
||||
idx->_iid,
|
||||
TRI_CopyVectorPointer(&matches));
|
||||
|
||||
LogIndexString(indexDefinition, part->_alias);
|
||||
LogIndexString(idx, part->_alias);
|
||||
}
|
||||
|
||||
if (!feeder) {
|
||||
|
@ -571,12 +583,9 @@ static TRI_data_feeder_t* DetermineIndexUsage (TRI_query_instance_t* const insta
|
|||
}
|
||||
|
||||
EXIT:
|
||||
TRI_FreeIndexDefinitions(indexDefinitions);
|
||||
TRI_DestroyVectorPointer(&matches);
|
||||
}
|
||||
|
||||
EXIT2:
|
||||
|
||||
if (!feeder) {
|
||||
// if no index can be used, we'll do a full table scan
|
||||
feeder = TRI_CreateDataFeederTableScan(instance,
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -138,7 +138,7 @@ static bool EqualKeyAttributeName (TRI_associative_synced_t* array, void const*
|
|||
static TRI_shape_aid_t FindAttributeName (TRI_shaper_t* shaper, char const* name) {
|
||||
TRI_df_attribute_marker_t marker;
|
||||
TRI_df_marker_t* result;
|
||||
bool ok;
|
||||
int res;
|
||||
size_t n;
|
||||
voc_shaper_t* s;
|
||||
void const* p;
|
||||
|
@ -175,9 +175,9 @@ static TRI_shape_aid_t FindAttributeName (TRI_shaper_t* shaper, char const* name
|
|||
marker._size = n;
|
||||
|
||||
// write into the shape collection
|
||||
ok = TRI_WriteBlobCollection(s->_collection, &marker.base, sizeof(TRI_df_attribute_marker_t), name, n, &result);
|
||||
res = TRI_WriteBlobCollection(s->_collection, &marker.base, sizeof(TRI_df_attribute_marker_t), name, n, &result);
|
||||
|
||||
if (! ok) {
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
TRI_UnlockMutex(&s->_attributeLock);
|
||||
return 0;
|
||||
}
|
||||
|
@ -283,7 +283,7 @@ static TRI_shape_t const* FindShape (TRI_shaper_t* shaper, TRI_shape_t* shape) {
|
|||
TRI_df_shape_marker_t marker;
|
||||
TRI_shape_t const* found;
|
||||
TRI_shape_t* l;
|
||||
bool ok;
|
||||
int res;
|
||||
voc_shaper_t* s;
|
||||
void* f;
|
||||
|
||||
|
@ -317,9 +317,9 @@ static TRI_shape_t const* FindShape (TRI_shaper_t* shaper, TRI_shape_t* shape) {
|
|||
shape->_sid = s->_nextSid++;
|
||||
|
||||
// write into the shape collection
|
||||
ok = TRI_WriteBlobCollection(s->_collection, &marker.base, sizeof(TRI_df_shape_marker_t), shape, shape->_size, &result);
|
||||
res = TRI_WriteBlobCollection(s->_collection, &marker.base, sizeof(TRI_df_shape_marker_t), shape, shape->_size, &result);
|
||||
|
||||
if (! ok) {
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
TRI_UnlockMutex(&s->_shapeLock);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -196,17 +196,24 @@ static TRI_vocbase_col_t* AddCollection (TRI_vocbase_t* vocbase,
|
|||
|
||||
if (found != NULL) {
|
||||
TRI_Free(col);
|
||||
|
||||
LOG_ERROR("duplicate entry for name '%s'", name);
|
||||
TRI_set_errno(TRI_ERROR_AVOCADO_DUPLICATE_NAME);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// check collection identifier
|
||||
// check collection identifier (unknown for new born collections)
|
||||
if (cid != 0) {
|
||||
found = TRI_InsertKeyAssociativePointer(&vocbase->_collectionsById, &cid, col, false);
|
||||
|
||||
if (found != NULL) {
|
||||
TRI_RemoveKeyAssociativePointer(&vocbase->_collectionsByName, name);
|
||||
TRI_Free(col);
|
||||
|
||||
LOG_ERROR("duplicate collection identifier '%lu' for name '%s'", (unsigned long) cid, name);
|
||||
TRI_set_errno(TRI_ERROR_AVOCADO_DUPLICATE_IDENTIFIER);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -219,7 +226,7 @@ static TRI_vocbase_col_t* AddCollection (TRI_vocbase_t* vocbase,
|
|||
/// @brief scans a directory and loads all collections
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void ScanPath (TRI_vocbase_t* vocbase, char const* path) {
|
||||
static bool ScanPath (TRI_vocbase_t* vocbase, char const* path) {
|
||||
TRI_vector_string_t files;
|
||||
TRI_col_type_e type;
|
||||
size_t n;
|
||||
|
@ -239,8 +246,10 @@ static void ScanPath (TRI_vocbase_t* vocbase, char const* path) {
|
|||
}
|
||||
|
||||
file = TRI_Concatenate2File(path, name);
|
||||
if (!file) {
|
||||
continue;
|
||||
|
||||
if (file == NULL) {
|
||||
TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (TRI_IsDirectory(file)) {
|
||||
|
@ -256,7 +265,15 @@ static void ScanPath (TRI_vocbase_t* vocbase, char const* path) {
|
|||
type = info._type;
|
||||
|
||||
if (type == TRI_COL_TYPE_SIMPLE_DOCUMENT) {
|
||||
AddCollection(vocbase, type, info._name, info._cid, file);
|
||||
TRI_vocbase_col_t* c;
|
||||
|
||||
c = AddCollection(vocbase, type, info._name, info._cid, file);
|
||||
|
||||
if (c == NULL) {
|
||||
LOG_FATAL("failed to add simple document collection from '%s'", file);
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG_DEBUG("added simple document collection from '%s'", file);
|
||||
}
|
||||
else {
|
||||
|
@ -272,6 +289,7 @@ static void ScanPath (TRI_vocbase_t* vocbase, char const* path) {
|
|||
}
|
||||
|
||||
TRI_DestroyVectorString(&files);
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -308,6 +326,8 @@ size_t PageSize;
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks if a collection is allowed
|
||||
///
|
||||
/// Returns 0 for success or the offending character.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char TRI_IsAllowedCollectionName (char const* name) {
|
||||
|
@ -414,6 +434,7 @@ TRI_vocbase_t* TRI_OpenVocBase (char const* path) {
|
|||
TRI_vocbase_t* vocbase;
|
||||
char* lockFile;
|
||||
int lockCheck;
|
||||
bool ok;
|
||||
|
||||
if (! TRI_IsDirectory(path)) {
|
||||
LOG_ERROR("database path '%s' is not a directory", path);
|
||||
|
@ -422,9 +443,18 @@ TRI_vocbase_t* TRI_OpenVocBase (char const* path) {
|
|||
|
||||
// check if the database is locked
|
||||
lockFile = TRI_Concatenate2File(path, "lock");
|
||||
|
||||
if (lockFile == NULL) {
|
||||
TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
|
||||
LOG_ERROR("out of memory when opening database");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lockCheck = TRI_VerifyLockFile(lockFile);
|
||||
|
||||
if (lockCheck) {
|
||||
TRI_set_errno(TRI_ERROR_AVOCADO_DATABASE_LOCKED);
|
||||
|
||||
LOG_FATAL("database is locked, please check the lock file '%s'", lockFile);
|
||||
TRI_FreeString(lockFile);
|
||||
return NULL;
|
||||
|
@ -439,32 +469,39 @@ TRI_vocbase_t* TRI_OpenVocBase (char const* path) {
|
|||
if (! lockCheck) {
|
||||
LOG_FATAL("cannot lock the database, please check the lock file '%s': %s", lockFile, TRI_last_error());
|
||||
TRI_FreeString(lockFile);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// setup vocbase structure
|
||||
vocbase = TRI_Allocate(sizeof(TRI_vocbase_t));
|
||||
|
||||
if (!vocbase) {
|
||||
LOG_ERROR("out of memory when opening vocbase");
|
||||
if (vocbase == NULL) {
|
||||
TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
|
||||
LOG_ERROR("out of memory when opening database");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vocbase->_cursors = TRI_CreateShadowsQueryCursor();
|
||||
if (!vocbase->_cursors) {
|
||||
|
||||
if (vocbase->_cursors == NULL) {
|
||||
TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
TRI_FreeShadowStore(vocbase->_cursors);
|
||||
TRI_Free(vocbase);
|
||||
LOG_ERROR("out of memory when opening vocbase");
|
||||
LOG_ERROR("out of memory when opening database");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vocbase->_lockFile = lockFile;
|
||||
vocbase->_path = TRI_DuplicateString(path);
|
||||
|
||||
if (!vocbase->_path) {
|
||||
if (vocbase->_path == NULL) {
|
||||
TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
TRI_FreeShadowStore(vocbase->_cursors);
|
||||
TRI_Free(vocbase);
|
||||
LOG_ERROR("out of memory when opening vocbase");
|
||||
LOG_ERROR("out of memory when opening database");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -485,7 +522,11 @@ TRI_vocbase_t* TRI_OpenVocBase (char const* path) {
|
|||
NULL);
|
||||
|
||||
// scan directory for collections
|
||||
ScanPath(vocbase, vocbase->_path);
|
||||
ok = ScanPath(vocbase, vocbase->_path);
|
||||
|
||||
if (! ok) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// vocbase is now active
|
||||
vocbase->_active = 1;
|
||||
|
@ -514,9 +555,8 @@ void TRI_CloseVocBase (TRI_vocbase_t* vocbase) {
|
|||
TRI_JoinThread(&vocbase->_synchroniser);
|
||||
TRI_JoinThread(&vocbase->_compactor);
|
||||
|
||||
// Free shadows
|
||||
// cursors
|
||||
if (vocbase->_cursors) {
|
||||
// cursors
|
||||
TRI_FreeShadowStore(vocbase->_cursors);
|
||||
}
|
||||
|
||||
|
@ -619,6 +659,8 @@ TRI_vocbase_col_t const* TRI_CreateCollectionVocBase (TRI_vocbase_t* vocbase, TR
|
|||
found = TRI_LookupByKeyAssociativePointer(&vocbase->_collectionsByName, name);
|
||||
|
||||
if (found != NULL) {
|
||||
TRI_set_errno(TRI_ERROR_AVOCADO_DUPLICATE_NAME);
|
||||
|
||||
LOG_ERROR("collection named '%s' already exists", name);
|
||||
TRI_WriteUnlockReadWriteLock(&vocbase->_lock);
|
||||
return NULL;
|
||||
|
@ -628,6 +670,8 @@ TRI_vocbase_col_t const* TRI_CreateCollectionVocBase (TRI_vocbase_t* vocbase, TR
|
|||
wrong = TRI_IsAllowedCollectionName(name);
|
||||
|
||||
if (wrong != 0) {
|
||||
TRI_set_errno(TRI_ERROR_AVOCADO_ILLEGAL_NAME);
|
||||
|
||||
LOG_ERROR("found illegal character in name: %c", wrong);
|
||||
TRI_WriteUnlockReadWriteLock(&vocbase->_lock);
|
||||
return NULL;
|
||||
|
@ -647,6 +691,8 @@ TRI_vocbase_col_t const* TRI_CreateCollectionVocBase (TRI_vocbase_t* vocbase, TR
|
|||
}
|
||||
}
|
||||
else {
|
||||
TRI_set_errno(TRI_ERROR_AVOCADO_UNKNOWN_COLLECTION_TYPE);
|
||||
|
||||
LOG_ERROR("unknown collection type: %d", parameter->_type);
|
||||
TRI_WriteUnlockReadWriteLock(&vocbase->_lock);
|
||||
return NULL;
|
||||
|
@ -694,6 +740,8 @@ TRI_vocbase_col_t const* TRI_LoadCollectionVocBase (TRI_vocbase_t* vocbase, char
|
|||
found.c = TRI_LookupByKeyAssociativePointer(&vocbase->_collectionsByName, name);
|
||||
|
||||
if (found.c == NULL) {
|
||||
TRI_set_errno(TRI_ERROR_AVOCADO_COLLECTION_NOT_FOUND);
|
||||
|
||||
LOG_ERROR("unknown collection '%s'", name);
|
||||
TRI_WriteUnlockReadWriteLock(&vocbase->_lock);
|
||||
return NULL;
|
||||
|
@ -727,6 +775,8 @@ TRI_vocbase_col_t const* TRI_LoadCollectionVocBase (TRI_vocbase_t* vocbase, char
|
|||
return found.c;
|
||||
}
|
||||
else {
|
||||
TRI_set_errno(TRI_ERROR_AVOCADO_UNKNOWN_COLLECTION_TYPE);
|
||||
|
||||
LOG_ERROR("unknown collection type %d for '%s'", (int) found.c->_type, name);
|
||||
TRI_WriteUnlockReadWriteLock(&vocbase->_lock);
|
||||
return NULL;
|
||||
|
@ -754,6 +804,8 @@ TRI_vocbase_col_t const* TRI_BearCollectionVocBase (TRI_vocbase_t* vocbase, char
|
|||
wrong = TRI_IsAllowedCollectionName(name);
|
||||
|
||||
if (wrong != 0) {
|
||||
TRI_set_errno(TRI_ERROR_AVOCADO_ILLEGAL_NAME);
|
||||
|
||||
LOG_ERROR("found illegal character in name: %c", wrong);
|
||||
TRI_WriteUnlockReadWriteLock(&vocbase->_lock);
|
||||
return NULL;
|
||||
|
@ -762,6 +814,11 @@ TRI_vocbase_col_t const* TRI_BearCollectionVocBase (TRI_vocbase_t* vocbase, char
|
|||
// check if the collection is not already loaded
|
||||
found.v = AddCollection(vocbase, TRI_COL_TYPE_SIMPLE_DOCUMENT, name, 0, NULL);
|
||||
|
||||
if (found.v == NULL) {
|
||||
TRI_WriteUnlockReadWriteLock(&vocbase->_lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
found.v->_newBorn = 1;
|
||||
|
||||
TRI_WriteUnlockReadWriteLock(&vocbase->_lock);
|
||||
|
|
Loading…
Reference in New Issue