|
|
@@ -2,6 +2,7 @@
|
|
|
#include "DataBackup.h"
|
|
|
#include "global.h"
|
|
|
#include "vr_ext.h"
|
|
|
+#include <set>
|
|
|
|
|
|
|
|
|
#include <imagehlp.h>
|
|
|
@@ -20,8 +21,8 @@ DataBackup::DataBackup()
|
|
|
void DataBackup::Init()
|
|
|
{
|
|
|
|
|
|
- int enable = GetPrivateProfileIntA("DataBackup", "Enable", 0, ".//conn.ini");
|
|
|
- if (!enable)
|
|
|
+ m_enable = GetPrivateProfileIntA("DataBackup", "Enable", 0, ".//conn.ini");
|
|
|
+ if (!m_enable)
|
|
|
{
|
|
|
if (FindDisk(DISK_SIZE))
|
|
|
{
|
|
|
@@ -77,11 +78,11 @@ void DataBackup::Init()
|
|
|
char dir[MAX_PATH] = { 0 };
|
|
|
_get_instance_dir(dir, MAX_PATH);
|
|
|
|
|
|
- string sourcedir = string(dir) + "data\\";
|
|
|
|
|
|
- string source = sourcedir + "*.*";
|
|
|
- string destdir = g_backuppath;//"C:\\VRBackup\\data\\";
|
|
|
- string dest = destdir + "*.*";
|
|
|
+ sourcedir = string(dir) + "data\\";
|
|
|
+ source = sourcedir + "*.db";
|
|
|
+ destdir = g_backuppath;//"C:\\VRBackup\\data\\";
|
|
|
+ dest = destdir + "*.db";
|
|
|
|
|
|
|
|
|
int pathrtn = MakeSureDirectoryPathExists(destdir.c_str());
|
|
|
@@ -103,65 +104,46 @@ void DataBackup::Init()
|
|
|
|
|
|
|
|
|
|
|
|
-
|
|
|
int datacount = 0;
|
|
|
int successcount = 0;
|
|
|
int backupcount = 0;
|
|
|
+ std::set<string> dbset;
|
|
|
+ std::set<string> backupset;
|
|
|
|
|
|
+ dbset = getdbset(source);
|
|
|
+ datacount = dbset.size();
|
|
|
|
|
|
+ backupset = getdbset(dest);
|
|
|
+ backupcount = backupset.size();
|
|
|
|
|
|
- intptr_t handle;
|
|
|
- _finddata_t findData;
|
|
|
-
|
|
|
- handle = _findfirst(source.c_str(), &findData); // 查找目录中的第一个文件
|
|
|
- if (handle == -1)
|
|
|
- {
|
|
|
- //Log("打开data目录失败!");
|
|
|
- //m_state = BackupState_READERROR;
|
|
|
+ std::set<string> diff1; // set1 中独有的元素
|
|
|
+ // 计算 set1 中独有的元素
|
|
|
+ std::set_difference(dbset.begin(), dbset.end(), backupset.begin(), backupset.end(), std::inserter(diff1, diff1.begin()));
|
|
|
|
|
|
- //找不到主目录的文件是第一次使用
|
|
|
- m_state = BackupState_NORMAL;
|
|
|
|
|
|
- return;
|
|
|
- }
|
|
|
+ string log = "共有" + to_string(datacount) + "个数据文件,备份目录有" + to_string(backupcount) + "个数据文件,主数据库独有"
|
|
|
+ + to_string(diff1.size()) +"个文件";
|
|
|
+ Log(log.c_str());
|
|
|
|
|
|
- do
|
|
|
+ for (auto it:diff1)
|
|
|
{
|
|
|
- if (findData.attrib & _A_SUBDIR)
|
|
|
- {
|
|
|
- /*if (string(findData.name) == "."
|
|
|
- || string(findData.name) == ".."
|
|
|
- ) */
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- std::string path1 = sourcedir + string(findData.name);
|
|
|
- std::string path2 = destdir + string(findData.name);
|
|
|
+ std::string path1 = sourcedir + it;
|
|
|
+ std::string path2 = destdir + it;
|
|
|
|
|
|
- datacount++;
|
|
|
-
|
|
|
- int rtn = CopyFileA(path1.c_str(), path2.c_str(), TRUE);//跳过存在的文件
|
|
|
- if (rtn)
|
|
|
- {
|
|
|
- successcount++;
|
|
|
- }
|
|
|
+ int rtn = CopyFileA(path1.c_str(), path2.c_str(), TRUE);//跳过存在的文件
|
|
|
+ if (rtn)
|
|
|
+ {
|
|
|
+ successcount++;
|
|
|
}
|
|
|
- } while (_findnext(handle, &findData) == 0); // 查找目录中的下一个文件
|
|
|
- _findclose(handle); // 关闭搜索句柄
|
|
|
-
|
|
|
-
|
|
|
+ }
|
|
|
|
|
|
backupcount = getFileCount(dest);
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- string log = "共找到" + to_string(datacount) + "个数据文件,复制" + to_string(successcount) + "个,当前备份目录有" + to_string(backupcount) + "个数据文件";
|
|
|
+ log = "主数据库复制" + to_string(successcount) + "个文件到备份数据库,备份数据库当前有"+to_string(backupcount)+"个文件";
|
|
|
Log(log.c_str());
|
|
|
|
|
|
|
|
|
+
|
|
|
if (backupcount < datacount)
|
|
|
{
|
|
|
m_state = BackupState_BACKUPERROR;
|
|
|
@@ -191,6 +173,118 @@ void DataBackup::Init()
|
|
|
}
|
|
|
|
|
|
|
|
|
+std::set<string> DataBackup::getdbset(string path)
|
|
|
+{
|
|
|
+ std::set<string> dbset;
|
|
|
+ intptr_t handle;
|
|
|
+ _finddata_t findData;
|
|
|
+ handle = _findfirst(path.c_str(), &findData); // 查找目录中的第一个文件
|
|
|
+ if (handle == -1)
|
|
|
+ {
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ do
|
|
|
+ {
|
|
|
+ if (string(findData.name) == "."
|
|
|
+ || string(findData.name) == ".."
|
|
|
+ ) // 是否是子目录并且不为"."或".."
|
|
|
+ {
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (string(findData.name).length() == 14)
|
|
|
+ {
|
|
|
+ dbset.insert(findData.name);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } while (_findnext(handle, &findData) == 0); // 查找目录中的下一个文件
|
|
|
+ }
|
|
|
+ _findclose(handle); // 关闭搜索句柄
|
|
|
+
|
|
|
+ return dbset;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+int DataBackup::recoverFromBackup(string& rtnmsg)
|
|
|
+{
|
|
|
+ int rtn = false;
|
|
|
+
|
|
|
+ if (m_state == BackupState_MAINDATALACKING)
|
|
|
+ {
|
|
|
+
|
|
|
+ int datacount = 0;
|
|
|
+ int successcount = 0;
|
|
|
+ int backupcount = 0;
|
|
|
+ std::set<string> dbset;
|
|
|
+ std::set<string> backupset;
|
|
|
+
|
|
|
+ dbset = getdbset(source);
|
|
|
+ datacount = dbset.size();
|
|
|
+
|
|
|
+ backupset = getdbset(dest);
|
|
|
+ backupcount = backupset.size();
|
|
|
+
|
|
|
+ std::set<string> diff2; // set2 中独有的元素
|
|
|
+ // 计算 set2 中独有的元素
|
|
|
+ std::set_difference(backupset.begin(), backupset.end(),dbset.begin(), dbset.end(), std::inserter(diff2, diff2.begin()));
|
|
|
+
|
|
|
+
|
|
|
+ string log = "共有" + to_string(datacount) + "个数据文件,备份目录有" + to_string(backupcount) + "个数据文件,备份数据库独有"
|
|
|
+ + to_string(diff2.size()) + "个文件";
|
|
|
+ Log(log.c_str());
|
|
|
+
|
|
|
+ for (auto it : diff2)
|
|
|
+ {
|
|
|
+ std::string path1 = sourcedir + it;
|
|
|
+ std::string path2 = destdir + it;
|
|
|
+
|
|
|
+ int rtn = CopyFileA(path2.c_str(), path1.c_str(), TRUE);//跳过存在的文件
|
|
|
+ if (rtn)
|
|
|
+ {
|
|
|
+ successcount++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ datacount = getFileCount(source);
|
|
|
+
|
|
|
+ log = "备份数据库复制" + to_string(successcount) + "个文件到主数据库,主数据库当前有" + to_string(datacount) + "个文件";
|
|
|
+ Log(log.c_str());
|
|
|
+
|
|
|
+
|
|
|
+ if (successcount != 0)
|
|
|
+ {
|
|
|
+ rtnmsg = "复制"+to_string(successcount) +"个文件";
|
|
|
+ if (datacount>=backupcount)
|
|
|
+ {
|
|
|
+ m_state = BackupState_NORMAL;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ rtnmsg += ",但主数据库文件数依然少于备份数据库";
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ rtnmsg = "复制0个文件,操作无效";
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ rtnmsg = "当前主数据库不需要修复";
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
void DataBackup::SetState(int state)
|
|
|
{
|
|
|
if (m_state == BackupState_MAINDATALACKING)
|