Mark a page in this BTreeFile as empty. Find the corresponding header page (create it if needed), and mark the corresponding slot in the header page as empty. @param tid - the transaction id @param dirtypages - the list of dirty pages which should be updated with all new dirty pages @param emptyPag
(TransactionId tid, Map<PageId, Page> dirtypages, int emptyPageNo)
| 1205 | * @throws TransactionAbortedException |
| 1206 | */ |
| 1207 | public void setEmptyPage(TransactionId tid, Map<PageId, Page> dirtypages, int emptyPageNo) |
| 1208 | throws DbException, IOException, TransactionAbortedException { |
| 1209 | |
| 1210 | // if this is the last page in the file (and not the only page), just |
| 1211 | // truncate the file |
| 1212 | // @TODO: Commented out because we should probably do this somewhere else in case the transaction aborts.... |
| 1213 | // synchronized(this) { |
| 1214 | // if(emptyPageNo == numPages()) { |
| 1215 | // if(emptyPageNo <= 1) { |
| 1216 | // // if this is the only page in the file, just return. |
| 1217 | // // It just means we have an empty root page |
| 1218 | // return; |
| 1219 | // } |
| 1220 | // long newSize = f.length() - BufferPool.getPageSize(); |
| 1221 | // FileOutputStream fos = new FileOutputStream(f, true); |
| 1222 | // FileChannel fc = fos.getChannel(); |
| 1223 | // fc.truncate(newSize); |
| 1224 | // fc.close(); |
| 1225 | // fos.close(); |
| 1226 | // return; |
| 1227 | // } |
| 1228 | // } |
| 1229 | |
| 1230 | // otherwise, get a read lock on the root pointer page and use it to locate |
| 1231 | // the first header page |
| 1232 | BTreeRootPtrPage rootPtr = getRootPtrPage(tid, dirtypages); |
| 1233 | BTreePageId headerId = rootPtr.getHeaderId(); |
| 1234 | BTreePageId prevId = null; |
| 1235 | int headerPageCount = 0; |
| 1236 | |
| 1237 | // if there are no header pages, create the first header page and update |
| 1238 | // the header pointer in the BTreeRootPtrPage |
| 1239 | if(headerId == null) { |
| 1240 | rootPtr = (BTreeRootPtrPage) getPage(tid, dirtypages, BTreeRootPtrPage.getId(tableid), Permissions.READ_WRITE); |
| 1241 | |
| 1242 | BTreeHeaderPage headerPage = (BTreeHeaderPage) getEmptyPage(tid, dirtypages, BTreePageId.HEADER); |
| 1243 | headerId = headerPage.getId(); |
| 1244 | headerPage.init(); |
| 1245 | rootPtr.setHeaderId(headerId); |
| 1246 | } |
| 1247 | |
| 1248 | // iterate through all the existing header pages to find the one containing the slot |
| 1249 | // corresponding to emptyPageNo |
| 1250 | while(headerId != null && (headerPageCount + 1) * BTreeHeaderPage.getNumSlots() < emptyPageNo) { |
| 1251 | BTreeHeaderPage headerPage = (BTreeHeaderPage) getPage(tid, dirtypages, headerId, Permissions.READ_ONLY); |
| 1252 | prevId = headerId; |
| 1253 | headerId = headerPage.getNextPageId(); |
| 1254 | headerPageCount++; |
| 1255 | } |
| 1256 | |
| 1257 | // at this point headerId should either be null or set with |
| 1258 | // the headerPage containing the slot corresponding to emptyPageNo. |
| 1259 | // Add header pages until we have one with a slot corresponding to emptyPageNo |
| 1260 | while((headerPageCount + 1) * BTreeHeaderPage.getNumSlots() < emptyPageNo) { |
| 1261 | BTreeHeaderPage prevPage = (BTreeHeaderPage) getPage(tid, dirtypages, prevId, Permissions.READ_WRITE); |
| 1262 | |
| 1263 | BTreeHeaderPage headerPage = (BTreeHeaderPage) getEmptyPage(tid, dirtypages, BTreePageId.HEADER); |
| 1264 | headerId = headerPage.getId(); |