00001 #include "kr_plat_ao.h" 00002 00003 #include "ac_app_context.h" 00004 #include "bb_blackboard.h" 00005 #include "er_errors.h" 00006 #include "kr_diskspace.h" 00007 #include "kr_sms_trigger_epoc.hpp" 00008 #include "sa_sensor_list_log_db.h" 00009 #include "ut_diskspace_epoc.hpp" 00010 #include "ut_telephony_epoc.h" 00011 #include "ut_retry_epoc.hpp" 00012 #include "utils_cl2.h" 00013 00014 // -------------------------------------------------- 00015 // disk space observing 00016 // -------------------------------------------------- 00017 00018 /***koog 00019 (require codegen/symbian-cxx) 00020 (ctor-defines/spec 00021 "CDiskObserver" ;; name 00022 "" ;; args 00023 "" ;; inits 00024 "" ;; ctor 00025 #t ;; ConstructL 00026 ) 00027 ***/ 00028 #define CTOR_DECL_CDiskObserver \ 00029 public: static CDiskObserver* NewLC(); \ 00030 public: static CDiskObserver* NewL(); \ 00031 private: CDiskObserver(); \ 00032 private: void ConstructL(); 00033 00034 #define CTOR_IMPL_CDiskObserver \ 00035 CDiskObserver* CDiskObserver::NewLC() \ 00036 { \ 00037 CDiskObserver* obj = new (ELeave) CDiskObserver(); \ 00038 CleanupStack::PushL(obj); \ 00039 obj->ConstructL(); \ 00040 return obj; \ 00041 } \ 00042 \ 00043 CDiskObserver* CDiskObserver::NewL() \ 00044 { \ 00045 CDiskObserver* obj = CDiskObserver::NewLC(); \ 00046 CleanupStack::Pop(obj); \ 00047 return obj; \ 00048 } \ 00049 \ 00050 CDiskObserver::CDiskObserver() \ 00051 {} 00052 /***end***/ 00053 NONSHARABLE_CLASS(CDiskObserver) : public CBase, public MDiskSpace 00054 { 00055 CTOR_DECL_CDiskObserver; 00056 00057 public: 00058 ~CDiskObserver(); 00059 00060 private: 00061 virtual void DiskSpaceNotify(TInt aDrive, TInt errCode); 00062 00063 private: 00064 DEF_SESSION(RFs, iFs); 00065 CDiskSpaceNotifier* iNotifier; 00066 }; 00067 00068 CTOR_IMPL_CDiskObserver; 00069 00070 void CDiskObserver::ConstructL() 00071 { 00072 TChar driveLetter = DATABASE_DRIVE_LETTER; 00073 TInt driveNum = 0; 00074 User::LeaveIfError(RFs::CharToDrive(driveLetter, driveNum)); 00075 00076 LEAVE_IF_ERROR_OR_SET_SESSION_OPEN(iFs, iFs.Connect()); 00077 int database_disk_threshold = ac_STATIC_GET(database_disk_threshold); 00078 iNotifier = CDiskSpaceNotifier::NewL(iFs, driveNum, 00079 this, 00080 (TInt64)database_disk_threshold); 00081 } 00082 00083 CDiskObserver::~CDiskObserver() 00084 { 00085 delete iNotifier; 00086 SESSION_CLOSE_IF_OPEN(iFs); 00087 } 00088 00089 void CDiskObserver::DiskSpaceNotify(TInt aDrive, TInt errCode) 00090 { 00091 (void)aDrive; 00092 if (errCode) { 00093 // We are not really expecting any errors here, not any that are 00094 // in the API docs, anyway. 00095 logg("unexpected error in disk observer: %d", errCode); 00096 } else { 00097 // There are a number of causes why we might get an 00098 // RFs::NotifyDiskSpace() event, so we have to do some further 00099 // checking here. 00100 TRAPD(errCode, CheckLoggingMediumReadyL(iFs)); 00101 if (errCode) { 00102 // One issue here is that we do not really know if it is safe to 00103 // try to log this error to the database. Possibly not, so the 00104 // debug log, if any, shall have to do. 00105 ex_txtlog_error(errCode); 00106 if (errCode == KErrDiskFull) { 00107 er_fatal_disk_low; 00108 } else { 00109 // A typical cause for getting here is attaching an USB cable, 00110 // resulting in KErrNotReady (-18). Hence this visible message 00111 // is somewhat appropriate. 00112 er_fatal_disk_not_ready; 00113 } 00114 } 00115 } 00116 } 00117 00118 // -------------------------------------------------- 00119 // network registration status observing 00120 // -------------------------------------------------- 00121 00122 /***koog 00123 (require codegen/symbian-cxx) 00124 (ctor-defines/spec 00125 "CRegistrationObserver" ;; name 00126 "" ;; args 00127 "" ;; inits 00128 "" ;; ctor 00129 #t ;; ConstructL 00130 ) 00131 ***/ 00132 #define CTOR_DECL_CRegistrationObserver \ 00133 public: static CRegistrationObserver* NewLC(); \ 00134 public: static CRegistrationObserver* NewL(); \ 00135 private: CRegistrationObserver(); \ 00136 private: void ConstructL(); 00137 00138 #define CTOR_IMPL_CRegistrationObserver \ 00139 CRegistrationObserver* CRegistrationObserver::NewLC() \ 00140 { \ 00141 CRegistrationObserver* obj = new (ELeave) CRegistrationObserver(); \ 00142 CleanupStack::PushL(obj); \ 00143 obj->ConstructL(); \ 00144 return obj; \ 00145 } \ 00146 \ 00147 CRegistrationObserver* CRegistrationObserver::NewL() \ 00148 { \ 00149 CRegistrationObserver* obj = CRegistrationObserver::NewLC(); \ 00150 CleanupStack::Pop(obj); \ 00151 return obj; \ 00152 } \ 00153 \ 00154 CRegistrationObserver::CRegistrationObserver() \ 00155 {} 00156 /***end***/ 00157 00158 #define This CRegistrationObserver 00159 00160 NONSHARABLE_CLASS(This) : 00161 public CBase, 00162 public MObserverObs_NetworkRegistration 00163 { 00164 CTOR_DECL_CRegistrationObserver; 00165 00166 public: 00167 ~CRegistrationObserver(); 00168 00169 private: 00170 virtual void ObservedData_NetworkRegistration(TData_NetworkRegistration const &aData); 00171 virtual void Failed_NetworkRegistration(TInt aError); 00172 virtual void InFlightMode_NetworkRegistration(); 00173 00174 private: 00175 CObserverAo_NetworkRegistration* iObserver; 00176 }; 00177 00178 CTOR_IMPL_CRegistrationObserver; 00179 00180 void This::ConstructL() 00181 { 00182 ac_AppContext* ac = ac_get_global_AppContext(); 00183 00184 iObserver = CObserverAo_NetworkRegistration::NewL(ac, *this); 00185 } 00186 00187 This::~CRegistrationObserver() 00188 { 00189 delete iObserver; 00190 } 00191 00192 void This::ObservedData_NetworkRegistration(TData_NetworkRegistration const &aData) 00193 { 00194 int status = aData.iRegStatus; 00195 logg("network registration status: %d", status); 00196 LogDb* logDb = ac_global_LogDb; 00197 if (logDb) { 00198 log_db_log_registration(logDb, status, NULL); 00199 } 00200 } 00201 00202 void This::Failed_NetworkRegistration(TInt aError) 00203 { 00204 er_log_symbian(0, aError, 00205 "network registration status query failure (giving up)"); 00206 } 00207 00208 void This::InFlightMode_NetworkRegistration() 00209 { 00210 logt("network registration observer sleeping (flight mode)"); 00211 } 00212 00213 #undef This 00214 00215 // -------------------------------------------------- 00216 // network information observing 00217 // -------------------------------------------------- 00218 00219 // In flight mode, we have been seeing KErrAccessDenied (-21). The 00220 // current implementation avoids querying in flight mode. 00221 00222 /***koog 00223 (require codegen/symbian-cxx) 00224 (ctor-defines/spec 00225 "CNetworkObserver" ;; name 00226 "" ;; args 00227 "" ;; inits 00228 "" ;; ctor 00229 #t ;; ConstructL 00230 ) 00231 ***/ 00232 #define CTOR_DECL_CNetworkObserver \ 00233 public: static CNetworkObserver* NewLC(); \ 00234 public: static CNetworkObserver* NewL(); \ 00235 private: CNetworkObserver(); \ 00236 private: void ConstructL(); 00237 00238 #define CTOR_IMPL_CNetworkObserver \ 00239 CNetworkObserver* CNetworkObserver::NewLC() \ 00240 { \ 00241 CNetworkObserver* obj = new (ELeave) CNetworkObserver(); \ 00242 CleanupStack::PushL(obj); \ 00243 obj->ConstructL(); \ 00244 return obj; \ 00245 } \ 00246 \ 00247 CNetworkObserver* CNetworkObserver::NewL() \ 00248 { \ 00249 CNetworkObserver* obj = CNetworkObserver::NewLC(); \ 00250 CleanupStack::Pop(obj); \ 00251 return obj; \ 00252 } \ 00253 \ 00254 CNetworkObserver::CNetworkObserver() \ 00255 {} 00256 /***end***/ 00257 00258 #define This CNetworkObserver 00259 00260 NONSHARABLE_CLASS(This) : 00261 public CBase, 00262 public MObserverObs_NetworkInfo 00263 { 00264 CTOR_DECL_CNetworkObserver; 00265 00266 public: 00267 ~CNetworkObserver(); 00268 00269 private: 00270 virtual void ObservedData_NetworkInfo(TData_NetworkInfo const &aData); 00271 virtual void ReportTransientError_NetworkInfo(TInt aError); 00272 virtual void RetriesExhausted_NetworkInfo(); 00273 virtual void InFlightMode_NetworkInfo(); 00274 00275 private: 00276 CObserverAo_NetworkInfo* iObserver; 00277 TData_NetworkInfo iOldData; 00278 TData_NetworkInfo iFlightModeData; 00279 }; 00280 00281 CTOR_IMPL_CNetworkObserver; 00282 00283 void This::ConstructL() 00284 { 00285 // The default constructor basically gives us what we want, but we 00286 // add the "operator" name to help us see from the logs what is 00287 // going on. 00288 _LIT(KFlightModeText, "(flight mode)"); 00289 iFlightModeData.iLongName.Copy(KFlightModeText); 00290 00291 ac_AppContext* ac = ac_get_global_AppContext(); 00292 iObserver = CObserverAo_NetworkInfo::NewL(ac, *this); 00293 } 00294 00295 This::~CNetworkObserver() 00296 { 00297 delete iObserver; 00298 } 00299 00300 void This::ObservedData_NetworkInfo(TData_NetworkInfo const &aData) 00301 { 00302 // Log operator long name, if it has changed. 00303 { 00304 if (aData.iLongName != iOldData.iLongName) { 00305 LogDb* logDb = ac_global_LogDb; 00306 HBufC8* text8 = ConvToUtf8ZL(aData.iLongName); 00307 CleanupStack::PushL(text8); 00308 guilogf("operator: name '%s'", (char*)text8->Ptr()); 00309 log_db_log_operator(logDb, (const char*)text8->Ptr(), NULL); 00310 kr_Controller_set_operator_name(ac_global_Controller, 00311 (const char*)text8->Ptr()); 00312 CleanupStack::PopAndDestroy(text8); 00313 } 00314 } 00315 00316 // Propagate any changed mobile network country code. 00317 if (iOldData.iCountryCode != aData.iCountryCode) { 00318 TLex lex(aData.iCountryCode); 00319 int mcc; 00320 TInt errCode = lex.Val(mcc); 00321 if (errCode) 00322 // Unexpected MCC. 00323 mcc = -1; 00324 // Notify interested parties. 00325 kr_Controller_set_current_mcc(ac_global_Controller, mcc); 00326 } 00327 00328 // Post data for those interested in GSM cell ID changes. 00329 if ((iOldData.iCountryCode != aData.iCountryCode) || 00330 (iOldData.iNetworkId != aData.iNetworkId) || 00331 (iOldData.iLocationAreaCode != aData.iLocationAreaCode) || 00332 (iOldData.iCellId != aData.iCellId)) { 00333 bb_Blackboard_notify(ac_global_Blackboard, 00334 bb_dt_cell_id, 00335 (gpointer)&aData, 0); 00336 } 00337 00338 iOldData = aData; 00339 00340 bb_Blackboard_notify(ac_global_Blackboard, 00341 bb_dt_network_info, 00342 (gpointer)&aData, 0); 00343 } 00344 00345 void This::ReportTransientError_NetworkInfo(TInt aError) 00346 { 00347 er_log_symbian(0, aError, "network info query failure (transient)"); 00348 } 00349 00350 void This::RetriesExhausted_NetworkInfo() 00351 { 00352 er_log_none(er_FATAL, "network info queries failing"); 00353 } 00354 00355 void This::InFlightMode_NetworkInfo() 00356 { 00357 logt("network info observer sleeping (flight mode)"); 00358 ObservedData_NetworkInfo(iFlightModeData); 00359 } 00360 00361 #undef This 00362 00363 // -------------------------------------------------- 00364 // network signal strength observing 00365 // -------------------------------------------------- 00366 00367 /* We require retries here in particular, as we have seen KErrOverflow frequently. In fact we have had enough many failures so as to run out of retries. 00368 00369 xxx Should find out why this is, if there are conditions under which it is not okay to make this query. Cannot find any information about the cause, but something to account for is that "this functionality is not available when the phone is in flight mode". 00370 00371 We try to account for the above by observing flightmode status, and refraining from making requests (or having outstanding requests) when flightmode is on. We shall see if this addresses the issue. 00372 00373 xxx Could more easily implement based on CObserverAo_SignalStrength. 00374 */ 00375 00376 /***koog 00377 (require codegen/symbian-cxx) 00378 (ctor-defines/spec 00379 "CSignalObserver" ;; name 00380 "" ;; args 00381 "" ;; inits 00382 "" ;; ctor 00383 #t ;; ConstructL 00384 ) 00385 ***/ 00386 #define CTOR_DECL_CSignalObserver \ 00387 public: static CSignalObserver* NewLC(); \ 00388 public: static CSignalObserver* NewL(); \ 00389 private: CSignalObserver(); \ 00390 private: void ConstructL(); 00391 00392 #define CTOR_IMPL_CSignalObserver \ 00393 CSignalObserver* CSignalObserver::NewLC() \ 00394 { \ 00395 CSignalObserver* obj = new (ELeave) CSignalObserver(); \ 00396 CleanupStack::PushL(obj); \ 00397 obj->ConstructL(); \ 00398 return obj; \ 00399 } \ 00400 \ 00401 CSignalObserver* CSignalObserver::NewL() \ 00402 { \ 00403 CSignalObserver* obj = CSignalObserver::NewLC(); \ 00404 CleanupStack::Pop(obj); \ 00405 return obj; \ 00406 } \ 00407 \ 00408 CSignalObserver::CSignalObserver() \ 00409 {} 00410 /***end***/ 00411 00412 #define This CSignalObserver 00413 00414 NONSHARABLE_CLASS(This) : 00415 public CBase, 00416 public MGetterObs_SignalStrength, 00417 public MNotifyObs_SignalStrength, 00418 public MRetryAoObserver 00419 { 00420 CTOR_DECL_CSignalObserver; 00421 00422 public: 00423 ~CSignalObserver(); 00424 00425 private: 00426 virtual void RetryTimerExpired(CRetryAo* src, TInt errCode); 00427 virtual void GotData_SignalStrength(TInt aError); 00428 virtual void ChangedData_SignalStrength(TInt aError); 00429 void HandleSignal(TInt aError, TData_SignalStrength const & aData); 00430 00431 private: 00432 CRetryAo* iRetryAo; 00433 TBool iGetterDone; 00434 CGetterAo_SignalStrength* iGetter; 00435 CNotifyAo_SignalStrength* iNotifier; 00436 00437 private: 00438 void MakeRequest(); 00439 void Cancel(); 00440 00441 // Flight mode observation. 00442 private: 00443 bb_Closure iClosure; 00444 void BbRegisterL(); 00445 void BbUnregister(); 00446 TBool GetFlightMode(); 00447 public: 00448 void HandleFlightModeChange(); 00449 }; 00450 00451 CTOR_IMPL_CSignalObserver; 00452 00453 void This::MakeRequest() 00454 { 00455 if (iGetterDone) 00456 iNotifier->MakeRequest(); 00457 else 00458 iGetter->MakeRequest(); 00459 } 00460 00461 void This::Cancel() 00462 { 00463 iRetryAo->Cancel(); 00464 iNotifier->Cancel(); 00465 iGetter->Cancel(); 00466 00467 iRetryAo->ResetFailures(); 00468 00469 // Once we begin observing again, we want a reading immediately, 00470 // rather than waiting for a change in readings. 00471 iGetterDone = EFalse; 00472 } 00473 00474 static void SignalObserverFlightModeChanged 00475 (bb_Blackboard* bb, enum bb_DataType dt, 00476 gpointer data, int len, gpointer arg) 00477 { 00478 (void)dt; 00479 (void)len; 00480 This* self = (This*)arg; 00481 self->HandleFlightModeChange(); 00482 } 00483 00484 void This::HandleFlightModeChange() 00485 { 00486 TBool fm = GetFlightMode(); 00487 if (fm) { 00488 Cancel(); 00489 00490 // Notify with value +1 to indicate no signal. 00491 kr_Controller_set_signal_strength(ac_global_Controller, 1); 00492 } else { 00493 MakeRequest(); 00494 } 00495 } 00496 00497 TBool This::GetFlightMode() 00498 { 00499 // Initial value (internal). 00500 bb_Blackboard* bb = ac_global_Blackboard; 00501 bb_Board* bd = bb_Blackboard_board(bb); 00502 return bd->flightmode; 00503 } 00504 00505 void This::BbRegisterL() 00506 { 00507 // Closure init. 00508 iClosure.changed = SignalObserverFlightModeChanged; 00509 iClosure.arg = this; 00510 00511 // Registration proper. 00512 bb_Blackboard* bb = ac_global_Blackboard; 00513 if (!bb_Blackboard_register(bb, bb_dt_flightmode, iClosure, NULL)) 00514 User::LeaveNoMemory(); 00515 } 00516 00517 void This::BbUnregister() 00518 { 00519 bb_Blackboard_unregister(ac_global_Blackboard, iClosure); 00520 } 00521 00522 void This::ConstructL() 00523 { 00524 BbRegisterL(); 00525 00526 ac_AppContext* ac = ac_get_global_AppContext(); 00527 00528 iRetryAo = CRetryAo::NewL(*this, 20, 60); 00529 00530 iGetter = new (ELeave) CGetterAo_SignalStrength(ac_Telephony(ac), *this); 00531 iNotifier = new (ELeave) CNotifyAo_SignalStrength(ac_Telephony(ac), *this); 00532 00533 TBool fm = GetFlightMode(); 00534 if (!fm) { 00535 // We will not be getting any signal strength reading for as long 00536 // as flightmode is on. Makes sense. 00537 MakeRequest(); 00538 } 00539 } 00540 00541 This::~CSignalObserver() 00542 { 00543 BbUnregister(); 00544 delete iGetter; 00545 delete iNotifier; 00546 delete iRetryAo; 00547 } 00548 00549 void This::RetryTimerExpired(CRetryAo* src, TInt errCode) 00550 { 00551 (void)src; 00552 if (errCode) { 00553 LogDb* logDb = ac_global_LogDb; 00554 ex_dblog_fatal_error_msg(logDb, "retry timer error", errCode); 00555 } else { 00556 MakeRequest(); 00557 } 00558 } 00559 00560 void This::GotData_SignalStrength(TInt aError) 00561 { 00562 HandleSignal(aError, iGetter->Data()); 00563 if (!aError) 00564 iGetterDone = ETrue; 00565 } 00566 00567 void This::ChangedData_SignalStrength(TInt aError) 00568 { 00569 HandleSignal(aError, iNotifier->Data()); 00570 } 00571 00572 void This::HandleSignal(TInt aError, 00573 TData_SignalStrength const & aData) 00574 { 00575 LogDb* logDb = ac_global_LogDb; 00576 if (aError) { 00577 ex_dblog_error_msg(logDb, "signal strength query failure", aError, NULL); 00578 if (!iRetryAo->Retry()) { 00579 er_log_none(er_FATAL, "signal strength queries failing"); 00580 } 00581 } else { 00582 iRetryAo->ResetFailures(); 00583 00584 int dbm = -(aData.iSignalStrength); 00585 int bars = aData.iBar; 00586 guilogf("signal: %d dBm (%d bars)", dbm, bars); 00587 log_db_log_signal(logDb, dbm, bars, NULL); 00588 iNotifier->MakeRequest(); 00589 00590 // Notify interested parties. Indiscriminately, receiver must 00591 // check for duplicates. 00592 kr_Controller_set_signal_strength(ac_global_Controller, dbm); 00593 } 00594 } 00595 00596 #undef This 00597 00598 // -------------------------------------------------- 00599 // auxiliary controller 00600 // -------------------------------------------------- 00601 00602 struct _kr_PlatAo { 00603 CDiskObserver* iDiskObserver; 00604 CRegistrationObserver* iRegistrationObserver; 00605 CNetworkObserver* iNetworkObserver; 00606 CSignalObserver* iSignalObserver; 00607 CSmsTrigger* iSmsTrigger; 00608 }; 00609 00610 extern "C" kr_PlatAo* kr_PlatAo_new(GError** error) 00611 { 00612 ac_AppContext* ac = ac_get_global_AppContext(); 00613 00614 kr_PlatAo* self = g_try_new0(kr_PlatAo, 1); 00615 if (G_UNLIKELY(!self)) { 00616 if (error) *error = gx_error_no_memory; 00617 return NULL; 00618 } 00619 00620 TRAPD(errCode, self->iDiskObserver = CDiskObserver::NewL()); 00621 if (G_UNLIKELY(errCode)) { 00622 kr_PlatAo_destroy(self); 00623 if (error) 00624 *error = gx_error_new(domain_symbian, errCode, 00625 "disk observer creation failure: %s (%d)", 00626 plat_error_strerror(errCode), errCode); 00627 return NULL; 00628 } 00629 00630 TRAP(errCode, self->iRegistrationObserver = CRegistrationObserver::NewL()); 00631 if (G_UNLIKELY(errCode)) { 00632 kr_PlatAo_destroy(self); 00633 if (error) 00634 *error = gx_error_new(domain_symbian, errCode, 00635 "registration observer creation failure: %s (%d)", 00636 plat_error_strerror(errCode), errCode); 00637 return NULL; 00638 } 00639 00640 #if __CAN_GET_NETWORK_INFO__ 00641 TRAP(errCode, self->iNetworkObserver = CNetworkObserver::NewL()); 00642 if (G_UNLIKELY(errCode)) { 00643 kr_PlatAo_destroy(self); 00644 if (error) 00645 *error = gx_error_new(domain_symbian, errCode, 00646 "network observer creation failure: %s (%d)", 00647 plat_error_strerror(errCode), errCode); 00648 return NULL; 00649 } 00650 #endif 00651 00652 TRAP(errCode, self->iSignalObserver = CSignalObserver::NewL()); 00653 if (G_UNLIKELY(errCode)) { 00654 kr_PlatAo_destroy(self); 00655 if (error) 00656 *error = gx_error_new(domain_symbian, errCode, 00657 "signal strength observer creation failure: %s (%d)", 00658 plat_error_strerror(errCode), errCode); 00659 return NULL; 00660 } 00661 00662 #if __FEATURE_REMOKON__ 00663 TRAP(errCode, self->iSmsTrigger = CSmsTrigger::NewL(ac)); 00664 if (G_UNLIKELY(errCode)) { 00665 kr_PlatAo_destroy(self); 00666 if (error) 00667 *error = gx_error_new(domain_symbian, errCode, 00668 "SMS trigger observer creation failure: %s (%d)", 00669 plat_error_strerror(errCode), errCode); 00670 return NULL; 00671 } 00672 #endif 00673 00674 return self; 00675 } 00676 00677 extern "C" void kr_PlatAo_destroy(kr_PlatAo* self) 00678 { 00679 if (self) { 00680 #if __FEATURE_REMOKON__ 00681 delete self->iSmsTrigger; 00682 #endif 00683 delete self->iSignalObserver; 00684 delete self->iNetworkObserver; 00685 delete self->iRegistrationObserver; 00686 delete self->iDiskObserver; 00687 g_free(self); 00688 } 00689 } 00690 00691 /** 00692 00693 kr_plat_ao_epoc.cpp 00694 00695 Copyright 2009 Helsinki Institute for Information Technology (HIIT) 00696 and the authors. All rights reserved. 00697 00698 Authors: Tero Hasu <tero.hasu@hut.fi> 00699 00700 Permission is hereby granted, free of charge, to any person 00701 obtaining a copy of this software and associated documentation files 00702 (the "Software"), to deal in the Software without restriction, 00703 including without limitation the rights to use, copy, modify, merge, 00704 publish, distribute, sublicense, and/or sell copies of the Software, 00705 and to permit persons to whom the Software is furnished to do so, 00706 subject to the following conditions: 00707 00708 The above copyright notice and this permission notice shall be 00709 included in all copies or substantial portions of the Software. 00710 00711 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 00712 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00713 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00714 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 00715 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 00716 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 00717 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 00718 SOFTWARE. 00719 00720 **/
ContextLogger2—ContextLogger2 Logger Daemon Internals—Generated on Mon May 2 13:49:54 2011 by Doxygen 1.6.1