#include "ace/UUID.h"#include "ace/Guard_T.h"#include "ace/Log_Msg.h"#include "ace/OS_NS_stdio.h"#include "ace/OS_NS_string.h"#include "ace/OS_NS_sys_time.h"#include "ace/OS_NS_netdb.h"#include "ace/OS_NS_unistd.h"#include "ace/ACE.h"
Go to the source code of this file.
Functions | |
| ACE_RCSID (ace, UUID,"$Id: UUID.cpp 85376 2009-05-18 17:12:47Z shuston $") 1 namespace ACE_Utils | |
| ACE_RCSID | ( | ace | , | |
| UUID | , | |||
| "$Id: UUID.cpp 85376 2009-05-18 17:12:47Z shuston $" | ||||
| ) |
Special case for the nil UUID.
Support versions 1, 3, and 4 only
Obtain a new timestamp. If UUID's are being generated too quickly the clock sequence will be incremented
ACE_Time_Value is in POSIX time, seconds since Jan 1, 1970. UUIDs use time in 100ns ticks since 15 October 1582. The difference is: 15 Oct 1582 - 1 Jan 1600: 17 days in Oct, 30 in Nov, 31 in Dec + 17 years and 4 leap days (1584, 88, 92 and 96) 1 Jan 1600 - 1 Jan 1900: 3 centuries + 73 leap days ( 25 in 17th cent. and 24 each in 18th and 19th centuries) 1 Jan 1900 - 1 Jan 1970: 70 years + 17 leap days. This adds up, in days: (17+30+31+365*17+4)+ (365*300+73)+ (365*70+17) or 122192928000000000U (0x1B21DD213814000) 100 ns ticks.
Get the time of day, convert to 100ns ticks then add the offset.
Definition at line 18 of file UUID.cpp.
00020 : UUID.cpp 85376 2009-05-18 17:12:47Z shuston $") 00021 00022 00023 ACE_BEGIN_VERSIONED_NAMESPACE_DECL 00024 00025 namespace ACE_Utils 00026 { 00027 // NIL version of the UUID 00028 const UUID UUID::NIL_UUID; 00029 00030 UUID::UUID (const ACE_CString& uuid_string) 00031 { 00032 this->init (); 00033 this->from_string_i (uuid_string); 00034 } 00035 00036 const UUID & 00037 UUID::operator = (const UUID & rhs) 00038 { 00039 if (this == &rhs) 00040 return *this; 00041 00042 // Reset the string version of the UUID a string version 00043 // exist, and the UUID is not equal to the old UUID. 00044 if (0 != this->as_string_.get ()) 00045 { 00046 if (0 == rhs.as_string_.get () || *this != rhs) 00047 this->as_string_.reset (); 00048 } 00049 00050 // Copy the contents of the UUID. 00051 ACE_OS::memcpy (&this->uuid_, &rhs.uuid_, BINARY_SIZE); 00052 00053 /// @todo We should create an UUID_Ex class for UUIDs that 00054 /// contain the thread id and process id. 00055 this->thr_id_ = rhs.thr_id_; 00056 this->pid_ = rhs.pid_; 00057 00058 return *this; 00059 } 00060 00061 const ACE_CString * UUID::to_string (void) const 00062 { 00063 // Compute the string representation only once. 00064 if (0 != this->as_string_.get ()) 00065 return this->as_string_.get (); 00066 00067 // Get a buffer exactly the correct size. Use the nil UUID as a 00068 // gauge. Don't forget the trailing nul. 00069 ACE_Auto_Array_Ptr <char> auto_clean; 00070 size_t UUID_STRING_LENGTH = 36 + thr_id_.length () + pid_.length (); 00071 char *buf = 0; 00072 00073 if (36 == UUID_STRING_LENGTH) 00074 { 00075 ACE_NEW_RETURN (buf, 00076 char[UUID_STRING_LENGTH + 1], 00077 0); 00078 00079 // Let the auto array pointer manage the buffer. 00080 auto_clean.reset (buf); 00081 00082 ACE_OS::sprintf (buf, 00083 "%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x", 00084 this->uuid_.time_low_, 00085 this->uuid_.time_mid_, 00086 this->uuid_.time_hi_and_version_, 00087 this->uuid_.clock_seq_hi_and_reserved_, 00088 this->uuid_.clock_seq_low_, 00089 (this->uuid_.node_.node_ID ()) [0], 00090 (this->uuid_.node_.node_ID ()) [1], 00091 (this->uuid_.node_.node_ID ()) [2], 00092 (this->uuid_.node_.node_ID ()) [3], 00093 (this->uuid_.node_.node_ID ()) [4], 00094 (this->uuid_.node_.node_ID ()) [5]); 00095 } 00096 else 00097 { 00098 UUID_STRING_LENGTH += 2; //for '-' 00099 ACE_NEW_RETURN (buf, 00100 char[UUID_STRING_LENGTH + 1], 00101 0); 00102 00103 // Let the auto array pointer manage the buffer. 00104 auto_clean.reset (buf); 00105 00106 ACE_OS::sprintf (buf, 00107 "%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x-%s-%s", 00108 this->uuid_.time_low_, 00109 this->uuid_.time_mid_, 00110 this->uuid_.time_hi_and_version_, 00111 this->uuid_.clock_seq_hi_and_reserved_, 00112 this->uuid_.clock_seq_low_, 00113 (this->uuid_.node_.node_ID ()) [0], 00114 (this->uuid_.node_.node_ID ()) [1], 00115 (this->uuid_.node_.node_ID ()) [2], 00116 (this->uuid_.node_.node_ID ()) [3], 00117 (this->uuid_.node_.node_ID ()) [4], 00118 (this->uuid_.node_.node_ID ()) [5], 00119 thr_id_.c_str (), 00120 pid_.c_str ()); 00121 } 00122 00123 // Save the string. 00124 ACE_CString * as_string = 0; 00125 00126 ACE_NEW_RETURN (as_string, 00127 ACE_CString (buf, UUID_STRING_LENGTH), 00128 0); 00129 00130 this->as_string_.reset (as_string); 00131 return this->as_string_.get (); 00132 } 00133 00134 void 00135 UUID::from_string_i (const ACE_CString& uuid_string) 00136 { 00137 if (uuid_string.length () < NIL_UUID.to_string ()->length ()) 00138 { 00139 ACE_ERROR ((LM_ERROR, 00140 "%N ACE_UUID::from_string_i - " 00141 "IllegalArgument (incorrect string length)\n")); 00142 return; 00143 } 00144 00145 /// Special case for the nil UUID. 00146 if (uuid_string == *NIL_UUID.to_string ()) 00147 { 00148 *this = NIL_UUID; 00149 return; 00150 } 00151 00152 unsigned int time_low; 00153 unsigned int time_mid; 00154 unsigned int time_hi_and_version; 00155 unsigned int clock_seq_hi_and_reserved; 00156 unsigned int clock_seq_low; 00157 unsigned int node [UUID_Node::NODE_ID_SIZE]; 00158 char thr_pid_buf [BUFSIZ]; 00159 00160 if (uuid_string.length () == NIL_UUID.to_string ()->length ()) 00161 { 00162 // This might seem quite strange this being in ACE, but it 00163 // seems to be a bit difficult to write a facade for ::sscanf 00164 // because some compilers dont support vsscanf, including 00165 // MSVC. It appears that most platforms support sscanf though 00166 // so we need to use it directly. 00167 const int nScanned = 00168 #if defined (ACE_HAS_TR24731_2005_CRT) 00169 sscanf_s ( 00170 #else 00171 ::sscanf ( 00172 #endif /* ACE_HAS_TR24731_2005_CRT */ 00173 uuid_string.c_str (), 00174 "%8x-%4x-%4x-%2x%2x-%2x%2x%2x%2x%2x%2x", 00175 &time_low, 00176 &time_mid, 00177 &time_hi_and_version, 00178 &clock_seq_hi_and_reserved, 00179 &clock_seq_low, 00180 &node[0], 00181 &node[1], 00182 &node[2], 00183 &node[3], 00184 &node[4], 00185 &node[5] 00186 ); 00187 00188 if (nScanned != 11) 00189 { 00190 ACE_DEBUG ((LM_DEBUG, 00191 "UUID::from_string_i - " 00192 "IllegalArgument (invalid string representation)\n")); 00193 return; 00194 } 00195 } 00196 else 00197 { 00198 const int nScanned = 00199 #if defined (ACE_HAS_TR24731_2005_CRT) 00200 sscanf_s (uuid_string.c_str (), 00201 "%8x-%4x-%4x-%2x%2x-%2x%2x%2x%2x%2x%2x-%s", 00202 &time_low, 00203 &time_mid, 00204 &time_hi_and_version, 00205 &clock_seq_hi_and_reserved, 00206 &clock_seq_low, 00207 &node[0], 00208 &node[1], 00209 &node[2], 00210 &node[3], 00211 &node[4], 00212 &node[5], 00213 thr_pid_buf, 00214 BUFSIZ 00215 ); 00216 #else 00217 ::sscanf (uuid_string.c_str (), 00218 "%8x-%4x-%4x-%2x%2x-%2x%2x%2x%2x%2x%2x-%s", 00219 &time_low, 00220 &time_mid, 00221 &time_hi_and_version, 00222 &clock_seq_hi_and_reserved, 00223 &clock_seq_low, 00224 &node[0], 00225 &node[1], 00226 &node[2], 00227 &node[3], 00228 &node[4], 00229 &node[5], 00230 thr_pid_buf 00231 ); 00232 #endif /* ACE_HAS_TR24731_2005_CRT */ 00233 00234 if (nScanned != 12) 00235 { 00236 ACE_DEBUG ((LM_DEBUG, 00237 "ACE_UUID::from_string_i - " 00238 "IllegalArgument (invalid string representation)\n")); 00239 return; 00240 } 00241 } 00242 00243 this->uuid_.time_low_ = static_cast<ACE_UINT32> (time_low); 00244 this->uuid_.time_mid_ = static_cast<ACE_UINT16> (time_mid); 00245 this->uuid_.time_hi_and_version_ = static_cast<ACE_UINT16> (time_hi_and_version); 00246 this->uuid_.clock_seq_hi_and_reserved_ = static_cast<u_char> (clock_seq_hi_and_reserved); 00247 this->uuid_.clock_seq_low_ = static_cast<u_char> (clock_seq_low); 00248 00249 for (size_t i = 0; i < UUID_Node::NODE_ID_SIZE; ++ i) 00250 this->uuid_.node_.node_ID ()[i] = static_cast <u_char> (node[i]); 00251 00252 // Support varient 10- only 00253 if ((this->uuid_.clock_seq_hi_and_reserved_ & 0xc0) != 0x80 && 00254 (this->uuid_.clock_seq_hi_and_reserved_ & 0xc0) != 0xc0) 00255 { 00256 ACE_DEBUG ((LM_DEBUG, 00257 "ACE_UUID::from_string_i - " 00258 "IllegalArgument (unsupported variant)\n")); 00259 return; 00260 } 00261 00262 /// Support versions 1, 3, and 4 only 00263 ACE_UINT16 V1 = this->uuid_.time_hi_and_version_; 00264 00265 if ((V1 & 0xF000) != 0x1000 && 00266 (V1 & 0xF000) != 0x3000 && 00267 (V1 & 0xF000) != 0x4000) 00268 { 00269 ACE_DEBUG ((LM_DEBUG, 00270 "ACE_UUID::from_string_i - " 00271 "IllegalArgument (unsupported version)\n")); 00272 return; 00273 } 00274 00275 if ((this->uuid_.clock_seq_hi_and_reserved_ & 0xc0) == 0xc0) 00276 { 00277 if (uuid_string.length () == NIL_UUID.to_string ()->length ()) 00278 { 00279 ACE_DEBUG ((LM_DEBUG, 00280 "ACE_UUID::from_string_i - " 00281 "IllegalArgument (Missing Thread and Process Id)\n")); 00282 return; 00283 } 00284 ACE_CString thr_pid_str (thr_pid_buf); 00285 ssize_t pos = static_cast<ssize_t> (thr_pid_str.find ('-')); 00286 if (pos == -1) 00287 ACE_DEBUG ((LM_DEBUG, 00288 "ACE_UUID::from_string_i - " 00289 "IllegalArgument (Thread and Process Id format incorrect)\n")); 00290 00291 this->thr_id_ = thr_pid_str.substr (0, pos); 00292 this->pid_ = thr_pid_str.substr (pos+1, thr_pid_str.length ()-pos-1); 00293 } 00294 } 00295 00296 UUID_Generator::UUID_Generator (void) 00297 : time_last_ (0), 00298 destroy_lock_ (true), 00299 is_init_ (false) 00300 { 00301 ACE_NEW (lock_, ACE_SYNCH_MUTEX); 00302 this->init (); 00303 } 00304 00305 UUID_Generator::~UUID_Generator (void) 00306 { 00307 if (destroy_lock_) 00308 delete lock_; 00309 } 00310 00311 void 00312 UUID_Generator::init (void) 00313 { 00314 if (this->is_init_) 00315 return; 00316 00317 ACE_OS::macaddr_node_t macaddress; 00318 int result = ACE_OS::getmacaddress (&macaddress); 00319 00320 UUID_Node::Node_ID node_id; 00321 00322 if (-1 != result) 00323 { 00324 ACE_OS::memcpy (node_id, 00325 macaddress.node, 00326 UUID_Node::NODE_ID_SIZE); 00327 } 00328 else 00329 { 00330 node_id [0] = static_cast<u_char> (ACE_OS::rand ()); 00331 node_id [1] = static_cast<u_char> (ACE_OS::rand ()); 00332 node_id [2] = static_cast<u_char> (ACE_OS::rand ()); 00333 node_id [3] = static_cast<u_char> (ACE_OS::rand ()); 00334 node_id [4] = static_cast<u_char> (ACE_OS::rand ()); 00335 node_id [5] = static_cast<u_char> (ACE_OS::rand ()); 00336 } 00337 00338 this->get_timestamp (time_last_); 00339 00340 { 00341 ACE_GUARD (ACE_SYNCH_MUTEX, ace_mon, *lock_); 00342 uuid_state_.timestamp = time_last_; 00343 00344 ACE_OS::memcpy (uuid_state_.node.node_ID (), 00345 node_id, 00346 UUID_Node::NODE_ID_SIZE); 00347 } 00348 00349 this->is_init_ = true; 00350 } 00351 00352 void 00353 UUID_Generator:: 00354 generate_UUID (UUID& uuid, ACE_UINT16 version, u_char variant) 00355 { 00356 UUID_Time timestamp; 00357 ACE_UINT16 clock_sequence; 00358 00359 this->get_timestamp_and_clocksequence (timestamp, 00360 clock_sequence); 00361 00362 // Construct a Version 1 UUID with the information in the arguements. 00363 uuid.time_low (static_cast<ACE_UINT32> (timestamp & 0xFFFFFFFF)); 00364 uuid.time_mid (static_cast<ACE_UINT16> ((timestamp >> 32) & 0xFFFF)); 00365 00366 ACE_UINT16 tHAV = static_cast<ACE_UINT16> ((timestamp >> 48) & 0xFFFF); 00367 tHAV |= (version << 12); 00368 uuid.time_hi_and_version (tHAV); 00369 00370 u_char cseqHAV; 00371 uuid.clock_seq_low (static_cast<u_char> (clock_sequence & 0xFF)); 00372 cseqHAV = static_cast<u_char> ((clock_sequence & 0x3f00) >> 8); 00373 uuid_state_.timestamp = timestamp; 00374 00375 cseqHAV |= variant; 00376 uuid.clock_seq_hi_and_reserved (cseqHAV); 00377 uuid.node (uuid_state_.node); 00378 00379 if (variant == 0xc0) 00380 { 00381 ACE_Thread_ID thread_id; 00382 char buf [BUFSIZ]; 00383 thread_id.to_string (buf); 00384 uuid.thr_id (buf); 00385 00386 ACE_OS::sprintf (buf, 00387 "%d", 00388 static_cast<int> (ACE_OS::getpid ())); 00389 uuid.pid (buf); 00390 } 00391 } 00392 00393 UUID* 00394 UUID_Generator::generate_UUID (ACE_UINT16 version, u_char variant) 00395 { 00396 UUID* uuid; 00397 ACE_NEW_RETURN (uuid, 00398 UUID, 00399 0); 00400 00401 this->generate_UUID (*uuid, version, variant); 00402 return uuid; 00403 } 00404 00405 /// Obtain a new timestamp. If UUID's are being generated too quickly 00406 /// the clock sequence will be incremented 00407 void 00408 UUID_Generator::get_timestamp (UUID_Time& timestamp) 00409 { 00410 ACE_GUARD (ACE_SYNCH_MUTEX, mon, *lock_); 00411 00412 this->get_systemtime (timestamp); 00413 00414 // Account for the clock being set back. Increment the clock / 00415 // sequence. 00416 if (timestamp <= time_last_) 00417 { 00418 uuid_state_.clock_sequence = static_cast<ACE_UINT16> 00419 ((uuid_state_.clock_sequence + 1) & ACE_UUID_CLOCK_SEQ_MASK); 00420 } 00421 // If the system time ticked since the last UUID was 00422 // generated. Set / the clock sequence back. 00423 else if (timestamp > time_last_) 00424 { 00425 uuid_state_.clock_sequence = 0; 00426 } 00427 00428 time_last_ = timestamp; 00429 } 00430 00431 void 00432 UUID_Generator::get_timestamp_and_clocksequence (UUID_Time& timestamp, 00433 ACE_UINT16& clock_sequence) 00434 { 00435 ACE_GUARD (ACE_SYNCH_MUTEX, mon, *lock_); 00436 00437 this->get_systemtime (timestamp); 00438 00439 // Account for the clock being set back. Increment the clock / 00440 // sequence. 00441 if (timestamp <= time_last_) 00442 uuid_state_.clock_sequence = static_cast<ACE_UINT16> ((uuid_state_.clock_sequence + 1) & ACE_UUID_CLOCK_SEQ_MASK); 00443 00444 // If the system time ticked since the last UUID was 00445 // generated. Set / the clock sequence back. 00446 else if (timestamp > time_last_) 00447 uuid_state_.clock_sequence = 0; 00448 00449 time_last_ = timestamp; 00450 clock_sequence = uuid_state_.clock_sequence; 00451 } 00452 00453 /** 00454 * ACE_Time_Value is in POSIX time, seconds since Jan 1, 1970. UUIDs use 00455 * time in 100ns ticks since 15 October 1582. The difference is: 00456 * 15 Oct 1582 - 1 Jan 1600: 17 days in Oct, 30 in Nov, 31 in Dec + 00457 * 17 years and 4 leap days (1584, 88, 92 and 96) 00458 * 1 Jan 1600 - 1 Jan 1900: 3 centuries + 73 leap days ( 25 in 17th cent. 00459 * and 24 each in 18th and 19th centuries) 00460 * 1 Jan 1900 - 1 Jan 1970: 70 years + 17 leap days. 00461 * This adds up, in days: (17+30+31+365*17+4)+ (365*300+73)+ (365*70+17) or 00462 * 122192928000000000U (0x1B21DD213814000) 100 ns ticks. 00463 */ 00464 void 00465 UUID_Generator::get_systemtime (UUID_Time & timestamp) 00466 { 00467 const UUID_Time timeOffset = 00468 #if defined (ACE_LACKS_UNSIGNEDLONGLONG_T) 00469 ACE_U_LongLong (ACE_INT64_LITERAL (0x1B21DD213814000)); 00470 #elif defined (ACE_LACKS_LONGLONG_T) 00471 ACE_U_LongLong (0x13814000u, 0x1B21DD2u); 00472 #else 00473 ACE_UINT64_LITERAL (0x1B21DD213814000); 00474 #endif /* ACE_LACKS_UNSIGNEDLONGLONG_T */ 00475 00476 /// Get the time of day, convert to 100ns ticks then add the offset. 00477 ACE_Time_Value now = ACE_OS::gettimeofday (); 00478 ACE_UINT64 time; 00479 now.to_usec (time); 00480 time = time * 10; 00481 timestamp = time + timeOffset; 00482 } 00483 00484 ACE_SYNCH_MUTEX* 00485 UUID_Generator::lock (void) 00486 { 00487 return this->lock_; 00488 } 00489 00490 void 00491 UUID_Generator::lock (ACE_SYNCH_MUTEX* lock, bool release_lock) 00492 { 00493 if (this->destroy_lock_) 00494 delete this->lock_; 00495 00496 this->lock_ = lock; 00497 this->destroy_lock_ = release_lock; 00498 } 00499 }
1.6.1