PageRenderTime 28ms CodeModel.GetById 18ms app.highlight 6ms RepoModel.GetById 0ms app.codeStats 0ms

/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
  1/*
  2 *  chunkList.h
  3 *  kangmodb
  4 *
  5 *  Created by 강모 김 on 11. 5. 1..
  6 *  Copyright 2011 강모소프트. All rights reserved.
  7 *
  8 */
  9
 10#ifndef _KD_CHUNK_LIST_H_
 11#define _KD_CHUNK_LIST_H_ (1)
 12
 13#include "list.h"
 14
 15/** @brief The header stored in the root chunk in the chunk list. Root chunk is the first chunk in the list.
 16 */
 17typedef struct stgRootChunkHeader
 18{
 19	/** @brief Keeps head/tail link of the double linked list.
 20	 */
 21	list_t chunkList;
 22} stgRootChunkHeader;
 23
 24/** @brief The header stored in chunks in the chunk list.  
 25 */
 26typedef struct stgChunkHeader
 27{
 28	/** @brief Keeps prev/next link of the double linked list.
 29	 */
 30	list_node_t nodeLinks;
 31} stgChunkHeader;
 32
 33/** @brief Maintain a double linked list that keeps track of multiple memory chunks.
 34 * 
 35 * - stgTransLogBuffer uses stgChunkList to keep multiple log chunks for a transaction.
 36 * - stgTable uses stgChunkList to keep multiple memory chunks to keep (key, data) pairs.
 37 */
 38class stgChunkList
 39{
 40private :
 41	/** @brief The first chunk in this chunk list. It has head/tail of the chunk list. 
 42	 */
 43    stgRootChunkHeader * rootChunk_;
 44	
 45	/** @brief The next chunk to iterate. Used by both iterate and reverseIterate.
 46	 */
 47	mutable void * nextIterationChunk_;
 48	
 49public :
 50
 51	/** @brief The size of unusable memory at the beginning of added chunk. 
 52	 */
 53	static const int CHUNK_UNUSABLE_SIZE = MAX(sizeof(stgRootChunkHeader), sizeof(stgChunkHeader));
 54	
 55	stgChunkList()
 56	{
 57		rootChunk_ = NULL;
 58		nextIterationChunk_ = NULL;
 59	}
 60	~stgChunkList()
 61	{
 62	}
 63	/** @brief See if the chunk list is empty.
 64	 */
 65	bool empty() const 
 66	{
 67		// If the root chunk(the first chunk) is NULL, it means the list is empty.
 68		return rootChunk_ == NULL;
 69	}
 70	/** @brief Add a chunk to the chunk list. 
 71	 */
 72	KD_VOID addChunk( const void * chunkAddress )
 73	{
 74		KD_TRY
 75		{
 76			if (rootChunk_ == NULL ) // No root chunk. Set the chunk as the root chunk
 77			{
 78				rootChunk_ = (stgRootChunkHeader*) chunkAddress;
 79				(void) list_init( &rootChunk_->chunkList ); 
 80			}
 81			else
 82			{
 83				stgChunkHeader * chunkHeader = (stgChunkHeader*) chunkAddress;
 84				(void) list_add_tail( &rootChunk_->chunkList, &chunkHeader->nodeLinks); 
 85			}
 86		}
 87		KD_CATCH
 88		KD_FINALLY
 89		KD_END
 90	}
 91	
 92	/** @brief Remove a chunk from the list.
 93	 */
 94	KD_VOID removeChunk( const void * chunkAddress )
 95	{
 96		KD_ASSERT( rootChunk_ != NULL );
 97
 98		KD_TRY
 99		{
100			// If the root chunk is removed, all chunks in the list are removed as well. This is by design.
101			if (chunkAddress == rootChunk_ )
102			{
103				rootChunk_ = NULL;
104			}
105			else // Not a root chunk, remove from the list 
106			{
107				stgChunkHeader * chunkHeader = (stgChunkHeader*) chunkAddress;
108				
109				(void) list_remove( &rootChunk_->chunkList, &chunkHeader->nodeLinks );
110			}
111		}
112		KD_CATCH
113		KD_FINALLY
114		KD_END
115	}
116	
117	/** @brief Initialize iterations.
118	 */
119	KD_VOID initIteration() const
120	{
121		KD_TRY
122		{
123			nextIterationChunk_ = rootChunk_;
124		}
125		KD_CATCH
126		KD_FINALLY
127		KD_END
128	} 
129
130	/** @brief Iterate a chunk. If no more chunk, *chunkAddress is set to NULL.
131	 */
132	KD_VOID iterate( void ** chunkAddress ) const
133	{
134		KD_DASSERT( chunkAddress != NULL );
135		
136		KD_TRY
137		{
138			if (nextIterationChunk_ == NULL) // End of iteration
139			{
140				*chunkAddress = NULL;
141			}
142			else 
143			{
144				*chunkAddress = nextIterationChunk_ ;
145				
146				if ( nextIterationChunk_ == rootChunk_ )
147				{
148					// Root chunk was the first one to iterate chunks. Next chunk to iterate is the one in head in the list.
149					nextIterationChunk_ = rootChunk_->chunkList.head;
150				}
151				else 
152				{
153					nextIterationChunk_ = ((stgChunkHeader*) nextIterationChunk_)->nodeLinks.next;
154				}
155
156				if ( nextIterationChunk_ == LIST_NODE_NULL( & rootChunk_->chunkList ) ) // Reached at the end of iteration?
157				{
158					nextIterationChunk_ = NULL;
159				}
160			}
161		}
162		KD_CATCH
163		KD_FINALLY
164		KD_END
165	} 
166
167	/** @brief Initialize iterations in reverse order.
168	 */
169	KD_VOID initReverseIteration() const
170	{
171		KD_TRY
172		{
173			if ( rootChunk_ == NULL ) // No chunk is added yet.
174			{
175				nextIterationChunk_ = NULL; // Nothing to iterate.
176			}
177			else 
178			{
179				// Start the reverse iteration from the tail of the list.
180				nextIterationChunk_ = rootChunk_->chunkList.tail;
181			}
182		}
183		KD_CATCH
184		KD_FINALLY
185		KD_END
186	} 
187
188	/** @brief Iterate a chunk in reverse order. If no more chunk, *chunkAddress is set to NULL.
189	 */
190	KD_VOID reverseIterate( void ** chunkAddress ) const
191	{
192		KD_DASSERT( chunkAddress != NULL );
193		
194		KD_TRY
195		{
196			if (nextIterationChunk_ == NULL) // End of iteration
197			{
198				*chunkAddress = NULL;
199			}
200			else 
201			{
202				*chunkAddress = nextIterationChunk_ ;
203				
204				if ( nextIterationChunk_ == rootChunk_ )
205				{
206					// Root chunk was the last one to iterate chunks in reverse order.
207					nextIterationChunk_ = NULL;
208				}
209				else 
210				{
211					nextIterationChunk_ = ((stgChunkHeader*) nextIterationChunk_)->nodeLinks.prev;
212				}
213				
214				if ( nextIterationChunk_ == LIST_NODE_NULL( & rootChunk_->chunkList ) ) // Reached at the end of the list?
215				{
216					// We need to iterate the root chunk, which is the last one to iterate in reverse order.
217					nextIterationChunk_ = rootChunk_;
218				}
219			}
220		}
221		KD_CATCH
222		KD_FINALLY
223		KD_END
224	} 
225};
226
227#endif /* _KD_CHUNK_LIST_H_ */