mirror of https://gitee.com/bigwinds/arangodb
292 lines
10 KiB
C
292 lines
10 KiB
C
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief general cursors
|
|
///
|
|
/// @file
|
|
///
|
|
/// DISCLAIMER
|
|
///
|
|
/// Copyright 2004-2013 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-2013, triAGENS GmbH, Cologne, Germany
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "VocBase/general-cursor.h"
|
|
|
|
#include "BasicsC/json.h"
|
|
#include "BasicsC/logging.h"
|
|
#include "BasicsC/vector.h"
|
|
|
|
#include "VocBase/shadow-data.h"
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- cursor result sets
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- constructors / destructors
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @addtogroup VocBase
|
|
/// @{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create a cursor result set
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_general_cursor_result_t* TRI_CreateCursorResult (void* data,
|
|
void (*freeData)(TRI_general_cursor_result_t*),
|
|
TRI_general_cursor_row_t (*getAt)(TRI_general_cursor_result_t const*, const TRI_general_cursor_length_t),
|
|
TRI_general_cursor_length_t (*getLength)(TRI_general_cursor_result_t const*)) {
|
|
|
|
TRI_general_cursor_result_t* result;
|
|
|
|
if (data == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
result = (TRI_general_cursor_result_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_general_cursor_result_t), false);
|
|
|
|
if (result == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
result->_data = data;
|
|
result->_freed = false;
|
|
|
|
result->freeData = freeData;
|
|
result->getAt = getAt;
|
|
result->getLength = getLength;
|
|
|
|
return result;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief destroy a cursor result set but do not free the pointer
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void TRI_DestroyCursorResult (TRI_general_cursor_result_t* const result) {
|
|
assert(result);
|
|
|
|
if (! result->_freed) {
|
|
result->freeData(result);
|
|
result->_freed = true;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief free a cursor result set
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void TRI_FreeCursorResult (TRI_general_cursor_result_t* const result) {
|
|
if (result != NULL) {
|
|
TRI_DestroyCursorResult(result);
|
|
TRI_Free(TRI_UNKNOWN_MEM_ZONE, result);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- cursors
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- private functions
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @addtogroup VocBase
|
|
/// @{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief returns the next element
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static inline TRI_general_cursor_row_t NextGeneralCursor (TRI_general_cursor_t* const cursor) {
|
|
if (cursor->_currentRow < cursor->_length) {
|
|
return cursor->_result->getAt(cursor->_result, cursor->_currentRow++);
|
|
}
|
|
|
|
if (! cursor->_result->_freed) {
|
|
cursor->_result->_freed = true;
|
|
cursor->_result->freeData(cursor->_result);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief checks if the cursor is exhausted
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static bool HasNextGeneralCursor (const TRI_general_cursor_t* const cursor) {
|
|
return cursor->_currentRow < cursor->_length;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief returns if the count flag is set for the cursor
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static bool HasCountGeneralCursor (const TRI_general_cursor_t* const cursor) {
|
|
return cursor->_hasCount;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief returns the maximum number of results per transfer
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static TRI_general_cursor_length_t GetBatchSizeGeneralCursor (const TRI_general_cursor_t* const cursor) {
|
|
return cursor->_batchSize;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief returns the cursor's extra data
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static TRI_json_t* GetExtraGeneralCursor (const TRI_general_cursor_t* const cursor) {
|
|
return cursor->_extra;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- public functions
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @addtogroup VocBase
|
|
/// @{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief frees a cursor
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void TRI_FreeGeneralCursor (TRI_general_cursor_t* cursor) {
|
|
if (cursor->_deleted) {
|
|
// prevent duplicate deletion
|
|
return;
|
|
}
|
|
|
|
cursor->_deleted = true;
|
|
|
|
if (cursor->_extra != NULL) {
|
|
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, cursor->_extra);
|
|
}
|
|
|
|
TRI_FreeCursorResult(cursor->_result);
|
|
|
|
TRI_DestroyMutex(&cursor->_lock);
|
|
TRI_Free(TRI_UNKNOWN_MEM_ZONE, cursor);
|
|
|
|
LOG_TRACE("destroyed general cursor");
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create a cursor
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_general_cursor_t* TRI_CreateGeneralCursor (TRI_general_cursor_result_t* result,
|
|
const bool doCount,
|
|
const TRI_general_cursor_length_t batchSize,
|
|
TRI_json_t* extra) {
|
|
TRI_general_cursor_t* cursor;
|
|
|
|
cursor = (TRI_general_cursor_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_general_cursor_t), false);
|
|
|
|
if (cursor == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
cursor->_result = result;
|
|
cursor->_extra = extra; // might be NULL
|
|
|
|
// state
|
|
cursor->_currentRow = 0;
|
|
cursor->_length = result->getLength(result);
|
|
cursor->_hasCount = doCount;
|
|
cursor->_batchSize = batchSize;
|
|
cursor->_deleted = false;
|
|
|
|
// assign functions
|
|
cursor->next = NextGeneralCursor;
|
|
cursor->hasNext = HasNextGeneralCursor;
|
|
cursor->hasCount = HasCountGeneralCursor;
|
|
cursor->getBatchSize = GetBatchSizeGeneralCursor;
|
|
cursor->getExtra = GetExtraGeneralCursor;
|
|
cursor->free = TRI_FreeGeneralCursor;
|
|
|
|
TRI_InitMutex(&cursor->_lock);
|
|
|
|
LOG_TRACE("created general cursor");
|
|
|
|
return cursor;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief exclusively lock a general cursor
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void TRI_LockGeneralCursor (TRI_general_cursor_t* const cursor) {
|
|
TRI_LockMutex(&cursor->_lock);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief unlock a general cursor
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void TRI_UnlockGeneralCursor (TRI_general_cursor_t* const cursor) {
|
|
assert(cursor);
|
|
|
|
TRI_UnlockMutex(&cursor->_lock);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief free a cursor based on its shadow data pointer
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void TRI_FreeShadowGeneralCursor (void* data) {
|
|
TRI_general_cursor_t* cursor = (TRI_general_cursor_t*) data;
|
|
|
|
TRI_FreeGeneralCursor(cursor);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create shadow data store for cursors
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_shadow_store_t* TRI_CreateShadowsGeneralCursor (void) {
|
|
return TRI_CreateShadowStore(&TRI_FreeShadowGeneralCursor);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Local Variables:
|
|
// mode: outline-minor
|
|
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}"
|
|
// End:
|