mirror of
https://github.com/YuhangQ/InvoDB.git
synced 2025-01-26 06:30:57 +00:00
创建 collection
This commit is contained in:
parent
2c318faf40
commit
6cb59287d7
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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() {}
|
||||
|
56
invodb/file/storage_page.cpp
Normal file
56
invodb/file/storage_page.cpp
Normal 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);
|
||||
}
|
||||
|
36
invodb/file/storage_page.h
Normal file
36
invodb/file/storage_page.h
Normal 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
|
@ -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] };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
@ -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;
|
||||
}
|
@ -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
|
||||
|
@ -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];
|
||||
}
|
||||
|
||||
|
@ -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&);
|
||||
};
|
||||
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
59
invodb/utils/logger.h
Normal 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
22
invodb/utils/uuid.h
Normal 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
|
Loading…
x
Reference in New Issue
Block a user