diff options
author | Mnikolenko ProductEngine <mnikolenko@productengine.com> | 2013-07-09 15:13:38 +0300 |
---|---|---|
committer | Mnikolenko ProductEngine <mnikolenko@productengine.com> | 2013-07-09 15:13:38 +0300 |
commit | 13361137d0d2ccb750d6002826763579d3d1cc69 (patch) | |
tree | 8d890c7ca94e8ec00c2bf6aa54e7bf3e7b4cf75c /indra/newview | |
parent | aa9282be1fca61445c49a91c7ad512bd6b561bf6 (diff) |
CHUI-978 FIXED Load data from chat log file in separate thread to prevent viewer freeze
Diffstat (limited to 'indra/newview')
-rwxr-xr-x | indra/newview/llfloaterconversationpreview.cpp | 42 | ||||
-rwxr-xr-x | indra/newview/llfloaterconversationpreview.h | 3 | ||||
-rwxr-xr-x | indra/newview/lllogchat.cpp | 248 | ||||
-rwxr-xr-x | indra/newview/lllogchat.h | 21 | ||||
-rwxr-xr-x | indra/newview/skins/default/xui/en/strings.xml | 3 |
5 files changed, 245 insertions, 72 deletions
diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp index a3d715530d..1a3fa27593 100755 --- a/indra/newview/llfloaterconversationpreview.cpp +++ b/indra/newview/llfloaterconversationpreview.cpp @@ -50,6 +50,7 @@ LLFloaterConversationPreview::LLFloaterConversationPreview(const LLSD& session_i 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; @@ -70,7 +71,7 @@ BOOL LLFloaterConversationPreview::postBuild() name = LLTrans::getString("NearbyChatTitle"); file = "chat"; } - + mChatHistoryFileName = file; LLStringUtil::format_map_t args; args["[NAME]"] = name; std::string title = getString("Title", args); @@ -80,23 +81,46 @@ BOOL LLFloaterConversationPreview::postBuild() load_params["load_all_history"] = true; load_params["cut_off_todays_date"] = false; - LLLogChat::loadChatHistory(file, mMessages, load_params); - mCurrentPage = mMessages.size() / mPageSize; + 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->setMaxValue(mCurrentPage + 1); - mPageSpinner->set(mCurrentPage + 1); - - std::string total_page_num = llformat("/ %d", mCurrentPage + 1); - getChild<LLTextBox>("page_num_label")->setValue(total_page_num); - + mPageSpinner->set(1); + mPageSpinner->setEnabled(false); + mChatHistoryLoaded = false; + LLLogChat::startChatHistoryThread(file, load_params); return LLFloater::postBuild(); } +void LLFloaterConversationPreview::SetPages(std::list<LLSD>& messages, const std::string& file_name) +{ + if(file_name == mChatHistoryFileName) + { + mMessages = messages; + + + mCurrentPage = mMessages.size() / mPageSize; + mPageSpinner->setEnabled(true); + mPageSpinner->setMaxValue(mCurrentPage+1); + mPageSpinner->set(mCurrentPage+1); + + std::string total_page_num = llformat("/ %d", mCurrentPage+1); + getChild<LLTextBox>("page_num_label")->setValue(total_page_num); + mChatHistoryLoaded = true; + + } + +} void LLFloaterConversationPreview::draw() { + if(mChatHistoryLoaded) + { + showHistory(); + mChatHistoryLoaded = false; + } LLFloater::draw(); } diff --git a/indra/newview/llfloaterconversationpreview.h b/indra/newview/llfloaterconversationpreview.h index b17ae84b63..389f3dfd09 100755 --- a/indra/newview/llfloaterconversationpreview.h +++ b/indra/newview/llfloaterconversationpreview.h @@ -42,6 +42,7 @@ public: virtual ~LLFloaterConversationPreview(){}; virtual BOOL postBuild(); + void SetPages(std::list<LLSD>& messages,const std::string& file_name); virtual void draw(); virtual void onOpen(const LLSD& key); @@ -59,6 +60,8 @@ private: std::list<LLSD> mMessages; std::string mAccountName; std::string mCompleteName; + std::string mChatHistoryFileName; + bool mChatHistoryLoaded; }; #endif /* LLFLOATERCONVERSATIONPREVIEW_H_ */ diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 379bbc5f8d..afaec48e7b 100755 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -25,7 +25,7 @@ */ #include "llviewerprecompiledheaders.h" - +#include "llfloaterconversationpreview.h" #include "llagent.h" #include "llagentui.h" #include "llavatarnamecache.h" @@ -206,6 +206,7 @@ private: }; LLLogChat::save_history_signal_t * LLLogChat::sSaveHistorySignal = NULL; +LLLoadHistoryThread::load_end_signal_t * LLLoadHistoryThread::mLoadEndSignal = NULL; //static std::string LLLogChat::makeLogFileName(std::string filename) @@ -336,75 +337,83 @@ 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()) - { - llwarns << "Session name is Empty!" << llendl; - 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(makeLogFileName(file_name), "r");/*Flawfinder: ignore*/ - if (!fptr) - { - fptr = LLFile::fopen(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; - } - } + 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. + } + } - 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; - } + 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); - std::string line(buffer); - //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); } +void LLLogChat::startChatHistoryThread(const std::string& file_name, const LLSD& load_params) +{ + + LLLoadHistoryThread* mThread = new LLLoadHistoryThread(); + mThread->start(); + mThread->setHistoryParams(file_name, load_params); +} // static std::string LLLogChat::oldLogFileName(std::string filename) { @@ -828,3 +837,116 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params im[LL_IM_TEXT] = name_and_text[IDX_TEXT]; return true; //parsed name and message text, maybe have a timestamp too } + + + + LLLoadHistoryThread::LLLoadHistoryThread() : LLThread("load chat history") + { + mNewLoad = false; + } + + void LLLoadHistoryThread::run() + { + while (!LLApp::isQuitting()) + { + if(mNewLoad) + { + loadHistory(mFileName,mMessages,mLoadParams); + shutdown(); + } + } + } + void LLLoadHistoryThread::setHistoryParams(const std::string& file_name, const LLSD& load_params) + { + mFileName = file_name; + mLoadParams = load_params; + mNewLoad = true; + } + 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 ; + } + + 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) + { + mNewLoad = false; + (*mLoadEndSignal)(messages, file_name); + 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); + 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'; + + if (firstline) + { + firstline = FALSE; + continue; + } + + std::string line(buffer); + + //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); + } + + //static + 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); + } diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h index bd70dbaac9..acee99afa2 100755 --- a/indra/newview/lllogchat.h +++ b/indra/newview/lllogchat.h @@ -28,6 +28,24 @@ #define LL_LLLOGCHAT_H class LLChat; +class LLLoadHistoryThread : public LLThread +{ +private: + 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); + 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); +}; class LLLogChat { @@ -39,6 +57,7 @@ public: LOG_LLSD, LOG_END }; + static std::string timestamp(bool withdate = false); static std::string makeLogFileName(std::string(filename)); /** @@ -54,6 +73,7 @@ public: 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); @@ -127,6 +147,7 @@ protected: virtual ~LLChatLogParser() {}; }; + // LLSD map lookup constants extern const std::string LL_IM_TIME; //("time"); extern const std::string LL_IM_TEXT; //("message"); diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index dcd2bf5ba7..f1e551695f 100755 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -3928,5 +3928,8 @@ Try enclosing path to the editor with double quotes. <string name="logging_calls_enabled_log_empty"> There are no logged conversations. After you contact someone, or someone contacts you, a log entry will be shown here. </string> + <string name="loading_chat_logs"> + Loading... + </string> </strings> |