/************************************************************************* * UrBackup - Client/Server backup system * Copyright (C) 2011 Martin Raiber * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . **************************************************************************/ #include "clientdao.h" #include "../stringtools.h" #include "../Interface/Server.h" #include ClientDAO::ClientDAO(IDatabase *pDB) { db=pDB; prepareQueries(); } void ClientDAO::prepareQueries(void) { q_get_files=db->Prepare("SELECT data,num FROM files WHERE name=?", false); q_add_files=db->Prepare("INSERT INTO files_tmp (name, num, data) VALUES (?,?,?)", false); q_get_dirs=db->Prepare("SELECT name, path, id FROM backupdirs", false); q_remove_all=db->Prepare("DELETE FROM files", false); q_get_changed_dirs=db->Prepare("SELECT id, name FROM mdirs", false); q_remove_changed_dirs=db->Prepare("DELETE FROM mdirs", false); q_modify_files=db->Prepare("UPDATE files SET data=?, num=? WHERE name=?", false); q_has_files=db->Prepare("SELECT count(*) AS num FROM files WHERE name=?", false); q_insert_shadowcopy=db->Prepare("INSERT INTO shadowcopies (vssid, ssetid, target, path, tname, orig_target, filesrv, vol, starttime, refs, starttoken) VALUES (?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, ?, ?)", false); q_get_shadowcopies=db->Prepare("SELECT id, vssid, ssetid, target, path, tname, orig_target, filesrv, vol, (strftime('%s','now') - strftime('%s', starttime)) AS passedtime, refs, starttoken FROM shadowcopies", false); q_remove_shadowcopies=db->Prepare("DELETE FROM shadowcopies WHERE id=?", false); q_save_changed_dirs=db->Prepare("INSERT OR REPLACE INTO mdirs_backup SELECT id,name FROM mdirs", false); q_delete_saved_changed_dirs=db->Prepare("DELETE FROM mdirs_backup", false); q_restore_saved_changed_dirs=db->Prepare("INSERT OR REPLACE INTO mdirs SELECT id, name FROM mdirs_backup", false); q_copy_from_tmp_files=db->Prepare("INSERT INTO files (num, data, name) SELECT num, data, name FROM files_tmp", false); q_delete_tmp_files=db->Prepare("DELETE FROM files_tmp", false); q_has_changed_gap=db->Prepare("SELECT name FROM mdirs WHERE name GLOB '##-GAP-##*'", false); q_get_del_dirs=db->Prepare("SELECT name FROM del_dirs", false); q_del_del_dirs=db->Prepare("DELETE FROM del_dirs", false); q_restore_del_dirs=db->Prepare("INSERT INTO del_dirs SELECT name FROM del_dirs_backup", false); q_copy_del_dirs=db->Prepare("INSERT INTO del_dirs_backup SELECT name FROM del_dirs", false); q_del_del_dirs_copy=db->Prepare("DELETE FROM del_dirs_backup", false); q_remove_del_dir=db->Prepare("DELETE FROM files WHERE name GLOB ?", false); q_get_shadowcopy_refcount=db->Prepare("SELECT refs FROM shadowcopies WHERE id=?", false); q_set_shadowcopy_refcount=db->Prepare("UPDATE shadowcopies SET refs=? WHERE id=?", false); q_save_changed_files=db->Prepare("INSERT OR REPLACE INTO mfiles_backup SELECT dir_id,name FROM mfiles", false); q_remove_changed_files=db->Prepare("DELETE FROM mfiles", false); q_delete_saved_changed_files=db->Prepare("DELETE FROM mfiles_backup", false); q_restore_saved_changed_files=db->Prepare("INSERT OR REPLACE INTO mfiles SELECT dir_id,name FROM mfiles_backup", false); q_has_changed_file=db->Prepare("SELECT dir_id FROM mfiles_backup WHERE dir_id=? AND name=?", false); q_get_changed_files=db->Prepare("SELECT name FROM mfiles_backup WHERE dir_id=?", false);; } void ClientDAO::destroyQueries(void) { db->destroyQuery(q_get_files); db->destroyQuery(q_add_files); db->destroyQuery(q_get_dirs); db->destroyQuery(q_remove_all); db->destroyQuery(q_get_changed_dirs); db->destroyQuery(q_remove_changed_dirs); db->destroyQuery(q_modify_files); db->destroyQuery(q_has_files); db->destroyQuery(q_insert_shadowcopy); db->destroyQuery(q_get_shadowcopies); db->destroyQuery(q_remove_shadowcopies); db->destroyQuery(q_save_changed_dirs); db->destroyQuery(q_delete_saved_changed_dirs); db->destroyQuery(q_restore_saved_changed_dirs); db->destroyQuery(q_copy_from_tmp_files); db->destroyQuery(q_delete_tmp_files); db->destroyQuery(q_has_changed_gap); db->destroyQuery(q_get_del_dirs); db->destroyQuery(q_del_del_dirs); db->destroyQuery(q_restore_del_dirs); db->destroyQuery(q_copy_del_dirs); db->destroyQuery(q_del_del_dirs_copy); db->destroyQuery(q_remove_del_dir); db->destroyQuery(q_get_shadowcopy_refcount); db->destroyQuery(q_set_shadowcopy_refcount); db->destroyQuery(q_save_changed_files); db->destroyQuery(q_remove_changed_files); db->destroyQuery(q_delete_saved_changed_files); db->destroyQuery(q_restore_saved_changed_files); db->destroyQuery(q_has_changed_file); db->destroyQuery(q_get_changed_files); } void ClientDAO::restartQueries(void) { destroyQueries(); prepareQueries(); } bool ClientDAO::getFiles(std::wstring path, std::vector &data) { q_get_files->Bind(path); db_results res=q_get_files->Read(); q_get_files->Reset(); if(res.size()==0) return false; std::wstring &qdata=res[0][L"data"]; if(qdata.empty()) return true; int num=watoi(res[0][L"num"]); char *ptr=(char*)&qdata[0]; while(ptr-(char*)&qdata[0]ConvertToUnicode(tmp); ptr+=ss; memcpy(&f.size, ptr, sizeof(int64)); ptr+=sizeof(int64); memcpy(&f.last_modified, ptr, sizeof(int64)); ptr+=sizeof(int64); char isdir=*ptr; ++ptr; if(isdir==0) f.isdir=false; else f.isdir=true; data.push_back(f); } return true; } char * constructData(const std::vector &data, size_t &datasize) { datasize=0; std::vector utf; for(size_t i=0;iConvertToUTF8(data[i].name); datasize+=us.size(); datasize+=sizeof(unsigned short); datasize+=sizeof(int64)*2; ++datasize; utf.push_back(us); } char *buffer=new char[datasize]; char *ptr=buffer; for(size_t i=0;i &data) { size_t ds; char *buffer=constructData(data, ds); q_add_files->Bind(path); q_add_files->Bind(ds); q_add_files->Bind(buffer, (_u32)ds); q_add_files->Write(); q_add_files->Reset(); delete []buffer; } void ClientDAO::modifyFiles(std::wstring path, const std::vector &data) { size_t ds; char *buffer=constructData(data, ds); q_modify_files->Bind(buffer, (_u32)ds); q_modify_files->Bind(ds); q_modify_files->Bind(path); q_modify_files->Write(); q_modify_files->Reset(); delete []buffer; } bool ClientDAO::hasFiles(std::wstring path) { q_has_files->Bind(path); db_results res=q_has_files->Read(); q_has_files->Reset(); if(res.size()>0) return res[0][L"num"]==L"1"; else return false; } std::vector ClientDAO::getBackupDirs(void) { db_results res=q_get_dirs->Read(); q_get_dirs->Reset(); std::vector ret; for(size_t i=0;iWrite(); } std::vector ClientDAO::getChangedDirs(bool del) { std::vector ret; db->BeginTransaction(); db_results res=q_get_changed_dirs->Read(); q_get_changed_dirs->Reset(); if(del) { q_save_changed_dirs->Write(); q_save_changed_dirs->Reset(); q_remove_changed_dirs->Write(); q_remove_changed_dirs->Reset(); } db->EndTransaction(); for(size_t i=0;iBeginTransaction(); q_save_changed_files->Write(); q_save_changed_files->Reset(); if(del) { q_remove_changed_files->Write(); q_remove_changed_files->Reset(); } db->EndTransaction(); } std::vector ClientDAO::getShadowcopies(void) { db_results res=q_get_shadowcopies->Read(); q_get_shadowcopies->Reset(); std::vector ret; for(size_t i=0;iBind((char*)&sc.vssid, sizeof(GUID) ); q_insert_shadowcopy->Bind((char*)&sc.ssetid, sizeof(GUID) ); q_insert_shadowcopy->Bind(sc.target); q_insert_shadowcopy->Bind(sc.path); q_insert_shadowcopy->Bind(sc.tname); q_insert_shadowcopy->Bind(sc.orig_target); q_insert_shadowcopy->Bind(sc.filesrv?1:0); q_insert_shadowcopy->Bind(sc.vol); q_insert_shadowcopy->Bind(sc.refs); q_insert_shadowcopy->Bind(sc.starttoken); q_insert_shadowcopy->Write(); q_insert_shadowcopy->Reset(); return (int)db->getLastInsertID(); } int ClientDAO::modShadowcopyRefCount(int id, int m) { q_get_shadowcopy_refcount->Bind(id); db_results res=q_get_shadowcopy_refcount->Read(); q_get_shadowcopy_refcount->Reset(); if(!res.empty()) { int refs=watoi(res[0][L"refs"]); refs+=m; q_set_shadowcopy_refcount->Bind(refs); q_set_shadowcopy_refcount->Bind(id); q_set_shadowcopy_refcount->Write(); q_set_shadowcopy_refcount->Reset(); return refs; } return -1; } void ClientDAO::deleteShadowcopy(int id) { q_remove_shadowcopies->Bind(id); q_remove_shadowcopies->Write(); q_remove_shadowcopies->Reset(); } void ClientDAO::deleteSavedChangedDirs(void) { q_delete_saved_changed_dirs->Write(); q_delete_saved_changed_dirs->Reset(); } void ClientDAO::restoreSavedChangedDirs(void) { q_restore_saved_changed_dirs->Write(); q_restore_saved_changed_dirs->Reset(); } void ClientDAO::deleteSavedChangedFiles(void) { q_delete_saved_changed_files->Write(); q_delete_saved_changed_files->Reset(); } void ClientDAO::restoreSavedChangedFiles(void) { q_restore_saved_changed_files->Write(); q_restore_saved_changed_files->Reset(); } void ClientDAO::copyFromTmpFiles(void) { q_copy_from_tmp_files->Write(); q_copy_from_tmp_files->Reset(); q_delete_tmp_files->Write(); q_delete_tmp_files->Reset(); } bool ClientDAO::hasChangedGap(void) { db_results res=q_has_changed_gap->Read(); q_has_changed_gap->Reset(); return !res.empty(); } void ClientDAO::deleteChangedDirs(void) { q_remove_changed_dirs->Write(); q_remove_changed_dirs->Reset(); } std::vector ClientDAO::getGapDirs(void) { db_results res=q_has_changed_gap->Read(); q_has_changed_gap->Reset(); std::vector ret; for(size_t i=0;i ClientDAO::getDelDirs(bool del) { std::vector ret; db->BeginTransaction(); db_results res=q_get_del_dirs->Read(); q_get_del_dirs->Reset(); if(del) { q_copy_del_dirs->Write(); q_copy_del_dirs->Reset(); q_del_del_dirs->Write(); q_del_del_dirs->Reset(); } db->EndTransaction(); for(size_t i=0;iWrite(); q_del_del_dirs_copy->Reset(); } void ClientDAO::restoreSavedDelDirs(void) { q_restore_del_dirs->Write(); q_restore_del_dirs->Reset(); } void ClientDAO::removeDeletedDir(const std::wstring &dir) { q_remove_del_dir->Bind(dir+L"*"); q_remove_del_dir->Write(); q_remove_del_dir->Reset(); } bool ClientDAO::hasFileChange(_i64 dir_id, std::wstring fn) { q_has_changed_file->Bind(dir_id); q_has_changed_file->Bind(fn); db_results res=q_has_changed_file->Read(); q_has_changed_file->Reset(); return !res.empty(); } std::vector ClientDAO::getChangedFiles(_i64 dir_id) { q_get_changed_files->Bind(dir_id); db_results res=q_get_changed_files->Read(); q_get_changed_files->Reset(); std::vector ret; ret.resize(res.size()); for(size_t i=0;i