Skip to content

Feature/array map #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
FROM trzeci/emscripten

30 changes: 30 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// For format details, see https://aka.ms/vscode-remote/devcontainer.json or the definition README at
{
"name": "rocksdb-ts project",
"dockerFile": "Dockerfile",
"runArgs": [
// Uncomment the next line to use a non-root user. On Linux, this will prevent
// new files getting created as root, but you may need to update the USER_UID
// and USER_GID in .devcontainer/Dockerfile to match your user if not 1000.
// "-u", "vscode",
"--cap-add=SYS_PTRACE",
"--security-opt",
"seccomp=unconfined"
],

// Use 'settings' to set *default* container specific settings.json values on container create.
// You can edit these settings after create using File > Preferences > Settings > Remote.
"settings": {
"terminal.integrated.shell.linux": "/bin/bash"
},

// Uncomment the next line if you want to publish any ports.
// "appPort": [],

// Add the IDs of extensions you want installed when the container is created in the array below.
"extensions": [
"ms-vscode.cpptools",
"austin.code-gnu-global",
"ms-vscode.vscode-typescript-tslint-plugin"
]
}
4 changes: 4 additions & 0 deletions binding-using-embind/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env bash
ROCKSDB_INCLUDE=/workspaces/rocksdb-ts/deps/rocksdb/rocksdb/include
ROCKSDB_INCLUDE2=/workspaces/rocksdb-ts/deps/rocksdb/rocksdb
em++ --bind -I$ROCKSDB_INCLUDE -I$ROCKSDB_INCLUDE2 -s WASM=1 -s ERROR_ON_UNDEFINED_SYMBOLS=0 -s EXPORTED_FUNCTIONS="['rocksdb_options_create']" -s EXTRA_EXPORTED_RUNTIME_METHODS='["cwrap"]' -s EMULATE_FUNCTION_POINTER_CASTS=1 -s ASSERTIONS=1 -s LINKABLE=1 -s DEMANGLE_SUPPORT=1 -s EXPORT_ALL=1 -O3 rocksdb.cpp ../deps/rocksdb/rocksdb/db/c.cc
18 changes: 18 additions & 0 deletions binding-using-embind/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
'use strict';
const m = require("./a.out.js");


m.onRuntimeInitialized = _ => {
console.log(m.Rocksdb);

const options = m.cwrap('rocksdb_options_create', 'number', []);

var x = new m.Rocksdb();
// var o = x.getOptions();
// var mm = m.rocksdb_options_create();
var mm = options();
console.log(mm);
// console.log(x, o);
// console.log(m.exclaim("hello world"));
};

51 changes: 51 additions & 0 deletions binding-using-embind/rocksdb.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#include <string>
#include <iostream>
#include <rocksdb/db.h>
#include <rocksdb/convenience.h>
#include <rocksdb/write_batch.h>
#include <rocksdb/cache.h>
#include <rocksdb/filter_policy.h>
#include <rocksdb/cache.h>
#include <rocksdb/comparator.h>
#include <rocksdb/env.h>
#include <rocksdb/options.h>
#include <rocksdb/table.h>
#include <rocksdb/c.h>
#include <emscripten/bind.h>
#include <algorithm>

using namespace rocksdb;
using namespace emscripten;

class Rocksdb {
private:
DB* db;
public:
Rocksdb() {}
Status Open(const Options& options, const std::string& name) {
return DB::Open(options, name, &this->db);
}
Options * getOptions() {
return new Options();
}
~Rocksdb() {}
};

EMSCRIPTEN_BINDINGS(rocksdbM) {
// value_object<rocksdb_options_t>("rocksdb_options_t")
// .field("rep", &rocksdb_options_t::rep);

class_<Status>("Status")
.constructor()
.function("ok", &Status::ok);
class_<Rocksdb>("Rocksdb")
.constructor<>()
.function("Open", &Rocksdb::Open)
.function("getOptions", &Rocksdb::getOptions, allow_raw_pointers());

function("rocksdb_options_create", &rocksdb_options_create, allow_raw_pointers());



}

1 change: 1 addition & 0 deletions generate-bindings/c.h.json

Large diffs are not rendered by default.

109 changes: 109 additions & 0 deletions generate-bindings/cindex-dump.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#!/usr/bin/env python
import json
#===- cindex-dump.py - cindex/Python Source Dump -------------*- python -*--===#
#
# The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
#===------------------------------------------------------------------------===#

from clang.cindex import CursorKind

#import CursorKind from clang.cindex.CursorKind

"""
A simple command line tool for dumping a source file using the Clang Index
Library.
"""

def get_diag_info(diag):
return { 'severity' : diag.severity,
'location' : diag.location,
'spelling' : diag.spelling,
'ranges' : diag.ranges,
'fixits' : diag.fixits }

def get_cursor_id(cursor, cursor_list = []):
if not opts.showIDs:
return None

if cursor is None:
return None

# FIXME: This is really slow. It would be nice if the index API exposed
# something that let us hash cursors.
for i,c in enumerate(cursor_list):
if cursor == c:
return i
cursor_list.append(cursor)
return len(cursor_list) - 1

def get_info(node, depth=0):
f_args=[]
f_result={}

if opts.maxDepth is not None and depth >= opts.maxDepth:
children = None
else:
children = [get_info(c, depth+1)
for c in node.get_children()]

if node.kind == CursorKind.FUNCTION_DECL:
for func_arg in node.get_children():
f_args.append({
'displayname': func_arg.displayname,
'kind': func_arg.kind.__repr__(),
'type': func_arg.type.kind.__repr__(),
'spelling': func_arg.type.spelling
})
f_result = {
'kind' : node.result_type.kind.__repr__(),
'spelling': node.result_type.spelling
}
return { 'id' : get_cursor_id(node).__str__(),
'kind' : node.kind.__repr__(),
'usr' : node.get_usr(),
'f_args' : f_args,
'f_result': f_result,
'spelling': node.spelling,
'is_definition' : node.is_definition(),
'definition id' : get_cursor_id(node.get_definition()),
'children' : children }

def main():
from clang.cindex import Index
from pprint import pprint

from optparse import OptionParser, OptionGroup

global opts

parser = OptionParser("usage: %prog [options] {filename} [clang-args*]")
parser.add_option("", "--show-ids", dest="showIDs",
help="Compute cursor IDs (very slow)",
action="store_true", default=False)
parser.add_option("", "--max-depth", dest="maxDepth",
help="Limit cursor expansion to depth N",
metavar="N", type=int, default=None)
parser.disable_interspersed_args()
(opts, args) = parser.parse_args()

if len(args) == 0:
parser.error('invalid number arguments')

index = Index.create()
tu = index.parse(None, args)
if not tu:
parser.error("unable to load input")

# pprint(('diags', map(get_diag_info, tu.diagnostics)))

# print(get_info(tu.cursor));

print(json.dumps(get_info(tu.cursor)) )

if __name__ == '__main__':
main()

37 changes: 37 additions & 0 deletions generate-bindings/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
const rocksdb_c_api_data = require("./c.h.json");

const functions = rocksdb_c_api_data
.children
.filter((d) => d.kind === "CursorKind.FUNCTION_DECL");


console.log("functions");
functions.forEach((v) => {
console.log(v.spelling);
});

console.log("types");
let types = new Set([]);
functions.forEach((v) => {
types = new Set([
...types,
...v.f_args.map(({ type }) => type)
]);
});

types.forEach((x) => {
console.log(x);
})

console.log("ctypes");
let ctypes = new Set([]);
functions.forEach((v) => {
ctypes = new Set([
...ctypes,
...v.f_args.map(({ spelling }) => spelling)
]);
});

ctypes.forEach((x) => {
console.log(x);
})
15 changes: 15 additions & 0 deletions generate-bindings/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "generate-bindings",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {

}
}
34 changes: 34 additions & 0 deletions src/RocksDbArray.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Unique, ReadOptionsContext, lib } from "./binding";
import { rockdbIterator, getEntry } from "./common";

export class RocksDbArray<T> implements ArrayLike<T> {
public rocksdbOpts: any = null;
public db: any = null;
public arr = [];

constructor(public location: string, public options: string) {
this.rocksdbOpts = lib.rocksdb_options_init_from_buffer(Buffer.from(options));
this.db = lib.rocksdb_open(Buffer.from(location, "utf-8"), this.rocksdbOpts);

return new Proxy(this, {
get(target: RocksDbArray<T>, key: any, receiver: any): T {
const arrIndex = typeof (key) === "number" && Number.isInteger(key) && key >= 0;
if (arrIndex) {
return target.arr[key];
}
else {
return target[key];
}
},
set(target: RocksDbArray<T>, key: PropertyKey, value: any, receiver: any): boolean {
const arrIndex = typeof (key) === "number" && Number.isInteger(key) && key >= 0;

return true;
}
});
}
public get length(): number {
return 0;
}
readonly [n: number]: T;
}
44 changes: 44 additions & 0 deletions src/RocksDbMap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Unique, ReadOptionsContext, lib } from "./binding";
import { rockdbIterator, getEntry } from "./common";

export class RocksDbMap<K, V> implements Map<K, V> {
public rocksdbOpts: any = null;
public db: any = null;
constructor(public location: string, public options: string) {
this.rocksdbOpts = lib.rocksdb_options_init_from_buffer(Buffer.from(options));
this.db = lib.rocksdb_open(Buffer.from(location, "utf-8"), this.rocksdbOpts);
}
public [Symbol.toStringTag] = "RocksDbMap";
public [Symbol.iterator](): IterableIterator<[K, V]> {
return [][Symbol.iterator]();
}
public entries(rOpts?: Unique<ReadOptionsContext>): IterableIterator<[K, V]>;
public entries(rOpts?: Unique<ReadOptionsContext>, startKey?: any): IterableIterator<[K, V]> {
return rockdbIterator(this.db, rOpts || lib.rocksdb_read_options_init(), startKey, getEntry);
}
public keys(): IterableIterator<K> {
return [][Symbol.iterator]();
}
public values(): IterableIterator<V> {
return [][Symbol.iterator]();
}
public clear(): void {
return void 0;
}
public delete(key: K): boolean {
return true;
}
public forEach(callbackfn: (value: V, key: K, map: Map<K, V>) => void, thisArg?: any): void {
return void 0;
}
public get(key: K): V | undefined {
return undefined;
}
public has(key: K): boolean {
return true;
}
public set(key: K, value: V): this {
return this;
}
public readonly size: number = 0;
}
5 changes: 5 additions & 0 deletions src/binding.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import path from 'path';
import builder from 'node-gyp-build';

export type Callback = (error: Error) => void;
export type CallbackWithValue<V> = (error: Error, value: V) => void;
export type CallbackWithKeyValue<K, V> = (error: Error, key: K, value: V) => void;
Expand Down Expand Up @@ -174,3 +177,5 @@ export interface RocksBinding {
logger_start(): void;
logger_stop(): void;
}

export const lib = builder(path.resolve(path.join(__dirname, '..')));
13 changes: 13 additions & 0 deletions src/common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Unique, ReadOptionsContext, DatabaseContext, IteratorContext, lib } from "./binding";

export const getEntry = (i: Unique<IteratorContext>): any => [lib.rocksdb_iterator_key(i), lib.rocksdb_iterator_value(i)];
const getKey = (i: Unique<IteratorContext>) => lib.rocksdb_iterator_key(i);
const getValue = (i: Unique<IteratorContext>) => lib.rocksdb_iterator_value(i);
export function* rockdbIterator(db: Unique<DatabaseContext>, rOpts: Unique<ReadOptionsContext>, startKey: any, getDataFn = getEntry) {
const i = lib.rocksdb_iterator_init(db, rOpts);
let hasValues = startKey ? lib.rocksdb_iterator_seek(i, startKey) : lib.rocksdb_iterator_seek_for_first(i);
while (hasValues) {
const nextKey = yield getDataFn(i);
hasValues = nextKey ? lib.rocksdb_iterator_seek(i, nextKey) : lib.rocksdb_iterator_next(i);
}
}
Loading