1717#undef LOG_TAG
1818#define LOG_TAG " CursorWindow"
1919
20- // #include <utils/Log.h>
21- // #include <binder/MemoryHeapBase.h>
22- // #include <binder/MemoryBase.h>
23-
2420#include < assert.h>
2521#include < string.h>
2622#include < stdlib.h>
2723#include < stdint.h>
28-
2924#include < jni.h>
30- // #include <JNIHelp.h>
31-
3225#include " CursorWindow.h"
3326
3427namespace sqlcipher {
@@ -73,6 +66,8 @@ void CursorWindow::clear()
7366 mFreeOffset = sizeof (window_header_t ) + ROW_SLOT_CHUNK_SIZE;
7467 // Mark the first chunk's next 'pointer' as null
7568 *((uint32_t *)(mData + mFreeOffset - sizeof (uint32_t ))) = 0 ;
69+ mChunkNumToNextChunkOffset .clear ();
70+ mLastChunkPtrOffset = 0 ;
7671}
7772
7873int32_t CursorWindow::freeSpace ()
@@ -110,7 +105,7 @@ field_slot_t * CursorWindow::allocRow()
110105 // If the last alloc relocated mData this will be rowSlot's new address, otherwise the value will not change
111106 rowSlot = (row_slot_t *)(mData + rowSlotOffset);
112107
113- LOG_WINDOW (" Allocated row %u, rowSlot is at offset %u, fieldDir is %d bytes at offset %u\n " , (mHeader ->numRows - 1 ), ((uint8_t *)rowSlot) - mData , fieldDirSize, fieldDirOffset);
108+ LOG_WINDOW (" Allocated row %u, rowSlot is at offset %u, fieldDir is %d bytes at offset %u\n " , (mHeader ->numRows - 1 ), ((uint8_t *)rowSlot) - mData , fieldDirSize, fieldDirOffset);
114109 rowSlot->offset = fieldDirOffset;
115110
116111 return fieldDir;
@@ -150,11 +145,23 @@ uint32_t CursorWindow::alloc(size_t requestedSize, bool aligned)
150145
151146row_slot_t * CursorWindow::getRowSlot (int row)
152147{
153- LOG_WINDOW (" enter getRowSlot current row num %d, this row %d" , mHeader ->numRows , row);
148+ LOG_WINDOW (" getRowSlot entered: requesting row:%d, current row num:%d" , row, mHeader ->numRows );
149+ unordered_map<int , uint32_t >::iterator result;
154150 int chunkNum = row / ROW_SLOT_CHUNK_NUM_ROWS;
155151 int chunkPos = row % ROW_SLOT_CHUNK_NUM_ROWS;
156152 int chunkPtrOffset = sizeof (window_header_t ) + ROW_SLOT_CHUNK_SIZE - sizeof (uint32_t );
157153 uint8_t * rowChunk = mData + sizeof (window_header_t );
154+
155+ // check for chunkNum in cache
156+ result = mChunkNumToNextChunkOffset .find (chunkNum);
157+ if (result != mChunkNumToNextChunkOffset .end ()){
158+ rowChunk = offsetToPtr (result->second );
159+ LOG_WINDOW (" Retrieved chunk offset from cache for row:%d" , row);
160+ return (row_slot_t *)(rowChunk + (chunkPos * sizeof (row_slot_t )));
161+ }
162+
163+ // walk the list, this shouldn't occur
164+ LOG_WINDOW (" getRowSlot walking list %d times to find rowslot for row:%d" , chunkNum, row);
158165 for (int i = 0 ; i < chunkNum; i++) {
159166 rowChunk = offsetToPtr (*((uint32_t *)(mData + chunkPtrOffset)));
160167 chunkPtrOffset = rowChunk - mData + (ROW_SLOT_CHUNK_NUM_ROWS * sizeof (row_slot_t ));
@@ -169,34 +176,45 @@ row_slot_t * CursorWindow::allocRowSlot()
169176 int chunkPos = mHeader ->numRows % ROW_SLOT_CHUNK_NUM_ROWS;
170177 int chunkPtrOffset = sizeof (window_header_t ) + ROW_SLOT_CHUNK_SIZE - sizeof (uint32_t );
171178 uint8_t * rowChunk = mData + sizeof (window_header_t );
172- LOG_WINDOW (" Allocating row slot, mHeader->numRows is %d, chunkNum is %d, chunkPos is %d" , mHeader ->numRows , chunkNum, chunkPos);
173- for (int i = 0 ; i < chunkNum; i++) {
179+ LOG_WINDOW (" allocRowSlot entered: Allocating row slot, mHeader->numRows is %d, chunkNum is %d, chunkPos is %d" ,
180+ mHeader ->numRows , chunkNum, chunkPos);
181+
182+ if (mLastChunkPtrOffset != 0 ){
183+ chunkPtrOffset = mLastChunkPtrOffset ;
184+ }
185+ if (chunkNum > 0 ) {
174186 uint32_t nextChunkOffset = *((uint32_t *)(mData + chunkPtrOffset));
175- LOG_WINDOW (" nextChunkOffset is %d" , nextChunkOffset);
187+ LOG_WINDOW (" nextChunkOffset is %d" , nextChunkOffset);
176188 if (nextChunkOffset == 0 ) {
189+ mLastChunkPtrOffset = chunkPtrOffset;
177190 // Allocate a new row chunk
178191 nextChunkOffset = alloc (ROW_SLOT_CHUNK_SIZE, true );
192+ mChunkNumToNextChunkOffset .insert (make_pair (chunkNum, nextChunkOffset));
179193 if (nextChunkOffset == 0 ) {
180194 return NULL ;
181195 }
182196 rowChunk = offsetToPtr (nextChunkOffset);
183- LOG_WINDOW (" allocated new chunk at %d, rowChunk = %p" , nextChunkOffset, rowChunk);
197+ LOG_WINDOW (" allocated new chunk at %d, rowChunk = %p" , nextChunkOffset, rowChunk);
184198 *((uint32_t *)(mData + chunkPtrOffset)) = rowChunk - mData ;
185199 // Mark the new chunk's next 'pointer' as null
186200 *((uint32_t *)(rowChunk + ROW_SLOT_CHUNK_SIZE - sizeof (uint32_t ))) = 0 ;
187201 } else {
188- LOG_WINDOW (" follwing 'pointer' to next chunk, offset of next pointer is %d" , chunkPtrOffset);
202+ LOG_WINDOW (" follwing 'pointer' to next chunk, offset of next pointer is %d" , chunkPtrOffset);
189203 rowChunk = offsetToPtr (nextChunkOffset);
190204 chunkPtrOffset = rowChunk - mData + (ROW_SLOT_CHUNK_NUM_ROWS * sizeof (row_slot_t ));
205+ if (chunkPos == ROW_SLOT_CHUNK_NUM_ROWS - 1 ){
206+ // prepare to allocate new rowslot_t now at end of row
207+ mLastChunkPtrOffset = chunkPtrOffset;
208+ }
191209 }
192210 }
193211 mHeader ->numRows ++;
194-
195212 return (row_slot_t *)(rowChunk + (chunkPos * sizeof (row_slot_t )));
196213}
197214
198215field_slot_t * CursorWindow::getFieldSlotWithCheck (int row, int column)
199216{
217+ LOG_WINDOW (" getFieldSlotWithCheck entered: row:%d column:%d" , row, column);
200218 if (row < 0 || row >= mHeader ->numRows || column < 0 || column >= mHeader ->numColumns ) {
201219 LOGE (" Bad request for field slot %d,%d. numRows = %d, numColumns = %d" , row, column, mHeader ->numRows , mHeader ->numColumns );
202220 return NULL ;
@@ -216,6 +234,7 @@ field_slot_t * CursorWindow::getFieldSlotWithCheck(int row, int column)
216234
217235uint32_t CursorWindow::read_field_slot (int row, int column, field_slot_t * slotOut)
218236{
237+ LOG_WINDOW (" read_field_slot entered: row:%d, column:%d, slotOut:%p" , row, column, slotOut);
219238 if (row < 0 || row >= mHeader ->numRows || column < 0 || column >= mHeader ->numColumns ) {
220239 LOGE (" Bad request for field slot %d,%d. numRows = %d, numColumns = %d" , row, column, mHeader ->numRows , mHeader ->numColumns );
221240 return -1 ;
@@ -229,9 +248,9 @@ uint32_t CursorWindow::read_field_slot(int row, int column, field_slot_t * slotO
229248 LOGE (" Invalid rowSlot, offset = %d" , rowSlot->offset );
230249 return -1 ;
231250 }
232- LOG_WINDOW (" Found field directory for %d,%d at rowSlot %d, offset %d" , row, column, (uint8_t *)rowSlot - mData , rowSlot->offset );
251+ LOG_WINDOW (" Found field directory for %d,%d at rowSlot %d, offset %d" , row, column, (uint8_t *)rowSlot - mData , rowSlot->offset );
233252 field_slot_t * fieldDir = (field_slot_t *)offsetToPtr (rowSlot->offset );
234- LOG_WINDOW (" Read field_slot_t %d,%d: offset = %d, size = %d, type = %d" , row, column, fieldDir[column].data .buffer .offset , fieldDir[column].data .buffer .size , fieldDir[column].type );
253+ LOG_WINDOW (" Read field_slot_t %d,%d: offset = %d, size = %d, type = %d" , row, column, fieldDir[column].data .buffer .offset , fieldDir[column].data .buffer .size , fieldDir[column].type );
235254
236255 // Copy the data to the out param
237256 slotOut->data .buffer .offset = fieldDir[column].data .buffer .offset ;
0 commit comments