mirror of https://gitee.com/bigwinds/arangodb
pluggable key generators
This commit is contained in:
parent
cdd163cc8a
commit
30ba8771a7
|
@ -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 \
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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:
|
|
@ -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--\\|/// @\\}\\)"
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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" },
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
///
|
||||
|
|
Loading…
Reference in New Issue