t_rc INXM_IndexHandle::CreateLastDataPage(STORM_PageHandle &pageHandle) { t_rc rc; int pageID; rc = this->sfh.ReservePage(pageHandle); if (rc != OK) { return rc; } rc = pageHandle.GetPageID(pageID); if (rc != OK) { return rc; } char *pageData; rc = pageHandle.GetDataPtr(&pageData); if (rc != OK) { return rc; } /* Write index init page header */ INXM_InitPageHeader pageHeader = { 1, 0 }; memcpy(pageData, &pageHeader, INXM_INITPAGEHEADER_SIZE); /* Update file header (new lastDataPage). */ this->inxmFileHeader.lastDataPage = pageID; memcpy(this->pData_FileHeader, &this->inxmFileHeader, INXM_FILEHEADER_SIZE); rc = this->sfh.FlushPage(this->pageNum_FileHeader); if (rc != OK) { return rc; } return(OK); }
t_rc INXM_IndexHandle::CreateNodePage(STORM_PageHandle &pageHandle, int &pageID, int parent, int next, int previous, bool isLeaf) { t_rc rc; rc = this->sfh.ReservePage(pageHandle); if (rc != OK) { return rc; } rc = pageHandle.GetPageID(pageID); if (rc != OK) { return rc; } char *pageData; rc = pageHandle.GetDataPtr(&pageData); if (rc != OK) { return rc; } /* Write index init page header */ INXM_InitPageHeader pageHeader = { 0, 0 }; memcpy(pageData, &pageHeader, INXM_INITPAGEHEADER_SIZE); /* Write index node page header */ INXM_NodePageHeader nPageHeader = { isLeaf, parent, next, previous }; memcpy(&pageData[INXM_INITPAGEHEADER_SIZE], &nPageHeader, INXM_NODEPAGEHEADER_SIZE); return(OK); }
/* We have a const problem with the method. We call GetPage from STORM which is not const!!! */ t_rc REM_RecordFileHandle::ReadRecord(const REM_RecordID &rid, REM_RecordHandle &rh) { /* Check is file is open. */ if (!this->isOpen) { return REM_FHCLOSED; } t_rc rc; /* Get pageID and slot number to find the record. */ int pageID, slot; rc = rid.GetPageID(pageID); if (rc != OK) { return rc; } rc = rid.GetSlot(slot); if (rc != OK) { return rc; } /* Get the STORM page that contains the record we need. */ STORM_PageHandle pageHandle; rc = this->sfh.GetPage(pageID, pageHandle); if (rc != OK) { return rc; } /* Check if REM Record Handler has data. If it doesn't, allocate the needed space. */ if (rh.pData == NULL) { rh.pData = new char[this->remFileHeader.recordSize]; } else { delete rh.pData; rh.pData = new char[this->remFileHeader.recordSize]; } char *pData; REM_PageHeader pageHeader; pageHandle.GetDataPtr(&pData); /* Check if slot number is not correct. */ memcpy(&pageHeader, pData, REM_PAGEHEADER_SIZE); if (slot > pageHeader.nRecords) { return REM_INVALIDRID; } /* Find the record we want and copy the data to the record handler. */ memcpy(rh.pData, &pData[REM_PAGEHEADER_SIZE+((slot-1)*this->remFileHeader.recordSize)], this->remFileHeader.recordSize); /* Add the recordID to the record handler. */ rh.rid = rid; /* Make Record Handler valid. */ rh.isValid = true; return (OK); }
t_rc REM_RecordFileHandle::UpdateRecord(const REM_RecordHandle &rh) { /* Check is file is open. */ if (!this->isOpen) { return REM_FHCLOSED; } t_rc rc; /* Exctract RID and get pageID and slot numbers. */ REM_RecordID rid; int pageID, slot; rc = rh.GetRecordID(rid); if (rc != OK) { return rc; } rc = rid.GetPageID(pageID); if (rc != OK) { return rc; } rc = rid.GetSlot(slot); if (rc != OK) { return rc; } /* Get the record and a pointer to the data inside. */ STORM_PageHandle pageHandle; char *pData; rc = this->sfh.GetPage(pageID, pageHandle); if (rc != OK) { return rc; } rc = pageHandle.GetDataPtr(&pData); if (rc != OK) { return rc; } /* Copy the new data. */ memcpy(&pData[REM_PAGEHEADER_SIZE+((slot-1)*this->remFileHeader.recordSize)], rh.pData, this->remFileHeader.recordSize); /* Mark the page as dirty because we modified it */ rc = this->sfh.MarkPageDirty(pageID); if (rc != OK) { return rc; } /* Unpin the page */ rc = this->sfh.UnpinPage(pageID); if (rc != OK) { return rc; } return (OK); }
// Δημιουργία νέου κόμβου/ρίζα t_rc INXM_IndexHandle::makeRoot(void *pData, const REM_RecordID &rid){ t_rc rc; int pageID; STORM_PageHandle myPageHandle; // Δέσμευση σελίδας rc = this->fh.ReservePage(myPageHandle); if (rc != OK) return rc; rc = this->fh.GetNextPage(this->fileHeaderPageID, myPageHandle); if (rc != OK) return rc; rc = myPageHandle.GetPageID(pageID); if (rc != OK) { return rc; } char* rData; rc = myPageHandle.GetDataPtr(&rData); if (rc != OK) { return rc; } this->fileHeader.rootPage = pageID; // Δημιουργία header για τη σελίδα // Κάθε σελίδα είναι και node NodeHeader nh; nh.numberOfItems = 1; for (int i = 0; i < 1200; i++) nh.sStatus.set(i,false); nh.sStatus.set(0, true); nh.left = -1; nh.right = -1; nh.parent = -1; nh.leaf = true; LeafItem item = { pData, rid }; // Εγγραφή του αντικειμένου memcpy(&rData[sizeof(NodeHeader)], this->getLeafItemData(item), this->getLeafItemSize()); this->fileHeader.numberOfNodes++; this->fileHeader.numberOfLeafNodes++; // Εγγραφή του nodeheader memcpy(&rData[0], &nh, sizeof(NodeHeader)); rc = this->fh.MarkPageDirty(pageID); if (rc != OK) return rc; rc = this->fh.FlushPage(pageID); if (rc != OK) return rc; rc = this->fh.UnpinPage(pageID); if (rc != OK) return rc; return(OK); }
t_rc INXM_IndexHandle::InsertEntry(void *pData, const REM_RecordID &rid){ t_rc rc; STORM_PageHandle pageHandle; /* * Έλεγχος αν υπάρχει δέντρο * Δημιουργία νέου δέντρου/ρίζας */ if( this->isOpen && this->fileHeader.numberOfNodes == 0 ){ makeRoot(pData, rid); return(OK); } /* * Υπάρχει ήδη δέντρο */ // Αναζήτηση για την εύρεση της ΣΩΣΤΗΣ σελίδας/φύλλου όπου θα μπεί ή νέα εγγραφή int rightPageID = searchRightPage( fileHeader.rootPage , pData); // Διαβάζω τον header αυτής της σελίδας char* data; rc = fh.GetPage(rightPageID, pageHandle); if (rc != OK) return rc; rc = pageHandle.GetDataPtr(&data); if (rc != OK) return rc; NodeHeader rightPageHeader; memcpy(&rightPageHeader, &data[0], sizeof(NodeHeader)); // Έλεγχος αν η σελίδα έχει χώρο bool freeSpace = checkLeafNodeForSpace(rightPageHeader); if(freeSpace){ // περίπτωση που η σελίδα έχει χώρο insert(rightPageID, pData, rid); return (OK); } else { // περίπτωση που η σελίδα ΔΕΝ έχει χώρο rc = splitLeafNode(rightPageID); if (rc != OK) return rc; int pageAfterSplitID = searchRightPage( fileHeader.rootPage , pData); insert(pageAfterSplitID, pData, rid); return (OK); } }
//----------------------------------------------------------------------------------------------- // GetPage // // Updates the page handle with the page with the given pageID //----------------------------------------------------------------------------------------------- t_rc STORM_FileHandle::GetPage(int pageID, STORM_PageHandle &pageHandle) { STORM_Frame *pFrame; t_rc rc; if (!m_isOpened) return (STORM_FILENOTOPENED); // Check if page is not valid. if (pageID < 1) return (STORM_INVALIDPAGE); if (pageID > m_fileSubHeader.numAllocatedPages) return (STORM_INVALIDPAGE); if (!IsPageReserved(pageID)) return (STORM_INVALIDPAGE); rc = m_pBfrMgr->NeedPage(m_fileID, pageID, &pFrame); if (rc != OK) return (rc); rc = pageHandle.Open(pFrame); m_filePos = pageID; return (rc); }
//----------------------------------------------------------------------------------------------- // ReservePage // // Reserves a new page for the file. //----------------------------------------------------------------------------------------------- t_rc STORM_FileHandle::ReservePage(STORM_PageHandle &pageHandle) { if (!m_isOpened) return (STORM_FILENOTOPENED); t_rc rc; int newPageID = INVALID_PAGEID; for (int pageCounter=1; pageCounter<=MAX_PAGES_PER_FILE; pageCounter++) { if (!IsPageReserved(pageCounter)) { newPageID = pageCounter; break; } } STORM_Frame *pFrame; if (newPageID == INVALID_PAGEID) // all pages are reserved { if (m_fileSubHeader.numAllocatedPages == MAX_PAGES_PER_FILE) return STORM_FILELIMITREACHED; // Reserve frame in buffer. rc = m_pBfrMgr->ReserveFrame(m_fileID, newPageID, &pFrame); if (rc != OK) return (rc); m_fileSubHeader.numAllocatedPages++; m_fileSubHeader.numReservedPages++; UpdateHeaderFrame(); rc = m_pBfrMgr->WritePage(pFrame); if (rc != OK) return (rc); } else // a free page has been found { // Reserve frame in buffer. rc = m_pBfrMgr->ReserveFrame(m_fileID, newPageID, &pFrame); if (rc != OK) return (rc); m_fileSubHeader.numReservedPages++; UpdateHeaderFrame(); if (newPageID > m_fileSubHeader.numAllocatedPages) { rc = m_pBfrMgr->WritePage(pFrame); if (rc != OK) return (rc); m_fileSubHeader.numAllocatedPages++; UpdateHeaderFrame(); } } SetPageReservationFlag(newPageID, true); // page is reserved now rc = pageHandle.Open(pFrame); if (rc != OK) return (rc); return (OK); }
t_rc INXM_IndexHandle::WriteData(STORM_PageHandle pageHandle, const REM_RecordID &rid, int &slot) { t_rc rc; INXM_Data *inxmData = new INXM_Data(); rid.GetPageID(inxmData->pageID); rid.GetSlot(inxmData->slot); char *leafPageData; rc = pageHandle.GetDataPtr(&leafPageData); if (rc != OK) { return rc; } /* Read leaf header. */ INXM_InitPageHeader pageHeader; memcpy(&pageHeader, leafPageData, INXM_INITPAGEHEADER_SIZE); /* Write data to correct place. */ memcpy(&leafPageData[INXM_INITPAGEHEADER_SIZE+pageHeader.nItems*INXM_DATA_SIZE], inxmData, INXM_DATA_SIZE); /* Update page header. */ slot = pageHeader.nItems; pageHeader.nItems++; memcpy(leafPageData, &pageHeader, INXM_INITPAGEHEADER_SIZE); int pageID; rc = pageHandle.GetPageID(pageID); if (rc != OK) { return rc; } /* Mark the page as dirty because we modified it */ rc = this->sfh.MarkPageDirty(pageID); if (rc != OK) { return rc; } rc = this->sfh.FlushPage(pageID); if (rc != OK) { return rc; } /* Unpin the page */ rc = this->sfh.UnpinPage (pageID); if (rc != OK) { return rc; } return(OK); }
t_rc INXM_IndexHandle::WriteNode(STORM_PageHandle pageHandle, int insertPoint, void *key, int left, int slot) { t_rc rc; INXM_Node *node = new INXM_Node(); node->left = left; node->slot = slot; char *nodePageData; rc = pageHandle.GetDataPtr(&nodePageData); if (rc != OK) { return rc; } /* Write data to correct place. */ memcpy(&nodePageData[INXM_INITPAGEHEADER_SIZE+INXM_NODEPAGEHEADER_SIZE+insertPoint*(INXM_NODE_SIZE+this->inxmFileHeader.attrLength)], node, INXM_NODE_SIZE); memcpy(&nodePageData[INXM_INITPAGEHEADER_SIZE+INXM_NODEPAGEHEADER_SIZE+insertPoint*(INXM_NODE_SIZE+this->inxmFileHeader.attrLength)+INXM_NODE_SIZE], key, this->inxmFileHeader.attrLength); /* Update page header. */ INXM_InitPageHeader pageHeader; rc = LoadInitHeaders(pageHandle, pageHeader); if (rc != OK) { return rc; } pageHeader.nItems++; memcpy(nodePageData, &pageHeader, INXM_INITPAGEHEADER_SIZE); int pageID; rc = pageHandle.GetPageID(pageID); if (rc != OK) { return rc; } /* Mark the page as dirty because we modified it */ rc = this->sfh.MarkPageDirty(pageID); if (rc != OK) { return rc; } rc = this->sfh.FlushPage(pageID); if (rc != OK) { return rc; } /* Unpin the page */ rc = this->sfh.UnpinPage (pageID); if (rc != OK) { return rc; } return(OK); }
// Επιστρέφει το id της σελίδας που θα πρέπει να γίνει η // εισαγωγή του νέου στοιχείου int INXM_IndexHandle::searchRightPage(int pageID, void* key){ STORM_PageHandle pageHandle; char* data; // Διαβάζουμε τον header της σελίδας fh.GetPage(pageID, pageHandle); pageHandle.GetDataPtr(&data); NodeHeader currentHeader; memcpy(¤tHeader, &data[0], sizeof(NodeHeader)); if( currentHeader.leaf == true ){ // ο κόμβος που μόλις διάβασα είναι φύλλο, τελειώνει η αναζήτηση return pageID; } else { // ο κόμβος που μόλις διάβασα είναι ενδιάμεσος, ελέγχω τις τιμές for(int i = 0; i < currentHeader.numberOfItems; i++){ InterItem currentItem, nextItem; char* currentData = new char[this->getInterItemSize()]; memcpy(currentData, &data[sizeof(NodeHeader)+i*this->getInterItemSize()], this->getInterItemSize()); currentItem = this->getInterItemStruct(currentData); memcpy(currentData, &data[sizeof(NodeHeader)+(i+1)*this->getInterItemSize()], this->getInterItemSize()); nextItem = this->getInterItemStruct(currentData); if(keyCompare(key, currentItem.key) < 0 ){ // akoloutha aristero paidi searchRightPage(currentItem.leftChild, key); } else if ( (keyCompare(key, currentItem.key) > 0) && ((keyCompare(key, nextItem.key) == 0) || (keyCompare(key, nextItem.key) < 0))) { // akoloutha aristero paidi searchRightPage(nextItem.leftChild, key); } else if ((keyCompare(key, currentItem.key) > 0) || (keyCompare(key, currentItem.key) == 0)){ //akoloutha deksi paidi searchRightPage(currentItem.leftChild, key); } } } }
t_rc INXM_IndexHandle::EditNode(STORM_PageHandle pageHandle, int slot, INXM_Node node) { t_rc rc; char *dataPageData; rc = pageHandle.GetDataPtr(&dataPageData); if (rc != OK) { return rc; } memcpy(&dataPageData[INXM_INITPAGEHEADER_SIZE+INXM_NODEPAGEHEADER_SIZE+(slot*(INXM_NODE_SIZE+this->inxmFileHeader.attrLength))], &node, INXM_NODE_SIZE+this->inxmFileHeader.attrLength); return(OK); }
t_rc INXM_IndexHandle::EditData(STORM_PageHandle pageHandle, int slot, INXM_Data data) { t_rc rc; char *dataPageData; rc = pageHandle.GetDataPtr(&dataPageData); if (rc != OK) { return rc; } memcpy(&dataPageData[INXM_INITPAGEHEADER_SIZE+(slot*INXM_DATA_SIZE)], &data, INXM_DATA_SIZE); return(OK); }
t_rc INXM_IndexHandle::LoadInitHeaders(STORM_PageHandle pageHandle, INXM_InitPageHeader &initPageHeader) { t_rc rc; /* Read headers. */ char *nodePage; rc = pageHandle.GetDataPtr(&nodePage); if (rc != OK) { return rc; } /* init page header. */ memcpy(&initPageHeader, nodePage, INXM_INITPAGEHEADER_SIZE); return(OK); }
t_rc INXM_IndexHandle::ReadData(STORM_PageHandle pageHandle, int slot, INXM_Data &data) { t_rc rc; /* Read headers. */ char *dataPage; rc = pageHandle.GetDataPtr(&dataPage); if (rc != OK) { return rc; } /* Read data. */ memcpy(&data, &dataPage[INXM_INITPAGEHEADER_SIZE+slot*INXM_DATA_SIZE], INXM_DATA_SIZE); return(OK); }
t_rc INXM_IndexHandle::InsertIntoLeaf(STORM_PageHandle leafPageHandle, void *key, const REM_RecordID &rid) { t_rc rc; /* Find correct point for the new key. */ INXM_InitPageHeader initPageHeader; LoadInitHeaders(leafPageHandle, initPageHeader); INXM_Node node; int insertPoint = 0; rc = ReadNode(leafPageHandle, insertPoint, node); if (rc != OK) { return rc; } while (insertPoint < initPageHeader.nItems && KeyCmp(node.key, key) < 0) { insertPoint++; rc = ReadNode(leafPageHandle, insertPoint, node); if (rc != OK) { return rc; } } /* Open needed space at correct point. */ int point = INXM_INITPAGEHEADER_SIZE + INXM_NODEPAGEHEADER_SIZE + insertPoint*(INXM_NODE_SIZE+this->inxmFileHeader.attrLength); char *leafData; rc = leafPageHandle.GetDataPtr(&leafData); if (rc != OK) { return rc; } memcpy(&leafData[point + INXM_NODE_SIZE+this->inxmFileHeader.attrLength], &leafData[point], (initPageHeader.nItems-insertPoint)*(INXM_NODE_SIZE+this->inxmFileHeader.attrLength)); /* Write new data. */ int slot; STORM_PageHandle lastDataPageHandle; rc = this->sfh.GetPage(this->inxmFileHeader.lastDataPage, lastDataPageHandle); if (rc != OK) { return rc; } rc = WriteData(lastDataPageHandle, rid, slot); if (rc != OK) { return rc; } /* Write new node. */ rc = WriteNode(leafPageHandle, insertPoint, key, this->inxmFileHeader.lastDataPage, slot); if (rc != OK) { return rc; } return(OK); }
t_rc INXM_IndexManager::OpenIndex(const char *fname, int indexNo, INXM_IndexHandle &ih) { /* Close index file handler if it's already open */ if (ih.isOpen) { CloseIndex(ih); } char buffer[128]; snprintf(buffer, sizeof(buffer), "%s.%d", fname, indexNo); /* Open file with STORM and assign a STORM File Handler to INXM Handler given in arguments */ t_rc rc = this->sm->OpenFile(buffer, ih.sfh); if (rc != OK) { return rc; } /* Use the STORM File Handler from INXM Handler given in arguments to get the first page. */ STORM_PageHandle pageHandle; rc = ih.sfh.GetFirstPage(pageHandle); if (rc != OK) { return rc; } /* Get data from first page. Those first data are the INXM File Header. */ rc = pageHandle.GetDataPtr(&ih.pData_FileHeader); if (rc != OK) { return rc; } rc = pageHandle.GetPageID(ih.pageNum_FileHeader); if (rc != OK) { return rc; } /* We keep File Header as a seperated copy inside the INXM Handler. * Using just a pointer in a sequence of dytes would be difficult. */ memcpy(&ih.inxmFileHeader, &ih.pData_FileHeader[0], INXM_FILEHEADER_SIZE); /* Successfully opened a record file handler */ ih.isOpen = true; return(OK); }
//----------------------------------------------------------------------------------------------- // GetFirstPage // // Updates the page handle with the first reserved page of the file. //----------------------------------------------------------------------------------------------- t_rc STORM_FileHandle::GetFirstPage(STORM_PageHandle &pageHandle) { t_rc rc; if (!m_isOpened) return (STORM_FILENOTOPENED); rc = GetNextPage(0, pageHandle); if (rc != OK) return (rc); int curPageID; pageHandle.GetPageID(curPageID); m_filePos = curPageID; return (OK); }
t_rc INXM_IndexHandle::UpdateNodeHeaders(STORM_PageHandle pageHandle, INXM_InitPageHeader initPageHeader, INXM_NodePageHeader nodePageHeader) { t_rc rc; /* Get page data pointer. */ char *nodePage; rc = pageHandle.GetDataPtr(&nodePage); if (rc != OK) { return rc; } /* init page header. */ memcpy(nodePage, &initPageHeader, INXM_INITPAGEHEADER_SIZE); /* node page header. */ memcpy(&nodePage[INXM_INITPAGEHEADER_SIZE], &nodePageHeader, INXM_NODEPAGEHEADER_SIZE); return(OK); }
t_rc INXM_IndexHandle::ReadNode(STORM_PageHandle pageHandle, int slot, INXM_Node &node) { t_rc rc; /* Read headers. */ char *nodePage; rc = pageHandle.GetDataPtr(&nodePage); if (rc != OK) { return rc; } /* Read node. */ memcpy(&node, &nodePage[INXM_INITPAGEHEADER_SIZE+INXM_NODEPAGEHEADER_SIZE+slot*(INXM_NODE_SIZE+this->inxmFileHeader.attrLength)], INXM_NODE_SIZE); /* Read key. */ void *key = malloc(this->inxmFileHeader.attrLength); memcpy(key, &nodePage[INXM_INITPAGEHEADER_SIZE+INXM_NODEPAGEHEADER_SIZE+slot*(INXM_NODE_SIZE+this->inxmFileHeader.attrLength)+INXM_NODE_SIZE], this->inxmFileHeader.attrLength); /* Update key pointer. */ node.key = key; return(OK); }
t_rc INXM_IndexHandle::insert(int rightPageID, void* key, const REM_RecordID &rid){ t_rc rc; // Δημιουργία leaf item LeafItem newItem; newItem.key = key; newItem.rid = rid; // Διαβάζω τον header και τα δεδομένα της σελίδας ( rightPage ) STORM_PageHandle pageHandle; char* hData; rc = fh.GetPage(rightPageID, pageHandle); if (rc != OK) return rc; rc = pageHandle.GetDataPtr(&hData); if (rc != OK) return rc; NodeHeader rightPageHeader; memcpy(&rightPageHeader, &hData[0], sizeof(NodeHeader)); bool posFound = false; LeafItem tempItem1 = newItem; LeafItem tempItem2; int i; for (i = 0; i < rightPageHeader.numberOfItems; i++) { // Διαβάζω ένα ένα τα αντικείμενα της σελίδας char* currentData = new char[this->getLeafItemSize()]; memcpy(currentData, &hData[sizeof(NodeHeader) + i*this->getLeafItemSize()], this->getLeafItemSize()); LeafItem currentItem; currentItem = this->getLeafItemStruct(currentData); if (keyCompare(newItem.key, currentItem.key) < 0 ) posFound = true; // Βρέθηκε η σωστή θέση μετακίνηση όλων των δεξίων item // μία θέση δεξιά if (posFound) { tempItem2 = currentItem; currentItem = tempItem1; tempItem1 = tempItem2; int j = rightPageHeader.numberOfItems ; rightPageHeader.sStatus.set(j,true); while( j != i ){ char* myCurrentData = new char[this->getLeafItemSize()]; memcpy(myCurrentData, &hData[sizeof(NodeHeader) + (j-1)*this->getLeafItemSize()], this->getLeafItemSize()); LeafItem myCurrentItem; myCurrentItem = this->getLeafItemStruct(myCurrentData); memcpy(&hData[sizeof(NodeHeader) + j*this->getLeafItemSize()], this->getLeafItemData(myCurrentItem), this->getLeafItemSize()); j--; } memcpy(&hData[sizeof(NodeHeader) + i*this->getLeafItemSize()], this->getLeafItemData(currentItem), this->getLeafItemSize()); break; } } if (!posFound){ memcpy(&hData[sizeof(NodeHeader) + i*this->getLeafItemSize()], this->getLeafItemData(newItem),this->getLeafItemSize()); rightPageHeader.sStatus.set(i,true); } rightPageHeader.numberOfItems++; // Εγγραφή του header memcpy(&hData[0], &rightPageHeader, sizeof(NodeHeader)); rc = this->fh.MarkPageDirty(rightPageID); if (rc != OK) return rc; rc = this->fh.FlushPage(rightPageID); if (rc != OK) return rc; rc = this->fh.UnpinPage(rightPageID); if (rc != OK) return rc; return (OK); }
t_rc INXM_IndexHandle::InsertIntoParent(int rootID, STORM_PageHandle leftPage, INXM_Node &keyNode, STORM_PageHandle rightPage) { t_rc rc; INXM_InitPageHeader leftInitPageHeader; INXM_NodePageHeader leftNodePageHeader; LoadNodeHeaders(leftPage, leftInitPageHeader, leftNodePageHeader); /* Case: new root. */ if (leftNodePageHeader.parent == 0) { int rightPageID; rc = rightPage.GetPageID(rightPageID); if (rc != OK) { return rc; } STORM_PageHandle newRootPageHandle; CreateNodePage(newRootPageHandle, this->inxmFileHeader.treeRoot, 0, rightPageID, 0, 0); int leftPageID; rc = leftPage.GetPageID(leftPageID); if (rc != OK) { return rc; } rc = WriteNode(newRootPageHandle, keyNode.key, leftPageID, 0); if (rc != OK) { return rc; } /* Update inxm file header. */ memcpy(this->pData_FileHeader, &this->inxmFileHeader, INXM_FILEHEADER_SIZE); rc = this->sfh.FlushPage(this->pageNum_FileHeader); if (rc != OK) { return rc; } /* Write all. */ rc = this->sfh.FlushAllPages(); if (rc != OK) { return rc; } return(OK); } /* Case: leaf or node. (Remainder of * function body.) */ /* Find the parent's node index to the left * page. */ int leftPageID; rc = leftPage.GetPageID(leftPageID); if (rc != OK) { return rc; } int rightPageID; rc = rightPage.GetPageID(rightPageID); if (rc != OK) { return rc; } int left_index = 0; INXM_Node node; INXM_InitPageHeader parentInitPageHeader; INXM_NodePageHeader parentNodePageHeader; LoadNodeHeaders(leftNodePageHeader.parent, parentInitPageHeader, parentNodePageHeader); while (left_index < parentInitPageHeader.nItems) { ReadNode(leftNodePageHeader.parent, left_index, node); if (node.left == leftPageID) { break; } left_index++; } /* Simple case: the new key fits into the page. */ STORM_PageHandle parentPageHandle; rc = this->sfh.GetPage(leftNodePageHeader.parent, parentPageHandle); if (rc != OK) { return rc; } if (LeafHasRoom(parentPageHandle)) { return InsertIntoNoLeaf(parentPageHandle, left_index, keyNode.key, rightPageID); } /* Harder case: split a not leaf page, in order * to preserve the B+ tree properties. */ // return insert_into_node_after_splitting(root, parent, left_index, key, right); return(OK); }
// Διαχωρισμός ΕΝΔΙΑΜΕΣΟΥ κόμβου ο οποίος έχει γεμίσει // Χρειάζομαι μόνο το id της σελίδας του κόμβου t_rc INXM_IndexHandle::splitInterNode(int pageToSplitID){ t_rc rc; // Διαβάζω τον Inter Node Header της σελίδας STORM_PageHandle pageHandle; char* data; rc = fh.GetPage(pageToSplitID, pageHandle); if (rc != OK) return rc; rc = pageHandle.GetDataPtr(&data); if (rc != OK) return rc; NodeHeader nh; // o header της σελίδας πρός διάσπαση memcpy(&nh, &data[0], sizeof(NodeHeader)); // Δημιουργία ΝΕΟΥ inter node // Δέσμευση σελίδας this->fh.ReservePage(pageHandle); if (rc != OK) return rc; int newInterPageID; rc = pageHandle.GetPageID(newInterPageID); if (rc != OK) { return rc; } char* newInterData; rc = pageHandle.GetDataPtr(&newInterData); if (rc != OK) { return rc; } // Αρχικοποίηση του νέου inter node header NodeHeader nhNew; nhNew.leaf = false; nhNew.parent = nh.parent; nhNew.right = -1; nhNew.left = -1; for (int i = 0; i < 1200; i++) nhNew.sStatus.set(i,false); // Μετακίνηση των μισών αντικειμένων από τον γεμάτο κόμβο // στον καινούριο for (int i = nh.numberOfItems/2; i < nh.numberOfItems; i++) { memcpy( &newInterData[sizeof(NodeHeader)+(i-nh.numberOfItems/2)*this->getInterItemSize()], &data[sizeof(NodeHeader)+i*this->getInterItemSize()], this->getInterItemSize()); // Μείωση πλήθους αντικειμένων στον έναν κόμβο nh.numberOfItems--; nh.sStatus.set(i, false); // Αύξηση πλήθους αντικειμένων στον άλλο κόμβο nhNew.numberOfItems++; nhNew.sStatus.set(i-nh.numberOfItems/2, true); } // Δημιουργία του ΠΑΤΕΡΑ ενδιάμεσου κόμβου // Δημιουργία του header NodeHeader nhParent; // Διαβάζω το ΠΡΩΤΟ item από το νέο ενδιάμεσο κόμβο που μόλις δημιούργησα char* firstItemData = new char[this->getInterItemSize()]; memcpy(&firstItemData, &newInterData[sizeof(NodeHeader)], this->getInterItemSize()); InterItem firstLeftItem = this->getInterItemStruct(firstItemData); // Δεικτόδοτηση του item που θα μπεί στον κόμβο πατέρα InterItem iItemNew; iItemNew.key = firstLeftItem.key; iItemNew.rightChild = newInterPageID; iItemNew.leftChild = pageToSplitID; if ( nh.parent > 0) { // Περίπτωση που ο προς διάσπαση κόμβος έχει πατέρα, δλδ δεν είναι ρίζα int parentPageID = nh.parent; char* parentData; rc = fh.GetPage(parentPageID, pageHandle); if (rc != OK) return rc; rc = pageHandle.GetDataPtr(&parentData); if (rc != OK) return rc; memcpy(&nhParent, &parentData[0], sizeof(NodeHeader)); if(checkInterNodeForSpace(nhParent)){ // περίπτωση που ο πατέρας έχει χώρο bool posFound = false; InterItem tempItem1 = iItemNew; InterItem tempItem2; int i; // Αντιγραφή του πρώτου item του δεξίου παιδιού // στον πατέρα for (i = 0; i < nhParent.numberOfItems+1; i++) { char* currentData = new char[this->getInterItemSize()]; InterItem currentItem; memcpy(currentData, &parentData[sizeof(NodeHeader)+i*this->getInterItemSize()], this->getInterItemSize()); currentItem = this->getInterItemStruct(currentData); if (keyCompare(iItemNew.key, currentItem.key) < 0 ) posFound = true; // Βρέθηκε η σωστή θέση μετακίνηση όλων των δεξίων item // μία θέση δεξιά if (posFound) { tempItem2 = currentItem; currentItem = tempItem1; tempItem1 = tempItem2; memcpy(&parentData[sizeof(NodeHeader)+i*this->getInterItemSize()],this->getInterItemData(currentItem),this->getInterItemSize()); } } nhParent.numberOfItems++; nhParent.sStatus.set(i-1,true); } else { // περίπτωση που ο πατέρας δεν έχει χώρο // ** // Anadromika splitInterNode(parentPageID); // ** } } else { // Περίπτωση που ο προς διάσπαση κόμβος ΔΕΝ έχει πατέρα, δλδ είναι ρίζα // Δημιουργία inter node // Δέσμευση σελίδας this->fh.ReservePage(pageHandle); if (rc != OK) return rc; int interPageID; rc = pageHandle.GetPageID(interPageID); if (rc != OK) { return rc; } char* interData; rc = pageHandle.GetDataPtr(&interData); if (rc != OK) { return rc; } nh.parent = interPageID; nhNew.parent = interPageID; for (int i = 0; i < 1200; i++) nhParent.sStatus.set(i,false); nhParent.parent = -1; nhParent.leaf = false; nhParent.sStatus.set(0,true); nhParent.numberOfItems++; nhParent.left = -1; nhParent.right = -1; // Εγγραφή του interItem memcpy(&interData[sizeof(NodeHeader)], this->getInterItemData(iItemNew), this->getInterItemSize()); // Ενημέρωση του header memcpy(&interData[0], &nhParent, sizeof(NodeHeader)); rc = this->fh.MarkPageDirty(interPageID); if (rc != OK) return rc; rc = this->fh.FlushPage(interPageID); if (rc != OK) return rc; rc = this->fh.UnpinPage(interPageID); if (rc != OK) return rc; } memcpy(&data[0], &nh, sizeof(NodeHeader)); memcpy(&newInterData[0], &nhNew, sizeof(NodeHeader)); return (OK); }
void testStorm() { STORM_StorageManager mgr; STORM_FileHandle fh; t_rc rc; int nAllocPages, nResPages; STORM_PageHandle ph; char *data; int val; int pid; int nreqs, nreads, nwrites, npinned, nframes; // ====================== STEP 1 =======================================// // Create the file. // Open the file. // Reserve 100 pages. // Store something in each page. // Close the file. //======================================================================// rc = mgr.CreateFile("test.dat"); if (rc != OK) {DisplayReturnCode(rc); Pause(); exit(-1);} rc = mgr.OpenFile("test.dat", fh); if (rc != OK) {DisplayReturnCode(rc); Pause(); exit(-1);} nAllocPages = fh.GetNumAllocatedPages(); nResPages = fh.GetNumReservedPages(); for (int i=1; i<=100; i++) { rc = fh.ReservePage(ph); if (rc != OK) {DisplayReturnCode(rc); Pause(); exit(-1);} // Copy something to the page. rc = ph.GetDataPtr(&data); memcpy(data, &i, sizeof(int)); // Mark the page as dirty. rc = ph.GetPageID(pid); if (rc != OK) {DisplayReturnCode(rc); exit(-1);} rc = fh.MarkPageDirty(pid); if (rc != OK) {DisplayReturnCode(rc); exit(-1);} // Unpin the page rc = fh.UnpinPage(pid); if (rc != OK) {DisplayReturnCode(rc); exit(-1);} } mgr.GetStats(nreqs, nreads, nwrites, npinned, nframes); printf("reqs: %d, reads: %d, writes: %d, pinned: %d, frames: %d\n", nreqs, nreads, nwrites, npinned, nframes); printf("allocated pages: %d, reserved pages: %d\n", fh.GetNumAllocatedPages(), fh.GetNumReservedPages()); rc = mgr.CloseFile(fh); if (rc != OK) {DisplayReturnCode(rc); exit(-1);} Pause(); // ====================== STEP 2 =======================================// // Open the file again. // Read every page of the file and print the page contents. // Release the first 50 pages. // Close the file. //======================================================================// rc = mgr.OpenFile("test.dat", fh); if (rc != OK){DisplayReturnCode(rc); exit(-1);} printf("allocated pages: %d, reserved pages: %d\n", fh.GetNumAllocatedPages(), fh.GetNumReservedPages()); // Display page contents. while (fh.GetNextPage(ph) != STORM_EOF) { rc = ph.GetDataPtr(&data); if (rc != OK) {DisplayReturnCode(rc);exit(-1);} memcpy(&val, data, sizeof(int)); ph.GetPageID(pid); printf("contents of page %d = %d\n", pid, val); // Unpin the page rc = fh.UnpinPage(pid); if (rc != OK) {DisplayReturnCode(rc); exit(-1);} } // Release pages from 1 to 50. for (int p=1; p<=50; p++) { rc = fh.ReleasePage(p); if (rc != OK) {DisplayReturnCode(rc); exit(-1);} } printf("allocated pages: %d, reserved pages: %d\n", fh.GetNumAllocatedPages(), fh.GetNumReservedPages()); rc = mgr.CloseFile(fh); if (rc != OK) {DisplayReturnCode(rc); exit(-1);} Pause(); // ====================== STEP 3 =======================================// // Open the file again. // Read every page of the file and print the page contents. // Close the file. // Finally, destroy the file. // // We expect to see only 50 pages staring from 51 up to 100, since the // first 50 have been released in the previous step. //======================================================================// rc = mgr.OpenFile("test.dat", fh); if (rc != OK){DisplayReturnCode(rc); exit(-1);} // Display page contents. while (fh.GetNextPage(ph) != STORM_EOF) { rc = ph.GetDataPtr(&data); if (rc != OK) {DisplayReturnCode(rc);exit(-1);} memcpy(&val, data, sizeof(int)); ph.GetPageID(pid); printf("contents of page %d = %d\n", pid, val); // Unpin the page fh.UnpinPage(pid); } printf("allocated pages: %d, reserved pages: %d\n", fh.GetNumAllocatedPages(), fh.GetNumReservedPages()); rc = mgr.CloseFile(fh); if (rc != OK) {DisplayReturnCode(rc); exit(-1);} Pause(); rc = mgr.DestroyFile("test.dat"); if (rc != OK) {DisplayReturnCode(rc);exit(-1);} }
t_rc REM_RecordFileHandle::InsertRecord(const char *pData, REM_RecordID &rid) { /* Check is file is open. */ if (!this->isOpen) { return REM_FHCLOSED; } t_rc rc; /* Find an empty page to write the new record. */ STORM_PageHandle targetPage; REM_PageHeader pageHeader = {0}; // The default number of records in a page is 0. char *pageData; /* If there is no free space (lastPageID=-1) then we reserve a new page. */ if (this->remFileHeader.isLastPageFull) { rc = sfh.ReservePage(targetPage); // Reserve the new page. if (rc != OK) { return rc; } /* We mark the last page as not full. */ this->remFileHeader.isLastPageFull = false; /* We update the file header and mark as dirty. */ memcpy(this->pData_FileHeader, &this->remFileHeader, REM_FILEHEADER_SIZE); rc = this->sfh.MarkPageDirty(this->pageNum_FileHeader); if (rc != OK) { return rc; } /* Get a pointer to the data of the new page to write the new data. */ rc = targetPage.GetDataPtr(&pageData); if (rc != OK) { return rc; } } /* If we have free space in a page, we just get the page. */ else { rc = this->sfh.GetLastPage(targetPage); if (rc != OK) { return rc; } /* Get a pointer to the data of the the page to read the REM Page Header. */ rc = targetPage.GetDataPtr(&pageData); if (rc != OK) { return rc; } memcpy(&pageHeader, pageData, REM_PAGEHEADER_SIZE); } /* We write the data to the proper position. The new record offset must be the page header size + the offset of each record there * is inside the page. We always place the new record at the end of the page. */ memcpy(&pageData[REM_PAGEHEADER_SIZE+(pageHeader.nRecords*this->remFileHeader.recordSize)], pData, this->remFileHeader.recordSize); /* Increase the number of records in the page header. This number is also the slot number of the record. */ int slotNum = ++pageHeader.nRecords; /* Declare page number, which is the pageID we are currently working on. */ int pageNum; rc = targetPage.GetPageID(pageNum); if (rc != OK) { return rc; } /* Check if page is full. */ if (pageHeader.nRecords == this->remFileHeader.recordsPerPage) { this->remFileHeader.isLastPageFull = true; /* We update the file header and mark as dirty. */ memcpy(this->pData_FileHeader, &this->remFileHeader, REM_FILEHEADER_SIZE); rc = this->sfh.MarkPageDirty(this->pageNum_FileHeader); if (rc != OK) { return rc; } /* Get a pointer to the data of the new page to write the new data. */ rc = targetPage.GetDataPtr(&pageData); if (rc != OK) { return rc; } } /* Write the new REM Page Header. */ memcpy(pageData, &pageHeader, REM_PAGEHEADER_SIZE); /* Mark the page as dirty because we modified it */ rc = this->sfh.MarkPageDirty(pageNum); if (rc != OK) { return rc; } this->sfh.FlushPage(pageNum); // We should reconsider when we are flushing pages!!! /* Unpin the page */ rc = this->sfh.UnpinPage (pageNum); if (rc != OK) { return rc; } /* Set the passed RID's page number and slot number */ rc = rid.SetPageID(pageNum); if (rc != OK) { return rc; } rc = rid.SetSlot(slotNum); if (rc != OK) { return rc; } /* Successfuly inserted record */ return (OK); }
t_rc INXM_IndexHandle::InsertIntoLeafAfterSplitting(int rootID, STORM_PageHandle leafPageHandle, void *key, const REM_RecordID &rid) { t_rc rc; STORM_PageHandle newLeafPageHandle; int newLeafPageID; rc = CreateNodePage(newLeafPageHandle, newLeafPageID, 0, 0, 0, true); if (rc != OK) { return rc; } /* Read leaf page headers. */ INXM_InitPageHeader leafPageHeader; rc = LoadInitHeaders(leafPageHandle, leafPageHeader); if (rc != OK) { return rc; } int insertPoint = 0; INXM_Node node; ReadNode(leafPageHandle, insertPoint, node); while (insertPoint < leafPageHeader.nItems && KeyCmp(node.key, key) < 0) { ReadNode(leafPageHandle, insertPoint, node); insertPoint++; } INXM_Node **temp_nodes = (INXM_Node **)malloc(INXM_NODE_SIZE*leafPageHeader.nItems); int i,j; for (i=0, j=0; i < leafPageHeader.nItems; i++, j++) { if (j == insertPoint) j++; ReadNode(leafPageHandle, i, *(temp_nodes[j])); } /* Write new data to last page. */ int newDataSlot; STORM_PageHandle lastDataPageHandle; rc = this->sfh.GetPage(this->inxmFileHeader.lastDataPage, lastDataPageHandle); if (rc != OK) { return rc; } rc = WriteData(lastDataPageHandle, rid, newDataSlot); if (rc != OK) { return rc; } /* Place new node to temp array. */ INXM_Node *newNode = new INXM_Node(); newNode->key = key; newNode->left = this->inxmFileHeader.lastDataPage; newNode->slot = newDataSlot; temp_nodes[insertPoint] = newNode; /* Reset leaf's nItems */ char *tmpData; leafPageHandle.GetDataPtr(&tmpData); leafPageHeader.nItems = 0; memcpy(tmpData, &leafPageHeader, INXM_INITPAGEHEADER_SIZE); int maxNodeRoom = (PAGE_DATA_SIZE-INXM_INITPAGEHEADER_SIZE-INXM_NODEPAGEHEADER_SIZE)/(INXM_NODE_SIZE+this->inxmFileHeader.attrLength); int split = Cut(maxNodeRoom); /* Write new data. */ for (i = 0; i < split; i++) { WriteNode(leafPageHandle, i, temp_nodes[i]->key, temp_nodes[i]->left, temp_nodes[i]->slot); } for (i = split, j = 0; i < maxNodeRoom; i++, j++) { WriteNode(newLeafPageHandle, j, temp_nodes[i]->key, temp_nodes[i]->left, temp_nodes[i]->slot); } free(temp_nodes); // This is not enough! INXM_NodePageHeader leafNodePageHeader; LoadNodeHeaders(leafPageHandle, leafPageHeader, leafNodePageHeader); INXM_NodePageHeader newLeafNodePageHeader; INXM_InitPageHeader newLeafPageHeader; rc = LoadNodeHeaders(newLeafPageHandle, newLeafPageHeader, newLeafNodePageHeader); if (rc != OK) { return rc; } int leafPageID; rc = leafPageHandle.GetPageID(leafPageID); if (rc != OK) { return rc; } newLeafNodePageHeader.next = leafNodePageHeader.next; newLeafNodePageHeader.previous = leafPageID; leafNodePageHeader.next = newLeafPageID; if (newLeafNodePageHeader.next != 0) { STORM_PageHandle nextLeafPageHandle; rc = this->sfh.GetPage(newLeafNodePageHeader.next, nextLeafPageHandle); if (rc != OK) { return rc; } INXM_InitPageHeader nextInitPageHeader; INXM_NodePageHeader nextNodePageHeader; LoadNodeHeaders(nextLeafPageHandle, nextInitPageHeader, nextNodePageHeader); nextNodePageHeader.previous = newLeafPageID; UpdateNodeHeaders(nextLeafPageHandle, nextInitPageHeader, nextNodePageHeader); } rc = UpdateNodeHeaders(leafPageHandle, leafPageHeader, leafNodePageHeader); if (rc != OK) { return rc; } rc = UpdateNodeHeaders(newLeafPageHandle, newLeafPageHeader, newLeafNodePageHeader); if (rc != OK) { return rc; } INXM_Node keyNode; rc = ReadNode(newLeafPageHandle, 0, keyNode); if (rc != OK) { return rc; } rc = InsertIntoParent(this->inxmFileHeader.treeRoot, leafPageHandle, keyNode, newLeafPageHandle); if (rc != OK) { return rc; } return(OK); }
t_rc REM_RecordFileHandle::DeleteRecord(const REM_RecordID &rid) { /* Check is file is open. */ if (!this->isOpen) { return REM_FHCLOSED; } t_rc rc; /* Read page and slot we want to delete. */ int pageID, slot; rc = rid.GetPageID(pageID); if (rc != OK) { return rc; } rc = rid.GetSlot(slot); if (rc != OK) { return rc; } /* Get wanted page. */ STORM_PageHandle wantedPageHandle; rc = this->sfh.GetPage(pageID, wantedPageHandle); if (rc != OK) { return rc; } /* Get the wanted page header. */ char *wantedData; REM_PageHeader wantedPageHeader; rc = wantedPageHandle.GetDataPtr(&wantedData); if (rc != OK) { return rc; } memcpy(&wantedPageHeader, wantedData, REM_PAGEHEADER_SIZE); if (slot > wantedPageHeader.nRecords) { return REM_INVALIDRID; } STORM_PageHandle lastPageHandle; int lastPageID; rc = this->sfh.GetLastPage(lastPageHandle); if (rc != OK) { return rc; } rc = lastPageHandle.GetPageID(lastPageID); if (rc != OK) { return rc; } /* Determine if we need to retrive an other page to replace the record. */ if (lastPageID == pageID) { /* Determine if our record is the last. */ if (wantedPageHeader.nRecords == slot) { /* Check if we need to release the page. */ if (wantedPageHeader.nRecords == 1) { rc = this->sfh.ReleasePage(pageID); if (rc != OK) { return rc; } /* We must change the lastPageID in REM File Header. */ this->remFileHeader.isLastPageFull = true; /* Copy new file header at memory */ memcpy(this->pData_FileHeader, &this->remFileHeader, REM_FILEHEADER_SIZE); /* Mark REM File Header frame as dirty */ rc = this->sfh.MarkPageDirty(this->pageNum_FileHeader); if (rc != OK) { return rc; } } else { /* If our record is the last one in the row but more data exist, we just decrease the number of records the page has. */ wantedPageHeader.nRecords--; /* Copy header back. */ memcpy(wantedData, &wantedPageHeader, REM_PAGEHEADER_SIZE); } } else { /* Copy the last record of this page (last page) in the position of the record we want to erase. */ memcpy(&wantedData[REM_PAGEHEADER_SIZE+((slot-1)*this->remFileHeader.recordSize)], &wantedData[REM_PAGEHEADER_SIZE+((wantedPageHeader.nRecords-1)*this->remFileHeader.recordSize)], this->remFileHeader.recordSize); /* Decrease the number of records the pages has. */ wantedPageHeader.nRecords--; /* Copy header back. */ memcpy(wantedData, &wantedPageHeader, REM_PAGEHEADER_SIZE); } } else { /* Get last record from last page to replace the asked record. */ char *lastData; rc = lastPageHandle.GetDataPtr(&lastData); if (rc != OK) { return rc; } /* Get last's page header. */ REM_PageHeader lastPageHeader; memcpy(&lastPageHeader, lastData, REM_PAGEHEADER_SIZE); /* Copy the data between the two pages */ memcpy(&wantedData[REM_PAGEHEADER_SIZE+((slot-1)*this->remFileHeader.recordSize)], &lastData[REM_PAGEHEADER_SIZE+((lastPageHeader.nRecords-1)*this->remFileHeader.recordSize)], this->remFileHeader.recordSize); /* Check if last page has no more records. */ if (lastPageHeader.nRecords == 1) { /* If we copied the last record we can safely release the last page. */ rc = this->sfh.ReleasePage(lastPageID); if (rc != OK) { return rc; } /* We must change the lastPageID in REM File Header. */ this->remFileHeader.isLastPageFull = true; /* Copy new file header at memory */ memcpy(this->pData_FileHeader, &this->remFileHeader, REM_FILEHEADER_SIZE); /* Mark REM File Header frame as dirty */ rc = this->sfh.MarkPageDirty(this->pageNum_FileHeader); if (rc != OK) { return rc; } } else { /* Decrease last page record number in its page header. */ lastPageHeader.nRecords--; memcpy(lastData, &lastPageHeader, REM_PAGEHEADER_SIZE); /* Mark last page as dirty due to last record removal. */ rc = sfh.MarkPageDirty(lastPageID); if (rc != OK) { return rc; } /* Unpin last page. */ rc = sfh.UnpinPage (lastPageID); if (rc != OK) { return rc; } } } /* Mark the page as dirty because we modified it */ rc = sfh.MarkPageDirty(pageID); if (rc != OK) { return rc; } /* Unpin the page */ rc = sfh.UnpinPage (pageID); if (rc != OK) { return rc; } sfh.FlushPage(pageID); /* Record successfully deleted */ return (OK); }
t_rc INXM_IndexManager::CreateIndex(const char *fname, int indexNo, t_attrType attrType, int attrLength) { // We need to find the number of records that fit in a page. int recordsPerPage = (PAGE_SIZE - INXM_INITPAGEHEADER_SIZE + INXM_NODEPAGEHEADER_SIZE)/(INXM_NODE_SIZE + attrLength); // We need only the integer part or we can "floor" the number. if (recordsPerPage < 1) { return (INXM_INVALIDRECSIZE); } char buffer[128]; snprintf(buffer, sizeof(buffer), "%s.%d", fname, indexNo); /* Create file by using STORM */ t_rc rc = this->sm->CreateFile(buffer); if (rc != OK) { return rc; } /* Open the created file */ STORM_FileHandle stormFileHandle; rc = this->sm->OpenFile(buffer, stormFileHandle); if (rc != OK) { return rc; } /* Allocate a new page for the INXM file header page. */ STORM_PageHandle stormPageHandle; rc = stormFileHandle.ReservePage(stormPageHandle); if (rc != OK) { return rc; } /* Get pointer to the contents (data) of the INXM file header page */ char *pData; int pageID; rc = stormPageHandle.GetDataPtr(&pData); if (rc != OK) { return rc; } /* Get the page number of the INXM file header page */ rc = stormPageHandle.GetPageID(pageID); if (rc != OK) { return rc; } /* Construct INXM File Header */ INXM_FileHeader fileHeader = { attrType, attrLength, 0, 0 }; /* Copy the INXM File Header to the first page */ memcpy(pData, &fileHeader, INXM_FILEHEADER_SIZE); /* Because we modified the INXM file header page, we write it to disk */ rc = stormFileHandle.MarkPageDirty(pageID); if (rc != OK) { return rc; } rc = stormFileHandle.FlushPage(pageID); if (rc != OK) { return rc; } /* We now unpin the header page because we are done modifying it. (We really need this?) */ rc = stormFileHandle.UnpinPage(pageID); if (rc != OK) { return rc; } /* We now close the file because we are done modifying it. (We really need this too?) */ rc = this->sm->CloseFile(stormFileHandle); if (rc != OK) { return rc; } return(OK); }