OSDN Git Service

alpha1 development in progress
authortkawata <takuji.kawata@gmail.com>
Wed, 28 Mar 2012 14:15:11 +0000 (23:15 +0900)
committertkawata <takuji.kawata@gmail.com>
Wed, 28 Mar 2012 14:15:11 +0000 (23:15 +0900)
- key-value storage enabled cell (BS) completed.
- test content file is provided in sample/Sample2_SimpleStorageCells

21 files changed:
Samples/Samples/Sample2_SimpleStorageCells/Container/cells.xhtml [new file with mode: 0644]
Samples/Samples/Sample2_SimpleStorageCells/Container/dstyle.css [new file with mode: 0644]
Samples/Samples/Sample2_SimpleStorageCells/property.xml [new file with mode: 0644]
Samples/Samples/Sample2_SimpleStorageCells/ui/index.html [new file with mode: 0644]
Source/DNEngine.cpp
Source/DNStorage.cpp
Source/DNStorage.h
Source/DNStorageImpl.h
Source/QtScript/dnqsbasiccell.cpp
Source/QtScript/dnqsbasiccell.h
Source/QtScript/dnqsbasicstoragecell.cpp [new file with mode: 0644]
Source/QtScript/dnqsbasicstoragecell.h [new file with mode: 0644]
Source/QtScript/dnqscellcode.cpp
Source/QtScript/dnqscellcodeinstance.cpp
Source/QtScript/dnqscontainer.cpp
Source/QtScript/dnqscontainer.h
Source/TKContainer.cpp
Source/TKContainer.h
Source/platform/qt/qtdnstorageimpl.cpp
Source/platform/qt/qtdnstorageimpl.h
dennco.pro

diff --git a/Samples/Samples/Sample2_SimpleStorageCells/Container/cells.xhtml b/Samples/Samples/Sample2_SimpleStorageCells/Container/cells.xhtml
new file mode 100644 (file)
index 0000000..8c52a13
--- /dev/null
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+<head><title>Dennco - test1</title>
+<link rel="stylesheet" type="text/css" href="dstyle.css" />  
+</head>
+
+<body>
+<h1>Sample2 - persistent storage test</h1>
+
+<a define="cell"  name="ConsoleOut">
+<a parameter="cellcode"  type="B"> </a>
+<pre parameter="script"> 
+<![CDATA[
+function doTick(time)   
+{
+       print("\nTickTime: " + time.toFixed(3));
+       print("   AutoCounter             :" + this.cell.receptors.CounterValue);
+       print("   PersistentAutoCounter   :" + this.cell.receptors.PersistentCounterValue);
+}
+]]>
+</pre>
+</a>
+
+<a define="cell"  name="AutoCounter">
+<a parameter="cellcode"  type="B"> </a>
+<pre parameter="script"> 
+<![CDATA[
+var counter = 0;
+function doTick(time)   
+{
+       this.counter ++;
+       this.cell.axonValue = counter;
+}
+]]>
+</pre>
+<a parameter="connection" href="#ConsoleOut" receptor="CounterValue"></a>
+<a parameter="connection" href="#output1" receptor="autoCounter"></a>
+</a>
+
+<a define="cell"  name="PersistentAutoCounter">
+<a parameter="cellcode"  type="BS"> </a>
+<pre parameter="script"> 
+<![CDATA[
+var counter;
+function doInit()
+{
+       counter = this.cell.storage.getValue("counter");
+       if (counter == undefined)
+       {
+               counter = 0;
+               this.cell.storage.setValue("counter", counter);
+       }
+}
+
+function doTick(time)   
+{
+       this.counter ++;
+       this.cell.axonValue = counter;
+}
+
+function doDestroy()
+{
+       this.cell.storage.setValue("counter", counter);
+}
+]]>
+</pre>
+<a parameter="connection" href="#ConsoleOut" receptor="PersistentCounterValue"></a>
+<a parameter="connection" href="#output2" receptor="persistentAutoCounter"></a>
+</a>
+
+<a define="cell"  name="output1"><a parameter="cellcode"  type="O"></a></a>
+<a define="cell"  name="output2"><a parameter="cellcode"  type="O"></a></a>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/Samples/Samples/Sample2_SimpleStorageCells/Container/dstyle.css b/Samples/Samples/Sample2_SimpleStorageCells/Container/dstyle.css
new file mode 100644 (file)
index 0000000..b22eed2
--- /dev/null
@@ -0,0 +1,51 @@
+
+a[define] {
+       border-top:    1px solid gray;
+       text-indent:   1em;
+       display:       block;
+       margin-top:    32px;
+       margin-bottom: 8px;
+} 
+
+a[define="cellcode"]:before {
+       content:       "Definition of CellCode : " attr(name)      "  (type:" attr(type) ")" ;
+       font-size:     large;
+       font-weight:   bold;
+       display:       inline;
+       white-space:   pre;
+}
+
+
+a[define="cell"]:before {
+       content:       "Definition of Cell : " attr(name)  ;
+       font-size:     large;
+       font-weight:   bold;
+       display:       inline;
+       white-space:   pre;
+}
+         
+a[parameter="cellcode"]:before {
+       content:       "CellCode : " attr(href)  attr(type); 
+       display:       inline;
+}
+
+a[parameter="cellcode"] {
+       text-indent:   1em;
+       display:       block;
+}
+
+a[parameter="connection"]:before {
+       content:       "-> " attr(href)  "(" attr(name) ")"; 
+       display:       inline;
+}
+
+a[parameter="connection"] {
+       text-indent:   2em;
+       display:       block;
+}
+
+[parameter="script"] { 
+        border:             1px solid gray;
+        background-color:   #f0f0cc;
+        margin-left:        2em;
+}
diff --git a/Samples/Samples/Sample2_SimpleStorageCells/property.xml b/Samples/Samples/Sample2_SimpleStorageCells/property.xml
new file mode 100644 (file)
index 0000000..e2adbbd
--- /dev/null
@@ -0,0 +1,8 @@
+<dennco>
+
+<TickIntervalSec>1.0</TickIntervalSec>
+<UIPath>/ui/index.html</UIPath>
+<EnableHTTPServer>no</EnableHTTPServer> <!-- not implemented yet -->
+<EnableSerialServer>no</EnableSerialServer> <!-- not implemented yet -->
+
+</dennco>
\ No newline at end of file
diff --git a/Samples/Samples/Sample2_SimpleStorageCells/ui/index.html b/Samples/Samples/Sample2_SimpleStorageCells/ui/index.html
new file mode 100644 (file)
index 0000000..8b1d928
--- /dev/null
@@ -0,0 +1,34 @@
+<html>
+<head>
+<title>Dennco Sample2 - Persistent storage test</title>
+<script type="text/javascript">
+var timerId = setInterval("updateOutput()", 500);
+
+function updateOutput()
+{
+       document.getElementById("output1Value").value = engine.getValue('/cells.xhtml#output1');
+       document.getElementById("output2Value").value = engine.getValue('/cells.xhtml#output2');
+}
+
+
+function stopTimer()
+{
+       clearInterval(timerId);
+}
+</script>
+</head>
+<body onunload="stopTimer()">
+<h3>Sample2 - Persistent storage test</h3>
+<table border=1 cellspacing=0 cellpadding=2>
+<tr>
+<td>Output from AutoCounter cell</td>
+<td><input type="text" disabled size="6" style="text-align:right" id="output1Value"/></td>
+</tr>
+<tr>
+<td>Output from PersistentAutoCounter cell</td>
+<td><input type="text" disabled size="6" style="text-align:right" id="output2Value"/></td>
+</tr>
+</table>
+
+</body>
+</html>
index 0e30595..03a47a2 100644 (file)
@@ -47,7 +47,8 @@ DNEngine::DNEngine(const char *contentPath) :
     dnGlobal()->updateRunningStatus(DNGlobal::STOPPED);
 
     std::string basePath(contentPath);
-    std::string containerRoot = basePath.append("/Container");
+    std::string containerRoot = basePath;
+    containerRoot.append("/Container");
     
     bool succeeded = false;
     succeeded = parseSettingFile(contentPath);
@@ -64,13 +65,17 @@ DNEngine::DNEngine(const char *contentPath) :
         }
         return;
     }
-    succeeded = parseContainerFile(containerRoot.c_str());
+
+    std::string dataStorePath = containerRoot;
+    dataStorePath.append("/data.db");
+
+    succeeded = mContainer->setDataStore(dataStorePath.c_str());
     if (!succeeded)
     {
         if (dnGlobal()->updateErrorStatus(DNGlobal::ERROR))
         {
             dnGlobal()->setMessage1("Initialization failed");
-            dnGlobal()->setMessage2("Failed to parse container file");
+            dnGlobal()->setMessage2("Failed to the setup data store");
         }
         else
         {
@@ -79,15 +84,13 @@ DNEngine::DNEngine(const char *contentPath) :
         return;
     }
 
-    std::string dataStorePath = containerRoot.append("/data.db");
-
-    succeeded = mContainer->setDataStore(dataStorePath.c_str());
+    succeeded = parseContainerFile(containerRoot.c_str());
     if (!succeeded)
     {
         if (dnGlobal()->updateErrorStatus(DNGlobal::ERROR))
         {
             dnGlobal()->setMessage1("Initialization failed");
-            dnGlobal()->setMessage2("Failed to the setup data store");
+            dnGlobal()->setMessage2("Failed to parse container file");
         }
         else
         {
@@ -273,6 +276,12 @@ bool DNEngine::stopEngine()
         delete mDoTickThread;
         mDoTickThread = NULL;
     }
+    if (mContainer)
+    {
+        mContainer->doDestroy();
+        mContainer->releaseDataStore();
+    }
+
     return r;
 }
 
index 363106a..2d5cb47 100644 (file)
@@ -45,6 +45,16 @@ bool  DNStorage::setValue(const char *path, const char *key, float value)
     return r;
 }
 
+int DNStorage::getCount(const char *path, const char *key)
+{
+    int r = 0;
+    if (impl)
+    {
+        r = impl->getCount(path,key);
+    }
+    return r;
+}
+
 float  DNStorage::getValue(const char *path, const char *key)
 {
     float r = 0;
index c9a3ed0..a18f656 100644 (file)
@@ -91,6 +91,7 @@ public:
     //methods for simple key-value storage
     bool                    setValue(const char *path, const char *key, float value);
     float                   getValue(const char *path, const char *key);
+    int                     getCount(const char *path, const char *key);
 
     //methods for dataset storage
     int                     insertToDataSet(const char *path, const char *key, float v, float x, float y, float z);
index 3590f4a..0ff4fb5 100644 (file)
@@ -30,6 +30,7 @@ public:
     virtual ~DNStorageImpl() {}
     virtual bool                    setValue(const char *path, const char *key, float value) = 0;
     virtual float                   getValue(const char *path, const char *key) = 0;
+    virtual int                     getCount(const char *path, const char *key) = 0;
 
     virtual int                     insertToDataSet(const char *path, const char *key, float v, float x, float y, float z) = 0;
     virtual const DNStorageDataSet  *queryDataSet(const char *path, const char *key, const DNStorageDataSetQuery *query) const = 0;
index 1798c8f..2e8e3ac 100644 (file)
@@ -18,6 +18,7 @@
 //
 #include "dnqsbasiccell.h"
 
+#include "TKContainer.h"
 #include "dnqscontainer.h"
 #include "TKLog.h"
 #include "TKReceptor.h"
index 1fa3219..f1cf350 100644 (file)
 #include <QtScript/QScriptValue>
 #include <QObject>
 
-class DNQSBasicCell : public DNQSCellBase, QObject
+class DNQSBasicCell : public DNQSCellBase
 {
 public:
-    DNQSBasicCell(DNQSContainer *container, std::string location, std::string name, bool canIntarface = false);
+    DNQSBasicCell(DNQSContainer *container, std::string location, std::string name, bool canInterface = false);
     virtual ~DNQSBasicCell();
 
     virtual bool    doTick(float time);
@@ -40,6 +40,7 @@ private:
     void            reflectValueFromScript();
     void            handleScriptException(const char *funcName);
 
+protected:
     QScriptEngine   *mEngine;
     QScriptValue    mQSReceptors;
     QScriptString   mAxonValueHandle;
diff --git a/Source/QtScript/dnqsbasicstoragecell.cpp b/Source/QtScript/dnqsbasicstoragecell.cpp
new file mode 100644 (file)
index 0000000..9d9ed6f
--- /dev/null
@@ -0,0 +1,116 @@
+//  Copyright (c) 2012 Dennco Project
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+//
+//  Created by tkawata on 3/28/2012.
+//
+#include "dnqsbasicstoragecell.h"
+
+#include "TKContainer.h"
+#include "dnqscontainer.h"
+#include "dnqsbasiccell.h"
+#include "TKLog.h"
+#include "TKDebug.h"
+#include "DNUtils.h"
+#include "DNStorage.h"
+
+static QScriptValue scriptStorageSetValue(QScriptContext *context, QScriptEngine *engine)
+{
+    QScriptValue data = context->thisObject().data();
+    TKASSERT(data.isQObject());
+    DNQSBasicStorageCell::QObjectSelfWrapper *wrapper = (DNQSBasicStorageCell::QObjectSelfWrapper*) data.toQObject();
+    TKASSERT(wrapper);
+    if (wrapper && context->argumentCount() >= 2)
+    {
+        wrapper->setValue(context->argument(0).toString().toUtf8().constData(),context->argument(1).toNumber());
+    }
+    return engine->nullValue();
+}
+
+static QScriptValue scriptStorageGetValue(QScriptContext *context, QScriptEngine *engine)
+{
+    QScriptValue data = context->thisObject().data();
+    TKASSERT(data.isQObject());
+    DNQSBasicStorageCell::QObjectSelfWrapper *wrapper = (DNQSBasicStorageCell::QObjectSelfWrapper*) data.toQObject();
+    TKASSERT(wrapper);
+    if (wrapper && context->argumentCount() >= 1)
+    {
+        QByteArray qkey = context->argument(0).toString().toUtf8();
+        const char *key = qkey.constData();
+        if (wrapper->getCount(key) == 0)
+        {
+            return engine->undefinedValue();
+        }
+        else
+        {
+            return QScriptValue(wrapper->getValue(key));
+        }
+    }
+    return engine->nullValue();
+}
+
+
+DNQSBasicStorageCell::DNQSBasicStorageCell(DNQSContainer *container, std::string location, std::string name, bool canInterface) :
+    DNQSBasicCell(container, location, name, canInterface)
+{
+
+    mQSStorage = mEngine->newObject();
+    mQSStorage.setProperty("setValue",mEngine->newFunction(scriptStorageSetValue, 2));
+    mQSStorage.setProperty("getValue",mEngine->newFunction(scriptStorageGetValue, 1));
+    mQSAPIInstance.setProperty("storage", mQSStorage,QScriptValue::ReadOnly|QScriptValue::Undeletable);
+    mQSelf = new QObjectSelfWrapper(this);
+    mQSStorage.setData(mEngine->newQObject(mQSelf));
+}
+
+DNQSBasicStorageCell::~DNQSBasicStorageCell()
+{
+    if (mQSelf)
+    {
+        delete mQSelf;
+        mQSelf = NULL;
+    }
+}
+
+DNQSBasicStorageCell::QObjectSelfWrapper::QObjectSelfWrapper(DNQSBasicStorageCell *self) : mSelf(self)
+{
+    mPath = getFQNString(self->mLocation.c_str(), self->mName.c_str());
+}
+
+int DNQSBasicStorageCell::QObjectSelfWrapper::getCount(const char* key)
+{
+    DNStorage *storage = mSelf->mContainer->getDataStore();
+    if (storage)
+        return storage->getCount(mPath.c_str(),key);
+    else
+        return 0;
+}
+
+float DNQSBasicStorageCell::QObjectSelfWrapper::getValue(const char *key)
+{
+    DNStorage *storage = mSelf->mContainer->getDataStore();
+    if (storage)
+        return storage->getValue(mPath.c_str(), key);
+    else
+        return 0.0;
+}
+
+bool DNQSBasicStorageCell::QObjectSelfWrapper::setValue(const char *key, float value)
+{
+    DNStorage *storage = mSelf->mContainer->getDataStore();
+    if (storage)
+        return storage->setValue(mPath.c_str(), key, value);
+    else
+        return false;
+}
diff --git a/Source/QtScript/dnqsbasicstoragecell.h b/Source/QtScript/dnqsbasicstoragecell.h
new file mode 100644 (file)
index 0000000..d4cb777
--- /dev/null
@@ -0,0 +1,55 @@
+//  Copyright (c) 2012 Dennco Project
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+//
+//  Created by tkawata on 3/28/2012.
+//
+#ifndef DNQSBASICSTORAGECELL_H
+#define DNQSBASICSTORAGECELL_H
+
+#include "dnqsbasiccell.h"
+
+#include <QtScript/QScriptEngine>
+#include <QtScript/QScriptValue>
+#include <QObject>
+
+#include <string>
+
+class DNQSBasicStorageCell : public DNQSBasicCell
+{
+public:
+    DNQSBasicStorageCell(DNQSContainer *container, std::string location, std::string name, bool canInterface = false);
+    virtual ~DNQSBasicStorageCell();
+
+    class QObjectSelfWrapper : public QObject
+    {
+    public:
+        QObjectSelfWrapper(DNQSBasicStorageCell *self);
+
+        int     getCount(const char* key);
+        float   getValue(const char *key);
+        bool    setValue(const char *key, float value);
+
+    private:
+        DNQSBasicStorageCell    *mSelf;
+        std::string             mPath;
+    };
+
+private:
+    QScriptValue        mQSStorage;
+    QObjectSelfWrapper  *mQSelf;
+};
+
+#endif // DNQSBASICSTORAGECELL_H
index c4dd256..2b7ab93 100644 (file)
@@ -20,6 +20,7 @@
 
 #include "DNUtils.h"
 #include "TKLog.h"
+#include "TKContainer.h"
 #include "dnqscontainer.h"
 #include "dnqscellbase.h"
 #include "dnqscellcodeinstance.h"
index 1ec72b7..c3d4392 100644 (file)
@@ -18,6 +18,7 @@
 //
 #include "dnqscellcodeinstance.h"
 
+#include "TKContainer.h"
 #include "dnqscontainer.h"
 #include "TKCell.h"
 #include "TKLog.h"
index 9232da0..43f5fd0 100644 (file)
 
 #include "TKCell.h"
 #include "TKCellCode.h"
+#include "TKContainer.h"
 #include "TKLog.h"
 #include "DNUtils.h"
 #include "versioninfo.h"
 #include "dnqsbasiccell.h"
 #include "dnqsinputcell.h"
 #include "dnqsoutputcell.h"
+#include "dnqsbasicstoragecell.h"
 #include "TKUICell.h"
 #include "dnqscellcode.h"
 #include "DNGlobal.h"
@@ -33,6 +35,7 @@
 const std::string DNQSContainer::CELLTYPE_JSBASIC = "B";
 const std::string DNQSContainer::CELLTYPE_OUT = "O";
 const std::string DNQSContainer::CELLTYPE_IN = "I";
+const std::string DNQSContainer::CELLTYPE_BASICSTORAGE = "BS";
 
 static QScriptValue scriptPrint(QScriptContext *context, QScriptEngine *engine)
 {
@@ -49,7 +52,7 @@ static QScriptValue scriptFQN(QScriptContext *context, QScriptEngine *engine)
     if (context->argumentCount() >= 2)
     {
         const char *location = context->argument(0).toString().toUtf8().constData();
-        const char *name = context->argument(0).toString().toUtf8().constData();
+        const char *name = context->argument(1).toString().toUtf8().constData();
 
         std::string fqnString = getFQNString(location, name);
         return QScriptValue(fqnString.c_str());
@@ -108,6 +111,10 @@ TKCell* DNQSContainer::createCellWithoutCellCodeClass(std::string theLocation, s
         cell = new DNQSOutputCell(this, theLocation, theName, true);
         noScript = true;
     }
+    else if (type == CELLTYPE_BASICSTORAGE)
+    {
+        cell = new DNQSBasicStorageCell(this, theLocation, theName, false);
+    }
     else
     {
         std::string message = std::string("Failed to construct cell '").append(theLocation).append("#").append(theName);
@@ -232,15 +239,6 @@ TKCellCode* DNQSContainer::createCellCode(std::string theName, std::string theAP
     return cellCode;
 }
 
-bool DNQSContainer::doTick(float time)
-{
-    for ( TKCellMap::iterator it = mCells.begin(); it != mCells.end(); ++it ) {
-        it->second->doTick(time);
-    }
-
-    return true;
-}
-
 void DNQSContainer::setValue(std::string key, float value)
 {
     mQSGlobalObject.setProperty(QString::fromStdString(key), QScriptValue(value));
index 6828c32..6cd318d 100644 (file)
@@ -34,8 +34,6 @@ public:
     virtual TKCell*     createCellWithCellCodeClass(std::string theLocation, std::string theName, TKCellCode *cellCode, std::string customScript);
     virtual TKCellCode* createCellCode(std::string theName, std::string theAPIType, std::string code);
 
-    virtual bool    doTick(float time);
-
     virtual void    setValue(std::string key, float value);
     virtual float   getValue(std::string key);
 
@@ -46,6 +44,7 @@ public:
     static const std::string CELLTYPE_JSBASIC;
     static const std::string CELLTYPE_OUT;
     static const std::string CELLTYPE_IN;
+    static const std::string CELLTYPE_BASICSTORAGE;
 
  private:
     QScriptEngine   *mQSEngine;
index 9d912b6..f614bb6 100644 (file)
 
 TKContainer::~TKContainer()
 {
+    doDestroy();
+    releaseDataStore();
+}
+
+bool TKContainer::doTick(float time)
+{
+    mLock.lock();
+    for ( TKCellMap::iterator it = mCells.begin(); it != mCells.end(); ++it ) {
+        it->second->doTick(time);
+    }
+    mLock.unlock();
+    return true;
+}
+
+bool TKContainer::doDestroy()
+{
+    mLock.lock();
+
     for ( TKCellMap::iterator it = mCells.begin(); it != mCells.end(); ++it ) {
         (it->second)->doDestroy();
     }
@@ -32,10 +50,8 @@ TKContainer::~TKContainer()
     mCells.clear();
     mInterfaceCells.clear();
 
-    if (mStorage)
-    {
-        delete mStorage;
-    }
+    mLock.unlock();
+    return true;
 }
 
 bool TKContainer::setDataStore(std::string storagePath)
@@ -44,6 +60,18 @@ bool TKContainer::setDataStore(std::string storagePath)
     return mStorage->isValid();
 }
 
+bool TKContainer::releaseDataStore()
+{
+    mLock.lock();
+    if (mStorage)
+    {
+        delete mStorage;
+        mStorage = NULL;
+    }
+    mLock.unlock();
+    return true;
+}
+
 TKCell* TKContainer::getCell(std::string theFQNName)
 {
     TKCellMap::iterator it = mCells.find(theFQNName);
index ce4b038..3d84340 100644 (file)
@@ -20,6 +20,8 @@
 #ifndef __INCLUDE_TKCONTAINER__
 #define __INCLUDE_TKCONTAINER__
 
+#include "TKLock.h"
+
 #include <string>
 #include <map>
 
@@ -39,19 +41,23 @@ public:
 
     const TKCellMap* getCells() { return &mCells; } 
     const TKCellCodeMap* getCellCodes() { return &mCellCodes; }
-    void setContentPath(std::string contentPath) { mContentPath = contentPath; }
+
+    void        setContentPath(std::string contentPath) { mContentPath = contentPath; }
     std::string getContentPath() { return mContentPath; }
-    bool setDataStore(std::string storagePath);
-    TKCell* getCell(std::string theFQNName);
-    TKCell* getInterfaceCell(std::string theFQNName);
+    bool        setDataStore(std::string storagePath);
+    DNStorage*  getDataStore() { return mStorage; }
+    bool        releaseDataStore();
+    TKCell*     getCell(std::string theFQNName);
+    TKCell*     getInterfaceCell(std::string theFQNName);
     TKCellCode* getCellCode(std::string theCellCodeName);
 
+    bool        doTick(float time);
+    bool        doDestroy();
+
     virtual TKCell*     createCellWithoutCellCodeClass(std::string theLocation, std::string theName, std::string type, std::string customScript) = 0;
     virtual TKCell*     createCellWithCellCodeClass(std::string theLocation, std::string theName, TKCellCode *cellCode, std::string customScript) = 0;
     virtual TKCellCode* createCellCode(std::string theName, std::string theAPIType, std::string code) = 0;
        
-    virtual bool doTick(float time) = 0;
-
     virtual void setValue(std::string key, float value) = 0;
     inline virtual float getValue(std::string key) = 0;
 
@@ -62,5 +68,8 @@ protected:
     TKCellCodeMap   mCellCodes;
     std::string     mContentPath;
     DNStorage       *mStorage;
+
+private:
+    TKLock          mLock;
 };
 #endif
index a30a1ae..8433035 100644 (file)
@@ -19,9 +19,9 @@
 #include "qtdnstorageimpl.h"
 
 #include "DNStorageImpl.h"
+#include "TKLog.h"
 
 #include <QtSql>
-
 #include <DNGlobal.h>
 
 //static
@@ -32,14 +32,27 @@ DNStorageImpl* DNStorageImpl::create(const char *storagePath)
 
 QtDNStorageImpl::~QtDNStorageImpl()
 {
-    if (mDB.isValid() && mDB.isOpen())
+    if (mQueries)
     {
-        mDB.close();
-        mDB.removeDatabase(mDB.connectionName());
+        delete mQueries;
+        mQueries = NULL;
+    }
+
+    if (mDatabase)
+    {
+        QString connectionName = mDatabase->database.connectionName();
+        if (mDatabase->database.isValid() && mDatabase->database.isOpen())
+        {
+            mDatabase->database.close();
+        }
+
+        delete mDatabase;
+        QSqlDatabase::removeDatabase(connectionName);
+        mDatabase = NULL;
     }
 }
 
-QtDNStorageImpl::QtDNStorageImpl(const char *storagePath)
+QtDNStorageImpl::QtDNStorageImpl(const char *storagePath) : mDatabase(NULL),mQueries(NULL)
 {
     mStoragePath = QString::fromLocal8Bit(storagePath);
     mIsValid = initDB();
@@ -52,42 +65,46 @@ bool QtDNStorageImpl::setValue(const char *path, const char *key, float value)
 
     QString qPath(path);
     QString qKey(key);
-    mPropertiesCountQuery.addBindValue(qPath);
-    mPropertiesCountQuery.addBindValue(qKey);
-    if (!mPropertiesCountQuery.exec())
+    mQueries->propertiesCountQuery.addBindValue(qPath);
+    mQueries->propertiesCountQuery.addBindValue(qKey);
+    if (!mQueries->propertiesCountQuery.exec())
     {
         std::string message = "SQL error while processing cell ";
         message.append(path);
         message.append("\n");
-        message.append(mPropertiesCountQuery.lastError().text().toStdString());
+        message.append(mQueries->propertiesCountQuery.lastError().text().toStdString());
+        TKLog::printf("%s", message.c_str());
         return false;
     }
-    int cnt = mPropertiesCountQuery.boundValue(1).toInt();
+    mQueries->propertiesCountQuery.next();
+    int cnt = mQueries->propertiesCountQuery.value(0).toInt();
     if (cnt == 0)
     {
-        mPropertiesInsertQuery.addBindValue(qPath);
-        mPropertiesInsertQuery.addBindValue(qKey);
-        mPropertiesInsertQuery.addBindValue(value);
-        if (!mPropertiesInsertQuery.exec())
+        mQueries->propertiesInsertQuery.addBindValue(qPath);
+        mQueries->propertiesInsertQuery.addBindValue(qKey);
+        mQueries->propertiesInsertQuery.addBindValue(value);
+        if (!mQueries->propertiesInsertQuery.exec())
         {
             std::string message = "SQL error while processing cell ";
             message.append(path);
             message.append("\n");
-            message.append(mPropertiesCountQuery.lastError().text().toStdString());
+            message.append(mQueries->propertiesCountQuery.lastError().text().toStdString());
+            TKLog::printf("%s", message.c_str());
             return false;
         }
     }
     else
     {
-        mPropertiesUpdateQuery.addBindValue(value);
-        mPropertiesUpdateQuery.addBindValue(qPath);
-        mPropertiesUpdateQuery.addBindValue(qKey);
-        if (!mPropertiesUpdateQuery.exec())
+        mQueries->propertiesUpdateQuery.addBindValue(value);
+        mQueries->propertiesUpdateQuery.addBindValue(qPath);
+        mQueries->propertiesUpdateQuery.addBindValue(qKey);
+        if (!mQueries->propertiesUpdateQuery.exec())
         {
             std::string message = "SQL error while processing cell ";
             message.append(path);
             message.append("\n");
-            message.append(mPropertiesCountQuery.lastError().text().toStdString());
+            message.append(mQueries->propertiesCountQuery.lastError().text().toStdString());
+            TKLog::printf("%s", message.c_str());
             return false;
         }
     }
@@ -97,34 +114,53 @@ bool QtDNStorageImpl::setValue(const char *path, const char *key, float value)
 
 float QtDNStorageImpl::getValue(const char *path, const char *key)
 {
-    if (!mIsValid)
+    if (mQueries == NULL || !mIsValid)
         return 0;
 
-    mPropertiesGetQuery.prepare("SELECT value FROM properties WHERE cell=? and key=?");
-
     QString qPath(path);
     QString qKey(key);
-    mPropertiesGetQuery.addBindValue(qPath);
-    mPropertiesGetQuery.addBindValue(qKey);
-    if (!mPropertiesGetQuery.exec())
+    mQueries->propertiesGetQuery.addBindValue(qPath);
+    mQueries->propertiesGetQuery.addBindValue(qKey);
+    if (!mQueries->propertiesGetQuery.exec())
     {
         std::string message = "SQL error while processing cell ";
         message.append(path);
         message.append("\n");
-        message.append(mPropertiesCountQuery.lastError().text().toStdString());
+        message.append(mQueries->propertiesCountQuery.lastError().text().toStdString());
+        TKLog::printf("%s", message.c_str());
         return false;
     }
-    if (mPropertiesGetQuery.size() > 0)
+    mQueries->propertiesGetQuery.next();
+    return mQueries->propertiesGetQuery.value(0).toFloat();
+}
+
+int QtDNStorageImpl::getCount(const char *path, const char *key)
+{
+    if (!mIsValid)
+        return false;
+
+    QString qPath(path);
+    QString qKey(key);
+    mQueries->propertiesCountQuery.addBindValue(qPath);
+    mQueries->propertiesCountQuery.addBindValue(qKey);
+    if (!mQueries->propertiesCountQuery.exec())
     {
-        return mPropertiesGetQuery.boundValue(1).toFloat();
+        std::string message = "SQL error while processing cell ";
+        message.append(path);
+        message.append("\n");
+        message.append(mQueries->propertiesCountQuery.lastError().text().toStdString());
+        TKLog::printf("%s", message.c_str());
+        return false;
     }
-    else
-        return 0.0;
+
+    mQueries->propertiesCountQuery.next();
+    return mQueries->propertiesCountQuery.value(0).toInt();
 }
 
+
 int QtDNStorageImpl::insertToDataSet(const char *path, const char *key, float v, float x, float y, float z)
 {
-    if (!mIsValid)
+    if (mQueries == NULL || !mIsValid)
         return 0;
     //TODO
     return 0;
@@ -132,7 +168,7 @@ int QtDNStorageImpl::insertToDataSet(const char *path, const char *key, float v,
 
 const DNStorageDataSet* QtDNStorageImpl::queryDataSet(const char *path, const char *key, const DNStorageDataSetQuery *query) const
 {
-    if (!mIsValid)
+    if (mQueries == NULL || !mIsValid)
         return 0;
     //TODO
     return 0;
@@ -140,7 +176,7 @@ const DNStorageDataSet* QtDNStorageImpl::queryDataSet(const char *path, const ch
 
 bool QtDNStorageImpl::updateDataSet(const char *path, const char *key, int index, float v, float x, float y, float z)
 {
-    if (!mIsValid)
+    if (mQueries == NULL || !mIsValid)
         return false;
     //TODO
     return false;
@@ -148,7 +184,7 @@ bool QtDNStorageImpl::updateDataSet(const char *path, const char *key, int index
 
 bool QtDNStorageImpl::deleteFromDataSet(const char *path, const char *key, int index)
 {
-    if (!mIsValid)
+    if (mQueries == NULL || !mIsValid)
         return false;
     //TODO
     return false;
@@ -156,26 +192,27 @@ bool QtDNStorageImpl::deleteFromDataSet(const char *path, const char *key, int i
 
 bool QtDNStorageImpl::flush()
 {
-    if (!mIsValid || !mDB.isValid())
+    if (mDatabase == NULL || !mIsValid)
         return false;
 
-    mDB.commit();
+    mDatabase->database.commit();
 
     return true;
 }
 
 bool QtDNStorageImpl::initDB()
 {
+    mDatabase = new QtDNDatabase;
 
-    mDB = QSqlDatabase::addDatabase("QSQLITE");
-    mDB.setDatabaseName(mStoragePath);
+    mDatabase->database = QSqlDatabase::addDatabase("QSQLITE");
+    mDatabase->database.setDatabaseName(mStoragePath);
 
-    if (!mDB.open())
+    if (!mDatabase->database.open())
     {
         std::string message = "Failied to open storage file ";
         message.append(mStoragePath.toStdString());
         message.append("\n");
-        message.append(mDB.lastError().text().toStdString());
+        message.append(mDatabase->database.lastError().text().toStdString());
         if (dnGlobal()->updateErrorStatus(DNGlobal::ERROR))
         {
             dnGlobal()->setMessage1("Persistent storage initialization error.");
@@ -184,19 +221,19 @@ bool QtDNStorageImpl::initDB()
         return false;
     }
 
-    QStringList tables = mDB.tables();
+    QStringList tables = mDatabase->database.tables();
     if (!tables.contains("properties"))
     {
         QSqlQuery q;
 
         if (!q.exec("CREATE TABLE properties(cell TEXT, prokey TEXT, value REAL, PRIMARY KEY (cell, prokey))"));
         {
-            if (mDB.lastError().type() != QSqlError::NoError)
+            if (mDatabase->database.lastError().type() != QSqlError::NoError)
             {
                 std::string message = "Failied to create data table (properties) in ";
                 message.append(mStoragePath.toStdString());
                 message.append("\n");
-                message.append(mDB.lastError().text().toStdString());
+                message.append(mDatabase->database.lastError().text().toStdString());
                 if (dnGlobal()->updateErrorStatus(DNGlobal::ERROR))
                 {
                     dnGlobal()->setMessage1("Persistent storage initialization error.");
@@ -213,12 +250,12 @@ bool QtDNStorageImpl::initDB()
 
         if (!q.exec("CREATE TABLE dataset(cell TEXT, dskey TEXT, dsindex INTEGER, v REAL, x REAL, y REAL, z REAL, PRIMARY KEY (cell, dskey, dsindex))"));
         {
-            if (mDB.lastError().type() !=  QSqlError::NoError)
+            if (mDatabase->database.lastError().type() !=  QSqlError::NoError)
             {
                 std::string message = "Failied to create data table (dataset) in ";
                 message.append(mStoragePath.toStdString());
                 message.append("\n");
-                message.append(mDB.lastError().text().toStdString());
+                message.append(mDatabase->database.lastError().text().toStdString());
                 if (dnGlobal()->updateErrorStatus(DNGlobal::ERROR))
                 {
                     dnGlobal()->setMessage1("Persistent storage initialization error.");
@@ -229,14 +266,30 @@ bool QtDNStorageImpl::initDB()
         }
     }
 
-    mPropertiesCountQuery.prepare("SELECT count(*) FROM properties WHERE cell=? and prokey=?");
-    mPropertiesInsertQuery.prepare("INSERT INTO properties (?,?,?)");
-    mPropertiesUpdateQuery.prepare("UPDATE SET value=? WHERE cell=? and prokey=?");
-    mPropertiesGetQuery.prepare("SELECT value FROM properties WHERE cell=? and prokey=?");
+    mQueries = new QtDNDBQueries;
+
+    mQueries->propertiesCountQuery.prepare("SELECT count(*) FROM properties WHERE cell=? and prokey=?");
+    mQueries->propertiesInsertQuery.prepare("INSERT INTO properties VALUES(?,?,?)");
+    mQueries->propertiesUpdateQuery.prepare("UPDATE properties SET value=? WHERE cell=? and prokey=?");
+    mQueries->propertiesGetQuery.prepare("SELECT value FROM properties WHERE cell=? and prokey=?");
+
+    mQueries->dataSetInsetToDataSetQuery.prepare("INSERT INTO dataset (?,?,?, ?,?,?,?)");
+    mQueries->dataSetUpdateDataSetQuery.prepare("UPDATE SET v=?, x=?, y=? z=? WHERE cell=? and dskey=? and dsindex=?");
+    mQueries->dataSetDeleteFromDataSetQuery.prepare("DELETE FROM dataset WHERE cell=? and key=? and index=?");
 
-    mDataSetInsetToDataSetQuery.prepare("INSERT INTO dataset (?,?,?, ?,?,?,?)");
-    mDataSetUpdateDataSetQuery.prepare("UPDATE SET v=?, x=?, y=? z=? WHERE cell=? and dskey=? and dsindex=?");
-    mDataSetDeleteFromDataSetQuery.prepare("DELETE FROM dataset WHERE cell=? and key=? and index=?");
+    if (mDatabase->database.lastError().type() != QSqlError::NoError)
+    {
+        std::string message = "Failied to prepare database ";
+        message.append(mStoragePath.toStdString());
+        message.append("\n");
+        message.append(mDatabase->database.lastError().text().toStdString());
+        if (dnGlobal()->updateErrorStatus(DNGlobal::ERROR))
+        {
+            dnGlobal()->setMessage1("Persistent storage initialization error.");
+            dnGlobal()->setMessage2(message);
+        }
+        return false;
+    }
 
     return true;
 }
index e5a6e5e..d9aebe3 100644 (file)
 #include <QString>
 #include <QtSql>
 
+class QtDNDatabase
+{
+public:
+    QSqlDatabase database;
+};
+
+class QtDNDBQueries
+{
+public:
+    QSqlQuery   propertiesCountQuery;
+    QSqlQuery   propertiesInsertQuery;
+    QSqlQuery   propertiesUpdateQuery;
+    QSqlQuery   propertiesGetQuery;
+
+    QSqlQuery   dataSetInsetToDataSetQuery;
+    QSqlQuery   dataSetUpdateDataSetQuery;
+    QSqlQuery   dataSetDeleteFromDataSetQuery;
+};
+
 class QtDNStorageImpl : public DNStorageImpl
 {
 public:
@@ -32,6 +51,7 @@ public:
 
     virtual bool                    setValue(const char *path, const char *key, float value);
     virtual float                   getValue(const char *path, const char *key);
+    virtual int                     getCount(const char *path, const char *key);
 
     virtual int                     insertToDataSet(const char *path, const char *key, float v, float x, float y, float z);
     virtual const DNStorageDataSet  *queryDataSet(const char *path, const char *key, const DNStorageDataSetQuery *query) const;
@@ -43,21 +63,12 @@ public:
     virtual bool    isValid() { return mIsValid; }
 
 private:
-    bool        initDB();
-    bool        mIsValid;
-    QString     mStoragePath;
-
-    QSqlQuery   mPropertiesCountQuery;
-    QSqlQuery   mPropertiesInsertQuery;
-    QSqlQuery   mPropertiesUpdateQuery;
-    QSqlQuery   mPropertiesGetQuery;
-
-    QSqlQuery   mDataSetInsetToDataSetQuery;
-    QSqlQuery   mDataSetUpdateDataSetQuery;
-    QSqlQuery   mDataSetDeleteFromDataSetQuery;
-
-    QSqlDatabase mDB;
+    bool            initDB();
+    bool            mIsValid;
+    QString         mStoragePath;
 
+    QtDNDatabase    *mDatabase;
+    QtDNDBQueries   *mQueries;
 };
 
 #endif // QTDNSTORAGEIMPL_H
index 4bad469..8a27d78 100644 (file)
@@ -54,7 +54,8 @@ SOURCES += Source/QtDennco/mainwindow.cpp \
     Source/QtScript/dnqsinputcell.cpp \
     Source/QtScript/dnqsoutputcell.cpp \
     Source/platform/qt/qtdnstorageimpl.cpp \
-    Source/DNStorage.cpp
+    Source/DNStorage.cpp \
+    Source/QtScript/dnqsbasicstoragecell.cpp
 
 HEADERS  += Source/QtDennco/mainwindow.h \
     Source/TKUICell.h \
@@ -108,7 +109,8 @@ HEADERS  += Source/QtDennco/mainwindow.h \
     Source/QtScript/dnqsoutputcell.h \
     Source/DNStorageImpl.h \
     Source/DNStorage.h \
-    Source/platform/qt/qtdnstorageimpl.h
+    Source/platform/qt/qtdnstorageimpl.h \
+    Source/QtScript/dnqsbasicstoragecell.h
 
 FORMS    += Source/QtDennco/mainwindow.ui
 Debug:DEFINES+=DEBUG