⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jnicli.cpp

📁 最新版本!fastdb是高效的内存数据库系统
💻 CPP
📖 第 1 页 / 共 3 页
字号:
#define _JNI_IMPLEMENTATION_ 1
#include <jni.h>

#include "fastdb.h"
#include "localcli.h"

static cli_var_type const cliTypeMap[] = {
    cli_oid, 
    cli_bool,   // TP_BOOL
    cli_int2,   // TP_CHAR
    cli_int1,   // TP_INT1
    cli_int2,   // TP_INT2
    cli_int4,   // TP_INT4
    cli_int8,   // TP_INT8
    cli_real4,  // TP_REAL4
    cli_real8,  // TP_REAL8
    cli_asciiz, // TP_STRING
    cli_int8,   // TP_DATE 
    cli_array_of_bool, // TP_BOOL_ARRAY
    cli_array_of_int2, // TP_CHAR_ARRAY
    cli_array_of_int1, // TP_INT1_ARRAY
    cli_array_of_int2, // TP_INT2_ARRAY
    cli_array_of_int4, // TP_INT4_ARRAY
    cli_array_of_int8, // TP_INT8_ARRAY
    cli_array_of_real4, // TP_REAL4_ARRAY
    cli_array_of_real8, // TP_REAL8_ARRAY
    cli_array_of_string, // TP_STRING_ARRAY
};

typedef char* charptr;
struct _abool { char n; bool v; };
struct _achar { char n; char v; };
struct _ajchar { char n; jchar v; };
struct _ajbyte { char n; jbyte v; };
struct _ajshort { char n; jshort v; };
struct _ajint { char n; jint v; };
struct _ajlong { char n; jlong v; };
struct _ajfloat { char n; jfloat v; };
struct _ajdouble { char n; jdouble v; };
struct _acharptr { char n; charptr v; };
struct _acli_array_t { char n; cli_array_t v; };

#define ALIGNOF(type) offsetof(_a##type, v)
#define SIZE_AND_ALIGNMENT(type) sizeof(type), ALIGNOF(type)
#define APPEND_FIXED(type) appendFixed(SIZE_AND_ALIGNMENT(type))

inline char const* getStringBody(JNIEnv* env, jstring str) {
    return env->GetStringUTFChars(str, 0);
}

inline void releaseStringBody(JNIEnv* env, jstring str, char const* body) {
    env->ReleaseStringUTFChars(str, body);
}

inline int getStringLength(JNIEnv* env, jstring str) {
    return env->GetStringUTFLength(str);
}

inline jstring newString(JNIEnv* env, char const* body) {
    return env->NewStringUTF(body);
}

class ClassDescriptor {
  public:
    int nColumns;
    cli_field_descriptor* columns;
    char*                 names;

    ~ClassDescriptor() { 
        delete[] columns;
        delete[] names;
    }
};

const size_t VARYING_BLOCK_SIZE = 1024;

struct VaryingBlock { 
    VaryingBlock* next;
    char          data[1];
};

class ObjectBuffer {
    dbSmallBuffer fixedPart;
    VaryingBlock* varyingPart;
    size_t fixedPos;
    size_t varyingPos;

  public:
    void* base() {
        return fixedPart.base();
    }

    ObjectBuffer() { 
        fixedPos = 0;
        varyingPos = 0;
        varyingPart = NULL;
    }

    ~ObjectBuffer() { 
        VaryingBlock *curr, *next;
        for (curr = varyingPart; curr != NULL; curr = next) { 
            next = curr->next;
            dbFree(curr);
        }
    }

    void* appendFixed(size_t size, size_t alignment) { 
        fixedPos = DOALIGN(fixedPos, alignment);
        fixedPart.put(fixedPos + size);
        void* ptr = fixedPart.base() + fixedPos;
        fixedPos += size;
        return ptr;
    }

    void* appendVarying(size_t nElems, size_t elemSize, size_t elemAlignment) { 
        varyingPos = DOALIGN(varyingPos, elemAlignment);
        size_t size = nElems*elemSize;
        void* ptr;
        if (varyingPart != NULL && varyingPos + size <= VARYING_BLOCK_SIZE) { 
            ptr = &varyingPart->data[varyingPos];
            varyingPos += size;
        } else {
            VaryingBlock* blk = (VaryingBlock*)
                dbMalloc(sizeof(VaryingBlock*) + (size < VARYING_BLOCK_SIZE ? VARYING_BLOCK_SIZE : size));
            blk->next = varyingPart;
            varyingPart = blk;
            ptr = varyingPart->data;
            varyingPos = size;
        }
        return ptr;
    }
};

class JniResultSet {
  public:
    byte*  record;
    size_t pos;
    dbAnyCursor cursor;
    bool   first;

    JniResultSet(dbTableDescriptor* desc) 
    : record(new byte[desc->size()]), pos(0), cursor(*desc, dbCursorViewOnly, record), first(true)
    {
        memset(record, 0, desc->size());
        cursor.reset();
    }

    int size() { 
        return cursor.getNumberOfRecords();
    }

    oid_t next() {
        pos = 0;
        if (first) { 
            if (cursor.isEmpty()) { 
                delete this;
                return 0;
            }
            first = false;
        } else if (!cursor.gotoNext()) {
            delete this;
            return 0;
        }
        cursor.fetch();
        return cursor.currId;
    }

    jbyte nextByte() { 
        return (jbyte)record[pos++];
    }

    jshort nextShort() { 
        pos = DOALIGN(pos, ALIGNOF(jshort));
        jshort val = *(jshort*)(record + pos);
        pos += sizeof(jshort);
        return val;
    }

    jint nextInt() { 
        pos = DOALIGN(pos, ALIGNOF(jint));
        jint val = *(jint*)(record + pos);
        pos += sizeof(jint);
        return val;
    }

    jlong nextLong() { 
        pos = DOALIGN(pos, ALIGNOF(jlong));
        jlong val = *(jlong*)(record + pos);
        pos += sizeof(jlong);
        return val;
    }

    jstring nextString(JNIEnv* env) { 
        pos = DOALIGN(pos, ALIGNOF(charptr));
        jstring val = newString(env, *(char**)(record + pos));
        pos += sizeof(char*);
        return val;
    }
       
    jbooleanArray nextBoolArray(JNIEnv* env) { 
        pos = DOALIGN(pos, ALIGNOF(cli_array_t));
        cli_array_t* arr = (cli_array_t*)(record + pos);
        jbooleanArray val = env->NewBooleanArray(arr->size);
        env->SetBooleanArrayRegion(val, 0, arr->size, (jboolean*)arr->data);
        pos += sizeof(cli_array_t);
        return val;
    }

    jcharArray nextCharArray(JNIEnv* env) { 
        pos = DOALIGN(pos, ALIGNOF(cli_array_t));
        cli_array_t* arr = (cli_array_t*)(record + pos);
        jcharArray val = env->NewCharArray(arr->size);
        env->SetCharArrayRegion(val, 0, arr->size, (jchar*)arr->data);
        pos += sizeof(cli_array_t);
        return val;
    }

    jbyteArray nextByteArray(JNIEnv* env) { 
        pos = DOALIGN(pos, ALIGNOF(cli_array_t));
        cli_array_t* arr = (cli_array_t*)(record + pos);
        jbyteArray val = env->NewByteArray(arr->size);
        env->SetByteArrayRegion(val, 0, arr->size, (jbyte*)arr->data);
        pos += sizeof(cli_array_t);
        return val;
    }
       
    jshortArray nextShortArray(JNIEnv* env) { 
        pos = DOALIGN(pos, ALIGNOF(cli_array_t));
        cli_array_t* arr = (cli_array_t*)(record + pos);
        jshortArray val = env->NewShortArray(arr->size);
        env->SetShortArrayRegion(val, 0, arr->size, (jshort*)arr->data);
        pos += sizeof(cli_array_t);
        return val;
    }
       
    jintArray nextIntArray(JNIEnv* env) { 
        pos = DOALIGN(pos, ALIGNOF(cli_array_t));
        cli_array_t* arr = (cli_array_t*)(record + pos);
        jintArray val = env->NewIntArray(arr->size);
        env->SetIntArrayRegion(val, 0, arr->size, (jint*)arr->data);
        pos += sizeof(cli_array_t);
        return val;
    }

    jlongArray nextLongArray(JNIEnv* env) { 
        pos = DOALIGN(pos, ALIGNOF(cli_array_t));
        cli_array_t* arr = (cli_array_t*)(record + pos);
        jlongArray val = env->NewLongArray(arr->size);
        env->SetLongArrayRegion(val, 0, arr->size, (jlong*)arr->data);
        pos += sizeof(cli_array_t);
        return val;
    }

    jfloatArray nextFloatArray(JNIEnv* env) { 
        pos = DOALIGN(pos, ALIGNOF(cli_array_t));
        cli_array_t* arr = (cli_array_t*)(record + pos);
        jfloatArray val = env->NewFloatArray(arr->size);
        env->SetFloatArrayRegion(val, 0, arr->size, (jfloat*)arr->data);
        pos += sizeof(cli_array_t);
        return val;
    }

    jdoubleArray nextDoubleArray(JNIEnv* env) { 
        pos = DOALIGN(pos, ALIGNOF(cli_array_t));
        cli_array_t* arr = (cli_array_t*)(record + pos);
        jdoubleArray val = env->NewDoubleArray(arr->size);
        env->SetDoubleArrayRegion(val, 0, arr->size, (jdouble*)arr->data);
        pos += sizeof(cli_array_t);
        return val;
    }

    jobjectArray nextStringArray(JNIEnv* env) { 
        pos = DOALIGN(pos, ALIGNOF(cli_array_t));
        cli_array_t* arr = (cli_array_t*)(record + pos);
        int size = (int)arr->size;
        jobjectArray val = env->NewObjectArray(size, env->FindClass("java/lang/String"), NULL);
        char** spp = (char**)arr->data;
        for (int i = 0; i < size; i++) {
            env->SetObjectArrayElement(val, i, newString(env, spp[i]));
        }
        pos += sizeof(cli_array_t);
        return val;
    }

    ~JniResultSet() { 
        delete[] record;
    }
};

class JniDatabase : public dbDatabase {
  private:
    oid_t   tableId;
    oid_t   nextTableId;
    JNIEnv* env;

  public:
    JniDatabase(JNIEnv* env, dbAccessType type, size_t poolSize) 
    : dbDatabase(type, poolSize)
    {
        this->env = env;
    }

    virtual void handleError(dbErrorClass error, char const* msg, int arg = 0) {
        jclass cls = env->FindClass("jnicli/CliException");
        if (cls != NULL) { 
            env->ThrowNew(cls, msg);        
        }
    }

    void open(char const* databaseName, char const* databasePath, int transactionCommitDelay)
    {
        if (!dbDatabase::open(databaseName, databasePath, transactionCommitDelay)) {
            handleError(dbDatabase::DatabaseOpenError, "Failed to open database");
            return;
        }
        dbTable* table = (dbTable*)getRow(dbMetaTableId);
        dbTableDescriptor* metatable = new dbTableDescriptor(table);
        linkTable(metatable, dbMetaTableId);
        oid_t tid = table->firstRow;
        nextTableId = tid;
        while (tid != 0) {
            table = (dbTable*)getRow(tid);
            dbTableDescriptor* desc = new dbTableDescriptor(table);
            linkTable(desc, tid);
            desc->setFlags();
            tid = table->next;
        }
    }  

    jstring nextTable() {
        tableId = nextTableId;
        if (tableId == 0) { 
            if (!completeDescriptorsInitialization()) {
                close();
                handleError(dbDatabase::DatabaseOpenError, "Referenced table not found");
            }
            return NULL;
        }
        dbTable* table = (dbTable*)getRow(tableId);
        jstring name = newString(env, (char*)((byte*)table + table->name.offs));
        nextTableId = table->next;
        return name;
    }

    dbTableDescriptor* createTable(char const* name, ClassDescriptor* clsDesc) {
        beginTransaction(dbExclusiveLock);
        dbTableDescriptor* tableDesc = NULL;
        int rc = dbCLI::create_table(this, name, clsDesc->nColumns, clsDesc->columns);
        if (rc == cli_unsupported_type) {
            handleError(dbDatabase::DatabaseOpenError, "Unsupported table field type");
            return NULL;
        }
        return findTableByName(name);
    }
        
    dbTableDescriptor* updateTable(char const* name, ClassDescriptor* clsDesc) {
        beginTransaction(dbExclusiveLock);
        int rc = dbCLI::alter_table(this, name, clsDesc->nColumns, clsDesc->columns);
        if (rc == cli_unsupported_type) {
            handleError(dbDatabase::DatabaseOpenError, "Unsupported table field type");
            return NULL;
        }
        return findTableByName(name);
    }

    oid_t insert(dbTableDescriptor* desc, ObjectBuffer* buf) { 
        dbAnyReference ref;
        char** ptr = (char**)buf->base();
        insertRecord(desc, &ref, buf->base());
        return ref.getOid();
    }

            
    JniResultSet* select(dbTableDescriptor* desc, char const* query) { 
        JniResultSet* rs = new JniResultSet(desc);        
        rs->cursor.select(query, dbCursorViewOnly, NULL);
        return rs;
    }
            

    void update(oid_t oid, dbTableDescriptor* desc, ObjectBuffer* buf) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -