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 88515 2010-01-13 08:47:38Z johnnyw $")
00021
00022
00023 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00024
00025 namespace ACE_Utils
00026 {
00027
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 {
00041
00042
00043 if (0 != this->as_string_.get ())
00044 {
00045 if (0 == rhs.as_string_.get () || *this != rhs)
00046 this->as_string_.reset ();
00047 }
00048
00049
00050 ACE_OS::memcpy (&this->uuid_, &rhs.uuid_, BINARY_SIZE);
00051
00052
00053
00054 this->thr_id_ = rhs.thr_id_;
00055 this->pid_ = rhs.pid_;
00056 }
00057
00058 return *this;
00059 }
00060
00061 const ACE_CString * UUID::to_string (void) const
00062 {
00063
00064 if (0 != this->as_string_.get ())
00065 return this->as_string_.get ();
00066
00067
00068
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
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;
00099 ACE_NEW_RETURN (buf,
00100 char[UUID_STRING_LENGTH + 1],
00101 0);
00102
00103
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
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
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
00163
00164
00165
00166
00167 const int nScanned =
00168 #if defined (ACE_HAS_TR24731_2005_CRT)
00169 sscanf_s (
00170 #else
00171 ::sscanf (
00172 #endif
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
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
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
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 const 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
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 = 0;
00397 ACE_NEW_RETURN (uuid,
00398 UUID,
00399 0);
00400
00401 this->generate_UUID (*uuid, version, variant);
00402 return uuid;
00403 }
00404
00405
00406
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
00415
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
00422
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
00440
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
00445
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
00455
00456
00457
00458
00459
00460
00461
00462
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
00475
00476
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 }
00500
00501 #if defined (ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION)
00502 template ACE_Singleton <ACE_Utils::UUID_Generator, ACE_SYNCH_MUTEX> *
00503 ACE_Singleton <ACE_Utils::UUID_Generator, ACE_SYNCH_MUTEX>::singleton_;
00504 #endif
00505
00506 ACE_END_VERSIONED_NAMESPACE_DECL