PageRenderTime 47ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/trunk/src/kangmodb/table.h

#
C Header | 249 lines | 113 code | 21 blank | 115 comment | 4 complexity | 8750903ef59496bb4e775f2e0478f99a MD5 | raw file
Possible License(s): BSD-3-Clause
  1. /**
  2. * table.h
  3. * kangmodb
  4. *
  5. * Created by 강모 김 on 11. 5. 1..
  6. * Copyright 2011 강모소프트. All rights reserved.
  7. *
  8. * Design of "Restart Recovery":
  9. * (1) Restart Recovery Speed Optimization
  10. * - To boost the restart recovery process, stgTable keeps (key, data) pairs in shared memory chunks allocated from stgSharedRegion.
  11. * - Log records of active transactions are also kept in stgTransLogBuffer which allocates shared memory chunks from stgSharedRegion.
  12. * c.f.> stgTableMgr manages the strSharedRegion object for all tables.
  13. *
  14. * (2) Power Failure or OS crash - We don't have shared memory regions.
  15. * - Redo all log records in the log stream where only committed transactions send its own log buffer.
  16. * - No need to undo any log records, because all transaction logs in the log stream are from committed transactions only.
  17. *
  18. * (3) Process Failure - We have shared memory regions.
  19. * (2.1) Phase I - Reconstruct stgTableMgr and stgTable objects from the shared memory region.
  20. * - Iterate shared memory chunks for stgTable objects to find out root chunk of each table.
  21. * - Root chunk is one of shared memory chunks allocated by stgSharedRegion, and becomes the start point for searching (key,data) pair.
  22. * - At this point, we can open a cursor for each table, but some tables may have uncommitted modifications by active transactions.
  23. * (2.2) Phase II - Reconstruct stgTransLogBuffer objects of active transactions from the shared memory region, rollback all logs.
  24. * - Iterate shared memory chunks for stgTransLogBuffer to find out root chunk of each transaction log buffer.
  25. * - Root chunk is one of shared memory chunks allocated by stgSharedRegion, and becomes the start point for traversing log records.
  26. * - Revert all new versions of (key, data) pairs made by these active transactions by traversing keys stored in log records.
  27. * (2.3) Phase III - Get the maxCommitVersion from the shared memory region, set it to maxCommitVersion_ member in stgTransMgr.
  28. * - stgTransMgr stores maxCommitVersion in the shared memory region.
  29. *
  30. * Design of "DATA Versioning on a KEY" :
  31. * - stgTable stores (KEY, DATA) pair. Duplicate key value is not allowed, so a KEY value is unique in a table.
  32. * - Each DATA has following flags
  33. * - (01bit) deleted
  34. * - Indicates the (KEY, DATA) pair is deleted
  35. * - (32bit) savepointID
  36. * - The savepoint ID. A new version of DATA is created only when the savepoint ID changes.
  37. * - Update/Delete with the same savepoint ID does not create a new version, but it is in-place updated.
  38. * - (64bit) commitVersion
  39. * - The commit version number. 0 indicates it is not committed yet. A number greater than 0 indicates it is committed.
  40. * - The version number increases monotonously. Transactions allocate the commit version number from stgTransMgr.
  41. * - savepointID can share data storage with commitVersion to optimize memory space.
  42. *
  43. * - Insertion : (KEY, DATA).
  44. * - stgTable inserts the KEY into access methods such as skip lists, and then dangles the DATA onto the key with the default savepoint 0(s0),
  45. * but the commit version is set to 0(c0) indicating it is not committed yet.
  46. * - (KEY, DATA-s0-c0)
  47. * - Upon tranasction commit, the transaction allocates a commit version(say 1234) from stgTransMgr, sets it to DATA indicating it is committed.
  48. * - After setting commit version to all (KEY,DATA) pairs that the transaction modified, call stgTransMgr::commitVersion to notify the transaction completed setting the commit version to all modified (KEY,VALUE) pair.
  49. * - This allows other transactions to read the committed (KEY,DATA) pairs.
  50. * - (KEY, DATA-c1234)
  51. * - When the key is updated, a new version of data, data_s0 is added. (key, data-s0-c0, data )
  52. * - When the transaction commits, it sets the commit version to the new version (key, data-c1234, data )
  53. * - When the key is deleted, a new version of data, data_s0 is added with its delete bit set. (key, data-deleted-s0-c0, data)
  54. * - When the transaction commits, it sets the commit version to the new version (key, data-deleted-c1234, data )
  55. *
  56. * Design of "Rollback to Savepoint" :
  57. * - Only one transaction can create a new version of DATA on a KEY. (Say, modifying transaction)
  58. * - In case the modifying transaction updates, deletes, or inserts DATA on a KEY multiple times,
  59. * no new version is created, but in-place update is done on the first new version of the data.
  60. * - However, when a savepoint number of a transaction increases because the transaction allocated a new savepoint,
  61. * a new version of data is is created for the savepoint when the transaction changes DATA on the KEY.
  62. * - (KEY, DATA-s1-c0, DATA-s0-c0 ) ; Savepoint number increase from s0 to s1. A dedicated new version for s1, DATA-s1-c0 is created.
  63. * - This is to help "Rollback to Savepoint". Rolling back to a savepoint simply removes all new versions created after the savepoint.
  64. * - (KEY, DATA-s0-c0) ; Rollback to Savepoint s0 removed the version DATA-s1-c0.
  65. * - How to iterate all KEYs that the transaction touched?
  66. * - We can interate log records in stgTransLogBuffer in reverse order until we meet the log for Savepoint s1.
  67. * - Each INSERT, UPDATE, DELETE log has the KEY value, so we can search the access method with the KEY.
  68. * - After removing all versions created since Savepoint s1, stgTransLogBuf is truncated at the position that Savepoint s1 log exists.
  69. *
  70. * Design of "Concurrency control for updating transactions on the same KEY " :
  71. * - Other transactions that want to access the same KEY whose DATA is modified by another transaction need to rollback.
  72. * - After the rollback, they need to wait until the modifying transaction does commit or rollback.
  73. * - And then, they get the new viewVersion, start accessing the (key, data) pair again.
  74. * - If no transaction created a new version of the pair yet, a transaction can create one for it.
  75. * - CAS(Compare and Swap) operation is used for implementing the concurrency control
  76. * to check whether another transaction has created a new version.
  77. * - Applications need to be aware of this process.
  78. * - Application programmers need to write the code to begin the transaction again, modify the same set of tables and (key, value) pairs again.
  79. */
  80. #ifndef _KD_TABLE_H_
  81. #define _KD_TABLE_H_ (1)
  82. #include "kdInfra.h"
  83. #include "types.h"
  84. #include "transMgr.h"
  85. #include "transaction.h"
  86. #include "set.h"
  87. #include "data.h"
  88. #include "chunkList.h"
  89. /** @brief The table of DATA versions on each KEY pairs. This is the interface called by both normal processing and restart recovery.
  90. */
  91. class stgTable
  92. {
  93. private :
  94. set_t * set_;
  95. stgChunkList chunks_;
  96. public :
  97. stgTable()
  98. {
  99. }
  100. ~stgTable()
  101. {
  102. }
  103. /** @brief Initialize the table object with the given tableId.
  104. */
  105. KD_VOID initialize(int tableId)
  106. {
  107. KD_TRY
  108. {
  109. set_ = set_alloc();
  110. // TODO : Check if set allocation failed.
  111. }
  112. KD_CATCH
  113. KD_FINALLY
  114. KD_END
  115. }
  116. /** @brief Destroy the table object.
  117. */
  118. KD_VOID destroy()
  119. {
  120. KD_TRY
  121. {
  122. // TODO : Destroy set_ object.
  123. }
  124. KD_CATCH
  125. KD_FINALLY
  126. KD_END
  127. }
  128. /** @brief Find the data descriptor associated with the given key.
  129. * @param dataDesc *dataDesc is set to the found data descriptor. Set *dataDesc to NULL if the key is not found.
  130. */
  131. KD_VOID getDataDesc(const stgKey & key, stgDataDesc ** dataDesc ) const
  132. {
  133. KD_TRY
  134. {
  135. stgDataDesc * foundData;
  136. foundData = (stgDataDesc*) set_lookup(set_, key);
  137. *dataDesc = foundData;
  138. }
  139. KD_CATCH
  140. KD_FINALLY
  141. KD_END
  142. }
  143. /** @brief If the key exists, simply return the associated data descritor. Otherwise allocate a new data descriptor, associate it with the given key, put it into an access method.
  144. * @param dataDesc The data descriptor associated with the given key.
  145. */
  146. KD_VOID putDataDesc(const stgKey & key, stgDataDesc ** dataDesc )
  147. {
  148. KD_TRY
  149. {
  150. stgDataDesc * newDataDesc ;
  151. stgDataDesc * existingDataDesc ;
  152. // TODO : Allocated newDataDesc from the shared memory chunk.
  153. KD_ASSERT(0);
  154. // TODO : Need allocate memory for stgKey::key_, copy the key content. Need to think about where we can free the memory.
  155. KD_ASSERT(0);
  156. // TODO : Think about what to do when two transactions concurrently try to call this function.
  157. existingDataDesc = (stgDataDesc*) set_update( set_, key, newDataDesc, 0 /* overwrite */ );
  158. // If the key already exists, throw KD_EXCP_KEY_EXISTS.
  159. if ( existingDataDesc )
  160. {
  161. // TODO : Free newDataDesc from the shared memory chunk.
  162. KD_ASSERT(0);
  163. *dataDesc = existingDataDesc;
  164. }
  165. else
  166. {
  167. *dataDesc = newDataDesc;
  168. }
  169. }
  170. KD_CATCH
  171. KD_FINALLY
  172. KD_END
  173. }
  174. /** @brief Find the latest data version whose version is less than or equal to the given viewVersion.
  175. * @param viewVersion : The maximum version that the transaction can view. Set it to MAX_DATA_VERSION to see uncomitted changes.
  176. */
  177. KD_VOID seekData(const stgVersion viewVersion, stgDataDesc * dataDesc, stgData * data )
  178. {
  179. KD_TRY
  180. {
  181. stgDataVersion * dataVersion;
  182. KD_CALL( dataDesc->findLatestVersion( viewVersion, & dataVersion) );
  183. if ( dataVersion == NULL )
  184. // The key is found, but this transaction can't see it or it is marked as deleted.
  185. KD_THROW( KD_EXCP_KEY_NOT_FOUND );
  186. if ( dataVersion->deleted )
  187. // The latest data version is marked as deleted.
  188. KD_THROW( KD_EXCP_KEY_NOT_FOUND );
  189. // No data copy happens. Simply copy the data pointer and set the length.
  190. *data = stgData( dataVersion->data, dataVersion->dataLength );
  191. }
  192. KD_CATCH
  193. KD_FINALLY
  194. KD_END
  195. }
  196. /** @brief Update the data latest data version within the given data descriptor.
  197. * If the latest uncomitted data version matches the current savepoint ID in tx, in-place update the data.
  198. * Otherwise create a new data version, set savepoint ID of the new version to the current one of tx, copy the data into the new version.
  199. */
  200. KD_VOID updateData(const stgVersion viewVersion, const stgSavepointId spID, stgDataDesc * dataDesc, const stgData & data )
  201. {
  202. KD_TRY
  203. {
  204. // TODO : Continue to implement.
  205. KD_ASSERT(0);
  206. }
  207. KD_CATCH
  208. KD_FINALLY
  209. KD_END
  210. }
  211. /** @brief Set the deleted bit of the latest data version within the given data descriptor.
  212. * If the latest uncomitted data version matches the current savepoint ID in tx, set the deleted bit.
  213. * Otherwise create a new data version, set savepoint ID of the new version to the current one of tx, set the deleted bit.
  214. * @deletedBit : true if deleted, false otherwise.
  215. */
  216. KD_VOID setDeletedBit(const stgVersion viewVersion, const stgSavepointId spID, stgDataDesc * dataDesc, bool deletedBit )
  217. {
  218. KD_TRY
  219. {
  220. // TODO : Implement
  221. KD_ASSERT(0);
  222. }
  223. KD_CATCH
  224. KD_FINALLY
  225. KD_END
  226. }
  227. };
  228. #endif /* _KD_TABLE_MGR_H_ */