适配 nodejs

This commit is contained in:
YuhangQ 2021-11-12 15:58:21 +08:00
parent c49cb450ce
commit 458ab0649a
30 changed files with 220 additions and 158 deletions

8
.gitignore vendored
View File

@ -1,3 +1,5 @@
test.invodb
/cmake-build-debug/
.idea
package-lock.json
*.invodb
.vscode
node_modules
build

8
.idea/.gitignore generated vendored
View File

@ -1,8 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

1
.idea/.name generated
View File

@ -1 +0,0 @@
InvoDB

2
.idea/InvoDB.iml generated
View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module classpath="CMake" type="CPP_MODULE" version="4" />

4
.idea/misc.xml generated
View File

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
</project>

8
.idea/modules.xml generated
View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/InvoDB.iml" filepath="$PROJECT_DIR$/.idea/InvoDB.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml generated
View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@ -1,14 +0,0 @@
cmake_minimum_required(VERSION 3.16.3)
project(InvoDB)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0")
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/collection/collection.cpp invodb/collection/collection.h invodb/file/storage_page.cpp invodb/file/storage_page.h invodb/utils/logger.h invodb/utils/uuid.h invodb/btree/node.h invodb/btree/btree.h invodb/btree/list.h invodb/collection/query.cpp invodb/utils/cache.h invodb/collection/index.cpp)

27
binding.gyp Normal file
View File

@ -0,0 +1,27 @@
{
"targets": [
{
"target_name": "core",
"sources": [
"./src/collection/collection.cpp",
"./src/collection/index.cpp",
"./src/collection/query.cpp",
"./src/file/page_manager.cpp",
"./src/file/storage_page.cpp",
"./src/main.cpp",
],
"include_dirs": [
"<!@(node -p \"require('node-addon-api').include\")"
],
"dependencies": [
"<!(node -p \"require('node-addon-api').gyp\")"
],
"cflags!": ["-fno-exceptions"],
"cflags_cc!": ["-fno-exceptions"],
"defines": ["NAPI_CPP_EXCEPTIONS"],
"xcode_settings": {
"GCC_ENABLE_CPP_EXCEPTIONS": "YES"
}
}
]
}

21
demo/test.js Normal file
View File

@ -0,0 +1,21 @@
const invodb = require('..')
invodb.database('zzz.invodb')
let col = invodb.colection('blog')
if(!col.exist()) col.create();
col.insert({ id: 1, title: "第一篇文章", author: "YuhangQ"})
col.insert({ id: 2, title: "第二篇文章", author: "Ciel"})
col.insert({ id: 3, title: "第三篇文章", author: "YuhangQ"})
col.insert({ id: 4, title: "第四篇文章", author: "By"})
let result = col.query({
id: {
$gte: 2,
$lte: 3
},
author: "YuhangQ"
})
console.log(result)

38
index.js Normal file
View File

@ -0,0 +1,38 @@
const core = require("./build/Release/core.node");
function database(filename) {
core.database(filename);
}
function colection(collectionName) {
function exist() { return core.exists(collectionName); }
function create() { core.create(collectionName); }
function insert(object) {
if(!core.exists(collectionName)) throw `Collection ${collectionName} doesn't exists!`;
let json = JSON.stringify(object);
core.insert(collectionName, json);
}
function remove(object) {
if(!core.exists(collectionName)) throw `Collection ${collectionName} doesn't exists!`;
let json = JSON.stringify(object);
core.remove(collectionName, json);
}
function query(object) {
if(!core.exists(collectionName)) throw `Collection ${collectionName} doesn't exists!`;
let json = JSON.stringify(object);
return core.query(collectionName, json);
}
return {
exist: exist,
create: create,
insert: insert,
remove: remove,
query: query
}
}
module.exports = {
database: database,
colection: colection
};

24
package.json Normal file
View File

@ -0,0 +1,24 @@
{
"name": "invodb",
"version": "1.0.0",
"description": "a nosql json document database",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"install": "node-gyp rebuild"
},
"repository": {
"type": "git",
"url": "git+https://github.com/YuhangQ/InvoDB.git"
},
"author": "",
"license": "ISC",
"gypfile": true,
"bugs": {
"url": "https://github.com/YuhangQ/InvoDB/issues"
},
"homepage": "https://github.com/YuhangQ/InvoDB#readme",
"dependencies": {
"node-addon-api": "^4.2.0"
}
}

View File

@ -5,8 +5,8 @@
#ifndef INVODB_BTREE_H
#define INVODB_BTREE_H
#include "btree/node.h"
#include "utils/uuid.h"
#include "node.h"
#include "../utils/uuid.h"
#define M_SIZE 1000 / (K_SIZE + 4)

View File

@ -13,8 +13,8 @@
#include <algorithm>
#include <map>
#include <type_traits>
#include "file/page_manager.h"
#include "invodb/utils/cache.h"
#include "../file/page_manager.h"
#include "../utils/cache.h"
template<int M_SIZE, typename KT, int K_SIZE>
class BTreeNode {

View File

@ -27,6 +27,10 @@ Collection& Collection::createCollection(const std::string &name) {
return *col;
}
bool Collection::existsCollection(const std::string& name) {
return map.count(name) != 0;
}
Collection &Collection::getCollection(const std::string &name) {
if(map.count(name) == 0) {
throw "no such collection";
@ -55,7 +59,7 @@ void Collection::insert(nlohmann::json &json) {
int add = PageManager::Instance().saveJSONToFile(json);
uuid->insert(id, add);
//Logger::info<std::string, std::string>("INSERT ", json.dump());
Logger::info<std::string, std::string>("INSERT ", json.dump());
// add index
indexJSON("", json, add);

View File

@ -5,16 +5,16 @@
#ifndef INVODB_COLLECTION_H
#define INVODB_COLLECTION_H
#include "file/page_manager.h"
#include "utils/logger.h"
#include "btree/btree.h"
#include "json/json.hpp"
#include "../file/page_manager.h"
#include "../utils/logger.h"
#include "../btree/btree.h"
#include "../json/json.hpp"
#include <map>
#include <set>
#include <algorithm>
#include <cstring>
#include "utils/uuid.h"
#include "btree/list.h"
#include "../utils/uuid.h"
#include "../btree/list.h"
class Collection {
public:
@ -23,6 +23,7 @@ public:
std::vector<nlohmann::json> query(const nlohmann::json &json);
static void loadCollections();
static Collection& getCollection(const std::string& name);
static bool existsCollection(const std::string& name);
static Collection& createCollection(const std::string& name);
void test();

View File

@ -152,11 +152,11 @@ std::set<nlohmann::json> Collection::innerQuery(const std::string &prefix, const
auto str = json.dump();
printf("query: %s prefix: %s\n", str.c_str(), prefix.c_str());
printf("result: \n");
for(auto it=res.begin(); it!=res.end(); it++) {
printf(" - %s\n", it->dump().c_str());
}
// printf("query: %s prefix: %s\n", str.c_str(), prefix.c_str());
// printf("result: \n");
// for(auto it=res.begin(); it!=res.end(); it++) {
// printf(" - %s\n", it->dump().c_str());
// }
return res;
}
@ -267,7 +267,7 @@ std::set<nlohmann::json>
Collection::queryNumber(const std::string &prefix, const double &minValue, const double &maxValue, const int &mod) {
std::set<nlohmann::json> res;
auto treeName = prefix + "$number";
printf(">>>> %s %f %f\n", prefix.c_str(), minValue, maxValue);
//printf(">>>> %s %f %f\n", prefix.c_str(), minValue, maxValue);
if(!index->exists(treeName)) {
return res;

View File

@ -3,10 +3,10 @@
//
#include "page_manager.h"
#include "btree/list.h"
int PageManager::loadDatabase(const char *filename) {
int PageManager::loadDatabase(const char *filename) {
std::ofstream file(filename, std::fstream::out);
file.close();
Instance().stream.open(filename);
Instance().stream.seekp(0, std::ios::end);
int index = Instance().stream.tellp() / 1024;

View File

@ -9,12 +9,9 @@
#include <fstream>
#include <map>
#include "../json/json.hpp"
#include "../utils/cache.h"
#include "storage_page.h"
#include "json/json.hpp"
#include "invodb/utils/cache.h"
template<typename T, int T_SIZE>
class List;
class PageManager {
public:

View File

@ -62,6 +62,8 @@ int StoragePage::getAddress() {
}
StoragePage::StoragePage() {
printf("aha!\n");
memset(page, 0, sizeof(page));
}

69
src/main.cpp Normal file
View File

@ -0,0 +1,69 @@
//
// Created by YuhangQ on 2021/9/24.
//
#include "main.h"
#include <napi.h>
using namespace Napi;
void database(const CallbackInfo& info) {
std::string filename = info[0].As<String>();
PageManager::loadDatabase(filename.c_str());
Collection::loadCollections();
}
Boolean exists(const CallbackInfo& info) {
std::string colName = info[0].As<String>();
return Boolean::New(info.Env(), Collection::existsCollection(colName));
}
void create(const CallbackInfo& info) {
std::string colName = info[0].As<String>();
Collection::createCollection(colName);
}
void insert(const CallbackInfo& info) {
std::string colName = info[0].As<String>();
std::string json = info[1].As<String>();
auto j = nlohmann::json::parse(json);
Collection::getCollection(colName).insert(j);
}
Array query(const CallbackInfo& info) {
std::string colName = info[0].As<String>();
std::string json = info[1].As<String>();
auto j = nlohmann::json::parse(json);
auto result = Collection::getCollection(colName).query(j);
auto res = Array::New(info.Env(), result.size());
for(int i=0; i<result.size(); i++) {
res.Set(i, String::New(info.Env(), result[i].dump()));
}
return res;
}
void _remove(const CallbackInfo& info) {
std::string colName = info[0].As<String>();
std::string json = info[1].As<String>();
auto j = nlohmann::json::parse(json);
Collection::getCollection(colName).remove(j);
}
Object Init(Env env, Object exports) {
srand(time(0));
exports.Set("database", Function::New(env, database));
exports.Set("exists", Function::New(env, exists));
exports.Set("create", Function::New(env, create));
exports.Set("insert", Function::New(env, insert));
exports.Set("query", Function::New(env, query));
exports.Set("remove", Function::New(env, _remove));
return exports;
}
NODE_API_MODULE(core, Init)

View File

@ -1,11 +1,9 @@
//
// Created by YuhangQ on 2021/9/24.
//
#include "main.h"
void testAndBenchmark(int n);
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <vector>
#include "../collection/collection.h"
#include "../btree/list.h"
Collection *col;
@ -53,84 +51,6 @@ void terminal() {
}
}
int main() {
int t = time(0);
srand(1635418590);
//srand(t);
printf("seed: %d\n", t);
system("rm -rf test.invodb && touch test.invodb");
PageManager::loadDatabase("test.invodb");
Collection::loadCollections();
PageManager& manager = PageManager::Instance();
try {
col = &Collection::getCollection("hello");
} catch(const char *error) {
Collection::createCollection("hello");
col = &Collection::getCollection("hello");
}
// nlohmann::json j = nlohmann::json::parse(R"(
//{
// "title" : "MongoDB 教程",
// "description" : "MongoDB 是一个 Nosql 数据库",
// "by" : "菜鸟教程",
// "url" : "http://www.runoob.com",
// "tags" : [
// "mongodb",
// "database",
// "NoSQL"
// ],
// "likes" : 100
//}
// )");
//
// col->insert(j);
//
// col->query(nlohmann::json::parse(R"(
//{
// "likes": {"$gt":50},
// "$or": [
// {"by": "菜鸟教程"},
// {"title": "MongoDB 教程"}
// ]
//}
// )"));
terminal();
// freopen("qq.txt", "r", stdin);
// const int n = 1000000;
// char qq[100], phone[100];
//
// clock_t start = clock();
// for(int i=0; i<n; i++) {
// scanf("%s%s", qq, phone);
// nlohmann::json json;
// json["qq"] = qq;
// json["phone"] = phone;
// col->insert(json);
//
// if(i % (n/1000) == 0) {
// printf("[%d/%d] time=%fs!\n", i, n, (double)(clock() - start) / CLOCKS_PER_SEC);
// start = clock();
// }
// }
//col->test();
//testAndBenchmark(20000);
return 0;
}
void testAndBenchmark(int n) {

View File

@ -7,7 +7,7 @@
#include <list>
#include <map>
#include "invodb/file/storage_page.h"
#include "../file/storage_page.h"
template<typename KT, typename VT>
class LRUCache {