美文网首页
用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)

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

  • 13.python多进程之Manager

    一、概述 Python中提供了强大的Manager类,专门用于实现多进程之间的数据共享; Manager类是数据不...

  • Python day13_进程

    用进程实现多任务 进程之间不共享全局变量

  • 面试准备——Binder相关

    Linux中的进程通信方式 进程间,用户空间的数据不可共享,所以用户空间相当于私有空间 进程间,内核空间的数据可共...

  • 共享内存

    Linux进程间通信 - 共享内存

  • VirtualApk源码分析-ContentProvider插件

    android通过ContentProvider可以实现进程间的数据共享,例如APP通过MediaProvider...

  • Android多进程通信之 Binder

    进程空间划分 在 Linux 中一个进程空间可以分为用户空间和内核空间,不同的进程它们的用户空间数据不可共享,但是...

  • 8.14

    进程间通信(IPC)实现方式共享内存:共享的内存间没有同步机制,需要进程协商解决;减少了数据的复制,速度更快 1...

  • Linux进程基础行为(二)

    本节主要讲Linux进程间通信在Linux中,各个进程都共享内核空间,因此LInux进程通信中的管道,消息队列等都...

  • 进程调度之并发控制(一)

    并发原理 进程间通信进程竞争或共享资源实现多进程同步时间分配 并发的一些困难:全局资源共享很难(会造成脏数据)资源...

网友评论

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

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