<commit_before>/*************************************************************************
*    UrBackup - Client/Server backup system
*    Copyright (C) 2011-2016 <NAME>
*
*    This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
*    You should have received a copy of the GNU Affero General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/

#include "server_dir_links.h"
#include "../urbackupcommon/os_functions.h"
#include "../Interface/Server.h"
#include "../stringtools.h"
#include "server_settings.h"
#include "../Interface/Mutex.h"
#include "../Interface/Database.h"
#include "../Interface/File.h"
#include "database.h"

namespace
{
	void reference_all_sublinks(ServerLinkDao& link_dao, int clientid, const std::string& target, const std::string& new_target)
	{
		std::string escaped_target = escape_glob_sql(target);

		std::vector<ServerLinkDao::DirectoryLinkEntry> entries = link_dao.getLinksInDirectory(clientid, escaped_target+os_file_sep()+"*");

		for(size_t i=0;i<entries.size();++i)
		{
			std::string subpath = entries[i].target.substr(target.size());
			std::string new_link_path = new_target + subpath;
			link_dao.addDirectoryLink(clientid, entries[i].name, new_link_path);
		}
	}

	IMutex* dir_link_mutex;
}

std::string escape_glob_sql(const std::string& glob)
{
	std::string ret;
	ret.reserve(glob.size());
	for(size_t i=0;i<glob.size();++i)
	{
		if(glob[i]=='?')
		{
			ret+="[?]";
		}
		else if(glob[i]=='[')
		{
			ret+="[[]";
		}
		else if(glob[i]=='*')
		{
			ret+="[*]";
		}
		else
		{
			ret+=glob[i];
		}
	}
	return ret;
}


bool link_directory_pool( int clientid, const std::string& target_dir, const std::string& src_dir, const std::string& pooldir, bool with_transaction,
	ServerLinkDao*& link_dao, ServerLinkJournalDao*& link_journal_dao)
{
	if (link_dao == NULL)
	{
		link_dao=new ServerLinkDao(Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER_LINKS));
	}

	DBScopedSynchronous synchonous_link_journal(NULL);

	if (!with_transaction && link_journal_dao == NULL)
	{
		IDatabase* link_journal_db = Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER_LINK_JOURNAL);
		link_journal_dao = new ServerLinkJournalDao(link_journal_db);
		synchonous_link_journal.reset(link_journal_db);
	}

	DBScopedSynchronous synchonous_link(link_dao->getDatabase());
	DBScopedWriteTransaction link_transaction(link_dao->getDatabase());

	IScopedLock lock(dir_link_mutex);

	std::string link_src_dir;<commit_msg>Fix dead lock with directory linking<commit_after>/*************************************************************************
*    UrBackup - Client/Server backup system
*    Copyright (C) 2011-2016 <NAME>
*
*    This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
*    You should have received a copy of the GNU Affero General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/

#include "server_dir_links.h"
#include "../urbackupcommon/os_functions.h"
#include "../Interface/Server.h"
#include "../stringtools.h"
#include "server_settings.h"
#include "../Interface/Mutex.h"
#include "../Interface/Database.h"
#include "../Interface/File.h"
#include "database.h"

namespace
{
	void reference_all_sublinks(ServerLinkDao& link_dao, int clientid, const std::string& target, const std::string& new_target)
	{
		std::string escaped_target = escape_glob_sql(target);

		std::vector<ServerLinkDao::DirectoryLinkEntry> entries = link_dao.getLinksInDirectory(clientid, escaped_target+os_file_sep()+"*");

		for(size_t i=0;i<entries.size();++i)
		{
			std::string subpath = entries[i].target.substr(target.size());
			std::string new_link_path = new_target + subpath;
			link_dao.addDirectoryLink(clientid, entries[i].name, new_link_path);
		}
	}

	IMutex* dir_link_mutex;
}

std::string escape_glob_sql(const std::string& glob)
{
	std::string ret;
	ret.reserve(glob.size());
	for(size_t i=0;i<glob.size();++i)
	{
		if(glob[i]=='?')
		{
			ret+="[?]";
		}
		else if(glob[i]=='[')
		{
			ret+="[[]";
		}
		else if(glob[i]=='*')
		{
			ret+="[*]";
		}
		else
		{
			ret+=glob[i];
		}
	}
	return ret;
}


bool link_directory_pool( int clientid, const std::string& target_dir, const std::string& src_dir, const std::string& pooldir, bool with_transaction,
	ServerLinkDao*& link_dao, ServerLinkJournalDao*& link_journal_dao)
{
	if (link_dao == NULL)
	{
		link_dao=new ServerLinkDao(Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER_LINKS));
	}

	DBScopedSynchronous synchonous_link_journal(NULL);

	if (!with_transaction && link_journal_dao == NULL)
	{
		IDatabase* link_journal_db = Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER_LINK_JOURNAL);
		link_journal_dao = new ServerLinkJournalDao(link_journal_db);
		synchonous_link_journal.reset(link_journal_db);
	}

	DBScopedSynchronous synchonous_link(link_dao->getDatabase());

	IScopedLock lock(dir_link_mutex);

	DBScopedWriteTransaction link_transaction(link_dao->getDatabase());

	std::string link_src_dir;
{'fraction_non_alphanumeric': 0.17355643044619423, 'fraction_numerical': 0.0036089238845144356, 'mean_word_length': 5.292053663570692, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '912360', 'n_tokens_mistral': 2086, 'n_tokens_neox': 2000, 'n_words': 464}