Changeset 232 for Evidence/Evidence.cc
- Timestamp:
- 06/30/10 08:48:02 (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
Evidence/Evidence.cc
r231 r232 17 17 These signals will then cause pause() to return which can be used 18 18 by the application to terminate gracefully. 19 - The static method ToString() converts the contents of a DIM Infoservice into text19 - The static method ToString() converts the contents of a DIM service into text 20 20 - A terminate-handler is installed for catching unhandled C++ exceptions. 21 21 … … 27 27 using namespace std; 28 28 29 EvidenceServer *ThisServer;30 31 29 // 32 30 // Internal configuration class of EvidenceServer 33 31 // 34 // Data that might be accessed by two threads are protected by mutex35 32 36 33 // Constructor … … 38 35 39 36 // Initialise 40 int Ret;41 if ((Ret = pthread_mutex_init(&Mutex, NULL)) != 0) {42 ThisServer->Message(ThisServer->FATAL, "pthread_mutex_init() failed in Config constructor (%s)", strerror(Ret));43 }44 37 CurrentItem = string(); 45 38 ConfigTimeStamp = 0; 46 47 // Signal delivered to this thread if configuration file changes48 39 ThreadID = pthread_self(); 49 40 … … 56 47 57 48 delete Service; 58 59 int Ret;60 if ((Ret = pthread_mutex_destroy(&Mutex)) != 0) {61 ThisServer->Message(ThisServer->ERROR, "pthread_mutex_destroy() failed in Config destructor (%s)", strerror(Ret));62 }63 49 } 64 50 … … 66 52 void EvidenceServer::Config::infoHandler() { 67 53 68 Lock();54 This->Lock(); 69 55 ConfigTimeStamp = getInfo()->getInt(); 70 Unlock();71 72 if (pthread_kill(ThreadID, This Server->ConfigSignal) != 0) {73 This Server->Message(ThisServer->WARN, "Could not send signal to main thread");56 This->Unlock(); 57 58 if (pthread_kill(ThreadID, This->ConfigSignal) != 0) { 59 This->Message(WARN, "Could not send signal to main thread"); 74 60 } 75 61 } … … 78 64 void EvidenceServer::Config::rpcInfoHandler(){ 79 65 80 Lock();66 This->Lock(); 81 67 // Update map 82 68 List[CurrentItem].Value = string(getString(), getSize()-1); … … 84 70 // Clear to allow new rpc call 85 71 CurrentItem.clear(); 86 Unlock();72 This->Unlock(); 87 73 } 88 74 … … 93 79 94 80 // If up-to-date data in configuration list available, return this 95 Lock();81 This->Lock(); 96 82 if ((List.count(Item) > 0) && (List[Item].Time >= ConfigTimeStamp)) Result = List[Item].Value; 97 Unlock();83 This->Unlock(); 98 84 if (!Result.empty()) return Result; 99 85 … … 106 92 if (!EvidenceServer::ServiceOK(&Config)) { 107 93 if (Default.empty()) { 108 This Server->Message(ThisServer->FATAL, "Configuration server unreachable, can't retrieve '%s'", Item.c_str());94 This->Message(FATAL, "Configuration server unreachable, can't retrieve '%s'", Item.c_str()); 109 95 } 110 96 else Result = Default; … … 117 103 // Update configuration map 118 104 if (!Result.empty()) { 119 Lock();105 This->Lock(); 120 106 List[Item].Value = Result; 121 107 List[Item].Time = ConfigTimeStamp; 122 Unlock();108 This->Unlock(); 123 109 } 124 110 } 125 111 126 // Non-blocking configuration request fro other threads112 // Non-blocking configuration request from other threads 127 113 if (pthread_self() != ThreadID) { 128 Lock();114 This->Lock(); 129 115 if (List.count(Item) > 0) { 130 116 // New request possible only when answer to previous request received … … 136 122 // Return current value 137 123 Result = List[Item].Value; 138 Unlock();124 This->Unlock(); 139 125 } 140 126 } 141 127 142 128 return Result; 143 }144 145 // Locking and unlocking for list access146 // Signal blocked before locking to avaoid dead-lock by calling GetConfig() from ConfigChanged().147 void EvidenceServer::Config::Lock() {148 149 int Ret = 0;150 sigset_t Set;151 152 if (ThisServer->ConfigSignal != 0) {153 Ret += abs(sigemptyset(&Set));154 Ret += abs(sigaddset(&Set, ThisServer->ConfigSignal));155 Ret += abs(pthread_sigmask(SIG_BLOCK, &Set, NULL));156 }157 Ret += abs(pthread_mutex_lock(&Mutex));158 159 if (Ret != 0) {160 ThisServer->Message(ThisServer->FATAL, "Thread related call failed in Config::Lock()");161 }162 }163 164 void EvidenceServer::Config::Unlock() {165 166 int Ret = 0;167 sigset_t Set;168 169 Ret += abs(pthread_mutex_unlock(&Mutex));170 if (ThisServer->ConfigSignal != 0) {171 Ret += abs(sigemptyset(&Set));172 Ret += abs(sigaddset(&Set, ThisServer->ConfigSignal));173 Ret += abs(pthread_sigmask(SIG_UNBLOCK, &Set, NULL));174 }175 176 if (Ret != 0) {177 ThisServer->Message(ThisServer->FATAL, "Thread related call failed in Config::Unlock()");178 }179 129 } 180 130 … … 185 135 186 136 int EvidenceServer::ConfigSignal = 0; 137 EvidenceServer *EvidenceServer::This = NULL; 187 138 188 139 // Constructor starts server with given name … … 193 144 MessageData = NULL; 194 145 ExitRequest = false; 195 ThisServer = this; 146 This = this; 147 148 // Initialise mutex 149 int Ret; 150 pthread_mutexattr_t Attr; 151 152 if ((Ret = pthread_mutexattr_settype(&Attr, PTHREAD_MUTEX_ERRORCHECK)) != 0) { 153 Message(FATAL, "pthread_mutex_settype() failed (%s)", strerror(Ret)); 154 } 155 if ((Ret = pthread_mutex_init(&Mutex, &Attr)) != 0) { 156 Message(FATAL, "pthread_mutex_init() failed (%s)", strerror(Ret)); 157 } 196 158 197 159 // Catch some signals … … 225 187 delete ConfClass; 226 188 delete MessageService; 227 delete MessageData; 189 delete[] MessageData; 190 191 int Ret; 192 if ((Ret = pthread_mutex_destroy(&Mutex)) != 0) { 193 Message(ERROR, "pthread_mutex_destroy() failed (%s)", strerror(Ret)); 194 } 228 195 } 229 196 … … 270 237 MessageService->updateService(NewMsg, sizeof(struct Message)+strlen(NewMsg->Text)+1); 271 238 } 272 delete MessageData;239 delete[] MessageData; 273 240 MessageData = NewMsg; 274 241 … … 311 278 } 312 279 313 // Signal emitted when configuraton file changes, signal handler calls ConfigChanged() 280 281 // Set signal emitted when configuraton file changes, signal handler calls ConfigChanged() 314 282 void EvidenceServer::ActivateSignal(int Signal) { 315 283 … … 323 291 324 292 293 // Locking and unlocking for list access 294 // Signal blocked before locking to avoid dead-lock by calling GetConfig() from ConfigChanged(). 295 void EvidenceServer::Lock() { 296 297 int Ret; 298 sigset_t Set; 299 300 if (ConfigSignal != 0) { 301 Ret = abs(sigemptyset(&Set)); 302 Ret += abs(sigaddset(&Set, ConfigSignal)); 303 Ret += abs(pthread_sigmask(SIG_BLOCK, &Set, NULL)); 304 305 if (Ret != 0) Message(FATAL, "Signal masking failed in Lock()"); 306 } 307 308 if ((Ret = pthread_mutex_lock(&Mutex)) != 0) { 309 Message(FATAL, "pthread_mutex_lock() failed in Lock() (%s)", strerror(Ret)); 310 } 311 } 312 313 void EvidenceServer::Unlock() { 314 315 int Ret; 316 sigset_t Set; 317 318 if ((Ret = pthread_mutex_unlock(&Mutex)) != 0) { 319 Message(FATAL, "pthread_mutex_unlock() failed in Unlock() (%s)", strerror(Ret)); 320 } 321 322 if (ConfigSignal != 0) { 323 Ret = abs(sigemptyset(&Set)); 324 Ret += abs(sigaddset(&Set, ConfigSignal)); 325 Ret += abs(pthread_sigmask(SIG_UNBLOCK, &Set, NULL)); 326 327 if (Ret != 0) Message(FATAL, "Signal unmasking failed in Unlock()"); 328 } 329 } 330 331 325 332 // ====== Static methods ====== 326 333 … … 332 339 // If signal indicates configuration change, invoke call-back 333 340 if (Signal == EvidenceServer::ConfigSignal) { 334 This Server->ConfigChanged();341 This->ConfigChanged(); 335 342 return; 336 343 } … … 339 346 if (!Called) { 340 347 Called = true; 341 This Server->ExitRequest = true;348 This->ExitRequest = true; 342 349 return; 343 350 } 344 351 345 352 // If invoked twice, call exit() 346 This Server->Message(ThisServer->WARN, "Signal handler called again, invoking exit() (signal %d)", Signal);353 This->Message(WARN, "Signal handler called again, invoking exit() (signal %d)", Signal); 347 354 exit(EXIT_FAILURE); 348 355 } … … 355 362 356 363 if (Terminating) { 357 Msg << This Server->Name << ": Terminate() called recursively, calling abort()";364 Msg << This->Name << ": Terminate() called recursively, calling abort()"; 358 365 printf("%s\n", Msg.str().c_str()); 359 This Server->SendToLog(Msg.str().c_str());366 This->SendToLog(Msg.str().c_str()); 360 367 abort(); 361 368 } … … 383 390 else Msg << "Terminate() called without an active exception"; 384 391 385 This Server->Message(FATAL, Msg.str().c_str());386 } 387 388 389 // Translates DIM Info safely to string (assures no inivalid memory accesses are made)390 string EvidenceServer::ToString( DimInfo *I) {392 This->Message(FATAL, Msg.str().c_str()); 393 } 394 395 396 // Translates DIM data safely to string (assures no invalid memory accesses are made) 397 string EvidenceServer::ToString(char *Format, void *Data, int Size) { 391 398 392 399 ostringstream Text; 393 400 394 // Safety check395 if (I->getSize() < 1) return string();396 397 401 // 'Message' service format handled here 398 if (strcmp( I->getFormat(), "I:1;C") == 0 && I->getSize()>=(int) sizeof(struct Message)) {399 struct Message *Msg = (struct Message *) I->getData();402 if (strcmp(Format, "I:1;C") == 0 && Size >= (int) sizeof(struct Message)) { 403 struct Message *Msg = (struct Message *) Data; 400 404 // Safely extract string and limit to length of C string (padding might make it longer) 401 string MsgText(Msg->Text, I->getSize()-sizeof(struct Message)); 402 //MsgText.erase(strlen(MsgText.c_str())); 405 string MsgText(Msg->Text, Size-sizeof(struct Message)); 403 406 Text << Msg->Severity << " " << MsgText.erase(strlen(MsgText.c_str())); 404 407 … … 407 410 408 411 // Structure: print hex representation 409 if (strlen( I->getFormat()) != 1) {410 for (int i=0; i< I->getSize(); i++) {411 Text << setw(2) << hex << *((char *) I->getData()+ i) << " ";412 if (strlen(Format) != 1) { 413 for (int i=0; i<Size; i++) { 414 Text << setw(2) << hex << *((char *) Data + i) << " "; 412 415 } 413 416 return Text.str(); … … 415 418 416 419 // String if format "C" and terminated with \0 417 if (strcmp(I->getFormat(),"C")==0 && *((char *) I->getData()+I->getSize()-1)=='\0') { 418 Text << I->getString(); 419 return Text.str(); 420 if (strcmp(Format, "C") == 0 && Size > 0 && *((char *) Data+Size-1)=='\0') { 421 return string((char *) Data); 420 422 } 421 423 422 424 // Number array 423 int Size;424 switch (* (I->getFormat())) {425 case 'C': Size = sizeof(char); break;425 int ElementSize; 426 switch (*Format) { 427 case 'C': ElementSize = sizeof(char); break; 426 428 case 'I': 427 case 'L': Size = sizeof(int); break;428 case 'S': Size = sizeof(short); break;429 case 'F': Size = sizeof(float); break;430 case 'D': Size = sizeof(double);break;431 case 'X': Size = sizeof(long long); break;429 case 'L': ElementSize = sizeof(int); break; 430 case 'S': ElementSize = sizeof(short); break; 431 case 'F': ElementSize = sizeof(float); break; 432 case 'D': ElementSize = sizeof(double); break; 433 case 'X': ElementSize = sizeof(long long); break; 432 434 default: return string(); 433 435 } 434 436 435 for (int i=0; i< I->getSize()/Size; i++) {437 for (int i=0; i<Size/ElementSize; i++) { 436 438 // Space between entries 437 439 if (i != 0) Text << " "; 438 440 439 441 // Translate data 440 switch (*(I->getFormat())) { 441 case 'C': Text << *((char *) I->getData() + i); 442 break; 442 switch (*Format) { 443 case 'C': Text << *((char *) Data + i); break; 443 444 case 'I': 444 case 'L': Text << *((int *) I->getData() + i); 445 break; 446 case 'S': Text << *((short *) I->getData() + i); 447 break; 448 case 'F': Text << *((float *) I->getData() + i); 449 break; 450 case 'D': Text << *((double *) I->getData() + i); 451 break; 452 case 'X': Text << *((long long *) I->getData() + i); 453 break; 445 case 'L': Text << *((int *) Data + i); break; 446 case 'S': Text << *((short *) Data + i); break; 447 case 'F': Text << *((float *) Data + i); break; 448 case 'D': Text << *((double *) Data + i); break; 449 case 'X': Text << *((long long *) Data + i); break; 454 450 } 455 451 }
Note:
See TracChangeset
for help on using the changeset viewer.