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

📄 timeseries.h

📁 嵌入式数据库软件 嵌入式数据库软件 嵌入式数据库软件
💻 H
📖 第 1 页 / 共 2 页
字号:
     * to doubled number of seconds in day multipied on maxElementsInBlock     */    dbTimeSeriesProcessor(dbDatabase& database, int minElementsInBlock=100, int maxElementsInBlock=100, time_t maxBlockTimeInterval=0) :        db(database)     {        assert(minElementsInBlock > 0 && maxElementsInBlock >= minElementsInBlock);        if (maxBlockTimeInterval == 0) {             maxBlockTimeInterval = 2*(maxElementsInBlock*24*60*60); // doubled interval in seconds, one element per day        }                this->maxElementsInBlock = maxElementsInBlock;        this->minElementsInBlock = minElementsInBlock;        this->maxBlockTimeInterval = maxBlockTimeInterval;        // correct instance of interval will be specified in select        Interval* dummy = NULL;        selectBlock = "blockId between",dummy->from,"and",dummy->till;        selectBlockReverse = "blockId between",dummy->from,"and",dummy->till,"order by blockId desc";    }    /**     * Remove elements for the sepcified period     * @param oid time series identifer (OID of the object associated with this time series)     * @param from inclusive low bound for element timestamp (set 0 to disable this criteria)     * @param till inclusive high bound for element timestamp (set INFINITE_TIME to disable this criteria)     * @return number of removed elements     */    int remove(oid_t oid, time_t from, time_t till)    {        Interval interval;        interval.from = generateBlockId(oid, from == 0 ? 0 : from - maxBlockTimeInterval);        interval.till = generateBlockId(oid, till);        dbCursor< dbTimeSeriesBlock<T> > blocks;        size_t nRemoved = 0;        if (blocks.select(selectBlock, dbCursorForUpdate, &interval)) {             do {                 int n = blocks->used;                T const* e =  blocks->elements.get();                int l = 0, r = n;                while (l < r)  {                    int i = (l+r) >> 1;                    if (from > e[i].time()) {                         l = i+1;                    } else {                         r = i;                    }                }                assert(l == r && (l == n || e[l].time() >= from));                 while (r < n && e[r].time() <= till) {                    r += 1;                    nRemoved += 1;                }                if (l == 0 && r == n) {                     blocks.remove();                } else if (l < n && l != r) {                     if (l == 0) {                         blocks->blockId = generateBlockId(oid, e[r].time());                    }                    T* ue = blocks->elements.update();                    while (r < n) {                         ue[l++] = ue[r++];                    }                    blocks->used = l;                    blocks.update();                }            } while (blocks.nextAvailable());        }        return nRemoved;    }                virtual~dbTimeSeriesProcessor() {}    /**     * This method should be actually private but since there is no portable way of declaration      * of friend templates classes recognized by all C++ compiler, it is made public.     * Do not use this method yourself.     */    int _openIteratorCursor(dbCursor< dbTimeSeriesBlock<T> >& cursor, oid_t oid, time_t from, time_t till)     {         Interval interval;        interval.from = generateBlockId(oid, from == 0 ? 0 : from - maxBlockTimeInterval);        interval.till = generateBlockId(oid, till);        return cursor.select(selectBlock, dbCursorViewOnly, &interval);    }   private:     db_int8 generateBlockId(oid_t oid, time_t date)      {        return cons_int8(oid, date);     }               void addNewBlock(oid_t oid, T const& data)     {         dbTimeSeriesBlock<T> block;         block.blockId = generateBlockId(oid, data.time());         block.elements.resize(minElementsInBlock);         block.used = 1;         block.elements.putat(0, data);         insert(block);     }     void insertInBlock(oid_t oid, dbCursor< dbTimeSeriesBlock<T> >& blocks, T const& data)     {         time_t t = data.time();         int i, n = blocks->used;         T const* e =  blocks->elements.get();         int l = 0, r = n;         while (l < r)  {             i = (l+r) >> 1;             if (t > e[i].time()) {                  l = i+1;             } else {                  r = i;             }         }         assert(l == r && (l == n || e[l].time() >= t));         if (r == 0) {              if (e[n-1].time() - t > maxBlockTimeInterval || n == maxElementsInBlock) {                  addNewBlock(oid, data);                 return;             }             blocks->blockId = generateBlockId(oid, t);         } else if (r == n) {             if (t - e[0].time() > maxBlockTimeInterval || n == maxElementsInBlock) {                  addNewBlock(oid, data);                 return;             }          }         if ((size_t)n == blocks->elements.length()) {              if (n == maxElementsInBlock) {                  T* u = blocks->elements.update();                 addNewBlock(oid, u[n-1]);                 for (i = n; --i > r; ) {                      u[i] = u[i-1];                 }                 u[r] = data;                 blocks.update();                 return;             }             blocks->elements.resize(n + minElementsInBlock < maxElementsInBlock ? n + minElementsInBlock : maxElementsInBlock);         }         T* u = blocks->elements.update();         for (i = n; i > r; i--) {              u[i] = u[i-1];         }         u[r] = data;         blocks->used += 1;         blocks.update();     }     dbDatabase& db;     int         maxElementsInBlock;     int         minElementsInBlock;     time_t      maxBlockTimeInterval;          dbQuery     selectBlock;     dbQuery     selectBlockReverse; };    /** * Time series forward iterator  */template<class T>class dbTimeSeriesIterator {   public:    /**     * Start iteration through elements belonging to the specified range.     * @param processor pointer to time series processor     * @param oid time series identifer (OID of the object associated with this time series)     * @param from inclusive low bound for element timestamp (set 0 to disable this criteria)     * @param till inclusive high bound for element timestamp (set INFINITE_TIME to disable this criteria)     */    void start(dbTimeSeriesProcessor<T>* processor, oid_t oid, time_t from, time_t till) {         first = pos = -1;        this->till = till;        if (processor->_openIteratorCursor(blocks, oid, from, till)) {             do {                 int n = blocks->used;                T const* e =  blocks->elements.get();                int l = 0, r = n;                while (l < r)  {                    int i = (l+r) >> 1;                    if (from > e[i].time()) {                         l = i+1;                    } else {                         r = i;                    }                }                assert(l == r && (l == n || e[l].time() >= from));                 if (l < n) {                     if (e[l].time() <= till) {                        first = pos = l;                    }                    return;                }            } while (blocks.next());        }            }                /**     * Get current iterator element     * @return <code>true</code> if there is current element, <code>false</code> otherwise     */    bool current(T& elem) {         if (pos >= 0) {             elem = blocks->elements[pos];            return true;        }        return false;    }        /**     * Move iterator position to next element.     * @return <code>true</code> if next element exists, <code>false</code> otherwise     */    bool next() {         if (pos >= 0) {             if (++pos == blocks->used) {                 if (!blocks.next()) {                     pos = -1;                    return false;                }                pos = 0;            }            if (blocks->elements[pos].time() <= till) {                return true;            }            pos = -1;        }        return false;    }    /**     * Reset iterator to the initial state     */    void reset() {         blocks.first();        pos = first;    }        /**     * Iterator costructor. If current() or next() method will always return false if     * them are invoked prior to start()     */    dbTimeSeriesIterator() {        first = pos = -1;    }  private:    dbCursor< dbTimeSeriesBlock<T> > blocks;    int                              pos;    int                              first;    time_t                           till;};    /** * Time series reverse iterator  */template<class T>class dbTimeSeriesReverseIterator {   public:    /**     * Start iteration through elements belonging to the specified range.     * @param processor pointer to time series processor     * @param oid time series identifer (OID of the object associated with this time series)     * @param from inclusive low bound for element timestamp (set 0 to disable this criteria)     * @param till inclusive high bound for element timestamp (set INFINITE_TIME to disable this criteria)     */    void start(dbTimeSeriesProcessor<T>* processor, oid_t oid, time_t from, time_t till) {         last = pos = -1;        this->from = from;        if (processor->_openIteratorCursor(blocks, oid, from, till)) {             do {                 int n = blocks->used;                blocks.last();                T const* e =  blocks->elements.get();                int l = 0, r = n;                while (l < r)  {                    int i = (l+r) >> 1;                    if (till >= e[i].time()) {                         l = i+1;                    } else {                         r = i;                    }                }                assert(l == r && (l == n || e[l].time() > till));                 if (l > 0) {                    if (e[l-1].time() >= from) {                        last = pos = l-1;                    }                    return;                }            } while (blocks.prev());        }            }                /**     * Get current iterator element     * @return <code>true</code> if there is current element, <code>false</code> otherwise     */    bool current(T& elem) {         if (pos >= 0) {             elem = blocks->elements[pos];            return true;        }        return false;    }        /**     * Move iterator position to next element.     * @return <code>true</code> if next element exists, <code>false</code> otherwise     */    bool next() {         if (pos >= 0) {             if (--pos < 0) {                if (!blocks.prev()) {                     return false;                }                pos = blocks->used-1;            }            if (blocks->elements[pos].time() >= from) {                return true;            }            pos = -1;        }        return false;    }    /**     * Reset iterator to the initial state     */    void reset() {         blocks.last();        pos = last;    }        /**     * Iterator costructor. If current() or next() method will always return false if     * them are invoked prior to start()     */    dbTimeSeriesReverseIterator() {        last = pos = -1;    }  private:    dbCursor< dbTimeSeriesBlock<T> > blocks;    int                              pos;    int                              last;    time_t                           from;};    #endif

⌨️ 快捷键说明

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