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 #ifdef HAVE_CONFIG_H
00033 #include "configure.h"
00034 #endif
00035
00036 #ifdef HAVE_SYS_TIME_H
00037 #include <sys/time.h>
00038 #else
00039 #error need sys/time.h
00040 #endif
00041
00042 #ifdef HAVE_UNISTD_H
00043 #include <unistd.h>
00044 #else
00045 #error need unistd.h
00046 #endif
00047
00048
00049 #include <cstdlib>
00050 #include <iomanip>
00051 #include <sstream>
00052
00053 #include "LiveSupport/Core/Uuid.h"
00054
00055
00056 using namespace LiveSupport::Core;
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 #define UUIDS_PER_TICK 1024
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 Ptr<Uuid>::Ref
00079 Uuid :: generateId(void) throw ()
00080 {
00081 Ptr<Uuid>::Ref id(new Uuid());
00082
00083 UuidTime timestamp;
00084 UuidTime lastTime;
00085 uint16_t clockseq;
00086 UuidNode node;
00087 UuidNode lastNode;
00088 int f;
00089
00090
00091
00092
00093
00094 getCurrentTime(×tamp);
00095
00096
00097 getIeeeNodeIdentifier(&node);
00098
00099
00100 f = id->readState(&clockseq, &lastTime, &lastNode);
00101
00102
00103
00104 if (!f || memcmp(&node, &lastNode, sizeof(UuidNode))) {
00105 clockseq = trueRandom();
00106 } else if (timestamp < lastTime) {
00107 clockseq++;
00108 }
00109
00110
00111 id->format(clockseq, timestamp, node);
00112 id->representAsString();
00113
00114
00115 id->writeState(clockseq, timestamp, node);
00116
00117
00118
00119 return id;
00120 }
00121
00122
00123
00124
00125
00126 void
00127 Uuid :: format(uint16_t clockSeq,
00128 UuidTime timestamp,
00129 UuidNode node) throw ()
00130 {
00131
00132
00133 timeLow = (unsigned long)(timestamp & 0xFFFFFFFF);
00134 timeMid = (unsigned short)((timestamp >> 32) & 0xFFFF);
00135 timeHiAndVersion = (unsigned short)((timestamp >> 48) & 0x0FFF);
00136 timeHiAndVersion |= (1 << 12);
00137 clockSeqLow = clockSeq & 0xFF;
00138 clockSeqHiAndReserved = (clockSeq & 0x3F00) >> 8;
00139 clockSeqHiAndReserved |= 0x80;
00140
00141 for (int i = 0; i < 6; ++i) {
00142 this->node[i] = node.nodeId[i];
00143 }
00144 }
00145
00146
00147
00148
00149
00150 void
00151 Uuid :: representAsString(void) throw ()
00152 {
00153 std::stringstream sstr;
00154
00155 sstr << std::hex << std::setw(8) << std::setfill('0') << timeLow << '-'
00156 << std::hex << std::setw(4) << std::setfill('0') << timeMid << '-'
00157 << std::hex << std::setw(4) << std::setfill('0')
00158 << timeHiAndVersion << '-'
00159 << std::hex << std::setw(2) << std::setfill('0')
00160 << (unsigned short) clockSeqHiAndReserved << '-'
00161 << std::hex << std::setw(2) << std::setfill('0')
00162 << (unsigned short) clockSeqLow << '-';
00163 for (int i = 0; i < 6; ++i) {
00164 sstr << std::hex << std::setw(2) << std::setfill('0')
00165 << (unsigned short) this->node[i];
00166 }
00167
00168 idAsString = sstr.str();
00169 }
00170
00171
00172
00173
00174
00175 int
00176 Uuid :: readState(uint16_t * clockSeq,
00177 UuidTime * timestamp,
00178 UuidNode * node) throw ()
00179 {
00180
00181
00182 return 0;
00183 }
00184
00185
00186
00187
00188
00189 void
00190 Uuid :: writeState(uint16_t clockSeq,
00191 UuidTime timestamp,
00192 UuidNode node) throw ()
00193 {
00194
00195 }
00196
00197
00198
00199
00200
00201 void
00202 Uuid :: getCurrentTime(UuidTime *timestamp) throw ()
00203 {
00204 UuidTime timeNow;
00205 static UuidTime timeLast;
00206 static uint16_t uuidsThisTick;
00207 static bool inited = false;
00208
00209 if (!inited) {
00210 getSystemTime(&timeNow);
00211 uuidsThisTick = UUIDS_PER_TICK;
00212 inited = true;
00213 };
00214
00215 while (true) {
00216 getSystemTime(&timeNow);
00217
00218
00219 if (timeLast != timeNow) {
00220
00221 uuidsThisTick = 0;
00222 break;
00223 };
00224 if (uuidsThisTick < UUIDS_PER_TICK) {
00225 uuidsThisTick++;
00226 break;
00227 };
00228
00229 };
00230
00231
00232 *timestamp = timeNow + uuidsThisTick;
00233 }
00234
00235
00236
00237
00238
00239 void
00240 Uuid :: getSystemTime(UuidTime * uuidTime) throw ()
00241 {
00242 struct timeval tp;
00243
00244 gettimeofday(&tp, (struct timezone *)0);
00245
00246
00247
00248
00249
00250 *uuidTime = (tp.tv_sec * 10000000)
00251 + (tp.tv_usec * 10)
00252 + 0x01B21DD213814000LL;
00253 }
00254
00255
00256
00257
00258
00259 void
00260 Uuid :: getIeeeNodeIdentifier(UuidNode * node) throw ()
00261 {
00262 long hostId = gethostid();
00263
00264 node->nodeId[5] = (char) (hostId & 0x0000000000ffL);
00265 node->nodeId[4] = (char) ((hostId & 0x00000000ff00L) >> 8);
00266 node->nodeId[3] = (char) ((hostId & 0x000000ff0000L) >> 16);
00267 node->nodeId[2] = (char) ((hostId & 0x0000ff000000L) >> 24);
00268
00269 node->nodeId[1] = 0;
00270 node->nodeId[0] = 0;
00271 }
00272
00273
00274
00275
00276
00277 uint16_t
00278 Uuid :: trueRandom(void) throw ()
00279 {
00280 static bool inited = false;
00281 UuidTime timeNow;
00282
00283 if (!inited) {
00284 getSystemTime(&timeNow);
00285 timeNow = timeNow/UUIDS_PER_TICK;
00286 srand((unsigned int)(((timeNow >> 32) ^ timeNow)&0xffffffff));
00287 inited = true;
00288 };
00289
00290 return rand();
00291 }
00292
00293
00294
00295
00296
00297 bool
00298 Uuid :: compare(const Uuid & id1,
00299 const Uuid & id2) throw ()
00300 {
00301 if (!(id1.timeLow == id2.timeLow
00302 && id1.timeMid == id2.timeMid
00303 && id1.timeHiAndVersion == id2.timeHiAndVersion
00304 && id1.clockSeqHiAndReserved == id2.clockSeqHiAndReserved
00305 && id1.clockSeqLow == id2.clockSeqLow)) {
00306
00307 return false;
00308 }
00309
00310 for (int i = 0; i < 6; ++i) {
00311 if (id1.node[i] != id2.node[i]) {
00312 return false;
00313 }
00314 }
00315
00316 return true;
00317 }
00318