VaKeR CYBER ARMY
Logo of a company Server : Apache/2.4.41 (Ubuntu)
System : Linux absol.cf 5.4.0-198-generic #218-Ubuntu SMP Fri Sep 27 20:18:53 UTC 2024 x86_64
User : www-data ( 33)
PHP Version : 7.4.33
Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Directory :  /var/www/html/keeview_app/html/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /var/www/html/keeview_app/html/jsfcache.js
const fcache = Object.freeze(function () {
    var fcache_retval = {};
    var fcore = {};

    var dbver = 6;
    var debugPrintFlag = false;

    if (navigator.platform !== undefined) {
        if (navigator.platform.toLowerCase() == "iphone") {
            fcore.workMode = "idb";
        }
    }

    if (window.androidfs !== undefined) {
        if (androidfs.support()) {
            fcore.workMode = "android";
        }
    }

    if (fcore.workMode === undefined) {
        fs.support(function (retval) {
            if (retval === true) {
                fcore.workMode = "fsapi";
            }
            else {
                fcore.workMode = "idb";
            }
        });
    }

    fcore.mkdir = function (callbackfunc, core, pathname) {
        if (fcore.workMode === undefined) {
            Thread.wait(
                function () {
                    return fcore.workMode !== undefined;
                },
                function () {
                    Thread.setTimeout({
                        func: fcore.mkdir,
                        args: [callbackfunc, core.dbname, pathname]
                    });
                }
            );
            return;
        }
        switch (fcore.workMode) {
            case "android":
                androidfs.mkdir(core.dbname + "_fsdb_" + pathname, callbackfunc);
                return;
            case "fsapi":
                fs.mkdir(callbackfunc, core.dbname + "_fsdb_" + pathname);
                return;
            case "idb":
                if (core.connectors === undefined) core.connectors = {};
                if (core.connectors[core.dbname] === undefined) {
                    idbfs.open("fsdb_" + core.dbname, function (success, content) {
                        core.connectors[core.dbname] = content;
                        Thread.setTimeout({
                            func: fcore.mkdir,
                            args: [callbackfunc, core, pathname]
                        });
                    });
                    return;
                }
                if (pathname.trim().length == 0) {
                    Thread.setTimeout({
                        func: callbackfunc,
                        args: [true]
                    });
                    return;
                }
                core.connectors[core.dbname].mkdir(pathname, function () {
                    callbackfunc(true);
                });
        }
    }

    fcore.sameArray = function (arr1, arr2) {
        var i;
        if ((arr1 === undefined) && (arr2 !== undefined)) return false;
        if ((arr2 === undefined) && (arr1 !== undefined)) return false;
        if (arr1.length != arr2.length) return false;
        for (i = 0; i < arr1.length; i++) {
            if (arr1[i] != arr2[i]) return false;
        }
        return true;
    }

    fcore.getFormat = function (data) {
        var format = Object.keys(data);
        format.sort();
        return format;
    }

    fcore.fromFormat = function (format, data) {
        var r = [];
        var i;
        for (i = 0; i < format.length; i++) {
            r.push(data[format[i]]);
        }
        return r;
    }

    fcore.toFormat = function (format, data) {
        var r = {};
        var i;
        for (i = 0; i < format.length; i++) {
            r[format[i]] = data[i];
        }
        return r;
    }

    fcore.defaultConfig = function (dbname, fieldList) {
        var r = {
            lastid: 0,
            lastuts: -1,
            fieldList: fieldList,
            chksum: EncodingClass.md5.encode(EncodingClass.string.fromVariable({
                lastid: 0,
                lastuts: -1,
                format: undefined
            }) + "_" + dbname + "_" + dbver)
        };
        return r;
    }

    fcore.resetTable = function (core, tablename, callbackfunc) {
        var options = core.tables[tablename].options;
        var mode = core.tables[tablename].mode;
        var fieldList;
        if (options !== undefined) {
            fieldList = options.fieldList;
        }
        core.tables[tablename] = {
            mode: mode,
            config: fcore.defaultConfig(core.dbname, fieldList),
            data: [],
            options: options,
            c1: 0,
            c2: 0,
            c3: 0
        };
        if (mode == "block") {
            core.tables[tablename].hostdata = [];
            core.tables[tablename].hostmodified = [];
        }
        fcore.resetCache(core, tablename, function () {
            Thread.setTimeout({
                func: core.init,
                args: [tablename, mode, callbackfunc, options]
            });
        });
    }

    fcore.preinit = function (core, tablename, mode, options, callbackfunc, success, content) {
        var fieldList;
        if (options !== undefined) {
            if (options.fieldList !== undefined) {
                options.fieldList.sort();
                fieldList = options.fieldList;
            }
        }
        if (!success) {
            if (debugPrintFlag) console.log("Can not open table " + tablename, content);
            Thread.setTimeout({
                func: callbackfunc,
                args: [false]
            });
            return false;
        }
        core.tables[tablename] = {
            mode: mode,
            config: fcore.defaultConfig(core.dbname, fieldList),
            data: [],
            options: options
        };
        if (mode == "block") {
            core.tables[tablename].hostdata = [];
            core.tables[tablename].hostmodified = [];
        }
        return true;
    }

    fcore.init = function (core, tablename, options, callbackfunc, success, content) {
        var i, keyList = [];
        var keyMark = {};
        if (!success) {
            if (debugPrintFlag) console.log("Can not open table " + tablename, content);
            Thread.setTimeout({
                func: callbackfunc,
                args: [false]
            });
            return;
        }
        for (i = 0; i < content.length; i++) {
            if (content[i].type == "file") {
                keyList.push(content[i].name);
                keyMark[content[i].name] = true;
            }
        }
        if (keyMark["config"] !== undefined) {
            Thread.setTimeout({
                func: core.fetchConfigFromCache,
                args: [keyList, tablename, callbackfunc]
            });
        }
        else {
            Thread.setTimeout({
                func: core.fetchDataFromServer,
                args: [tablename, callbackfunc, 0, 0, 0]
            });
        }
    }

    fcore.fsinit = function (core, dbname) {
        return function (tablename, mode, callbackfunc, options) {
            if (core.inited[tablename] === undefined) core.inited[tablename] = null;
            fcore.mkdir(function (tablename, mode, callbackfunc) {
                return function (success, content) {
                    if (!fcore.preinit(core, tablename, mode, options, callbackfunc, success, content)) return;
                    fs.readDir(function (success, content) {
                        fcore.init(core, tablename, options, callbackfunc, success, content);
                    }, core.dbname + "_fsdb_" + tablename);
                }
            } (tablename, mode, callbackfunc), core, tablename);
        }
    }

    fcore.androidinit = function (core, dbname) {
        return function (tablename, mode, callbackfunc, options) {
            if (core.inited[tablename] === undefined) core.inited[tablename] = null;
            fcore.mkdir(function (tablename, mode, callbackfunc) {
                return function (success, content) {
                    if (!fcore.preinit(core, tablename, mode, options, callbackfunc, success, content)) return;
                    androidfs.readDir(core.dbname + "_fsdb_" + tablename, function (success, content) {
                        fcore.init(core, tablename, options, callbackfunc, success, content);
                    });
                }
            } (tablename, mode, callbackfunc), core, tablename);
        }
    }

    fcore.idbinit = function (core, dbname) {
        return function (tablename, mode, callbackfunc, options) {
            var fieldList;
            if (options !== undefined) {
                fieldList = options.fieldList;
            }
            if (core.inited[tablename] === undefined) core.inited[tablename] = null;
            fcore.mkdir(function (tablename, mode, callbackfunc) {
                return function (success, content) {
                    if (!fcore.preinit(core, tablename, mode, options, callbackfunc, success, content)) return;
                    core.connectors[core.dbname].readDir(tablename, function (content) {
                        fcore.init(core, tablename, options, callbackfunc, true, content);
                    });
                }
            } (tablename, mode, callbackfunc), core, tablename);
        }
    }

    fcore.getTableFields = function (core, tablename, configvalue, callbackfunc) {
        core.apiqueue.push({
            url: core.url,
            params: [
                {
                    name: "task",
                    value: "format"
                },
                {
                    name: "name",
                    value: tablename
                },
                {
                    name: "lastid",
                    value: 0
                },
                {
                    name: "lastuts",
                    value: 0
                }
            ],
            func: function (core, tablename, configvalue, callbackfunc) {
                return function (success, data) {
                    var i, sindex, slen, name, flist, fmark;
                    if (success) {
                        sindex = 0;
                        flist = [];
                        while (sindex < data.length) {
                            slen = EncodingClass.number.fromArray("i32", data, sindex);
                            sindex += 4;
                            name = EncodingClass.string.fromUint8Array(data, sindex, slen);
                            sindex += slen;
                            name = EncodingClass.utf8.decode(name);
                            flist.push(name);
                        }
                        flist.sort();
                        fmark = {};
                        for (i = 0; i < flist.length; i++) {
                            fmark[flist[i]] = true;
                        }
                        if (configvalue.format === undefined) {
                            console.log("format not found [" + tablename + "]");
                            Thread.setTimeout({
                                func: callbackfunc,
                                args: [false, flist, "format not found"]
                            });
                            return;
                        }
                        if (configvalue.fieldList === undefined) {
                            for (i = 0; i < configvalue.format.length; i++) {
                                name = configvalue.format[i];
                                if (fmark[name] === undefined) {
                                    console.log("database changed [" + tablename + "]");
                                    Thread.setTimeout({
                                        func: callbackfunc,
                                        args: [false, flist, "database changed"]
                                    });
                                    return;
                                }
                                delete fmark[name];
                            }
                            if (Object.keys(fmark).length > 0) {
                                console.log("database changed [" + tablename + "]");
                                Thread.setTimeout({
                                    func: callbackfunc,
                                    args: [false, flist, "database changed"]
                                });
                                return;
                            }
                            Thread.setTimeout({
                                func: callbackfunc,
                                args: [true, flist]
                            });
                        }
                        else {
                            for (i = 0; i < configvalue.fieldList.length; i++) {
                                name = configvalue.fieldList[i];
                                if (fmark[name] === undefined) {
                                    console.log("database changed [" + tablename + "]");
                                    Thread.setTimeout({
                                        func: callbackfunc,
                                        args: [false, configvalue.fieldList, "database changed"]
                                    });
                                    return;
                                }
                                delete fmark[name];
                            }
                            Thread.setTimeout({
                                func: callbackfunc,
                                args: [true, configvalue.fieldList]
                            });
                        }
                    }
                    else {
                        Thread.setTimeout({
                            func: fcore.getTableFields,
                            args: [core, tablename, configvalue, callbackfunc],
                            time: 5000
                        });
                    }
                }
            } (core, tablename, configvalue, callbackfunc)
        });
    }

    fcore.resetCache = function (core, tablename, callbackfunc) {
        var pathname, xfunc;
        xfunc = function (callbackfunc) {
            return function () {
                console.log("cache removed [" + tablename + "]");
                callbackfunc();
            }
        } (callbackfunc);
        switch (fcore.workMode) {
            case "android":
                pathname = core.dbname + "_fsdb_" + tablename;
                androidfs.remove(pathname, function () {
                    androidfs.mkdir(pathname, xfunc);
                });
                return;
            case "fsapi":
                pathname = core.dbname + "_fsdb_" + tablename;
                fs.remove(function () {
                    fs.mkdir(xfunc, pathname);
                }, pathname);
                return;
            case "idb":
                core.connectors[core.dbname].remove(tablename, function () {
                    core.connectors[core.dbname].mkdir(tablename, xfunc);
                });
                return;
        }
    }

    fcore.readConfig = function (core, keyList, tablename, callbackfunc, success, value) {
        var ok, i, mark, options;
        if ((!success) || (value === null)) {
            value = {};
        }
        else if (value[0] === null) {
            value = {};
        }
        else if (!value[0].success) {
            value = {};
        }
        else {
            value = EncodingClass.number.toVariable(value[0].content);
        }
        if (value === undefined) value = {};
        if ((value.fieldList === undefined) && (core.tables[tablename].config.fieldList !== undefined)) {
            ok = false;
        }
        else if ((value.fieldList !== undefined) && (core.tables[tablename].config.fieldList === undefined)) {
            ok = false;
        }
        else if (value.fieldList !== undefined) {
            if (value.fieldList.length != core.tables[tablename].config.fieldList.length) {
                ok = false;
            }
            else {
                ok = true;
                mark = {};
                for (i = 0; i < value.fieldList.length; i++) {
                    mark[value.fieldList[i]] = true;
                }
                for (i = 0; i < core.tables[tablename].config.fieldList.length; i++) {
                    if (mark[core.tables[tablename].config.fieldList[i]] === undefined) {
                        ok = false;
                        break;
                    }
                }
                mark = null;
            }
        }
        else {
            ok = true;
        }
        if (ok) {
            ok = ((success) && (keyList.length > 0) && (EncodingClass.md5.encode(EncodingClass.string.fromVariable({
                lastid: value.lastid,
                lastuts: value.lastuts,
                format: value.format
            }) + "_" + core.dbname + "_" + dbver) == value.chksum));
        }
        if (ok) {
            fcore.getTableFields(core, tablename, value, function (success, format, message) {
                if (success) {
                    core.tables[tablename].config = value;
                    core.tables[tablename].config.format = format;
                    Thread.setTimeout({
                        func: core.fetchDataFromCache,
                        args: [keyList, tablename, callbackfunc]
                    });
                }
                else {
                    fcore.resetCache(core, tablename, function () {
                        core.tables[tablename].c1 = 0;
                        core.tables[tablename].c2 = 0;
                        core.tables[tablename].c3 = 0;
                        core.tables[tablename].config.format = format;
                        Thread.setTimeout({
                            func: core.fetchDataFromServer,
                            args: [tablename, callbackfunc, 0, 0, 0]
                        });
                    });
                }
            });
        }
        else {
            options = core.tables[tablename].options;
            fcore.getTableFields(core, tablename, fcore.defaultConfig(core.dbname, value.fieldList), function (success, format, message) {
                fcore.resetCache(core, tablename, function () {
                    core.tables[tablename].c1 = 0;
                    core.tables[tablename].c2 = 0;
                    core.tables[tablename].c3 = 0;
                    core.tables[tablename].options = options;
                    core.tables[tablename].config.format = format;
                    Thread.setTimeout({
                        func: core.fetchDataFromServer,
                        args: [tablename, callbackfunc, 0, 0, 0]
                    });
                });
            });
        }
    }

    fcore.readProcess_block = function (name, retval, callbackfunc) {
        var segno = parseInt(name.substr(1));
        var totallength = 0, xlen = 0;
        var xkey;
        var start, length, offset, edata = [];
        var i, j;
        var v1 = 0, v2 = 0, v3 = 0, uts;
        xkey = [retval[0], retval[1], retval[2], 0];
        ts = EncodingClass.number.rndFunc(0x9E3779B9, 0x243F6A88, 0xB7E15162, EncodingClass.number.fromArray("i32", xkey));
        for (i = 3; (i < retval.length) && (i < 5); i++) {
            retval[i] ^=  ts(256);
        }
        if (EncodingClass.number.fromArray("i16", retval, 3) != dbver) {
            callbackfunc({
                type: "remove",
                content: "invalid dbver"
            });
            return;
        }
        for (i = 5; i < retval.length; i++) {
            retval[i] ^=  ts(256);
        }
        for (start = 5; start < retval.length; start += length + 16) {
            offset = EncodingClass.number.fromArray("i32", retval, start);
            length = EncodingClass.number.fromArray("i32", retval, start + 4);
            uts = EncodingClass.number.fromArray("f64", retval, start + 8);
            v1 = (((v1 + offset) % 0xFFFFFF) + 0xFFFFFF) % 0xFFFFFF;
            v2 = (((v2 + uts) % 0xFFFFFF) + 0xFFFFFF) % 0xFFFFFF;
            v3 = (((v3 + offset*uts) % 0xFFFFFF) + 0xFFFFFF) % 0xFFFFFF;
            edata.push([offset, start + 4]);
        }
        callbackfunc({
            type: "data",
            content: {
                hostdata: retval,
                edata: edata,
                chksum: [v1, v2, v3]
            }
        }, [retval.buffer]);
    }

    fcore.readProcess_row = function (name, retval, callbackfunc) {
        var transferList = [];
        var segno = parseInt(name.substr(1));
        var tlen = 0, xlen = 0;
        var nval, xkey;
        var start, length, offset, tcontent, tdata = [], offsetList = [], segData = null, edata = [];
        var i, j, first = -1;
        var v1 = 0, v2 = 0, v3 = 0, uts;
        xkey = [retval[0], retval[1], retval[2], 0];
        ts = EncodingClass.number.rndFunc(0x9E3779B9, 0x243F6A88, 0xB7E15162, EncodingClass.number.fromArray("i32", xkey));
        for (i = 3; (i < retval.length) && (i < 5); i++) {
            retval[i] ^=  ts(256);
        }
        if (EncodingClass.number.fromArray("i16", retval, 3) != dbver) {
            callbackfunc({
                type: "remove",
                content: "invalid dbver"
            });
            return;
        }
        for (i = 5; i < retval.length; i++) {
            retval[i] ^=  ts(256);
        }
        for (start = 5; start < retval.length; start += length + 16) {
            offset = EncodingClass.number.fromArray("i32", retval, start);
            length = EncodingClass.number.fromArray("i32", retval, start + 4) + 8;
            uts = EncodingClass.number.fromArray("f64", retval, start + 8);
            segData = new Uint8Array(length);
            for (i = 0; i < length; i++) {
                segData[i] = retval[start + 4 + i];
            }
            if (first == -1) first = offset;
            v1 = (((v1 + offset) % 0xFFFFFF) + 0xFFFFFF) % 0xFFFFFF;
            v2 = (((v2 + uts) % 0xFFFFFF) + 0xFFFFFF) % 0xFFFFFF;
            v3 = (((v3 + offset*uts) % 0xFFFFFF) + 0xFFFFFF) % 0xFFFFFF;
            edata.push([offset, segData]);
            transferList.push(segData.buffer);
        }
        segData = null;
        retval = null;
        tdata = null;
        offsetList = null;
        callbackfunc({
            type: "data",
            content: {
                edata: edata,
                chksum: [v1, v2, v3]
            }
        }, transferList);
    }

    fcore.pool = Thread.createWorkerPool({
        extcode: EncodingClass.exportCode(),
        modules: {
            rowfunc: fcore.readProcess_row,
            blockfunc: fcore.readProcess_block,
            dbver: dbver
        },
        afunc: function (params, callbackfunc) {
            switch (params.mode) {
                case "row":
                    rowfunc(params.name, params.content, callbackfunc);
                    break;
                case "block":
                    blockfunc(params.name, params.content, callbackfunc);
                    break;
                default:
                    callbackfunc({ type: "null" });
                    break;
            }
        }
    });

    fcache_retval.open = function (dbname, requesturi, calldataFunc) {
        var core = {
            url: "dbload.php",
            dbname: dbname,
            inited: {},
            tables: {},
            apiqueue: [],
            apiThreadCount: 0,
            decodequeue: [],
            decodeWorkerCount: 0
        };
        var retval = {};
        if (requesturi !== undefined) core.url = requesturi;
        if (calldataFunc !== undefined) core.calldataFunc = calldataFunc;

        core.mainRnd = EncodingClass.number.rndFunc((new Date()).getTime());

        core.init = function (tablename, mode, callbackfunc, options) {
            Thread.wait(
                function () {
                    return fcore.workMode !== undefined;
                },
                function () {
                    switch (fcore.workMode) {
                        case "android":
                            core.init = fcore.androidinit(core, dbname);
                            break;
                        case "fsapi":
                            core.init = fcore.fsinit(core, dbname);
                            break;
                        case "idb":
                            core.init = fcore.idbinit(core, dbname);
                            break;
                    }
                    core.init(tablename, mode, callbackfunc, options);
                }
            );
        }

        core.promiseInit = function (core) {
            return function (tablename, mode, options) {
                var host = {};
                Thread.setTimeout({
                    func: core.init,
                    args: [tablename, mode, function (host) {
                        return function (instance) {
                            host.resolve(instance);
                        }
                    } (host), options]
                });
                return new Promise(function(resolve, reject) {
                    host.resolve = resolve;
                    host.reject = reject;
                });
            }
        } (core);

        core.fetchConfigFromCache = function (core) {
            return function (keyList, tablename, callbackfunc) {
                switch (fcore.workMode) {
                    case "android":
                        androidfs.readFiles({
                            path: core.dbname + "_fsdb_" + tablename,
                            list: ["config"],
                            callbackfunc: function (success, value) {
                                if (success) {
                                    if (value.length > 0) {
                                        value[0].content = EncodingClass.string.fromUint8Array(value[0].content);
                                    }
                                }
                                fcore.readConfig(core, keyList, tablename, callbackfunc, success, value);
                            }
                        });
                        break;
                    case "fsapi":
                        fs.readFiles({
                            path: core.dbname + "_fsdb_" + tablename,
                            list: ["config"],
                            callbackfunc: function (success, value) {
                                fcore.readConfig(core, keyList, tablename, callbackfunc, success, value);
                            }
                        });
                        break;
                    case "idb":
                        core.connectors[core.dbname].readFile(tablename + "/config", function (r) {
                            if (r !== null) {
                                r = EncodingClass.string.fromUint8Array(r);
                                fcore.readConfig(core, keyList, tablename, callbackfunc, true, [{
                                    success: true,
                                    content: r
                                }]);
                            }
                            else {
                                fcore.readConfig(core, keyList, tablename, callbackfunc, false);
                            }
                        });
                        break;
                }
            }
        } (core);

        core.fetchDataFromCacheThread = function (core) {
            return function (host) {
                var sname, index;
                var flist, i, keys, path = [];
                var v1 = 0, v2 = 0, v3 = 0;
                var pfunc = function () {
                    if (flist.length == 0) {
                        Thread.setTimeout({
                            func: core.fetchDataFromServer,
                            args: [host.tablename, host.callbackfunc, v1, v2, v3]
                        });
                        return;
                    }
                    switch (fcore.workMode) {
                        case "android":
                            androidfs.readFiles({
                                path: core.dbname + "_fsdb_" + host.tablename,
                                list: [flist[0]],
                                callbackfunc: function (success, content) {
                                    var i, j, offset;
                                    if (!success) {
                                        if (debugPrintFlag) console.log("can not read data");
                                        Thread.setTimeout({ func: perror });
                                        return;
                                    }
                                    Thread.setTimeout({
                                        func: pfunc2,
                                        args: [content[0].content]
                                    });
                                }
                            });
                            break;
                        case "fsapi":
                            fs.readFiles({
                                path: core.dbname + "_fsdb_" + host.tablename,
                                list: [flist[0]],
                                mode: "u8",
                                callbackfunc: function (success, content) {
                                    var i, j, offset;
                                    if (!success) {
                                        if (debugPrintFlag) console.log("can not read data");
                                        Thread.setTimeout({ func: perror });
                                        return;
                                    }
                                    Thread.setTimeout({
                                        func: pfunc2,
                                        args: [content[0].content]
                                    });
                                }
                            });
                            break;
                        case "idb":
                            core.connectors[core.dbname].readFile(host.tablename + "/" + flist[0], function (content) {
                                if (content === null) {
                                    if (debugPrintFlag) console.log("can not read data");
                                    Thread.setTimeout({ func: perror });
                                    return;
                                }
                                Thread.setTimeout({
                                    func: pfunc2,
                                    args: [content]
                                });
                            });
                            break;
                    }
                };
                var pfunc2 = function (content) {
                    //extraParams: {dbver: dbver, path: [core.dbname + "_fsdb_" + host.tablename]},
                    fcore.pool.acall({
                        params: {
                            name: flist[0],
                            mode: core.tables[host.tablename].mode,
                            content: content
                        },
                        transferList: [content.buffer],
                        callbackfunc: function (r) {
                            switch (r.type) {
                                case "null":
                                    if (debugPrintFlag) console.log("can not read data");
                                    break;
                                case "remove":
                                    switch (fcore.workMode) {
                                        case "android":
                                            androidfs.remove (core.dbname + "_fsdb_" + host.tablename + "/" + flist[0], function (success, error) {
                                                console.log("[" + host.tablename + "] " + r.content + " ]");
                                                Thread.setTimeout({ func: perror });
                                            });
                                            return;
                                        case "fsapi":
                                            fs.remove (function (success, error) {
                                                console.log("[" + host.tablename + "] " + r.content + " ]");
                                                Thread.setTimeout({ func: perror });
                                            }, core.dbname + "_fsdb_" + host.tablename + "/" + flist[0]);
                                            return;
                                        case "idb":
                                            core.connectors[core.dbname].remove(host.tablename + "/" + flist[0], function () {
                                                console.log("[" + host.tablename + "] " + r.content + " ]");
                                                Thread.setTimeout({ func: perror });
                                            });
                                            return;
                                    }
                                    break;
                                case "data":
                                    Thread.setTimeout({
                                        func: pfunc3,
                                        args: [r.content]
                                    });
                                    return;
                            }
                            console.log("Invalid response from cache [" + host.tablename + "] (" + r.type + ")");
                            Thread.setTimeout({ func: perror });
                        }
                    });
                };
                var pfunc3 = function (content) {
                    var index, j;
                    v1 = (v1 + content.chksum[0]) % 0xFFFFFF;
                    v2 = (v2 + content.chksum[1]) % 0xFFFFFF;
                    v3 = (v3 + content.chksum[2]) % 0xFFFFFF;
                    if (core.tables[host.tablename].mode == "block") {
                        index = parseInt(flist[0].substr(1));
                        core.tables[host.tablename].hostdata[index] = content.hostdata;
                    }
                    for (j = 0; j < content.edata.length; j++) {
                        offset = content.edata[j][0];
                        core.tables[host.tablename].data[offset] = content.edata[j][1];
                    }
                    Thread.setTimeout({ func: pnext });
                };
                var pnext = function () {
                    flist.shift();
                    Thread.setTimeout({ func: pfunc });
                }
                var perror = function () {
                    Thread.setTimeout({
                        func: fcore.resetTable,
                        args: [core, host.tablename, host.callbackfunc]
                    });
                }
                flist = EncodingClass.string.duplicateObject(host.keyList);
                Thread.setTimeout({ func: pfunc });
            }
        } (core);

        core.fetchDataFromCache = function (core) {
            return function (kList, tablename, callbackfunc) {
                var host;
                var sname, index, keyList = [];
                var i;
                if (debugPrintFlag) console.log("fetchDataFromCache", tablename);
                for (i = 0; i < kList.length; i++) {
                    if (kList[i].substr(0, 1) != "s") continue;
                    index = parseInt(kList[i].substr(1));
                    if (("s" + index) != kList[i]) continue;
                    keyList.push(kList[i]);
                }
                if (keyList.length == 0) {
                    Thread.setTimeout({
                        func: core.fetchDataFromServer,
                        args: [tablename, callbackfunc, 0, 0, 0]
                    });
                    return;
                }
                host = {
                    tablename: tablename,
                    keyList: keyList,
                    callbackfunc: callbackfunc,
                    queue: []
                }
                Thread.setTimeout({
                    func: core.fetchDataFromCacheThread,
                    args: [host]
                });
            }
        } (core);

        core.apiThread = function (core) {
            return function () {
                var calldata;
                //while ((core.apiqueue.length > 0) && (core.apiThreadCount < 320)) {
                    while (core.apiqueue.length > 0) {
                        calldata = core.apiqueue.shift();
                        if (core.calldataFunc !== undefined) core.calldataFunc(calldata);
                        calldata.ru8 = true;
                        calldata.func = function (func) {
                            return function (success, contents) {
                                Thread.setTimeout({
                                    func: func,
                                    args: [success, contents]
                                });
                                core.apiThreadCount--;
                            }
                        } (calldata.func);
                        FormClass.zip_call(calldata);
                        core.apiThreadCount++;
                    }
                    Thread.setTimeout({
                        func: core.apiThread,
                        time: 2
                    });
            }
        } (core);
        Thread.setTimeout({func: core.apiThread});

        core.decodeFunc = function (params) {
            var r;
            var xf, i, j, k, t, s, xlen;
            var retval = [];
            transferList = [];
            params.content = params.content.subarray(1, params.content.length);
            r = EncodingClass.number.toTable(params.content);
            for (i = 0; i < r.length; i++) {
                offset = r[i].id;
                segment = offset >> 12;
                if (xf === undefined) {
                    xf = Object.keys(r[i]);
                    xf.sort();
                }
                if (t === undefined) {
                    t = [];
                    for (j = 0; j < xf.length; j++) t.push(null);
                }
                xlen = 8;
                for (j = 0; j < xf.length; j++) {
                    s = EncodingClass.number.fromVariable(r[i][xf[j]]);
                    t[j] = s;
                    xlen += s.length;
                }
                if (xlen > 0) {
                    s = new Uint8Array(xlen);
                    EncodingClass.number.writeArray("f64", ~~(r[i].uts.getTime() / 1000), s, 0);
                    xlen = 8;
                    for (j = 0; j < xf.length; j++) {
                        for (k = 0; k < t[j].length; k++) {
                            s[xlen++] = t[j].charCodeAt(k);
                        }
                    }
                    retval.push({
                        id: offset,
                        uts: r[i].uts,
                        data: s
                    });
                    transferList.push(s.buffer);
                }
            }
            return {
                format: xf,
                data: retval
            };
        }

        core.decodeBlob = Thread.generateBlob({
            extcode: EncodingClass.exportCode(),
            func: core.decodeFunc
        });

        core.fetchDataFromServer = function (core) {
            return function (tablename, callbackfunc, c1, c2, c3) {
                var host = {
                    tablename: tablename,
                    segMark: {},
                    total: 0,
                    finished: 0,
                    lastindex: -1,
                    callbackfunc: callbackfunc
                };
                host.genCallbackFunc = function (host) {
                    return function (index) {
                        return function (content) {
                            var i, j, k, r, t, segment, offset, start;
                            var uts, lastuts = -1, lastid = 0;
                            var v1 = 0, v2 = 0, v3 = 0, v;
                            r = content.data;
                            if (content.format !== undefined) {
                                if (!fcore.sameArray(core.tables[host.tablename].config.format, content.format)) {
                                    core.tables[host.tablename].data = [];
                                    if (core.tables[host.tablename].mode == "block") {
                                        core.tables[host.tablename].hostdata = [];
                                        core.tables[host.tablename].hostmodified = [];
                                    }
                                    core.tables[host.tablename].config.format = content.format;
                                    core.tables[host.tablename].c1 = 0;
                                    core.tables[host.tablename].c2 = 0;
                                    core.tables[host.tablename].c3 = 0;
                                }
                            }
                            switch (core.tables[host.tablename].mode) {
                                case "row":
                                    for (i = 0; i < r.length; i++) {
                                        offset = r.id;
                                        segment = offset >> 12;
                                        v = core.wgetContent(host.tablename, offset, true);
                                        if (v !== undefined) {
                                            uts = ~~(v.uts.getTime() / 1000);
                                            v1 = (((v1 - offset) % 0xFFFFFF) + 0xFFFFFF) % 0xFFFFFF;
                                            v2 = (((v2 - uts) % 0xFFFFFF) + 0xFFFFFF) % 0xFFFFFF;
                                            v3 = (((v3 - offset*uts) % 0xFFFFFF) + 0xFFFFFF) % 0xFFFFFF;
                                        }
                                        host.segMark[segment] = true;
                                        uts = r[i].uts.getTime();
                                        if (uts > lastuts) {
                                            lastuts = uts;
                                            lastid = offset;
                                        }
                                        else if ((uts == lastuts) && (offset > lastid)) {
                                            lastuts = uts;
                                            lastid = offset;
                                        }
                                        core.tables[host.tablename].data[offset] = r[i].data;
                                        uts = ~~(uts / 1000);
                                        v1 = (((v1 + offset) % 0xFFFFFF) + 0xFFFFFF) % 0xFFFFFF;
                                        v2 = (((v2 + uts) % 0xFFFFFF) + 0xFFFFFF) % 0xFFFFFF;
                                        v3 = (((v3 + offset*uts) % 0xFFFFFF) + 0xFFFFFF) % 0xFFFFFF;
                                    }
                                    break;
                                case "block":
                                    for (i = 0; i < r.length; i++) {
                                        offset = r[i].id;
                                        segment = offset >> 12;
                                        v = core.wgetContent(host.tablename, offset, true);
                                        if (v !== undefined) {
                                            if (v.uts === undefined) {
                                                v = v;
                                            }
                                            uts = ~~(v.uts.getTime() / 1000);
                                            v1 = (((v1 - offset) % 0xFFFFFF) + 0xFFFFFF) % 0xFFFFFF;
                                            v2 = (((v2 - uts) % 0xFFFFFF) + 0xFFFFFF) % 0xFFFFFF;
                                            v3 = (((v3 - offset*uts) % 0xFFFFFF) + 0xFFFFFF) % 0xFFFFFF;
                                        }
                                        host.segMark[segment] = true;
                                        uts = r[i].uts.getTime();
                                        if (uts > lastuts) {
                                            lastuts = uts;
                                            lastid = offset;
                                        }
                                        else if ((uts == lastuts) && (offset > lastid)) {
                                            lastuts = uts;
                                            lastid = offset;
                                        }
                                        uts = ~~(uts / 1000);
                                        v1 = (((v1 + offset) % 0xFFFFFF) + 0xFFFFFF) % 0xFFFFFF;
                                        v2 = (((v2 + uts) % 0xFFFFFF) + 0xFFFFFF) % 0xFFFFFF;
                                        v3 = (((v3 + offset*uts) % 0xFFFFFF) + 0xFFFFFF) % 0xFFFFFF;
                                        t = r[i].data;
                                        start = core.tables[host.tablename].data[offset];
                                        if ((start === undefined) || (start == -1)) {
                                            core.tables[host.tablename].hostmodified[offset] = t;
                                            core.tables[host.tablename].data[offset] = -1;
                                        }
                                        else if (EncodingClass.number.fromArray("i32", core.tables[host.tablename].hostdata[segment], start) >= t.length) {
                                            for (j = 0; j < t.length; j++) {
                                                core.tables[host.tablename].hostdata[segment][start + j + 4] = t[j];
                                            }
                                            k = EncodingClass.number.toArray("i32", t.length);
                                            for (j = 0; j < 4; j++) {
                                                core.tables[host.tablename].hostdata[segment][start + j] = k[j];
                                            }
                                            if (core.tables[host.tablename].hostmodified[offset] !== undefined) delete core.tables[host.tablename].hostmodified[offset];
                                        }
                                        else {
                                            core.tables[host.tablename].hostmodified[offset] = t;
                                        }
                                    }
                                    break;
                            }
                            if (index > host.lastindex) {
                                host.lastindex = index;
                                core.tables[host.tablename].config.lastuts = lastuts;
                                core.tables[host.tablename].config.lastid = lastid;
                            }
                            c1 = (v1 + c1) % 0xFFFFFF;
                            c2 = (v2 + c2) % 0xFFFFFF;
                            c3 = (v3 + c3) % 0xFFFFFF;

                            host.finished++;
                            if (host.finished == host.total) {
                                Thread.setTimeout({func: host.finalize});
                            }
                        }
                    }
                } (host);
                host.finalize = function (host) {
                    return function () {
                        core.tables[host.tablename].c1 = c1;
                        core.tables[host.tablename].c2 = c2;
                        core.tables[host.tablename].c3 = c3;
                        Thread.setTimeout({
                            func: core.saveCache,
                            args: [host.tablename, Object.keys(host.segMark), host.callbackfunc]
                        });
                    }
                } (host);
                if (debugPrintFlag) console.log("fetchDataFromServer", tablename);
                if (core.tables[tablename] === undefined) throw new Error("Invalid tablename [" + tablename + "]");
                if (core.tables[tablename].config === undefined) throw new Error("No config tablename [" + tablename + "]");
                var pList = [
                    {
                        name: "name",
                        value: tablename
                    },
                    {
                        name: "lastid",
                        value: core.tables[tablename].config.lastid
                    },
                    {
                        name: "lastuts",
                        value: core.tables[tablename].config.lastuts
                    }
                ];
                if (core.tables[tablename].config.fieldList !== undefined) pList.push({
                    name: "fields",
                    value: EncodingClass.string.fromVariable(core.tables[tablename].config.fieldList)
                });
                core.apiqueue.push({
                    url: core.url,
                    params: pList,
                    func: function (host) {
                        return function (success, contents) {
                            var i, j, k;
                            var segMark = {}, r, t, xf, v;
                            var content, code, start, length;
                            var segment, offset, uts, buf, keys, lastid;
                            var tempqueue = [];
                            if (!success) {
                                if (debugPrintFlag) console.log("query failed, try again in 5s");
                                Thread.setTimeout({
                                    func: core.fetchDataFromServer,
                                    args: [tablename, callbackfunc, c1, c2, c3],
                                    time: 5000
                                });
                                return;
                            }
                            for (k = 0; k < contents.length; k++) {
                                code = contents[k].content[0];
                                switch (code) {
                                    case 0:     // data
                                        tempqueue.push({
                                            data: contents[k].content,
                                            callbackfunc: host.genCallbackFunc(k)
                                        });
                                        host.total++;
                                        break;
                                    case 1:     // deleted data
                                        host.deleted = [];
                                        start = 1;
                                        content = contents[k].content;
                                        while (start < content.length) {
                                            t = content[start++];
                                            if (t == 0) {
                                                offset = EncodingClass.number.fromArray("i32", content, start);
                                                start += 4;
                                                segment = offset >> 12;
                                                if (core.tables[host.tablename].safemode !== true) {
                                                    v = core.wgetContent(host.tablename, offset, true);
                                                    if (v !== undefined) {
                                                        uts = ~~(v.uts.getTime() / 1000);
                                                        c1 = (((c1 - offset) % 0xFFFFFF) + 0xFFFFFF) % 0xFFFFFF;
                                                        c2 = (((c2 - uts) % 0xFFFFFF) + 0xFFFFFF) % 0xFFFFFF;
                                                        c3 = (((c3 - offset*uts) % 0xFFFFFF) + 0xFFFFFF) % 0xFFFFFF;
                                                    }
                                                }
                                                switch (core.tables[host.tablename].mode) {
                                                    case "block":
                                                        if (core.tables[host.tablename].hostmodified[offset] !== undefined) {
                                                            host.segMark[segment] = true;
                                                            delete core.tables[host.tablename].hostmodified[offset];
                                                        }
                                                        // intentionally omit break command - not syntax error
                                                    case "row":
                                                        if (core.tables[host.tablename].data[offset] !== undefined) {
                                                            host.segMark[segment] = true;
                                                            delete core.tables[host.tablename].data[offset];
                                                        }
                                                        break;
                                                }
                                            }
                                            else {
                                                offset = EncodingClass.number.fromArray("i32", content, start);
                                                start += 4;
                                                length = EncodingClass.number.fromArray("i32", content, start);
                                                start += 4;
                                                for (j = 0; j < length; j++) {
                                                    segment = offset >> 12;
                                                    if (core.tables[host.tablename].safemode !== true) {
                                                        v = core.wgetContent(host.tablename, offset, true);
                                                        if (v !== undefined) {
                                                            uts = ~~(v.uts.getTime() / 1000);
                                                            c1 = (((c1 - offset) % 0xFFFFFF) + 0xFFFFFF) % 0xFFFFFF;
                                                            c2 = (((c2 - uts) % 0xFFFFFF) + 0xFFFFFF) % 0xFFFFFF;
                                                            c3 = (((c3 - offset*uts) % 0xFFFFFF) + 0xFFFFFF) % 0xFFFFFF;
                                                        }
                                                    }
                                                    switch (core.tables[host.tablename].mode) {
                                                        case "block":
                                                            if (core.tables[host.tablename].hostmodified[offset] !== undefined) {
                                                                host.segMark[segment] = true;
                                                                delete core.tables[host.tablename].hostmodified[offset];
                                                            }
                                                            // intentionally omit break command - not syntax error
                                                        case "row":
                                                            if (core.tables[host.tablename].data[offset] !== undefined) {
                                                                host.segMark[segment] = true;
                                                                delete core.tables[host.tablename].data[offset];
                                                            }
                                                            break;
                                                    }
                                                    offset++;
                                                }
                                            }
                                        }
                                        break;
                                    case 2:     // lastid
                                        content = contents[k].content;
                                        lastid = EncodingClass.number.fromArray("i32", content, 1);
                                        keys = Object.keys(core.tables[host.tablename].data);
                                        i = 0;
                                        Thread.exec(
                                            function () {
                                                if (i == keys.length) return true;
                                                offset = parseInt(keys[i++]);
                                                if (offset > lastid) {
                                                    segment = offset >> 12;
                                                    if (core.tables[host.tablename].safemode !== true) {
                                                        v = core.wgetContent(host.tablename, offset, true);
                                                        if (v !== undefined) {
                                                            uts = ~~(v.uts.getTime() / 1000);
                                                            c1 = (((c1 - offset) % 0xFFFFFF) + 0xFFFFFF) % 0xFFFFFF;
                                                            c2 = (((c2 - uts) % 0xFFFFFF) + 0xFFFFFF) % 0xFFFFFF;
                                                            c3 = (((c3 - offset*uts) % 0xFFFFFF) + 0xFFFFFF) % 0xFFFFFF;
                                                        }
                                                    }
                                                    switch (core.tables[host.tablename].mode) {
                                                        case "block":
                                                            if (core.tables[host.tablename].hostmodified[offset] !== undefined) {
                                                                host.segMark[segment] = true;
                                                                delete core.tables[host.tablename].hostmodified[offset];
                                                            }
                                                            // intentionally omit break command - not syntax error
                                                        case "row":
                                                            if (core.tables[host.tablename].data[offset] !== undefined) {
                                                                host.segMark[segment] = true;
                                                                delete core.tables[host.tablename].data[offset];
                                                            }
                                                            break;
                                                    }
                                                }
                                                return false;
                                            },
                                            function () {
                                                keys = Object.keys(core.tables[host.tablename].hostmodified);
                                                i = 0;
                                                Thread.exec(
                                                    function () {
                                                        if (i == keys.length) {
                                                            for (i = 0; i < tempqueue.length; i++) {
                                                                core.decodequeue.push(tempqueue[i]);
                                                            }
                                                            tempqueue = null;
                                                            if (host.total == 0) Thread.setTimeout({func: host.finalize});
                                                            return true;
                                                        }
                                                        offset = parseInt(keys[i++]);
                                                        if (offset > lastid) {
                                                            segment = offset >> 12;
                                                            if (core.tables[host.tablename].safemode !== true) {
                                                                v = core.wgetContent(host.tablename, offset, true);
                                                                if (v !== undefined) {
                                                                    uts = ~~(v.uts.getTime() / 1000);
                                                                    c1 = (((c1 - offset) % 0xFFFFFF) + 0xFFFFFF) % 0xFFFFFF;
                                                                    c2 = (((c2 - uts) % 0xFFFFFF) + 0xFFFFFF) % 0xFFFFFF;
                                                                    c3 = (((c3 - offset*uts) % 0xFFFFFF) + 0xFFFFFF) % 0xFFFFFF;
                                                                }
                                                            }
                                                            switch (core.tables[host.tablename].mode) {
                                                                case "block":
                                                                    if (core.tables[host.tablename].hostmodified[offset] !== undefined) {
                                                                        host.segMark[segment] = true;
                                                                        delete core.tables[host.tablename].hostmodified[offset];
                                                                    }
                                                                    // intentionally omit break command - not syntax error
                                                                case "row":
                                                                    if (core.tables[host.tablename].data[offset] !== undefined) {
                                                                        host.segMark[segment] = true;
                                                                        delete core.tables[host.tablename].data[offset];
                                                                    }
                                                                    break;
                                                            }
                                                        }
                                                        return false;
                                                    }
                                                );
                                            }
                                        );
                                        return;
                                }
                            }
                            for (i = 0; i < tempqueue.length; i++) {
                                core.decodequeue.push(tempqueue[i]);
                            }
                            tempqueue = null;
                            if (host.total == 0) Thread.setTimeout({func: host.finalize});
                        }
                    } (host)
                });
            }
        } (core);

        core.decodeThread = function (core) {
            return function () {
                var instance;
                while ((core.decodequeue.length > 0) && (core.decodeWorkerCount < 8)) {
                    instance = {};
                    if (debugPrintFlag) {
                        instance.thread = function (me) {
                            return {
                                call: function (params) {
                                    var value = core.decodeFunc(params);
                                    me.thread.callbackfunc(value);
                                },
                                callbackfunc: core.genCallbackRetvalFunc(me),
                                terminate: function () {
                                    delete me.thread;
                                }
                            }
                        } (instance);
                    }
                    else {
                        instance.thread = Thread.createFromBlob({
                            blobURL: core.decodeBlob,
                            callbackfunc: core.genCallbackRetvalFunc(instance)
                        })[0];
                    }
                    instance.exec = function (me) {
                        return function () {
                            var task = core.decodequeue.shift();
                            me.task = task.callbackfunc;
                            me.thread.call(
                                {
                                    content: task.data,
                                    size: task.data.length
                                },
                                [task.data.buffer]
                            );
                        }
                    } (instance);
                    instance.callbackfunc = function (me) {
                        return function (retval) {
                            Thread.setTimeout({
                                func: me.task,
                                args: [retval]
                            });
                            if (core.decodequeue.length > 0) {
                                me.exec();
                            }
                            else {
                                me.thread.terminate();
                                core.decodeWorkerCount--;
                            }
                        }
                    } (instance);
                    instance.exec();
                    core.decodeWorkerCount++;
                }
                Thread.setTimeout({func: core.decodeThread}, 5);
            }
        } (core);

        Thread.setTimeout({func: core.decodeThread}, 5);

        core.writeCache = function (core) {
            return function (callbackfunc, path, list, transferList) {
                var rv = [];
                var writeThread = function () {
                    if (list.length == 0) {
                        Thread.setTimeout({
                            func: callbackfunc,
                            args: [true, rv]
                        });
                        return;
                    }
                    switch (fcore.workMode) {
                        case "android":
                            androidfs.writeFiles({
                                path: core.dbname + "_fsdb_" + path,
                                list: [{
                                    name: list[0].name,
                                    value: list[0].value
                                }],
                                callbackfunc: function (success, content) {
                                   rv.push(content[0]);
                                   list.shift();
                                   Thread.setTimeout({ func: writeThread });
                                }
                            });
                            break;
                        case "idb":
                            core.connectors[core.dbname].writeFile(path + "/" + list[0].name, list[0].value, function () {
                                rv.push({
                                    name: list[0].name,
                                    success: true,
                                    content: list[0].value.length
                                });
                                list.shift();
                                Thread.setTimeout({ func: writeThread });
                            });
                            break;
                    }
                }
                switch (fcore.workMode) {
                    case "fsapi":
                        fs.writeFiles({
                            path: core.dbname + "_fsdb_" + path,
                            list: list,
                            transferList: transferList,
                            callbackfunc: callbackfunc
                        });
                        break;
                    case "android":
                    case "idb":
                        transferList = null;
                        Thread.setTimeout({ func: writeThread });
                        break;
                }
            }
        } (core);

        core.prepareSaveDataThreads = Thread.createWorkerPool({
            extcode: EncodingClass.exportCode(),
            func: function (params) {
                var dbver = params.dbver;
                var mode = params.mode;
                var xkey = params.xkey;
                var hostdata = params.hostdata;
                var data = params.data;
                var v, xv, ts, ti;
                var i, k, offset, old, xlen = 5;
                transferList = [];
                if (mode == "row") {
                    for (i = 0; i < data.length; i++) {
                        offset = data[i][0];
                        xlen += data[i][1].length;
                    }
                    v = null;
                    xv = new Uint8Array(xlen);
                    EncodingClass.number.writeArray("i16", dbver, xv, 3);
                    xlen = 5;
                    for (i = 0; i < data.length; i++) {
                        offset = data[i][0];
                        EncodingClass.number.writeArray("i32", offset, xv, xlen);
                        xlen += 4;
                        EncodingClass.number.writeArray("i32", data[i][1].length - 8, xv, xlen);
                        xlen += 4;
                        for (j = 0; j < data[i][1].length; j++) {
                            xv[xlen++] = data[i][1][j];
                        }
                        transferList.push(data[i][1]);
                    }
                }
                else {
                    for (i = k = 0; i < data.length; i++) {
                        if (data[i][1] !== -1) data[k++] = data[i];
                    }
                    data.length = k;
                    for (i = 0; i < data.length; i++) {
                        if (EncodingClass.type.isNumber(data[i][1])) {
                            l = EncodingClass.number.fromArray("i32", hostdata, data[i][1]) + 8;
                        }
                        else {
                            l = data[i][1].length;
                        }
                        xlen += l + 8;
                    }
                    v = new Uint8Array(xlen);
                    EncodingClass.number.writeArray("i16", dbver, v, 3);
                    xlen = 5;
                    for (i = 0; i < data.length; i++) {
                        offset = data[i][0];
                        if (EncodingClass.type.isNumber(data[i][1])) {
                            EncodingClass.number.writeArray("i32", offset, v, xlen);
                            xlen += 4;
                            start = data[i][1];
                            data[i][1] = xlen;
                            l = EncodingClass.number.fromArray("i32", hostdata, start) + 12;
                            for (j = 0; j < l; j++) {
                                v[xlen++] = hostdata[start + j];
                            }
                        }
                        else {
                            EncodingClass.number.writeArray("i32", offset, v, xlen);
                            xlen += 4;
                            old = data[i][1];
                            data[i][1] = xlen;
                            l = old.length;
                            EncodingClass.number.writeArray("i32", l - 8, v, xlen);
                            xlen += 4;
                            for (j = 0; j < l; j++) {
                                v[xlen++] = old[j];
                            }
                        }
                    }
                    transferList.push(v.buffer);
                    xv = new Uint8Array(v.length);
                    xv.set(v);
                }
                transferList.push(xv.buffer);
                ts = EncodingClass.number.rndFunc(0x9E3779B9, 0x243F6A88, 0xB7E15162, xkey);
                ti = EncodingClass.number.toArray("i32", xkey);
                for (i = 0; i < 3; i++) xv[i] = ti[i];
                for (i = 3; i < xv.length; i++) xv[i] ^= ts(256);
                return {
                    hostdata: v,
                    data: data,
                    saveData: xv
                }
            }
        });

        core.getChecksum = function (core) {
            return function (tablename, callbackfunc) {
                var calldata = {
                    url: core.url,
                    params: [
                        {
                            name: "name",
                            value: tablename
                        },
                        {
                            name: "lastid",
                            value: 0
                        },
                        {
                            name: "lastuts",
                            value: 0
                        },
                        {
                            name: "task",
                            value: "chksum"
                        }
                    ],
                    func: function (success, message) {
                        if (success) {
                            if (message.substr(0, 2) == "ok") {
                                Thread.setTimeout({
                                    func: callbackfunc,
                                    args: [message.substr(2)]
                                });
                            }
                            else {
                                if (debugPrintFlag) console.log("request run-time error", message);
                            }
                        }
                        else {
                            if (debugPrintFlag) console.log("request error, try again in 5s");
                            Thread.setTimeout({
                                func: core.getChecksum,
                                args: [tablename, callbackfunc]
                            });
                        }
                    }
                };
                if (core.calldataFunc !== undefined) core.calldataFunc(calldata);
                FormClass.api_call(calldata);
            }
        } (core);

        core.remove = function (core) {
            return function (tablename, callbackfunc) {
                switch (fcore.workMode) {
                    case "android":
                        androidfs.remove(core.dbname + "_fsdb_" + tablename, function (success) {
                            Thread.setTimeout({
                                func: callbackfunc,
                                args: [success]
                            });
                        });
                        break;
                    case "fsapi":
                        fs.remove(function (success) {
                            Thread.setTimeout({
                                func: callbackfunc,
                                args: [success]
                            });
                        }, core.dbname + "_fsdb_" + tablename);
                        break;
                    case "idb":
                        core.connectors[core.dbname].remove(tablename, function () {
                            callbackfunc();
                        });
                        break;
                }
            }
        } (core);

        core.saveCacheThread = function (core) {
            return function (host) {
                var transferList = [];
                var segno, xkey, fs, ts;
                var i, j, k, v, t, p, l, xv, ti, xlen, start;
                var data, hostdata, transferList;
                for (k = 0; k < host.segList.length; k++) {
                    segno = parseInt(host.segList[k]);
                    fs = segno << 12;
                    ts = fs + 4096;
                    data = [];
                    transferList = [];
                    if (core.tables[host.tablename].mode == "row") {
                        for (i = fs; i < ts; i++) {
                            if (core.tables[host.tablename].data[i] !== undefined) {
                                data.push([i, core.tables[host.tablename].data[i]]);
                                if (core.tables[host.tablename].safemode !== true) transferList.push(core.tables[host.tablename].data[i].buffer);
                            }
                        }
                        hostdata = null;
                    }
                    else {
                        if (core.tables[host.tablename].hostdata[segno] !== undefined) {
                            hostdata = core.tables[host.tablename].hostdata[segno];
                            if (core.tables[host.tablename].safemode !== true) transferList.push(hostdata.buffer);
                        }
                        else {
                            hostdata = null;
                        }
                        for (i = fs; i < ts; i++) {
                            if (core.tables[host.tablename].hostmodified[i] !== undefined) {
                                data.push([i, core.tables[host.tablename].hostmodified[i]]);
                                if (core.tables[host.tablename].safemode !== true) transferList.push(core.tables[host.tablename].hostmodified[i].buffer);
                            }
                            else if (core.tables[host.tablename].data[i] !== undefined) {
                                data.push([i, core.tables[host.tablename].data[i]]);
                            }
                        }
                    }
                    xkey = (core.mainRnd(0xFFFFFFF) + segno * 1001 + 11) & 0xFFFFFF;
                    core.prepareSaveDataThreads.call({
                        params: {
                            mode: core.tables[host.tablename].mode,
                            dbver: dbver,
                            xkey: xkey,
                            hostdata: hostdata,
                            data: data
                        },
                        transferList: transferList,
                        callbackfunc: function (host, segno, index) {
                            return function (retval) {
                                var i, offset, transferList;
                                if (core.tables[host.tablename] === undefined) return;
                                if (core.tables[host.tablename].hostdata === undefined) core.tables[host.tablename].hostdata = [];
                                if (retval.hostdata !== null) core.tables[host.tablename].hostdata[segno] = retval.hostdata;
                                for (i = 0; i < retval.data.length; i++) {
                                    offset = retval.data[i][0];
                                    core.tables[host.tablename].data[offset] = retval.data[i][1];
                                    if (core.tables[host.tablename].mode == "block") {
                                        if (core.tables[host.tablename].hostmodified[offset] !== undefined) delete core.tables[host.tablename].hostmodified[offset];
                                    }
                                }
                                host.queue[index] = {
                                    name: "s" + segno,
                                    value: retval.saveData
                                }
                                host.finished++;
                                if (host.finished == host.total) {
                                    transferList = [];
                                    for (i = 0; i < host.queue.length; i++) {
                                        if (!EncodingClass.type.isString(host.queue[i].value)) {
                                            transferList.push(host.queue[i].value.buffer);
                                        }
                                    }
                                    if (core.tables[host.tablename].safemode !== true) {
                                        core.getChecksum(host.tablename, function (chksum) {
                                            if (chksum == EncodingClass.md5.encode(core.tables[host.tablename].c1 + "/" + core.tables[host.tablename].c2 + "/" + core.tables[host.tablename].c3)) {
                                                if (debugPrintFlag) console.log("checksum ok", host.tablename);
                                                core.writeCache(function () {
                                                    if (debugPrintFlag) console.log("saveCache done", host.tablename);
                                                    core.tables[host.tablename].safemode = true;
                                                    Thread.setTimeout({
                                                        func: host.callbackfunc,
                                                        args: [true]
                                                    });
                                                }, host.tablename, host.queue, transferList);
                                            }
                                            else {
                                                if (debugPrintFlag) console.log("checksum error", host.tablename);
                                                host.mode = core.tables[host.tablename].mode;
                                                fcore.resetTable(core, host.tablename, host.callbackfunc);
                                            }
                                        });
                                    }
                                    else {
                                        core.writeCache(function () {
                                            if (debugPrintFlag) console.log("saveCache done 1", host.tablename);
                                            core.tables[host.tablename].safemode = true;
                                            Thread.setTimeout({
                                                func: host.callbackfunc,
                                                args: [true]
                                            });
                                        }, host.tablename, host.queue, transferList);
                                    }
                                }
                            }
                        } (host, segno, k)
                    });
                    host.queue.push(null);
                }
                core.tables[host.tablename].config.chksum = EncodingClass.md5.encode(EncodingClass.string.fromVariable({
                    lastid: core.tables[host.tablename].config.lastid,
                    lastuts: core.tables[host.tablename].config.lastuts,
                    format: core.tables[host.tablename].config.format
                }) + "_" + core.dbname + "_" + dbver);
                host.queue.push({
                    name: "config",
                    value: EncodingClass.number.fromVariable(core.tables[host.tablename].config)
                });
                if (core.tables[host.tablename].safemode !== true) {
                    if (core.tables[host.tablename].mode == "block") core.tables[host.tablename].hostmodified = [];
                }
            }
        } (core);

        core.saveCache = function (core) {
            return function (tablename, segList, callbackfunc) {
                if (debugPrintFlag) console.log("saveCache", tablename);
                var host = {
                    tablename: tablename,
                    segList: segList,
                    total: segList.length,
                    queue: [],
                    finished: 0,
                    callbackfunc: callbackfunc
                };
                var i;
                if (host.total > 0) {
                    Thread.setTimeout({
                        func: core.saveCacheThread,
                        args: [host]
                    });
                }
                else {
                    core.tables[tablename].config.chksum = EncodingClass.md5.encode(EncodingClass.string.fromVariable({
                        lastid: core.tables[tablename].config.lastid,
                        lastuts: core.tables[tablename].config.lastuts,
                        format: core.tables[tablename].config.format
                    }) + "_" + core.dbname + "_" + dbver);
                    if (core.tables[host.tablename].safemode !== true) {
                        core.getChecksum(host.tablename, function (chksum) {
                            //if (chksum == core.tables[host.tablename].c1 + "/" + core.tables[host.tablename].c2 + "/" + core.tables[host.tablename].c3) {
                            if (chksum == EncodingClass.md5.encode(core.tables[host.tablename].c1 + "/" + core.tables[host.tablename].c2 + "/" + core.tables[host.tablename].c3)) {
                                if (debugPrintFlag) console.log("checksum ok", host.tablename);
                                core.writeCache(function () {
                                    if (debugPrintFlag) console.log("saveCache done 2", tablename);
                                    core.tables[host.tablename].safemode = true;
                                    Thread.setTimeout({
                                        func: callbackfunc,
                                        args: [true]
                                    });
                                }, tablename, [{name: "config", value: EncodingClass.number.fromVariable(core.tables[tablename].config)}]);
                            }
                            else {
                                if (debugPrintFlag) console.log("checksum error", host.tablename);
                                host.mode = core.tables[host.tablename].mode;
                                fcore.resetTable(core, host.tablename, host.callbackfunc);
                            }
                        });
                        return;
                    }

                    core.writeCache(function () {
                        if (debugPrintFlag) console.log("saveCache done", tablename);
                        core.tables[host.tablename].safemode = true;
                        Thread.setTimeout({
                            func: callbackfunc,
                            args: [true]
                        });
                    }, tablename, [{name: "config", value: EncodingClass.number.fromVariable(core.tables[tablename].config)}]);
                }
            }
        } (core);

        core.wgetContent = function (core) {
            return function (tablename, id, keeputs) {
				var segno;
                if (core.tables[tablename] === undefined) return undefined;
                if (core.tables[tablename].config.format === undefined) return undefined;
                switch (core.tables[tablename].mode) {
                    case "row":
                        if (core.tables[tablename].data[id] === undefined) return undefined;
                        break;
                    case "block":
                        if ((core.tables[tablename].data[id] === undefined) && (core.tables[tablename].hostmodified[id] === undefined)) return undefined;
						segno = id >> 12;
						if (core.tables[tablename].hostdata[segno] === undefined) return undefined;
                        break;
                }
                return core.getContent(tablename, id, keeputs);
            }
        } (core);

        core.wgetContent2 = function (core) {
            return function (tablename, ids, keeputs, callbackfunc) {
                var r = [];
                if (core.tables[tablename] === undefined) {
                    Thread.setTimeout({func: callbackfunc});
                    return;
                }
                if (ids.length == 0) {
                    Thread.setTimeout({
                        func: callbackfunc,
                        args: [[]]
                    });
                    return;
                }
                if (core.tables[tablename].config.format === undefined) {
                    Thread.setTimeout({func: callbackfunc});
                    return;
                }
                var index = 0, imax = 10;
                var readThread = function () {
                    var stime = (new Date()).getTime();
                    var i, id, ilen;
                    var xtime = stime, ttime;
                    while (index < ids.length) {
                        ilen = ids.length - index;
                        if (ilen > imax) ilen = imax;
                        for (i = 0; i < ilen; i++) {
                            id = ids[index++];
                            switch (core.tables[tablename].mode) {
                                case "row":
                                    if (core.tables[tablename].data[id] === undefined) continue;
                                    break;
                                case "block":
                                    if ((core.tables[tablename].data[id] === undefined) && (core.tables[tablename].hostmodified[id] === undefined)) continue;
                                    break;
                            }
                            r.push(core.getContent(tablename, id, keeputs));
                        }
                        ttime = (new Date()).getTime();
                        if (ttime - stime > 40) break;
                        if (ttime - xtime < 5) {
                            imax = ~~(imax * 1.1);
                        }
                        else {
                            imax = ~~(imax * 0.9);
                            if (imax < 10) imax = 10;
                        }
                        xtime = ttime;
                    }
                    if (index == ids.length) {
                        Thread.setTimeout({
                            func: callbackfunc,
                            args: [r]
                        });
                    }
                    else {
                        Thread.setTimeout({func: readThread});
                    }
                }
                Thread.setTimeout({func: readThread});
            }
        } (core);

        core.getContent = function (core) {
            return function (tablename, id, keeputs) {
                var segno, v, start, length;
                switch (core.tables[tablename].mode) {
                    case "row":
                        v = EncodingClass.string.fromUint8Array(core.tables[tablename].data[id], 8);
                        break;
                    case "block":
                        segno = id >> 12;
                        if (core.tables[tablename].hostmodified[id] !== undefined) {
                            v = EncodingClass.string.fromUint8Array(core.tables[tablename].hostmodified[id], 8);
                        }
                        else {
                            start = core.tables[tablename].data[id];
                            length = EncodingClass.number.fromArray("i32", core.tables[tablename].hostdata[segno], start);
                            v = EncodingClass.string.fromUint8Array(core.tables[tablename].hostdata[segno], start + 12, length);
                        }
                        break;
                    default:
                        return undefined;
                }
                v = EncodingClass.number.toStructRecord(core.tables[tablename].config.format, v);
                if (keeputs !== true) {
                    delete v.uts;
                }
                else {
                    if (core.tables[tablename].hostmodified[id] !== undefined) {
                        v.uts = new Date(EncodingClass.number.fromArray("f64", core.tables[tablename].hostmodified[id]));
                    }
                    else {
                        v.uts = new Date(EncodingClass.number.fromArray("f64", core.tables[tablename].hostdata[segno], start + 4));
                    }
                }
                return v;
            }
        } (core);

        core.getInstance = function (core) {
            return function (tablename) {
                var r = {};
                r.exists = function (id) {
                    if (core.tables[tablename] === undefined) return false;
                    return core.tables[tablename].data[id] !== undefined;
                };
                r.getIDList = function (callbackfunc) {
                    return core.getIDList(tablename, callbackfunc);
                };
                r.read = function (id) {
                    return core.wgetContent(tablename, id);
                };
                r.reads = function (ids, callbackfunc) {
                    return core.wgetContent2(tablename, ids, false, callbackfunc);
                };
                r.promiseReads = function (ids) {
                    return new Promise(function(resolve, reject) {
                        core.wgetContent2(tablename, ids, false, function (values) {
                            resolve(values);
                        });
                    });
                };

                r.load = function (callbackfunc) {
                    core.tables[tablename].safemode = true;
                    Thread.setTimeout({
                        func: core.fetchDataFromServer,
                        args: [tablename, callbackfunc, 0, 0, 0]
                    });
                };
                r.promiseLoad = function () {
                    var host = {};
                    Thread.setTimeout({
                        func: r.load,
                        args: [function () {
                            Thread.setTimeout({func: host.resolve});
                        }]
                    });
                    return new Promise(function(resolve, reject) {
                        host.resolve = resolve;
                        host.reject = reject;
                    });
                };
                r.reset = function (callbackfunc) {
                    fcore.resetTable(core, tablename, function () {
                        Thread.setTimeout({
                            func: core.fetchDataFromServer,
                            args: [tablename, callbackfunc, 0, 0, 0]
                        });
                    });
                }
                r.promiseReset = function () {
                    var host = {};
                    Thread.setTimeout({
                        func: r.reset,
                        args: [function () {
                            Thread.setTimeout({func: host.resolve});
                        }]
                    });
                    return new Promise(function(resolve, reject) {
                        host.resolve = resolve;
                        host.reject = reject;
                    });
                }
                r.search = function (searchFunc, callbackfunc) {
                    return core.search(tablename, searchFunc, callbackfunc);
                };
                r.psearch = function (params) {
                    var nthread, searchFunc, extraParams, callbackfunc;
                    nthread = params.nthread;
                    searchFunc = params.searchFunc;
                    extraParams = params.extraParams;
                    callbackfunc = params.callbackfunc;
                    postFunc = params.postFunc;
                    if (nthread === undefined) nthread = navigator.hardwareConcurrency;
                    if (callbackfunc === undefined) return;
                    if (!EncodingClass.type.isFunction(callbackfunc)) return;
                    if (searchFunc === undefined) return;
                    if (!EncodingClass.type.isFunction(searchFunc)) return;
                    if (postFunc !== undefined) if (!EncodingClass.type.isFunction(postFunc)) postFunc = undefined;
                    core.psearch(tablename, nthread, searchFunc, postFunc, callbackfunc, extraParams);
                };
                r.promiseSearch = function (me) {
                    return function (params) {
                        return new Promise(function(resolve, reject) {
                            me.psearch({
                                nthread: params.nthread,
                                searchFunc: params.searchFunc,
                                extraParams: params.extraParams,
                                postFunc: params.postFunc,
                                callbackfunc: function (retval) {
                                    resolve(retval);
                                }
                            });
                        });
                    }
                } (r);
                return r;
            }
        } (core);

        core.load = function (core) {
            return function (tablename, mode, callbackfunc, options) {
                if (core.inited[tablename] === undefined) {
                    core.init(tablename, mode, function (success) {
                        if (success) {
                            core.inited[tablename] = true;
                            core.tables[tablename].instance = core.getInstance(tablename);
                            Thread.setTimeout({
                                func: callbackfunc,
                                args: [core.tables[tablename].instance]
                            });
                        }
                        else {
                            Thread.setTimeout({
                                func: callbackfunc,
                                args: []
                            });
                        }
                    }, options);
                    return;
                }
                if (core.inited[tablename] === null) {
                    Thread.wait(
                        function (tablename) {
                            return function () {
                                return (core.inited[tablename] !== null) && (core.inited[tablename] !== undefined);
                            }
                        } (tablename),
                        function (callbackfunc, tablename) {
                            return function () {
                                Thread.setTimeout({
                                    func: callbackfunc,
                                    args: [core.tables[tablename].instance]
                                });
                            }
                        } (callbackfunc, tablename)
                    );
                    return;
                }
                Thread.setTimeout({
                    func: callbackfunc,
                    args: [core.tables[tablename].instance]
                });
            }
        } (core);

        core.promiseLoad = function (core) {
            return function (tablename, mode, options) {
                return new Promise(function(resolve, reject) {
                    core.load(tablename, mode, function (result) {
                        Thread.setTimeout({
                            func: resolve,
                            args: [result]
                        });
                    }, options);
                });
            }
        } (core);

        core.searchblob = Thread.generateBlob({
            extcode: "var searchFunc, extraParams, format, mode, window = {};\r\n" +
                    EncodingClass.exportCode(),
            func: function (params) {
                var task, content, segno, ffsets, id, fs;
                var i, j, r, v, xv;
                var slen, tdata, tlength;
                task = params[0];
                content = params[1];
                switch (task) {
                    case "func":
                        r = EncodingClass.pack.fromUint8Array(content.searchFunc);
                        r = r.read();
                        searchFunc = r.searchFunc;
                        extraParams = r.extraParams;
                        r = null;
                        format = content.format;
                        mode = content.mode;
                        return true;
                    case "search":
                        r = [];
                        switch (mode) {
                            case "row":
                                for (i = 0; i < content.data.length; i++) {
                                    v = EncodingClass.string.fromUint8Array(content.data[i]);
                                    v = EncodingClass.number.toStructRecord(format, v);
                                    delete v.uts;
                                    try {
                                        v = searchFunc(v);
                                        if (v !== null) r.push(v);
                                    }
                                    catch (e) {
                                    }
                                }
                                break;
                            case "block":
                                for (i = 0; i < content.data.length; i++) {
                                    v = content.data[i];
                                    if (EncodingClass.type.isNumber(v)) {
                                        length = EncodingClass.number.fromArray("i32", content.hostdata, v);
                                        v = EncodingClass.string.fromUint8Array(content.hostdata, v + 12, length);
                                    }
                                    else {
                                        v = EncodingClass.string.fromUint8Array(v);
                                    }
                                    v = EncodingClass.number.toStructRecord(format, v);
                                    delete v.uts;
                                    try {
                                        v = searchFunc(v);
                                        if (v !== null) r.push(v);
                                    }
                                    catch (e) {
                                    }
                                }
                                break;
                        }
                        v = EncodingClass.pack.fromVariable(r);
                        r = v.toUint8Array();
                        v.terminate();
                        transferList = [r.buffer];
                        return r;
                    case "clear":
                        searchFunc = null;
                        extraParams = null;
                        format = null;
                        mode = null;
                        return true;
                }
            }
        });

        core.genCallbackRetvalFunc = function (me) {
            return function (retval) {
                Thread.setTimeout({
                    func: me.callbackfunc,
                    args: [retval]
                });
            }
        };

        core.psearch = function (core) {
            return function (tablename, nthread, searchFunc, postFunc, callbackfunc, extraParams) {
                var host = {
                    postFunc: postFunc,
                    threads: [],
                    segLists: [],
                    segKeys: [],
                    nthread: nthread,
                    segMark: [],
                    waiting: 0
                };
                var segno;
                var keys, table;
                var i, t, v;
                if (searchFunc === undefined) return;
                if (core.tables[tablename] === undefined) {
                    Thread.setTimeout({
                        func: callbackfunc,
                        args: [[]]
                    });
                    return;
                };
                table = core.tables[tablename].data;
                keys = Object.keys(table);
                if (keys.length == 0) {
                    Thread.setTimeout({
                        func: callbackfunc,
                        args: [[]]
                    });
                    return;
                }
                t = EncodingClass.pack.fromVariable({
                    searchFunc: searchFunc,
                    extraParams: extraParams
                });
                host.searchFunc = t.toUint8Array();
                t.terminate();
                for (i = 0; i < keys.length; i++) {
                    segno = parseInt(keys[i]) >> 12;
                    if (host.segMark[segno] === undefined) {
                        host.segMark[segno] = true;
                        host.segLists.push(segno);
                    }
                }
                keys = null;
                host.segLists.sort((a, b) => (b - a));
                for (i = 0; i < host.segLists.length; i++) {
                    host.segKeys.push(host.segLists[i]);
                }
                if (nthread > navigator.hardwareConcurrency * 2) nthread = navigator.hardwareConcurrency * 2;
                while (host.threads.length < nthread) {
                    t = {};
                    t.instance = Thread.createFromBlob({
                        blobURL: core.searchblob,
                        callbackfunc: core.genCallbackRetvalFunc(t)
                    })[0];
                    host.threads.push(t);
                }
                host.receiveThread = function (host) {
                    return function (vhost) {
                        vhost.r = EncodingClass.pack.fromUint8Array(vhost.r);
                        vhost.r.read([], function (r) {
                            var i, k, v;
                            if (host.postFunc !== undefined) {
                                for (i = k = 0; i < r.length; i++) {
                                    try {
                                        v = host.postFunc(r[i]);
                                        if (v !== null) r[k++] = v;
                                    }
                                    catch (e) {
                                        console.log("postFunc error", e);
                                    }
                                }
                                while (r.length > k) r.pop();
                            }
                            host.segMark[vhost.segno] = r;
                            vhost.r.terminate();
                            delete vhost.r;
                            delete vhost.segno;
                            host.waiting--;
                        });
                    }
                } (host);

                host.search = function (host) {
                    return function (thread, segno) {
                        var i, t, fs, ts, content = {data: [], segno: segno};
                        var transferList = [];
                        thread.callbackfunc = function (retval) {
                            vhost = {
                                segno: segno,
                                r: retval
                            };
                            host.waiting++;
                            Thread.setTimeout({
                                func: host.workingThread,
                                args: [thread],
                                priority: 9
                            });
                            Thread.setTimeout({
                                func: host.receiveThread,
                                args: [vhost]
                            });
                        }
                        fs = segno << 12;
                        ts = (segno + 1) << 12;
                        switch (core.tables[tablename].mode) {
                            case "row":
                                for (i = fs; i < ts; i++) {
                                    if (core.tables[tablename].data[i] !== undefined) {
                                        t = new Uint8Array(core.tables[tablename].data[i]);
                                        content.data.push(t);
                                        transferList.push(t.buffer);
                                    }
                                }
                                break;
                            case "block":
                                t = new Uint8Array(core.tables[tablename].hostdata[segno]);
                                content.hostdata = t;
                                transferList.push(t.buffer);
                                for (i = fs; i < ts; i++) {
                                    if (core.tables[tablename].data[i] !== undefined) {
                                        if (core.tables[tablename].hostmodified[i] !== undefined) {
                                            t = new Uint8Array(core.tables[tablename].hostmodified[i]);
                                            transferList.push(t.buffer);
                                            content.data.push(t);
                                        }
                                        else {
                                            content.data.push(core.tables[tablename].data[i]);
                                        }
                                    }
                                }
                                break;
                        }
                        thread.instance.call(["search", content], transferList);
                    }
                } (host);
                host.workingThread = function (host) {
                    return function (thread) {
                        if (host.segLists.length > 0) {
                            if (thread === undefined) {
                                if (host.threads.length > 0) {
                                    thread = host.threads.pop();
                                    thread.callbackfunc = function () {
                                        Thread.setTimeout({
                                            func: host.workingThread,
                                            args: [thread]
                                        });
                                    }
                                    EncodingClass.number.duplicateTypedArray(host.searchFunc, function (fdata) {
                                        thread.instance.call(["func", {
                                            searchFunc: fdata,
                                            format: core.tables[tablename].config.format,
                                            mode: core.tables[tablename].mode
                                        }], [fdata.buffer]);
                                    });
                                }
                                return;
                            }
                            host.search(thread, host.segLists.pop());
                            return;
                        }
                        if (thread !== undefined) {
                            thread.callbackfunc = function () {
                                delete thread.callbackfunc;
                                host.threads.push(thread);
                                if (host.threads.length == host.nthread) {
                                    while (host.threads.length > 0) host.threads.pop().instance.terminate();
                                    Thread.wait(
                                        function () {
                                            return host.waiting == 0;
                                        },
                                        function () {
                                            var i, r, segno;
                                            r = [];
                                            while (host.segKeys.length > 0) {
                                                segno = host.segKeys.pop();
                                                for (i = 0; i < host.segMark[segno].length; i++) {
                                                    r.push(host.segMark[segno][i]);
                                                }
                                            }
                                            Thread.setTimeout({
                                                func: callbackfunc,
                                                args: [r]
                                            });
                                        }
                                    );
                                }
                            }
                            thread.instance.call(["clear"]);
                        }
                    }
                } (host);
                while ((host.segLists.length > 0) && (host.threads.length > 0)) host.workingThread();
            }
        } (core);

        core.getIDList = function (core) {
            return function (tablename, callbackfunc) {
                var keys, i;
                if (core.tables[tablename] === undefined) {
                    if (callbackfunc !== undefined) {
                        Thread.setTimeout({
                            func: callbackfunc,
                            args: [[]]
                        });
                    }
                    return [];
                }
                keys = Object.keys(core.tables[tablename].data);
                if (callbackfunc === undefined) {
                    for (i = 0; i < keys.length; i++) {
                        keys[i] = parseInt(keys[i]);
                    }
                    keys.sort((a, b) => (a - b));
                    return keys;
                }
                i = 0;
                Thread.exec(
                    function () {
                        if (i >= keys.length) return true;
                        keys[i] = parseInt(keys[i]);
                        i++;
                        return false;
                    },
                    function () {
                        EncodingClass.number.asyncSort(keys, (a, b) => (a - b), function () {
                            callbackfunc(keys);
                        });
                    }
                );
            }
        } (core);

        core.backgroundSearch = function (core) {
            return function (tablename, searchFunc, callbackfunc) {
                var keys, r = [], index = 0;
                var searchThread = function () {
                    var time = (new Date()).getTime();
                    var v, t, i, ilen;
                    while (index < keys.length) {
                        ilen = keys.length - index;
                        if (ilen > 1024) ilen = 1024;
                        for (i = 0; i < ilen; i++) {
                            t = core.getContent(tablename, keys[index++]);
                            try {
                                v = searchFunc(t);
                                if (v !== null) r.push(v);
                            }
                            catch (e) {
                            }
                        }
                        if ((new Date()).getTime() - time > 40) break;
                    }
                    if (index == keys.length) {
                        if (EncodingClass.type.isFunction(callbackfunc)) {
                            Thread.setTimeout({
                                func: callbackfunc,
                                args: [r]
                            });
                        }
                        return;
                    }
                    Thread.setTimeout({func: searchThread});
                }
                keys = core.getIDList(tablename);
                Thread.setTimeout({func: searchThread});
            }
        } (core);

        core.search = function (core) {
            return function (tablename, searchFunc, callbackfunc) {
                var r = [], keys;
                var i, t, v;
                if (core.tables[tablename] === undefined) {
                    if (callbackfunc !== undefined) {
                        callbackfunc([]);
                        return false;
                    }
                    return [];
                }
                if (callbackfunc === undefined) {
                    keys = core.getIDList(tablename);
                    for (i = 0; i < keys.length; i++) {
                        t = core.getContent(tablename, keys[i]);
                        try {
                            v = searchFunc(t);
                            if (v !== null) r.push(v);
                        }
                        catch (e) {
                        }
                    }
                    return r;
                }
                else {
                    Thread.setTimeout({
                        func: core.backgroundSearch,
                        args: [tablename, searchFunc, callbackfunc]
                    });
                    return true;
                }
            }
        } (core);
        retval.load = function (core) {
            return function (tablename, mode, callbackfunc, fieldList) {
                if (mode === undefined) mode = "block";
                mode = mode.toLowerCase();
                if ((mode != "row") && (mode != "block")) mode = "block";
                core.load(tablename, mode, callbackfunc, fieldList);
            }
        } (core);
        retval.promiseLoad = function (core) {
            return function (tablename, mode, fieldList) {
                return core.promiseLoad(tablename, mode, fieldList);
            }
        } (core);
        retval.erase = function (core) {
            return function (tablename, callbackfunc) {
                core.remove(tablename, function (success) {
                    delete core.tables[tablename];
                    if (debugPrintFlag) console.log("erase table " + tablename, success);
                    Thread.setTimeout({func: callbackfunc});
                });
            }
        } (core);
        retval.eraseAll = function (core) {
            return function (callbackfunc) {
                var keys;
                var i;
                var count = 0;
                keys = Object.keys(core.tables);
                for (i = 0; i < keys.length; i++) {
                    retval.erase(keys[i], function () {
                        count++;
                        if (count == keys.length) Thread.setTimeout({func: callbackfunc});
                    });
                }
            }
        } (core);
        Object.defineProperty(retval, "url", {
            get: function () {
                    return core.url;
            },
            set: function (value) {
                core.url = value;
            }
        });
        if (false) {
            delete retval.erase;
            delete retval.eraseAll;
        }
        return retval;
    }

    return Object.freeze(fcache_retval);
} ());

VaKeR 2022