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