00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <Basics.H>
00025 #include <BufStream.H>
00026 #include <FS.H>
00027
00028 #include <iomanip>
00029
00030 #include "logging.H"
00031
00032 #include "lock_timing.H"
00033 #include "VRConcurrency.H"
00034
00035 #include <stdio.h>
00036 #include <sys/time.h>
00037 #include <assert.h>
00038
00039 using std::setw;
00040 using std::setfill;
00041 using Basics::OBufStream;
00042
00043
00044 extern ReadersWritersLock userGroup_lock;
00045
00046 #define TIMING_RECORDER_BUF_SIZE 32768
00047
00048 enum which_lock_t
00049 {
00050 stable,
00051 volatileRoot,
00052 userGroup
00053 };
00054
00055 class Lock_Timing_Recorder
00056 {
00057 private:
00058
00059 static Basics::mutex list_mu;
00060 static Lock_Timing_Recorder *list_head;
00061 Lock_Timing_Recorder *list_next;
00062
00063
00064
00065 Basics::mutex mu;
00066
00067
00068 unsigned long my_thread_index;
00069
00070
00071 FILE *timing_record_stream;
00072
00073
00074 unsigned long file_end_time;
00075
00076
00077 char write_buffer[TIMING_RECORDER_BUF_SIZE];
00078
00079
00080 unsigned int current_byte_count;
00081
00082
00083 bool stable_locked, volatileRoot_locked, userGroup_locked;
00084
00085
00086
00087
00088
00089 struct timeval stable_time, volatileRoot_time, userGroup_time;
00090
00091
00092 void record_delta(struct timeval *last_time);
00093
00094
00095 void start_new_file(struct timeval ¤t_time);
00096
00097
00098 void lock_data(which_lock_t lock,
00099 struct timeval *&last_time_p,
00100 bool *&locked_p,
00101 char &lock_marker);
00102
00103 void write_delta_record(char record_marker,
00104 char lock_marker,
00105 struct timeval *last_time_p);
00106
00107 public:
00108 Lock_Timing_Recorder();
00109 ~Lock_Timing_Recorder();
00110
00111 void acquire_read_start(which_lock_t lock);
00112
00113 void acquire_read_done(which_lock_t lock, bool failed = false);
00114
00115 void acquire_write_start(which_lock_t lock);
00116
00117 void acquire_write_done(which_lock_t lock, bool failed = false);
00118
00119 void release_start(which_lock_t lock);
00120
00121 void release_done(which_lock_t lock);
00122
00123 void locked_reason(which_lock_t lock, const char *reason);
00124
00125
00126
00127
00128 static void *new_file_check(void *arg);
00129 };
00130
00131 Basics::mutex Lock_Timing_Recorder::list_mu;
00132 Lock_Timing_Recorder *Lock_Timing_Recorder::list_head = 0;
00133
00134 static pthread_key_t lock_timing_key;
00135 static pthread_once_t lock_timing_once = PTHREAD_ONCE_INIT;
00136
00137
00138
00139
00140
00141 static bool recording_timing = false;
00142
00143 extern Basics::mutex popen_mu;
00144
00145 static unsigned int timing_file_minutes = 60;
00146
00147 extern "C"
00148 {
00149 static void lock_timing_cleanup(void *tsd) throw()
00150 {
00151 if(tsd != 0)
00152 {
00153 Lock_Timing_Recorder *recorder = (Lock_Timing_Recorder *) tsd;
00154
00155 delete recorder;
00156 }
00157 }
00158 }
00159
00160 #if !defined(__linux__)
00161
00162
00163
00164 static Basics::thread new_file_check_thread;
00165 #endif
00166
00167 extern "C"
00168 {
00169 static void lock_timing_init() throw()
00170 {
00171 int err = pthread_key_create(&lock_timing_key, lock_timing_cleanup);
00172 assert(err == 0);
00173
00174 try
00175 {
00176 Text unused;
00177 if(VestaConfig::get("Repository",
00178 "timing_file_minutes", unused))
00179 timing_file_minutes = VestaConfig::get_int("Repository",
00180 "timing_file_minutes");
00181 }
00182 catch (VestaConfig::failure f)
00183 {
00184 Repos::dprintf(DBG_ALWAYS,
00185 "VestaConfig::failure in VestaSourceServerExport: %s\n",
00186 f.msg.cchars());
00187 abort();
00188 }
00189
00190 #if !defined(__linux__)
00191
00192
00193
00194
00195
00196
00197 Basics::thread_attr new_file_check_attr;
00198 #if defined (_POSIX_THREAD_PRIORITY_SCHEDULING) && !defined(__linux__)
00199
00200 new_file_check_attr.set_schedpolicy(SCHED_RR);
00201 new_file_check_attr.set_inheritsched(PTHREAD_EXPLICIT_SCHED);
00202 new_file_check_attr.set_sched_priority(sched_get_priority_min(SCHED_RR));
00203 #endif
00204 new_file_check_thread.fork_and_detach(Lock_Timing_Recorder::new_file_check,
00205 0,
00206 new_file_check_attr);
00207 #endif
00208 }
00209 }
00210
00211 static Lock_Timing_Recorder *find_recorder(bool create = false)
00212 {
00213
00214 pthread_once(&lock_timing_once, lock_timing_init);
00215
00216
00217 Lock_Timing_Recorder *recorder =
00218 (Lock_Timing_Recorder *) pthread_getspecific(lock_timing_key);
00219 if((recorder == 0) && recording_timing && create)
00220 {
00221
00222
00223
00224 recorder = NEW(Lock_Timing_Recorder);
00225 }
00226
00227 return recorder;
00228 }
00229
00230 static bool determine_which_lock(ReadersWritersLock *lock_p,
00231 which_lock_t &lock)
00232 {
00233
00234 if(lock_p == &StableLock)
00235 {
00236 lock = stable;
00237 return true;
00238 }
00239 else if(lock_p == &VolatileRootLock)
00240 {
00241 lock = volatileRoot;
00242 return true;
00243 }
00244 else if(lock_p == &userGroup_lock)
00245 {
00246 lock = userGroup;
00247 return true;
00248 }
00249
00250
00251 return false;
00252 }
00253
00254 void rwlock_acquire_read_start(ReadersWritersLock *lock_p)
00255 {
00256
00257 which_lock_t lock;
00258 if(!determine_which_lock(lock_p, lock))
00259 return;
00260
00261
00262 Lock_Timing_Recorder *recorder = find_recorder(true);
00263
00264 if(recorder != 0)
00265 {
00266 recorder->acquire_read_start(lock);
00267 }
00268 }
00269
00270 void rwlock_acquire_read_done(ReadersWritersLock *lock_p, bool failed)
00271 {
00272
00273 which_lock_t lock;
00274 if(!determine_which_lock(lock_p, lock))
00275 return;
00276
00277
00278 Lock_Timing_Recorder *recorder = find_recorder();
00279
00280 if(recorder != 0)
00281 {
00282 recorder->acquire_read_done(lock, failed);
00283 }
00284 }
00285
00286 void rwlock_acquire_write_start(ReadersWritersLock *lock_p)
00287 {
00288
00289 which_lock_t lock;
00290 if(!determine_which_lock(lock_p, lock))
00291 return;
00292
00293
00294 Lock_Timing_Recorder *recorder = find_recorder(true);
00295
00296 if(recorder != 0)
00297 {
00298 recorder->acquire_write_start(lock);
00299 }
00300 }
00301
00302 void rwlock_acquire_write_done(ReadersWritersLock *lock_p,bool failed)
00303 {
00304
00305 which_lock_t lock;
00306 if(!determine_which_lock(lock_p, lock))
00307 return;
00308
00309
00310 Lock_Timing_Recorder *recorder = find_recorder();
00311
00312 if(recorder != 0)
00313 {
00314 recorder->acquire_write_done(lock, failed);
00315 }
00316 }
00317
00318 void rwlock_release_start(ReadersWritersLock *lock_p)
00319 {
00320
00321 which_lock_t lock;
00322 if(!determine_which_lock(lock_p, lock))
00323 return;
00324
00325
00326 Lock_Timing_Recorder *recorder = find_recorder();
00327
00328 if(recorder != 0)
00329 {
00330 recorder->release_start(lock);
00331 }
00332 }
00333
00334 void rwlock_release_done(ReadersWritersLock *lock_p)
00335 {
00336
00337 which_lock_t lock;
00338 if(!determine_which_lock(lock_p, lock))
00339 return;
00340
00341
00342 Lock_Timing_Recorder *recorder = find_recorder();
00343
00344 if(recorder != 0)
00345 {
00346 recorder->release_done(lock);
00347 }
00348 }
00349
00350 void rwlock_locked_reason(ReadersWritersLock *lock_p, const char *reason)
00351 {
00352
00353 which_lock_t lock;
00354 if(!determine_which_lock(lock_p, lock))
00355 return;
00356
00357
00358 Lock_Timing_Recorder *recorder = find_recorder();
00359
00360 if(recorder != 0)
00361 {
00362 recorder->locked_reason(lock, reason);
00363 }
00364 }
00365
00366 void rwlock_timing_control(bool enable)
00367 {
00368 recording_timing = enable;
00369 }
00370
00371 Lock_Timing_Recorder::Lock_Timing_Recorder()
00372 : current_byte_count(0), timing_record_stream(0),
00373 stable_locked(false), volatileRoot_locked(false), userGroup_locked(false),
00374 file_end_time(0), list_next(0)
00375 {
00376 pthread_once(&lock_timing_once, lock_timing_init);
00377
00378 stable_time.tv_sec = 0;
00379 stable_time.tv_usec = 0;
00380 volatileRoot_time.tv_sec = 0;
00381 volatileRoot_time.tv_usec = 0;
00382 userGroup_time.tv_sec = 0;
00383 userGroup_time.tv_usec = 0;
00384
00385
00386 #if defined(__linux__)
00387 my_thread_index = pthread_self()/1024;
00388 #elif defined(__osf__)
00389 my_thread_index = pthread_getsequence_np(pthread_self());
00390 #else
00391 #error Need way to get thread index for this platform
00392 #endif
00393
00394
00395 assert(pthread_getspecific(lock_timing_key) == 0);
00396
00397
00398 int err = pthread_setspecific(lock_timing_key, (void *) this);
00399 assert(err == 0);
00400
00401
00402 Lock_Timing_Recorder::list_mu.lock();
00403 this->list_next = Lock_Timing_Recorder::list_head;
00404 Lock_Timing_Recorder::list_head = this;
00405 Lock_Timing_Recorder::list_mu.unlock();
00406 }
00407
00408 void Lock_Timing_Recorder::start_new_file(struct timeval ¤t_time)
00409 {
00410
00411 if(timing_record_stream != 0)
00412 {
00413 fflush(timing_record_stream);
00414 popen_mu.lock();
00415 pclose(timing_record_stream);
00416 popen_mu.unlock();
00417 }
00418
00419
00420
00421
00422
00423 struct tm time_detail;
00424 if(file_end_time == 0)
00425 {
00426 localtime_r(&(current_time.tv_sec), &time_detail);
00427 time_detail.tm_sec = 0;
00428 time_detail.tm_min -= (time_detail.tm_min%timing_file_minutes);
00429 }
00430
00431 else
00432 {
00433 time_t file_label_time = file_end_time;
00434 localtime_r(&file_label_time, &time_detail);
00435 }
00436
00437
00438
00439 OBufStream l_dirname;
00440 l_dirname << "timings."
00441 << (time_detail.tm_year+1900) << "-"
00442 << setw(2) << setfill('0') << (time_detail.tm_mon + 1) << "-"
00443 << setw(2) << setfill('0') << time_detail.tm_mday;
00444 if(!FS::Exists(l_dirname.str()))
00445 {
00446 mkdir(l_dirname.str(), 0755);
00447 }
00448
00449
00450
00451 OBufStream l_cmd;
00452 l_cmd << "exec gzip - > " << l_dirname.str()
00453 << "/rwlocks.pid_" << getpid()
00454 << ".thread_" << my_thread_index
00455 << "."
00456 << setw(2) << setfill('0') << time_detail.tm_hour << "_"
00457 << setw(2) << setfill('0') << time_detail.tm_min;
00458 popen_mu.lock();
00459 timing_record_stream = popen(l_cmd.str(), "w");
00460 popen_mu.unlock();
00461 assert(timing_record_stream != 0);
00462
00463
00464
00465 file_end_time = mktime(&time_detail) + 60*timing_file_minutes;
00466 }
00467
00468 Lock_Timing_Recorder::~Lock_Timing_Recorder()
00469 {
00470 if(timing_record_stream != 0)
00471 {
00472 fflush(timing_record_stream);
00473 popen_mu.lock();
00474 pclose(timing_record_stream);
00475 popen_mu.unlock();
00476 }
00477
00478
00479 Lock_Timing_Recorder::list_mu.lock();
00480 Lock_Timing_Recorder **points_to_me = &Lock_Timing_Recorder::list_head;
00481 while((*points_to_me != this) &&
00482 (*points_to_me != 0))
00483 {
00484 points_to_me = &((*points_to_me)->list_next);
00485 }
00486 if(*points_to_me == this)
00487 {
00488 *points_to_me = this->list_next;
00489 }
00490 Lock_Timing_Recorder::list_mu.unlock();
00491
00492 }
00493
00494 void Lock_Timing_Recorder::lock_data(which_lock_t lock,
00495 struct timeval *&last_time_p,
00496 bool *&locked_p,
00497 char &lock_marker)
00498 {
00499 last_time_p = 0;
00500 locked_p = 0;
00501 lock_marker = 0;
00502
00503
00504 switch(lock)
00505 {
00506 case stable:
00507 last_time_p = &(this->stable_time);
00508 locked_p = &(this->stable_locked);
00509 lock_marker = 1;
00510 break;
00511 case volatileRoot:
00512 last_time_p = &(this->volatileRoot_time);
00513 locked_p = &(this->volatileRoot_locked);
00514 lock_marker = 2;
00515 break;
00516 case userGroup:
00517 last_time_p = &(this->userGroup_time);
00518 locked_p = &(this->userGroup_locked);
00519 lock_marker = 3;
00520 break;
00521 }
00522 assert(last_time_p != 0);
00523 assert(locked_p != 0);
00524 assert(lock_marker != 0);
00525 }
00526
00527 #define USECS_PER_SEC 1000000
00528
00529 static struct timeval delta_time(const struct timeval &time_a,
00530 const struct timeval &time_b)
00531 {
00532 struct timeval result;
00533
00534 if(time_a.tv_sec == time_b.tv_sec)
00535 {
00536 result.tv_sec = 0;
00537
00538 result.tv_usec = ((time_b.tv_usec >= time_a.tv_usec)
00539 ? time_b.tv_usec - time_a.tv_usec
00540 : 0);
00541 }
00542 else if(time_b.tv_sec > time_a.tv_sec)
00543 {
00544 result.tv_sec = (time_b.tv_sec - time_a.tv_sec) - 1;
00545 result.tv_usec = (time_b.tv_usec + USECS_PER_SEC) - time_a.tv_usec;
00546 if(result.tv_usec > USECS_PER_SEC)
00547 {
00548 result.tv_sec += result.tv_usec/USECS_PER_SEC;
00549 result.tv_usec %= USECS_PER_SEC;
00550 }
00551 }
00552 else
00553 {
00554
00555 result.tv_sec = 0;
00556 result.tv_usec = 0;
00557 }
00558
00559 return result;
00560 }
00561
00562 void Lock_Timing_Recorder::record_delta(struct timeval *last_time)
00563 {
00564
00565 struct timeval current_time;
00566 struct timezone unused_tz;
00567 int err = gettimeofday(¤t_time, &unused_tz);
00568 assert(err == 0);
00569
00570
00571 struct timeval delta = delta_time(*last_time, current_time);
00572
00573
00574 unsigned short sec_delta = delta.tv_sec;
00575 assert(sec_delta == delta.tv_sec);
00576 memcpy(&(write_buffer[current_byte_count]),
00577 (void *) &sec_delta, sizeof(unsigned short));
00578 assert(sizeof(unsigned short) == 2);
00579 current_byte_count += sizeof(unsigned short);
00580
00581
00582 unsigned int usec_delta = delta.tv_usec;
00583 memcpy(&(write_buffer[current_byte_count]),
00584 (void *) &usec_delta, sizeof(unsigned int));
00585 assert(sizeof(unsigned int) == 4);
00586 current_byte_count += sizeof(unsigned int);
00587
00588
00589
00590 *last_time = current_time;
00591 }
00592
00593 void Lock_Timing_Recorder::write_delta_record(char record_marker,
00594 char lock_marker,
00595 struct timeval *last_time_p)
00596 {
00597
00598 write_buffer[current_byte_count++] = lock_marker;
00599
00600
00601
00602 write_buffer[current_byte_count++] = record_marker;
00603
00604
00605 record_delta(last_time_p);
00606
00607
00608 assert(current_byte_count < TIMING_RECORDER_BUF_SIZE);
00609 }
00610
00611 void Lock_Timing_Recorder::acquire_read_start(which_lock_t lock)
00612 {
00613 this->mu.lock();
00614
00615 struct timeval *last_time_p;
00616 bool *locked_p;
00617 char lock_marker;
00618
00619
00620 if(!recording_timing)
00621 {
00622 this->mu.unlock();
00623 return;
00624 }
00625
00626
00627 lock_data(lock, last_time_p, locked_p, lock_marker);
00628
00629
00630 assert(!(*locked_p));
00631
00632
00633 struct timezone unused_tz;
00634 int err = gettimeofday(last_time_p, &unused_tz);
00635 assert(err == 0);
00636
00637
00638 if((timing_record_stream == 0) || (last_time_p->tv_sec >= file_end_time))
00639 {
00640 start_new_file(*last_time_p);
00641
00642
00643
00644 err = gettimeofday(last_time_p, &unused_tz);
00645 assert(err == 0);
00646 }
00647
00648
00649
00650
00651
00652
00653 write_buffer[current_byte_count++] = lock_marker;
00654
00655
00656 write_buffer[current_byte_count++] = 1;
00657
00658
00659 unsigned int start_sec = last_time_p->tv_sec;
00660 memcpy(&(write_buffer[current_byte_count]), (void *) &start_sec,
00661 sizeof(unsigned int));
00662 current_byte_count += sizeof(unsigned int);
00663
00664
00665 unsigned int start_usec = last_time_p->tv_usec;
00666 memcpy(&(write_buffer[current_byte_count]), (void *) &start_usec,
00667 sizeof(unsigned int));
00668 current_byte_count += sizeof(unsigned int);
00669
00670
00671 assert(current_byte_count < TIMING_RECORDER_BUF_SIZE);
00672
00673 this->mu.unlock();
00674 }
00675
00676 void Lock_Timing_Recorder::acquire_read_done(which_lock_t lock,
00677 bool failed)
00678 {
00679 this->mu.lock();
00680
00681
00682
00683 if(current_byte_count == 0)
00684 {
00685 this->mu.unlock();
00686 return;
00687 }
00688
00689 struct timeval *last_time_p;
00690 bool *locked_p;
00691 char lock_marker;
00692
00693
00694 lock_data(lock, last_time_p, locked_p, lock_marker);
00695
00696
00697
00698 if(last_time_p->tv_sec == 0)
00699 {
00700 this->mu.unlock();
00701 return;
00702 }
00703
00704
00705 assert(!(*locked_p));
00706 *locked_p = true;
00707
00708
00709
00710 write_delta_record(failed ? 3 : 2,
00711 lock_marker,
00712 last_time_p);
00713
00714 this->mu.unlock();
00715 }
00716
00717 void Lock_Timing_Recorder::acquire_write_start(which_lock_t lock)
00718 {
00719 this->mu.lock();
00720
00721 struct timeval *last_time_p;
00722 bool *locked_p;
00723 char lock_marker;
00724
00725
00726 if(!recording_timing)
00727 {
00728 this->mu.unlock();
00729 return;
00730 }
00731
00732
00733 lock_data(lock, last_time_p, locked_p, lock_marker);
00734
00735
00736 assert(!(*locked_p));
00737
00738
00739 struct timezone unused_tz;
00740 int err = gettimeofday(last_time_p, &unused_tz);
00741 assert(err == 0);
00742
00743
00744 if((timing_record_stream == 0) || (last_time_p->tv_sec >= file_end_time))
00745 {
00746 start_new_file(*last_time_p);
00747
00748
00749
00750 err = gettimeofday(last_time_p, &unused_tz);
00751 assert(err == 0);
00752 }
00753
00754
00755
00756
00757
00758
00759 write_buffer[current_byte_count++] = lock_marker;
00760
00761
00762 write_buffer[current_byte_count++] = 4;
00763
00764
00765 unsigned int start_sec = last_time_p->tv_sec;
00766 memcpy(&(write_buffer[current_byte_count]), (void *) &start_sec,
00767 sizeof(unsigned int));
00768 current_byte_count += sizeof(unsigned int);
00769
00770
00771 unsigned int start_usec = last_time_p->tv_usec;
00772 memcpy(&(write_buffer[current_byte_count]), (void *) &start_usec,
00773 sizeof(unsigned int));
00774 current_byte_count += sizeof(unsigned int);
00775
00776
00777 assert(current_byte_count < TIMING_RECORDER_BUF_SIZE);
00778
00779 this->mu.unlock();
00780 }
00781
00782 void Lock_Timing_Recorder::acquire_write_done(which_lock_t lock,
00783 bool failed)
00784 {
00785 this->mu.lock();
00786
00787
00788
00789 if(current_byte_count == 0)
00790 {
00791 this->mu.unlock();
00792 return;
00793 }
00794
00795 struct timeval *last_time_p;
00796 bool *locked_p;
00797 char lock_marker;
00798
00799
00800 lock_data(lock, last_time_p, locked_p, lock_marker);
00801
00802
00803
00804 if(last_time_p->tv_sec == 0)
00805 {
00806 this->mu.unlock();
00807 return;
00808 }
00809
00810
00811 assert(!(*locked_p));
00812 *locked_p = true;
00813
00814
00815
00816 write_delta_record(failed ? 6 : 5,
00817 lock_marker,
00818 last_time_p);
00819
00820 this->mu.unlock();
00821 }
00822
00823 void Lock_Timing_Recorder::release_start(which_lock_t lock)
00824 {
00825 this->mu.lock();
00826
00827
00828
00829 if(current_byte_count == 0)
00830 {
00831 this->mu.unlock();
00832 return;
00833 }
00834
00835 struct timeval *last_time_p;
00836 bool *locked_p;
00837 char lock_marker;
00838
00839
00840 lock_data(lock, last_time_p, locked_p, lock_marker);
00841
00842
00843
00844 if(!*locked_p)
00845 {
00846 this->mu.unlock();
00847 return;
00848 }
00849
00850
00851 write_delta_record(7,
00852 lock_marker,
00853 last_time_p);
00854
00855 this->mu.unlock();
00856 }
00857
00858 void Lock_Timing_Recorder::release_done(which_lock_t lock)
00859 {
00860 this->mu.lock();
00861
00862
00863
00864 if(current_byte_count == 0)
00865 {
00866 this->mu.unlock();
00867 return;
00868 }
00869
00870 struct timeval *last_time_p;
00871 bool *locked_p;
00872 char lock_marker;
00873
00874
00875 lock_data(lock, last_time_p, locked_p, lock_marker);
00876
00877
00878
00879 if(!*locked_p)
00880 {
00881 this->mu.unlock();
00882 return;
00883 }
00884
00885
00886 *locked_p = false;
00887
00888
00889 write_delta_record(8,
00890 lock_marker,
00891 last_time_p);
00892
00893
00894 last_time_p->tv_sec = 0;
00895 last_time_p->tv_usec = 0;
00896
00897
00898
00899 if(!stable_locked && !volatileRoot_locked && !userGroup_locked)
00900 {
00901
00902 size_t written = fwrite(write_buffer, current_byte_count, 1,
00903 timing_record_stream);
00904 assert(written == 1);
00905 fflush(timing_record_stream);
00906
00907
00908 current_byte_count = 0;
00909 }
00910
00911 this->mu.unlock();
00912 }
00913
00914 void Lock_Timing_Recorder::locked_reason(which_lock_t lock,
00915 const char *reason)
00916 {
00917 this->mu.lock();
00918
00919
00920
00921 if(current_byte_count == 0)
00922 {
00923 this->mu.unlock();
00924 return;
00925 }
00926
00927 struct timeval *last_time_p;
00928 bool *locked_p;
00929 char lock_marker;
00930
00931
00932 lock_data(lock, last_time_p, locked_p, lock_marker);
00933
00934
00935
00936 if(!*locked_p)
00937 {
00938 this->mu.unlock();
00939 return;
00940 }
00941
00942
00943
00944
00945
00946
00947 write_buffer[current_byte_count++] = lock_marker;
00948
00949
00950 write_buffer[current_byte_count++] = 9;
00951
00952
00953 strcpy(&(write_buffer[current_byte_count]), reason);
00954 current_byte_count += strlen(reason)+1;
00955
00956
00957 assert(current_byte_count < TIMING_RECORDER_BUF_SIZE);
00958
00959 this->mu.unlock();
00960 }
00961
00962 void *Lock_Timing_Recorder::new_file_check(void *arg)
00963 {
00964
00965
00966
00967 unsigned int to_sleep = timing_file_minutes * 15;
00968 while(to_sleep > 0)
00969 to_sleep = sleep(to_sleep);
00970
00971 while(1)
00972 {
00973
00974
00975
00976
00977 to_sleep = timing_file_minutes * 30;
00978 while(to_sleep > 0)
00979 to_sleep = sleep(to_sleep);
00980
00981
00982 struct timeval current_time;
00983 struct timezone unused_tz;
00984 int err = gettimeofday(¤t_time, &unused_tz);
00985 assert(err == 0);
00986
00987
00988 Lock_Timing_Recorder::list_mu.lock();
00989 Lock_Timing_Recorder *cur = Lock_Timing_Recorder::list_head;
00990 while(cur != 0)
00991 {
00992 cur->mu.lock();
00993
00994
00995
00996 if((cur->timing_record_stream != 0) &&
00997 !cur->stable_locked && !cur->volatileRoot_locked && !cur->userGroup_locked &&
00998 (current_time.tv_sec > cur->file_end_time))
00999 {
01000 cur->start_new_file(current_time);
01001 }
01002 cur->mu.unlock();
01003
01004
01005 cur = cur->list_next;
01006 }
01007 Lock_Timing_Recorder::list_mu.unlock();
01008 }
01009
01010
01011 return 0;
01012 }