//-------------------------------------------------------------------- // BufMgr::FindFrame // // Input : pid - a page id // Output : None // Purpose : Look for the page in the buffer pool, return the frame // number if found. // PreCond : None // PostCond : None // Return : the frame number if found. INVALID_FRAME otherwise. //-------------------------------------------------------------------- int BufMgr::FindFrame( PageID pid ) { Frame* currFrame; for (int iter = 0; iter < numFrames; iter++) { currFrame = &frames[iter]; if (currFrame->GetPageID() == pid) { return iter; } } return INVALID_FRAME; }
//-------------------------------------------------------------------- // BufMgr::UnpinPage // // Input : pid - page id of a particular page // dirty - indicate whether the page with page id = pid // is dirty or not. (Optional, default to false) // Output : None // Purpose : Unpin the page with page id = pid in the buffer. Mark // the page dirty if dirty is true. // Condition: The page is already in the buffer and is pinned. // PostCond : The page is unpinned and the number of pin on the // page decrease by one. // Return : OK if operation is successful. FAIL otherwise. //-------------------------------------------------------------------- Status BufMgr::UnpinPage(PageID pid, bool dirty) { //std::cout << "Unin PageID " << pid << std::endl; ////std::cout << "Unpinning page " << pid << " Dirty?: " << dirty << std::endl; int frameIndex = FindFrame(pid); if (frameIndex == INVALID_FRAME) return FAIL; Frame* targetFrame = &frames[frameIndex]; if (targetFrame->NotPinned()) return FAIL; if (dirty) targetFrame->DirtyIt(); targetFrame->Unpin(); if (targetFrame->NotPinned()) replacer->AddFrame(targetFrame->GetPageID()); return OK; }
//-------------------------------------------------------------------- // BufMgr::FlushPage // // Input : pid - page id of a particular page // Output : None // Purpose : Flush the page with the given pid to disk. // Condition: The page with page id = pid must be in the buffer, // and is not pinned. pid cannot be INVALID_PAGE. // PostCond : The page with page id = pid is written to disk if it's dirty. // The frame where the page resides is empty. // Return : OK if operation is successful. FAIL otherwise. //-------------------------------------------------------------------- Status BufMgr::FlushPage(PageID pid) { //std::cout << "Flush Page" << pid << std::endl; ////std::cout << "Flush Page " << pid << std::endl; int frameIndex = FindFrame(pid); if (frameIndex == INVALID_FRAME) return FAIL; Frame* targetFrame = &frames[frameIndex]; if(!targetFrame->IsValid() || !targetFrame->NotPinned()) return FAIL; if (targetFrame->IsDirty()){ if (targetFrame->Write() != OK) return FAIL; numDirtyPageWrites++; } replacer->RemoveFrame(targetFrame->GetPageID()); targetFrame->EmptyIt(); //std::cout << "Flush OK " << std::endl; return OK; }
Status BufMgr::FlushAllPages() { //std::cout << "Flush all " << std::endl; bool failedOnce = false; Frame* currFrame; for (int iter = 0; iter < numFrames; iter++) { currFrame = &frames[iter]; if (currFrame->IsValid()) { // Check that the frame is not pinned if (!currFrame->NotPinned()){ failedOnce = true; } if (currFrame->IsDirty()){ if (currFrame->Write() != OK) failedOnce = true; numDirtyPageWrites++; } replacer->RemoveFrame(currFrame->GetPageID()); currFrame->EmptyIt(); } } return (failedOnce) ? FAIL : OK; }
//-------------------------------------------------------------------- // BufMgr::PinPage // // Input : pid - page id of a particular page // isEmpty - (optional, default to false) if true indicate // that the page to be pinned is an empty page. // Output : page - a pointer to a page in the buffer pool. (NULL // if fail) // Purpose : Pin the page with page id = pid to the buffer. // Read the page from disk unless isEmpty is true or unless // the page is already in the buffer. // Condition: Either the page is already in the buffer, or there is at // least one frame available in the buffer pool for the // page. // PostCond : The page with page id = pid resides in the buffer and // is pinned. The number of pin on the page increase by // one. // Return : OK if operation is successful. FAIL otherwise. //-------------------------------------------------------------------- Status BufMgr::PinPage(PageID pid, Page*& page, bool isEmpty) { if(pid == INVALID_PAGE) return FAIL; totalCall++; // Check if the page is in the buffer pool bool inPool = false; Frame* currFrame; for (int iter = 0; iter < numFrames; iter++) { currFrame = &frames[iter]; if (currFrame->GetPageID() == pid){ inPool = true; totalHit++; break; } } if (inPool){ // Increase its pin count and set output page pointer currFrame->Pin(); page = currFrame->GetPage(); } else { // Find the first free frame if there is one bool foundEmptyFrame = false; for (int iter = 0; iter < numFrames; iter++) { currFrame = &frames[iter]; if (!currFrame->IsValid()){ foundEmptyFrame = true; break; } } if (!foundEmptyFrame) { // Find a page to evict based on our replacement policy int replacedPageID = replacer->PickVictim(); // Get a pointer to the frame we will flush for (int iter = 0; iter < numFrames; iter++) { currFrame = &frames[iter]; if (currFrame->GetPageID() == replacedPageID){ break; } } if(FlushPage(replacedPageID) != OK) { page = NULL; return FAIL; } } currFrame->SetPageID(pid); currFrame->Pin(); // If the page is not empty, read it in from disk if (!isEmpty && currFrame->Read(pid) != OK) { page = NULL; return FAIL; } page = currFrame->GetPage(); } // Now that the frame is pinned we need to remove it from the ones that can be evicted replacer->RemoveFrame(currFrame->GetPageID()); ////std::cout << "pinned page: " << currFrame->GetPageID() <<std::endl; return OK; }