代码
#ifndef __MY_DATA__
#define __MY_DATA__
#include <unordered_map>
#include <pthread.h>
#include "fileUtil.hpp"
#include "config.hpp"
namespace cloudBackup
{
typedef struct BackupAInfo
{
bool _isZipped;
size_t _fsize;
time_t _atime;
time_t _ctime;
time_t _mtime;
std::string _backupPath;
std::string _zipPath;
std::string _url;
bool NewBackupAInfo(const std::string &filename)
{
FileUtil fileUtil(filename);
if (fileUtil.Exists() == false)
{
Log::log(Error, "BackupInfo::NewBackupAInfo file not exists!: %s: %d", strerror(errno), errno);
return false;
}
Config *config = Config::GetInstance();
std::string zipDir = config->GetZipDir();
std::string zipSuffix = config->GetZipSuffix();
std::string urlPrefix = config->GetUrlPrefix();
this->_isZipped = false;
this->_fsize = fileUtil.FileSize();
this->_atime = fileUtil.LastATime();
this->_ctime = fileUtil.LastCTime();
this->_mtime = fileUtil.LastMTime();
this->_backupPath = filename;
this->_zipPath = zipDir + fileUtil.FileName() + zipSuffix;
this->_url = urlPrefix + fileUtil.FileName();
return true;
}
void showMsg()
{
std::cout << "_isZipped: " << _isZipped << std::endl;
std::cout << "_fsize: " << _fsize << std::endl;
std::cout << "_atime: " << _atime << std::endl;
std::cout << "_ctime: " << _ctime << std::endl;
std::cout << "_mtime: " << _mtime << std::endl;
std::cout << "_backupPath: " << _backupPath << std::endl;
std::cout << "_zipPath: " << _zipPath << std::endl;
std::cout << "_url: " << _url << std::endl;
}
} BackupAInfo;
class DataManager
{
private:
std::string _backupAInfoFile;
std::unordered_map<std::string, BackupAInfo> _table;
pthread_rwlock_t _rwlock;
public:
DataManager()
{
_backupAInfoFile = Config::GetInstance()->GetBackupAInfoFName();
pthread_rwlock_init(&_rwlock, NULL);
InitLoad();
}
~DataManager()
{
pthread_rwlock_destroy(&_rwlock);
}
bool InitLoad()
{
FileUtil fileUtil(_backupAInfoFile);
if (fileUtil.Exists() == false)
{
Log::log(Info, "DataManager::InitLoad file not exist, no need to load: %s: %d", strerror(errno), errno);
return true;
}
std::string content;
fileUtil.GetContent(&content);
Json::Value root;
JsonUtil::Deserialize(content, &root);
for (int i = 0; i < root.size(); i++)
{
BackupAInfo info;
info._isZipped = root[i]["_isZipped"].asBool();
info._fsize = root[i]["_fsize"].asInt64();
info._atime = root[i]["_atime"].asInt64();
info._ctime = root[i]["_ctime"].asInt64();
info._mtime = root[i]["_mtime"].asInt64();
info._zipPath = root[i]["_zipPath"].asString();
info._backupPath = root[i]["_backupPath"].asString();
info._url = root[i]["_url"].asString();
Insert_Table(info);
}
return true;
}
bool Insert_Table(const BackupAInfo &info)
{
pthread_rwlock_wrlock(&_rwlock);
_table[info._url] = info;
pthread_rwlock_unlock(&_rwlock);
Storage();
return true;
}
bool Storage()
{
std::vector<BackupAInfo> array;
this->GetAllBackupAInfo(&array);
Json::Value root;
for (int i = 0; i < array.size(); i++)
{
Json::Value item;
item["_isZipped"] = array[i]._isZipped;
item["_fsize"] = (Json::Int64)array[i]._fsize;
item["_atime"] = (Json::Int64)array[i]._atime;
item["_ctime"] = (Json::Int64)array[i]._ctime;
item["_mtime"] = (Json::Int64)array[i]._mtime;
item["_backupPath"] = array[i]._backupPath;
item["_zipPath"] = array[i]._zipPath;
item["_url"] = array[i]._url;
root.append(item);
}
std::string content;
JsonUtil::Serialize(root, &content);
FileUtil fileUtil(_backupAInfoFile);
fileUtil.SetContent(content);
return true;
}
bool GetAllBackupAInfo(std::vector<BackupAInfo> *array)
{
pthread_rwlock_wrlock(&_rwlock);
for (auto it = _table.begin(); it != _table.end(); ++it)
array->push_back(it->second);
pthread_rwlock_unlock(&_rwlock);
return true;
}
bool Update(const BackupAInfo &info)
{
pthread_rwlock_wrlock(&_rwlock);
_table[info._url] = info;
pthread_rwlock_unlock(&_rwlock);
Storage();
return true;
}
bool GetOneByURL(const std::string &url, BackupAInfo *info)
{
pthread_rwlock_wrlock(&_rwlock);
auto it = _table.find(url);
if (it == _table.end())
{
pthread_rwlock_unlock(&_rwlock);
Log::log(Error, "DataManager::GetOneByURL not find url-?: %s: %d", strerror(errno), errno);
return false;
}
*info = it->second;
pthread_rwlock_unlock(&_rwlock);
return true;
}
bool GetOneByRealPath(const std::string &filename, BackupAInfo *info)
{
pthread_rwlock_wrlock(&_rwlock);
for (auto it = _table.begin(); it != _table.end(); ++it)
{
if (it->second._backupPath == filename)
{
*info = it->second;
pthread_rwlock_unlock(&_rwlock);
return true;
}
}
pthread_rwlock_unlock(&_rwlock);
Log::log(Error, "DataManager::GetOneByRealPath not find realpath-?: %s: %d", strerror(errno), errno);
return false;
}
};
}
#endif
测试代码
#include "fileUtil.hpp"
#include "jsonUtil.hpp"
#include "config.hpp"
#include "data.hpp"
#include <thread>
using namespace std;
void DataTest(const std::string &filename)
{
std::cout << "NewBackupAInfo " << std::endl;
cloudBackup::BackupAInfo info;
info.NewBackupAInfo(filename);
info.showMsg();
std::cout << std::endl;
std::cout << " GetOneByURL" << std::endl;
cloudBackup::DataManager dataManager;
dataManager.Insert_Table(info);
cloudBackup::BackupAInfo tmp;
dataManager.GetOneByURL("/download/makefile", &tmp);
tmp.showMsg();
std::cout << std::endl;
std::cout << "GetAllBackupAInfo " << std::endl;
std::vector<cloudBackup::BackupAInfo> array;
dataManager.GetAllBackupAInfo(&array);
for (auto &a : array)
a.showMsg();
std::cout << std::endl;
std::cout << "info._isZipped = true " << std::endl;
info._isZipped = true;
dataManager.Update(info);
array.clear();
dataManager.GetAllBackupAInfo(&array);
for (auto &a : array)
a.showMsg();
std::cout << std::endl;
std::cout << "GetOneByRealPath" << std::endl;
dataManager.GetOneByRealPath(filename, &tmp);
tmp.showMsg();
std::cout << std::endl;
}
int main(int argc, char *argv[])
{
DataTest(argv[1]);
return 0;
}
数据管理总结
- backupAInfo.dat:存放的是备份文件属性信息。其中的reqDownloadPath是备份文件被用户通过浏览器下载时候的http请求资源路径。
- std::unordered_map<std::string, BackupAInfo> _table;存放:以reqDownloadPath为key,以backupAInfo_root对象为value的键值对
- 代码总体