// // Created by YuhangQ on 2021/9/24. // #include "page_manager.h" #include "btree/list.h" int PageManager::loadDatabase(const char *filename) { Instance().stream.open(filename); Instance().stream.seekp(0, std::ios::end); int index = Instance().stream.tellp() / 1024; if(index == 0) { StoragePage(0).save(); StoragePage(1).save(); StoragePage(2).save(); } return 0; } std::shared_ptr PageManager::getPage(const int &index) { if(cache.exist(index)) { return cache.get(index); } auto page = std::make_shared(index); // 调整指针位置 stream.clear(); stream.seekg((long long)index * 1024); stream.read(*page, 1024); return page; } void PageManager::setPage(const int &index, const StoragePage &page) { cache.put(index, std::make_shared(page)); stream.clear(); stream.seekg((long long)index * 1024); stream.write(page, 1024); } int PageManager::allocate() { // try to allocate from free block list auto page = getPage(0); int index = page->getIntStartFrom(0); if(index != 0) { auto allocatePage = getPage(index); page->setIntStartFrom(0, allocatePage->next()); // reset allocatePage->clear(); allocatePage->save(); page->save(); //printf("allocate: %d\n", index); return index; } // allocate block at the end stream.seekp(0, std::ios::end); index = stream.tellp() / 1024; setPage(index, StoragePage(index)); return index; } void PageManager::release(const int &index, const bool &next) { auto page = getPage(0); int head = page->getIntStartFrom(0); auto releasePage = getPage(index); releasePage->setNext(head); page->setIntStartFrom(0, releasePage->getAddress()); page->save(); releasePage->save(); //printf("release: %d\n", index); } nlohmann::json PageManager::readJSONFromFile(const int &index) { std::string content; auto page = getPage(index); while(true) { for(int i=0; i<1016; i++) { if((*page)[i] == '\0') break; content.push_back((*page)[i]); } if(page->next() == 0) break; page = getPage(page->next()); } return nlohmann::json::parse(content); } int PageManager::saveJSONToFile(const nlohmann::json& json) { std::string content = json.dump(); int size = content.size(); auto page = getPage(allocate()); int res = page->getAddress(); int p = 0; while(p < size) { int len = std::min(size - p, 1016); page->setStartFrom(0, &content.c_str()[p], len); page->save(); p += len; if(p < size) { int newPage = allocate(); int lastPage = page->getAddress(); page->setNext(newPage); page->save(); page = getPage(newPage); page->setLast(lastPage); page->save(); } } return res; }