/trunk/src/kangmodb/chunkList.h
C Header | 227 lines | 157 code | 23 blank | 47 comment | 28 complexity | e5b963839e623ad337c1be9535de4bac MD5 | raw file
Possible License(s): BSD-3-Clause
- /*
- * chunkList.h
- * kangmodb
- *
- * Created by 강모 김 on 11. 5. 1..
- * Copyright 2011 강모소프트. All rights reserved.
- *
- */
- #ifndef _KD_CHUNK_LIST_H_
- #define _KD_CHUNK_LIST_H_ (1)
- #include "list.h"
- /** @brief The header stored in the root chunk in the chunk list. Root chunk is the first chunk in the list.
- */
- typedef struct stgRootChunkHeader
- {
- /** @brief Keeps head/tail link of the double linked list.
- */
- list_t chunkList;
- } stgRootChunkHeader;
- /** @brief The header stored in chunks in the chunk list.
- */
- typedef struct stgChunkHeader
- {
- /** @brief Keeps prev/next link of the double linked list.
- */
- list_node_t nodeLinks;
- } stgChunkHeader;
- /** @brief Maintain a double linked list that keeps track of multiple memory chunks.
- *
- * - stgTransLogBuffer uses stgChunkList to keep multiple log chunks for a transaction.
- * - stgTable uses stgChunkList to keep multiple memory chunks to keep (key, data) pairs.
- */
- class stgChunkList
- {
- private :
- /** @brief The first chunk in this chunk list. It has head/tail of the chunk list.
- */
- stgRootChunkHeader * rootChunk_;
-
- /** @brief The next chunk to iterate. Used by both iterate and reverseIterate.
- */
- mutable void * nextIterationChunk_;
-
- public :
- /** @brief The size of unusable memory at the beginning of added chunk.
- */
- static const int CHUNK_UNUSABLE_SIZE = MAX(sizeof(stgRootChunkHeader), sizeof(stgChunkHeader));
-
- stgChunkList()
- {
- rootChunk_ = NULL;
- nextIterationChunk_ = NULL;
- }
- ~stgChunkList()
- {
- }
- /** @brief See if the chunk list is empty.
- */
- bool empty() const
- {
- // If the root chunk(the first chunk) is NULL, it means the list is empty.
- return rootChunk_ == NULL;
- }
- /** @brief Add a chunk to the chunk list.
- */
- KD_VOID addChunk( const void * chunkAddress )
- {
- KD_TRY
- {
- if (rootChunk_ == NULL ) // No root chunk. Set the chunk as the root chunk
- {
- rootChunk_ = (stgRootChunkHeader*) chunkAddress;
- (void) list_init( &rootChunk_->chunkList );
- }
- else
- {
- stgChunkHeader * chunkHeader = (stgChunkHeader*) chunkAddress;
- (void) list_add_tail( &rootChunk_->chunkList, &chunkHeader->nodeLinks);
- }
- }
- KD_CATCH
- KD_FINALLY
- KD_END
- }
-
- /** @brief Remove a chunk from the list.
- */
- KD_VOID removeChunk( const void * chunkAddress )
- {
- KD_ASSERT( rootChunk_ != NULL );
- KD_TRY
- {
- // If the root chunk is removed, all chunks in the list are removed as well. This is by design.
- if (chunkAddress == rootChunk_ )
- {
- rootChunk_ = NULL;
- }
- else // Not a root chunk, remove from the list
- {
- stgChunkHeader * chunkHeader = (stgChunkHeader*) chunkAddress;
-
- (void) list_remove( &rootChunk_->chunkList, &chunkHeader->nodeLinks );
- }
- }
- KD_CATCH
- KD_FINALLY
- KD_END
- }
-
- /** @brief Initialize iterations.
- */
- KD_VOID initIteration() const
- {
- KD_TRY
- {
- nextIterationChunk_ = rootChunk_;
- }
- KD_CATCH
- KD_FINALLY
- KD_END
- }
- /** @brief Iterate a chunk. If no more chunk, *chunkAddress is set to NULL.
- */
- KD_VOID iterate( void ** chunkAddress ) const
- {
- KD_DASSERT( chunkAddress != NULL );
-
- KD_TRY
- {
- if (nextIterationChunk_ == NULL) // End of iteration
- {
- *chunkAddress = NULL;
- }
- else
- {
- *chunkAddress = nextIterationChunk_ ;
-
- if ( nextIterationChunk_ == rootChunk_ )
- {
- // Root chunk was the first one to iterate chunks. Next chunk to iterate is the one in head in the list.
- nextIterationChunk_ = rootChunk_->chunkList.head;
- }
- else
- {
- nextIterationChunk_ = ((stgChunkHeader*) nextIterationChunk_)->nodeLinks.next;
- }
- if ( nextIterationChunk_ == LIST_NODE_NULL( & rootChunk_->chunkList ) ) // Reached at the end of iteration?
- {
- nextIterationChunk_ = NULL;
- }
- }
- }
- KD_CATCH
- KD_FINALLY
- KD_END
- }
- /** @brief Initialize iterations in reverse order.
- */
- KD_VOID initReverseIteration() const
- {
- KD_TRY
- {
- if ( rootChunk_ == NULL ) // No chunk is added yet.
- {
- nextIterationChunk_ = NULL; // Nothing to iterate.
- }
- else
- {
- // Start the reverse iteration from the tail of the list.
- nextIterationChunk_ = rootChunk_->chunkList.tail;
- }
- }
- KD_CATCH
- KD_FINALLY
- KD_END
- }
- /** @brief Iterate a chunk in reverse order. If no more chunk, *chunkAddress is set to NULL.
- */
- KD_VOID reverseIterate( void ** chunkAddress ) const
- {
- KD_DASSERT( chunkAddress != NULL );
-
- KD_TRY
- {
- if (nextIterationChunk_ == NULL) // End of iteration
- {
- *chunkAddress = NULL;
- }
- else
- {
- *chunkAddress = nextIterationChunk_ ;
-
- if ( nextIterationChunk_ == rootChunk_ )
- {
- // Root chunk was the last one to iterate chunks in reverse order.
- nextIterationChunk_ = NULL;
- }
- else
- {
- nextIterationChunk_ = ((stgChunkHeader*) nextIterationChunk_)->nodeLinks.prev;
- }
-
- if ( nextIterationChunk_ == LIST_NODE_NULL( & rootChunk_->chunkList ) ) // Reached at the end of the list?
- {
- // We need to iterate the root chunk, which is the last one to iterate in reverse order.
- nextIterationChunk_ = rootChunk_;
- }
- }
- }
- KD_CATCH
- KD_FINALLY
- KD_END
- }
- };
- #endif /* _KD_CHUNK_LIST_H_ */