<commit_before>/**
 * @fileOverview
 * @author bluefox
 * @version 0.2
 */

/** @module statesInMemory */

/* jshint -W097 */
/* jshint strict:false */
/* jslint node: true */
'use strict';

var socketio          = require('socket.io');
var fs                = require('fs');
var getDefaultDataDir = require(__dirname + '/../tools').getDefaultDataDir;

// settings = {
//    change:    function (id, state) {},
//    connected: function (nameOfServer) {},
//    logger: {
//           silly: function (msg) {},
//           debug: function (msg) {},
//           info:  function (msg) {},
//           warn:  function (msg) {},
//           error: function (msg) {}
//    },
//    connection: {
//           dataDir: 'relative path'
//    },
//    processObjects: false/true,
//    auth: null, //unused
//    secure: true/false,
//    certificates: as required by createServer
//    port: 9000,
//    host: localhost
// };
//

function StatesInMemory(settings) {
    if (!(this instanceof StatesInMemory)) return new StatesInMemory(settings);
    settings            = settings || {};

    var change          = settings.change;

    var states          = {};
    var objects         = {};
    var fifo            = {};
    var messagebox      = {};
    var logs            = {};
    var session         = {};
    var globalMessageId = Math.round(Math.random() * 100000000);
    var globalLogId     = Math.round(Math.random() * 100000000);

    var expires         = [];
    var adapterSubs     = [];
    var lastExpire      = null;
    var expiresInterval = null;
    var namespace       = settings.namespace || '';

    // path is always relative to appName.js-controller
    var dataDir = (settings.connection.dataDir || getDefaultDataDir());
    if (dataDir) {
        if (dataDir[0] === '.' && dataDir[1] === '.') {
            dataDir = __dirname + '/../../' + dataDir;
        } else if (dataDir[0] === '.' && dataDir[1] === '/') {
            dataDir = __dirname + '/../../' + dataDir.substring(2);
        }
    }
    dataDir = dataDir.replace(/\\/g, '/');
    if (dataDir[dataDir.length - 1] !== '/') dataDir += '/';

    var objectsName = dataDir + 'objects.json';
    var fifosName   = dataDir + 'fifos.json';
    var statesName  = dataDir + 'states.json';
    objectsName += 'objects.json';


    var stateTimer =        null;
    var configTimer =       null;
    var fifoTimer =         null;

    var that =              this;

    var log = settings.logger;
    if (!log) {
        log = {
            silly: function (msg) {/*console.log(msg);*/},
            debug: function (msg) {/*console.log(msg);*/},
            info:  function (msg) {/*console.log(msg);*/},
            warn:  function (msg) {
                console.log(msg);
            },
            error: function (msg) {
                console.log(msg);
            }
        };
    } else if (!log.silly) {
        log.silly = log.debug;
    }

    var server = {
        app:       null,
        server:    null,
        io:        null,
        settings:  settings
    };

    var __construct = (function () {
        settings.connection.maxQueue = settings.connection.maxQueue || 1000;

        // load values from file
        if (fs.existsSync(statesName)) {
            try {
                states = JSON.parse(fs.readFileSync(statesName).toString());
            } catch (e) {
                log.error(namespace + ' Cannot parse ' + statesName + ': ' + e);
                if (fs.existsSync(statesName + '.bak')) {
                    try {
                        states = JSON.parse(fs.readFileSync(statesName + '.bak').toString());
                    } catch (e) {
                        log.error(namespace + ' Cannot parse ' + statesName + '.bak: ' + e);
                        states = {};
                    }
                } else {
                    states = {};
                }
            }
        } else if (fs.existsSync(statesName + '.bak')) {
            try {
                states = JSON.parse(fs.readFileSync(statesName + '.bak').toString());
            } catch (e) {
                log.error(namespace + ' Cannot parse ' + statesName + '.bak: ' + e);
                states = {};
            }
        } else {
            states = {};
        }

        if (fs.existsSync(fifosName)) {
            try {
                fifo = JSON.parse(fs.readFileSync(fifosName).toString());
            } catch (e) {
                log.error(namespace + ' Cannot parse ' + fifosName + ': ' + e);
                if (fs.existsSync(fifosName + '.bak')) {
                    try {
                        fifo = JSON.parse(fs.readFileSync(fifosName + '.bak').toString());
                    } catch (e) {
                        log.error(namespace + ' Cannot parse ' + fifosName + '.bak: ' + e);
                        fifo = {};
                    }
                } else {
                    fifo = {};
                }
            }
        } else if (fs.existsSync(fifosName + '.bak')) {
            try {
                fifo = JSON.parse(fs.readFileSync(fifosName + '.bak').toString());
            } catch (e) {
                log.error(namespace + ' Cannot parse ' + fifosName + '.bak: ' + e);
                fifo = {};
            }
        } else {
            fifo = {};
        }

        if (settings.processObjects && fs.existsSync(objectsName)) {
            try {
                objects = JSON.parse(fs.readFileSync(objectsName).toString());
            } catch (e) {
                log.error(namespace + ' Cannot parse ' + objectsName + ': ' + e);
                if (fs.existsSync(objectsName + '.bak')) {
                    try {
                        objects = JSON.parse(fs.readFileSync(objectsName + '.bak').toString());
                    } catch (e) {
                        log.error(namespace + ' Cannot parse ' + objectsName + '.bak: ' + e);
                        objects = {};
                    }
                } else {
                    objects = {};
                }
            }
        } else if (fs.existsSync(objectsName + '.bak')) {
            try {
                objects = JSON.parse(fs.readFileSync(objectsName + '.bak').toString());
            } catch (e) {
                log.error(namespace + ' Cannot parse ' + objectsName + '.bak: ' + e);
                objects = {};
            }
        } else {
            objects = {};
        }

        // Reset expires, that are still in DB
        expireAll();

        // Check if directory exists
        objectsName = objectsName.replace(/\\/g, '/');
        var parts = objectsName.split('/');
        parts.pop();
        parts = parts.join('/');
        if (!fs.existsSync(parts)) fs.mkdirSync(parts);

        _initWebServer(settings.connection, server);

        if (settings.connected) {
            setImmediate(function () {
                settings.connected('InMemoryDB');
            });
        }
    })();

    function expireAll() {
        for (var i = expires.length - 1; i >= 0; i--) {
            var e = expires[i];
            if (states[e]) {
                states[e].ts  = (new Date()).getTime();
                states[e].lc = (states[e].val) ? states[e].ts : states[e].lc;
                states[e].val = null;
                delete states[e].expire;
                that.publishAll('state', e, states[e]);
            }
        }
        // Set as expire all states that could expire
        for (var t in states) {
            if (!states.hasOwnProperty(t)) continue;
            if (states[t].expire !== undefined) {
                states[t].ts  = (new Date()).getTime();
                states[t].lc = (states[t].val) ? states[t].ts : states[t].lc;
                states[t].val = null;
                delete states[t].expire;
            }
        }
        expires = [];
    }

    function expiresCheck() {
        var now = (new Date()).getTime();
        if (lastExpire !== null) {
            var diff = now - lastExpire;
            var count = 0;
            for (var i = expires.length - 1; i >= 0; i--) {
                var e = expires[i];<commit_msg>(bluefox) fix some errors by restore<commit_after>/**
 * @fileOverview
 * @author bluefox
 * @version 0.2
 */

/** @module statesInMemory */

/* jshint -W097 */
/* jshint strict:false */
/* jslint node: true */
'use strict';

var socketio          = require('socket.io');
var fs                = require('fs');
var getDefaultDataDir = require(__dirname + '/../tools').getDefaultDataDir;

// settings = {
//    change:    function (id, state) {},
//    connected: function (nameOfServer) {},
//    logger: {
//           silly: function (msg) {},
//           debug: function (msg) {},
//           info:  function (msg) {},
//           warn:  function (msg) {},
//           error: function (msg) {}
//    },
//    connection: {
//           dataDir: 'relative path'
//    },
//    processObjects: false/true,
//    auth: null, //unused
//    secure: true/false,
//    certificates: as required by createServer
//    port: 9000,
//    host: localhost
// };
//

function StatesInMemory(settings) {
    if (!(this instanceof StatesInMemory)) return new StatesInMemory(settings);
    settings            = settings || {};

    var change          = settings.change;

    var states          = {};
    var objects         = {};
    var fifo            = {};
    var messagebox      = {};
    var logs            = {};
    var session         = {};
    var globalMessageId = Math.round(Math.random() * 100000000);
    var globalLogId     = Math.round(Math.random() * 100000000);

    var expires         = [];
    var adapterSubs     = [];
    var lastExpire      = null;
    var expiresInterval = null;
    var namespace       = settings.namespace || '';

    // path is always relative to appName.js-controller
    var dataDir = (settings.connection.dataDir || getDefaultDataDir());
    if (dataDir) {
        if (dataDir[0] === '.' && dataDir[1] === '.') {
            dataDir = __dirname + '/../../' + dataDir;
        } else if (dataDir[0] === '.' && dataDir[1] === '/') {
            dataDir = __dirname + '/../../' + dataDir.substring(2);
        }
    }
    dataDir = dataDir.replace(/\\/g, '/');
    if (dataDir[dataDir.length - 1] !== '/') dataDir += '/';

    var objectsName = dataDir + 'objects.json';
    var fifosName   = dataDir + 'fifos.json';
    var statesName  = dataDir + 'states.json';
    objectsName += 'objects.json';


    var stateTimer =        null;
    var configTimer =       null;
    var fifoTimer =         null;

    var that =              this;

    var log = settings.logger;
    if (!log) {
        log = {
            silly: function (msg) {/*console.log(msg);*/},
            debug: function (msg) {/*console.log(msg);*/},
            info:  function (msg) {/*console.log(msg);*/},
            warn:  function (msg) {
                console.log(msg);
            },
            error: function (msg) {
                console.log(msg);
            }
        };
    } else if (!log.silly) {
        log.silly = log.debug;
    }

    var server = {
        app:       null,
        server:    null,
        io:        null,
        settings:  settings
    };

    var __construct = (function () {
        settings.connection.maxQueue = settings.connection.maxQueue || 1000;

        // load values from file
        if (fs.existsSync(statesName)) {
            try {
                states = JSON.parse(fs.readFileSync(statesName).toString());
            } catch (e) {
                log.error(namespace + ' Cannot parse ' + statesName + ': ' + e);
                if (fs.existsSync(statesName + '.bak')) {
                    try {
                        states = JSON.parse(fs.readFileSync(statesName + '.bak').toString());
                    } catch (e) {
                        log.error(namespace + ' Cannot parse ' + statesName + '.bak: ' + e);
                        states = {};
                    }
                } else {
                    states = {};
                }
            }
        } else if (fs.existsSync(statesName + '.bak')) {
            try {
                states = JSON.parse(fs.readFileSync(statesName + '.bak').toString());
            } catch (e) {
                log.error(namespace + ' Cannot parse ' + statesName + '.bak: ' + e);
                states = {};
            }
        } else {
            states = {};
        }

        if (fs.existsSync(fifosName)) {
            try {
                fifo = JSON.parse(fs.readFileSync(fifosName).toString());
            } catch (e) {
                log.error(namespace + ' Cannot parse ' + fifosName + ': ' + e);
                if (fs.existsSync(fifosName + '.bak')) {
                    try {
                        fifo = JSON.parse(fs.readFileSync(fifosName + '.bak').toString());
                    } catch (e) {
                        log.error(namespace + ' Cannot parse ' + fifosName + '.bak: ' + e);
                        fifo = {};
                    }
                } else {
                    fifo = {};
                }
            }
        } else if (fs.existsSync(fifosName + '.bak')) {
            try {
                fifo = JSON.parse(fs.readFileSync(fifosName + '.bak').toString());
            } catch (e) {
                log.error(namespace + ' Cannot parse ' + fifosName + '.bak: ' + e);
                fifo = {};
            }
        } else {
            fifo = {};
        }

        if (settings.processObjects && fs.existsSync(objectsName)) {
            try {
                objects = JSON.parse(fs.readFileSync(objectsName).toString());
            } catch (e) {
                log.error(namespace + ' Cannot parse ' + objectsName + ': ' + e);
                if (fs.existsSync(objectsName + '.bak')) {
                    try {
                        objects = JSON.parse(fs.readFileSync(objectsName + '.bak').toString());
                    } catch (e) {
                        log.error(namespace + ' Cannot parse ' + objectsName + '.bak: ' + e);
                        objects = {};
                    }
                } else {
                    objects = {};
                }
            }
        } else if (fs.existsSync(objectsName + '.bak')) {
            try {
                objects = JSON.parse(fs.readFileSync(objectsName + '.bak').toString());
            } catch (e) {
                log.error(namespace + ' Cannot parse ' + objectsName + '.bak: ' + e);
                objects = {};
            }
        } else {
            objects = {};
        }

        // Reset expires, that are still in DB
        expireAll();

        // Check if directory exists
        objectsName = objectsName.replace(/\\/g, '/');
        var parts = objectsName.split('/');
        parts.pop();
        parts = parts.join('/');
        if (!fs.existsSync(parts)) fs.mkdirSync(parts);

        _initWebServer(settings.connection, server);

        if (settings.connected) {
            setImmediate(function () {
                settings.connected('InMemoryDB');
            });
        }
    })();

    function expireAll() {
        for (var i = expires.length - 1; i >= 0; i--) {
            var e = expires[i];
            if (states[e]) {
                states[e].ts  = (new Date()).getTime();
                states[e].lc = (states[e].val) ? states[e].ts : states[e].lc;
                states[e].val = null;
                delete states[e].expire;
                that.publishAll('state', e, states[e]);
            }
        }
        // Set as expire all states that could expire
        for (var t in states) {
            if (!states.hasOwnProperty(t) || !states[t]) continue;
            if (states[t].expire !== undefined) {
                states[t].ts  = (new Date()).getTime();
                states[t].lc = (states[t].val) ? states[t].ts : states[t].lc;
                states[t].val = null;
                delete states[t].expire;
            }
        }
        expires = [];
    }

    function expiresCheck() {
        var now = (new Date()).getTime();
        if (lastExpire !== null) {
            var diff = now - lastExpire;
            var count = 0;
            for (var i = expires.length - 1; i >= 0; i--) {
                var e = expires[i];
{'fraction_non_alphanumeric': 0.15153747007917512, 'fraction_numerical': 0.005155588289449457, 'mean_word_length': 1.3444604316546762, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 4, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6516586', 'n_tokens_mistral': 4714, 'n_tokens_neox': 4455, 'n_words': 1003}