📄 dsmcc_storage.cpp
字号:
#include "dsmcc_storage.h"
bool DSM_CC::FilesystemStorage::StoreObject(uint32_t download_id, uint16_t module_id, uint8_t module_version, const BIOP::ServiceGateway& srg) {
(void)module_version;
if(!rootvalid) {
return false;
}
// By definition, the srg "is" the root directory, so its placement is the empty string
QString key = PlacementKey(download_id, module_id, srg.header);
QString placement = "";
placement_map[key] = placement;
uint32_t num_bindings = srg.bindings.size();
// Now, preallocate placements for all child objects
for(uint32_t i = 0; i < num_bindings; ++i) {
if(srg.bindings[i].ior.profiles[0].id_tag != BIOP_PROFILE_ID_BIOP) {
continue;
}
BIOP::BIOPProfile profile = srg.bindings[i].ior.profiles[0].biop;
BIOP::Name name = srg.bindings[i].name;
key = PlacementKey(profile.object_location.carousel_id,
profile.object_location.module_id,
profile.object_location.object_key,
profile.object_location.object_key_length);
placement = "/";
for(uint8_t j = 0; j < name.id.size(); ++j) {
placement += name.id[j];
}
placement_map[key] = placement;
}
return true;
}
bool DSM_CC::FilesystemStorage::StoreObject(uint32_t download_id, uint16_t module_id, uint8_t module_version, const BIOP::DirectoryMessage& dm) {
(void)module_version;
if(!rootvalid) {
return false;
}
QString dmkey = PlacementKey(download_id, module_id, dm.header);
QString placement = placement_map[dmkey];
// First off, create this directory
if(mkdir((rootpath + placement).ascii(), O_CREAT) && (errno != EEXIST)) {
#ifdef DSM_CC_TRACE_STORAGE
DSM_CC_TRACE_GENERAL("FilesystemStorage", "ERROR: Could not create directory");
DSM_CC_TRACE_STR("FilesystemStorage", "dirname", (rootpath + placement).ascii());
#endif
return false;
}
// And now, preallocate placements for all children
uint32_t num_bindings = dm.bindings.size();
for(uint32_t i = 0; i < num_bindings; ++i) {
if(dm.bindings[i].ior.profiles[0].id_tag != BIOP_PROFILE_ID_BIOP) {
continue;
}
BIOP::BIOPProfile profile = dm.bindings[i].ior.profiles[0].biop;
BIOP::Name name = dm.bindings[i].name;
QString key = PlacementKey(profile.object_location.carousel_id,
profile.object_location.module_id,
profile.object_location.object_key,
profile.object_location.object_key_length);
// If only I knew why this simply will _not_ work with normal append operators
QString bindplacement;
bindplacement.sprintf("%s/", placement_map[dmkey].ascii());
for(uint8_t j = 0; j < name.id.size(); ++j) {
bindplacement += name.id[j];
}
placement_map[key] = bindplacement;
}
return true;
}
bool DSM_CC::FilesystemStorage::StoreObject(uint32_t download_id, uint16_t module_id, uint8_t module_version, const BIOP::FileMessage& fm) {
(void)module_version;
if(!rootvalid) {
return false;
}
QString key = PlacementKey(download_id, module_id, fm.header);
QString placement = placement_map[key];
// Now simply dump all of it to the filesystem
FILE* fp;
if((fp = fopen((rootpath + placement).ascii(), "wb")) == NULL) {
#ifdef DSM_CC_TRACE_STORAGE
DSM_CC_TRACE_GENERAL("FilesystemStorage", "ERROR: Could not create file");
DSM_CC_TRACE_STR("FilesystemStorage", "filename", (rootpath + placement).ascii());
#endif
return false;
}
size_t written;
if((written = fwrite(fm.contents, sizeof(uint8_t), fm.header.message_body_length - 4, fp)) != fm.header.message_body_length - 4) {
#ifdef DSM_CC_TRACE_STORAGE
DSM_CC_TRACE_GENERAL("FilesystemStorage", "ERROR: Could not write enough data to file");
DSM_CC_TRACE_STR("FilesystemStorage", "filename", (rootpath + placement).ascii());
DSM_CC_TRACE_NUM("FilesystemStorage", "bytes written", written, "8");
DSM_CC_TRACE_NUM("FilesystemStorage", "bytes attempted", fm.header.message_body_length - 4, "8");
#endif
return false;
}
fclose(fp);
return true;
}
void DSM_CC::FilesystemStorage::SetStorageRoot(QString newroot) {
if(mkdir(newroot.ascii(), O_CREAT) && (errno != EEXIST)) {
#ifdef DSM_CC_TRACE_STORAGE
DSM_CC_TRACE_GENERAL("FilesystemStorage", "ERROR: Could not create storage root");
DSM_CC_TRACE_STR("FilesystemStorage", "dirname", newroot.ascii());
#endif
return;
}
rootvalid = true;
rootpath = newroot;
}
QString DSM_CC::FilesystemStorage::GetStorageRoot() {
return rootpath;
}
uint32_t DSM_CC::MythDatabaseStorage::next_insert_id = 0;
uint32_t DSM_CC::MythDatabaseStorage::GetNextInsertId() {
// Get and cache the next available id value from the database
MSqlQuery query(MSqlQuery::InitCon());
query.prepare("SELECT max(id) FROM dsmcc_objects");
query.exec();
if(!query.isActive()) {
#ifdef DSM_CC_TRACE_STORAGE
DSM_CC_TRACE_GENERAL("MythDBStorage", "Could not query maximum id from database");
#endif
return false;
}
query.next();
return next_insert_id = query.value(0).toInt() + 1;
}
bool DSM_CC::MythDatabaseStorage::StoreObject(uint32_t download_id, uint16_t module_id, uint8_t module_version, const BIOP::ServiceGateway& srg) {
// First of all make sure that next_insert_id is initialized
// This is only useful in this StoreObject() overload because it's guaranteed to be called first
if(next_insert_id == 0) {
if(!GetNextInsertId()) {
return false;
}
}
MSqlQuery query(MSqlQuery::InitCon());
// Insert ourselves into the parent relationship map
QString key = PlacementKey(download_id, module_id, srg.header);
object_info[key].parent = 0;
object_info[key].name = "";
// Do we exist in the database?
query.prepare(QString(
"SELECT id, module_version FROM dsmcc_objects "
"WHERE download_id = %1 AND module_id = %2 AND object_key = ?"
).arg(download_id).arg(module_id)
);
query.bindValue(0, MakeString(srg.header.object_key.begin(), srg.header.object_key.size()));
query.exec();
if(!query.isActive()) {
#ifdef DSM_CC_TRACE_STORAGE
DSM_CC_TRACE_STR("MythDBStorage", "Bad query", query.executedQuery().ascii());
#endif
return false;
}
if(!query.size()) {
// No, we don't exist, so insert the record
query.prepare(QString(
"INSERT INTO dsmcc_objects (id, download_id, module_id, module_version, object_key, object_name, object_type, parent_id) "
"VALUES (%1, %2, %3, %4, ?, '', 'srg', 0)"
).arg(next_insert_id++).arg(download_id).arg(module_id).arg(module_version)
);
query.bindValue(0, MakeString(srg.header.object_key.begin(), srg.header.object_key.size()));
query.exec();
if(!query.isActive()) {
#ifdef DSM_CC_TRACE_STORAGE
DSM_CC_TRACE_STR("MythDBStorage", "Bad query", query.executedQuery().ascii());
#endif
return false;
}
}
else {
// We exist; if the module version is the same, then do nothing
// Otherwise, update the record to reflect the new data
query.next();
if(query.value(1).toInt() != module_version) {
// Simply update the version; nothing else required (the object key is the same, see first query)
QString newquery("UPDATE dsmcc_objects SET module_version = %1 WHERE id = %2");
query.prepare(newquery.arg(module_version).arg(query.value(0).toInt()));
query.exec();
if(!query.isActive()) {
#ifdef DSM_CC_TRACE_STORAGE
DSM_CC_TRACE_STR("MythDBStorage", "Bad query", query.executedQuery().ascii());
#endif
return false;
}
}
}
// Great! Now we have to prepare child object data in the hashtables
uint32_t num_bindings = srg.bindings.size();
for(uint32_t i = 0; i < num_bindings; ++i) {
if(srg.bindings[i].ior.profiles[0].id_tag != BIOP_PROFILE_ID_BIOP) {
continue;
}
BIOP::BIOPProfile profile = srg.bindings[i].ior.profiles[0].biop;
QString key = PlacementKey(profile.object_location.carousel_id,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -