00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107 #include "TROOT.h"
00108 #include "TUUID.h"
00109 #include "TError.h"
00110 #include "TSystem.h"
00111 #include "TInetAddress.h"
00112 #include "TMD5.h"
00113 #include "Bytes.h"
00114 #include <string.h>
00115 #include <stdlib.h>
00116 #ifdef R__WIN32
00117 #include "Windows4Root.h"
00118 #include <Iphlpapi.h>
00119 #else
00120 #include <unistd.h>
00121 #include <sys/time.h>
00122 #if defined(R__LINUX) && !defined(R__WINGCC)
00123 #include <sys/sysinfo.h>
00124 #endif
00125 #endif
00126
00127
00128 ClassImp(TUUID)
00129
00130
00131 TUUID::TUUID()
00132 {
00133
00134
00135 static uuid_time_t time_last;
00136 static UShort_t clockseq;
00137 static Bool_t firstTime = kTRUE;
00138 if (firstTime) {
00139 if (gSystem) {
00140
00141 UInt_t seed = (UInt_t) (Long64_t(gSystem->Now()) + gSystem->GetPid());
00142 #ifdef R__WIN32
00143 srand(seed);
00144 #else
00145 srandom(seed);
00146 #endif
00147 }
00148 GetCurrentTime(&time_last);
00149 #ifdef R__WIN32
00150 clockseq = 1+(UShort_t)(65536*rand()/(RAND_MAX+1.0));
00151 #else
00152 clockseq = 1+(UShort_t)(65536*random()/(RAND_MAX+1.0));
00153 #endif
00154 firstTime = kFALSE;
00155 }
00156
00157 uuid_time_t timestamp;
00158
00159
00160 GetCurrentTime(×tamp);
00161
00162
00163 if (CmpTime(×tamp, &time_last) == -1) {
00164 clockseq = (clockseq + 1) & 0x3FFF;
00165 if (clockseq == 0) clockseq++;
00166 }
00167
00168 Format(clockseq, timestamp);
00169
00170 time_last = timestamp;
00171 fUUIDIndex = 1<<30;
00172 }
00173
00174
00175 TUUID::~TUUID()
00176 {
00177
00178
00179
00180 }
00181
00182
00183 Int_t TUUID::CmpTime(uuid_time_t *t1, uuid_time_t *t2)
00184 {
00185
00186
00187 if (t1->high < t2->high) return -1;
00188 if (t1->high > t2->high) return 1;
00189 if (t1->low < t2->low) return -1;
00190 if (t1->low > t2->low) return 1;
00191 return 0;
00192 }
00193
00194
00195 void TUUID::SetFromString(const char *uuid)
00196 {
00197
00198
00199
00200
00201 Long_t timeLo;
00202 int timeMid;
00203 int timeHiAndVersion;
00204 int clockSeqHiAndRes;
00205 int clockSeqLo;
00206 int node[6];
00207
00208 sscanf(uuid, "%8lx-%4x-%4x-%2x%2x-%2x%2x%2x%2x%2x%2x",
00209 &timeLo,
00210 &timeMid,
00211 &timeHiAndVersion,
00212 &clockSeqHiAndRes,
00213 &clockSeqLo,
00214 &node[0], &node[1], &node[2], &node[3], &node[4], &node[5]);
00215
00216
00217
00218 fTimeLow = (UInt_t) timeLo;
00219 fTimeMid = (UShort_t) timeMid;
00220 fTimeHiAndVersion = (UShort_t) timeHiAndVersion;
00221 fClockSeqHiAndReserved = (UChar_t) clockSeqHiAndRes;
00222 fClockSeqLow = (UChar_t) clockSeqLo;
00223 fNode[0] = (UChar_t) node[0];
00224 fNode[1] = (UChar_t) node[1];
00225 fNode[2] = (UChar_t) node[2];
00226 fNode[3] = (UChar_t) node[3];
00227 fNode[4] = (UChar_t) node[4];
00228 fNode[5] = (UChar_t) node[5];
00229 fUUIDIndex = 1<<30;
00230 }
00231
00232
00233 TUUID::TUUID(const char *uuid)
00234 {
00235
00236
00237 fTimeLow = 0;
00238 fTimeMid = 0;
00239 fTimeHiAndVersion = 0;
00240 fClockSeqHiAndReserved = 0;
00241 fClockSeqLow = 0;
00242 fNode[0] = 0;
00243 fUUIDIndex = 0;
00244
00245 if (!uuid || !*uuid)
00246 Error("TUUID", "null string not allowed");
00247 else
00248 SetFromString(uuid);
00249 }
00250
00251
00252 void TUUID::FillBuffer(char *&buffer)
00253 {
00254
00255
00256 Version_t version = TUUID::Class_Version();
00257 tobuf(buffer, version);
00258 tobuf(buffer, fTimeLow);
00259 tobuf(buffer, fTimeMid);
00260 tobuf(buffer, fTimeHiAndVersion);
00261 tobuf(buffer, fClockSeqHiAndReserved);
00262 tobuf(buffer, fClockSeqLow);
00263 for (Int_t i = 0; i < 6; i++)
00264 tobuf(buffer, fNode[i]);
00265 }
00266
00267
00268 void TUUID::ReadBuffer(char *&buffer)
00269 {
00270
00271
00272 Version_t version;
00273 frombuf(buffer, &version);
00274 frombuf(buffer, &fTimeLow);
00275 frombuf(buffer, &fTimeMid);
00276 frombuf(buffer, &fTimeHiAndVersion);
00277 frombuf(buffer, &fClockSeqHiAndReserved);
00278 frombuf(buffer, &fClockSeqLow);
00279 for (Int_t i = 0; i < 6; i++)
00280 frombuf(buffer, &fNode[i]);
00281 }
00282
00283
00284 void TUUID::StreamerV1(TBuffer &b)
00285 {
00286
00287
00288
00289
00290 b >> fTimeLow;
00291 b >> fTimeMid;
00292 b >> fTimeHiAndVersion;
00293 b >> fClockSeqHiAndReserved;
00294 b >> fClockSeqLow;
00295 for (UInt_t i = 0; i < 6; i++) {
00296 b >> fNode[i];
00297 }
00298 }
00299
00300
00301 void TUUID::Format(UShort_t clockseq, uuid_time_t ts)
00302 {
00303
00304
00305 fTimeLow = ts.low;
00306 fTimeMid = (UShort_t)(ts.high & 0xFFFF);
00307 fTimeHiAndVersion = (UShort_t)((ts.high >> 16) & 0x0FFF);
00308 fTimeHiAndVersion |= (1 << 12);
00309 fClockSeqLow = clockseq & 0xFF;
00310 fClockSeqHiAndReserved = (clockseq & 0x3F00) >> 8;
00311 fClockSeqHiAndReserved |= 0x80;
00312 GetNodeIdentifier();
00313 }
00314
00315
00316 void TUUID::GetCurrentTime(uuid_time_t *timestamp)
00317 {
00318
00319
00320
00321
00322 const UShort_t uuids_per_tick = 1024;
00323
00324 static uuid_time_t time_last;
00325 static UShort_t uuids_this_tick;
00326 static Bool_t init = kFALSE;
00327
00328 if (!init) {
00329 GetSystemTime(&time_last);
00330 uuids_this_tick = uuids_per_tick;
00331 init = kTRUE;
00332 }
00333
00334 uuid_time_t time_now;
00335
00336 while (1) {
00337 GetSystemTime(&time_now);
00338
00339
00340 if (CmpTime(&time_last, &time_now)) {
00341
00342 uuids_this_tick = 0;
00343 break;
00344 }
00345 if (uuids_this_tick < uuids_per_tick) {
00346 uuids_this_tick++;
00347 break;
00348 }
00349
00350 }
00351
00352 time_last = time_now;
00353
00354 if (uuids_this_tick != 0) {
00355 if (time_now.low & 0x80000000) {
00356 time_now.low += uuids_this_tick;
00357 if (!(time_now.low & 0x80000000))
00358 time_now.high++;
00359 } else
00360 time_now.low += uuids_this_tick;
00361 }
00362
00363 timestamp->high = time_now.high;
00364 timestamp->low = time_now.low;
00365 }
00366
00367
00368 void TUUID::GetSystemTime(uuid_time_t *timestamp)
00369 {
00370
00371
00372 #ifdef R__WIN32
00373 ULARGE_INTEGER time;
00374 GetSystemTimeAsFileTime((FILETIME *)&time);
00375
00376
00377
00378
00379 time.QuadPart +=
00380 (unsigned __int64) (1000*1000*10)
00381 * (unsigned __int64) (60 * 60 * 24)
00382 * (unsigned __int64) (17+30+31+365*18+5);
00383
00384 timestamp->high = time.HighPart;
00385 timestamp->low = time.LowPart;
00386 #else
00387 struct timeval tp;
00388 gettimeofday(&tp, 0);
00389
00390
00391
00392 ULong64_t uuid_time = ((ULong64_t)tp.tv_sec * 10000000) + (tp.tv_usec * 10) +
00393 0x01B21DD213814000LL;
00394 timestamp->high = (UInt_t) (uuid_time >> 32);
00395 timestamp->low = (UInt_t) (uuid_time & 0xFFFFFFFF);
00396 #endif
00397 }
00398
00399
00400 void TUUID::GetNodeIdentifier()
00401 {
00402
00403
00404
00405 static UInt_t adr = 0;
00406
00407 if (gSystem) {
00408 #ifndef R__WIN32
00409 if (!adr) {
00410 TInetAddress addr = gSystem->GetHostByName(gSystem->HostName());
00411 if (addr.IsValid())
00412 adr = addr.GetAddress();
00413 else
00414 adr = 1;
00415 }
00416 #else
00417
00418
00419
00420
00421 if (!adr) {
00422 PIP_ADAPTER_INFO ainfo = (PIP_ADAPTER_INFO) malloc(sizeof(IP_ADAPTER_INFO));
00423 ULONG buflen = sizeof(IP_ADAPTER_INFO);
00424 DWORD stat = GetAdaptersInfo(ainfo, &buflen);
00425 if (stat == ERROR_BUFFER_OVERFLOW) {
00426 free(ainfo);
00427 ainfo = (PIP_ADAPTER_INFO) malloc(buflen);
00428 stat = GetAdaptersInfo(ainfo, &buflen);
00429 }
00430 if (stat != ERROR_SUCCESS)
00431 adr = 1;
00432 else {
00433
00434 PIP_ADAPTER_INFO adapter = ainfo;
00435 int a, b, c, d;
00436 sscanf(adapter->IpAddressList.IpAddress.String, "%d.%d.%d.%d",
00437 &a, &b, &c, &d);
00438 adr = (a << 24) | (b << 16) | (c << 8) | d;
00439 }
00440 free(ainfo);
00441 }
00442 #endif
00443 if (adr > 2) {
00444 memcpy(fNode, &adr, 4);
00445 fNode[4] = 0xbe;
00446 fNode[5] = 0xef;
00447 return;
00448 }
00449 }
00450 static UChar_t seed[16];
00451 if (adr < 2) {
00452 GetRandomInfo(seed);
00453 seed[0] |= 0x80;
00454 if (gSystem) adr = 2;
00455 }
00456 memcpy(fNode, seed, sizeof(fNode));
00457 fTimeHiAndVersion |= (3 << 12);
00458 }
00459
00460
00461 void TUUID::GetRandomInfo(UChar_t seed[16])
00462 {
00463
00464
00465 #ifdef R__WIN32
00466 struct randomness {
00467 MEMORYSTATUS m;
00468 SYSTEM_INFO s;
00469 FILETIME t;
00470 LARGE_INTEGER pc;
00471 DWORD tc;
00472 DWORD l;
00473 char hostname[MAX_COMPUTERNAME_LENGTH + 1];
00474 };
00475 randomness r;
00476
00477
00478 GlobalMemoryStatus(&r.m);
00479
00480 GetSystemInfo(&r.s);
00481
00482 GetSystemTimeAsFileTime(&r.t);
00483
00484 QueryPerformanceCounter(&r.pc);
00485
00486 r.tc = GetTickCount();
00487 r.l = MAX_COMPUTERNAME_LENGTH + 1;
00488 GetComputerName(r.hostname, &r.l);
00489 #else
00490 struct randomness {
00491 #if defined(R__LINUX) && !defined(R__WINGCC)
00492 struct sysinfo s;
00493 #endif
00494 struct timeval t;
00495 char hostname[257];
00496 };
00497 randomness r;
00498
00499 #if defined(R__LINUX) && !defined(R__WINGCC)
00500 sysinfo(&r.s);
00501 #endif
00502 gettimeofday(&r.t, 0);
00503 gethostname(r.hostname, 256);
00504 #endif
00505 TMD5 md5;
00506 md5.Update((UChar_t *)&r, sizeof(randomness));
00507 md5.Final(seed);
00508 }
00509
00510
00511 void TUUID::Print() const
00512 {
00513
00514
00515 printf("%s\n", AsString());
00516 }
00517
00518
00519 const char *TUUID::AsString() const
00520 {
00521
00522
00523 static char uuid[40];
00524
00525 snprintf(uuid,40, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
00526 fTimeLow, fTimeMid, fTimeHiAndVersion, fClockSeqHiAndReserved,
00527 fClockSeqLow, fNode[0], fNode[1], fNode[2], fNode[3], fNode[4],
00528 fNode[5]);
00529
00530 return uuid;
00531 }
00532
00533
00534 UShort_t TUUID::Hash() const
00535 {
00536
00537
00538 Short_t c0 = 0, c1 = 0, x, y;
00539 char *c = (char *) &fTimeLow;
00540
00541
00542
00543
00544
00545
00546
00547 c0 += *c++; c1 += c0;
00548 c0 += *c++; c1 += c0;
00549 c0 += *c++; c1 += c0;
00550 c0 += *c++; c1 += c0;
00551
00552 c0 += *c++; c1 += c0;
00553 c0 += *c++; c1 += c0;
00554 c0 += *c++; c1 += c0;
00555 c0 += *c++; c1 += c0;
00556
00557 c0 += *c++; c1 += c0;
00558 c0 += *c++; c1 += c0;
00559 c0 += *c++; c1 += c0;
00560 c0 += *c++; c1 += c0;
00561
00562 c0 += *c++; c1 += c0;
00563 c0 += *c++; c1 += c0;
00564 c0 += *c++; c1 += c0;
00565 c0 += *c++; c1 += c0;
00566
00567
00568 x = -c1 % 255;
00569 if (x < 0)
00570 x += 255;
00571
00572
00573 y = (c1 - c0) % 255;
00574 if (y < 0)
00575 y += 255;
00576
00577 return UShort_t((y << 8) + x);
00578 }
00579
00580
00581 Int_t TUUID::Compare(const TUUID &u) const
00582 {
00583
00584
00585
00586
00587
00588 #define CHECK(f1, f2) if (f1 != f2) return f1 < f2 ? -1 : 1;
00589 CHECK(fTimeLow, u.fTimeLow)
00590 CHECK(fTimeMid, u.fTimeMid)
00591 CHECK(fTimeHiAndVersion, u.fTimeHiAndVersion)
00592 CHECK(fClockSeqHiAndReserved, u.fClockSeqHiAndReserved)
00593 CHECK(fClockSeqLow, u.fClockSeqLow)
00594 for (int i = 0; i < 6; i++) {
00595 if (fNode[i] < u.fNode[i])
00596 return -1;
00597 if (fNode[i] > u.fNode[i])
00598 return 1;
00599 }
00600 return 0;
00601 }
00602
00603
00604 TInetAddress TUUID::GetHostAddress() const
00605 {
00606
00607
00608
00609 if ((fTimeHiAndVersion >> 12) == 1) {
00610 UInt_t addr;
00611 memcpy(&addr, fNode, 4);
00612 return TInetAddress("????", addr, 0);
00613 }
00614 return TInetAddress();
00615 }
00616
00617
00618 TDatime TUUID::GetTime() const
00619 {
00620
00621
00622 TDatime dt;
00623 uuid_time_t ts;
00624
00625 ts.low = fTimeLow;
00626 ts.high = (UInt_t)fTimeMid;
00627 ts.high |= (UInt_t)((fTimeHiAndVersion & 0x0FFF) << 16);
00628
00629
00630
00631
00632 ULong64_t high = ts.high;
00633 ULong64_t uuid_time = (high << 32) + ts.low;
00634 uuid_time -= 0x01B21DD213814000LL;
00635 uuid_time /= 10000000LL;
00636 UInt_t tt = (UInt_t) uuid_time;
00637 dt.Set(tt);
00638
00639 return dt;
00640 }
00641
00642
00643 void TUUID::GetUUID(UChar_t uuid[16]) const
00644 {
00645
00646
00647 memcpy(uuid, &fTimeLow, 16);
00648 }
00649
00650
00651 void TUUID::SetUUID(const char *uuid)
00652 {
00653
00654
00655
00656 if (!uuid || !*uuid)
00657 Error("SetUUID", "null string not allowed");
00658 else
00659 SetFromString(uuid);
00660 }
00661
00662
00663 TBuffer &operator<<(TBuffer &buf, const TUUID &uuid)
00664 {
00665
00666
00667 R__ASSERT( buf.IsWriting() );
00668
00669 const_cast<TUUID&>(uuid).Streamer(buf);
00670 return buf;
00671 }