TUUID.cxx

Go to the documentation of this file.
00001 // @(#)root/base:$Id: TUUID.cxx 35958 2010-10-01 08:06:24Z brun $
00002 // Author: Fons Rademakers   30/9/2001
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2001, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //////////////////////////////////////////////////////////////////////////
00013 //                                                                      //
00014 // TUUID                                                                //
00015 //                                                                      //
00016 // This class defines a UUID (Universally Unique IDentifier), also      //
00017 // known as GUIDs (Globally Unique IDentifier). A UUID is 128 bits      //
00018 // long, and if generated according to this algorithm, is either        //
00019 // guaranteed to be different from all other UUIDs/GUIDs generated      //
00020 // until 3400 A.D. or extremely likely to be different. UUIDs were      //
00021 // originally used in the Network Computing System (NCS) and            //
00022 // later in the Open Software Foundation's (OSF) Distributed Computing  //
00023 // Environment (DCE).                                                   //
00024 //                                                                      //
00025 // Structure of universal unique IDs (UUIDs).                           //
00026 //                                                                      //
00027 // Depending on the network data representation, the multi-             //
00028 // octet unsigned integer fields are subject to byte swapping           //
00029 // when communicated between dissimilar endian machines.                //
00030 //                                                                      //
00031 // +-----------------------------------+                                //
00032 // |     low 32 bits of time           |  0-3   .fTimeLow               //
00033 // +-------------------------------+----                                //
00034 // |     mid 16 bits of time       |      4-5   .fTimeMid               //
00035 // +-------+-----------------------+                                    //
00036 // | vers. |   hi 12 bits of time  |      6-7   .fTimeHiAndVersion      //
00037 // +-------+-------+---------------+                                    //
00038 // |Res | clkSeqHi |                      8     .fClockSeqHiAndReserved //
00039 // +---------------+                                                    //
00040 // |   clkSeqLow   |                      9     .fClockSeqLow           //
00041 // +---------------+------------------+                                 //
00042 // |            node ID               |   10-15 .fNode                  //
00043 // +----------------------------------+                                 //
00044 //                                                                      //
00045 // The adjusted time stamp is split into three fields, and the          //
00046 // clockSeq is split into two fields.                                   //
00047 //                                                                      //
00048 // The timestamp is a 60-bit value. For UUID version 1, this            //
00049 // is represented by Coordinated Universal Time (UTC/GMT) as            //
00050 // a count of 100-nanosecond intervals since 00:00:00.00,               //
00051 // 15 October 1582 (the date of Gregorian reform to the                 //
00052 // Christian calendar).                                                 //
00053 //                                                                      //
00054 // The version number is multiplexed in the 4 most significant          //
00055 // bits of the 'fTimeHiAndVersion' field. There are two defined         //
00056 // versions:                                                            //
00057 //               MSB <---                                               //
00058 // Version      4-Bit Code      Description                             //
00059 // ------------------------------------------------------------         //
00060 // |  1           0 0 0 1     DCE version, as specified herein.         //
00061 // |  2           0 0 1 0     DCE Security version, with                //
00062 // |                          embedded POSIX UIDs.                      //
00063 // |  3           0 0 1 1     node id is a random value                 //
00064 // ------------------------------------------------------------         //
00065 //                                                                      //
00066 // Clock Sequence                                                       //
00067 //                                                                      //
00068 // The clock sequence value must be changed whenever:                   //
00069 //                                                                      //
00070 //    The UUID generator detects that the local value of UTC            //
00071 //    has gone backward; this may be due to re-syncing of the system    //
00072 //    clock.                                                            //
00073 //                                                                      //
00074 // While a node is operational, the UUID service always saves           //
00075 // the last UTC used to create a UUID. Each time a new UUID             //
00076 // is created, the current UTC is compared to the saved value           //
00077 // and if either the current value is less or the saved value           //
00078 // was lost, then the clock sequence is incremented modulo              //
00079 // 16,384, thus avoiding production of duplicted UUIDs.                 //
00080 //                                                                      //
00081 // The clock sequence must be initialized to a random number            //
00082 // to minimize the correlation across system. This provides             //
00083 // maximum protection against node identifiers that may move            //
00084 // or switch from system to system rapidly.                             //
00085 //                                                                      //
00086 // Clock Adjustment                                                     //
00087 //                                                                      //
00088 // UUIDs may be created at a rate greater than the system clock         //
00089 // resolution. Therefore, the system must also maintain an              //
00090 // adjustment value to be added to the lower-order bits of the          //
00091 // time. Logically, each time the system clock ticks, the               //
00092 // adjustment value is cleared. Every time a UUID is generated,         //
00093 // the current adjustment value is read and incremented, and            //
00094 // then added to the UTC time field of the UUID.                        //
00095 //                                                                      //
00096 // Clock Overrun                                                        //
00097 //                                                                      //
00098 // The 100-nanosecond granularity of time should prove sufficient       //
00099 // even for bursts of UUID production in the next generation of         //
00100 // high-performance multiprocessors. If a system overruns the           //
00101 // clock adjustment by requesting too many UUIDs within a single        //
00102 // system clock tick, the UUID generator will stall until the           //
00103 // system clock catches up.                                             //
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    // Create a UUID.
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          // try to get a unique seed per process
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    // get current time
00160    GetCurrentTime(&timestamp);
00161 
00162    // if clock went backward change clockseq
00163    if (CmpTime(&timestamp, &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    // delete this TUUID
00178 
00179    //gROOT->GetUUIDs()->RemoveUUID(fUUIDIndex);
00180 }
00181 
00182 //______________________________________________________________________________
00183 Int_t TUUID::CmpTime(uuid_time_t *t1, uuid_time_t *t2)
00184 {
00185    // Compare two time values.
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    // Set this UUID to the value specified in uuid ((which must be in
00198    // TUUID::AsString() format).
00199 
00200    // Format is tttttttt-tttt-cccc-cccc-nnnnnnnnnnnn.
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    // Note that we're going through this agony because scanf is
00217    // defined to know only to scan into "int"s or "long"s.
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    // Initialize a TUUID with uuid (which must be in TUUID::AsString() format).
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    // Stream UUID into output buffer.
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    // Stream UUID from input buffer.
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    // Stream UUID from input buffer.
00287    // This function is for the exclusive use of TDirectory::Streamer() to
00288    // read a non-versioned version of TUUID.
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    // Make a UUID from timestamp, clockseq and node id.
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    // Get current time as 60 bit 100ns ticks since whenever.
00319    // Compensate for the fact that real clock resolution is less
00320    // than 100ns.
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       // if clock reading changed since last UUID generated
00340       if (CmpTime(&time_last, &time_now))  {
00341          // reset count of uuid's generated with this clock reading
00342          uuids_this_tick = 0;
00343          break;
00344       }
00345       if (uuids_this_tick < uuids_per_tick) {
00346          uuids_this_tick++;
00347          break;
00348       }
00349       // going too fast for our clock; spin
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    // Get system time with 100ns precision. Time is since Oct 15, 1582.
00371 
00372 #ifdef R__WIN32
00373    ULARGE_INTEGER time;
00374    GetSystemTimeAsFileTime((FILETIME *)&time);
00375    // NT keeps time in FILETIME format which is 100ns ticks since
00376    // Jan 1, 1601. UUIDs use time in 100ns ticks since Oct 15, 1582.
00377    // The difference is 17 Days in Oct + 30 (Nov) + 31 (Dec)
00378    // + 18 years and 5 leap days.
00379    time.QuadPart +=
00380             (unsigned __int64) (1000*1000*10)       // seconds
00381           * (unsigned __int64) (60 * 60 * 24)       // days
00382           * (unsigned __int64) (17+30+31+365*18+5); // # of days
00383 
00384    timestamp->high = time.HighPart;
00385    timestamp->low  = time.LowPart;
00386 #else
00387    struct timeval tp;
00388    gettimeofday(&tp, 0);
00389    // Offset between UUID formatted times and Unix formatted times.
00390    // UUID UTC base time is October 15, 1582.
00391    // Unix base time is January 1, 1970.
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    // Get node identifier. Try first to get network address, if no
00403    // network interface try random info based on some machine parameters.
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;  // illegal address
00415       }
00416 #else
00417       // this way to get the machine's IP address is needed because
00418       // GetHostByName() on Win32 contacts the DNS which we don't want
00419       // as firewall tools like ZoneAlarm are likely to catch it and
00420       // alarm the user
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;  // illegal address
00432          else {
00433             // take address of first adapter
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;  // illegal address
00455    }
00456    memcpy(fNode, seed, sizeof(fNode));
00457    fTimeHiAndVersion |= (3 << 12);    // version == 3: random node info
00458 }
00459 
00460 //______________________________________________________________________________
00461 void TUUID::GetRandomInfo(UChar_t seed[16])
00462 {
00463    // Get random info based on some machine parameters.
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    // memory usage stats
00478    GlobalMemoryStatus(&r.m);
00479    // random system stats
00480    GetSystemInfo(&r.s);
00481    // 100ns resolution time of day
00482    GetSystemTimeAsFileTime(&r.t);
00483    // high resolution performance counter
00484    QueryPerformanceCounter(&r.pc);
00485    // milliseconds since last boot
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    // Print UUID.
00514 
00515    printf("%s\n", AsString());
00516 }
00517 
00518 //______________________________________________________________________________
00519 const char *TUUID::AsString() const
00520 {
00521    // Return UUID as string. Copy string immediately since it will be reused.
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    // Compute 16-bit hash value of the UUID.
00537 
00538    Short_t  c0 = 0, c1 = 0, x, y;
00539    char    *c = (char *) &fTimeLow;
00540 
00541    // For speed lets unroll the following loop:
00542    //   for (i = 0; i < 16; i++) {
00543    //      c0 += *c++;
00544    //      c1 += c0;
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    //  Calculate the value for "First octet" of the hash
00568    x = -c1 % 255;
00569    if (x < 0)
00570       x += 255;
00571 
00572    // Calculate the value for "second octet" of the hash
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    // Compare two UUIDs "lexically" and return
00584    //    -1   this is lexically before u
00585    //     0   this is equal to u
00586    //     1   this is lexically after u
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    // Get address of host encoded in UUID. If host id is not an ethernet
00607    // address, but random info, then the returned TInetAddress is not valid.
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    // Get time from UUID.
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    // Offset between UUID formatted times and Unix formatted times.
00630    // UUID UTC base time is October 15, 1582.
00631    // Unix base time is January 1, 1970.
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    // Return uuid in specified buffer (16 byte = 128 bits).
00646 
00647    memcpy(uuid, &fTimeLow, 16);
00648 }
00649 
00650 //______________________________________________________________________________
00651 void TUUID::SetUUID(const char *uuid)
00652 {
00653    // Set this UUID to the value specified in uuid ((which must be in
00654    // TUUID::AsString() format).
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    // Input operator.  Delegate to Streamer.
00666 
00667    R__ASSERT( buf.IsWriting() );
00668 
00669    const_cast<TUUID&>(uuid).Streamer(buf);
00670    return buf;
00671 }

Generated on Tue Jul 5 14:11:24 2011 for ROOT_528-00b_version by  doxygen 1.5.1