创建 collection

This commit is contained in:
YuhangQ 2021-10-23 16:28:57 +08:00
parent 2c318faf40
commit 6cb59287d7
15 changed files with 310 additions and 134 deletions

View File

@ -3,8 +3,12 @@ project(InvoDB)
set(CMAKE_CXX_STANDARD 14)
include_directories(/opt/homebrew/Cellar/boost/1.76.0/include)
include_directories(.)
include_directories(./invodb)
add_executable(InvoDB
invodb/main.cpp
invodb/main.h invodb/file/page_manager.cpp invodb/file/page_manager.h invodb/file/virtual_storage.cpp invodb/file/virtual_storage.h invodb/models/json.cpp invodb/models/json.h invodb/invodb.cpp invodb/invodb.h invodb/models/collection.cpp invodb/models/collection.h)
invodb/main.h invodb/file/page_manager.cpp invodb/file/page_manager.h invodb/models/json.cpp invodb/models/json.h invodb/invodb.cpp invodb/invodb.h invodb/models/collection.cpp invodb/models/collection.h invodb/file/storage_page.cpp invodb/file/storage_page.h invodb/utils/logger.h invodb/utils/uuid.h)

View File

@ -10,7 +10,7 @@ int PageManager::loadDatabase(const char *filename) {
}
StoragePage PageManager::getPage(const int &index) {
StoragePage page;
StoragePage page(index);
// 调整指针位置
stream.clear();
stream.seekg(index * 1024);
@ -24,29 +24,9 @@ void PageManager::setPage(const int &index, const StoragePage &page) {
stream.write(page, 1024);
}
void StoragePage::print() {
for(int i=0; i<16; i++) {
for(int j=0; j<256; j++) {
printf("%u ", page[i * 16 + j]);
}
printf("\n");
}
int PageManager::allocate() {
stream.seekp(0, std::ios::end);
int index = stream.tellp() / 1024;
setPage(index, StoragePage(index));
return index;
}
/**
*
* @return
*/
int StoragePage::next() {
return *((const int *)&page[1020]);
}
int StoragePage::setNext(const int &nextPage) {
*((int *)&page[1020]) = nextPage;
return 0;
}
int *StoragePage::intArray() {
return (int *)page;
}

View File

@ -7,21 +7,8 @@
#include <iostream>
#include <fstream>
#include <cstring>
class StoragePage {
public:
void print();
int next();
int setNext(const int& nextPage);
int* intArray();
StoragePage() { memset(page, 0, sizeof(page)); }
char& operator[] (int index) { return this->page[index]; }
operator const char *() const { return this->page; }
operator char *() { return this->page; }
private:
char page[1024];
};
#include "storage_page.h"
class PageManager {
public:
@ -33,10 +20,9 @@ public:
StoragePage getPage(const int &index);
void setPage(const int &index, const StoragePage &page);
int allocate();
void free(const int &index);
private:
std::fstream stream;
// 私有化实现单例
PageManager() {}
~PageManager() {}

View File

@ -0,0 +1,56 @@
//
// Created by YuhangQ on 2021/10/22.
//
#include "storage_page.h"
#include "page_manager.h"
void StoragePage::print() {
printf("-------------------PageInfo--------------------\n");
for(int i=0; i<8; i++) {
for(int j=0; j<32; j++) {
printf("%u ", intArray()[i*32+j]);
}
printf("\n");
}
}
int StoragePage::next() {
return getIntStartFrom(1020);
}
void StoragePage::setNext(const int& nextPage) {
setIntStartFrom(1020, nextPage);
}
int StoragePage::last() {
return getIntStartFrom(1016);
}
void StoragePage::setLast(const int& lastPage) {
setIntStartFrom(1016, lastPage);
}
int *StoragePage::intArray() {
return (int *)page;
}
int StoragePage::getIntStartFrom(const int& index) {
return *((const int *)&page[index]);
}
void StoragePage::setIntStartFrom(const int& index, const int& value) {
*((int *)&page[index]) = value;
}
void StoragePage::setStringStartFrom(const int &index, const char *str) {
for(int i=0; i<strlen(str); i++) {
page[index+i] = str[i];
}
}
void StoragePage::save() {
PageManager::Instance().setPage(address, *this);
}

View File

@ -0,0 +1,36 @@
//
// Created by YuhangQ on 2021/10/22.
//
#ifndef INVODB_STORAGE_PAGE_H
#define INVODB_STORAGE_PAGE_H
#include <iostream>
#include <cstring>
class PageManager;
class StoragePage {
public:
void print();
int next();
void setNext(const int& nextPage);
int last();
void setLast(const int& lastPage);
void save();
int getIntStartFrom(const int &index);
void setIntStartFrom(const int &index, const int &value);
void setStringStartFrom(const int &index, const char *str);
int *intArray();
StoragePage(const int& id) { memset(page, 0, sizeof(page)); }
char& operator[] (int index) { return this->page[index]; }
operator const char *() const { return this->page; }
operator char *() { return this->page; }
private:
char page[1024];
int address;
};
#endif //INVODB_STORAGE_PAGE_H

View File

@ -1,47 +0,0 @@
//
// Created by YuhangQ on 2021/9/30.
//
#include "virtual_storage.h"
int VirtualStorage::loadDatabase(const char *filename) {
int result = PageManager::loadDatabase(filename);
return result;
}
StoragePage VirtualStorage::getPage(const int &index) {
PageManager& manager = PageManager::Instance();
return manager.getPage(getPhysicalAddress(index));
}
void VirtualStorage::setPage(const int &index, const StoragePage &page) {
PageManager& manager = PageManager::Instance();
manager.setPage(getPhysicalAddress(index), page);
}
int VirtualStorage::getPhysicalAddress(const int &index) {
loadPageInfoTable(index >> 2);
return (table[index >> 2].addr << 2) || (index & 3);
}
int VirtualStorage::getNextAddress(const int &index) {
loadPageInfoTable(index >> 2);
return table[index >> 2].next;
}
void VirtualStorage::loadPageInfoTable(const int &index) {
PageManager& manager = PageManager::Instance();
// 未命中 cache
if(table.count(index) == 0) {
int pageIndex = 1 + index / 512;
// 加载页表
StoragePage page = manager.getPage(pageIndex);
int *arr = page.intArray();
for(int i=0; i<512; i++) {
table[(pageIndex - 1) * 512 + i] = TableEl{ arr[2*i], arr[2*i+1] };
}
}
}

View File

@ -1,38 +0,0 @@
//
// Created by YuhangQ on 2021/9/30.
//
#ifndef INVODB_VIRTUAL_STORAGE_H
#define INVODB_VIRTUAL_STORAGE_H
#include <map>
#include "page_manager.h"
class VirtualStorage {
public:
static VirtualStorage& Instance() {
static VirtualStorage instance;
return instance;
}
static int loadDatabase(const char *filename);
StoragePage getPage(const int &index);
void setPage(const int &index, const StoragePage &page);
int allocate();
private:
struct TableEl {
int addr;
int next;
};
// 页表 Cache
std::map<int, TableEl> table;
int getPhysicalAddress(const int &index);
int getNextAddress(const int &index);
void loadPageInfoTable(const int &index);
// 私有化实现单例
VirtualStorage() {}
~VirtualStorage() {}
VirtualStorage(const PageManager&);
VirtualStorage& operator=(const PageManager&);
};
#endif //INVODB_VIRTUAL_STORAGE_H

View File

@ -5,12 +5,17 @@
#include "main.h"
int main() {
VirtualStorage::loadDatabase("test.invodb");
VirtualStorage& storage = VirtualStorage::Instance();
PageManager::loadDatabase("test.invodb");
Collection::loadCollections();
PageManager& manager = PageManager::Instance();
Collection &col = Collection::getCollection("hello");
JSON json("{\"hello\": 1}");
col.insert(json);
return 0;
}

View File

@ -6,7 +6,6 @@
#define INVODB_MAIN_H
#include <iostream>
#include "file/virtual_storage.h"
#include "invodb/models/json.h"
#include "models/collection.h"
#endif //INVODB_MAIN_H

View File

@ -3,3 +3,84 @@
//
#include "collection.h"
#include "utils/uuid.h"
Collection::Collection(const std::string &name, const int &firstPage) {
Logger::info<std::string, std::string>("load Collection: ", name);
}
void Collection::insert(JSON &json) {
if(!json.HasMember(" __Invo_ID__")) {
std::string uuid = generateUUID();
Document::AllocatorType &allocator = json.GetAllocator();
Value invoid (kStringType);
invoid.SetString(uuid.c_str(), uuid.size());
json.AddMember(" __Invo_ID__", invoid, allocator);
}
Logger::info<std::string>(json.ToString());
}
std::map<std::string, Collection*> Collection::map;
std::set<int> Collection::free;
void Collection::loadCollections() {
// 前四页为集合信息页
for (int id = 0; id < 4; id++) {
StoragePage page = PageManager::Instance().getPage(id);
PageManager::Instance().setPage(id, page);
for (int i = 0; i < 32; i++) {
int p = i * 32;
int len = strlen(&page[p]);
std::string name(&page[p], len > 28 ? 28 : len);
int firstPage = page.getIntStartFrom(p + 28);
// if free
if (firstPage == 0) free.insert(id * 32 + i);
// not free
else map.insert(make_pair(name, new Collection(name, firstPage)));
}
}
Logger::info<std::string, int>("Successfully load Collections: ", 128 - free.size());
}
Collection& Collection::createCollection(const std::string &name) {
// exist
if(map.count(name) != 0) {
throw "collection has already exist";
}
// no free line
if(free.size() == 0) {
throw "you are reach the max limit count of collections";
}
int id = *free.begin();
free.erase(free.begin());
StoragePage page = PageManager::Instance().getPage(id / 32);
id %= 32;
int collectionPage = PageManager::Instance().allocate();
if(name.size() > 28) {
throw "too long name of collection";
}
page.setStringStartFrom(id*32, name.c_str());
page.setIntStartFrom(id*32+28, collectionPage);
page.save();
Collection *col = new Collection(name, collectionPage);
map.insert(make_pair(name, col));
return *col;
}
Collection &Collection::getCollection(const std::string &name) {
if(map.count(name) == 0) {
throw "no such collection";
}
return *map[name];
}

View File

@ -5,9 +5,28 @@
#ifndef INVODB_COLLECTION_H
#define INVODB_COLLECTION_H
#include "file/page_manager.h"
#include "utils/logger.h"
#include "json.h"
#include <map>
#include <set>
#include <algorithm>
#include <cstring>
class Collection {
public:
static void insert(JSON &json);
static void loadCollections();
static Collection& getCollection(const std::string& name);
static Collection& createCollection(const std::string& name);
private:
static std::map<std::string, Collection*> map;
static std::set<int> free;
Collection(const std::string& name,const int& firstPage);
Collection() {}
~Collection() {}
Collection(const Collection&);
Collection& operator=(const Collection&);
};

View File

@ -2,4 +2,11 @@
// Created by YuhangQ on 2021/10/9.
//
#include "json.h"
#include "json.h"
std::string JSON::ToString() {
StringBuffer buffer;
Writer<StringBuffer> writer(buffer);
this->Accept(writer);
return buffer.GetString();
}

View File

@ -7,11 +7,18 @@
#include <string>
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
using namespace rapidjson;
class JSON : public Document {
public:
JSON(std::string json): Document() { this->Parse(json.c_str()); }
JSON(const char *json): Document() { this->Parse(json); }
std::string ToString();
private:
};

59
invodb/utils/logger.h Normal file
View File

@ -0,0 +1,59 @@
//
// Created by YuhangQ on 2021/10/22.
//
#ifndef INVODB_LOGGER_H
#define INVODB_LOGGER_H
#include <iostream>
#include <string>
class Logger {
public:
template<typename T>
static void info(const T& msg);
template<typename T, typename K>
static void info(const T& first, const K& second);
template<typename T>
static void warn(const T& msg);
template<typename T, typename K>
static void warn(const T& first, const K& second);
template<typename T>
static void error(const T& msg);
template<typename T, typename K>
static void error(const T& first, const K& second);
};
template<typename T>
void Logger::info(const T &msg) {
std::cout << "[INFO] " << msg << std::endl;
}
template<typename T, typename K>
void Logger::info(const T &first, const K &second) {
std::cout << "[INFO] " << first << second << std::endl;
}
template<typename T>
void Logger::warn(const T &msg) {
std::cout << "[WARN] " << msg << std::endl;
}
template<typename T, typename K>
void Logger::warn(const T &first, const K &second) {
std::cout << "[WARN] " << first << second << std::endl;
}
template<typename T>
void Logger::error(const T &msg) {
std::cout << "[ERROR] " << msg << std::endl;
}
template<typename T, typename K>
void Logger::error(const T &first, const K &second) {
std::cout << "[ERROR] " << first << second << std::endl;
}
#endif //INVODB_LOGGER_H

22
invodb/utils/uuid.h Normal file
View File

@ -0,0 +1,22 @@
//
// Created by YuhangQ on 2021/10/23.
//
#ifndef INVODB_UUID_H
#define INVODB_UUID_H
#include <iostream>
#include <string>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/uuid/uuid_generators.hpp>
std::string generateUUID() {
boost::uuids::uuid a_uuid = boost::uuids::random_generator()();
std::string uuid_string = boost::uuids::to_string(a_uuid);
std::remove(uuid_string.begin(), uuid_string.end(), '-');
uuid_string.resize(32);
return uuid_string;
}
#endif //INVODB_UUID_H