1 /* Copyright (C) 2014 InfiniDB, Inc.
2
3 This program is free software; you can redistribute it and/or
4 modify it under the terms of the GNU General Public License
5 as published by the Free Software Foundation; version 2 of
6 the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
16 MA 02110-1301, USA. */
17
18 /* ========================================================================== */
19 /* */
20 /* we_indexlist.cpp */
21 /* (c) 2001 Author */
22 /* */
23 /* Description */
24 /* */
25 /* ========================================================================== */
26 #include <stdio.h>
27 #include <string.h>
28 #ifndef _MSC_VER
29 #include <inttypes.h>
30 #endif
31 #include "we_indexlist.h"
32 using namespace std;
33
34 namespace WriteEngine
35 {
36 /**
37 * Constructor
38 */
IndexList()39 IndexList::IndexList()
40 : m_oid((OID) INVALID_NUM), m_useNarray(true),
41 m_curLevel(INVALID_NUM), m_curBlkPos(0),
42 m_curLevelPos(INVALID_NUM)
43
44 {
45 m_freemgr.setDebugLevel(DEBUG_0);
46 init();
47 };
48 /****************************************************************
49 * DESCRIPTION:
50 * Public Function for adding a header
51 * (1) Given a key value and a row ID,
52 * (2) Return a pointer for insertion into the correct position
53 * in the Index Tree List Pointer group
54 * (3) A return code should indicate success or failur
55 * PARAMETERS:
56 * input
57 * pFile - File Handler
58 * rid - Input row ID
59 * key - Input key value
60 * output
61 * listHdrPtr - Output a pointer to the index list header
62 * RETURN:
63 * success - successfully created the index list header
64 * failure - it did not create the index list header
65 *
66 *******************************************************************/
addIndexListHdr(FILE * pFile,const RID & rowId,const uint64_t & key,IdxEmptyListEntry * newEmptyListPtr)67 const int IndexList::addIndexListHdr( FILE* pFile, const RID& rowId,
68 const uint64_t& key,
69 IdxEmptyListEntry* newEmptyListPtr)
70 {
71 int rc;
72 CommBlock cb;
73 m_pFile = pFile;
74 cb.file.oid = m_oid;
75 cb.file.pFile = m_pFile;
76 //Set up the header structure
77 //Initialize header blokcs
78 rc = resetBlk(&m_hdrBlock);
79 m_hdrLbid = INVALID_LBID;
80 m_hdrSbid = INVALID_NUM;
81 m_hdrEntry = INVALID_NUM;
82
83 //Initialize the new Index List header to null
84 memset( &m_curIdxRidListHdr, 0, LIST_HDR_SIZE );
85 //Assign the bit fields for the first entry in the Index List Header
86 m_curIdxRidListHdr.idxRidListSize.type = LIST_SIZE_TYPE;
87 m_curIdxRidListHdr.idxRidListSize.spare = 0x0;
88 m_curIdxRidListHdr.idxRidListSize.size = 1;
89 //Assign the bit fields for the second entry of the Index List Header
90 m_curIdxRidListHdr.key = key;
91 //Assign bit fields for the third entry of the Index List Header
92 m_curIdxRidListHdr.firstIdxRidListEntry.type = LIST_RID_TYPE;
93 m_curIdxRidListHdr.firstIdxRidListEntry.spare = 0x0;
94 m_curIdxRidListHdr.firstIdxRidListEntry.rid = rowId ;
95 //Assign bit fields for the fourth entry of the Index List Header
96 m_curIdxRidListHdr.nextIdxRidListPtr.type = LIST_NOT_USED_TYPE;
97 m_curIdxRidListHdr.nextIdxRidListPtr.spare = 0x0;
98 m_curIdxRidListHdr.nextIdxRidListPtr.llp = 0x0;
99 /* Get assigned space for the header from free manager
100 * Get the new block for the new idx list header
101 * The header needs LIST_HDR_SIZE bytes
102 */
103 rc = getSegment(pFile, ENTRY_4, newEmptyListPtr);
104
105 if (rc != NO_ERROR)
106 return rc;
107
108 m_hdrLbid = newEmptyListPtr->fbo;
109 m_hdrSbid = newEmptyListPtr->sbid;
110 m_hdrEntry = newEmptyListPtr->entry;
111
112 //Write Index List Header to the file block
113 //Write LIST_HDR_SIZE bytes in one time.
114
115 rc = readDBFile( cb, m_hdrBlock.data, m_hdrLbid );
116 rc = writeSubBlockEntry( cb, &m_hdrBlock, m_hdrLbid, m_hdrSbid,
117 m_hdrEntry, LIST_HDR_SIZE, &m_curIdxRidListHdr );
118
119 if (rc != NO_ERROR)
120 {
121 return rc;
122 }
123
124 //Wrote Header Block Out already, Start Over next time
125 //Update the flags to indicate there is data on the header block
126 m_hdrBlock.dirty = true;
127 m_hdrBlock.lbid = m_hdrLbid;
128 m_hdrBlock.state = BLK_READ;
129 m_lastLbid = INVALID_LBID;
130 //DONE
131 return rc;
132 };
133 /****************************************************************
134 * DESCRIPTION:
135 *
136 *
137 * RETURN:
138 * success - successfully created the index list header
139 * failure - it did not create the index list header
140 ***********************************************************/
updateIndexList(FILE * pFile,const RID & newRid,const uint64_t & key,IdxEmptyListEntry * curIdxRidListHdrPtr)141 const int IndexList::updateIndexList(FILE* pFile, const RID& newRid,
142 const uint64_t& key,
143 IdxEmptyListEntry* curIdxRidListHdrPtr)
144 {
145 int rc;
146 m_pFile = pFile;
147
148 //Initialization
149 if ( (key != m_curIdxRidListHdr.key) || (m_hdrBlock.state == BLK_INIT))
150 {
151 rc = initGetHdr(key, curIdxRidListHdrPtr);
152
153 if (key != m_curIdxRidListHdr.key)
154 return ERR_IDX_LIST_INVALID_KEY;
155 }
156
157 rc = updateIndexList(newRid, key);
158
159 if (rc != NO_ERROR)
160 {
161 return rc;
162 }
163
164 //Write everything out
165 rc = updateIndexListWrite();
166 return rc;
167 };
168 /****************************************************************
169 * DESCRIPTION:
170 * (0) THIS FUNCIION CAN ONLY BE CALLED WITH THE PUBLIC
171 *
172 * RETURN:
173 * success - successfully created the index list header
174 * failure - it did not create the index list header
175 ***********************************************************/
updateIndexList(const RID & newRid,const uint64_t & key)176 const int IndexList::updateIndexList(const RID& newRid, const uint64_t& key)
177 {
178 int rc = NO_ERROR;
179
180 //m_lastLbid==0 or not determines if we can skip from the header,the first
181 //subblock or go to the last inserted block
182 if (m_lastLbid == (uint64_t)INVALID_LBID)
183 {
184 rc = updateHdrSub(newRid, key);
185 }
186 else // get the lastLbid info from header
187 {
188 //m_lastLbid > 0, space is in some block now
189 m_lbid = m_lastLbid;
190 m_sbid = 0;
191 m_entry = 0;
192 m_segType = LIST_BLOCK_TYPE;
193 m_curType = LIST_BLOCK_TYPE;
194 rc = addRidInBlk(newRid);
195 }
196
197 return rc;
198 };
199
200 /************************************************
201 * Description:
202 * Find a entry for the given rowId and Key
203 * Then Delete it from the list
204 * Move the rest of the row id up in the same
205 * sub block an decrement the count in that subblock
206 * decrement the header size
207 * Converted
208 * input
209 * pFile -- File Handler
210 * rowId -- row id
211 * key -- value
212 * curIdxRidListHdrPtr - point to the header
213 *
214 * return value
215 * Success -- 0
216 * Fail -- ERR_IDX_LIST_INVALID_DELETE
217 ************************************************/
deleteIndexList(FILE * pFile,const RID & rowId,const uint64_t & key,IdxEmptyListEntry * curIdxRidListHdrPtr)218 const int IndexList::deleteIndexList( FILE* pFile, const RID& rowId,
219 const uint64_t& key, IdxEmptyListEntry* curIdxRidListHdrPtr)
220 {
221 int rc = ERR_IDX_LIST_INVALID_DELETE;
222 m_pFile = pFile;
223
224 getHdrInfo(curIdxRidListHdrPtr);
225
226 if (key != m_curIdxRidListHdr.key)
227 {
228 memset( m_hdrBlock.data, 0, sizeof(m_hdrBlock.data));
229 m_hdrBlock.dirty = false;
230 m_hdrBlock.state = BLK_INIT;
231 return ERR_IDX_LIST_INVALID_KEY;
232 }
233
234 rc = deleteIndexList(rowId, key);
235 return rc;
236 }
237
238 /************************************************
239 * Description:
240 * Converted - keep the first sub block
241 * Find a entry for the given rowId and Key
242 * Then Delete it from the list
243 * Move the rest of the row id up in the same
244 * sub block an decrement the count in that subblock
245 * decrement the header size
246 * input
247 * pFile -- File Handler
248 * rowId -- row id
249 * key -- value
250 * curIdxRidListHdrPtr - point to the header
251 *
252 * return value
253 * Success -- 0
254 * Fail -- ERR_IDX_LIST_INVALID_DELETE
255 ************************************************/
deleteIndexList(const RID & rowId,const uint64_t & key)256 const int IndexList::deleteIndexList( const RID& rowId, const uint64_t& key)
257 {
258 int rc = ERR_IDX_LIST_INVALID_DELETE;
259 RID savedRid ;
260 DataBlock prevDataBlock;
261
262 CommBlock cb;
263 cb.file.oid = m_oid;
264 cb.file.pFile = m_pFile;
265
266 //Check the first row location, 3rd entry
267 //Because it may be deleted from the delete action
268 //The header size cannot tell us the rowid size on header
269 if (m_curIdxRidListHdr.firstIdxRidListEntry.type
270 == (int)LIST_RID_TYPE)
271 {
272 if (m_curIdxRidListHdr.firstIdxRidListEntry.rid
273 == rowId)
274 {
275 m_curIdxRidListHdr.firstIdxRidListEntry.type
276 = LIST_NOT_USED_TYPE; //not used type
277 m_curIdxRidListHdr.firstIdxRidListEntry.rid = 0;
278 m_curIdxRidListHdr.idxRidListSize.size--;
279 rc = writeSubBlockEntry(cb, &m_hdrBlock, m_hdrLbid,
280 m_hdrSbid, m_hdrEntry,
281 LIST_HDR_SIZE,
282 &m_curIdxRidListHdr );
283 memset(m_hdrBlock.data, 0, sizeof(m_hdrBlock.data));
284 m_hdrBlock.dirty = false;
285 m_dLbid = m_hdrLbid;
286 m_dSbid = m_hdrSbid;
287 m_dEntry = m_hdrEntry + 2;
288
289 return rc;
290 }
291 };
292
293 //Check Header last entry's type
294 int type = m_curIdxRidListHdr.nextIdxRidListPtr.type;
295
296 switch (type)
297 {
298 case LIST_NOT_USED_TYPE://Header is not full, no sub-block linked
299 //No RowId here
300 memset(m_hdrBlock.data, 0, sizeof(m_hdrBlock.data));
301 m_hdrBlock.dirty = false;
302 m_dLbid = -1LL;
303 m_dSbid = -1;
304 m_dEntry = -1;
305 return ERR_IDX_LIST_INVALID_DELETE; //not found, failed
306
307 case LIST_RID_TYPE:// There is a row id here, Check!
308 savedRid = m_curIdxRidListHdr.nextIdxRidListPtr.llp;
309
310 if (savedRid == rowId)
311 {
312 m_curIdxRidListHdr.nextIdxRidListPtr.type
313 = LIST_NOT_USED_TYPE;
314 m_curIdxRidListHdr.nextIdxRidListPtr.llp = 0;
315 m_curIdxRidListHdr.idxRidListSize.size--;
316 rc = writeSubBlockEntry(cb, &m_hdrBlock, m_hdrLbid,
317 m_hdrSbid, m_hdrEntry,
318 LIST_HDR_SIZE,
319 &m_curIdxRidListHdr );
320 m_hdrBlock.dirty = false;
321 memset(m_hdrBlock.data, 0, sizeof(m_hdrBlock.data));
322 m_dLbid = m_hdrLbid;
323 m_dSbid = m_hdrSbid;
324 m_dEntry = 3;
325
326 return rc;
327 }
328 else
329 {
330 m_hdrBlock.dirty = false;
331 memset(m_hdrBlock.data, 0, sizeof(m_hdrBlock.data));
332 m_dLbid = -1LL;
333 m_dSbid = -1;
334 m_dEntry = -1;
335 return ERR_IDX_LIST_INVALID_DELETE;
336 }
337
338 case LIST_SUBBLOCK_TYPE://Not found in header,
339 rc = deleteInSub(rowId);
340
341 if (rc == NO_ERROR)
342 return rc;
343
344 rc = deleteInBlock(rowId);
345 return rc;
346 break;
347
348 default:
349 break;
350 };//end of switch
351
352 return ERR_IDX_LIST_INVALID_DELETE;
353 }
354 }
355