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