void getArchiveSettings(JSON::Object &obj, IDatabase *db, int clientid) { IQuery *q_get=db->Prepare("SELECT value FROM settings_db.settings WHERE clientid="+nconvert(clientid)+" AND key=?"); q_get->Bind("overwrite"); db_results res=q_get->Read(); q_get->Reset(); if(res.empty() || res[0][L"value"]!=L"true") clientid=0; q_get->Bind("overwrite_archive_settings"); res=q_get->Read(); if(res.empty() || res[0][L"value"]!=L"true") clientid=0; IQuery *q=db->Prepare("SELECT next_archival, interval, interval_unit, length, length_unit, backup_types FROM settings_db.automatic_archival WHERE clientid=?"); q->Bind(clientid); res=q->Read(); JSON::Array arr; for(size_t i=0;i<res.size();++i) { _i64 archive_next=watoi64(res[i][L"next_archival"]); JSON::Object ca; ca.set("next_archival", res[i][L"next_archival"]); ca.set("archive_every", watoi(res[i][L"interval"])); ca.set("archive_every_unit", res[i][L"interval_unit"]); ca.set("archive_for", watoi(res[i][L"length"])); ca.set("archive_for_unit", res[i][L"length_unit"]); ca.set("archive_backup_type", ServerAutomaticArchive::getBackupType(watoi(res[i][L"backup_types"]))); ca.set("archive_window", res[i][L"archive_window"]); if(archive_next>0 && clientid!=0) { _i64 tl=archive_next-(_i64)Server->getTimeSeconds(); ca.set("archive_timeleft", tl); } else { ca.set("archive_timeleft", "-"); } arr.add(ca); } obj.set("archive_settings", arr); }
std::vector<SMDir> ClientDAO::getChangedDirs(bool del) { std::vector<SMDir> 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;i<res.size();++i) { ret.push_back(SMDir(watoi64(res[i][L"id"]), res[i][L"name"] ) ); } return ret; }
void ServerAutomaticArchive::archiveBackups(void) { db_results res_clients=db->Read("SELECT id FROM clients"); for(size_t i=0;i<res_clients.size();++i) { int clientid=watoi(res_clients[i][L"id"]); int r_clientid=clientid; IQuery *q_get=db->Prepare("SELECT value FROM settings_db.settings WHERE clientid=? AND key=?"); q_get->Bind(clientid); q_get->Bind("overwrite"); db_results res=q_get->Read(); q_get->Reset(); if(res.empty() || res[0][L"value"]!=L"true") r_clientid=0; q_get->Bind(clientid); q_get->Bind("overwrite_archive_settings"); res=q_get->Read(); q_get->Reset(); if(res.empty() || res[0][L"value"]!=L"true") r_clientid=0; bool archive_settings_copied=false; q_get->Bind(clientid); q_get->Bind("archive_settings_copied"); res=q_get->Read(); if(!res.empty() && res[0][L"value"]==L"true") archive_settings_copied=true; if(r_clientid==0 && !archive_settings_copied) { copyArchiveSettings(clientid); } IQuery *q_get_archived=db->Prepare("SELECT id, next_archival, interval, length, backup_types, archive_window FROM settings_db.automatic_archival WHERE clientid=?"); q_get_archived->Bind(clientid); db_results res_archived=q_get_archived->Read(); for(size_t j=0;j<res_archived.size();++j) { _i64 next_archival=watoi64(res_archived[j][L"next_archival"]); std::wstring &archive_window=res_archived[j][L"archive_window"]; _i64 curr_time=Server->getTimeSeconds(); if(next_archival<curr_time && (archive_window.empty() || isInArchiveWindow(archive_window)) ) { int backupid=getNonArchivedFileBackup(watoi(res_archived[j][L"backup_types"]), clientid); if(backupid!=0) { int length=watoi(res_archived[j][L"length"]); archiveFileBackup(backupid, length); Server->Log("Archived file backup with id="+nconvert(backupid)+" for "+nconvert(length)+" seconds", LL_INFO); updateInterval(watoi(res_archived[j][L"id"]), watoi(res_archived[j][L"interval"])); } else { Server->Log("Did not find file backup suitable for archiving with backup_type="+nconvert(watoi(res_archived[j][L"backup_types"])), LL_INFO); } } } } }
void LMDBFileIndex::create(get_data_callback_t get_data_callback, void *userdata) { begin_txn(0); IDatabase *db=Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER_FILES_NEW); ServerFilesDao filesdao(db); size_t n_done=0; size_t n_rows=0; SIndexKey last; int64 last_prev_entry; int64 last_id; db_results res; do { res=get_data_callback(n_done, n_rows, userdata); ++n_rows; for(size_t i=0;i<res.size();++i) { const std::string& shahash=res[i]["shahash"]; int64 id = watoi64(res[i]["id"]); SIndexKey key(reinterpret_cast<const char*>(shahash.c_str()), watoi64(res[i]["filesize"]), watoi(res[i]["clientid"])); int64 next_entry = watoi64(res[i]["next_entry"]); int64 prev_entry = watoi64(res[i]["prev_entry"]); int pointed_to = watoi(res[i]["pointed_to"]); assert(memcmp(&last, &key, sizeof(SIndexKey))!=1); if(key==last) { if(last_prev_entry==0) { filesdao.setPrevEntry(id, last_id); } if(next_entry==0 && (last_prev_entry==0 || last_prev_entry==id) ) { filesdao.setNextEntry(last_id, id); } if(pointed_to) { filesdao.setPointedTo(0, id); } last=key; last_id=id; last_prev_entry=prev_entry; continue; } else { if(!pointed_to) { filesdao.setPointedTo(1, id); } } put(key, id, MDB_APPEND); if(_has_error) { Server->Log("LMDB error after putting element. Error state interrupting..", LL_ERROR); return; } if(n_done % 1000 == 0 && n_done>0) { if ((Server->getFailBits() & IServer::FAIL_DATABASE_CORRUPTED) || (Server->getFailBits() & IServer::FAIL_DATABASE_IOERR) || (Server->getFailBits() & IServer::FAIL_DATABASE_FULL)) { Server->Log("Database error. Stopping.", LL_ERROR); return; } Server->Log("File entry index contains "+convert(n_done)+" entries now.", LL_INFO); } if(n_done % c_create_commit_n == 0 && n_done>0) { commit_transaction(); begin_txn(0); } ++n_done; last=key; last_id=id; last_prev_entry=prev_entry; } } while(!res.empty()); commit_transaction(); }
void ServerAutomaticArchive::copyArchiveSettings(int clientid) { db_results res_all=db->Read("SELECT id, next_archival, interval, interval_unit, length, length_unit, backup_types, archive_window FROM settings_db.automatic_archival WHERE clientid=0"); std::vector<std::wstring> next_archivals; for(size_t i=0;i<res_all.size();++i) { std::wstring &interval=res_all[i][L"interval"]; std::wstring &length=res_all[i][L"length"]; std::wstring &backup_types=res_all[i][L"backup_types"]; std::wstring &id=res_all[i][L"id"]; std::wstring &archive_window=res_all[i][L"archive_window"]; std::wstring next_archival=res_all[i][L"next_archival"]; IQuery *q_next=db->Prepare("SELECT next_archival FROM settings_db.automatic_archival WHERE clientid=? AND interval=? AND length=? AND backup_types=? AND archive_window=?"); IQuery *q_num=db->Prepare("SELECT count(*) AS num FROM settings_db.automatic_archival WHERE clientid=0 AND interval=? AND length=? AND backup_types=? AND archive_window=? AND id<?"); q_num->Bind(interval); q_num->Bind(length); q_num->Bind(backup_types); q_num->Bind(archive_window); q_num->Bind(id); db_results res_num=q_num->Read(); int num=watoi(res_num[0][L"num"]); q_next->Bind(clientid); q_next->Bind(interval); q_next->Bind(length); q_next->Bind(backup_types); q_next->Bind(archive_window); db_results res_next=q_next->Read(); if((size_t)num<res_next.size()) { next_archival=res_next[num][L"next_archival"]; _i64 na=watoi64(next_archival); if(na==0) { next_archival=convert(Server->getTimeSeconds()); } } next_archivals.push_back(next_archival); } IQuery *q_del_all=db->Prepare("DELETE FROM settings_db.automatic_archival WHERE clientid=?"); IQuery *q_insert_all=db->Prepare("INSERT INTO settings_db.automatic_archival (next_archival, interval, interval_unit, length, length_unit, backup_types, clientid, archive_window)" "VALUES (?,?,?,?,?,?,?,?)"); q_del_all->Bind(clientid); q_del_all->Write(); for(size_t i=0;i<res_all.size();++i) { std::wstring &interval=res_all[i][L"interval"]; std::wstring &length=res_all[i][L"length"]; std::wstring &backup_types=res_all[i][L"backup_types"]; std::wstring &archive_window=res_all[i][L"archive_window"]; q_insert_all->Bind(next_archivals[i]); q_insert_all->Bind(interval); q_insert_all->Bind(res_all[i][L"interval_unit"]); q_insert_all->Bind(length); q_insert_all->Bind(res_all[i][L"length_unit"]); q_insert_all->Bind(backup_types); q_insert_all->Bind(clientid); q_insert_all->Bind(archive_window); q_insert_all->Write(); q_insert_all->Reset(); } IQuery *q_insert_copied=db->Prepare("INSERT INTO settings_db.settings (key, value, clientid) VALUES ('archive_settings_copied','true',?)"); q_insert_copied->Bind(clientid); q_insert_copied->Write(); }