Beispiel #1
0
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();
}