美文网首页
用QSQLite实现进程共享数据类(linux)

用QSQLite实现进程共享数据类(linux)

作者: 诸事圆成 | 来源:发表于2019-12-13 10:41 被阅读0次

    下面是用qt的QSQLITE做的数据库,我的环境是redhat
    项目要求是提供2个接口:

    1.void set(QString key, QString value); //将key-value存入数据库
    2.QString get(QString key);// 从数据库获取数据

    自己发现的注意点:
    1.QSQLite是QT自带的,是跨平台的,主要用QSqlDatabase和QSqlQuery来操作。
    2.QSQLIte是支持同步的,同步是支持并发读, 但若A线程写,B线程同时也写,我发现B线程的写操作数据库就不处理了。

    1. QSqlQuery和QSqlDatabase的操作,总是感觉不能完全把握,还需进一步观察。
    #-------------------------------------------------
    #
    # Project created by QtCreator 2019-12-07T17:35:30
    #
    #-------------------------------------------------
    
    QT       += core gui sql
    
    greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    
    TARGET = ECOTS_DataStorage
    TEMPLATE = app
    
    # The following define makes your compiler emit warnings if you use
    # any feature of Qt which has been marked as deprecated (the exact warnings
    # depend on your compiler). Please consult the documentation of the
    # deprecated API in order to know how to port your code away from it.
    DEFINES += QT_DEPRECATED_WARNINGS
    #DEFINES += QT_NO_DEBUG_OUTPUT
    # You can also make your code fail to compile if you use deprecated APIs.
    # In order to do so, uncomment the following line.
    # You can also select to disable deprecated APIs only up to a certain version of Qt.
    #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
    
    
    SOURCES += \
         main.cpp \
        datastorage.cpp
    
    
    HEADERS += \
        datastorage.h
    
    /** datastorage.h */
    #ifndef DATASTORAGE_H
    #define DATASTORAGE_H
    
    #include <QtSql>
    #include <QtSql/QSqlDatabase>
    #include <QtSql/QSqlQuery>
    #include <QtSql/QSqlRecord>
    #include <QtSql/QSqlError>
    
    #include <QString>
    #include <QStringList>
    #include <QDebug>
    #include <QMap>
    
    #include <stdio.h>
    #include <string.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <algorithm>
    
    
    #define DEFAULT_DATABASE_PATH "/tmp/.ECOTS.db"
    
    #define DEFAULT_TABLE_NAME "ECOTS"
    
    
    namespace ECOTS
    {
    
    class DataStorage
    {
    public:
        //get singleton obj
        static DataStorage &getDataStorage();
        //insert or update
        void setVariable(const QString &_key, const QString &_value);
        //view
        QString getVariableString(const QString &_key);
    
        //output tables to map
        int printTable(QMap<QString,QString> &tableInfo_);
        //close database
        bool close();
        bool deleteTable(const QString &_tableName = "ECOTS");
    
    protected:
        //check database path is accessible, if not exist path -> mkdir 777
        void checkStorageDbPath(const QString &_dbFile);
        //check table exits in database or not
        bool isTableExist(const QString &_tableName);
        //create table in databse
        bool createTable(const QString &_tableName);
        // exec sql
        bool exeSqlCmd(QSqlQuery &_query,  const QString &_cmd);
    
    private:
        DataStorage();
        ~DataStorage();
        QSqlDatabase sqldb;
        QReadWriteLock rw;
    };
    
    
    } //namespace
    
    
    
    
    #endif // DATASTORAGE_H
    
    
    
    /** datastorage.cpp */
    #include "datastorage.h"
    
    /*
     * @brief:
     *
     * @parameter in:
     * @parameter out:
     *
     * @return:
     */
    
    ECOTS::DataStorage &ECOTS::DataStorage::getDataStorage()
    {
        static DataStorage obj;
        return obj;
    }
    
    
    
    ECOTS::DataStorage::DataStorage()
    {
        if(QSqlDatabase::contains("qt_sql_default_connection"))
        {
            qDebug() << "connection  is exist ";
            sqldb = QSqlDatabase::database("qt_sql_default_connection");
        }
        else
        {
            qDebug() << "connection is new ";
            /* add SQLITE dirver */
            sqldb = QSqlDatabase::addDatabase("QSQLITE");
        }
        checkStorageDbPath(QString(DEFAULT_DATABASE_PATH));
        sqldb.setDatabaseName(QString(DEFAULT_DATABASE_PATH));
        if (!sqldb.isOpen())
        {
            if (!sqldb.open())
            {
                qDebug() << "open database error: " << sqldb.lastError().text();
            }
        }
    
         qDebug() << "get database name:  " << sqldb.databaseName();
         qDebug() << "get database connection name: " << sqldb.connectionNames();
    
    
         if (!isTableExist("ECOTS"))
         {
             createTable(QString(DEFAULT_TABLE_NAME));
         }
    
          qDebug() << "this database has tables: " << sqldb.tables();
    
    }
    
    
    
    ECOTS::DataStorage::~DataStorage()
    {
       sqldb.close();
    }
    
    
    
    void ECOTS::DataStorage::checkStorageDbPath(const QString &_dbFile)
    {
        std::string stFile = _dbFile.toStdString();
        std::string dbPath = stFile.substr(0, stFile.find_last_of('/') + 1);
    
        qDebug() << "database path is: " << QString::fromStdString(dbPath);
    
        if (!access(dbPath.c_str(), F_OK))
        {//check path exist or not
            mkdir(dbPath.c_str(), 0777);
        }
        chmod(DEFAULT_DATABASE_PATH, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH);
    }
    
    
    
    bool ECOTS::DataStorage::isTableExist(const QString &_tableName)
    {
        return sqldb.tables().contains(_tableName);
    }
    
    
    
    bool ECOTS::DataStorage::createTable(const QString &_tableName)
    {
        QSqlQuery query;
        QString  checkCmd = "SELECT * FROM " + _tableName;
        if (!query.exec(checkCmd))
        {//table not exist
            QString sqlCmd = "CREATE TABLE IF NOT EXISTS " + _tableName +
                    " (ID INTEGER PRIMARY KEY AUTOINCREMENT, Name TEXT NOT NULL, Value TEXT NOT NULL)";
    
            query.prepare(sqlCmd);
            if (!query.exec())
            {
                qDebug() << "exec sql error: " << query.lastError().text();
                return false;
            }
            qDebug() << "create table success";
        }
        return true;
    
    }
    
    
    
    
    void ECOTS::DataStorage::setVariable(const QString &_key, const QString &_value)
    {
        QWriteLocker wlock(&rw);
    
        QString backupValue = _value;
        if (_value.isNull())
        {//prevent input NULL to database
           backupValue = "null";
        }
    
        QSqlQuery query;
        bool isExist = false;
    
        // determine whether key exists in table
        QString boolCmd = "SELECT * FROM ECOTS WHERE Name = '" + _key + "'";
        if (exeSqlCmd(query, boolCmd))
        {
            if (query.next())
            {
                isExist = true;
            }
        }
        else
        {
            return;
        }
    
        if (!isExist)
        { //key not exist -> insert
            QString insertCmd = "INSERT INTO ECOTS (Name, Value) VALUES ('" + _key + "', '" + backupValue + "')";
            if (exeSqlCmd(query, insertCmd)) {
                qDebug() << QString("insert new data key=%1, value=%2 success").arg(_key).arg(backupValue);
            }
        }
        else
        {//key is exist -> update
            QString updateCmd = "UPDATE ECOTS SET Value = '" + backupValue + "' WHERE Name = '" + _key + "'";
            if (exeSqlCmd(query, updateCmd)) {
                qDebug() << QString("update %1 = %2 success").arg(_key).arg(backupValue);
            }
        }
    }
    
    
    
    QString ECOTS::DataStorage::getVariableString(const QString &_key)
    {
        QReadLocker rlock(&rw);
        QString result("");
        QSqlQuery query;
        QString printCmd("SELECT * FROM ECOTS");
        if (exeSqlCmd(query, printCmd))
        {
            while (query.next()) // if key not exist in table -> query.next=false
            {
               int tId = query.value(0).toInt();
               QString tname = query.value(1).toString();
               QString tvalue = query.value(2).toString();
    
               qDebug() << QString("ID=%1  Name=%2   Value=%3").arg(tId).arg(tname).arg(tvalue);
    
               if (_key == tname)
               {
                   result = tvalue;
                   break;
               }
            }
        }
        return result;
    }
    
    
    int ECOTS::DataStorage::printTable(QMap<QString, QString> &tableInfo_)
    {
        tableInfo_.clear();
        QSqlQuery query;
        QString printCmd("SELECT * FROM ECOTS");
        if (exeSqlCmd(query, printCmd))
        {
            while (query.next())
            {
               QString tname = query.value(1).toString();
               QString tvalue = query.value(2).toString();
               tableInfo_.insert(tname, tvalue);
            }
        }
        return tableInfo_.size();
    }
    
    
    bool ECOTS::DataStorage::close()
    {
       sqldb.close();
    
       return (sqldb.isOpen() ? false : true);
    }
    
    bool  ECOTS::DataStorage::deleteTable(const QString &_tableName)
    {
        QSqlQuery query;
        QString rmCmd = "DROP TABLE " + _tableName;
        exeSqlCmd(query, rmCmd);
    
        return ((sqldb.tables().contains(_tableName) )? false : true);
    }
    
    
    bool ECOTS::DataStorage::exeSqlCmd(QSqlQuery &_query, const QString &_cmd)
    {
        if (_cmd.isEmpty())
            return false;
    
        bool result = false;
        _query.prepare(_cmd);
        if (!_query.exec()) {
           qDebug() << "exec sql error: " << _query.lastError().text();
        } else {
           qDebug() << QString("exec cmd: %1 success").arg(_cmd);
           result = true;
        }
        return result;
    }
    
    /*测试代码 */
    
    #include <QApplication>
    #include "datastorage.h"
    #include <QThread>
    #include <QVector>
    #include <QStringList>
    #include <QTime>
    #include <QDebug>
    
    void __sleep(unsigned int msec)
    {
        QTime dieTime = QTime::currentTime().addMSecs(msec);
        while (QTime::currentTime() < dieTime)
        {
            QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
        }
    }
    
    class dbThread : public QThread
    {
    public:
        dbThread() {}
    protected:
        void run()
        {
            qDebug() << "thread start ...";
            ECOTS::DataStorage &db = ECOTS::DataStorage::getDataStorage();
            qDebug() << QString(" thread-id:   %1").arg(QThread::currentThreadId());
            QStringList list;
            list << "aaa" << "bbb" << "ccc" << "ddd" << "eee" << "fff" << "ggg" << "sss" << "xxx";
            qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
            while (1)
            {
                int t = qrand()  % 9;
                qDebug() << QString("thread: %1 set var %2").arg(QThread::currentThreadId()).arg(list[t]);
                db.setVariable("SessionID", list.at(t) );
                db.setVariable("TestProgramPath", list.at(t));
                QThread::sleep(3);
            }
        }
    };
    
    class dbThread1 : public QThread
    {
    public:
        dbThread1() {}
    protected:
        void run()
        {
            qDebug() << "thread start ...";
            ECOTS::DataStorage &db = ECOTS::DataStorage::getDataStorage();
            qDebug() << QString(" thread-id:   %1").arg(QThread::currentThreadId());
            QStringList list;
            list << "111" << "222" << "333" << "444" << "555" << "666" << "777" << "888" << "999";
            qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
            while (1)
            {
                int t = qrand()  % 9;
                qDebug() << QString("thread: %1 set var %2").arg(QThread::currentThreadId()).arg(list[t]);
                db.setVariable("SessionID", list.at(t) );
                db.setVariable("TestProgramName", list.at(t));
                QThread::sleep(3);
            }
        }
    };
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
        /* create database */
        ECOTS::DataStorage &db = ECOTS::DataStorage::getDataStorage();
    
        /* insert or update data*/
        QMap<QString, QString> hoge;
        hoge["TestProgramName"] = "demoTP";
        hoge["TestProgramPath"] = "/home/jwu/device";
        hoge["SessionID"] = ":0";
        hoge["LotID"] = "m123";
        hoge["waferID"] = "wafer_000001";
        hoge["SessionID"] = ":9";
    
        dbThread t1;
        dbThread1 t2;
        t1.start();
        t2.start();
    
    
        while(1)
        {
    
            qDebug() <<"ID = " << QThread::currentThreadId() << "  ***getVar ---> " << db.getVariableString("SessionID");
            __sleep(5000);
        }
    
    
       t1.wait();
       t2.wait();
        return a.exec();
    }
    

    相关文章

      网友评论

          本文标题:用QSQLite实现进程共享数据类(linux)

          本文链接:https://www.haomeiwen.com/subject/orffnctx.html