00001
00002
00003 #include "ace/UUID.h"
00004 #include "ace/Guard_T.h"
00005
00006 #if !defined (__ACE_INLINE__)
00007 #include "ace/UUID.inl"
00008 #endif
00009
00010 #include "ace/Log_Msg.h"
00011 #include "ace/OS_NS_stdio.h"
00012 #include "ace/OS_NS_string.h"
00013 #include "ace/OS_NS_sys_time.h"
00014 #include "ace/OS_NS_netdb.h"
00015 #include "ace/OS_NS_unistd.h"
00016 #include "ace/ACE.h"
00017
00018 ACE_RCSID (ace,
00019 UUID,
00020 "$Id: UUID.cpp 81541 2008-04-30 13:56:12Z shuston $")
00021
00022
00023 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00024
00025 namespace ACE_Utils
00026 {
00027 UUID_Node::UUID_Node (void)
00028 {
00029 for (int i = 0; i < UUID_Node::NODE_ID_SIZE; ++i)
00030 node_ID_[i] = 0;
00031 }
00032
00033 UUID_Node::Node_ID&
00034 UUID_Node::node_ID (void)
00035 {
00036 return node_ID_;
00037 }
00038
00039 void
00040 UUID_Node::node_ID (Node_ID& node_ID)
00041 {
00042 for (int i = 0; i < UUID_Node::NODE_ID_SIZE; ++i)
00043 node_ID_[i] = node_ID[i];
00044 }
00045
00046 UUID UUID::NIL_UUID;
00047
00048
00049
00050 UUID::UUID (void)
00051 : time_low_ (0),
00052 time_mid_ (0),
00053 time_hi_and_version_ (0),
00054 clock_seq_hi_and_reserved_ (0),
00055 clock_seq_low_ (0),
00056 node_ (0),
00057 node_release_ (true),
00058 as_string_ (0)
00059 {
00060 ACE_NEW (node_,
00061 UUID_Node);
00062 }
00063
00064
00065 UUID::UUID (const ACE_CString& uuid_string)
00066 : time_low_ (0),
00067 time_mid_ (0),
00068 time_hi_and_version_ (0),
00069 clock_seq_hi_and_reserved_ (0),
00070 clock_seq_low_ (0),
00071 node_ (0),
00072 node_release_ (true),
00073 as_string_ (0)
00074 {
00075 ACE_NEW (node_,
00076 UUID_Node);
00077
00078 this->from_string_i (uuid_string);
00079 }
00080
00081 UUID::UUID (const UUID &right)
00082 : time_low_ (right.time_low_),
00083 time_mid_ (right.time_mid_),
00084 time_hi_and_version_ (right.time_hi_and_version_),
00085 clock_seq_hi_and_reserved_ (right.clock_seq_hi_and_reserved_),
00086 clock_seq_low_ (right.clock_seq_low_),
00087 as_string_ (0)
00088 {
00089 ACE_NEW (node_,
00090 UUID_Node (*right.node_));
00091 }
00092
00093 UUID::~UUID (void)
00094 {
00095 if (node_release_)
00096 delete node_;
00097
00098 if (as_string_ != 0)
00099 delete as_string_;
00100 }
00101
00102 const ACE_CString*
00103 UUID::to_string (void)
00104 {
00105
00106 if (as_string_ == 0)
00107 {
00108
00109
00110 size_t UUID_STRING_LENGTH = 36 + thr_id_.length () + pid_.length ();
00111 char *buf = 0;
00112
00113 if ((thr_id_.length () != 0) && (pid_.length () != 0))
00114 {
00115 UUID_STRING_LENGTH += 2;
00116 ACE_NEW_RETURN (buf,
00117 char[UUID_STRING_LENGTH + 1],
00118 0);
00119
00120 ACE_OS::sprintf (buf,
00121 "%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x-%s-%s",
00122 this->time_low_,
00123 this->time_mid_,
00124 this->time_hi_and_version_,
00125 this->clock_seq_hi_and_reserved_,
00126 this->clock_seq_low_,
00127 (this->node_->node_ID ()) [0],
00128 (this->node_->node_ID ()) [1],
00129 (this->node_->node_ID ()) [2],
00130 (this->node_->node_ID ()) [3],
00131 (this->node_->node_ID ()) [4],
00132 (this->node_->node_ID ()) [5],
00133 thr_id_.c_str (),
00134 pid_.c_str ()
00135 );
00136 }
00137 else
00138 {
00139 ACE_NEW_RETURN (buf,
00140 char[UUID_STRING_LENGTH + 1],
00141 0);
00142
00143 ACE_OS::sprintf (buf,
00144 "%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x",
00145 this->time_low_,
00146 this->time_mid_,
00147 this->time_hi_and_version_,
00148 this->clock_seq_hi_and_reserved_,
00149 this->clock_seq_low_,
00150 (this->node_->node_ID ()) [0],
00151 (this->node_->node_ID ()) [1],
00152 (this->node_->node_ID ()) [2],
00153 (this->node_->node_ID ()) [3],
00154 (this->node_->node_ID ()) [4],
00155 (this->node_->node_ID ()) [5]
00156 );
00157 }
00158
00159
00160
00161 ACE_NEW_NORETURN (this->as_string_,
00162 ACE_CString (buf, UUID_STRING_LENGTH));
00163
00164
00165 delete [] buf;
00166
00167
00168
00169 if (this->as_string_ == 0 )
00170 return 0;
00171 }
00172
00173 return as_string_;
00174 }
00175
00176 void
00177 UUID::from_string_i (const ACE_CString& uuid_string)
00178 {
00179 if (uuid_string.length () < NIL_UUID.to_string ()->length ())
00180 {
00181 ACE_ERROR ((LM_ERROR,
00182 "%N ACE_UUID::from_string_i - "
00183 "IllegalArgument (incorrect string length)\n"));
00184 return;
00185 }
00186
00187
00188 if (uuid_string == *NIL_UUID.to_string ())
00189 {
00190 bool copy_constructor_not_supported = false;
00191 ACE_ASSERT (copy_constructor_not_supported);
00192
00193 ACE_UNUSED_ARG (copy_constructor_not_supported);
00194 return;
00195 }
00196
00197 unsigned int time_low;
00198 unsigned int time_mid;
00199 unsigned int time_hi_and_version;
00200 unsigned int clock_seq_hi_and_reserved;
00201 unsigned int clock_seq_low;
00202 unsigned int node [UUID_Node::NODE_ID_SIZE];
00203 char thr_pid_buf [BUFSIZ];
00204
00205 if (uuid_string.length () == NIL_UUID.to_string ()->length ())
00206 {
00207
00208
00209
00210
00211
00212 const int nScanned =
00213 #if defined (ACE_HAS_TR24731_2005_CRT)
00214 sscanf_s (
00215 #else
00216 ::sscanf (
00217 #endif
00218 uuid_string.c_str (),
00219 "%8x-%4x-%4x-%2x%2x-%2x%2x%2x%2x%2x%2x",
00220 &time_low,
00221 &time_mid,
00222 &time_hi_and_version,
00223 &clock_seq_hi_and_reserved,
00224 &clock_seq_low,
00225 &node[0],
00226 &node[1],
00227 &node[2],
00228 &node[3],
00229 &node[4],
00230 &node[5]
00231 );
00232
00233 if (nScanned != 11)
00234 {
00235 ACE_DEBUG ((LM_DEBUG,
00236 "UUID::from_string_i - "
00237 "IllegalArgument (invalid string representation)\n"));
00238 return;
00239 }
00240 }
00241 else
00242 {
00243 const int nScanned =
00244 #if defined (ACE_HAS_TR24731_2005_CRT)
00245 sscanf_s (uuid_string.c_str (),
00246 "%8x-%4x-%4x-%2x%2x-%2x%2x%2x%2x%2x%2x-%s",
00247 &time_low,
00248 &time_mid,
00249 &time_hi_and_version,
00250 &clock_seq_hi_and_reserved,
00251 &clock_seq_low,
00252 &node[0],
00253 &node[1],
00254 &node[2],
00255 &node[3],
00256 &node[4],
00257 &node[5],
00258 thr_pid_buf,
00259 BUFSIZ
00260 );
00261 #else
00262 ::sscanf (uuid_string.c_str (),
00263 "%8x-%4x-%4x-%2x%2x-%2x%2x%2x%2x%2x%2x-%s",
00264 &time_low,
00265 &time_mid,
00266 &time_hi_and_version,
00267 &clock_seq_hi_and_reserved,
00268 &clock_seq_low,
00269 &node[0],
00270 &node[1],
00271 &node[2],
00272 &node[3],
00273 &node[4],
00274 &node[5],
00275 thr_pid_buf
00276 );
00277 #endif
00278
00279 if (nScanned != 12)
00280 {
00281 ACE_DEBUG ((LM_DEBUG,
00282 "ACE_UUID::from_string_i - "
00283 "IllegalArgument (invalid string representation)\n"));
00284 return;
00285 }
00286 }
00287
00288 this->time_low_ = static_cast<ACE_UINT32> (time_low);
00289 this->time_mid_ = static_cast<ACE_UINT16> (time_mid);
00290 this->time_hi_and_version_ = static_cast<ACE_UINT16> (time_hi_and_version);
00291 this->clock_seq_hi_and_reserved_ = static_cast<u_char> (clock_seq_hi_and_reserved);
00292 this->clock_seq_low_ = static_cast<u_char> (clock_seq_low);
00293
00294 UUID_Node::Node_ID node_id;
00295 for (int i = 0; i < UUID_Node::NODE_ID_SIZE; ++i)
00296 node_id [i] = static_cast<u_char> (node[i]);
00297
00298 this->node_->node_ID (node_id);
00299
00300
00301 if ((this->clock_seq_hi_and_reserved_ & 0xc0) != 0x80 && (this->clock_seq_hi_and_reserved_ & 0xc0) != 0xc0)
00302 {
00303 ACE_DEBUG ((LM_DEBUG,
00304 "ACE_UUID::from_string_i - "
00305 "IllegalArgument (unsupported variant)\n"));
00306 return;
00307 }
00308
00309
00310 ACE_UINT16 V1 = this->time_hi_and_version_;
00311
00312 if ((V1 & 0xF000) != 0x1000 &&
00313 (V1 & 0xF000) != 0x3000 &&
00314 (V1 & 0xF000) != 0x4000)
00315 {
00316 ACE_DEBUG ((LM_DEBUG,
00317 "ACE_UUID::from_string_i - "
00318 "IllegalArgument (unsupported version)\n"));
00319 return;
00320 }
00321
00322 if ((this->clock_seq_hi_and_reserved_ & 0xc0) == 0xc0)
00323 {
00324 if (uuid_string.length () == NIL_UUID.to_string ()->length ())
00325 {
00326 ACE_DEBUG ((LM_DEBUG,
00327 "ACE_UUID::from_string_i - "
00328 "IllegalArgument (Missing Thread and Process Id)\n"));
00329 return;
00330 }
00331 ACE_CString thr_pid_str (thr_pid_buf);
00332 ssize_t pos = static_cast<ssize_t> (thr_pid_str.find ('-'));
00333 if (pos == -1)
00334 ACE_DEBUG ((LM_DEBUG,
00335 "ACE_UUID::from_string_i - "
00336 "IllegalArgument (Thread and Process Id format incorrect)\n"));
00337
00338 this->thr_id_ = thr_pid_str.substr (0, pos);
00339 this->pid_ = thr_pid_str.substr (pos+1, thr_pid_str.length ()-pos-1);
00340 }
00341 }
00342
00343 UUID_Generator::UUID_Generator ()
00344 : time_last_ (0),
00345 destroy_lock_ (true)
00346 {
00347 ACE_NEW (lock_,
00348 ACE_SYNCH_MUTEX);
00349 }
00350
00351 UUID_Generator::~UUID_Generator ()
00352 {
00353 if (destroy_lock_)
00354 delete lock_;
00355 }
00356
00357 void
00358 UUID_Generator::init (void)
00359 {
00360 ACE_OS::macaddr_node_t macaddress;
00361 int result = ACE_OS::getmacaddress (&macaddress);
00362
00363 UUID_Node::Node_ID node_id;
00364 if (result != -1)
00365 {
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375 ACE_OS::memcpy (&node_id,
00376 macaddress.node,
00377 sizeof (node_id));
00378 }
00379 else
00380 {
00381 node_id [0] = static_cast<u_char> (ACE_OS::rand ());
00382 node_id [1] = static_cast<u_char> (ACE_OS::rand ());
00383 node_id [2] = static_cast<u_char> (ACE_OS::rand ());
00384 node_id [3] = static_cast<u_char> (ACE_OS::rand ());
00385 node_id [4] = static_cast<u_char> (ACE_OS::rand ());
00386 node_id [5] = static_cast<u_char> (ACE_OS::rand ());
00387 }
00388
00389 this->get_timestamp (time_last_);
00390
00391 {
00392 ACE_GUARD (ACE_SYNCH_MUTEX, ace_mon, *lock_);
00393 uuid_state_.timestamp = time_last_;
00394 uuid_state_.node.node_ID (node_id);
00395 }
00396 }
00397
00398 void
00399 UUID_Generator::generate_UUID (UUID& uuid,ACE_UINT16 version,
00400 u_char variant)
00401 {
00402 UUID_Time timestamp;
00403 ACE_UINT16 clock_sequence;
00404
00405 this->get_timestamp_and_clocksequence (timestamp,
00406 clock_sequence);
00407
00408
00409 uuid.time_low (static_cast<ACE_UINT32> (timestamp & 0xFFFFFFFF));
00410 uuid.time_mid (static_cast<ACE_UINT16> ((timestamp >> 32) & 0xFFFF));
00411
00412 ACE_UINT16 tHAV = static_cast<ACE_UINT16> ((timestamp >> 48) & 0xFFFF);
00413 tHAV |= (version << 12);
00414 uuid.time_hi_and_version (tHAV);
00415
00416 u_char cseqHAV;
00417 uuid.clock_seq_low (static_cast<u_char> (clock_sequence & 0xFF));
00418 cseqHAV = static_cast<u_char> ((clock_sequence & 0x3f00) >> 8);
00419 uuid_state_.timestamp = timestamp;
00420
00421 cseqHAV |= variant;
00422 uuid.clock_seq_hi_and_reserved (cseqHAV);
00423 uuid.node (& (uuid_state_.node));
00424
00425 if (variant == 0xc0)
00426 {
00427 ACE_Thread_ID thread_id;
00428 char buf [BUFSIZ];
00429 thread_id.to_string (buf);
00430 uuid.thr_id (buf);
00431
00432 ACE_OS::sprintf (buf,
00433 "%d",
00434 static_cast<int> (ACE_OS::getpid ()));
00435 uuid.pid (buf);
00436 }
00437 }
00438
00439 UUID*
00440 UUID_Generator::generate_UUID (ACE_UINT16 version, u_char variant)
00441 {
00442 UUID* uuid;
00443 ACE_NEW_RETURN (uuid,
00444 UUID,
00445 0);
00446
00447 this->generate_UUID (*uuid, version, variant);
00448 return uuid;
00449 }
00450
00451
00452
00453 void
00454 UUID_Generator::get_timestamp (UUID_Time& timestamp)
00455 {
00456 ACE_GUARD (ACE_SYNCH_MUTEX, mon, *lock_);
00457
00458 this->get_systemtime (timestamp);
00459
00460
00461
00462 if (timestamp <= time_last_)
00463 {
00464 uuid_state_.clock_sequence = static_cast<ACE_UINT16>
00465 ((uuid_state_.clock_sequence + 1) & ACE_UUID_CLOCK_SEQ_MASK);
00466 }
00467
00468
00469 else if (timestamp > time_last_)
00470 {
00471 uuid_state_.clock_sequence = 0;
00472 }
00473
00474 time_last_ = timestamp;
00475 }
00476
00477 void
00478 UUID_Generator::get_timestamp_and_clocksequence (UUID_Time& timestamp,
00479 ACE_UINT16& clock_sequence)
00480 {
00481 ACE_GUARD (ACE_SYNCH_MUTEX, mon, *lock_);
00482
00483 this->get_systemtime (timestamp);
00484
00485
00486
00487 if (timestamp <= time_last_)
00488 uuid_state_.clock_sequence = static_cast<ACE_UINT16> ((uuid_state_.clock_sequence + 1) & ACE_UUID_CLOCK_SEQ_MASK);
00489
00490
00491
00492 else if (timestamp > time_last_)
00493 uuid_state_.clock_sequence = 0;
00494
00495 time_last_ = timestamp;
00496 clock_sequence = uuid_state_.clock_sequence;
00497 }
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510 void
00511 UUID_Generator::get_systemtime (UUID_Time & timestamp)
00512 {
00513 const UUID_Time timeOffset =
00514 #if defined (ACE_LACKS_UNSIGNEDLONGLONG_T)
00515 ACE_U_LongLong (ACE_INT64_LITERAL (0x1B21DD213814000));
00516 #elif defined (ACE_LACKS_LONGLONG_T)
00517 ACE_U_LongLong (0x13814000u, 0x1B21DD2u);
00518 #else
00519 ACE_UINT64_LITERAL (0x1B21DD213814000);
00520 #endif
00521
00522
00523 ACE_Time_Value now = ACE_OS::gettimeofday ();
00524 ACE_UINT64 time;
00525 now.to_usec (time);
00526 time = time * 10;
00527 timestamp = time + timeOffset;
00528 }
00529
00530 ACE_SYNCH_MUTEX*
00531 UUID_Generator::lock (void)
00532 {
00533 return this->lock_;
00534 }
00535
00536 void
00537 UUID_Generator::lock (ACE_SYNCH_MUTEX* lock,
00538 bool release_lock)
00539 {
00540 if (this->destroy_lock_)
00541 delete this->lock_;
00542
00543 this->lock_ = lock;
00544 this->destroy_lock_ = release_lock;
00545 }
00546
00547 }
00548
00549 #if defined (ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION)
00550 template ACE_Singleton<ACE_Utils::UUID_Generator, ACE_SYNCH_MUTEX> *
00551 ACE_Singleton<ACE_Utils::UUID_Generator, ACE_SYNCH_MUTEX>::singleton_;
00552 #endif
00553
00554 ACE_END_VERSIONED_NAMESPACE_DECL