1
0
Fork 0

fixed memleak

This commit is contained in:
Jan Steemann 2013-03-22 18:38:17 +01:00
parent a8d5a06f57
commit c473e42f77
10 changed files with 328 additions and 82 deletions

View File

@ -2193,7 +2193,7 @@ static v8::Handle<v8::Value> JS_NextGeneralCursor (v8::Arguments const& argv) {
if (argv.Length() != 0) {
return scope.Close(v8::ThrowException(
TRI_CreateErrorObject(TRI_ERROR_ILLEGAL_OPTION,
"usage: count()")));
"usage: next()")));
}
TRI_vocbase_t* vocbase = GetContextVocBase();
@ -3400,7 +3400,7 @@ static v8::Handle<v8::Value> JS_CountVocbaseCol (v8::Arguments const& argv) {
// READ-LOCK start
trx.lockRead();
size_t s = primary->size(primary);
const TRI_voc_size_t s = primary->size(primary);
trx.finish(res);
// READ-LOCK end

View File

@ -206,7 +206,7 @@ typedef struct TRI_col_header_marker_s {
char _padding_col_header_marker[4];
#endif
TRI_voc_cid_t _cid; // 8 bytes
TRI_voc_cid_t _cid; // 8 bytes
}
TRI_col_header_marker_t;

View File

@ -312,16 +312,16 @@ TRI_datafile_t;
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_df_marker_s {
TRI_voc_size_t _size; // 4 bytes, must be supplied
TRI_voc_crc_t _crc; // 4 bytes, will be generated
TRI_voc_size_t _size; // 4 bytes, must be supplied
TRI_voc_crc_t _crc; // 4 bytes, will be generated
TRI_df_marker_type_t _type; // 4 bytes, must be supplied
TRI_df_marker_type_t _type; // 4 bytes, must be supplied
#ifdef TRI_PADDING_32
char _padding_df_marker[4];
#endif
TRI_voc_tick_t _tick; // 8 bytes, will be generated
TRI_voc_tick_t _tick; // 8 bytes, will be generated
}
TRI_df_marker_t;

View File

@ -369,12 +369,10 @@ static int CloneDocumentMarker (TRI_df_marker_t const* original,
return TRI_ERROR_OUT_OF_MEMORY;
}
// copy non-changed data (e.g. key(s)) from old marker into new marker
memcpy(marker, original, baseLength);
// set the marker type, size, revision id etc.
tick = TRI_NewTickVocBase();
TRI_InitMarker(&marker->base, markerType, *totalSize, tick);
// copy non-changed data (e.g. key(s)) from old marker into new marker
TRI_CloneMarker(&marker->base, original, baseLength, *totalSize, tick);
marker->_rid = tick;
marker->_shape = shaped->_sid;

View File

@ -36,11 +36,33 @@
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief clones a marker
////////////////////////////////////////////////////////////////////////////////
void TRI_CloneMarker (TRI_df_marker_t* dst,
TRI_df_marker_t const* src,
TRI_voc_size_t copyLength,
TRI_voc_size_t newSize,
TRI_voc_tick_t tick) {
TRI_ASSERT_DEBUG(src != NULL);
TRI_ASSERT_DEBUG(dst != NULL);
TRI_ASSERT_DEBUG(copyLength > 0);
TRI_ASSERT_DEBUG(newSize > 0);
TRI_ASSERT_DEBUG(tick > 0);
memcpy(dst, src, copyLength);
dst->_size = newSize;
dst->_crc = 0;
dst->_tick = tick;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief initialises a marker with the most basic information
////////////////////////////////////////////////////////////////////////////////
void TRI_InitMarker (TRI_df_marker_t* const marker,
void TRI_InitMarker (TRI_df_marker_t* marker,
TRI_df_marker_type_e type,
TRI_voc_size_t size,
TRI_voc_tick_t tick) {
@ -49,10 +71,13 @@ void TRI_InitMarker (TRI_df_marker_t* const marker,
TRI_ASSERT_DEBUG(size > 0);
TRI_ASSERT_DEBUG(tick > 0);
marker->_type = type;
// initialise the basic byytes
memset(marker, 0, size);
marker->_size = size;
marker->_tick = tick;
marker->_crc = 0;
marker->_type = type;
marker->_tick = tick;
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -45,11 +45,21 @@ extern "C" {
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief clones a marker
////////////////////////////////////////////////////////////////////////////////
void TRI_CloneMarker (TRI_df_marker_t*,
TRI_df_marker_t const*,
TRI_voc_size_t,
TRI_voc_size_t,
TRI_voc_tick_t);
////////////////////////////////////////////////////////////////////////////////
/// @brief initialises a marker with the most basic information
////////////////////////////////////////////////////////////////////////////////
void TRI_InitMarker (TRI_df_marker_t* const,
void TRI_InitMarker (TRI_df_marker_t*,
TRI_df_marker_type_e,
TRI_voc_size_t,
TRI_voc_tick_t);

View File

@ -184,8 +184,8 @@ static TRI_datafile_t* CreateJournal (TRI_primary_collection_t* primary,
TRI_InitMarker(&cm.base, TRI_COL_MARKER_HEADER, sizeof(TRI_col_header_marker_t), TRI_NewTickVocBase());
cm._cid = collection->_info._cid;
cm._type = (TRI_col_type_t) collection->_info._type;
cm._cid = collection->_info._cid;
res = TRI_WriteCrcElementDatafile(journal, position, &cm.base, sizeof(cm), true);

View File

@ -50,27 +50,163 @@
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief return the status of the transaction as a string
/// @brief hashes the collection id
////////////////////////////////////////////////////////////////////////////////
static const char* StatusTransaction (const TRI_transaction_status_e status) {
switch (status) {
case TRI_TRANSACTION_UNDEFINED:
return "undefined";
case TRI_TRANSACTION_CREATED:
return "created";
case TRI_TRANSACTION_RUNNING:
return "running";
case TRI_TRANSACTION_COMMITTED:
return "committed";
case TRI_TRANSACTION_ABORTED:
return "aborted";
case TRI_TRANSACTION_FAILED:
return "failed";
static uint64_t HashKeyCid (TRI_associative_pointer_t* array, void const* key) {
TRI_transaction_cid_t const* k = key;
return (uint64_t) *k;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief hashs the collection id
////////////////////////////////////////////////////////////////////////////////
static uint64_t HashElementCid (TRI_associative_pointer_t* array, void const* element) {
TRI_transaction_collection_global_t const* e = element;
return (uint64_t) e->_cid;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief compares a collection id and a collection
////////////////////////////////////////////////////////////////////////////////
static bool EqualKeyCid (TRI_associative_pointer_t* array, void const* key, void const* element) {
TRI_transaction_cid_t const* k = key;
TRI_transaction_collection_global_t const* e = element;
return *k == e->_cid;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create a global instance of a collection
////////////////////////////////////////////////////////////////////////////////
static TRI_transaction_collection_global_t* CreateGlobalInstance (TRI_transaction_cid_t cid) {
TRI_transaction_collection_global_t* globalInstance;
globalInstance = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_transaction_collection_global_t), false);
if (globalInstance != NULL) {
globalInstance->_cid = cid;
globalInstance->_lastStartedReader = 0;
globalInstance->_lastFinishedReader = 0;
globalInstance->_lastStartedWriter = 0;
globalInstance->_lastAbortedWriter = 0;
globalInstance->_lastFinishedWriter = 0;
TRI_InitReadWriteLock(&globalInstance->_lock);
}
assert(false);
return "unknown";
return globalInstance;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create a global instance of a collection
////////////////////////////////////////////////////////////////////////////////
static void FreeGlobalInstance (TRI_transaction_collection_global_t* globalInstance) {
TRI_DestroyReadWriteLock(&globalInstance->_lock);
TRI_Free(TRI_UNKNOWN_MEM_ZONE, globalInstance);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief get the global instance of a collection
////////////////////////////////////////////////////////////////////////////////
static TRI_transaction_collection_global_t* GetGlobalInstance (TRI_transaction_context_t* context,
TRI_transaction_cid_t cid,
const bool create) {
TRI_transaction_collection_global_t* globalInstance;
TRI_transaction_collection_global_t* found;
// acquire a read-lock on the global list of collections
TRI_ReadLockReadWriteLock(&context->_collectionsLock);
globalInstance = TRI_LookupByKeyAssociativePointer(&context->_collections, &cid);
TRI_ReadUnlockReadWriteLock(&context->_collectionsLock);
if (globalInstance != NULL) {
// we already have a global instance
return globalInstance;
}
// collection not found
if (! create) {
// not asked to create a new global instance
return NULL;
}
// create a new global instance
globalInstance = CreateGlobalInstance(cid);
if (globalInstance == NULL) {
return NULL;
}
// write lock and insert the new instance, but only if no one else has inserted it
TRI_WriteLockReadWriteLock(&context->_collectionsLock);
found = TRI_InsertKeyAssociativePointer(&context->_collections, &cid, globalInstance, false);
TRI_WriteUnlockReadWriteLock(&context->_collectionsLock);
if (found != NULL) {
// someone else inserted another global instance. so we'll return it
FreeGlobalInstance(globalInstance);
return found;
}
// our own instance has been inserted
return globalInstance;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief update the global transaction statistics
////////////////////////////////////////////////////////////////////////////////
static int UpdateGlobalStats (const TRI_transaction_t const* trx,
const TRI_transaction_status_e status) {
size_t i, n;
n = trx->_collections._length;
for (i = 0; i < n; ++i) {
TRI_transaction_collection_t* collection;
TRI_transaction_collection_global_t* globalInstance;
collection = (TRI_transaction_collection_t*) TRI_AtVectorPointer(&trx->_collections, i);
globalInstance = collection->_globalInstance;
TRI_ASSERT_DEBUG(globalInstance != NULL);
TRI_WriteLockReadWriteLock(&globalInstance->_lock);
if (collection->_accessType == TRI_TRANSACTION_READ) {
if (status == TRI_TRANSACTION_RUNNING) {
globalInstance->_lastStartedReader = trx->_id;
}
else if (status == TRI_TRANSACTION_ABORTED ||
status == TRI_TRANSACTION_COMMITTED) {
globalInstance->_lastFinishedReader = trx->_id;
}
}
else {
if (status == TRI_TRANSACTION_RUNNING) {
globalInstance->_lastStartedWriter = trx->_id;
}
else if (status == TRI_TRANSACTION_ABORTED) {
globalInstance->_lastAbortedWriter = trx->_id;
}
else if (status == TRI_TRANSACTION_COMMITTED) {
globalInstance->_lastFinishedWriter = trx->_id;
}
}
TRI_WriteUnlockReadWriteLock(&globalInstance->_lock);
}
return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
@ -100,6 +236,14 @@ TRI_transaction_context_t* TRI_CreateTransactionContext (TRI_vocbase_t* const vo
}
context->_vocbase = vocbase;
TRI_InitAssociativePointer(&context->_collections,
TRI_UNKNOWN_MEM_ZONE,
HashKeyCid,
HashElementCid,
EqualKeyCid,
NULL);
TRI_InitReadWriteLock(&context->_collectionsLock);
return context;
}
@ -109,6 +253,9 @@ TRI_transaction_context_t* TRI_CreateTransactionContext (TRI_vocbase_t* const vo
////////////////////////////////////////////////////////////////////////////////
void TRI_FreeTransactionContext (TRI_transaction_context_t* const context) {
TRI_DestroyAssociativePointer(&context->_collections);
TRI_DestroyReadWriteLock(&context->_collectionsLock);
TRI_Free(TRI_UNKNOWN_MEM_ZONE, context);
}
@ -130,8 +277,20 @@ void TRI_FreeTransactionContext (TRI_transaction_context_t* const context) {
/// this function gets called for all collections that are dropped
////////////////////////////////////////////////////////////////////////////////
void TRI_RemoveCollectionTransactionContext (TRI_transaction_context_t* const context,
void TRI_RemoveCollectionTransactionContext (TRI_transaction_context_t* context,
const TRI_transaction_cid_t cid) {
TRI_transaction_collection_global_t* globalInstance;
globalInstance = GetGlobalInstance(context, cid, false);
if (globalInstance != NULL) {
// write lock and remove the instance
TRI_WriteLockReadWriteLock(&context->_collectionsLock);
TRI_RemoveKeyAssociativePointer(&context->_collections, &cid);
TRI_WriteUnlockReadWriteLock(&context->_collectionsLock);
FreeGlobalInstance(globalInstance);
}
}
////////////////////////////////////////////////////////////////////////////////
@ -151,6 +310,30 @@ void TRI_RemoveCollectionTransactionContext (TRI_transaction_context_t* const co
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief return the status of the transaction as a string
////////////////////////////////////////////////////////////////////////////////
static const char* StatusTransaction (const TRI_transaction_status_e status) {
switch (status) {
case TRI_TRANSACTION_UNDEFINED:
return "undefined";
case TRI_TRANSACTION_CREATED:
return "created";
case TRI_TRANSACTION_RUNNING:
return "running";
case TRI_TRANSACTION_COMMITTED:
return "committed";
case TRI_TRANSACTION_ABORTED:
return "aborted";
case TRI_TRANSACTION_FAILED:
return "failed";
}
assert(false);
return "unknown";
}
////////////////////////////////////////////////////////////////////////////////
/// @brief find a collection in the transaction's list of collections
////////////////////////////////////////////////////////////////////////////////
@ -190,10 +373,18 @@ static TRI_transaction_collection_t* FindCollection (const TRI_transaction_t* co
/// @brief create a transaction collection container
////////////////////////////////////////////////////////////////////////////////
static TRI_transaction_collection_t* CreateCollection (const TRI_transaction_cid_t cid,
static TRI_transaction_collection_t* CreateCollection (TRI_transaction_context_t* context,
const TRI_transaction_cid_t cid,
const TRI_transaction_type_e accessType,
const int nestingLevel) {
TRI_transaction_collection_t* collection;
TRI_transaction_collection_global_t* globalInstance;
globalInstance = GetGlobalInstance(context, cid, true);
if (globalInstance == NULL) {
return NULL;
}
collection = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_transaction_collection_t), false);
@ -203,13 +394,12 @@ static TRI_transaction_collection_t* CreateCollection (const TRI_transaction_cid
}
// initialise collection properties
collection->_cid = cid;
collection->_accessType = accessType;
collection->_nestingLevel = nestingLevel;
collection->_collection = NULL;
collection->_locked = false;
collection->_numWrites = 0;
collection->_cid = cid;
collection->_accessType = accessType;
collection->_nestingLevel = nestingLevel;
collection->_collection = NULL;
collection->_locked = false;
collection->_globalInstance = globalInstance;
return collection;
}
@ -426,8 +616,13 @@ static int UpdateTransactionStatus (TRI_transaction_t* const trx,
TRI_ASSERT_DEBUG(status == TRI_TRANSACTION_COMMITTED || status == TRI_TRANSACTION_ABORTED);
}
if (status == TRI_TRANSACTION_RUNNING || status == TRI_TRANSACTION_COMMITTED || status == TRI_TRANSACTION_ABORTED) {
// notify all participating collections about the transaction status change
if (status == TRI_TRANSACTION_RUNNING ||
status == TRI_TRANSACTION_ABORTED ||
status == TRI_TRANSACTION_COMMITTED) {
// notify all participating collections about the status change
UpdateGlobalStats(trx, status);
// update the global statistics
NotifyCollections(trx, status);
}
@ -491,9 +686,6 @@ void TRI_FreeTransaction (TRI_transaction_t* const trx) {
TRI_AbortTransaction(trx, 0);
}
// TODO: this shouldn't be necessary at all
// ReleaseCollections(trx, 0);
// free all collections
i = trx->_collections._length;
while (i-- > 0) {
@ -690,7 +882,7 @@ int TRI_AddCollectionTransaction (TRI_transaction_t* const trx,
}
// collection was not contained. now create and insert it
collection = CreateCollection(cid, accessType, nestingLevel);
collection = CreateCollection(trx->_context, cid, accessType, nestingLevel);
if (collection == NULL) {
// out of memory

View File

@ -59,6 +59,16 @@ struct TRI_vocbase_col_s;
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief transaction id
////////////////////////////////////////////////////////////////////////////////
typedef uint64_t TRI_transaction_id_t;
////////////////////////////////////////////////////////////////////////////////
/// @brief collection id
////////////////////////////////////////////////////////////////////////////////
typedef uint64_t TRI_transaction_cid_t;
////////////////////////////////////////////////////////////////////////////////
@ -124,18 +134,10 @@ TRI_transaction_status_e;
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_transaction_context_s {
//TRI_transaction_id_t _id; // last transaction id assigned
TRI_read_write_lock_t _rwLock; // lock used to either simulatensously read this structure,
// or uniquely modify this structure
#if 0
TRI_mutex_t _lock; // lock used to serialize starting/stopping transactions
TRI_mutex_t _collectionLock; // lock used when accessing _collections
TRI_transaction_list_t _readTransactions; // global list of currently ongoing read transactions
TRI_transaction_list_t _writeTransactions; // global list of currently ongoing write transactions
TRI_associative_pointer_t _collections; // list of collections (TRI_transaction_collection_global_t)
#endif
struct TRI_vocbase_s* _vocbase; // pointer to vocbase
TRI_associative_pointer_t _collections;
TRI_read_write_lock_t _collectionsLock;
struct TRI_vocbase_s* _vocbase;
}
TRI_transaction_context_t;
@ -182,7 +184,7 @@ void TRI_FreeTransactionContext (TRI_transaction_context_t* const);
/// this function must be called for all collections that are dropped
////////////////////////////////////////////////////////////////////////////////
void TRI_RemoveCollectionTransactionContext (TRI_transaction_context_t* const,
void TRI_RemoveCollectionTransactionContext (TRI_transaction_context_t*,
const TRI_transaction_cid_t);
////////////////////////////////////////////////////////////////////////////////
@ -202,17 +204,35 @@ void TRI_RemoveCollectionTransactionContext (TRI_transaction_context_t* const,
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief global instance of a collection
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_transaction_collection_global_s {
TRI_transaction_cid_t _cid;
TRI_read_write_lock_t _lock;
TRI_transaction_id_t _lastStartedReader;
TRI_transaction_id_t _lastFinishedReader;
TRI_transaction_id_t _lastStartedWriter;
TRI_transaction_id_t _lastAbortedWriter;
TRI_transaction_id_t _lastFinishedWriter;
}
TRI_transaction_collection_global_t;
////////////////////////////////////////////////////////////////////////////////
/// @brief collection used in a transaction
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_transaction_collection_s {
TRI_transaction_cid_t _cid; // collection id
TRI_transaction_type_e _accessType; // access type (read|write)
int _nestingLevel; // the transaction level that added this collection
struct TRI_vocbase_col_s* _collection; // vocbase collection pointer
uint64_t _numWrites; // number of writes performed for the collection
bool _locked; // collection lock flag
TRI_transaction_cid_t _cid; // collection id
TRI_transaction_type_e _accessType; // access type (read|write)
int _nestingLevel; // the transaction level that added this collection
struct TRI_vocbase_col_s* _collection; // vocbase collection pointer
TRI_transaction_collection_global_t* _globalInstance; // pointer to the global instance
bool _locked; // collection lock flag
}
TRI_transaction_collection_t;
@ -238,14 +258,13 @@ TRI_transaction_hint_e;
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_transaction_s {
TRI_transaction_context_t* _context; // global context object
// TODO: fix
uint64_t _id;
TRI_transaction_type_e _type; // access type (read|write)
TRI_transaction_status_e _status; // current status
TRI_vector_pointer_t _collections; // list of participating collections
TRI_transaction_hint_t _hints; // hints;
int _nestingLevel;
TRI_transaction_context_t* _context; // global context object
TRI_transaction_id_t _id;
TRI_transaction_type_e _type; // access type (read|write)
TRI_transaction_status_e _status; // current status
TRI_vector_pointer_t _collections; // list of participating collections
TRI_transaction_hint_t _hints; // hints;
int _nestingLevel;
}
TRI_transaction_t;

View File

@ -101,7 +101,7 @@ static TRI_spin_t TickLock;
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief hashs the auth info
/// @brief hashes the auth info
////////////////////////////////////////////////////////////////////////////////
static uint64_t HashKeyAuthInfo (TRI_associative_pointer_t* array, void const* key) {
@ -111,7 +111,7 @@ static uint64_t HashKeyAuthInfo (TRI_associative_pointer_t* array, void const* k
}
////////////////////////////////////////////////////////////////////////////////
/// @brief hashs the auth info
/// @brief hashes the auth info
////////////////////////////////////////////////////////////////////////////////
static uint64_t HashElementAuthInfo (TRI_associative_pointer_t* array, void const* element) {
@ -132,7 +132,7 @@ static bool EqualKeyAuthInfo (TRI_associative_pointer_t* array, void const* key,
}
////////////////////////////////////////////////////////////////////////////////
/// @brief hashs the collection id
/// @brief hashes the collection id
////////////////////////////////////////////////////////////////////////////////
static uint64_t HashKeyCid (TRI_associative_pointer_t* array, void const* key) {
@ -142,7 +142,7 @@ static uint64_t HashKeyCid (TRI_associative_pointer_t* array, void const* key) {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief hashs the collection id
/// @brief hashes the collection id
////////////////////////////////////////////////////////////////////////////////
static uint64_t HashElementCid (TRI_associative_pointer_t* array, void const* element) {
@ -163,7 +163,7 @@ static bool EqualKeyCid (TRI_associative_pointer_t* array, void const* key, void
}
////////////////////////////////////////////////////////////////////////////////
/// @brief hashs the collection name
/// @brief hashes the collection name
////////////////////////////////////////////////////////////////////////////////
static uint64_t HashKeyCollectionName (TRI_associative_pointer_t* array, void const* key) {
@ -173,7 +173,7 @@ static uint64_t HashKeyCollectionName (TRI_associative_pointer_t* array, void co
}
////////////////////////////////////////////////////////////////////////////////
/// @brief hashs the collection name
/// @brief hashes the collection name
////////////////////////////////////////////////////////////////////////////////
static uint64_t HashElementCollectionName (TRI_associative_pointer_t* array, void const* element) {
@ -1362,6 +1362,7 @@ void TRI_DestroyVocBase (TRI_vocbase_t* vocbase) {
TRI_vocbase_col_t* collection;
collection = (TRI_vocbase_col_t*) vocbase->_deadCollections._buffer[i];
TRI_RemoveCollectionTransactionContext(vocbase->_transactionContext, collection->_cid);
FreeCollection(vocbase, collection);
}
@ -1370,6 +1371,7 @@ void TRI_DestroyVocBase (TRI_vocbase_t* vocbase) {
TRI_vocbase_col_t* collection;
collection = (TRI_vocbase_col_t*) vocbase->_collections._buffer[i];
TRI_RemoveCollectionTransactionContext(vocbase->_transactionContext, collection->_cid);
FreeCollection(vocbase, collection);
}