diff options
author | Jacek Antonelli | 2008-08-15 23:45:50 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:45:50 -0500 |
commit | 2a4dea528f670b9bb1f77ef27a8a1dd16603d114 (patch) | |
tree | 95c68e362703c9099d571ecbdc6142b1cda1e005 /linden/indra/llcommon | |
parent | Second Life viewer sources 1.20.6 (diff) | |
download | meta-impy-2a4dea528f670b9bb1f77ef27a8a1dd16603d114.zip meta-impy-2a4dea528f670b9bb1f77ef27a8a1dd16603d114.tar.gz meta-impy-2a4dea528f670b9bb1f77ef27a8a1dd16603d114.tar.bz2 meta-impy-2a4dea528f670b9bb1f77ef27a8a1dd16603d114.tar.xz |
Second Life viewer sources 1.20.7
Diffstat (limited to 'linden/indra/llcommon')
30 files changed, 1590 insertions, 174 deletions
diff --git a/linden/indra/llcommon/files.lst b/linden/indra/llcommon/files.lst index 6f03155..fd6a07c 100644 --- a/linden/indra/llcommon/files.lst +++ b/linden/indra/llcommon/files.lst | |||
@@ -12,12 +12,16 @@ llcommon/llerrorthread.cpp | |||
12 | llcommon/llevent.cpp | 12 | llcommon/llevent.cpp |
13 | llcommon/llfasttimer.cpp | 13 | llcommon/llfasttimer.cpp |
14 | llcommon/llfile.cpp | 14 | llcommon/llfile.cpp |
15 | llcommon/llfindlocale.cpp | ||
15 | llcommon/llfixedbuffer.cpp | 16 | llcommon/llfixedbuffer.cpp |
16 | llcommon/llformat.cpp | 17 | llcommon/llformat.cpp |
17 | llcommon/llframetimer.cpp | 18 | llcommon/llframetimer.cpp |
19 | llcommon/llheartbeat.cpp | ||
20 | llcommon/llindraconfigfile.cpp | ||
18 | llcommon/lllog.cpp | 21 | llcommon/lllog.cpp |
19 | llcommon/llliveappconfig.cpp | 22 | llcommon/llliveappconfig.cpp |
20 | llcommon/lllivefile.cpp | 23 | llcommon/lllivefile.cpp |
24 | llcommon/lllog.cpp | ||
21 | llcommon/llmemory.cpp | 25 | llcommon/llmemory.cpp |
22 | llcommon/llmemorystream.cpp | 26 | llcommon/llmemorystream.cpp |
23 | llcommon/llmetrics.cpp | 27 | llcommon/llmetrics.cpp |
diff --git a/linden/indra/llcommon/llapp.cpp b/linden/indra/llcommon/llapp.cpp index bd2e377..ebace4e 100644 --- a/linden/indra/llcommon/llapp.cpp +++ b/linden/indra/llcommon/llapp.cpp | |||
@@ -49,11 +49,24 @@ | |||
49 | LONG WINAPI default_windows_exception_handler(struct _EXCEPTION_POINTERS *exception_infop); | 49 | LONG WINAPI default_windows_exception_handler(struct _EXCEPTION_POINTERS *exception_infop); |
50 | BOOL ConsoleCtrlHandler(DWORD fdwCtrlType); | 50 | BOOL ConsoleCtrlHandler(DWORD fdwCtrlType); |
51 | #else | 51 | #else |
52 | #include <unistd.h> // for fork() | 52 | # include <signal.h> |
53 | # include <unistd.h> // for fork() | ||
53 | void setup_signals(); | 54 | void setup_signals(); |
54 | void default_unix_signal_handler(int signum, siginfo_t *info, void *); | 55 | void default_unix_signal_handler(int signum, siginfo_t *info, void *); |
55 | const S32 LL_SMACKDOWN_SIGNAL = SIGUSR1; | 56 | # if LL_DARWIN |
56 | #endif | 57 | /* OSX doesn't support SIGRT* */ |
58 | S32 LL_SMACKDOWN_SIGNAL = SIGUSR1; | ||
59 | S32 LL_HEARTBEAT_SIGNAL = SIGUSR2; | ||
60 | # else | ||
61 | /* We want reliable delivery of our signals - SIGRT* is it. */ | ||
62 | /* Old LinuxThreads versions eat SIGRTMIN+0 to SIGRTMIN+2, avoid those. */ | ||
63 | /* Note that SIGRTMIN/SIGRTMAX may expand to a glibc function call with a | ||
64 | nonconstant result so these are not consts and cannot be used in constant- | ||
65 | expressions. SIGRTMAX may return -1 on rare broken setups. */ | ||
66 | S32 LL_SMACKDOWN_SIGNAL = (SIGRTMAX >= 0) ? (SIGRTMAX-1) : SIGUSR1; | ||
67 | S32 LL_HEARTBEAT_SIGNAL = (SIGRTMAX >= 0) ? (SIGRTMAX-0) : SIGUSR2; | ||
68 | # endif // LL_DARWIN | ||
69 | #endif // LL_WINDOWS | ||
57 | 70 | ||
58 | // the static application instance | 71 | // the static application instance |
59 | LLApp* LLApp::sApplication = NULL; | 72 | LLApp* LLApp::sApplication = NULL; |
@@ -523,6 +536,9 @@ void setup_signals() | |||
523 | sigaction(SIGSEGV, &act, NULL); | 536 | sigaction(SIGSEGV, &act, NULL); |
524 | sigaction(SIGSYS, &act, NULL); | 537 | sigaction(SIGSYS, &act, NULL); |
525 | 538 | ||
539 | sigaction(LL_HEARTBEAT_SIGNAL, &act, NULL); | ||
540 | sigaction(LL_SMACKDOWN_SIGNAL, &act, NULL); | ||
541 | |||
526 | // Asynchronous signals that are normally ignored | 542 | // Asynchronous signals that are normally ignored |
527 | sigaction(SIGCHLD, &act, NULL); | 543 | sigaction(SIGCHLD, &act, NULL); |
528 | sigaction(SIGUSR2, &act, NULL); | 544 | sigaction(SIGUSR2, &act, NULL); |
@@ -533,7 +549,6 @@ void setup_signals() | |||
533 | sigaction(SIGINT, &act, NULL); | 549 | sigaction(SIGINT, &act, NULL); |
534 | 550 | ||
535 | // Asynchronous signals that result in core | 551 | // Asynchronous signals that result in core |
536 | sigaction(LL_SMACKDOWN_SIGNAL, &act, NULL); | ||
537 | sigaction(SIGQUIT, &act, NULL); | 552 | sigaction(SIGQUIT, &act, NULL); |
538 | } | 553 | } |
539 | 554 | ||
@@ -555,6 +570,9 @@ void clear_signals() | |||
555 | sigaction(SIGSEGV, &act, NULL); | 570 | sigaction(SIGSEGV, &act, NULL); |
556 | sigaction(SIGSYS, &act, NULL); | 571 | sigaction(SIGSYS, &act, NULL); |
557 | 572 | ||
573 | sigaction(LL_HEARTBEAT_SIGNAL, &act, NULL); | ||
574 | sigaction(LL_SMACKDOWN_SIGNAL, &act, NULL); | ||
575 | |||
558 | // Asynchronous signals that are normally ignored | 576 | // Asynchronous signals that are normally ignored |
559 | sigaction(SIGCHLD, &act, NULL); | 577 | sigaction(SIGCHLD, &act, NULL); |
560 | 578 | ||
@@ -565,7 +583,6 @@ void clear_signals() | |||
565 | 583 | ||
566 | // Asynchronous signals that result in core | 584 | // Asynchronous signals that result in core |
567 | sigaction(SIGUSR2, &act, NULL); | 585 | sigaction(SIGUSR2, &act, NULL); |
568 | sigaction(LL_SMACKDOWN_SIGNAL, &act, NULL); | ||
569 | sigaction(SIGQUIT, &act, NULL); | 586 | sigaction(SIGQUIT, &act, NULL); |
570 | } | 587 | } |
571 | 588 | ||
@@ -586,16 +603,7 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *) | |||
586 | 603 | ||
587 | switch (signum) | 604 | switch (signum) |
588 | { | 605 | { |
589 | case SIGALRM: | 606 | case SIGCHLD: |
590 | case SIGPIPE: | ||
591 | case SIGUSR2: | ||
592 | // We don't care about these signals, ignore them | ||
593 | if (LLApp::sLogInSignal) | ||
594 | { | ||
595 | llinfos << "Signal handler - Ignoring this signal" << llendl; | ||
596 | } | ||
597 | return; | ||
598 | case SIGCHLD: | ||
599 | if (LLApp::sLogInSignal) | 607 | if (LLApp::sLogInSignal) |
600 | { | 608 | { |
601 | llinfos << "Signal handler - Got SIGCHLD from " << info->si_pid << llendl; | 609 | llinfos << "Signal handler - Got SIGCHLD from " << info->si_pid << llendl; |
@@ -624,59 +632,6 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *) | |||
624 | clear_signals(); | 632 | clear_signals(); |
625 | raise(signum); | 633 | raise(signum); |
626 | return; | 634 | return; |
627 | case LL_SMACKDOWN_SIGNAL: // Smackdown treated just like any other app termination, for now | ||
628 | if (LLApp::sLogInSignal) | ||
629 | { | ||
630 | llwarns << "Signal handler - Handling smackdown signal!" << llendl; | ||
631 | } | ||
632 | else | ||
633 | { | ||
634 | // Don't log anything, even errors - this is because this signal could happen anywhere. | ||
635 | LLError::setDefaultLevel(LLError::LEVEL_NONE); | ||
636 | } | ||
637 | |||
638 | // Change the signal that we reraise to SIGABRT, so we generate a core dump. | ||
639 | signum = SIGABRT; | ||
640 | case SIGBUS: | ||
641 | case SIGSEGV: | ||
642 | case SIGQUIT: | ||
643 | if (LLApp::sLogInSignal) | ||
644 | { | ||
645 | llwarns << "Signal handler - Handling fatal signal!" << llendl; | ||
646 | } | ||
647 | if (LLApp::isError()) | ||
648 | { | ||
649 | // Received second fatal signal while handling first, just die right now | ||
650 | // Set the signal handlers back to default before handling the signal - this makes the next signal wipe out the app. | ||
651 | clear_signals(); | ||
652 | |||
653 | if (LLApp::sLogInSignal) | ||
654 | { | ||
655 | llwarns << "Signal handler - Got another fatal signal while in the error handler, die now!" << llendl; | ||
656 | } | ||
657 | raise(signum); | ||
658 | return; | ||
659 | } | ||
660 | |||
661 | if (LLApp::sLogInSignal) | ||
662 | { | ||
663 | llwarns << "Signal handler - Flagging error status and waiting for shutdown" << llendl; | ||
664 | } | ||
665 | // Flag status to ERROR, so thread_error does its work. | ||
666 | LLApp::setError(); | ||
667 | // Block in the signal handler until somebody says that we're done. | ||
668 | while (LLApp::sErrorThreadRunning && !LLApp::isStopped()) | ||
669 | { | ||
670 | ms_sleep(10); | ||
671 | } | ||
672 | |||
673 | if (LLApp::sLogInSignal) | ||
674 | { | ||
675 | llwarns << "Signal handler - App is stopped, reraising signal" << llendl; | ||
676 | } | ||
677 | clear_signals(); | ||
678 | raise(signum); | ||
679 | return; | ||
680 | case SIGINT: | 635 | case SIGINT: |
681 | case SIGHUP: | 636 | case SIGHUP: |
682 | case SIGTERM: | 637 | case SIGTERM: |
@@ -697,10 +652,76 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *) | |||
697 | } | 652 | } |
698 | LLApp::setQuitting(); | 653 | LLApp::setQuitting(); |
699 | return; | 654 | return; |
655 | case SIGALRM: | ||
656 | case SIGPIPE: | ||
657 | case SIGUSR2: | ||
700 | default: | 658 | default: |
701 | if (LLApp::sLogInSignal) | 659 | if (signum == LL_SMACKDOWN_SIGNAL || |
702 | { | 660 | signum == SIGBUS || |
703 | llwarns << "Signal handler - Unhandled signal, ignoring!" << llendl; | 661 | signum == SIGILL || |
662 | signum == SIGFPE || | ||
663 | signum == SIGSEGV || | ||
664 | signum == SIGQUIT) | ||
665 | { | ||
666 | if (signum == LL_SMACKDOWN_SIGNAL) | ||
667 | { | ||
668 | // Smackdown treated just like any other app termination, for now | ||
669 | if (LLApp::sLogInSignal) | ||
670 | { | ||
671 | llwarns << "Signal handler - Handling smackdown signal!" << llendl; | ||
672 | } | ||
673 | else | ||
674 | { | ||
675 | // Don't log anything, even errors - this is because this signal could happen anywhere. | ||
676 | LLError::setDefaultLevel(LLError::LEVEL_NONE); | ||
677 | } | ||
678 | |||
679 | // Change the signal that we reraise to SIGABRT, so we generate a core dump. | ||
680 | signum = SIGABRT; | ||
681 | } | ||
682 | |||
683 | if (LLApp::sLogInSignal) | ||
684 | { | ||
685 | llwarns << "Signal handler - Handling fatal signal!" << llendl; | ||
686 | } | ||
687 | if (LLApp::isError()) | ||
688 | { | ||
689 | // Received second fatal signal while handling first, just die right now | ||
690 | // Set the signal handlers back to default before handling the signal - this makes the next signal wipe out the app. | ||
691 | clear_signals(); | ||
692 | |||
693 | if (LLApp::sLogInSignal) | ||
694 | { | ||
695 | llwarns << "Signal handler - Got another fatal signal while in the error handler, die now!" << llendl; | ||
696 | } | ||
697 | raise(signum); | ||
698 | return; | ||
699 | } | ||
700 | |||
701 | if (LLApp::sLogInSignal) | ||
702 | { | ||
703 | llwarns << "Signal handler - Flagging error status and waiting for shutdown" << llendl; | ||
704 | } | ||
705 | // Flag status to ERROR, so thread_error does its work. | ||
706 | LLApp::setError(); | ||
707 | // Block in the signal handler until somebody says that we're done. | ||
708 | while (LLApp::sErrorThreadRunning && !LLApp::isStopped()) | ||
709 | { | ||
710 | ms_sleep(10); | ||
711 | } | ||
712 | |||
713 | if (LLApp::sLogInSignal) | ||
714 | { | ||
715 | llwarns << "Signal handler - App is stopped, reraising signal" << llendl; | ||
716 | } | ||
717 | clear_signals(); | ||
718 | raise(signum); | ||
719 | return; | ||
720 | } else { | ||
721 | if (LLApp::sLogInSignal) | ||
722 | { | ||
723 | llinfos << "Signal handler - Unhandled signal " << signum << ", ignoring!" << llendl; | ||
724 | } | ||
704 | } | 725 | } |
705 | } | 726 | } |
706 | } | 727 | } |
diff --git a/linden/indra/llcommon/llapp.h b/linden/indra/llcommon/llapp.h index 50a70ae..9d8ff88 100644 --- a/linden/indra/llcommon/llapp.h +++ b/linden/indra/llcommon/llapp.h | |||
@@ -46,7 +46,8 @@ typedef void (*LLAppErrorHandler)(); | |||
46 | typedef void (*LLAppChildCallback)(int pid, bool exited, int status); | 46 | typedef void (*LLAppChildCallback)(int pid, bool exited, int status); |
47 | 47 | ||
48 | #if !LL_WINDOWS | 48 | #if !LL_WINDOWS |
49 | extern const S32 LL_SMACKDOWN_SIGNAL; | 49 | extern S32 LL_SMACKDOWN_SIGNAL; |
50 | extern S32 LL_HEARTBEAT_SIGNAL; | ||
50 | 51 | ||
51 | // Clear all of the signal handlers (which we want to do for the child process when we fork | 52 | // Clear all of the signal handlers (which we want to do for the child process when we fork |
52 | void clear_signals(); | 53 | void clear_signals(); |
diff --git a/linden/indra/llcommon/llapr.cpp b/linden/indra/llcommon/llapr.cpp index 08c40a4..78bf876 100644 --- a/linden/indra/llcommon/llapr.cpp +++ b/linden/indra/llcommon/llapr.cpp | |||
@@ -54,7 +54,7 @@ void ll_init_apr() | |||
54 | 54 | ||
55 | void ll_cleanup_apr() | 55 | void ll_cleanup_apr() |
56 | { | 56 | { |
57 | llinfos << "Cleaning up APR" << llendl; | 57 | LL_INFOS("APR") << "Cleaning up APR" << LL_ENDL; |
58 | 58 | ||
59 | if (gLogMutexp) | 59 | if (gLogMutexp) |
60 | { | 60 | { |
@@ -118,7 +118,7 @@ bool ll_apr_warn_status(apr_status_t status) | |||
118 | if(APR_SUCCESS == status) return false; | 118 | if(APR_SUCCESS == status) return false; |
119 | #ifndef LL_WINDOWS | 119 | #ifndef LL_WINDOWS |
120 | char buf[MAX_STRING]; /* Flawfinder: ignore */ | 120 | char buf[MAX_STRING]; /* Flawfinder: ignore */ |
121 | llwarns << "APR: " << apr_strerror(status, buf, MAX_STRING) << llendl; | 121 | LL_WARNS_ONCE("APR") << "APR: " << apr_strerror(status, buf, MAX_STRING) << LL_ENDL; |
122 | #endif | 122 | #endif |
123 | return true; | 123 | return true; |
124 | } | 124 | } |
@@ -294,7 +294,7 @@ bool ll_apr_file_remove(const LLString& filename, apr_pool_t* pool) | |||
294 | s = apr_file_remove(filename.c_str(), pool); | 294 | s = apr_file_remove(filename.c_str(), pool); |
295 | if (s != APR_SUCCESS) | 295 | if (s != APR_SUCCESS) |
296 | { | 296 | { |
297 | lldebugs << "ll_apr_file_remove failed on file: " << filename << llendl; | 297 | LL_DEBUGS("APR") << "ll_apr_file_remove failed on file: " << filename << LL_ENDL; |
298 | ll_apr_warn_status(s); | 298 | ll_apr_warn_status(s); |
299 | return false; | 299 | return false; |
300 | } | 300 | } |
@@ -308,7 +308,7 @@ bool ll_apr_file_rename(const LLString& filename, const LLString& newname, apr_p | |||
308 | s = apr_file_rename(filename.c_str(), newname.c_str(), pool); | 308 | s = apr_file_rename(filename.c_str(), newname.c_str(), pool); |
309 | if (s != APR_SUCCESS) | 309 | if (s != APR_SUCCESS) |
310 | { | 310 | { |
311 | lldebugs << "ll_apr_file_rename failed on file: " << filename << llendl; | 311 | LL_DEBUGS("APR") << "ll_apr_file_rename failed on file: " << filename << LL_ENDL; |
312 | ll_apr_warn_status(s); | 312 | ll_apr_warn_status(s); |
313 | return false; | 313 | return false; |
314 | } | 314 | } |
@@ -365,7 +365,7 @@ bool ll_apr_dir_make(const LLString& dirname, apr_pool_t* pool) | |||
365 | s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, pool); | 365 | s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, pool); |
366 | if (s != APR_SUCCESS) | 366 | if (s != APR_SUCCESS) |
367 | { | 367 | { |
368 | lldebugs << "ll_apr_dir_make failed on file: " << dirname << llendl; | 368 | LL_DEBUGS("APR") << "ll_apr_dir_make failed on file: " << dirname << LL_ENDL; |
369 | ll_apr_warn_status(s); | 369 | ll_apr_warn_status(s); |
370 | return false; | 370 | return false; |
371 | } | 371 | } |
@@ -379,7 +379,7 @@ bool ll_apr_dir_remove(const LLString& dirname, apr_pool_t* pool) | |||
379 | s = apr_file_remove(dirname.c_str(), pool); | 379 | s = apr_file_remove(dirname.c_str(), pool); |
380 | if (s != APR_SUCCESS) | 380 | if (s != APR_SUCCESS) |
381 | { | 381 | { |
382 | lldebugs << "ll_apr_dir_remove failed on file: " << dirname << llendl; | 382 | LL_DEBUGS("APR") << "ll_apr_dir_remove failed on file: " << dirname << LL_ENDL; |
383 | ll_apr_warn_status(s); | 383 | ll_apr_warn_status(s); |
384 | return false; | 384 | return false; |
385 | } | 385 | } |
diff --git a/linden/indra/llcommon/llares.cpp b/linden/indra/llcommon/llares.cpp index 4adf0c3..4d054e4 100644 --- a/linden/indra/llcommon/llares.cpp +++ b/linden/indra/llcommon/llares.cpp | |||
@@ -154,7 +154,7 @@ void LLAres::getSrvRecords(const std::string &name, SrvResponder *resp) | |||
154 | 154 | ||
155 | void LLAres::rewriteURI(const std::string &uri, UriRewriteResponder *resp) | 155 | void LLAres::rewriteURI(const std::string &uri, UriRewriteResponder *resp) |
156 | { | 156 | { |
157 | llinfos << "Rewriting " << uri << llendl; | 157 | LL_DEBUGS2("AppInit","Rewrite") << "Rewriting " << uri << LL_ENDL; |
158 | 158 | ||
159 | resp->mUri = LLURI(uri); | 159 | resp->mUri = LLURI(uri); |
160 | search("_" + resp->mUri.scheme() + "._tcp." + resp->mUri.hostName(), | 160 | search("_" + resp->mUri.scheme() + "._tcp." + resp->mUri.hostName(), |
@@ -163,7 +163,8 @@ void LLAres::rewriteURI(const std::string &uri, UriRewriteResponder *resp) | |||
163 | 163 | ||
164 | LLQueryResponder::LLQueryResponder() | 164 | LLQueryResponder::LLQueryResponder() |
165 | : LLAres::QueryResponder(), | 165 | : LLAres::QueryResponder(), |
166 | mResult(ARES_ENODATA) | 166 | mResult(ARES_ENODATA), |
167 | mType(RES_INVALID) | ||
167 | { | 168 | { |
168 | } | 169 | } |
169 | 170 | ||
diff --git a/linden/indra/llcommon/llcommon.vcproj b/linden/indra/llcommon/llcommon.vcproj index ab4e67a..f54ea13 100644 --- a/linden/indra/llcommon/llcommon.vcproj +++ b/linden/indra/llcommon/llcommon.vcproj | |||
@@ -199,6 +199,9 @@ | |||
199 | RelativePath=".\llfile.cpp"> | 199 | RelativePath=".\llfile.cpp"> |
200 | </File> | 200 | </File> |
201 | <File | 201 | <File |
202 | RelativePath=".\llfindlocale.cpp"> | ||
203 | </File> | ||
204 | <File | ||
202 | RelativePath=".\llfixedbuffer.cpp"> | 205 | RelativePath=".\llfixedbuffer.cpp"> |
203 | </File> | 206 | </File> |
204 | <File | 207 | <File |
@@ -208,6 +211,12 @@ | |||
208 | RelativePath=".\llframetimer.cpp"> | 211 | RelativePath=".\llframetimer.cpp"> |
209 | </File> | 212 | </File> |
210 | <File | 213 | <File |
214 | RelativePath=".\llheartbeat.cpp"> | ||
215 | </File> | ||
216 | <File | ||
217 | RelativePath=".\llindraconfigfile.cpp"> | ||
218 | </File> | ||
219 | <File | ||
211 | RelativePath=".\llliveappconfig.cpp"> | 220 | RelativePath=".\llliveappconfig.cpp"> |
212 | </File> | 221 | </File> |
213 | <File | 222 | <File |
@@ -417,12 +426,18 @@ | |||
417 | RelativePath=".\llhash.h"> | 426 | RelativePath=".\llhash.h"> |
418 | </File> | 427 | </File> |
419 | <File | 428 | <File |
429 | RelativePath=".\llheartbeat.h"> | ||
430 | </File> | ||
431 | <File | ||
420 | RelativePath=".\llindexedqueue.h"> | 432 | RelativePath=".\llindexedqueue.h"> |
421 | </File> | 433 | </File> |
422 | <File | 434 | <File |
423 | RelativePath=".\llkeythrottle.h"> | 435 | RelativePath=".\llkeythrottle.h"> |
424 | </File> | 436 | </File> |
425 | <File | 437 | <File |
438 | RelativePath=".\llkeyusetracker.h"> | ||
439 | </File> | ||
440 | <File | ||
426 | RelativePath=".\lllinkedqueue.h"> | 441 | RelativePath=".\lllinkedqueue.h"> |
427 | </File> | 442 | </File> |
428 | <File | 443 | <File |
diff --git a/linden/indra/llcommon/llcommon_vc8.vcproj b/linden/indra/llcommon/llcommon_vc8.vcproj index 5578075..a298499 100644 --- a/linden/indra/llcommon/llcommon_vc8.vcproj +++ b/linden/indra/llcommon/llcommon_vc8.vcproj | |||
@@ -289,6 +289,10 @@ | |||
289 | > | 289 | > |
290 | </File> | 290 | </File> |
291 | <File | 291 | <File |
292 | RelativePath=".\llfindlocale.cpp" | ||
293 | > | ||
294 | </File> | ||
295 | <File | ||
292 | RelativePath=".\llfixedbuffer.cpp" | 296 | RelativePath=".\llfixedbuffer.cpp" |
293 | > | 297 | > |
294 | </File> | 298 | </File> |
@@ -301,6 +305,14 @@ | |||
301 | > | 305 | > |
302 | </File> | 306 | </File> |
303 | <File | 307 | <File |
308 | RelativePath=".\llheartbeat.cpp" | ||
309 | > | ||
310 | </File> | ||
311 | <File | ||
312 | RelativePath=".\llindraconfigfile.cpp" | ||
313 | > | ||
314 | </File> | ||
315 | <File | ||
304 | RelativePath=".\llliveappconfig.cpp" | 316 | RelativePath=".\llliveappconfig.cpp" |
305 | > | 317 | > |
306 | </File> | 318 | </File> |
@@ -563,6 +575,10 @@ | |||
563 | > | 575 | > |
564 | </File> | 576 | </File> |
565 | <File | 577 | <File |
578 | RelativePath=".\llfindlocale.h" | ||
579 | > | ||
580 | </File> | ||
581 | <File | ||
566 | RelativePath=".\llfixedbuffer.h" | 582 | RelativePath=".\llfixedbuffer.h" |
567 | > | 583 | > |
568 | </File> | 584 | </File> |
@@ -587,6 +603,10 @@ | |||
587 | > | 603 | > |
588 | </File> | 604 | </File> |
589 | <File | 605 | <File |
606 | RelativePath=".\llindraconfigfile.h" | ||
607 | > | ||
608 | </File> | ||
609 | <File | ||
590 | RelativePath=".\lllinkedqueue.h" | 610 | RelativePath=".\lllinkedqueue.h" |
591 | > | 611 | > |
592 | </File> | 612 | </File> |
@@ -759,6 +779,22 @@ | |||
759 | > | 779 | > |
760 | </File> | 780 | </File> |
761 | <File | 781 | <File |
782 | RelativePath=".\metaclass.h" | ||
783 | > | ||
784 | </File> | ||
785 | <File | ||
786 | RelativePath=".\metaclasst.h" | ||
787 | > | ||
788 | </File> | ||
789 | <File | ||
790 | RelativePath=".\metaproperty.h" | ||
791 | > | ||
792 | </File> | ||
793 | <File | ||
794 | RelativePath=".\metapropertyt.h" | ||
795 | > | ||
796 | </File> | ||
797 | <File | ||
762 | RelativePath=".\new_mem_ops.h" | 798 | RelativePath=".\new_mem_ops.h" |
763 | > | 799 | > |
764 | </File> | 800 | </File> |
diff --git a/linden/indra/llcommon/llcommon_vc9.vcproj b/linden/indra/llcommon/llcommon_vc9.vcproj index 0bb2d11..1ae534d 100644 --- a/linden/indra/llcommon/llcommon_vc9.vcproj +++ b/linden/indra/llcommon/llcommon_vc9.vcproj | |||
@@ -290,6 +290,10 @@ | |||
290 | > | 290 | > |
291 | </File> | 291 | </File> |
292 | <File | 292 | <File |
293 | RelativePath=".\llfindlocale.cpp" | ||
294 | > | ||
295 | </File> | ||
296 | <File | ||
293 | RelativePath=".\llfixedbuffer.cpp" | 297 | RelativePath=".\llfixedbuffer.cpp" |
294 | > | 298 | > |
295 | </File> | 299 | </File> |
@@ -302,6 +306,14 @@ | |||
302 | > | 306 | > |
303 | </File> | 307 | </File> |
304 | <File | 308 | <File |
309 | RelativePath=".\llheartbeat.cpp" | ||
310 | > | ||
311 | </File> | ||
312 | <File | ||
313 | RelativePath=".\llindraconfigfile.cpp" | ||
314 | > | ||
315 | </File> | ||
316 | <File | ||
305 | RelativePath=".\llliveappconfig.cpp" | 317 | RelativePath=".\llliveappconfig.cpp" |
306 | > | 318 | > |
307 | </File> | 319 | </File> |
@@ -564,6 +576,10 @@ | |||
564 | > | 576 | > |
565 | </File> | 577 | </File> |
566 | <File | 578 | <File |
579 | RelativePath=".\llfindlocale.h" | ||
580 | > | ||
581 | </File> | ||
582 | <File | ||
567 | RelativePath=".\llfixedbuffer.h" | 583 | RelativePath=".\llfixedbuffer.h" |
568 | > | 584 | > |
569 | </File> | 585 | </File> |
@@ -588,6 +604,10 @@ | |||
588 | > | 604 | > |
589 | </File> | 605 | </File> |
590 | <File | 606 | <File |
607 | RelativePath=".\llindraconfigfile.h" | ||
608 | > | ||
609 | </File> | ||
610 | <File | ||
591 | RelativePath=".\lllinkedqueue.h" | 611 | RelativePath=".\lllinkedqueue.h" |
592 | > | 612 | > |
593 | </File> | 613 | </File> |
diff --git a/linden/indra/llcommon/llerror.cpp b/linden/indra/llcommon/llerror.cpp index 0e7db89..b74b288 100644 --- a/linden/indra/llcommon/llerror.cpp +++ b/linden/indra/llcommon/llerror.cpp | |||
@@ -408,6 +408,8 @@ namespace LLError | |||
408 | LevelMap functionLevelMap; | 408 | LevelMap functionLevelMap; |
409 | LevelMap classLevelMap; | 409 | LevelMap classLevelMap; |
410 | LevelMap fileLevelMap; | 410 | LevelMap fileLevelMap; |
411 | LevelMap tagLevelMap; | ||
412 | std::map<std::string, unsigned int> uniqueLogMessages; | ||
411 | 413 | ||
412 | LLError::FatalFunction crashFunction; | 414 | LLError::FatalFunction crashFunction; |
413 | LLError::TimeFunction timeFunction; | 415 | LLError::TimeFunction timeFunction; |
@@ -494,11 +496,17 @@ namespace LLError | |||
494 | namespace LLError | 496 | namespace LLError |
495 | { | 497 | { |
496 | CallSite::CallSite(ELevel level, | 498 | CallSite::CallSite(ELevel level, |
497 | const char* file, int line, | 499 | const char* file, |
498 | const std::type_info& class_info, const char* function) | 500 | int line, |
501 | const std::type_info& class_info, | ||
502 | const char* function, | ||
503 | const char* broadTag, | ||
504 | const char* narrowTag, | ||
505 | bool printOnce) | ||
499 | : mLevel(level), mFile(file), mLine(line), | 506 | : mLevel(level), mFile(file), mLine(line), |
500 | mClassInfo(class_info), mFunction(function), | 507 | mClassInfo(class_info), mFunction(function), |
501 | mCached(false), mShouldLog(false) | 508 | mCached(false), mShouldLog(false), |
509 | mBroadTag(broadTag), mNarrowTag(narrowTag), mPrintOnce(printOnce) | ||
502 | { } | 510 | { } |
503 | 511 | ||
504 | 512 | ||
@@ -552,6 +560,15 @@ namespace | |||
552 | #endif | 560 | #endif |
553 | 561 | ||
554 | LogControlFile& e = LogControlFile::fromDirectory(dir); | 562 | LogControlFile& e = LogControlFile::fromDirectory(dir); |
563 | |||
564 | // NOTE: We want to explicitly load the file before we add it to the event timer | ||
565 | // that checks for changes to the file. Else, we're not actually loading the file yet, | ||
566 | // and most of the initialization happens without any attention being paid to the | ||
567 | // log control file. Not to mention that when it finally gets checked later, | ||
568 | // all log statements that have been evaluated already become dirty and need to be | ||
569 | // evaluated for printing again. So, make sure to call checkAndReload() | ||
570 | // before addToEventTimer(). | ||
571 | e.checkAndReload(); | ||
555 | e.addToEventTimer(); | 572 | e.addToEventTimer(); |
556 | } | 573 | } |
557 | } | 574 | } |
@@ -625,6 +642,14 @@ namespace LLError | |||
625 | g.invalidateCallSites(); | 642 | g.invalidateCallSites(); |
626 | s.fileLevelMap[file_name] = level; | 643 | s.fileLevelMap[file_name] = level; |
627 | } | 644 | } |
645 | |||
646 | void setTagLevel(const std::string& tag_name, ELevel level) | ||
647 | { | ||
648 | Globals& g = Globals::get(); | ||
649 | Settings& s = Settings::get(); | ||
650 | g.invalidateCallSites(); | ||
651 | s.tagLevelMap[tag_name] = level; | ||
652 | } | ||
628 | } | 653 | } |
629 | 654 | ||
630 | namespace { | 655 | namespace { |
@@ -674,6 +699,8 @@ namespace LLError | |||
674 | s.functionLevelMap.clear(); | 699 | s.functionLevelMap.clear(); |
675 | s.classLevelMap.clear(); | 700 | s.classLevelMap.clear(); |
676 | s.fileLevelMap.clear(); | 701 | s.fileLevelMap.clear(); |
702 | s.tagLevelMap.clear(); | ||
703 | s.uniqueLogMessages.clear(); | ||
677 | 704 | ||
678 | setPrintLocation(config["print-location"]); | 705 | setPrintLocation(config["print-location"]); |
679 | setDefaultLevel(decodeLevel(config["default-level"])); | 706 | setDefaultLevel(decodeLevel(config["default-level"])); |
@@ -689,6 +716,7 @@ namespace LLError | |||
689 | setLevels(s.functionLevelMap, entry["functions"], level); | 716 | setLevels(s.functionLevelMap, entry["functions"], level); |
690 | setLevels(s.classLevelMap, entry["classes"], level); | 717 | setLevels(s.classLevelMap, entry["classes"], level); |
691 | setLevels(s.fileLevelMap, entry["files"], level); | 718 | setLevels(s.fileLevelMap, entry["files"], level); |
719 | setLevels(s.tagLevelMap, entry["tags"], level); | ||
692 | } | 720 | } |
693 | } | 721 | } |
694 | } | 722 | } |
@@ -850,7 +878,7 @@ namespace { | |||
850 | return false; | 878 | return false; |
851 | } | 879 | } |
852 | 880 | ||
853 | level = i->second; | 881 | level = i->second; |
854 | return true; | 882 | return true; |
855 | } | 883 | } |
856 | 884 | ||
@@ -929,9 +957,15 @@ namespace LLError | |||
929 | 957 | ||
930 | ELevel compareLevel = s.defaultLevel; | 958 | ELevel compareLevel = s.defaultLevel; |
931 | 959 | ||
932 | checkLevelMap(s.functionLevelMap, function_name, compareLevel) | 960 | // The most specific match found will be used as the log level, |
961 | // since the computation short circuits. | ||
962 | // So, in increasing order of importance: | ||
963 | // Default < Broad Tag < File < Class < Function < Narrow Tag | ||
964 | ((site.mNarrowTag != NULL) ? checkLevelMap(s.tagLevelMap, site.mNarrowTag, compareLevel) : false) | ||
965 | || checkLevelMap(s.functionLevelMap, function_name, compareLevel) | ||
933 | || checkLevelMap(s.classLevelMap, class_name, compareLevel) | 966 | || checkLevelMap(s.classLevelMap, class_name, compareLevel) |
934 | || checkLevelMap(s.fileLevelMap, abbreviateFile(site.mFile), compareLevel); | 967 | || checkLevelMap(s.fileLevelMap, abbreviateFile(site.mFile), compareLevel) |
968 | || ((site.mBroadTag != NULL) ? checkLevelMap(s.tagLevelMap, site.mBroadTag, compareLevel) : false); | ||
935 | 969 | ||
936 | site.mCached = true; | 970 | site.mCached = true; |
937 | g.addCallSite(site); | 971 | g.addCallSite(site); |
@@ -1018,6 +1052,29 @@ namespace LLError | |||
1018 | #endif | 1052 | #endif |
1019 | prefix << site.mFunction << ": "; | 1053 | prefix << site.mFunction << ": "; |
1020 | } | 1054 | } |
1055 | |||
1056 | if (site.mPrintOnce) | ||
1057 | { | ||
1058 | std::map<std::string, unsigned int>::iterator messageIter = s.uniqueLogMessages.find(message); | ||
1059 | if (messageIter != s.uniqueLogMessages.end()) | ||
1060 | { | ||
1061 | messageIter->second++; | ||
1062 | unsigned int num_messages = messageIter->second; | ||
1063 | if (num_messages == 10 || num_messages == 50 || (num_messages % 100) == 0) | ||
1064 | { | ||
1065 | prefix << "ONCE (" << num_messages << "th time seen): "; | ||
1066 | } | ||
1067 | else | ||
1068 | { | ||
1069 | return; | ||
1070 | } | ||
1071 | } | ||
1072 | else | ||
1073 | { | ||
1074 | prefix << "ONCE: "; | ||
1075 | s.uniqueLogMessages[message] = 1; | ||
1076 | } | ||
1077 | } | ||
1021 | 1078 | ||
1022 | prefix << message; | 1079 | prefix << message; |
1023 | message = prefix.str(); | 1080 | message = prefix.str(); |
diff --git a/linden/indra/llcommon/llerror.h b/linden/indra/llcommon/llerror.h index e1ace39..0a066bf 100644 --- a/linden/indra/llcommon/llerror.h +++ b/linden/indra/llcommon/llerror.h | |||
@@ -45,23 +45,23 @@ | |||
45 | 45 | ||
46 | Code can log messages with constuctions like this: | 46 | Code can log messages with constuctions like this: |
47 | 47 | ||
48 | llinfos << "request to fizzbip agent " << agent_id | 48 | LL_INFOS("StringTag") << "request to fizzbip agent " << agent_id |
49 | << " denied due to timeout" << llendl; | 49 | << " denied due to timeout" << LL_ENDL; |
50 | 50 | ||
51 | Messages can be logged to one of four increasing levels of concern, | 51 | Messages can be logged to one of four increasing levels of concern, |
52 | using one of four "streams": | 52 | using one of four "streams": |
53 | 53 | ||
54 | lldebugs - debug messages that are normally supressed | 54 | LL_DEBUGS("StringTag") - debug messages that are normally supressed |
55 | llinfos - informational messages that are normall shown | 55 | LL_INFOS("StringTag") - informational messages that are normall shown |
56 | llwarns - warning messages that singal a problem | 56 | LL_WARNS("StringTag") - warning messages that singal a problem |
57 | llerrs - error messages that are major, unrecoverable failures | 57 | LL_ERRS("StringTag") - error messages that are major, unrecoverable failures |
58 | 58 | ||
59 | The later (llerrs) automatically crashes the process after the message | 59 | The later (LL_ERRS("StringTag")) automatically crashes the process after the message |
60 | is logged. | 60 | is logged. |
61 | 61 | ||
62 | Note that these "streams" are actually #define magic. Rules for use: | 62 | Note that these "streams" are actually #define magic. Rules for use: |
63 | * they cannot be used as normal streams, only to start a message | 63 | * they cannot be used as normal streams, only to start a message |
64 | * messages written to them MUST be terminated with llendl | 64 | * messages written to them MUST be terminated with LL_ENDL |
65 | * between the opening and closing, the << operator is indeed | 65 | * between the opening and closing, the << operator is indeed |
66 | writing onto a std::ostream, so all conversions and stream | 66 | writing onto a std::ostream, so all conversions and stream |
67 | formating are available | 67 | formating are available |
@@ -85,7 +85,7 @@ | |||
85 | { | 85 | { |
86 | if (i > 100) | 86 | if (i > 100) |
87 | { | 87 | { |
88 | llwanrs << "called with a big value for i: " << i << llendl; | 88 | LL_WARNS("FooBarTag") << "called with a big value for i: " << i << LL_ENDL; |
89 | } | 89 | } |
90 | ... | 90 | ... |
91 | } | 91 | } |
@@ -100,7 +100,7 @@ | |||
100 | 100 | ||
101 | Lastly, logging is now very efficient in both compiled code and execution | 101 | Lastly, logging is now very efficient in both compiled code and execution |
102 | when skipped. There is no need to wrap messages, even debugging ones, in | 102 | when skipped. There is no need to wrap messages, even debugging ones, in |
103 | #ifdef _DEBUG constructs. lldebugs messages are compiled into all builds, | 103 | #ifdef _DEBUG constructs. LL_DEBUGS("StringTag") messages are compiled into all builds, |
104 | even release. Which means you can use them to help debug even when deployed | 104 | even release. Which means you can use them to help debug even when deployed |
105 | to a real grid. | 105 | to a real grid. |
106 | */ | 106 | */ |
@@ -144,7 +144,7 @@ namespace LLError | |||
144 | // intended for public use. | 144 | // intended for public use. |
145 | public: | 145 | public: |
146 | CallSite(ELevel, const char* file, int line, | 146 | CallSite(ELevel, const char* file, int line, |
147 | const std::type_info& class_info, const char* function); | 147 | const std::type_info& class_info, const char* function, const char* broadTag, const char* narrowTag, bool printOnce); |
148 | 148 | ||
149 | bool shouldLog() | 149 | bool shouldLog() |
150 | { return mCached ? mShouldLog : Log::shouldLog(*this); } | 150 | { return mCached ? mShouldLog : Log::shouldLog(*this); } |
@@ -156,9 +156,12 @@ namespace LLError | |||
156 | // these describe the call site and never change | 156 | // these describe the call site and never change |
157 | const ELevel mLevel; | 157 | const ELevel mLevel; |
158 | const char* const mFile; | 158 | const char* const mFile; |
159 | const int mLine; | 159 | const int mLine; |
160 | const std::type_info& mClassInfo; | 160 | const std::type_info& mClassInfo; |
161 | const char* const mFunction; | 161 | const char* const mFunction; |
162 | const char* const mBroadTag; | ||
163 | const char* const mNarrowTag; | ||
164 | const bool mPrintOnce; | ||
162 | 165 | ||
163 | // these implement a cache of the call to shouldLog() | 166 | // these implement a cache of the call to shouldLog() |
164 | bool mCached; | 167 | bool mCached; |
@@ -200,39 +203,66 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG; | |||
200 | See top of file for common usage. | 203 | See top of file for common usage. |
201 | */ | 204 | */ |
202 | 205 | ||
203 | #define lllog(level) \ | 206 | #define lllog(level, broadTag, narrowTag, once) \ |
204 | { \ | 207 | { \ |
205 | static LLError::CallSite _site( \ | 208 | static LLError::CallSite _site( \ |
206 | level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__);\ | 209 | level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__, broadTag, narrowTag, once);\ |
207 | if (_site.shouldLog()) \ | 210 | if (_site.shouldLog()) \ |
208 | { \ | 211 | { \ |
209 | std::ostringstream* _out = LLError::Log::out(); \ | 212 | std::ostringstream* _out = LLError::Log::out(); \ |
210 | (*_out) | 213 | (*_out) |
211 | 214 | ||
215 | // DEPRECATED: Don't call directly, use LL_ENDL instead, which actually looks like a macro | ||
212 | #define llendl \ | 216 | #define llendl \ |
213 | LLError::End(); \ | 217 | LLError::End(); \ |
214 | LLError::Log::flush(_out, _site); \ | 218 | LLError::Log::flush(_out, _site); \ |
215 | } \ | 219 | } \ |
216 | } | 220 | } |
217 | 221 | ||
218 | #define llinfos lllog(LLError::LEVEL_INFO) | 222 | // DEPRECATED: Use the new macros that allow tags and *look* like macros. |
219 | #define lldebugs lllog(LLError::LEVEL_DEBUG) | 223 | #define lldebugs lllog(LLError::LEVEL_DEBUG, NULL, NULL, false) |
220 | #define llwarns lllog(LLError::LEVEL_WARN) | 224 | #define llinfos lllog(LLError::LEVEL_INFO, NULL, NULL, false) |
221 | #define llerrs lllog(LLError::LEVEL_ERROR) | 225 | #define llwarns lllog(LLError::LEVEL_WARN, NULL, NULL, false) |
222 | 226 | #define llerrs lllog(LLError::LEVEL_ERROR, NULL, NULL, false) | |
223 | #define llcont (*_out) | 227 | #define llcont (*_out) |
228 | |||
229 | // NEW Macros for debugging, allow the passing of a string tag | ||
230 | |||
231 | // One Tag | ||
232 | #define LL_DEBUGS(broadTag) lllog(LLError::LEVEL_DEBUG, broadTag, NULL, false) | ||
233 | #define LL_INFOS(broadTag) lllog(LLError::LEVEL_INFO, broadTag, NULL, false) | ||
234 | #define LL_WARNS(broadTag) lllog(LLError::LEVEL_WARN, broadTag, NULL, false) | ||
235 | #define LL_ERRS(broadTag) lllog(LLError::LEVEL_ERROR, broadTag, NULL, false) | ||
236 | // Two Tags | ||
237 | #define LL_DEBUGS2(broadTag, narrowTag) lllog(LLError::LEVEL_DEBUG, broadTag, narrowTag, false) | ||
238 | #define LL_INFOS2(broadTag, narrowTag) lllog(LLError::LEVEL_INFO, broadTag, narrowTag, false) | ||
239 | #define LL_WARNS2(broadTag, narrowTag) lllog(LLError::LEVEL_WARN, broadTag, narrowTag, false) | ||
240 | #define LL_ERRS2(broadTag, narrowTag) lllog(LLError::LEVEL_ERROR, broadTag, narrowTag, false) | ||
241 | |||
242 | // Only print the log message once (good for warnings or infos that would otherwise | ||
243 | // spam the log file over and over, such as tighter loops). | ||
244 | #define LL_DEBUGS_ONCE(broadTag) lllog(LLError::LEVEL_DEBUG, broadTag, NULL, true) | ||
245 | #define LL_INFOS_ONCE(broadTag) lllog(LLError::LEVEL_INFO, broadTag, NULL, true) | ||
246 | #define LL_WARNS_ONCE(broadTag) lllog(LLError::LEVEL_WARN, broadTag, NULL, true) | ||
247 | #define LL_DEBUGS2_ONCE(broadTag, narrowTag) lllog(LLError::LEVEL_DEBUG, broadTag, narrowTag, true) | ||
248 | #define LL_INFOS2_ONCE(broadTag, narrowTag) lllog(LLError::LEVEL_INFO, broadTag, narrowTag, true) | ||
249 | #define LL_WARNS2_ONCE(broadTag, narrowTag) lllog(LLError::LEVEL_WARN, broadTag, narrowTag, true) | ||
250 | |||
251 | #define LL_ENDL llendl | ||
252 | #define LL_CONT (*_out) | ||
253 | |||
224 | /* | 254 | /* |
225 | Use this construct if you need to do computation in the middle of a | 255 | Use this construct if you need to do computation in the middle of a |
226 | message: | 256 | message: |
227 | 257 | ||
228 | llinfos << "the agent " << agend_id; | 258 | LL_INFOS("AgentGesture") << "the agent " << agend_id; |
229 | switch (f) | 259 | switch (f) |
230 | { | 260 | { |
231 | case FOP_SHRUGS: llcont << "shrugs"; break; | 261 | case FOP_SHRUGS: LL_CONT << "shrugs"; break; |
232 | case FOP_TAPS: llcont << "points at " << who; break; | 262 | case FOP_TAPS: LL_CONT << "points at " << who; break; |
233 | case FOP_SAYS: llcont << "says " << message; break; | 263 | case FOP_SAYS: LL_CONT << "says " << message; break; |
234 | } | 264 | } |
235 | llcont << " for " << t << " seconds" << llendl; | 265 | LL_CONT << " for " << t << " seconds" << LL_ENDL; |
236 | 266 | ||
237 | Such computation is done iff the message will be logged. | 267 | Such computation is done iff the message will be logged. |
238 | */ | 268 | */ |
diff --git a/linden/indra/llcommon/llfile.cpp b/linden/indra/llcommon/llfile.cpp index 32e9622..fc0d481 100644 --- a/linden/indra/llcommon/llfile.cpp +++ b/linden/indra/llcommon/llfile.cpp | |||
@@ -160,7 +160,7 @@ LLFILE * LLFile::_Fiopen(const char *filename, std::ios::openmode mode,int) // p | |||
160 | | ios_base::binary, | 160 | | ios_base::binary, |
161 | 0}; | 161 | 0}; |
162 | 162 | ||
163 | FILE *fp = 0; | 163 | LLFILE *fp = 0; |
164 | int n; | 164 | int n; |
165 | ios_base::openmode atendflag = mode & ios_base::ate; | 165 | ios_base::openmode atendflag = mode & ios_base::ate; |
166 | ios_base::openmode norepflag = mode & ios_base::_Noreplace; | 166 | ios_base::openmode norepflag = mode & ios_base::_Noreplace; |
@@ -207,7 +207,7 @@ void llifstream::open(const char* _Filename, /* Flawfinder: ignore */ | |||
207 | int _Prot) | 207 | int _Prot) |
208 | { // open a C stream with specified mode | 208 | { // open a C stream with specified mode |
209 | 209 | ||
210 | FILE* filep = LLFile::_Fiopen(_Filename,_Mode | ios_base::in, _Prot); | 210 | LLFILE* filep = LLFile::_Fiopen(_Filename,_Mode | ios_base::in, _Prot); |
211 | if(filep == NULL) | 211 | if(filep == NULL) |
212 | { | 212 | { |
213 | _Myios::setstate(ios_base::failbit); /*Flawfinder: ignore*/ | 213 | _Myios::setstate(ios_base::failbit); /*Flawfinder: ignore*/ |
@@ -258,7 +258,7 @@ void llofstream::open(const char* _Filename, /* Flawfinder: ignore */ | |||
258 | int _Prot) | 258 | int _Prot) |
259 | { // open a C stream with specified mode | 259 | { // open a C stream with specified mode |
260 | 260 | ||
261 | FILE* filep = LLFile::_Fiopen(_Filename,_Mode | ios_base::out, _Prot); | 261 | LLFILE* filep = LLFile::_Fiopen(_Filename,_Mode | ios_base::out, _Prot); |
262 | if(filep == NULL) | 262 | if(filep == NULL) |
263 | { | 263 | { |
264 | _Myios::setstate(ios_base::failbit); /*Flawfinder: ignore*/ | 264 | _Myios::setstate(ios_base::failbit); /*Flawfinder: ignore*/ |
diff --git a/linden/indra/llcommon/llfile.h b/linden/indra/llcommon/llfile.h index d449ec9..189edbf 100644 --- a/linden/indra/llcommon/llfile.h +++ b/linden/indra/llcommon/llfile.h | |||
@@ -42,6 +42,8 @@ | |||
42 | 42 | ||
43 | typedef FILE LLFILE; | 43 | typedef FILE LLFILE; |
44 | 44 | ||
45 | #include <fstream> | ||
46 | |||
45 | #ifdef LL_WINDOWS | 47 | #ifdef LL_WINDOWS |
46 | #define USE_LLFILESTREAMS 1 | 48 | #define USE_LLFILESTREAMS 1 |
47 | #else | 49 | #else |
diff --git a/linden/indra/llcommon/llfindlocale.cpp b/linden/indra/llcommon/llfindlocale.cpp new file mode 100644 index 0000000..47da974 --- /dev/null +++ b/linden/indra/llcommon/llfindlocale.cpp | |||
@@ -0,0 +1,525 @@ | |||
1 | /** | ||
2 | * @file llfindlocale.cpp | ||
3 | * @brief Detect system language setting | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2008&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2008, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
13 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
14 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
17 | * There are special exceptions to the terms and conditions of the GPL as | ||
18 | * it is applied to this Source Code. View the full text of the exception | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | ||
22 | * By copying, modifying or distributing this software, you acknowledge | ||
23 | * that you have read and understood your obligations described above, | ||
24 | * and agree to abide by those obligations. | ||
25 | * | ||
26 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
27 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
28 | * COMPLETENESS OR PERFORMANCE. | ||
29 | * $/LicenseInfo$ | ||
30 | */ | ||
31 | |||
32 | /* Yes, this was originally C code. */ | ||
33 | |||
34 | #include "linden_common.h" | ||
35 | |||
36 | #include <stdlib.h> | ||
37 | #include <string.h> | ||
38 | #include <ctype.h> | ||
39 | |||
40 | #ifdef WIN32 | ||
41 | #include <windows.h> | ||
42 | #include <winnt.h> | ||
43 | #endif | ||
44 | |||
45 | #include "llfindlocale.h" | ||
46 | |||
47 | static int | ||
48 | is_lcchar(const int c) { | ||
49 | return isalnum(c); | ||
50 | } | ||
51 | |||
52 | static void | ||
53 | lang_country_variant_from_envstring(const char *str, | ||
54 | char **lang, | ||
55 | char **country, | ||
56 | char **variant) { | ||
57 | int end = 0; | ||
58 | int start; | ||
59 | |||
60 | /* get lang, if any */ | ||
61 | start = end; | ||
62 | while (is_lcchar(str[end])) { | ||
63 | ++end; | ||
64 | } | ||
65 | if (start != end) { | ||
66 | int i; | ||
67 | int len = end - start; | ||
68 | char *s = (char*)malloc(len + 1); | ||
69 | for (i=0; i<len; ++i) { | ||
70 | s[i] = tolower(str[start + i]); | ||
71 | } | ||
72 | s[i] = '\0'; | ||
73 | *lang = s; | ||
74 | } else { | ||
75 | *lang = NULL; | ||
76 | } | ||
77 | |||
78 | if (str[end] && str[end]!=':') { /* not at end of str */ | ||
79 | ++end; | ||
80 | } | ||
81 | |||
82 | /* get country, if any */ | ||
83 | start = end; | ||
84 | while (is_lcchar(str[end])) { | ||
85 | ++end; | ||
86 | } | ||
87 | if (start != end) { | ||
88 | int i; | ||
89 | int len = end - start; | ||
90 | char *s = (char*)malloc(len + 1); | ||
91 | for (i=0; i<len; ++i) { | ||
92 | s[i] = toupper(str[start + i]); | ||
93 | } | ||
94 | s[i] = '\0'; | ||
95 | *country = s; | ||
96 | } else { | ||
97 | *country = NULL; | ||
98 | } | ||
99 | |||
100 | if (str[end] && str[end]!=':') { /* not at end of str */ | ||
101 | ++end; | ||
102 | } | ||
103 | |||
104 | /* get variant, if any */ | ||
105 | start = end; | ||
106 | while (str[end] && str[end]!=':') { | ||
107 | ++end; | ||
108 | } | ||
109 | if (start != end) { | ||
110 | int i; | ||
111 | int len = end - start; | ||
112 | char *s = (char*)malloc(len + 1); | ||
113 | for (i=0; i<len; ++i) { | ||
114 | s[i] = str[start + i]; | ||
115 | } | ||
116 | s[i] = '\0'; | ||
117 | *variant = s; | ||
118 | } else { | ||
119 | *variant = NULL; | ||
120 | } | ||
121 | } | ||
122 | |||
123 | |||
124 | static int | ||
125 | accumulate_locstring(const char *str, FL_Locale *l) { | ||
126 | char *lang = NULL; | ||
127 | char *country = NULL; | ||
128 | char *variant = NULL; | ||
129 | if (str) { | ||
130 | lang_country_variant_from_envstring(str, &lang, &country, &variant); | ||
131 | if (lang) { | ||
132 | l->lang = lang; | ||
133 | l->country = country; | ||
134 | l->variant = variant; | ||
135 | return 1; | ||
136 | } | ||
137 | } | ||
138 | free(lang); free(country); free(variant); | ||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | |||
143 | static int | ||
144 | accumulate_env(const char *name, FL_Locale *l) { | ||
145 | char *env; | ||
146 | char *lang = NULL; | ||
147 | char *country = NULL; | ||
148 | char *variant = NULL; | ||
149 | env = getenv(name); | ||
150 | if (env) { | ||
151 | return accumulate_locstring(env, l); | ||
152 | } | ||
153 | free(lang); free(country); free(variant); | ||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | |||
158 | static void | ||
159 | canonise_fl(FL_Locale *l) { | ||
160 | /* this function fixes some common locale-specifying mistakes */ | ||
161 | /* en_UK -> en_GB */ | ||
162 | if (l->lang && 0 == strcmp(l->lang, "en")) { | ||
163 | if (l->country && 0 == strcmp(l->country, "UK")) { | ||
164 | free((void*)l->country); | ||
165 | l->country = strdup("GB"); | ||
166 | } | ||
167 | } | ||
168 | /* ja_JA -> ja_JP */ | ||
169 | if (l->lang && 0 == strcmp(l->lang, "ja")) { | ||
170 | if (l->country && 0 == strcmp(l->country, "JA")) { | ||
171 | free((void*)l->country); | ||
172 | l->country = strdup("JP"); | ||
173 | } | ||
174 | } | ||
175 | } | ||
176 | |||
177 | |||
178 | #ifdef WIN32 | ||
179 | #include <stdio.h> | ||
180 | #define ML(pn,sn) MAKELANGID(LANG_##pn, SUBLANG_##pn##_##sn) | ||
181 | #define MLN(pn) MAKELANGID(LANG_##pn, SUBLANG_DEFAULT) | ||
182 | #define RML(pn,sn) MAKELANGID(LANG_##pn, SUBLANG_##sn) | ||
183 | typedef struct { | ||
184 | LANGID id; | ||
185 | char* code; | ||
186 | } IDToCode; | ||
187 | static const IDToCode both_to_code[] = { | ||
188 | {ML(ENGLISH,US), "en_US.ISO_8859-1"}, | ||
189 | {ML(ENGLISH,CAN), "en_CA"}, /* english / canadian */ | ||
190 | {ML(ENGLISH,UK), "en_GB"}, | ||
191 | {ML(ENGLISH,EIRE), "en_IE"}, | ||
192 | {ML(ENGLISH,AUS), "en_AU"}, | ||
193 | {MLN(GERMAN), "de_DE"}, | ||
194 | {MLN(SPANISH), "es_ES"}, | ||
195 | {ML(SPANISH,MEXICAN), "es_MX"}, | ||
196 | {MLN(FRENCH), "fr_FR"}, | ||
197 | {ML(FRENCH,CANADIAN), "fr_CA"}, | ||
198 | {ML(FRENCH,BELGIAN), "fr_BE"}, /* ? */ | ||
199 | {ML(DUTCH,BELGIAN), "nl_BE"}, /* ? */ | ||
200 | {ML(PORTUGUESE,BRAZILIAN), "pt_BR"}, | ||
201 | {MLN(PORTUGUESE), "pt_PT"}, | ||
202 | {MLN(SWEDISH), "sv_SE"}, | ||
203 | {ML(CHINESE,HONGKONG), "zh_HK"}, | ||
204 | /* these are machine-generated and not yet verified */ | ||
205 | {RML(AFRIKAANS,DEFAULT), "af_ZA"}, | ||
206 | {RML(ALBANIAN,DEFAULT), "sq_AL"}, | ||
207 | {RML(ARABIC,ARABIC_ALGERIA), "ar_DZ"}, | ||
208 | {RML(ARABIC,ARABIC_BAHRAIN), "ar_BH"}, | ||
209 | {RML(ARABIC,ARABIC_EGYPT), "ar_EG"}, | ||
210 | {RML(ARABIC,ARABIC_IRAQ), "ar_IQ"}, | ||
211 | {RML(ARABIC,ARABIC_JORDAN), "ar_JO"}, | ||
212 | {RML(ARABIC,ARABIC_KUWAIT), "ar_KW"}, | ||
213 | {RML(ARABIC,ARABIC_LEBANON), "ar_LB"}, | ||
214 | {RML(ARABIC,ARABIC_LIBYA), "ar_LY"}, | ||
215 | {RML(ARABIC,ARABIC_MOROCCO), "ar_MA"}, | ||
216 | {RML(ARABIC,ARABIC_OMAN), "ar_OM"}, | ||
217 | {RML(ARABIC,ARABIC_QATAR), "ar_QA"}, | ||
218 | {RML(ARABIC,ARABIC_SAUDI_ARABIA), "ar_SA"}, | ||
219 | {RML(ARABIC,ARABIC_SYRIA), "ar_SY"}, | ||
220 | {RML(ARABIC,ARABIC_TUNISIA), "ar_TN"}, | ||
221 | {RML(ARABIC,ARABIC_UAE), "ar_AE"}, | ||
222 | {RML(ARABIC,ARABIC_YEMEN), "ar_YE"}, | ||
223 | {RML(ARMENIAN,DEFAULT), "hy_AM"}, | ||
224 | {RML(AZERI,AZERI_CYRILLIC), "az_AZ"}, | ||
225 | {RML(AZERI,AZERI_LATIN), "az_AZ"}, | ||
226 | {RML(BASQUE,DEFAULT), "eu_ES"}, | ||
227 | {RML(BELARUSIAN,DEFAULT), "be_BY"}, | ||
228 | /*{RML(BRETON,DEFAULT), "br_FR"},*/ | ||
229 | {RML(BULGARIAN,DEFAULT), "bg_BG"}, | ||
230 | {RML(CATALAN,DEFAULT), "ca_ES"}, | ||
231 | {RML(CHINESE,CHINESE_HONGKONG), "zh_HK"}, | ||
232 | {RML(CHINESE,CHINESE_MACAU), "zh_MO"}, | ||
233 | {RML(CHINESE,CHINESE_SIMPLIFIED), "zh_CN"}, | ||
234 | {RML(CHINESE,CHINESE_SINGAPORE), "zh_SG"}, | ||
235 | {RML(CHINESE,CHINESE_TRADITIONAL), "zh_TW"}, | ||
236 | /*{RML(CORNISH,DEFAULT), "kw_GB"},*/ | ||
237 | {RML(CZECH,DEFAULT), "cs_CZ"}, | ||
238 | {RML(DANISH,DEFAULT), "da_DK"}, | ||
239 | {RML(DUTCH,DUTCH), "nl_NL"}, | ||
240 | {RML(DUTCH,DUTCH_BELGIAN), "nl_BE"}, | ||
241 | /*{RML(DUTCH,DUTCH_SURINAM), "nl_SR"},*/ | ||
242 | {RML(ENGLISH,ENGLISH_AUS), "en_AU"}, | ||
243 | {RML(ENGLISH,ENGLISH_BELIZE), "en_BZ"}, | ||
244 | {RML(ENGLISH,ENGLISH_CAN), "en_CA"}, | ||
245 | {RML(ENGLISH,ENGLISH_CARIBBEAN), "en_CB"}, | ||
246 | {RML(ENGLISH,ENGLISH_EIRE), "en_IE"}, | ||
247 | {RML(ENGLISH,ENGLISH_JAMAICA), "en_JM"}, | ||
248 | {RML(ENGLISH,ENGLISH_NZ), "en_NZ"}, | ||
249 | {RML(ENGLISH,ENGLISH_PHILIPPINES), "en_PH"}, | ||
250 | {RML(ENGLISH,ENGLISH_SOUTH_AFRICA), "en_ZA"}, | ||
251 | {RML(ENGLISH,ENGLISH_TRINIDAD), "en_TT"}, | ||
252 | {RML(ENGLISH,ENGLISH_UK), "en_GB"}, | ||
253 | {RML(ENGLISH,ENGLISH_US), "en_US"}, | ||
254 | {RML(ENGLISH,ENGLISH_ZIMBABWE), "en_ZW"}, | ||
255 | /*{RML(ESPERANTO,DEFAULT), "eo_"},*/ | ||
256 | {RML(ESTONIAN,DEFAULT), "et_EE"}, | ||
257 | {RML(FAEROESE,DEFAULT), "fo_FO"}, | ||
258 | {RML(FARSI,DEFAULT), "fa_IR"}, | ||
259 | {RML(FINNISH,DEFAULT), "fi_FI"}, | ||
260 | {RML(FRENCH,FRENCH), "fr_FR"}, | ||
261 | {RML(FRENCH,FRENCH_BELGIAN), "fr_BE"}, | ||
262 | {RML(FRENCH,FRENCH_CANADIAN), "fr_CA"}, | ||
263 | {RML(FRENCH,FRENCH_LUXEMBOURG), "fr_LU"}, | ||
264 | {RML(FRENCH,FRENCH_MONACO), "fr_MC"}, | ||
265 | {RML(FRENCH,FRENCH_SWISS), "fr_CH"}, | ||
266 | /*{RML(GAELIC,GAELIC), "ga_IE"},*/ | ||
267 | /*{RML(GAELIC,GAELIC_MANX), "gv_GB"},*/ | ||
268 | /*{RML(GAELIC,GAELIC_SCOTTISH), "gd_GB"},*/ | ||
269 | /*{RML(GALICIAN,DEFAULT), "gl_ES"},*/ | ||
270 | {RML(GEORGIAN,DEFAULT), "ka_GE"}, | ||
271 | {RML(GERMAN,GERMAN), "de_DE"}, | ||
272 | {RML(GERMAN,GERMAN_AUSTRIAN), "de_AT"}, | ||
273 | {RML(GERMAN,GERMAN_LIECHTENSTEIN), "de_LI"}, | ||
274 | {RML(GERMAN,GERMAN_LUXEMBOURG), "de_LU"}, | ||
275 | {RML(GERMAN,GERMAN_SWISS), "de_CH"}, | ||
276 | {RML(GREEK,DEFAULT), "el_GR"}, | ||
277 | {RML(GUJARATI,DEFAULT), "gu_IN"}, | ||
278 | {RML(HEBREW,DEFAULT), "he_IL"}, | ||
279 | {RML(HINDI,DEFAULT), "hi_IN"}, | ||
280 | {RML(HUNGARIAN,DEFAULT), "hu_HU"}, | ||
281 | {RML(ICELANDIC,DEFAULT), "is_IS"}, | ||
282 | {RML(INDONESIAN,DEFAULT), "id_ID"}, | ||
283 | {RML(ITALIAN,ITALIAN), "it_IT"}, | ||
284 | {RML(ITALIAN,ITALIAN_SWISS), "it_CH"}, | ||
285 | {RML(JAPANESE,DEFAULT), "ja_JP"}, | ||
286 | {RML(KANNADA,DEFAULT), "kn_IN"}, | ||
287 | {RML(KAZAK,DEFAULT), "kk_KZ"}, | ||
288 | {RML(KONKANI,DEFAULT), "kok_IN"}, | ||
289 | {RML(KOREAN,KOREAN), "ko_KR"}, | ||
290 | /*{RML(KYRGYZ,DEFAULT), "ky_KG"},*/ | ||
291 | {RML(LATVIAN,DEFAULT), "lv_LV"}, | ||
292 | {RML(LITHUANIAN,LITHUANIAN), "lt_LT"}, | ||
293 | {RML(MACEDONIAN,DEFAULT), "mk_MK"}, | ||
294 | {RML(MALAY,MALAY_BRUNEI_DARUSSALAM), "ms_BN"}, | ||
295 | {RML(MALAY,MALAY_MALAYSIA), "ms_MY"}, | ||
296 | {RML(MARATHI,DEFAULT), "mr_IN"}, | ||
297 | /*{RML(MONGOLIAN,DEFAULT), "mn_MN"},*/ | ||
298 | {RML(NORWEGIAN,NORWEGIAN_BOKMAL), "nb_NO"}, | ||
299 | {RML(NORWEGIAN,NORWEGIAN_NYNORSK), "nn_NO"}, | ||
300 | {RML(POLISH,DEFAULT), "pl_PL"}, | ||
301 | {RML(PORTUGUESE,PORTUGUESE), "pt_PT"}, | ||
302 | {RML(PORTUGUESE,PORTUGUESE_BRAZILIAN), "pt_BR"}, | ||
303 | {RML(PUNJABI,DEFAULT), "pa_IN"}, | ||
304 | {RML(ROMANIAN,DEFAULT), "ro_RO"}, | ||
305 | {RML(RUSSIAN,DEFAULT), "ru_RU"}, | ||
306 | {RML(SANSKRIT,DEFAULT), "sa_IN"}, | ||
307 | {RML(SERBIAN,DEFAULT), "hr_HR"}, | ||
308 | {RML(SERBIAN,SERBIAN_CYRILLIC), "sr_SP"}, | ||
309 | {RML(SERBIAN,SERBIAN_LATIN), "sr_SP"}, | ||
310 | {RML(SLOVAK,DEFAULT), "sk_SK"}, | ||
311 | {RML(SLOVENIAN,DEFAULT), "sl_SI"}, | ||
312 | {RML(SPANISH,SPANISH), "es_ES"}, | ||
313 | {RML(SPANISH,SPANISH_ARGENTINA), "es_AR"}, | ||
314 | {RML(SPANISH,SPANISH_BOLIVIA), "es_BO"}, | ||
315 | {RML(SPANISH,SPANISH_CHILE), "es_CL"}, | ||
316 | {RML(SPANISH,SPANISH_COLOMBIA), "es_CO"}, | ||
317 | {RML(SPANISH,SPANISH_COSTA_RICA), "es_CR"}, | ||
318 | {RML(SPANISH,SPANISH_DOMINICAN_REPUBLIC), "es_DO"}, | ||
319 | {RML(SPANISH,SPANISH_ECUADOR), "es_EC"}, | ||
320 | {RML(SPANISH,SPANISH_EL_SALVADOR), "es_SV"}, | ||
321 | {RML(SPANISH,SPANISH_GUATEMALA), "es_GT"}, | ||
322 | {RML(SPANISH,SPANISH_HONDURAS), "es_HN"}, | ||
323 | {RML(SPANISH,SPANISH_MEXICAN), "es_MX"}, | ||
324 | {RML(SPANISH,SPANISH_MODERN), "es_ES"}, | ||
325 | {RML(SPANISH,SPANISH_NICARAGUA), "es_NI"}, | ||
326 | {RML(SPANISH,SPANISH_PANAMA), "es_PA"}, | ||
327 | {RML(SPANISH,SPANISH_PARAGUAY), "es_PY"}, | ||
328 | {RML(SPANISH,SPANISH_PERU), "es_PE"}, | ||
329 | {RML(SPANISH,SPANISH_PUERTO_RICO), "es_PR"}, | ||
330 | {RML(SPANISH,SPANISH_URUGUAY), "es_UY"}, | ||
331 | {RML(SPANISH,SPANISH_VENEZUELA), "es_VE"}, | ||
332 | {RML(SWAHILI,DEFAULT), "sw_KE"}, | ||
333 | {RML(SWEDISH,SWEDISH), "sv_SE"}, | ||
334 | {RML(SWEDISH,SWEDISH_FINLAND), "sv_FI"}, | ||
335 | /*{RML(SYRIAC,DEFAULT), "syr_SY"},*/ | ||
336 | {RML(TAMIL,DEFAULT), "ta_IN"}, | ||
337 | {RML(TATAR,DEFAULT), "tt_TA"}, | ||
338 | {RML(TELUGU,DEFAULT), "te_IN"}, | ||
339 | {RML(THAI,DEFAULT), "th_TH"}, | ||
340 | {RML(TURKISH,DEFAULT), "tr_TR"}, | ||
341 | {RML(UKRAINIAN,DEFAULT), "uk_UA"}, | ||
342 | {RML(URDU,URDU_PAKISTAN), "ur_PK"}, | ||
343 | {RML(UZBEK,UZBEK_CYRILLIC), "uz_UZ"}, | ||
344 | {RML(UZBEK,UZBEK_LATIN), "uz_UZ"}, | ||
345 | {RML(VIETNAMESE,DEFAULT), "vi_VN"}, | ||
346 | /*{RML(WALON,DEFAULT), "wa_BE"},*/ | ||
347 | /*{RML(WELSH,DEFAULT), "cy_GB"},*/ | ||
348 | }; | ||
349 | static const IDToCode primary_to_code[] = { | ||
350 | {LANG_AFRIKAANS, "af"}, | ||
351 | {LANG_ARABIC, "ar"}, | ||
352 | {LANG_AZERI, "az"}, | ||
353 | {LANG_BULGARIAN, "bg"}, | ||
354 | /*{LANG_BRETON, "br"},*/ | ||
355 | {LANG_BELARUSIAN, "by"}, | ||
356 | {LANG_CATALAN, "ca"}, | ||
357 | {LANG_CZECH, "cs"}, | ||
358 | /*{LANG_WELSH, "cy"},*/ | ||
359 | {LANG_DANISH, "da"}, | ||
360 | {LANG_GERMAN, "de"}, | ||
361 | {LANG_GREEK, "el"}, | ||
362 | {LANG_ENGLISH, "en"}, | ||
363 | /*{LANG_ESPERANTO, "eo"},*/ | ||
364 | {LANG_SPANISH, "es"}, | ||
365 | {LANG_ESTONIAN, "et"}, | ||
366 | {LANG_BASQUE, "eu"}, | ||
367 | {LANG_FARSI, "fa"}, | ||
368 | {LANG_FINNISH, "fi"}, | ||
369 | {LANG_FAEROESE, "fo"}, | ||
370 | {LANG_FRENCH, "fr"}, | ||
371 | /*{LANG_GAELIC, "ga"},*/ | ||
372 | /*{LANG_GALICIAN, "gl"},*/ | ||
373 | {LANG_GUJARATI, "gu"}, | ||
374 | {LANG_HEBREW, "he"}, | ||
375 | {LANG_HINDI, "hi"}, | ||
376 | {LANG_SERBIAN, "hr"}, | ||
377 | {LANG_HUNGARIAN, "hu"}, | ||
378 | {LANG_ARMENIAN, "hy"}, | ||
379 | {LANG_INDONESIAN, "id"}, | ||
380 | {LANG_ITALIAN, "it"}, | ||
381 | {LANG_JAPANESE, "ja"}, | ||
382 | {LANG_GEORGIAN, "ka"}, | ||
383 | {LANG_KAZAK, "kk"}, | ||
384 | {LANG_KANNADA, "kn"}, | ||
385 | {LANG_KOREAN, "ko"}, | ||
386 | /*{LANG_KYRGYZ, "ky"},*/ | ||
387 | {LANG_LITHUANIAN, "lt"}, | ||
388 | {LANG_LATVIAN, "lv"}, | ||
389 | {LANG_MACEDONIAN, "mk"}, | ||
390 | /*{LANG_MONGOLIAN, "mn"},*/ | ||
391 | {LANG_MARATHI, "mr"}, | ||
392 | {LANG_MALAY, "ms"}, | ||
393 | {LANG_NORWEGIAN, "nb"}, | ||
394 | {LANG_DUTCH, "nl"}, | ||
395 | {LANG_NORWEGIAN, "nn"}, | ||
396 | {LANG_NORWEGIAN, "no"},/* unofficial? */ | ||
397 | {LANG_PUNJABI, "pa"}, | ||
398 | {LANG_POLISH, "pl"}, | ||
399 | {LANG_PORTUGUESE, "pt"}, | ||
400 | {LANG_ROMANIAN, "ro"}, | ||
401 | {LANG_RUSSIAN, "ru"}, | ||
402 | {LANG_SLOVAK, "sk"}, | ||
403 | {LANG_SLOVENIAN, "sl"}, | ||
404 | {LANG_ALBANIAN, "sq"}, | ||
405 | {LANG_SERBIAN, "sr"}, | ||
406 | {LANG_SWEDISH, "sv"}, | ||
407 | {LANG_SWAHILI, "sw"}, | ||
408 | {LANG_TAMIL, "ta"}, | ||
409 | {LANG_THAI, "th"}, | ||
410 | {LANG_TURKISH, "tr"}, | ||
411 | {LANG_TATAR, "tt"}, | ||
412 | {LANG_UKRAINIAN, "uk"}, | ||
413 | {LANG_URDU, "ur"}, | ||
414 | {LANG_UZBEK, "uz"}, | ||
415 | {LANG_VIETNAMESE, "vi"}, | ||
416 | /*{LANG_WALON, "wa"},*/ | ||
417 | {LANG_CHINESE, "zh"}, | ||
418 | }; | ||
419 | static int num_primary_to_code = | ||
420 | sizeof(primary_to_code) / sizeof(*primary_to_code); | ||
421 | static int num_both_to_code = | ||
422 | sizeof(both_to_code) / sizeof(*both_to_code); | ||
423 | |||
424 | static const int | ||
425 | lcid_to_fl(LCID lcid, | ||
426 | FL_Locale *rtn) { | ||
427 | LANGID langid = LANGIDFROMLCID(lcid); | ||
428 | LANGID primary_lang = PRIMARYLANGID(langid); | ||
429 | /*LANGID sub_lang = SUBLANGID(langid);*/ | ||
430 | int i; | ||
431 | /* try to find an exact primary/sublanguage combo that we know about */ | ||
432 | for (i=0; i<num_both_to_code; ++i) { | ||
433 | if (both_to_code[i].id == langid) { | ||
434 | accumulate_locstring(both_to_code[i].code, rtn); | ||
435 | return 1; | ||
436 | } | ||
437 | } | ||
438 | /* fallback to just checking the primary language id */ | ||
439 | for (i=0; i<num_primary_to_code; ++i) { | ||
440 | if (primary_to_code[i].id == primary_lang) { | ||
441 | accumulate_locstring(primary_to_code[i].code, rtn); | ||
442 | return 1; | ||
443 | } | ||
444 | } | ||
445 | return 0; | ||
446 | } | ||
447 | #endif | ||
448 | |||
449 | |||
450 | FL_Success | ||
451 | FL_FindLocale(FL_Locale **locale, FL_Domain domain) { | ||
452 | FL_Success success = FL_FAILED; | ||
453 | FL_Locale *rtn = (FL_Locale*)malloc(sizeof(FL_Locale)); | ||
454 | rtn->lang = NULL; | ||
455 | rtn->country = NULL; | ||
456 | rtn->variant = NULL; | ||
457 | |||
458 | #ifdef WIN32 | ||
459 | /* win32 >= mswindows95 */ | ||
460 | { | ||
461 | LCID lcid = GetThreadLocale(); | ||
462 | if (lcid_to_fl(lcid, rtn)) { | ||
463 | success = FL_CONFIDENT; | ||
464 | } | ||
465 | if (success == FL_FAILED) { | ||
466 | /* assume US English on mswindows systems unless we know otherwise */ | ||
467 | if (accumulate_locstring("en_US.ISO_8859-1", rtn)) { | ||
468 | success = FL_DEFAULT_GUESS; | ||
469 | } | ||
470 | } | ||
471 | } | ||
472 | #else | ||
473 | /* assume unixoid */ | ||
474 | { | ||
475 | /* examples: */ | ||
476 | /* sv_SE.ISO_8859-1 */ | ||
477 | /* fr_FR.ISO8859-1 */ | ||
478 | /* no_NO_NB */ | ||
479 | /* no_NO_NY */ | ||
480 | /* no_NO */ | ||
481 | /* de_DE */ | ||
482 | /* try the various vars in decreasing order of authority */ | ||
483 | if (accumulate_env("LC_ALL", rtn) || | ||
484 | accumulate_env("LC_MESSAGES", rtn) || | ||
485 | accumulate_env("LANG", rtn) || | ||
486 | accumulate_env("LANGUAGE", rtn)) { | ||
487 | success = FL_CONFIDENT; | ||
488 | } | ||
489 | if (success == FL_FAILED) { | ||
490 | /* assume US English on unixoid systems unless we know otherwise */ | ||
491 | if (accumulate_locstring("en_US.ISO_8859-1", rtn)) { | ||
492 | success = FL_DEFAULT_GUESS; | ||
493 | } | ||
494 | } | ||
495 | } | ||
496 | #endif | ||
497 | |||
498 | if (success != FL_FAILED) { | ||
499 | canonise_fl(rtn); | ||
500 | } | ||
501 | |||
502 | *locale = rtn; | ||
503 | return success; | ||
504 | } | ||
505 | |||
506 | |||
507 | void | ||
508 | FL_FreeLocale(FL_Locale **locale) { | ||
509 | if (locale) { | ||
510 | FL_Locale *l = *locale; | ||
511 | if (l) { | ||
512 | if (l->lang) { | ||
513 | free((void*)l->lang); | ||
514 | } | ||
515 | if (l->country) { | ||
516 | free((void*)l->country); | ||
517 | } | ||
518 | if (l->variant) { | ||
519 | free((void*)l->variant); | ||
520 | } | ||
521 | free(l); | ||
522 | *locale = NULL; | ||
523 | } | ||
524 | } | ||
525 | } | ||
diff --git a/linden/indra/llcommon/llfindlocale.h b/linden/indra/llcommon/llfindlocale.h new file mode 100644 index 0000000..6cc2dbb --- /dev/null +++ b/linden/indra/llcommon/llfindlocale.h | |||
@@ -0,0 +1,65 @@ | |||
1 | /** | ||
2 | * @file llfindlocale.h | ||
3 | * @brief Detect system language setting | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2008&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2008, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
13 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
14 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
17 | * There are special exceptions to the terms and conditions of the GPL as | ||
18 | * it is applied to this Source Code. View the full text of the exception | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | ||
22 | * By copying, modifying or distributing this software, you acknowledge | ||
23 | * that you have read and understood your obligations described above, | ||
24 | * and agree to abide by those obligations. | ||
25 | * | ||
26 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
27 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
28 | * COMPLETENESS OR PERFORMANCE. | ||
29 | * $/LicenseInfo$ | ||
30 | */ | ||
31 | |||
32 | #ifndef __findlocale_h_ | ||
33 | #define __findlocale_h_ | ||
34 | |||
35 | typedef const char* FL_Lang; | ||
36 | typedef const char* FL_Country; | ||
37 | typedef const char* FL_Variant; | ||
38 | |||
39 | typedef struct { | ||
40 | FL_Lang lang; | ||
41 | FL_Country country; | ||
42 | FL_Variant variant; | ||
43 | } FL_Locale; | ||
44 | |||
45 | typedef enum { | ||
46 | /* for some reason we failed to even guess: this should never happen */ | ||
47 | FL_FAILED = 0, | ||
48 | /* couldn't query locale -- returning a guess (almost always English) */ | ||
49 | FL_DEFAULT_GUESS = 1, | ||
50 | /* the returned locale type was found by successfully asking the system */ | ||
51 | FL_CONFIDENT = 2 | ||
52 | } FL_Success; | ||
53 | |||
54 | typedef enum { | ||
55 | FL_MESSAGES = 0 | ||
56 | } FL_Domain; | ||
57 | |||
58 | /* This allocates/fills in a FL_Locale structure with pointers to | ||
59 | strings (which should be treated as static), or NULL for inappropriate / | ||
60 | undetected fields. */ | ||
61 | FL_Success FL_FindLocale(FL_Locale **locale, FL_Domain domain); | ||
62 | /* This should be used to free the struct written by FL_FindLocale */ | ||
63 | void FL_FreeLocale(FL_Locale **locale); | ||
64 | |||
65 | #endif /*__findlocale_h_*/ | ||
diff --git a/linden/indra/llcommon/llheartbeat.cpp b/linden/indra/llcommon/llheartbeat.cpp new file mode 100644 index 0000000..13bcd46 --- /dev/null +++ b/linden/indra/llcommon/llheartbeat.cpp | |||
@@ -0,0 +1,165 @@ | |||
1 | /** | ||
2 | * @file llheartbeat.cpp | ||
3 | * @brief Class encapsulating logic for telling a watchdog that we live. | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2008&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2008, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
13 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
14 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
17 | * There are special exceptions to the terms and conditions of the GPL as | ||
18 | * it is applied to this Source Code. View the full text of the exception | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | ||
22 | * By copying, modifying or distributing this software, you acknowledge | ||
23 | * that you have read and understood your obligations described above, | ||
24 | * and agree to abide by those obligations. | ||
25 | * | ||
26 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
27 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
28 | * COMPLETENESS OR PERFORMANCE. | ||
29 | * $/LicenseInfo$ | ||
30 | */ | ||
31 | |||
32 | #include <errno.h> | ||
33 | #include <signal.h> | ||
34 | |||
35 | #include "linden_common.h" | ||
36 | #include "llapp.h" | ||
37 | |||
38 | #include "llheartbeat.h" | ||
39 | |||
40 | LLHeartbeat::LLHeartbeat(F32 secs_between_heartbeat, | ||
41 | F32 aggressive_heartbeat_panic_secs, | ||
42 | F32 aggressive_heartbeat_max_blocking_secs) | ||
43 | : mSecsBetweenHeartbeat(secs_between_heartbeat), | ||
44 | mAggressiveHeartbeatPanicSecs(aggressive_heartbeat_panic_secs), | ||
45 | mAggressiveHeartbeatMaxBlockingSecs(aggressive_heartbeat_max_blocking_secs), | ||
46 | mSuppressed(false) | ||
47 | { | ||
48 | mBeatTimer.reset(); | ||
49 | mBeatTimer.setTimerExpirySec(mSecsBetweenHeartbeat); | ||
50 | mPanicTimer.reset(); | ||
51 | mPanicTimer.setTimerExpirySec(mAggressiveHeartbeatPanicSecs); | ||
52 | } | ||
53 | |||
54 | LLHeartbeat::~LLHeartbeat() | ||
55 | { | ||
56 | // do nothing. | ||
57 | } | ||
58 | |||
59 | void | ||
60 | LLHeartbeat::setSuppressed(bool is_suppressed) | ||
61 | { | ||
62 | mSuppressed = is_suppressed; | ||
63 | } | ||
64 | |||
65 | // returns 0 on success, -1 on permanent failure, 1 on temporary failure | ||
66 | int | ||
67 | LLHeartbeat::rawSend() | ||
68 | { | ||
69 | #if LL_WINDOWS | ||
70 | return 0; // Pretend we succeeded. | ||
71 | #else | ||
72 | if (mSuppressed) | ||
73 | return 0; // Pretend we succeeded. | ||
74 | |||
75 | union sigval dummy; | ||
76 | int result = sigqueue(getppid(), LL_HEARTBEAT_SIGNAL, dummy); | ||
77 | if (result == 0) | ||
78 | return 0; // success | ||
79 | |||
80 | int err = errno; | ||
81 | if (err == EAGAIN) | ||
82 | return 1; // failed to queue, try again | ||
83 | |||
84 | return -1; // other failure. | ||
85 | #endif | ||
86 | } | ||
87 | |||
88 | int | ||
89 | LLHeartbeat::rawSendWithTimeout(F32 timeout_sec) | ||
90 | { | ||
91 | int result = 0; | ||
92 | |||
93 | // Spin tightly until our heartbeat is digested by the watchdog | ||
94 | // or we time-out. We don't really want to sleep because our | ||
95 | // wake-up time might be undesirably synchronised to a hidden | ||
96 | // clock by the system's scheduler. | ||
97 | mTimeoutTimer.reset(); | ||
98 | mTimeoutTimer.setTimerExpirySec(timeout_sec); | ||
99 | do { | ||
100 | result = rawSend(); | ||
101 | //llinfos << " HEARTSENDc=" << result << llendl; | ||
102 | } while (result==1 && !mTimeoutTimer.hasExpired()); | ||
103 | |||
104 | return result; | ||
105 | } | ||
106 | |||
107 | bool | ||
108 | LLHeartbeat::send(F32 timeout_sec) | ||
109 | { | ||
110 | bool total_success = false; | ||
111 | int result = 1; | ||
112 | |||
113 | if (timeout_sec > 0.f) { | ||
114 | // force a spin until success or timeout | ||
115 | result = rawSendWithTimeout(timeout_sec); | ||
116 | } else { | ||
117 | if (mBeatTimer.hasExpired()) { | ||
118 | // zero-timeout; we don't care too much whether our | ||
119 | // heartbeat was digested. | ||
120 | result = rawSend(); | ||
121 | //llinfos << " HEARTSENDb=" << result << llendl; | ||
122 | } | ||
123 | } | ||
124 | |||
125 | if (result == -1) { | ||
126 | // big failure. | ||
127 | } else if (result == 0) { | ||
128 | total_success = true; | ||
129 | } else { | ||
130 | // need to retry at some point | ||
131 | } | ||
132 | |||
133 | if (total_success) { | ||
134 | mBeatTimer.reset(); | ||
135 | mBeatTimer.setTimerExpirySec(mSecsBetweenHeartbeat); | ||
136 | // reset the time until we start panicking about lost | ||
137 | // heartbeats again. | ||
138 | mPanicTimer.reset(); | ||
139 | mPanicTimer.setTimerExpirySec(mAggressiveHeartbeatPanicSecs); | ||
140 | } else { | ||
141 | // leave mBeatTimer as expired so we'll lazily poke the | ||
142 | // watchdog again next time through. | ||
143 | } | ||
144 | |||
145 | if (mPanicTimer.hasExpired()) { | ||
146 | // It's been ages since we successfully had a heartbeat | ||
147 | // digested by the watchdog. Sit here and spin a while | ||
148 | // in the hope that we can force it through. | ||
149 | llwarns << "Unable to deliver heartbeat to launcher for " << mPanicTimer.getElapsedTimeF32() << " seconds. Going to try very hard for up to " << mAggressiveHeartbeatMaxBlockingSecs << " seconds." << llendl; | ||
150 | result = rawSendWithTimeout(mAggressiveHeartbeatMaxBlockingSecs); | ||
151 | if (result == 0) { | ||
152 | total_success = true; | ||
153 | } else { | ||
154 | // we couldn't even force it through. That's bad, | ||
155 | // but we'll try again in a while. | ||
156 | llwarns << "Could not deliver heartbeat to launcher even after trying very hard for " << mAggressiveHeartbeatMaxBlockingSecs << " seconds." << llendl; | ||
157 | } | ||
158 | |||
159 | // in any case, reset the panic timer. | ||
160 | mPanicTimer.reset(); | ||
161 | mPanicTimer.setTimerExpirySec(mAggressiveHeartbeatPanicSecs); | ||
162 | } | ||
163 | |||
164 | return total_success; | ||
165 | } | ||
diff --git a/linden/indra/llcommon/llheartbeat.h b/linden/indra/llcommon/llheartbeat.h new file mode 100644 index 0000000..8a2fa0a --- /dev/null +++ b/linden/indra/llcommon/llheartbeat.h | |||
@@ -0,0 +1,73 @@ | |||
1 | /** | ||
2 | * @file llheartbeat.h | ||
3 | * @brief Class encapsulating logic for telling a watchdog that we live. | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2008&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2008, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
13 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
14 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
17 | * There are special exceptions to the terms and conditions of the GPL as | ||
18 | * it is applied to this Source Code. View the full text of the exception | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | ||
22 | * By copying, modifying or distributing this software, you acknowledge | ||
23 | * that you have read and understood your obligations described above, | ||
24 | * and agree to abide by those obligations. | ||
25 | * | ||
26 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
27 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
28 | * COMPLETENESS OR PERFORMANCE. | ||
29 | * $/LicenseInfo$ | ||
30 | */ | ||
31 | |||
32 | #ifndef LL_LLHEARTBEAT_H | ||
33 | #define LL_LLHEARTBEAT_H | ||
34 | |||
35 | #include "linden_common.h" | ||
36 | |||
37 | #include "lltimer.h" | ||
38 | |||
39 | // Note: Win32 does not support the heartbeat/smackdown system; | ||
40 | // heartbeat-delivery turns into a no-op there. | ||
41 | |||
42 | class LLHeartbeat | ||
43 | { | ||
44 | public: | ||
45 | // secs_between_heartbeat: after a heartbeat is successfully delivered, | ||
46 | // we suppress sending more for this length of time. | ||
47 | // aggressive_heartbeat_panic_secs: if we've been failing to | ||
48 | // successfully deliver heartbeats for this length of time then | ||
49 | // we block for a while until we're really sure we got one delivered. | ||
50 | // aggressive_heartbeat_max_blocking_secs: this is the length of | ||
51 | // time we block for when we're aggressively ensuring that a 'panic' | ||
52 | // heartbeat was delivered. | ||
53 | LLHeartbeat(F32 secs_between_heartbeat = 5.0f, | ||
54 | F32 aggressive_heartbeat_panic_secs = 10.0f, | ||
55 | F32 aggressive_heartbeat_max_blocking_secs = 4.0f); | ||
56 | ~LLHeartbeat(); | ||
57 | |||
58 | bool send(F32 timeout_sec = 0.0f); | ||
59 | void setSuppressed(bool is_suppressed); | ||
60 | |||
61 | private: | ||
62 | int rawSend(); | ||
63 | int rawSendWithTimeout(F32 timeout_sec); | ||
64 | F32 mSecsBetweenHeartbeat; | ||
65 | F32 mAggressiveHeartbeatPanicSecs; | ||
66 | F32 mAggressiveHeartbeatMaxBlockingSecs; | ||
67 | bool mSuppressed; | ||
68 | LLTimer mBeatTimer; | ||
69 | LLTimer mPanicTimer; | ||
70 | LLTimer mTimeoutTimer; | ||
71 | }; | ||
72 | |||
73 | #endif // LL_HEARTBEAT_H | ||
diff --git a/linden/indra/llcommon/llindraconfigfile.cpp b/linden/indra/llcommon/llindraconfigfile.cpp new file mode 100644 index 0000000..7ef1a9b --- /dev/null +++ b/linden/indra/llcommon/llindraconfigfile.cpp | |||
@@ -0,0 +1,107 @@ | |||
1 | /** | ||
2 | * @file llindraconfigfile.cpp | ||
3 | * | ||
4 | * | ||
5 | * This class is an LLLiveFile that has config info for indra | ||
6 | * Currently only whether it's blacklisted | ||
7 | * | ||
8 | * $LicenseInfo:firstyear=2007&license=internal$ | ||
9 | * | ||
10 | * Copyright (c) 2007-2008, Linden Research, Inc. | ||
11 | * | ||
12 | * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of | ||
13 | * this source code is governed by the Linden Lab Source Code Disclosure | ||
14 | * Agreement ("Agreement") previously entered between you and Linden | ||
15 | * Lab. By accessing, using, copying, modifying or distributing this | ||
16 | * software, you acknowledge that you have been informed of your | ||
17 | * obligations under the Agreement and agree to abide by those obligations. | ||
18 | * | ||
19 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
20 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
21 | * COMPLETENESS OR PERFORMANCE. | ||
22 | * $/LicenseInfo$ | ||
23 | */ | ||
24 | |||
25 | #include "llindraconfigfile.h" | ||
26 | |||
27 | #include "llfile.h" | ||
28 | #include "llsd.h" | ||
29 | #include "llsdserialize.h" | ||
30 | #include "llframetimer.h" | ||
31 | |||
32 | static std::string sConfigDir = ""; | ||
33 | static const char indraConfigFileName[] = "indra.xml"; | ||
34 | |||
35 | |||
36 | LLIndraConfigFile::LLIndraConfigFile() | ||
37 | : LLLiveFile(filename(), configFileRefreshRate), | ||
38 | mConfig(LLSD()) | ||
39 | { | ||
40 | } | ||
41 | |||
42 | //static | ||
43 | void LLIndraConfigFile::initClass(const std::string& config_dir) | ||
44 | { | ||
45 | sConfigDir = config_dir; | ||
46 | llinfos << "LLIndraConfigFile::initClass config dir " | ||
47 | << config_dir << "/" << indraConfigFileName << llendl; | ||
48 | } | ||
49 | |||
50 | LLSD LLIndraConfigFile::getConfig(const std::string& config_name) | ||
51 | { | ||
52 | if (sConfigDir.empty()) | ||
53 | { | ||
54 | llerrs << "LLIndraConfigFile::initClass() not called" << llendl; | ||
55 | } | ||
56 | |||
57 | LLFrameTimer::updateFrameTime(); | ||
58 | |||
59 | static LLIndraConfigFile the_file; | ||
60 | the_file.checkAndReload(); | ||
61 | |||
62 | return the_file.mConfig[config_name]; | ||
63 | } | ||
64 | |||
65 | std::string LLIndraConfigFile::filename() | ||
66 | { | ||
67 | std::ostringstream ostr; | ||
68 | |||
69 | ostr << sConfigDir | ||
70 | << "/" << indraConfigFileName; | ||
71 | |||
72 | return ostr.str(); | ||
73 | } | ||
74 | |||
75 | /* virtual */ | ||
76 | void LLIndraConfigFile::loadFile() | ||
77 | { | ||
78 | llinfos << "LLIndraConfigFile::loadFile: reading from " | ||
79 | << filename() << llendl; | ||
80 | |||
81 | LLSD config; | ||
82 | |||
83 | { | ||
84 | llifstream file(filename().c_str()); | ||
85 | if (file.is_open()) | ||
86 | { | ||
87 | LLSDSerialize::fromXML(config, file); | ||
88 | } | ||
89 | |||
90 | if (config.isUndefined()) | ||
91 | { | ||
92 | llinfos << "LLIndraConfigFile::loadFile: file missing, ill-formed," | ||
93 | " or simply undefined; not changing the blacklist" << llendl; | ||
94 | return; | ||
95 | } | ||
96 | } | ||
97 | |||
98 | if (config.isMap()) | ||
99 | { | ||
100 | mConfig = config; | ||
101 | } | ||
102 | else | ||
103 | { | ||
104 | llwarns << "LLIndraConfigFile: " << indraConfigFileName << " expects a map; wrong format" << llendl; | ||
105 | return; | ||
106 | } | ||
107 | } | ||
diff --git a/linden/indra/llcommon/llindraconfigfile.h b/linden/indra/llcommon/llindraconfigfile.h new file mode 100644 index 0000000..271a848 --- /dev/null +++ b/linden/indra/llcommon/llindraconfigfile.h | |||
@@ -0,0 +1,50 @@ | |||
1 | /** | ||
2 | * @file llindraconfigfile.h | ||
3 | * @brief manages configuration file for indra.xml | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2007&license=internal$ | ||
6 | * | ||
7 | * Copyright (c) 2007-2008, Linden Research, Inc. | ||
8 | * | ||
9 | * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of | ||
10 | * this source code is governed by the Linden Lab Source Code Disclosure | ||
11 | * Agreement ("Agreement") previously entered between you and Linden | ||
12 | * Lab. By accessing, using, copying, modifying or distributing this | ||
13 | * software, you acknowledge that you have been informed of your | ||
14 | * obligations under the Agreement and agree to abide by those obligations. | ||
15 | * | ||
16 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
17 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
18 | * COMPLETENESS OR PERFORMANCE. | ||
19 | * $/LicenseInfo$ | ||
20 | */ | ||
21 | |||
22 | #ifndef LL_LLINDRACONFIGFILE_H | ||
23 | #define LL_LLINDRACONFIGFILE_H | ||
24 | |||
25 | #include <string> | ||
26 | #include "linden_common.h" | ||
27 | |||
28 | #include "lllivefile.h" | ||
29 | #include "llsd.h" | ||
30 | |||
31 | |||
32 | // To use, call LLIndraConfigFile::initClass(config_dir); | ||
33 | // Then whenever getConfig is called, it will check and reload automatically | ||
34 | |||
35 | class LLIndraConfigFile : public LLLiveFile | ||
36 | { | ||
37 | public: | ||
38 | LLIndraConfigFile(); | ||
39 | static void initClass(const std::string& config_dir); | ||
40 | static LLSD getConfig(const std::string& config_name); | ||
41 | |||
42 | private: | ||
43 | static std::string filename(); | ||
44 | |||
45 | protected: | ||
46 | /* virtual */ void loadFile(); | ||
47 | LLSD mConfig; | ||
48 | }; | ||
49 | |||
50 | #endif //LL_LLINDRACONFIGFILE_H | ||
diff --git a/linden/indra/llcommon/llkeyusetracker.h b/linden/indra/llcommon/llkeyusetracker.h new file mode 100644 index 0000000..c37ba24 --- /dev/null +++ b/linden/indra/llcommon/llkeyusetracker.h | |||
@@ -0,0 +1,220 @@ | |||
1 | /** | ||
2 | * @file llkeyusetracker.h | ||
3 | * @brief Declaration of the LLKeyUseTracker class. | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2003&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2003-2008, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
13 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
14 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
17 | * There are special exceptions to the terms and conditions of the GPL as | ||
18 | * it is applied to this Source Code. View the full text of the exception | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | ||
22 | * By copying, modifying or distributing this software, you acknowledge | ||
23 | * that you have read and understood your obligations described above, | ||
24 | * and agree to abide by those obligations. | ||
25 | * | ||
26 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
27 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
28 | * COMPLETENESS OR PERFORMANCE. | ||
29 | * $/LicenseInfo$ | ||
30 | */ | ||
31 | |||
32 | #ifndef LL_KEYUSETRACKER_H | ||
33 | #define LL_KEYUSETRACKER_H | ||
34 | |||
35 | // This is a generic cache for an arbitrary data type indexed against an | ||
36 | // arbitrary key type. The cache length is determined by expiration time | ||
37 | // tince against last use and set size. The age of elements and the size | ||
38 | // of the cache are queryable. | ||
39 | // | ||
40 | // This is implemented as a list, which makes search O(n). If you reuse this | ||
41 | // for something with a large dataset, consider reimplementing with a Boost | ||
42 | // multimap based on both a map(key) and priority queue(last_use). | ||
43 | |||
44 | template <class TKey, class TData> | ||
45 | class KeyUseTrackerNodeImpl | ||
46 | { | ||
47 | public: | ||
48 | U64 mLastUse; | ||
49 | U32 mUseCount; | ||
50 | TKey mKey; | ||
51 | TData mData; | ||
52 | |||
53 | KeyUseTrackerNodeImpl( TKey k, TData d ) : | ||
54 | mLastUse(0), | ||
55 | mUseCount(0), | ||
56 | mKey( k ), | ||
57 | mData( d ) | ||
58 | { | ||
59 | } | ||
60 | }; | ||
61 | |||
62 | |||
63 | template <class TKey, class TData> | ||
64 | class LLKeyUseTracker | ||
65 | { | ||
66 | typedef KeyUseTrackerNodeImpl<TKey,TData> TKeyUseTrackerNode; | ||
67 | typedef std::list<TKeyUseTrackerNode *> TKeyList; | ||
68 | TKeyList mKeyList; | ||
69 | U64 mMemUsecs; | ||
70 | U64 mLastExpire; | ||
71 | U32 mMaxCount; | ||
72 | U32 mCount; | ||
73 | |||
74 | static U64 getTime() | ||
75 | { | ||
76 | // This function operates on a frame basis, not instantaneous. | ||
77 | // We can rely on its output for determining first use in a | ||
78 | // frame. | ||
79 | return LLFrameTimer::getTotalTime(); | ||
80 | } | ||
81 | |||
82 | void ageKeys() | ||
83 | { | ||
84 | U64 now = getTime(); | ||
85 | if( now == mLastExpire ) | ||
86 | { | ||
87 | return; | ||
88 | } | ||
89 | mLastExpire = now; | ||
90 | |||
91 | while( !mKeyList.empty() && (now - mKeyList.front()->mLastUse > mMemUsecs ) ) | ||
92 | { | ||
93 | delete mKeyList.front(); | ||
94 | mKeyList.pop_front(); | ||
95 | mCount--; | ||
96 | } | ||
97 | } | ||
98 | |||
99 | TKeyUseTrackerNode *findNode( TKey key ) | ||
100 | { | ||
101 | ageKeys(); | ||
102 | |||
103 | typename TKeyList::iterator i; | ||
104 | for( i = mKeyList.begin(); i != mKeyList.end(); i++ ) | ||
105 | { | ||
106 | if( (*i)->mKey == key ) | ||
107 | return *i; | ||
108 | } | ||
109 | |||
110 | return NULL; | ||
111 | } | ||
112 | |||
113 | TKeyUseTrackerNode *removeNode( TKey key ) | ||
114 | { | ||
115 | TKeyUseTrackerNode *i; | ||
116 | i = findNode( key ); | ||
117 | if( i ) | ||
118 | { | ||
119 | mKeyList.remove( i ); | ||
120 | mCount--; | ||
121 | return i; | ||
122 | } | ||
123 | |||
124 | return NULL; | ||
125 | } | ||
126 | |||
127 | public: | ||
128 | LLKeyUseTracker( U32 memory_seconds, U32 max_count ) : | ||
129 | mLastExpire(0), | ||
130 | mMaxCount( max_count ), | ||
131 | mCount(0) | ||
132 | { | ||
133 | mMemUsecs = ((U64)memory_seconds) * 1000000; | ||
134 | } | ||
135 | |||
136 | ~LLKeyUseTracker() | ||
137 | { | ||
138 | // Flush list | ||
139 | while( !mKeyList.empty() ) | ||
140 | { | ||
141 | delete mKeyList.front(); | ||
142 | mKeyList.pop_front(); | ||
143 | mCount--; | ||
144 | } | ||
145 | } | ||
146 | |||
147 | void markUse( TKey key, TData data ) | ||
148 | { | ||
149 | TKeyUseTrackerNode *node = removeNode( key ); | ||
150 | if( !node ) | ||
151 | { | ||
152 | node = new TKeyUseTrackerNode(key, data); | ||
153 | } | ||
154 | else | ||
155 | { | ||
156 | // Update data | ||
157 | node->mData = data; | ||
158 | } | ||
159 | node->mLastUse = getTime(); | ||
160 | node->mUseCount++; | ||
161 | mKeyList.push_back( node ); | ||
162 | mCount++; | ||
163 | |||
164 | // Too many items? Drop head | ||
165 | if( mCount > mMaxCount ) | ||
166 | { | ||
167 | delete mKeyList.front(); | ||
168 | mKeyList.pop_front(); | ||
169 | mCount--; | ||
170 | } | ||
171 | } | ||
172 | |||
173 | void forgetKey( TKey key ) | ||
174 | { | ||
175 | TKeyUseTrackerNode *node = removeNode( key ); | ||
176 | if( node ) | ||
177 | { | ||
178 | delete node; | ||
179 | } | ||
180 | } | ||
181 | |||
182 | U32 getUseCount( TKey key ) | ||
183 | { | ||
184 | TKeyUseTrackerNode *node = findNode( key ); | ||
185 | if( node ) | ||
186 | { | ||
187 | return node->mUseCount; | ||
188 | } | ||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | U64 getTimeSinceUse( TKey key ) | ||
193 | { | ||
194 | TKeyUseTrackerNode *node = findNode( key ); | ||
195 | if( node ) | ||
196 | { | ||
197 | U64 now = getTime(); | ||
198 | U64 delta = now - node->mLastUse; | ||
199 | return (U32)( delta / 1000000 ); | ||
200 | } | ||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | TData *getLastUseData( TKey key ) | ||
205 | { | ||
206 | TKeyUseTrackerNode *node = findNode( key ); | ||
207 | if( node ) | ||
208 | { | ||
209 | return &node->mData; | ||
210 | } | ||
211 | return NULL; | ||
212 | } | ||
213 | |||
214 | U32 getKeyCount() | ||
215 | { | ||
216 | return mCount; | ||
217 | } | ||
218 | }; | ||
219 | |||
220 | #endif | ||
diff --git a/linden/indra/llcommon/lllivefile.h b/linden/indra/llcommon/lllivefile.h index 1d55f7b..0a18fe0 100644 --- a/linden/indra/llcommon/lllivefile.h +++ b/linden/indra/llcommon/lllivefile.h | |||
@@ -32,6 +32,8 @@ | |||
32 | #ifndef LL_LLLIVEFILE_H | 32 | #ifndef LL_LLLIVEFILE_H |
33 | #define LL_LLLIVEFILE_H | 33 | #define LL_LLLIVEFILE_H |
34 | 34 | ||
35 | const F32 configFileRefreshRate = 5.0; // seconds | ||
36 | |||
35 | 37 | ||
36 | class LLLiveFile | 38 | class LLLiveFile |
37 | { | 39 | { |
diff --git a/linden/indra/llcommon/llmemory.cpp b/linden/indra/llcommon/llmemory.cpp index 0f08877..5edeb4b 100644 --- a/linden/indra/llcommon/llmemory.cpp +++ b/linden/indra/llcommon/llmemory.cpp | |||
@@ -387,7 +387,7 @@ U64 getCurrentRSS() | |||
387 | U64 getCurrentRSS() | 387 | U64 getCurrentRSS() |
388 | { | 388 | { |
389 | static const char statPath[] = "/proc/self/stat"; | 389 | static const char statPath[] = "/proc/self/stat"; |
390 | FILE *fp = fopen(statPath, "r"); | 390 | LLFILE *fp = LLFile::fopen(statPath, "r"); |
391 | U64 rss = 0; | 391 | U64 rss = 0; |
392 | 392 | ||
393 | if (fp == NULL) | 393 | if (fp == NULL) |
diff --git a/linden/indra/llcommon/llprocessor.cpp b/linden/indra/llcommon/llprocessor.cpp index d67a9c4..1c0f7e0 100644 --- a/linden/indra/llcommon/llprocessor.cpp +++ b/linden/indra/llcommon/llprocessor.cpp | |||
@@ -2230,7 +2230,7 @@ bool CProcessor::WriteInfoTextFile(const char *strFilename) | |||
2230 | return false; | 2230 | return false; |
2231 | 2231 | ||
2232 | // Then we create a new file (CREATE_ALWAYS) | 2232 | // Then we create a new file (CREATE_ALWAYS) |
2233 | FILE *file = LLFile::fopen(strFilename, "w"); /* Flawfinder: ignore */ | 2233 | LLFILE *file = LLFile::fopen(strFilename, "w"); /* Flawfinder: ignore */ |
2234 | if (!file) | 2234 | if (!file) |
2235 | return false; | 2235 | return false; |
2236 | 2236 | ||
diff --git a/linden/indra/llcommon/llptrskipmap.h b/linden/indra/llcommon/llptrskipmap.h index b369d77..8592197 100644 --- a/linden/indra/llcommon/llptrskipmap.h +++ b/linden/indra/llcommon/llptrskipmap.h | |||
@@ -238,7 +238,8 @@ private: | |||
238 | template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH> | 238 | template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH> |
239 | inline LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::LLPtrSkipMap() | 239 | inline LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::LLPtrSkipMap() |
240 | : mInsertFirst(NULL), | 240 | : mInsertFirst(NULL), |
241 | mEquals(defaultEquals) | 241 | mEquals(defaultEquals), |
242 | mNumberOfSteps(0) | ||
242 | { | 243 | { |
243 | if (BINARY_DEPTH < 2) | 244 | if (BINARY_DEPTH < 2) |
244 | { | 245 | { |
@@ -259,7 +260,8 @@ template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH> | |||
259 | inline LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::LLPtrSkipMap(insert_func insert_first, | 260 | inline LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::LLPtrSkipMap(insert_func insert_first, |
260 | equals_func equals) | 261 | equals_func equals) |
261 | : mInsertFirst(insert_first), | 262 | : mInsertFirst(insert_first), |
262 | mEquals(equals) | 263 | mEquals(equals), |
264 | mNumberOfSteps(0) | ||
263 | { | 265 | { |
264 | if (BINARY_DEPTH < 2) | 266 | if (BINARY_DEPTH < 2) |
265 | { | 267 | { |
diff --git a/linden/indra/llcommon/llsdserialize.h b/linden/indra/llcommon/llsdserialize.h index 41e0aa5..f5282b4 100644 --- a/linden/indra/llcommon/llsdserialize.h +++ b/linden/indra/llcommon/llsdserialize.h | |||
@@ -390,7 +390,7 @@ public: | |||
390 | /** | 390 | /** |
391 | * Options for output | 391 | * Options for output |
392 | */ | 392 | */ |
393 | enum e_formatter_options_type | 393 | typedef enum e_formatter_options_type |
394 | { | 394 | { |
395 | OPTIONS_NONE = 0, | 395 | OPTIONS_NONE = 0, |
396 | OPTIONS_PRETTY = 1 | 396 | OPTIONS_PRETTY = 1 |
diff --git a/linden/indra/llcommon/llsdutil.h b/linden/indra/llcommon/llsdutil.h index c058185..ae6d694 100644 --- a/linden/indra/llcommon/llsdutil.h +++ b/linden/indra/llcommon/llsdutil.h | |||
@@ -101,4 +101,16 @@ BOOL compare_llsd_with_template( | |||
101 | const LLSD& template_llsd, | 101 | const LLSD& template_llsd, |
102 | LLSD& resultant_llsd); | 102 | LLSD& resultant_llsd); |
103 | 103 | ||
104 | // Simple function to copy data out of input & output iterators if | ||
105 | // there is no need for casting. | ||
106 | template<typename Input> LLSD llsd_copy_array(Input iter, Input end) | ||
107 | { | ||
108 | LLSD dest; | ||
109 | for (; iter != end; ++iter) | ||
110 | { | ||
111 | dest.append(*iter); | ||
112 | } | ||
113 | return dest; | ||
114 | } | ||
115 | |||
104 | #endif // LL_LLSDUTIL_H | 116 | #endif // LL_LLSDUTIL_H |
diff --git a/linden/indra/llcommon/llsys.cpp b/linden/indra/llcommon/llsys.cpp index ccdcd00..1285851 100644 --- a/linden/indra/llcommon/llsys.cpp +++ b/linden/indra/llcommon/llsys.cpp | |||
@@ -293,7 +293,7 @@ U32 LLOSInfo::getProcessVirtualSizeKB() | |||
293 | #if LL_WINDOWS | 293 | #if LL_WINDOWS |
294 | #endif | 294 | #endif |
295 | #if LL_LINUX | 295 | #if LL_LINUX |
296 | FILE* status_filep = LLFile::fopen("/proc/self/status", "rb"); | 296 | LLFILE* status_filep = LLFile::fopen("/proc/self/status", "rb"); |
297 | S32 numRead = 0; | 297 | S32 numRead = 0; |
298 | char buff[STATUS_SIZE]; /* Flawfinder: ignore */ | 298 | char buff[STATUS_SIZE]; /* Flawfinder: ignore */ |
299 | 299 | ||
@@ -336,7 +336,7 @@ U32 LLOSInfo::getProcessResidentSizeKB() | |||
336 | #if LL_WINDOWS | 336 | #if LL_WINDOWS |
337 | #endif | 337 | #endif |
338 | #if LL_LINUX | 338 | #if LL_LINUX |
339 | FILE* status_filep = LLFile::fopen("/proc/self/status", "rb"); | 339 | LLFILE* status_filep = LLFile::fopen("/proc/self/status", "rb"); |
340 | if (status_filep != NULL) | 340 | if (status_filep != NULL) |
341 | { | 341 | { |
342 | S32 numRead = 0; | 342 | S32 numRead = 0; |
@@ -398,7 +398,7 @@ LLCPUInfo::LLCPUInfo() | |||
398 | 398 | ||
399 | #elif LL_LINUX | 399 | #elif LL_LINUX |
400 | std::map< LLString, LLString > cpuinfo; | 400 | std::map< LLString, LLString > cpuinfo; |
401 | FILE* cpuinfo_fp = LLFile::fopen(CPUINFO_FILE, "rb"); | 401 | LLFILE* cpuinfo_fp = LLFile::fopen(CPUINFO_FILE, "rb"); |
402 | if(cpuinfo_fp) | 402 | if(cpuinfo_fp) |
403 | { | 403 | { |
404 | char line[MAX_STRING]; | 404 | char line[MAX_STRING]; |
@@ -486,7 +486,7 @@ void LLCPUInfo::stream(std::ostream& s) const | |||
486 | } | 486 | } |
487 | #else | 487 | #else |
488 | // *NOTE: This works on linux. What will it do on other systems? | 488 | // *NOTE: This works on linux. What will it do on other systems? |
489 | FILE* cpuinfo = LLFile::fopen(CPUINFO_FILE, "rb"); | 489 | LLFILE* cpuinfo = LLFile::fopen(CPUINFO_FILE, "rb"); |
490 | if(cpuinfo) | 490 | if(cpuinfo) |
491 | { | 491 | { |
492 | char line[MAX_STRING]; | 492 | char line[MAX_STRING]; |
@@ -621,7 +621,7 @@ void LLMemoryInfo::stream(std::ostream& s) const | |||
621 | s << "Total Physical KB: " << phys << std::endl; | 621 | s << "Total Physical KB: " << phys << std::endl; |
622 | #else | 622 | #else |
623 | // *NOTE: This works on linux. What will it do on other systems? | 623 | // *NOTE: This works on linux. What will it do on other systems? |
624 | FILE* meminfo = LLFile::fopen(MEMINFO_FILE,"rb"); | 624 | LLFILE* meminfo = LLFile::fopen(MEMINFO_FILE,"rb"); |
625 | if(meminfo) | 625 | if(meminfo) |
626 | { | 626 | { |
627 | char line[MAX_STRING]; /* Flawfinder: ignore */ | 627 | char line[MAX_STRING]; /* Flawfinder: ignore */ |
@@ -665,7 +665,7 @@ BOOL gunzip_file(const char *srcfile, const char *dstfile) | |||
665 | BOOL retval = FALSE; | 665 | BOOL retval = FALSE; |
666 | gzFile src = NULL; | 666 | gzFile src = NULL; |
667 | U8 buffer[UNCOMPRESS_BUFFER_SIZE]; | 667 | U8 buffer[UNCOMPRESS_BUFFER_SIZE]; |
668 | FILE *dst = NULL; | 668 | LLFILE *dst = NULL; |
669 | S32 bytes = 0; | 669 | S32 bytes = 0; |
670 | (void *) strcpy(tmpfile, dstfile); /* Flawfinder: ignore */ | 670 | (void *) strcpy(tmpfile, dstfile); /* Flawfinder: ignore */ |
671 | (void *) strncat(tmpfile, ".t", sizeof(tmpfile) - strlen(tmpfile) -1); /* Flawfinder: ignore */ | 671 | (void *) strncat(tmpfile, ".t", sizeof(tmpfile) - strlen(tmpfile) -1); /* Flawfinder: ignore */ |
@@ -700,7 +700,7 @@ BOOL gzip_file(const char *srcfile, const char *dstfile) | |||
700 | BOOL retval = FALSE; | 700 | BOOL retval = FALSE; |
701 | U8 buffer[COMPRESS_BUFFER_SIZE]; | 701 | U8 buffer[COMPRESS_BUFFER_SIZE]; |
702 | gzFile dst = NULL; | 702 | gzFile dst = NULL; |
703 | FILE *src = NULL; | 703 | LLFILE *src = NULL; |
704 | S32 bytes = 0; | 704 | S32 bytes = 0; |
705 | (void *) strcpy(tmpfile, dstfile); /* Flawfinder: ignore */ | 705 | (void *) strcpy(tmpfile, dstfile); /* Flawfinder: ignore */ |
706 | (void *) strncat(tmpfile, ".t", sizeof(tmpfile) - strlen(tmpfile) -1); /* Flawfinder: ignore */ | 706 | (void *) strncat(tmpfile, ".t", sizeof(tmpfile) - strlen(tmpfile) -1); /* Flawfinder: ignore */ |
diff --git a/linden/indra/llcommon/lltimer.cpp b/linden/indra/llcommon/lltimer.cpp index a421dce..25d9897 100644 --- a/linden/indra/llcommon/lltimer.cpp +++ b/linden/indra/llcommon/lltimer.cpp | |||
@@ -39,10 +39,8 @@ | |||
39 | # define WIN32_LEAN_AND_MEAN | 39 | # define WIN32_LEAN_AND_MEAN |
40 | # include <winsock2.h> | 40 | # include <winsock2.h> |
41 | # include <windows.h> | 41 | # include <windows.h> |
42 | #elif LL_LINUX || LL_SOLARIS | 42 | #elif LL_LINUX || LL_SOLARIS || LL_DARWIN |
43 | # include <sys/time.h> | 43 | # include <errno.h> |
44 | # include <sched.h> | ||
45 | #elif LL_DARWIN | ||
46 | # include <sys/time.h> | 44 | # include <sys/time.h> |
47 | #else | 45 | #else |
48 | # error "architecture not supported" | 46 | # error "architecture not supported" |
@@ -81,42 +79,55 @@ U64 gLastTotalTimeClockCount = 0; | |||
81 | //--------------------------------------------------------------------------- | 79 | //--------------------------------------------------------------------------- |
82 | 80 | ||
83 | #if LL_WINDOWS | 81 | #if LL_WINDOWS |
84 | void ms_sleep(long ms) | 82 | void ms_sleep(U32 ms) |
85 | { | 83 | { |
86 | Sleep((U32)ms); | 84 | Sleep(ms); |
87 | } | 85 | } |
88 | 86 | #elif LL_LINUX || LL_SOLARIS || LL_DARWIN | |
89 | void llyield() | 87 | void ms_sleep(U32 ms) |
90 | { | 88 | { |
91 | SleepEx(0, TRUE); // Relinquishes time slice to any thread of equal priority, can be woken up by extended IO functions | 89 | long mslong = ms; // tv_nsec is a long |
92 | } | 90 | struct timespec thiswait, nextwait; |
93 | #elif LL_LINUX || LL_SOLARIS | 91 | bool sleep_more = false; |
94 | void ms_sleep(long ms) | ||
95 | { | ||
96 | struct timespec t; | ||
97 | t.tv_sec = ms / 1000; | ||
98 | t.tv_nsec = (ms % 1000) * 1000000l; | ||
99 | nanosleep(&t, NULL); | ||
100 | } | ||
101 | 92 | ||
102 | void llyield() | 93 | thiswait.tv_sec = ms / 1000; |
103 | { | 94 | thiswait.tv_nsec = (mslong % 1000) * 1000000l; |
104 | sched_yield(); | 95 | do { |
105 | } | 96 | int result = nanosleep(&thiswait, &nextwait); |
106 | #elif LL_DARWIN | ||
107 | void ms_sleep(long ms) | ||
108 | { | ||
109 | struct timespec t; | ||
110 | t.tv_sec = ms / 1000; | ||
111 | t.tv_nsec = (ms % 1000) * 1000000l; | ||
112 | nanosleep(&t, NULL); | ||
113 | } | ||
114 | 97 | ||
115 | void llyield() | 98 | // check if sleep was interrupted by a signal; unslept |
116 | { | 99 | // remainder was written back into 't' and we just nanosleep |
117 | // sched_yield(); | 100 | // again. |
101 | sleep_more = (result == -1 && EINTR == errno); | ||
102 | |||
103 | if (sleep_more) | ||
104 | { | ||
105 | if ( nextwait.tv_sec > thiswait.tv_sec || | ||
106 | (nextwait.tv_sec == thiswait.tv_sec && | ||
107 | nextwait.tv_nsec >= thiswait.tv_nsec) ) | ||
108 | { | ||
109 | // if the remaining time isn't actually going | ||
110 | // down then we're being shafted by low clock | ||
111 | // resolution - manually massage the sleep time | ||
112 | // downward. | ||
113 | if (nextwait.tv_nsec > 1000000) { | ||
114 | // lose 1ms | ||
115 | nextwait.tv_nsec -= 1000000; | ||
116 | } else { | ||
117 | if (nextwait.tv_sec == 0) { | ||
118 | // already so close to finished | ||
119 | sleep_more = false; | ||
120 | } else { | ||
121 | // lose up to 1ms | ||
122 | nextwait.tv_nsec = 0; | ||
123 | } | ||
124 | } | ||
125 | } | ||
126 | thiswait = nextwait; | ||
127 | } | ||
128 | } while (sleep_more); | ||
118 | } | 129 | } |
119 | #else | 130 | #else |
120 | # error "architecture not supported" | 131 | # error "architecture not supported" |
121 | #endif | 132 | #endif |
122 | 133 | ||
@@ -323,7 +334,7 @@ void LLTimer::setTimerExpirySec(F32 expiration) | |||
323 | + (U64)((F32)(expiration * gClockFrequency)); | 334 | + (U64)((F32)(expiration * gClockFrequency)); |
324 | } | 335 | } |
325 | 336 | ||
326 | F32 LLTimer::getRemainingTimeF32() | 337 | F32 LLTimer::getRemainingTimeF32() const |
327 | { | 338 | { |
328 | U64 cur_ticks = get_clock_count(); | 339 | U64 cur_ticks = get_clock_count(); |
329 | if (cur_ticks > mExpirationTicks) | 340 | if (cur_ticks > mExpirationTicks) |
@@ -348,7 +359,7 @@ BOOL LLTimer::checkExpirationAndReset(F32 expiration) | |||
348 | } | 359 | } |
349 | 360 | ||
350 | 361 | ||
351 | BOOL LLTimer::hasExpired() | 362 | BOOL LLTimer::hasExpired() const |
352 | { | 363 | { |
353 | return (get_clock_count() >= mExpirationTicks) | 364 | return (get_clock_count() >= mExpirationTicks) |
354 | ? TRUE : FALSE; | 365 | ? TRUE : FALSE; |
@@ -550,3 +561,4 @@ void LLEventTimer::updateClass() | |||
550 | } | 561 | } |
551 | } | 562 | } |
552 | 563 | ||
564 | |||
diff --git a/linden/indra/llcommon/lltimer.h b/linden/indra/llcommon/lltimer.h index 8a4bc76..91b93d6 100644 --- a/linden/indra/llcommon/lltimer.h +++ b/linden/indra/llcommon/lltimer.h | |||
@@ -87,11 +87,11 @@ public: | |||
87 | void setLastClockCount(U64 current_count); // Sets the timer so that the next elapsed call will be relative to this time | 87 | void setLastClockCount(U64 current_count); // Sets the timer so that the next elapsed call will be relative to this time |
88 | void setTimerExpirySec(F32 expiration); | 88 | void setTimerExpirySec(F32 expiration); |
89 | BOOL checkExpirationAndReset(F32 expiration); | 89 | BOOL checkExpirationAndReset(F32 expiration); |
90 | BOOL hasExpired(); | 90 | BOOL hasExpired() const; |
91 | F32 getElapsedTimeAndResetF32(); // Returns elapsed time in seconds with reset | 91 | F32 getElapsedTimeAndResetF32(); // Returns elapsed time in seconds with reset |
92 | F64 getElapsedTimeAndResetF64(); | 92 | F64 getElapsedTimeAndResetF64(); |
93 | 93 | ||
94 | F32 getRemainingTimeF32(); | 94 | F32 getRemainingTimeF32() const; |
95 | 95 | ||
96 | static BOOL knownBadTimer(); | 96 | static BOOL knownBadTimer(); |
97 | 97 | ||
@@ -112,12 +112,8 @@ U64 get_clock_count(); | |||
112 | F64 calc_clock_frequency(U32 msecs); | 112 | F64 calc_clock_frequency(U32 msecs); |
113 | void update_clock_frequencies(); | 113 | void update_clock_frequencies(); |
114 | 114 | ||
115 | |||
116 | // Sleep for milliseconds | 115 | // Sleep for milliseconds |
117 | void ms_sleep(long ms); | 116 | void ms_sleep(U32 ms); |
118 | |||
119 | // Yield | ||
120 | //void llyield(); // Yield your timeslice - not implemented yet for Mac, so commented out. | ||
121 | 117 | ||
122 | // Returns the correct UTC time in seconds, like time(NULL). | 118 | // Returns the correct UTC time in seconds, like time(NULL). |
123 | // Useful on the viewer, which may have its local clock set wrong. | 119 | // Useful on the viewer, which may have its local clock set wrong. |
diff --git a/linden/indra/llcommon/llversionserver.h b/linden/indra/llcommon/llversionserver.h index e865b6a..e3ceadf 100644 --- a/linden/indra/llcommon/llversionserver.h +++ b/linden/indra/llcommon/llversionserver.h | |||
@@ -33,9 +33,9 @@ | |||
33 | #define LL_LLVERSIONSERVER_H | 33 | #define LL_LLVERSIONSERVER_H |
34 | 34 | ||
35 | const S32 LL_VERSION_MAJOR = 1; | 35 | const S32 LL_VERSION_MAJOR = 1; |
36 | const S32 LL_VERSION_MINOR = 20; | 36 | const S32 LL_VERSION_MINOR = 21; |
37 | const S32 LL_VERSION_PATCH = 0; | 37 | const S32 LL_VERSION_PATCH = 1; |
38 | const S32 LL_VERSION_BUILD = 83892; | 38 | const S32 LL_VERSION_BUILD = 86526; |
39 | 39 | ||
40 | const char * const LL_CHANNEL = "Second Life Server"; | 40 | const char * const LL_CHANNEL = "Second Life Server"; |
41 | 41 | ||
diff --git a/linden/indra/llcommon/llversionviewer.h b/linden/indra/llcommon/llversionviewer.h index 71bb12e..db3d42d 100644 --- a/linden/indra/llcommon/llversionviewer.h +++ b/linden/indra/llcommon/llversionviewer.h | |||
@@ -34,7 +34,7 @@ | |||
34 | 34 | ||
35 | const S32 LL_VERSION_MAJOR = 1; | 35 | const S32 LL_VERSION_MAJOR = 1; |
36 | const S32 LL_VERSION_MINOR = 20; | 36 | const S32 LL_VERSION_MINOR = 20; |
37 | const S32 LL_VERSION_PATCH = 5; | 37 | const S32 LL_VERSION_PATCH = 7; |
38 | const S32 LL_VERSION_BUILD = 0; | 38 | const S32 LL_VERSION_BUILD = 0; |
39 | 39 | ||
40 | const char * const LL_CHANNEL = "Second Life Release"; | 40 | const char * const LL_CHANNEL = "Second Life Release"; |