1
0
Fork 0

pluggable key generators

This commit is contained in:
Jan Steemann 2012-11-14 12:44:56 +01:00
parent cdd163cc8a
commit 30ba8771a7
14 changed files with 630 additions and 70 deletions

View File

@ -82,6 +82,7 @@ bin_arangod_SOURCES = \
arangod/VocBase/general-cursor.c \
arangod/VocBase/headers.c \
arangod/VocBase/index.c \
arangod/VocBase/key-generator.c \
arangod/VocBase/primary-collection.c \
arangod/VocBase/shadow-data.c \
arangod/VocBase/shape-collection.c \

View File

@ -459,6 +459,14 @@ void RestVocbaseBaseHandler::generateTransactionError (const string& collection,
generateError(HttpResponse::BAD, res, "geo constraint violated");
return;
case TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD:
generateError(HttpResponse::BAD, res, "invalid document key");
return;
case TRI_ERROR_ARANGO_DOCUMENT_KEY_UNEXPECTED:
generateError(HttpResponse::BAD, res, "collection does not allow using user-defined keys");
return;
case TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND:
generateDocumentNotFound(cid, key);
return;

View File

@ -66,7 +66,7 @@ static void InitCollection (TRI_vocbase_t* vocbase,
collection->_state = TRI_COL_STATE_WRITE;
collection->_lastError = 0;
collection->_cid = info->_cid;
collection->_cid = info->_cid;
TRI_CopyString(collection->_name, info->_name, sizeof(collection->_name));
collection->_maximalSize = info->_maximalSize;
collection->_waitForSync = info->_waitForSync;

View File

@ -213,7 +213,7 @@ typedef struct TRI_col_info_s {
TRI_voc_size_t _maximalSize; // maximal size of memory mapped file
bool _waitForSync; // if true, wait for msync
bool _deleted; // if true, collections has been deleted
bool _deleted; // if true, collection has been deleted
}
TRI_col_info_t;

View File

@ -35,6 +35,7 @@
#include "ShapedJson/shape-accessor.h"
#include "VocBase/edge-collection.h"
#include "VocBase/index.h"
#include "VocBase/key-generator.h"
#include "VocBase/voc-shaper.h"
// -----------------------------------------------------------------------------
@ -1046,14 +1047,14 @@ static TRI_doc_mptr_t CreateShapedJson (TRI_doc_operation_context_t* context,
size_t keySize;
char* keyBody;
TRI_voc_size_t keyBodySize;
char ridBuffer[22]; // can hold even the biggest stringified uint64_t
char* keySource;
char keyBuffer[TRI_COLLECTION_KEY_MAX_LENGTH + 1];
TRI_doc_mptr_t mptr;
// initialise the result
memset(&mptr, 0, sizeof(mptr));
primary = context->_collection;
document = (TRI_document_collection_t*) primary;
if (type != TRI_DOC_MARKER_KEY_DOCUMENT &&
type != TRI_DOC_MARKER_KEY_EDGE) {
@ -1063,43 +1064,36 @@ static TRI_doc_mptr_t CreateShapedJson (TRI_doc_operation_context_t* context,
return mptr;
}
// type is valid
if (type == TRI_DOC_MARKER_KEY_DOCUMENT) {
// create a document
TRI_doc_document_key_marker_t marker;
TRI_key_generator_t* keyGenerator;
int res;
memset(&marker, 0, sizeof(marker));
InitDocumentMarker(&marker, TRI_DOC_MARKER_KEY_DOCUMENT, json, true);
// create key using key generator
keyGenerator = (TRI_key_generator_t*) primary->_keyGenerator;
assert(keyGenerator != NULL);
if (key) {
document = (TRI_document_collection_t*) primary;
// check key
if (regexec(&document->DocumentKeyRegex, key, 0, NULL, 0) != 0 || strlen(key) > document->keyLength) {
res = keyGenerator->generate(keyGenerator, TRI_COLLECTION_KEY_MAX_LENGTH, &marker, key, (char*) &keyBuffer, &keySize);
if (res != TRI_ERROR_NO_ERROR) {
// key generation failed
Unlock(context);
primary->base._lastError = TRI_set_errno(TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD);
return mptr;
}
}
// type & key are valid
if (type == TRI_DOC_MARKER_KEY_DOCUMENT) {
// create a document
TRI_doc_document_key_marker_t marker;
memset(&marker, 0, sizeof(marker));
InitDocumentMarker(&marker, TRI_DOC_MARKER_KEY_DOCUMENT, json, true);
if (key) {
// we have a key!
keySize = strlen(key) + 1;
keySource = key;
}
else {
// create key from did
keySize = TRI_StringUInt64InPlace(marker._rid, ridBuffer) + 1;
keySource = (char*) &ridBuffer;
}
keySize += 1;
keyBodySize = ((keySize + TRI_DF_BLOCK_ALIGN - 1) / TRI_DF_BLOCK_ALIGN) * TRI_DF_BLOCK_ALIGN;
keyBody = TRI_Allocate(TRI_CORE_MEM_ZONE, keyBodySize, true);
TRI_CopyString(keyBody, keySource, keySize);
TRI_CopyString(keyBody, (char*) &keyBuffer, keySize);
marker._offsetKey = sizeof(marker);
marker._offsetJson = sizeof(marker) + keyBodySize;
@ -1121,8 +1115,10 @@ static TRI_doc_mptr_t CreateShapedJson (TRI_doc_operation_context_t* context,
// create an edge
TRI_doc_edge_key_marker_t marker;
TRI_document_edge_t const* edge;
TRI_key_generator_t* keyGenerator;
size_t fromSize;
size_t toSize;
int res;
edge = data;
@ -1136,20 +1132,24 @@ static TRI_doc_mptr_t CreateShapedJson (TRI_doc_operation_context_t* context,
fromSize = strlen(edge->_fromKey) + 1;
toSize = strlen(edge->_toKey) + 1;
if (key) {
// we have a key!
keySize = strlen(key) + 1;
keySource = key;
}
else {
// create key from did
keySize = TRI_StringUInt64InPlace(marker.base._rid, ridBuffer) + 1;
keySource = (char*) &ridBuffer;
// create key using key generator
keyGenerator = (TRI_key_generator_t*) primary->_keyGenerator;
assert(keyGenerator != NULL);
res = keyGenerator->generate(keyGenerator, TRI_COLLECTION_KEY_MAX_LENGTH, &marker.base, key, (char*) &keyBuffer, &keySize);
if (res != TRI_ERROR_NO_ERROR) {
// key generation failed
Unlock(context);
primary->base._lastError = TRI_set_errno(TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD);
return mptr;
}
keySize += 1;
keyBodySize = ((keySize + fromSize + toSize + TRI_DF_BLOCK_ALIGN - 1) / TRI_DF_BLOCK_ALIGN) * TRI_DF_BLOCK_ALIGN;
keyBody = TRI_Allocate(TRI_CORE_MEM_ZONE, keyBodySize, true);
TRI_CopyString(keyBody, keySource, keySize);
TRI_CopyString(keyBody, &keyBuffer, keySize);
TRI_CopyString((keyBody + keySize), edge->_toKey, toSize);
TRI_CopyString((keyBody + keySize + toSize), edge->_fromKey, fromSize);
@ -1738,9 +1738,14 @@ static bool OpenIndexIterator (char const* filename, void* data) {
static bool InitDocumentCollection (TRI_document_collection_t* collection,
TRI_shaper_t* shaper) {
TRI_index_t* primary;
char* expr;
int res;
TRI_InitPrimaryCollection(&collection->base, shaper);
res = TRI_InitPrimaryCollection(&collection->base, shaper);
if (res != TRI_ERROR_NO_ERROR) {
TRI_DestroyPrimaryCollection(&collection->base);
return false;
}
collection->_headers = TRI_CreateSimpleHeaders(sizeof(TRI_doc_mptr_t));
if (collection->_headers == NULL) {
@ -1780,16 +1785,7 @@ static bool InitDocumentCollection (TRI_document_collection_t* collection,
collection->base.update = UpdateShapedJson;
collection->base.updateJson = UpdateJson;
collection->base.destroy = DeleteShapedJson;
expr = "^[0-9a-zA-Z][_0-9a-zA-Z]*$";
if (regcomp(&collection->DocumentKeyRegex, expr, REG_ICASE | REG_EXTENDED) != 0) {
LOG_FATAL("cannot compile regular expression");
TRI_FlushLogging();
exit(EXIT_FAILURE);
}
collection->keyLength = 200;
return true;
}
@ -1908,8 +1904,6 @@ void TRI_DestroyDocumentCollection (TRI_document_collection_t* collection) {
TRI_DestroyVectorPointer(&collection->_allIndexes);
TRI_DestroyPrimaryCollection(&collection->base);
regfree(&collection->DocumentKeyRegex);
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -197,18 +197,6 @@ typedef struct TRI_document_collection_s {
// .............................................................................
TRI_condition_t _journalsCondition;
// .............................................................................
// key regex
// .............................................................................
regex_t DocumentKeyRegex;
// .............................................................................
// maximum key length
// .............................................................................
uint32_t keyLength;
}
TRI_document_collection_t;

View File

@ -0,0 +1,411 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief collection key generators
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2011 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2012, triagens GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#include "key-generator.h"
#include <regex.h>
#include "BasicsC/conversions.h"
#include "BasicsC/json.h"
#include "BasicsC/strings.h"
#include "BasicsC/voc-errors.h"
#include "VocBase/primary-collection.h"
#include "VocBase/vocbase.h"
// -----------------------------------------------------------------------------
// --SECTION-- SPECIALIZED KEY GENERATORS
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// --SECTION-- REVISION KEY GENERATOR
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// --SECTION-- private types
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup VocBase
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief revision keygen private data
////////////////////////////////////////////////////////////////////////////////
typedef struct revision_keygen_s {
char* _prefix; // key prefix
size_t _prefixLength; // length of key prefix
size_t _padLength; // length of 0 bytes used for left padding
regex_t _regex; // key validation regex
bool _allowUserKeys; // allow keys supplied by user?
}
revision_keygen_t;
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup VocBase
/// @{
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- private functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief initialise the revision key generator
////////////////////////////////////////////////////////////////////////////////
static int RevisionInit (TRI_key_generator_t* const generator,
const TRI_json_t* const options) {
revision_keygen_t* data;
data = (revision_keygen_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(revision_keygen_t), false);
if (data == NULL) {
return TRI_ERROR_OUT_OF_MEMORY;
}
// defaults
data->_prefix = NULL;
data->_prefixLength = 0;
data->_padLength = 0;
data->_allowUserKeys = true;
if (regcomp(&data->_regex, "^[0-9a-zA-Z][_0-9a-zA-Z]*$", REG_ICASE | REG_EXTENDED) != 0) {
// OOM
TRI_Free(TRI_UNKNOWN_MEM_ZONE, data);
return TRI_ERROR_OUT_OF_MEMORY;
}
if (options != NULL) {
TRI_json_t* option;
option = TRI_LookupArrayJson(options, "prefix");
if (option != NULL && option->_type == TRI_JSON_STRING) {
data->_prefix = TRI_DuplicateStringZ(TRI_UNKNOWN_MEM_ZONE, option->_value._string.data);
if (data->_prefix == NULL) {
// OOM
TRI_Free(TRI_UNKNOWN_MEM_ZONE, data);
return TRI_ERROR_NO_ERROR;
}
data->_prefixLength = strlen(data->_prefix);
}
option = TRI_LookupArrayJson(options, "pad");
if (option != NULL && option->_type == TRI_JSON_NUMBER) {
data->_padLength = (size_t) option->_value._number;
}
option = TRI_LookupArrayJson(options, "allowUserKeys");
if (option != NULL && option->_type == TRI_JSON_BOOLEAN) {
data->_allowUserKeys = option->_value._boolean;
}
}
generator->_data = (void*) data;
return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief free the revision key generator
////////////////////////////////////////////////////////////////////////////////
static void RevisionFree (TRI_key_generator_t* const generator) {
revision_keygen_t* data;
data = (revision_keygen_t*) generator->_data;
if (data != NULL) {
if (data->_prefix != NULL) {
TRI_FreeString(TRI_UNKNOWN_MEM_ZONE, data->_prefix);
}
regfree(&data->_regex);
TRI_Free(TRI_UNKNOWN_MEM_ZONE, data);
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief generate a new key
/// the caller must make sure that the outBuffer is big enough to hold at least
/// maxLength + 1 bytes
////////////////////////////////////////////////////////////////////////////////
static int RevisionKey (TRI_key_generator_t* const generator,
const size_t maxLength,
const TRI_doc_document_key_marker_t* const marker,
const char* const userKey,
char* const outBuffer,
size_t* const outLength) {
revision_keygen_t* data;
char* current;
data = (revision_keygen_t*) generator->_data;
assert(data != NULL);
current = outBuffer;
if (userKey != NULL) {
size_t userKeyLength;
// user has specified a key
if (! data->_allowUserKeys) {
// we do not allow user-generated keys
return TRI_ERROR_ARANGO_DOCUMENT_KEY_UNEXPECTED;
}
userKeyLength = strlen(userKey);
if (userKeyLength > maxLength) {
// user key is too long
return TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD;
}
if (regexec(&data->_regex, userKey, 0, NULL, 0) != 0) {
return TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD;
}
memcpy(outBuffer, userKey, userKeyLength);
current += userKeyLength;
}
else {
// user has not specified a key, generate one
TRI_voc_rid_t revision = marker->_rid;
if (data->_prefix != NULL && data->_prefixLength > 0) {
// copy the prefix
memcpy(current, data->_prefix, data->_prefixLength);
current += data->_prefixLength;
}
if (data->_padLength == 0) {
current += TRI_StringUInt64InPlace(revision, current);
}
else {
char numBuffer[22];
size_t length;
length = TRI_StringUInt64InPlace(revision, (char*) &numBuffer);
if (length < data->_padLength) {
// pad with 0s
size_t padLength;
padLength = data->_padLength - length;
memset(current, '0', padLength);
current += padLength;
}
memcpy(current, (char*) &numBuffer, length);
current += length;
}
}
// add 0 byte
*current = '\0';
if (current - outBuffer > maxLength) {
return TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD;
}
*outLength = (current - outBuffer);
return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- KEY GENERATOR
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// --SECTION-- private static variables
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup VocBase
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief name of traditional key generator
////////////////////////////////////////////////////////////////////////////////
static const char* Traditional = "traditional";
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- private functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup VocBase
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief check whether the generaror type name is valid
////////////////////////////////////////////////////////////////////////////////
static bool ValidType (const char* const name) {
if (TRI_EqualString(name, Traditional)) {
return true;
}
return false;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief get the generator type from JSON
////////////////////////////////////////////////////////////////////////////////
static const char* GeneratorType (const TRI_json_t* const parameters) {
TRI_json_t* type;
if (parameters == NULL || parameters->_type != TRI_JSON_ARRAY) {
return Traditional;
}
type = TRI_LookupArrayJson(parameters, "type");
if (type == NULL || parameters->_type != TRI_JSON_STRING) {
return Traditional;
}
return parameters->_value._string.data;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create a new generator
////////////////////////////////////////////////////////////////////////////////
static TRI_key_generator_t* CreateGenerator (const TRI_json_t* const parameters,
TRI_primary_collection_t* const collection) {
TRI_key_generator_t* generator;
const char* type;
type = GeneratorType(parameters);
if (! ValidType(type)) {
return NULL;
}
generator = (TRI_key_generator_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_key_generator_t), false);
if (generator == NULL) {
return NULL;
}
generator->_data = NULL;
generator->_collection = collection;
if (TRI_EqualString(type, Traditional)) {
generator->init = &RevisionInit;
generator->generate = &RevisionKey;
generator->free = &RevisionFree;
}
return generator;
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- constructors / destructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup VocBase
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief create a key generator and attach it to the collection
////////////////////////////////////////////////////////////////////////////////
int TRI_CreateKeyGenerator (const TRI_json_t* const parameters,
TRI_primary_collection_t* const collection) {
TRI_key_generator_t* generator;
TRI_json_t* options;
int res;
generator = CreateGenerator(parameters, collection);
if (generator == NULL) {
return TRI_ERROR_OUT_OF_MEMORY;
}
options = NULL;
if (parameters != NULL) {
options = TRI_LookupArrayJson(parameters, "options");
if (options != NULL && options->_type != TRI_JSON_ARRAY) {
options = NULL;
}
}
res = generator->init(generator, options);
if (res == TRI_ERROR_NO_ERROR) {
collection->_keyGenerator = generator;
}
else {
TRI_FreeKeyGenerator(generator);
}
return res;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief free a key generator
////////////////////////////////////////////////////////////////////////////////
void TRI_FreeKeyGenerator (TRI_key_generator_t* generator) {
if (generator->free != NULL) {
generator->free(generator);
}
TRI_Free(TRI_UNKNOWN_MEM_ZONE, generator);
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
// End:

View File

@ -0,0 +1,126 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief collection key generator
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2011 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2012, triagens GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#ifndef TRIAGENS_DURHAM_VOC_BASE_KEY_GENERATOR_H
#define TRIAGENS_DURHAM_VOC_BASE_KEY_GENERATOR_H 1
#include "BasicsC/common.h"
#ifdef __cplusplus
extern "C" {
#endif
// -----------------------------------------------------------------------------
// --SECTION-- KEY GENERATORS
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// --SECTION-- FORWARD DECLARATIONS
// -----------------------------------------------------------------------------
struct TRI_doc_document_key_marker_s;
struct TRI_json_s;
struct TRI_primary_collection_s;
// -----------------------------------------------------------------------------
// --SECTION-- public defines
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup VocBase
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief maximum length of a key in a collection
////////////////////////////////////////////////////////////////////////////////
#define TRI_COLLECTION_KEY_MAX_LENGTH (128)
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public types
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup VocBase
/// @{
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_key_generator_s {
struct TRI_json_s* _parameters;
struct TRI_primary_collection_s* _collection;
void* _data;
int (*init)(struct TRI_key_generator_s* const, const struct TRI_json_s* const);
int (*generate)(struct TRI_key_generator_s* const, const size_t, const struct TRI_doc_document_key_marker_s* const, const char* const, char* const, size_t* const);
void (*free)(struct TRI_key_generator_s* const);
}
TRI_key_generator_t;
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- constructors / destructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup VocBase
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief create a key generator and attach it to the collection
////////////////////////////////////////////////////////////////////////////////
int TRI_CreateKeyGenerator (const struct TRI_json_s* const,
struct TRI_primary_collection_s* const);
////////////////////////////////////////////////////////////////////////////////
/// @brief free a key generator
////////////////////////////////////////////////////////////////////////////////
void TRI_FreeKeyGenerator (TRI_key_generator_t* const);
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus
}
#endif
#endif
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"

View File

@ -33,7 +33,8 @@
#include <BasicsC/logging.h>
#include <BasicsC/strings.h>
#include <VocBase/voc-shaper.h>
#include "VocBase/key-generator.h"
#include "VocBase/voc-shaper.h"
// -----------------------------------------------------------------------------
// --SECTION-- private functions
@ -414,10 +415,13 @@ static TRI_voc_size_t Count (TRI_primary_collection_t* primary) {
/// @brief initialises a primary collection
////////////////////////////////////////////////////////////////////////////////
void TRI_InitPrimaryCollection (TRI_primary_collection_t* collection,
TRI_shaper_t* shaper) {
int TRI_InitPrimaryCollection (TRI_primary_collection_t* collection,
TRI_shaper_t* shaper) {
int res;
collection->_shaper = shaper;
collection->_capConstraint = NULL;
collection->_keyGenerator = NULL;
collection->figures = Figures;
collection->size = Count;
@ -439,6 +443,11 @@ void TRI_InitPrimaryCollection (TRI_primary_collection_t* collection,
0);
TRI_InitReadWriteLock(&collection->_lock);
// init key generator. TODO: make this configurable
res = TRI_CreateKeyGenerator(NULL, collection);
return res;
}
////////////////////////////////////////////////////////////////////////////////
@ -446,6 +455,10 @@ void TRI_InitPrimaryCollection (TRI_primary_collection_t* collection,
////////////////////////////////////////////////////////////////////////////////
void TRI_DestroyPrimaryCollection (TRI_primary_collection_t* collection) {
if (collection->_keyGenerator != NULL) {
TRI_FreeKeyGenerator(collection->_keyGenerator);
}
TRI_DestroyReadWriteLock(&collection->_lock);
TRI_DestroyAssociativePointer(&collection->_primaryIndex);

View File

@ -43,6 +43,7 @@ extern "C" {
// -----------------------------------------------------------------------------
struct TRI_cap_constraint_s;
struct TRI_key_generator_s;
struct TRI_primary_collection_s;
struct TRI_transaction_s;
@ -323,6 +324,7 @@ typedef struct TRI_primary_collection_s {
TRI_associative_pointer_t _datafileInfo;
TRI_associative_pointer_t _primaryIndex;
struct TRI_key_generator_s* _keyGenerator;
struct TRI_cap_constraint_s* _capConstraint;
@ -446,7 +448,7 @@ TRI_doc_abort_transaction_marker_t;
/// @brief initializes a primary collection structure
////////////////////////////////////////////////////////////////////////////////
void TRI_InitPrimaryCollection (TRI_primary_collection_t*, TRI_shaper_t*);
int TRI_InitPrimaryCollection (TRI_primary_collection_t*, TRI_shaper_t*);
////////////////////////////////////////////////////////////////////////////////
/// @brief destroys a primary collection

View File

@ -72,6 +72,7 @@
"ERROR_ARANGO_COLLECTION_NOT_UNLOADED" : { "code" : 1217, "message" : "collection must be unloaded" },
"ERROR_ARANGO_COLLECTION_TYPE_INVALID" : { "code" : 1218, "message" : "collection type invalid" },
"ERROR_ARANGO_DOCUMENT_KEY_BAD" : { "code" : 1219, "message" : "illegal document key" },
"ERROR_ARANGO_DOCUMENT_KEY_UNEXPECTED" : { "code" : 1220, "message" : "unexpected document key" },
"ERROR_ARANGO_DATAFILE_FULL" : { "code" : 1300, "message" : "datafile full" },
"ERROR_QUERY_KILLED" : { "code" : 1500, "message" : "query killed" },
"ERROR_QUERY_PARSE" : { "code" : 1501, "message" : "%s" },

View File

@ -90,6 +90,7 @@ ERROR_ARANGO_DOCUMENT_TOO_LARGE,1216,"document too large","Will be raised when t
ERROR_ARANGO_COLLECTION_NOT_UNLOADED,1217,"collection must be unloaded","Will be raised when a collection should be unloaded, but has a different status."
ERROR_ARANGO_COLLECTION_TYPE_INVALID,1218,"collection type invalid","Will be raised when an invalid collection type is used in a request."
ERROR_ARANGO_DOCUMENT_KEY_BAD,1219,"illegal document key","Will be raised when a document key is corrupt."
ERROR_ARANGO_DOCUMENT_KEY_UNEXPECTED,1220,"unexpected document key","Will be raised when a user-defined document key is supplied for collections with auto key generation."
################################################################################
## ArangoDB storage errors

View File

@ -68,6 +68,7 @@ void TRI_InitialiseErrorMessages (void) {
REG_ERROR(ERROR_ARANGO_COLLECTION_NOT_UNLOADED, "collection must be unloaded");
REG_ERROR(ERROR_ARANGO_COLLECTION_TYPE_INVALID, "collection type invalid");
REG_ERROR(ERROR_ARANGO_DOCUMENT_KEY_BAD, "illegal document key");
REG_ERROR(ERROR_ARANGO_DOCUMENT_KEY_UNEXPECTED, "unexpected document key");
REG_ERROR(ERROR_ARANGO_DATAFILE_FULL, "datafile full");
REG_ERROR(ERROR_QUERY_KILLED, "query killed");
REG_ERROR(ERROR_QUERY_PARSE, "%s");

View File

@ -137,6 +137,9 @@ extern "C" {
/// Will be raised when an invalid collection type is used in a request.
/// - 1219: @CODE{illegal document key}
/// Will be raised when a document key is corrupt.
/// - 1220: @CODE{unexpected document key}
/// Will be raised when a user-defined document key is supplied for
/// collections with auto key generation.
/// - 1300: @CODE{datafile full}
/// Will be raised when the datafile reaches its limit.
/// - 1500: @CODE{query killed}
@ -910,6 +913,17 @@ void TRI_InitialiseErrorMessages (void);
#define TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD (1219)
////////////////////////////////////////////////////////////////////////////////
/// @brief 1220: ERROR_ARANGO_DOCUMENT_KEY_UNEXPECTED
///
/// unexpected document key
///
/// Will be raised when a user-defined document key is supplied for collections
/// with auto key generation.
////////////////////////////////////////////////////////////////////////////////
#define TRI_ERROR_ARANGO_DOCUMENT_KEY_UNEXPECTED (1220)
////////////////////////////////////////////////////////////////////////////////
/// @brief 1300: ERROR_ARANGO_DATAFILE_FULL
///