diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp
index 5041f4689da28690e532e3f27aab47aeca931d76..a358b7c10b62a17fcfd25fe5e39c90233e1fdaef 100755
--- a/indra/newview/llfloaterconversationpreview.cpp
+++ b/indra/newview/llfloaterconversationpreview.cpp
@@ -32,6 +32,7 @@
 #include "llfloaterimnearbychat.h"
 #include "llspinctrl.h"
 #include "lltrans.h"
+#include "llnotificationsutil.h"
 
 const std::string LL_FCP_COMPLETE_NAME("complete_name");
 const std::string LL_FCP_ACCOUNT_NAME("user_name");
@@ -45,14 +46,20 @@ LLFloaterConversationPreview::LLFloaterConversationPreview(const LLSD& session_i
 	mAccountName(session_id[LL_FCP_ACCOUNT_NAME]),
 	mCompleteName(session_id[LL_FCP_COMPLETE_NAME]),
 	mMutex(NULL),
-	mShowHistory(false)
+	mShowHistory(false),
+	mMessages(NULL),
+	mHistoryThreadsBusy(false),
+	mOpened(false)
+{
+}
+
+LLFloaterConversationPreview::~LLFloaterConversationPreview()
 {
 }
 
 BOOL LLFloaterConversationPreview::postBuild()
 {
 	mChatHistory = getChild<LLChatHistory>("chat_history");
-	LLLoadHistoryThread::setLoadEndSignal(boost::bind(&LLFloaterConversationPreview::setPages, this, _1, _2));
 
 	const LLConversation* conv = LLConversationLog::instance().getConversation(mSessionID);
 	std::string name;
@@ -79,31 +86,21 @@ BOOL LLFloaterConversationPreview::postBuild()
 	std::string title = getString("Title", args);
 	setTitle(title);
 
-	LLSD load_params;
-	load_params["load_all_history"] = true;
-	load_params["cut_off_todays_date"] = false;
-
-
-	LLSD loading;
-	loading[LL_IM_TEXT] = LLTrans::getString("loading_chat_logs");
-	mMessages.push_back(loading);
-	mPageSpinner = getChild<LLSpinCtrl>("history_page_spin");
-	mPageSpinner->setCommitCallback(boost::bind(&LLFloaterConversationPreview::onMoreHistoryBtnClick, this));
-	mPageSpinner->setMinValue(1);
-	mPageSpinner->set(1);
-	mPageSpinner->setEnabled(false);
-	LLLogChat::startChatHistoryThread(file, load_params);
 	return LLFloater::postBuild();
 }
 
-void LLFloaterConversationPreview::setPages(std::list<LLSD>& messages, const std::string& file_name)
+void LLFloaterConversationPreview::setPages(std::list<LLSD>* messages, const std::string& file_name)
 {
-	if(file_name == mChatHistoryFileName)
+	if(file_name == mChatHistoryFileName && messages)
 	{
 		// additional protection to avoid changes of mMessages in setPages()
 		LLMutexLock lock(&mMutex);
+		if (mMessages)
+		{
+			delete mMessages; // Clean up temporary message list with "Loading..." text
+		}
 		mMessages = messages;
-		mCurrentPage = (mMessages.size() ? (mMessages.size() - 1) / mPageSize : 0);
+		mCurrentPage = (mMessages->size() ? (mMessages->size() - 1) / mPageSize : 0);
 
 		mPageSpinner->setEnabled(true);
 		mPageSpinner->setMaxValue(mCurrentPage+1);
@@ -113,6 +110,11 @@ void LLFloaterConversationPreview::setPages(std::list<LLSD>& messages, const std
 		getChild<LLTextBox>("page_num_label")->setValue(total_page_num);
 		mShowHistory = true;
 	}
+	LLLoadHistoryThread* loadThread = LLLogChat::getLoadHistoryThread(mSessionID);
+	if (loadThread)
+	{
+		loadThread->removeLoadEndSignal(boost::bind(&LLFloaterConversationPreview::setPages, this, _1, _2));
+	}
 }
 
 void LLFloaterConversationPreview::draw()
@@ -127,24 +129,82 @@ void LLFloaterConversationPreview::draw()
 
 void LLFloaterConversationPreview::onOpen(const LLSD& key)
 {
+	if (mOpened)
+	{
+		return;
+	}
+	mOpened = true;
+	if (!LLLogChat::historyThreadsFinished(mSessionID))
+	{
+		LLNotificationsUtil::add("ChatHistoryIsBusyAlert");
+		mHistoryThreadsBusy = true;
+		closeFloater();
+		return;
+	}
+	LLSD load_params;
+	load_params["load_all_history"] = true;
+	load_params["cut_off_todays_date"] = false;
+
+	// The temporary message list with "Loading..." text
+	// Will be deleted upon loading completion in setPages() method
+	mMessages = new std::list<LLSD>();
+
+
+	LLSD loading;
+	loading[LL_IM_TEXT] = LLTrans::getString("loading_chat_logs");
+	mMessages->push_back(loading);
+	mPageSpinner = getChild<LLSpinCtrl>("history_page_spin");
+	mPageSpinner->setCommitCallback(boost::bind(&LLFloaterConversationPreview::onMoreHistoryBtnClick, this));
+	mPageSpinner->setMinValue(1);
+	mPageSpinner->set(1);
+	mPageSpinner->setEnabled(false);
+
+	// The actual message list to load from file
+	// Will be deleted in a separate thread LLDeleteHistoryThread not to freeze UI
+	// LLDeleteHistoryThread is started in destructor
+	std::list<LLSD>* messages = new std::list<LLSD>();
+
+	LLLogChat::cleanupHistoryThreads();
+	
+	LLLoadHistoryThread* loadThread = new LLLoadHistoryThread(mChatHistoryFileName, messages, load_params);
+	loadThread->setLoadEndSignal(boost::bind(&LLFloaterConversationPreview::setPages, this, _1, _2));
+	loadThread->start();
+	LLLogChat::addLoadHistoryThread(mSessionID, loadThread);
+
+	LLDeleteHistoryThread* deleteThread = new LLDeleteHistoryThread(messages, loadThread);
+	LLLogChat::addDeleteHistoryThread(mSessionID, deleteThread);
+
 	mShowHistory = true;
 }
 
+void LLFloaterConversationPreview::onClose(bool app_quitting)
+{
+	mOpened = false;
+	if (!mHistoryThreadsBusy)
+	{
+		LLDeleteHistoryThread* deleteThread = LLLogChat::getDeleteHistoryThread(mSessionID);
+		if (deleteThread)
+		{
+			deleteThread->start();
+		}
+	}
+}
+
 void LLFloaterConversationPreview::showHistory()
 {
 	// additional protection to avoid changes of mMessages in setPages
 	LLMutexLock lock(&mMutex);
-	if(!mMessages.size() || mCurrentPage * mPageSize >= mMessages.size())
+	if(mMessages == NULL || !mMessages->size() || mCurrentPage * mPageSize >= mMessages->size())
 	{
 		return;
 	}
 
 	mChatHistory->clear();
 	std::ostringstream message;
-	std::list<LLSD>::const_iterator iter = mMessages.begin();
+	std::list<LLSD>::const_iterator iter = mMessages->begin();
 	std::advance(iter, mCurrentPage * mPageSize);
-	
-	for (int msg_num = 0; iter != mMessages.end() && msg_num < mPageSize; ++iter, ++msg_num)
+
+	for (int msg_num = 0; iter != mMessages->end() && msg_num < mPageSize; ++iter, ++msg_num)
 	{
 		LLSD msg = *iter;
 
diff --git a/indra/newview/llfloaterconversationpreview.h b/indra/newview/llfloaterconversationpreview.h
index b0488f4ff127d51bdd58417b3cf0629bdc01e318..a8dbbc9ffe0c112721f984dfcd1dd821afbe82e4 100755
--- a/indra/newview/llfloaterconversationpreview.h
+++ b/indra/newview/llfloaterconversationpreview.h
@@ -39,13 +39,14 @@ class LLFloaterConversationPreview : public LLFloater
 public:
 
 	LLFloaterConversationPreview(const LLSD& session_id);
-	virtual ~LLFloaterConversationPreview(){};
+	virtual ~LLFloaterConversationPreview();
 
 	virtual BOOL postBuild();
-	void setPages(std::list<LLSD>& messages,const std::string& file_name);
+	void setPages(std::list<LLSD>* messages,const std::string& file_name);
 
 	virtual void draw();
 	virtual void onOpen(const LLSD& key);
+	virtual void onClose(bool app_quitting);
 
 private:
 	void onMoreHistoryBtnClick();
@@ -58,11 +59,13 @@ class LLFloaterConversationPreview : public LLFloater
 	int				mCurrentPage;
 	int				mPageSize;
 
-	std::list<LLSD> mMessages;
+	std::list<LLSD>*	mMessages;
 	std::string		mAccountName;
 	std::string		mCompleteName;
-	std::string     mChatHistoryFileName;
+	std::string		mChatHistoryFileName;
 	bool			mShowHistory;
+	bool			mHistoryThreadsBusy;
+	bool			mOpened;
 };
 
 #endif /* LLFLOATERCONVERSATIONPREVIEW_H_ */
diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp
index 90b169ecd3ab3332049fc532c2ac03f853e2792f..09eb40d83012e1cf4b3e419c4d8d0ba6f5207962 100755
--- a/indra/newview/lllogchat.cpp
+++ b/indra/newview/lllogchat.cpp
@@ -206,7 +206,11 @@ class LLLogChatTimeScanner: public LLSingleton<LLLogChatTimeScanner>
 };
 
 LLLogChat::save_history_signal_t * LLLogChat::sSaveHistorySignal = NULL;
-LLLoadHistoryThread::load_end_signal_t * LLLoadHistoryThread::mLoadEndSignal = NULL;
+
+std::map<LLUUID,LLLoadHistoryThread *> LLLogChat::sLoadHistoryThreads;
+std::map<LLUUID,LLDeleteHistoryThread *> LLLogChat::sDeleteHistoryThreads;
+LLMutex* LLLogChat::sHistoryThreadsMutex = NULL;
+
 
 //static
 std::string LLLogChat::makeLogFileName(std::string filename)
@@ -337,83 +341,179 @@ void LLLogChat::saveHistory(const std::string& filename,
 void LLLogChat::loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params)
 {
 	if (file_name.empty())
-				{
-					LL_WARNS("LLLogChat::loadChatHistory") << "Session name is Empty!" << LL_ENDL;
-					return ;
-				}
+	{
+		LL_WARNS("LLLogChat::loadChatHistory") << "Session name is Empty!" << LL_ENDL;
+		return ;
+	}
 
-				bool load_all_history = load_params.has("load_all_history") ? load_params["load_all_history"].asBoolean() : false;
+	bool load_all_history = load_params.has("load_all_history") ? load_params["load_all_history"].asBoolean() : false;
 
-				LLFILE* fptr = LLFile::fopen(LLLogChat::makeLogFileName(file_name), "r");/*Flawfinder: ignore*/
-				if (!fptr)
-				{
-					fptr = LLFile::fopen(LLLogChat::oldLogFileName(file_name), "r");/*Flawfinder: ignore*/
-					if (!fptr)
-					{
-						return;						//No previous conversation with this name.
-					}
-				}
+	LLFILE* fptr = LLFile::fopen(LLLogChat::makeLogFileName(file_name), "r");/*Flawfinder: ignore*/
+	if (!fptr)
+	{
+		fptr = LLFile::fopen(LLLogChat::oldLogFileName(file_name), "r");/*Flawfinder: ignore*/
+		if (!fptr)
+		{
+			return;						//No previous conversation with this name.
+		}
+	}
 
-				char buffer[LOG_RECALL_SIZE];		/*Flawfinder: ignore*/
-				char *bptr;
-				S32 len;
-				bool firstline = TRUE;
-
-				if (load_all_history || fseek(fptr, (LOG_RECALL_SIZE - 1) * -1  , SEEK_END))
-				{	//We need to load the whole historyFile or it's smaller than recall size, so get it all.
-					firstline = FALSE;
-					if (fseek(fptr, 0, SEEK_SET))
-					{
-						fclose(fptr);
-						return;
-					}
-				}
-			while (fgets(buffer, LOG_RECALL_SIZE, fptr)  && !feof(fptr))
-				{
-					len = strlen(buffer) - 1;		/*Flawfinder: ignore*/
-					for (bptr = (buffer + len); (*bptr == '\n' || *bptr == '\r') && bptr>buffer; bptr--)	*bptr='\0';
-
-					if (firstline)
-					{
-						firstline = FALSE;
-						continue;
-					}
-
-					std::string line(buffer);
-
-					//updated 1.23 plain text log format requires a space added before subsequent lines in a multilined message
-					if (' ' == line[0])
-					{
-						line.erase(0, MULTI_LINE_PREFIX.length());
-						append_to_last_message(messages, '\n' + line);
-					}
-					else if (0 == len && ('\n' == line[0] || '\r' == line[0]))
-					{
-						//to support old format's multilined messages with new lines used to divide paragraphs
-						append_to_last_message(messages, line);
-					}
-					else
-					{
-						LLSD item;
-						if (!LLChatLogParser::parse(line, item, load_params))
-						{
-							item[LL_IM_TEXT] = line;
-						}
-						messages.push_back(item);
-					}
-				}
-				fclose(fptr);
+	char buffer[LOG_RECALL_SIZE];		/*Flawfinder: ignore*/
+	char *bptr;
+	S32 len;
+	bool firstline = TRUE;
+
+	if (load_all_history || fseek(fptr, (LOG_RECALL_SIZE - 1) * -1  , SEEK_END))
+	{	//We need to load the whole historyFile or it's smaller than recall size, so get it all.
+		firstline = FALSE;
+		if (fseek(fptr, 0, SEEK_SET))
+		{
+			fclose(fptr);
+			return;
+		}
+	}
+	while (fgets(buffer, LOG_RECALL_SIZE, fptr)  && !feof(fptr))
+	{
+		len = strlen(buffer) - 1;		/*Flawfinder: ignore*/
+		for (bptr = (buffer + len); (*bptr == '\n' || *bptr == '\r') && bptr>buffer; bptr--)	*bptr='\0';
+
+		if (firstline)
+		{
+			firstline = FALSE;
+			continue;
+		}
 
+		std::string line(buffer);
 
+		//updated 1.23 plain text log format requires a space added before subsequent lines in a multilined message
+		if (' ' == line[0])
+		{
+			line.erase(0, MULTI_LINE_PREFIX.length());
+			append_to_last_message(messages, '\n' + line);
+		}
+		else if (0 == len && ('\n' == line[0] || '\r' == line[0]))
+		{
+			//to support old format's multilined messages with new lines used to divide paragraphs
+			append_to_last_message(messages, line);
+		}
+		else
+		{
+			LLSD item;
+			if (!LLChatLogParser::parse(line, item, load_params))
+			{
+				item[LL_IM_TEXT] = line;
+			}
+			messages.push_back(item);
+		}
+	}
+	fclose(fptr);
 }
 
-void LLLogChat::startChatHistoryThread(const std::string& file_name, const LLSD& load_params)
+// static
+bool LLLogChat::historyThreadsFinished(LLUUID session_id)
 {
+	LLMutexLock lock(historyThreadsMutex());
+	bool finished = true;
+	std::map<LLUUID,LLLoadHistoryThread *>::iterator it = sLoadHistoryThreads.find(session_id);
+	if (it != sLoadHistoryThreads.end())
+	{
+		finished = it->second->isFinished();
+	}
+	if (!finished)
+	{
+		return false;
+	}
+	std::map<LLUUID,LLDeleteHistoryThread *>::iterator dit = sDeleteHistoryThreads.find(session_id);
+	if (dit != sDeleteHistoryThreads.end())
+	{
+		finished = finished && dit->second->isFinished();
+	}
+	return finished;
+}
 
-	LLLoadHistoryThread* mThread = new LLLoadHistoryThread();
-	mThread->start();
-	mThread->setHistoryParams(file_name, load_params);
+// static
+LLLoadHistoryThread* LLLogChat::getLoadHistoryThread(LLUUID session_id)
+{
+	LLMutexLock lock(historyThreadsMutex());
+	std::map<LLUUID,LLLoadHistoryThread *>::iterator it = sLoadHistoryThreads.find(session_id);
+	if (it != sLoadHistoryThreads.end())
+	{
+		return it->second;
+	}
+	return NULL;
+}
+
+// static
+LLDeleteHistoryThread* LLLogChat::getDeleteHistoryThread(LLUUID session_id)
+{
+	LLMutexLock lock(historyThreadsMutex());
+	std::map<LLUUID,LLDeleteHistoryThread *>::iterator it = sDeleteHistoryThreads.find(session_id);
+	if (it != sDeleteHistoryThreads.end())
+	{
+		return it->second;
+	}
+	return NULL;
+}
+
+// static
+bool LLLogChat::addLoadHistoryThread(LLUUID& session_id, LLLoadHistoryThread* lthread)
+{
+	LLMutexLock lock(historyThreadsMutex());
+	std::map<LLUUID,LLLoadHistoryThread *>::const_iterator it = sLoadHistoryThreads.find(session_id);
+	if (it != sLoadHistoryThreads.end())
+	{
+		return false;
+	}
+	sLoadHistoryThreads[session_id] = lthread;
+	return true;
 }
+
+// static
+bool LLLogChat::addDeleteHistoryThread(LLUUID& session_id, LLDeleteHistoryThread* dthread)
+{
+	LLMutexLock lock(historyThreadsMutex());
+	std::map<LLUUID,LLDeleteHistoryThread *>::const_iterator it = sDeleteHistoryThreads.find(session_id);
+	if (it != sDeleteHistoryThreads.end())
+	{
+		return false;
+	}
+	sDeleteHistoryThreads[session_id] = dthread;
+	return true;
+}
+
+// static
+void LLLogChat::cleanupHistoryThreads()
+{
+	LLMutexLock lock(historyThreadsMutex());
+	std::vector<LLUUID> uuids;
+	std::map<LLUUID,LLLoadHistoryThread *>::iterator lit = sLoadHistoryThreads.begin();
+	for (; lit != sLoadHistoryThreads.end(); lit++)
+	{
+		if (lit->second->isFinished() && sDeleteHistoryThreads[lit->first]->isFinished())
+		{
+			delete lit->second;
+			delete sDeleteHistoryThreads[lit->first];
+			uuids.push_back(lit->first);
+		}
+	}
+	std::vector<LLUUID>::iterator uuid_it = uuids.begin();
+	for ( ;uuid_it != uuids.end(); uuid_it++)
+	{
+		sLoadHistoryThreads.erase(*uuid_it);
+		sDeleteHistoryThreads.erase(*uuid_it);
+	}
+}
+
+//static
+LLMutex* LLLogChat::historyThreadsMutex()
+{
+	if (sHistoryThreadsMutex == NULL)
+	{
+		sHistoryThreadsMutex = new LLMutex(NULL);
+	}
+	return sHistoryThreadsMutex;
+}
+
 // static
 std::string LLLogChat::oldLogFileName(std::string filename)
 {
@@ -845,115 +945,188 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params
 	return true;  //parsed name and message text, maybe have a timestamp too
 }
 
+LLDeleteHistoryThread::LLDeleteHistoryThread(std::list<LLSD>* messages, LLLoadHistoryThread* loadThread)
+	: LLActionThread("delete chat history"),
+	mMessages(messages),
+	mLoadThread(loadThread)
+{
+}
 
+LLDeleteHistoryThread::~LLDeleteHistoryThread()
+{
+}
 
-	LLLoadHistoryThread::LLLoadHistoryThread() : LLThread("load chat history")
- 	{
-		mNewLoad = false;
+void LLDeleteHistoryThread::run()
+{
+	if (mLoadThread != NULL)
+	{
+		mLoadThread->waitFinished();
 	}
-
-	void LLLoadHistoryThread::run()
+	if (NULL != mMessages)
 	{
-		while (!LLApp::isQuitting())
-			{
-			    if(mNewLoad)
-				{
-					loadHistory(mFileName,mMessages,mLoadParams);
-					shutdown();
-				}
-			}
+		delete mMessages;
 	}
-	void LLLoadHistoryThread::setHistoryParams(const std::string& file_name, const LLSD& load_params)
+	mMessages = NULL;
+	setFinished();
+}
+
+LLActionThread::LLActionThread(const std::string& name)
+	: LLThread(name),
+	mMutex(NULL),
+	mRunCondition(NULL),
+	mFinished(false)
+{
+}
+
+LLActionThread::~LLActionThread()
+{
+}
+
+void LLActionThread::waitFinished()
+{
+	mMutex.lock();
+	if (!mFinished)
 	{
-		mFileName = file_name;
-		mLoadParams = load_params;
-		mNewLoad = true;
+		mMutex.unlock();
+		mRunCondition.wait();
 	}
-	void LLLoadHistoryThread::loadHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params)
+	else
 	{
+		mMutex.unlock();	
+	}
+}
 
-		if (file_name.empty())
-			{
-			LL_WARNS("LLLogChat::loadHistory") << "Session name is Empty!" << LL_ENDL;
-				return ;
-			}
+void LLActionThread::setFinished()
+{
+	mMutex.lock();
+	mFinished = true;
+	mMutex.unlock();
+	mRunCondition.signal();
+}
 
-			bool load_all_history = load_params.has("load_all_history") ? load_params["load_all_history"].asBoolean() : false;
+LLLoadHistoryThread::LLLoadHistoryThread(const std::string& file_name, std::list<LLSD>* messages, const LLSD& load_params)
+	: LLActionThread("load chat history"),
+	mMessages(messages),
+	mFileName(file_name),
+	mLoadParams(load_params),
+	mNewLoad(true),
+	mLoadEndSignal(NULL)
+{
+}
 
-			LLFILE* fptr = LLFile::fopen(LLLogChat::makeLogFileName(file_name), "r");/*Flawfinder: ignore*/
-			if (!fptr)
-			{
-				fptr = LLFile::fopen(LLLogChat::oldLogFileName(file_name), "r");/*Flawfinder: ignore*/
-				if (!fptr)
-				{
-					mNewLoad = false;
-					(*mLoadEndSignal)(messages, file_name);
-					return;						//No previous conversation with this name.
-				}
-			}
+LLLoadHistoryThread::~LLLoadHistoryThread()
+{
+}
 
-			char buffer[LOG_RECALL_SIZE];		/*Flawfinder: ignore*/
-			char *bptr;
-			S32 len;
-			bool firstline = TRUE;
+void LLLoadHistoryThread::run()
+{
+	if(mNewLoad)
+	{
+		loadHistory(mFileName, mMessages, mLoadParams);
+		int count = mMessages->size();
+		llinfos << "mMessages->size(): " << count << llendl;
+		setFinished();
+	}
+}
 
-			if (load_all_history || fseek(fptr, (LOG_RECALL_SIZE - 1) * -1  , SEEK_END))
-			{	//We need to load the whole historyFile or it's smaller than recall size, so get it all.
-				firstline = FALSE;
-				if (fseek(fptr, 0, SEEK_SET))
-				{
-					fclose(fptr);
-					mNewLoad = false;
-					(*mLoadEndSignal)(messages, file_name);
-					return;
-				}
-			}
-		while (fgets(buffer, LOG_RECALL_SIZE, fptr)  && !feof(fptr))
-			{
-				len = strlen(buffer) - 1;		/*Flawfinder: ignore*/
-				for (bptr = (buffer + len); (*bptr == '\n' || *bptr == '\r') && bptr>buffer; bptr--)	*bptr='\0';
+void LLLoadHistoryThread::loadHistory(const std::string& file_name, std::list<LLSD>* messages, const LLSD& load_params)
+{
+	if (file_name.empty())
+	{
+		LL_WARNS("LLLogChat::loadHistory") << "Session name is Empty!" << LL_ENDL;
+		return ;
+	}
 
-				if (firstline)
-				{
-					firstline = FALSE;
-					continue;
-				}
+	bool load_all_history = load_params.has("load_all_history") ? load_params["load_all_history"].asBoolean() : false;
+	LLFILE* fptr = LLFile::fopen(LLLogChat::makeLogFileName(file_name), "r");/*Flawfinder: ignore*/
 
-				std::string line(buffer);
+	if (!fptr)
+	{
+		fptr = LLFile::fopen(LLLogChat::oldLogFileName(file_name), "r");/*Flawfinder: ignore*/
+		if (!fptr)
+		{
+			mNewLoad = false;
+			(*mLoadEndSignal)(messages, file_name);
+			return;						//No previous conversation with this name.
+		}
+	}
 
-				//updated 1.23 plaint text log format requires a space added before subsequent lines in a multilined message
-				if (' ' == line[0])
-				{
-					line.erase(0, MULTI_LINE_PREFIX.length());
-					append_to_last_message(messages, '\n' + line);
-				}
-				else if (0 == len && ('\n' == line[0] || '\r' == line[0]))
-				{
-					//to support old format's multilined messages with new lines used to divide paragraphs
-					append_to_last_message(messages, line);
-				}
-				else
-				{
-					LLSD item;
-					if (!LLChatLogParser::parse(line, item, load_params))
-					{
-						item[LL_IM_TEXT] = line;
-					}
-					messages.push_back(item);
-				}
-			}
+	char buffer[LOG_RECALL_SIZE];		/*Flawfinder: ignore*/
+
+	char *bptr;
+	S32 len;
+	bool firstline = TRUE;
+
+	if (load_all_history || fseek(fptr, (LOG_RECALL_SIZE - 1) * -1  , SEEK_END))
+	{	//We need to load the whole historyFile or it's smaller than recall size, so get it all.
+		firstline = FALSE;
+		if (fseek(fptr, 0, SEEK_SET))
+		{
 			fclose(fptr);
 			mNewLoad = false;
 			(*mLoadEndSignal)(messages, file_name);
+			return;
+		}
 	}
 
-	//static
-	boost::signals2::connection LLLoadHistoryThread::setLoadEndSignal(const load_end_signal_t::slot_type& cb)
+
+	while (fgets(buffer, LOG_RECALL_SIZE, fptr)  && !feof(fptr))
 	{
-		if (NULL == mLoadEndSignal)
+		len = strlen(buffer) - 1;		/*Flawfinder: ignore*/
+
+		for (bptr = (buffer + len); (*bptr == '\n' || *bptr == '\r') && bptr>buffer; bptr--)	*bptr='\0';
+
+
+		if (firstline)
 		{
-			mLoadEndSignal = new load_end_signal_t();
+			firstline = FALSE;
+			continue;
 		}
+		std::string line(buffer);
 
-		return mLoadEndSignal->connect(cb);
+		//updated 1.23 plaint text log format requires a space added before subsequent lines in a multilined message
+		if (' ' == line[0])
+		{
+			line.erase(0, MULTI_LINE_PREFIX.length());
+			append_to_last_message(*messages, '\n' + line);
+		}
+		else if (0 == len && ('\n' == line[0] || '\r' == line[0]))
+		{
+			//to support old format's multilined messages with new lines used to divide paragraphs
+			append_to_last_message(*messages, line);
+		}
+		else
+		{
+			LLSD item;
+			if (!LLChatLogParser::parse(line, item, load_params))
+			{
+				item[LL_IM_TEXT] = line;
+			}
+			messages->push_back(item);
+		}
 	}
+
+	fclose(fptr);
+	mNewLoad = false;
+	(*mLoadEndSignal)(messages, file_name);
+}
+	
+boost::signals2::connection LLLoadHistoryThread::setLoadEndSignal(const load_end_signal_t::slot_type& cb)
+{
+	if (NULL == mLoadEndSignal)
+	{
+		mLoadEndSignal = new load_end_signal_t();
+	}
+
+	return mLoadEndSignal->connect(cb);
+}
+
+void LLLoadHistoryThread::removeLoadEndSignal(const load_end_signal_t::slot_type& cb)
+{
+	if (NULL != mLoadEndSignal)
+	{
+		mLoadEndSignal->disconnect_all_slots();
+		delete mLoadEndSignal;
+	}
+	mLoadEndSignal = NULL;
+}
diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h
index acee99afa2c1ee723ee958d963826555d1da62a7..81f75ef6265575b407c27229f2a25f428a172129 100755
--- a/indra/newview/lllogchat.h
+++ b/indra/newview/lllogchat.h
@@ -28,23 +28,54 @@
 #define LL_LLLOGCHAT_H
 
 class LLChat;
-class LLLoadHistoryThread : public LLThread
+
+class LLActionThread : public LLThread
 {
+public:
+	LLActionThread(const std::string& name);
+	~LLActionThread();
+
+	void waitFinished();
+	bool isFinished() { return mFinished; }
+protected:
+	void setFinished();
 private:
-	std::string mFileName;
-	std::list<LLSD> mMessages;
+	bool mFinished;
+	LLMutex	mMutex;
+	LLCondition mRunCondition;
+};
+
+class LLLoadHistoryThread : public LLActionThread
+{
+private:
+	const std::string& mFileName;
+	std::list<LLSD>* mMessages;
 	LLSD mLoadParams;
 	bool mNewLoad;
 public:
-	LLLoadHistoryThread();
-
-	void setHistoryParams(const std::string& file_name, const LLSD& load_params);
-	virtual void loadHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params);
+	LLLoadHistoryThread(const std::string& file_name, std::list<LLSD>* messages, const LLSD& load_params);
+	~LLLoadHistoryThread();
+	//void setHistoryParams(const std::string& file_name, const LLSD& load_params);
+	virtual void loadHistory(const std::string& file_name, std::list<LLSD>* messages, const LLSD& load_params);
     virtual void run();
 
-   typedef boost::signals2::signal<void (std::list<LLSD>& messages,const std::string& file_name)> load_end_signal_t;
-   static load_end_signal_t * mLoadEndSignal;
-   static boost::signals2::connection setLoadEndSignal(const load_end_signal_t::slot_type& cb);
+	typedef boost::signals2::signal<void (std::list<LLSD>* messages,const std::string& file_name)> load_end_signal_t;
+	load_end_signal_t * mLoadEndSignal;
+	boost::signals2::connection setLoadEndSignal(const load_end_signal_t::slot_type& cb);
+	void removeLoadEndSignal(const load_end_signal_t::slot_type& cb);
+};
+
+class LLDeleteHistoryThread : public LLActionThread
+{
+private:
+	std::list<LLSD>* mMessages;
+	LLLoadHistoryThread* mLoadThread;
+public:
+	LLDeleteHistoryThread(std::list<LLSD>* messages, LLLoadHistoryThread* loadThread);
+	~LLDeleteHistoryThread();
+
+	virtual void run();
+	static void deleteHistory();
 };
 
 class LLLogChat
@@ -73,7 +104,6 @@ class LLLogChat
 	static void getListOfTranscriptBackupFiles(std::vector<std::string>& list_of_transcriptions);
 
 	static void loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params = LLSD());
-	static void startChatHistoryThread(const std::string& file_name, const LLSD& load_params);
 
 	typedef boost::signals2::signal<void ()> save_history_signal_t;
 	static boost::signals2::connection setSaveHistorySignal(const save_history_signal_t::slot_type& cb);
@@ -90,9 +120,21 @@ class LLLogChat
 	static bool isTranscriptExist(const LLUUID& avatar_id, bool is_group=false);
 	static bool isNearbyTranscriptExist();
 
+	static bool historyThreadsFinished(LLUUID session_id);
+	static LLLoadHistoryThread* getLoadHistoryThread(LLUUID session_id);
+	static LLDeleteHistoryThread* getDeleteHistoryThread(LLUUID session_id);
+	static bool addLoadHistoryThread(LLUUID& session_id, LLLoadHistoryThread* lthread);
+	static bool addDeleteHistoryThread(LLUUID& session_id, LLDeleteHistoryThread* dthread);
+	static void cleanupHistoryThreads();
+
 private:
 	static std::string cleanFileName(std::string filename);
 	static save_history_signal_t * sSaveHistorySignal;
+
+	static std::map<LLUUID,LLLoadHistoryThread *> sLoadHistoryThreads;
+	static std::map<LLUUID,LLDeleteHistoryThread *> sDeleteHistoryThreads;
+	static LLMutex* sHistoryThreadsMutex;
+	static LLMutex* historyThreadsMutex();
 };
 
 /**
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 2cb8f788d42c8eb66c563f16cc8d6663d48b3f40..4dcc1950cad3439e81fde1ab73093c5fa142c04d 100755
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -10224,4 +10224,14 @@ Cannot create large prims that intersect other players.  Please re-try when othe
      yestext="OK"/>
   </notification>
   
+  <notification
+   icon="alert.tga"
+   name="ChatHistoryIsBusyAlert"
+   type="alertmodal">
+   Chat history file is busy with previous operation. Please try again in a few minutes or choose chat with another person.
+    <usetemplate
+     name="okbutton"
+     yestext="OK"/>
+  </notification>
+  
 </notifications>