解决多线程情况下写数据库导致的数据库崩溃问题

This commit is contained in:
luoliangyi 2022-06-16 17:52:10 +08:00
parent c251e80145
commit 3b15c7b050
4 changed files with 99 additions and 83 deletions

View File

@ -99,7 +99,6 @@ namespace ver_2
// 保存路径表
sqlite3_exec(m_sqlite, "create table save_filenames (filename text)", NULL, NULL, NULL);
// 设备配置表
sqlite3_exec(m_sqlite, "create table device_params (name text, value_type text, value text)", NULL, NULL, NULL);
@ -114,32 +113,25 @@ namespace ver_2
std::vector<MainTableInfo> tables;
char** result = NULL;
int rows, cols;
ret = sqlite3_get_table(m_sqlite, "select * from table_", &result, &rows, &cols, NULL);
assert(0 == ret && rows > 0 && cols == 2);
sqlite3_stmt* stmt = NULL;
ret = sqlite3_prepare(m_sqlite, "select * from table_", -1, &stmt, NULL);
assert(0 == ret);
for (int i = 0; i < rows; i++)
ret = sqlite3_step(stmt);
while (SQLITE_ROW == ret)
{
MainTableInfo info;
for (int j = 0; j < cols; j++)
{
if (0 == strcmp("id", result[j]))
{
info.id = atoi(result[(i + 1) * cols + j]);
}
else if (0 == strcmp("name", result[j]))
{
info.tableName = result[(i + 1) * cols + j];
}
}
info.id = sqlite3_column_int(stmt, 0);
info.tableName = (const char*)sqlite3_column_text(stmt, 1);
tables.push_back(info);
ret = sqlite3_step(stmt);
}
sqlite3_free_table(result);
assert(!tables.empty());
ret = sqlite3_finalize(stmt);
assert(0 == ret);
assert(!tables.empty());
std::sort(tables.begin(), tables.end(), MainTableSort);
m_currBatchId = tables[tables.size() - 1].tableName;
}
@ -185,6 +177,14 @@ namespace ver_2
StopScan(errInfo);
}
void ManagerV2::ScanImage(const ScanImageParam* param)
{
assert(NULL != param && this == param->mgr);
m_saveFilePathList.push_back(param->fileName);
RestoreSaveFilePathList(m_saveFilePathList);
}
void ManagerV2::SetSaneEvent(SaneEvent event, void* param)
{
assert(NULL != event && NULL != param);
@ -353,10 +353,8 @@ namespace ver_2
return ret;
imagePath = imagePath2;
HGBase_EnterLock(m_lock);
m_saveFilePathList.push_back(imagePath);
RestoreSaveFilePathList(m_saveFilePathList);
HGBase_LeaveLock(m_lock);
errInfo.clear();
return 0;
@ -367,7 +365,6 @@ namespace ver_2
int ret = -1;
errInfo = "错误";
HGBase_EnterLock(m_lock);
for (int i = 0; i < (int)m_saveFilePathList.size(); ++i)
{
if (filePath == m_saveFilePathList[i])
@ -383,14 +380,12 @@ namespace ver_2
}
}
RestoreSaveFilePathList(m_saveFilePathList);
HGBase_LeaveLock(m_lock);
return ret;
}
int ManagerV2::ClearGlobalFileSavePath(std::string& errInfo)
{
HGBase_EnterLock(m_lock);
int i = 0;
while (i < (int)m_saveFilePathList.size())
{
@ -413,7 +408,6 @@ namespace ver_2
}
}
RestoreSaveFilePathList(m_saveFilePathList);
HGBase_LeaveLock(m_lock);
HGBase_DeleteDir(m_globalCfg.fileSavePath.c_str());
errInfo.clear();
@ -530,10 +524,8 @@ namespace ver_2
int ret = SaveImage(outImage, outImagePath);
if (0 == ret)
{
HGBase_EnterLock(m_lock);
m_saveFilePathList.push_back(outImagePath);
RestoreSaveFilePathList(m_saveFilePathList);
HGBase_LeaveLock(m_lock);
errInfo.clear();
}
@ -600,10 +592,8 @@ namespace ver_2
}
outImagePath = outImagePath2;
HGBase_EnterLock(m_lock);
m_saveFilePathList.push_back(outImagePath);
RestoreSaveFilePathList(m_saveFilePathList);
HGBase_LeaveLock(m_lock);
return ret;
}
@ -672,10 +662,8 @@ namespace ver_2
if (0 == SaveImage(img, imgPath))
{
outImagePathList.push_back(imgPath);
HGBase_EnterLock(m_lock);
m_saveFilePathList.push_back(imgPath);
RestoreSaveFilePathList(m_saveFilePathList);
HGBase_LeaveLock(m_lock);
errInfo.clear();
ret = 0;
}
@ -762,10 +750,8 @@ namespace ver_2
}
outZipPath = outZipPath2;
HGBase_EnterLock(m_lock);
m_saveFilePathList.push_back(outZipPath);
RestoreSaveFilePathList(m_saveFilePathList);
HGBase_LeaveLock(m_lock);
return ret;
}
@ -788,10 +774,8 @@ namespace ver_2
{
if (0 == SaveImage(img, outImagePath))
{
HGBase_EnterLock(m_lock);
m_saveFilePathList.push_back(outImagePath);
RestoreSaveFilePathList(m_saveFilePathList);
HGBase_LeaveLock(m_lock);
errInfo.clear();
ret = 0;
}
@ -965,10 +949,8 @@ namespace ver_2
{
if (0 == SaveImage(image, outImagePath))
{
HGBase_EnterLock(m_lock);
m_saveFilePathList.push_back(outImagePath);
RestoreSaveFilePathList(m_saveFilePathList);
HGBase_LeaveLock(m_lock);
errInfo.clear();
ret = 0;
}
@ -1237,32 +1219,25 @@ namespace ver_2
std::vector<MainTableInfo> tables;
char** result = NULL;
int rows, cols;
int ret = sqlite3_get_table(m_sqlite, "select * from table_", &result, &rows, &cols, NULL);
assert(0 == ret && rows > 0 && cols == 2);
sqlite3_stmt* stmt = NULL;
int ret = sqlite3_prepare(m_sqlite, "select * from table_", -1, &stmt, NULL);
assert(0 == ret);
for (int i = 0; i < rows; i++)
ret = sqlite3_step(stmt);
while (SQLITE_ROW == ret)
{
MainTableInfo info;
for (int j = 0; j < cols; j++)
{
if (0 == strcmp("id", result[j]))
{
info.id = atoi(result[(i + 1) * cols + j]);
}
else if (0 == strcmp("name", result[j]))
{
info.tableName = result[(i + 1) * cols + j];
}
}
info.id = sqlite3_column_int(stmt, 0);
info.tableName = (const char*)sqlite3_column_text(stmt, 1);
tables.push_back(info);
ret = sqlite3_step(stmt);
}
sqlite3_free_table(result);
assert(!tables.empty());
ret = sqlite3_finalize(stmt);
assert(0 == ret);
assert(!tables.empty());
std::sort(tables.begin(), tables.end(), MainTableSort);
for (int i = 0; i < (int)tables.size(); ++i)
batchIdList.push_back(tables[i].tableName);
@ -1616,10 +1591,8 @@ namespace ver_2
if (SaveToFile((const HGByte*)imgData, imgSize, imagePath2))
{
imagePath = imagePath2;
HGBase_EnterLock(m_lock);
m_saveFilePathList.push_back(imagePath);
RestoreSaveFilePathList(m_saveFilePathList);
HGBase_LeaveLock(m_lock);
errInfo.clear();
rc = 0;
@ -1686,6 +1659,10 @@ namespace ver_2
int ret;
char sql[1024];
ret = sqlite3_exec(m_sqlite, "begin", NULL, NULL, NULL);
assert(0 == ret);
bool ok = true;
for (int i = 0; i < (int)tables.size(); ++i)
{
if (tables[i].idx >= insertPos)
@ -1693,9 +1670,22 @@ namespace ver_2
sprintf(sql, "update 'table_%s' set idx = '%d' where id = '%d'",
m_currBatchId.c_str(), tables[i].idx + 1, tables[i].id);
ret = sqlite3_exec(m_sqlite, sql, NULL, NULL, NULL);
assert(0 == ret);
if (0 != ret)
{
ok = false;
break;
}
}
}
if (!ok)
{
ret = sqlite3_exec(m_sqlite, "rollback", NULL, NULL, NULL);
assert(0 == ret);
delete[] thumbData;
delete[] imgData;
return -1;
}
sprintf(sql, "insert into 'table_%s' (idx, format, tag, image, thumb) values ('%d', '%s', '%s', ?, ?)", m_currBatchId.c_str(),
insertPos, imgFormat.c_str(), imageTag.c_str());
@ -1708,6 +1698,16 @@ namespace ver_2
assert(0 == ret);
sqlite3_step(stmt);
ret = sqlite3_finalize(stmt);
if (0 != ret)
{
ret = sqlite3_exec(m_sqlite, "rollback", NULL, NULL, NULL);
assert(0 == ret);
delete[] thumbData;
delete[] imgData;
return -1;
}
ret = sqlite3_exec(m_sqlite, "commit", NULL, NULL, NULL);
assert(0 == ret);
if (!m_bindFolder.empty())
@ -3515,36 +3515,27 @@ namespace ver_2
{
tables.clear();
char** result = NULL;
sqlite3_stmt* stmt = NULL;
char sql[256];
sprintf(sql, "select id, idx, format from 'table_%s'", m_currBatchId.c_str());
int rows, cols;
int ret = sqlite3_get_table(m_sqlite, sql, &result, &rows, &cols, NULL);
int ret = sqlite3_prepare(m_sqlite, sql, -1, &stmt, NULL);
assert(0 == ret);
for (int i = 0; i < rows; i++)
ret = sqlite3_step(stmt);
while (SQLITE_ROW == ret)
{
BatchTableInfo info;
for (int j = 0; j < cols; j++)
{
if (0 == strcmp("id", result[j]))
{
info.id = atoi(result[(i + 1) * cols + j]);
}
else if (0 == strcmp("idx", result[j]))
{
info.idx = atoi(result[(i + 1) * cols + j]);
}
else if (0 == strcmp("format", result[j]))
{
info.format = result[(i + 1) * cols + j];
}
}
info.id = sqlite3_column_int(stmt, 0);
info.idx = sqlite3_column_int(stmt, 1);
info.format = (const char *)sqlite3_column_text(stmt, 2);
tables.push_back(info);
ret = sqlite3_step(stmt);
}
sqlite3_free_table(result);
ret = sqlite3_finalize(stmt);
assert(0 == ret);
std::sort(tables.begin(), tables.end(), BatchTableSort);
}
@ -3937,8 +3928,17 @@ namespace ver_2
int ret = p->SaveImage(img, imagePath);
if (0 == ret)
{
p->m_saveFilePathList.push_back(imagePath);
p->RestoreSaveFilePathList(p->m_saveFilePathList);
ScanImageParam* scanImageParam = new ScanImageParam;
scanImageParam->mgr = p;
scanImageParam->fileName = imagePath;
HGMsg msg;
msg.id = MSGID_SCAN_IMAGE;
msg.data = scanImageParam;
if (HGBASE_ERR_OK != HGBase_PostPumpMessage(p->m_msgPump, &msg))
{
delete scanImageParam;
}
if (NULL != p->m_saneImageCallback)
p->m_saneImageCallback(imagePath.c_str(), p->m_saneImageParam);

View File

@ -130,6 +130,8 @@ namespace ver_2
void CloseDev(const CloseDevParam* param);
// 扫描完成
void ScanFinish(const ScanFinishParam* param);
// 扫描图像
void ScanImage(const ScanImageParam* param);
// 设置回调
void SetSaneEvent(SaneEvent event, void* param);

View File

@ -96,6 +96,7 @@ namespace ver_2
{
MSGID_CLOSE_DEVICE = 3L,
MSGID_SCAN_FINISH,
MSGID_SCAN_IMAGE,
MSGID_WS_COMMAND,
MSGID_WS_EVENT
};
@ -114,6 +115,12 @@ namespace ver_2
ManagerV2* mgr;
};
struct ScanImageParam
{
ManagerV2* mgr;
std::string fileName;
};
struct WSCmdParam
{
WSServer* svr;

View File

@ -116,6 +116,13 @@ namespace ver_2
delete param;
}
break;
case MSGID_SCAN_IMAGE:
{
ScanImageParam* param = (ScanImageParam*)msg->data;
param->mgr->ScanImage(param);
delete param;
}
break;
case MSGID_WS_COMMAND:
{
WSCmdParam* param = (WSCmdParam*)msg->data;