From a2e22732f195dc075a733c79f15156752f522a43 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Tue, 30 Jul 2013 19:13:45 -0700 Subject: Summer cleaning - removed a lot of llcommon dependencies to speed up build times consolidated most indra-specific constants in llcommon under indra_constants.h fixed issues with operations on mixed unit types (implicit and explicit) made LL_INFOS() style macros variadic in order to subsume other logging methods such as ll_infos added optional tag output to error recorders --- indra/newview/lllogchat.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/newview/lllogchat.cpp') diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 2d7454b636..60272749ff 100755 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -292,7 +292,7 @@ void LLLogChat::saveHistory(const std::string& filename, if (tmp_filename.empty()) { std::string warn = "Chat history filename [" + filename + "] is empty!"; - llwarning(warn, 666); + LL_WARNS() << warn << LL_ENDL; llassert(tmp_filename.size()); return; } @@ -662,7 +662,7 @@ void LLChatLogFormatter::format(const LLSD& im, std::ostream& ostr) const { if (!im.isMap()) { - llwarning("invalid LLSD type of an instant message", 0); + LL_WARNS() << "invalid LLSD type of an instant message" << LL_ENDL; return; } -- cgit v1.2.3 From e340009fc59d59e59b2e8d903a884acb76b178eb Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Fri, 9 Aug 2013 17:11:19 -0700 Subject: second phase summer cleaning replace llinfos, lldebugs, etc with new LL_INFOS(), LL_DEBUGS(), etc. --- indra/newview/lllogchat.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/newview/lllogchat.cpp') diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 60272749ff..e8424d840a 100755 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -300,7 +300,7 @@ void LLLogChat::saveHistory(const std::string& filename, llofstream file (LLLogChat::makeLogFileName(filename), std::ios_base::app); if (!file.is_open()) { - llwarns << "Couldn't open chat history log! - " + filename << llendl; + LL_WARNS() << "Couldn't open chat history log! - " + filename << LL_ENDL; return; } @@ -337,7 +337,7 @@ void LLLogChat::loadChatHistory(const std::string& file_name, std::list& m { if (file_name.empty()) { - llwarns << "Session name is Empty!" << llendl; + LL_WARNS() << "Session name is Empty!" << LL_ENDL; return ; } -- cgit v1.2.3 From 443c502ccc3abe50b7747fb2ba4d3b6bd74c1dc6 Mon Sep 17 00:00:00 2001 From: PavelK ProductEngine Date: Tue, 3 Dec 2013 19:32:56 +0200 Subject: MAINT-3476 FIX Opening large chat histories from conversation log eats up huge amounts of memory, leading to viewer crash. --- indra/newview/lllogchat.cpp | 481 ++++++++++++++++++++++++++++++-------------- 1 file changed, 327 insertions(+), 154 deletions(-) (limited to 'indra/newview/lllogchat.cpp') diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 90b169ecd3..09eb40d830 100755 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -206,7 +206,11 @@ private: }; LLLogChat::save_history_signal_t * LLLogChat::sSaveHistorySignal = NULL; -LLLoadHistoryThread::load_end_signal_t * LLLoadHistoryThread::mLoadEndSignal = NULL; + +std::map LLLogChat::sLoadHistoryThreads; +std::map 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& 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::iterator it = sLoadHistoryThreads.find(session_id); + if (it != sLoadHistoryThreads.end()) + { + finished = it->second->isFinished(); + } + if (!finished) + { + return false; + } + std::map::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::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::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::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::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 uuids; + std::map::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::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* 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& 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* 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* 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; +} -- cgit v1.2.3 From 5e55cfd49e591ca6c07b37d8eee80eb71011e57b Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Tue, 10 Dec 2013 16:43:23 -0800 Subject: SH-4653 FIX Interesting: Viewer crashes while reading chat history fixed code that was causing abnormal thread termination in the first place --- indra/newview/lllogchat.cpp | 186 ++++++++++++++++++++++---------------------- 1 file changed, 93 insertions(+), 93 deletions(-) (limited to 'indra/newview/lllogchat.cpp') diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index a3cdf29ef2..92974b9cef 100755 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -845,115 +845,115 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params return true; //parsed name and message text, maybe have a timestamp too } +LLLoadHistoryThread::LLLoadHistoryThread() : LLThread("load chat history") +{ + mNewLoad = false; +} - - 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) +void LLLoadHistoryThread::run() +{ + while (!LLApp::isQuitting()) { - mFileName = file_name; - mLoadParams = load_params; - mNewLoad = true; + if(mNewLoad) + { + loadHistory(mFileName,mMessages,mLoadParams); + break; + } } - void LLLoadHistoryThread::loadHistory(const std::string& file_name, std::list& 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. - } - } +void LLLoadHistoryThread::setHistoryParams(const std::string& file_name, const LLSD& load_params) +{ + mFileName = file_name; + mLoadParams = load_params; + mNewLoad = true; +} - char buffer[LOG_RECALL_SIZE]; /*Flawfinder: ignore*/ - char *bptr; - S32 len; - bool firstline = TRUE; +void LLLoadHistoryThread::loadHistory(const std::string& file_name, std::list& messages, const LLSD& load_params) +{ + if (file_name.empty()) + { + LL_WARNS("LLLogChat::loadHistory") << "Session name is Empty!" << LL_ENDL; + return ; + } - 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'; + bool load_all_history = load_params.has("load_all_history") ? load_params["load_all_history"].asBoolean() : false; - if (firstline) - { - firstline = FALSE; - continue; - } + 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. + } + } - std::string line(buffer); + char buffer[LOG_RECALL_SIZE]; /*Flawfinder: ignore*/ + char *bptr; + S32 len; + bool firstline = TRUE; - //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); - } - } + 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; } - return mLoadEndSignal->connect(cb); + 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); +} -- cgit v1.2.3 From 99de75c225b5c74478e7a1b5a761924ef2e51f66 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine Date: Fri, 13 Dec 2013 16:48:28 +0200 Subject: MAINT-3522 FIXED Continue loop after adding Nearby chat history to the list. --- indra/newview/lllogchat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/lllogchat.cpp') diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 09eb40d830..d0ecf80706 100755 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -575,7 +575,7 @@ void LLLogChat::findTranscriptFiles(std::string pattern, std::vectoradd(dirname, filename)); LLFile::close(filep); - return; + continue; } char buffer[LOG_RECALL_SIZE]; -- cgit v1.2.3