UUID.cpp

Go to the documentation of this file.
00001 //UUID.cpp,v 1.31 2006/04/19 19:13:09 jwillemsen Exp
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 /* __ACE_INLINE__ */
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            "UUID.cpp,v 1.31 2006/04/19 19:13:09 jwillemsen Exp")
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   /// Construct a nil UUID. Such a UUID has every one of it's data
00054   /// elements set to zero.
00055   UUID::UUID(void)
00056     : timeLow_ (0),
00057       timeMid_ (0),
00058     timeHiAndVersion_ (0),
00059       clockSeqHiAndReserved_ (0),
00060       clockSeqLow_ (0),
00061       as_string_ (0)
00062   {
00063     ACE_NEW (node_,
00064              UUID_node);
00065 
00066     node_release_ = 1;
00067   }
00068 
00069   /// Construct a UUID from a string representation of an UUID.
00070   UUID::UUID (const ACE_CString& uuid_string)
00071     : timeLow_ (0),
00072       timeMid_ (0),
00073       timeHiAndVersion_ (0),
00074       clockSeqHiAndReserved_ (0),
00075       clockSeqLow_ (0),
00076       as_string_ (0)
00077   {
00078     ACE_NEW (node_,
00079              UUID_node);
00080 
00081     node_release_ = 1;
00082 
00083 
00084     if (uuid_string.length() < NIL_UUID.to_string ()->length ())
00085       {
00086         ACE_DEBUG ((LM_DEBUG,
00087                     "%N ACE_UUID::UUID - "
00088                     "IllegalArgument(incorrect string length)\n"));
00089         return;
00090       }
00091 
00092     /// Special case for the nil UUID.
00093     if (uuid_string == *NIL_UUID.to_string ())
00094       {
00095         bool copy_constructor_not_supported = false;
00096         ACE_ASSERT (copy_constructor_not_supported);
00097         //*this = NIL_UUID;
00098         ACE_UNUSED_ARG (copy_constructor_not_supported);
00099         return;
00100       }
00101 
00102     unsigned int timeLow;
00103     unsigned int timeMid;
00104     unsigned int timeHiAndVersion;
00105     unsigned int clockSeqHiAndReserved;
00106     unsigned int clockSeqLow;
00107     unsigned int node [UUID_node::NODE_ID_SIZE];
00108     char thr_pid_buf [BUFSIZ];
00109 
00110     if (uuid_string.length() == NIL_UUID.to_string()->length())
00111       {
00112         // This might seem quite strange this being in ACE, but it
00113         // seems to be a bit difficult to write a facade for ::sscanf
00114         // because some compilers dont support vsscanf, including
00115         // MSVC. It appears that most platforms support sscanf though
00116         // so we need to use it directly.
00117         const int nScanned =
00118           ::sscanf(uuid_string.c_str(),
00119                    "%8x-%4x-%4x-%2x%2x-%2x%2x%2x%2x%2x%2x",
00120                    &timeLow,
00121                    &timeMid,
00122                    &timeHiAndVersion,
00123                    &clockSeqHiAndReserved,
00124                    &clockSeqLow,
00125                    &node[0],
00126                    &node[1],
00127                    &node[2],
00128                    &node[3],
00129                    &node[4],
00130                    &node[5]
00131                    );
00132 
00133         if (nScanned != 11)
00134           {
00135             ACE_DEBUG ((LM_DEBUG,
00136                         "UUID::UUID - "
00137                         "IllegalArgument(invalid string representation)\n"));
00138             return;
00139           }
00140       }
00141     else
00142       {
00143         const int nScanned =
00144           ::sscanf (uuid_string.c_str(),
00145                     "%8x-%4x-%4x-%2x%2x-%2x%2x%2x%2x%2x%2x-%s",
00146                     &timeLow,
00147                     &timeMid,
00148                     &timeHiAndVersion,
00149                     &clockSeqHiAndReserved,
00150                     &clockSeqLow,
00151                     &node[0],
00152                     &node[1],
00153                     &node[2],
00154                     &node[3],
00155                     &node[4],
00156                     &node[5],
00157                     thr_pid_buf
00158                     );
00159 
00160         if (nScanned != 12)
00161           {
00162             ACE_DEBUG ((LM_DEBUG,
00163                         "ACE_UUID::ACE_UUID - "
00164                         "IllegalArgument(invalid string representation)\n"));
00165             return;
00166           }
00167       }
00168 
00169     this->timeLow_ = static_cast<ACE_UINT32> (timeLow);
00170     this->timeMid_ = static_cast<ACE_UINT16> (timeMid);
00171     this->timeHiAndVersion_ = static_cast<ACE_UINT16> (timeHiAndVersion);
00172     this->clockSeqHiAndReserved_ = static_cast<u_char> (clockSeqHiAndReserved);
00173     this->clockSeqLow_ = static_cast<u_char> (clockSeqLow);
00174 
00175     UUID_node::NodeID nodeID;
00176     for (int i = 0; i < UUID_node::NODE_ID_SIZE; ++i)
00177       nodeID [i] = static_cast<u_char> (node[i]);
00178 
00179     this->node_->nodeID (nodeID);
00180 
00181     // Support varient 10- only
00182     if ((this->clockSeqHiAndReserved_ & 0xc0) != 0x80 && (this->clockSeqHiAndReserved_ & 0xc0) != 0xc0)
00183       {
00184         ACE_DEBUG ((LM_DEBUG,
00185                     "ACE_UUID_Impl::ACE_UUID_Impl - "
00186                     "IllegalArgument(unsupported variant)\n"));
00187         return;
00188       }
00189 
00190     /// Support versions 1, 3, and 4 only
00191     ACE_UINT16 V1 = this->timeHiAndVersion_;
00192 
00193     if ((V1 & 0xF000) != 0x1000 &&
00194         (V1 & 0xF000) != 0x3000 &&
00195       (V1 & 0xF000) != 0x4000)
00196       {
00197         ACE_DEBUG ((LM_DEBUG,
00198                     "ACE_UUID::ACE_UUID - "
00199                     "IllegalArgument(unsupported version)\n"));
00200         return;
00201       }
00202     if ((this->clockSeqHiAndReserved_ & 0xc0) == 0xc0)
00203       {
00204         if (uuid_string.length() == NIL_UUID.to_string()->length())
00205           {
00206             ACE_DEBUG ((LM_DEBUG,
00207                       "ACE_UUID::ACE_UUID - "
00208                         "IllegalArgument (Missing Thread and Process Id)\n"));
00209             return;
00210           }
00211         ACE_CString thr_pid_str (thr_pid_buf);
00212         ssize_t pos = thr_pid_str.find ('-');
00213         if (pos == -1)
00214           ACE_DEBUG ((LM_DEBUG,
00215                       "ACE_UUID::ACE_UUID - "
00216                       "IllegalArgument (Thread and Process Id format incorrect)\n"));
00217 
00218         this->thr_id_ = thr_pid_str.substr (0, pos);
00219       this->pid_ = thr_pid_str.substr (pos+1, thr_pid_str.length ()-pos-1);
00220       }
00221   }
00222 
00223   UUID::~UUID (void)
00224   {
00225     if (node_release_)
00226       delete node_;
00227 
00228     if (as_string_ != 0)
00229       delete as_string_;
00230   }
00231 
00232   const ACE_CString*
00233   UUID::to_string (void)
00234   {
00235     /// Only compute the string representation once.
00236     if (as_string_ == 0)
00237       {
00238         // Get a buffer exactly the correct size. Use the nil UUID as a
00239         // gauge.  Don't forget the trailing nul.
00240         size_t UUID_STRING_LENGTH = 36 + thr_id_.length () + pid_.length ();
00241         char *buf;
00242 
00243         if ((thr_id_.length () != 0) && (pid_.length () != 0))
00244           {
00245             UUID_STRING_LENGTH += 2; //for '-'
00246             ACE_NEW_RETURN (buf,
00247                             char[UUID_STRING_LENGTH + 1],
00248                             0);
00249 
00250             ACE_OS::sprintf(buf,
00251                             "%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x-%s-%s",
00252                             this->timeLow_,
00253                             this->timeMid_,
00254                             this->timeHiAndVersion_,
00255                             this->clockSeqHiAndReserved_,
00256                             this->clockSeqLow_,
00257                             (this->node_->nodeID ()) [0],
00258                             (this->node_->nodeID ()) [1],
00259                             (this->node_->nodeID ()) [2],
00260                             (this->node_->nodeID ()) [3],
00261                             (this->node_->nodeID ()) [4],
00262                             (this->node_->nodeID ()) [5],
00263                             thr_id_.c_str (),
00264                             pid_.c_str ()
00265                             );
00266           }
00267         else
00268           {
00269             ACE_NEW_RETURN (buf,
00270                             char[UUID_STRING_LENGTH + 1],
00271                             0);
00272 
00273             ACE_OS::sprintf (buf,
00274                              "%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x",
00275                              this->timeLow_,
00276                              this->timeMid_,
00277                              this->timeHiAndVersion_,
00278                              this->clockSeqHiAndReserved_,
00279                              this->clockSeqLow_,
00280                              (this->node_->nodeID ()) [0],
00281                              (this->node_->nodeID ()) [1],
00282                              (this->node_->nodeID ()) [2],
00283                              (this->node_->nodeID ()) [3],
00284                              (this->node_->nodeID ()) [4],
00285                              (this->node_->nodeID ()) [5]
00286                              );
00287           }
00288 
00289         ACE_NEW_RETURN (this->as_string_,
00290                         ACE_CString (buf, UUID_STRING_LENGTH),
00291                         0);
00292         delete [] buf;
00293       }
00294 
00295     return as_string_;
00296   }
00297 
00298   UUID_Generator::UUID_Generator ()
00299     : timeLast_ (0)
00300   {
00301     ACE_NEW (lock_,
00302              ACE_SYNCH_MUTEX);
00303     destroy_lock_ = 1;
00304   }
00305 
00306   UUID_Generator::~UUID_Generator()
00307   {
00308     if (destroy_lock_)
00309       delete lock_;
00310   }
00311 
00312   void
00313   UUID_Generator::init (void)
00314   {
00315     ACE_OS::macaddr_node_t macaddress;
00316     int result =
00317       ACE_OS::getmacaddress (&macaddress);
00318 
00319     UUID_node::NodeID nodeID;
00320     if (result != -1)
00321       {
00322 //         ACE_DEBUG ((LM_DEBUG,
00323 //                     "%02X-%02X-%02X-%02X-%02X-%02X\n",
00324 //                     macaddress.node [0],
00325 //                     macaddress.node [1],
00326 //                     macaddress.node [2],
00327 //                     macaddress.node [3],
00328 //                     macaddress.node [4],
00329 //                     macaddress.node [5]));
00330 
00331         ACE_OS::memcpy (&nodeID,
00332                         macaddress.node,
00333                         sizeof (nodeID));
00334       }
00335     else
00336       {
00337         nodeID [0] = static_cast<u_char> (ACE_OS::rand());
00338         nodeID [1] = static_cast<u_char> (ACE_OS::rand());
00339         nodeID [2] = static_cast<u_char> (ACE_OS::rand());
00340         nodeID [3] = static_cast<u_char> (ACE_OS::rand());
00341         nodeID [4] = static_cast<u_char> (ACE_OS::rand());
00342         nodeID [5] = static_cast<u_char> (ACE_OS::rand());
00343       }
00344 
00345     this->get_timestamp (timeLast_);
00346 
00347     {
00348       ACE_GUARD (ACE_SYNCH_MUTEX, ace_mon, *lock_);
00349       uuid_state_.timestamp = timeLast_;
00350       uuid_state_.node.nodeID (nodeID);
00351     }
00352   }
00353 
00354 
00355   void
00356   UUID_Generator::generateUUID (UUID& uuid,ACE_UINT16 version, u_char variant)
00357   {
00358     UUID_time timestamp;
00359     this->get_timestamp (timestamp);
00360 
00361 
00362     // Construct a Version 1 UUID with the information in the arguements.
00363     uuid.timeLow (static_cast<ACE_UINT32> (timestamp & 0xFFFFFFFF));
00364     uuid.timeMid (static_cast<ACE_UINT16> ((timestamp >> 32) & 0xFFFF));
00365 
00366 
00367     ACE_UINT16 tHAV = static_cast<ACE_UINT16> ((timestamp >> 48) & 0xFFFF);
00368     tHAV |= (version << 12);
00369     uuid.timeHiAndVersion (tHAV);
00370 
00371     u_char cseqHAV;
00372     {
00373       ACE_GUARD (ACE_SYNCH_MUTEX, mon, *lock_);
00374       uuid.clockSeqLow (static_cast<u_char> (uuid_state_.clockSequence & 0xFF));
00375       cseqHAV = static_cast<u_char> ((uuid_state_.clockSequence & 0x3f00) >> 8);
00376       uuid_state_.timestamp = timestamp;
00377     }
00378 
00379     cseqHAV |= variant;
00380     uuid.clockSeqHiAndReserved (cseqHAV);
00381     uuid.node (&(uuid_state_.node));
00382 
00383     if (variant == 0xc0)
00384     {
00385       ACE_Thread_ID thread_id;
00386       char buf [BUFSIZ];
00387       thread_id.to_string (buf);
00388       uuid.thr_id (buf);
00389 
00390       ACE_OS::sprintf (buf,
00391                        "%d",
00392                        static_cast<int> (ACE_OS::getpid ()));
00393       uuid.pid (buf);
00394     }
00395   }
00396 
00397   UUID*
00398   UUID_Generator::generateUUID (ACE_UINT16 version, u_char variant)
00399   {
00400     UUID* uuid;
00401     ACE_NEW_RETURN (uuid,
00402                     UUID,
00403                     0);
00404 
00405     this->generateUUID (*uuid, version, variant);
00406     return uuid;
00407   }
00408 
00409   /// Obtain a new timestamp. If UUID's are being generated too quickly
00410   /// the clock sequence will be incremented
00411   void
00412   UUID_Generator::get_timestamp (UUID_time& timestamp)
00413   {
00414     ACE_GUARD (ACE_SYNCH_MUTEX, mon, *lock_);
00415 
00416     this->get_systemtime(timestamp);
00417 
00418     // Account for the clock being set back. Increment the clock /
00419     // sequence.
00420     if (timestamp <= timeLast_)
00421       uuid_state_.clockSequence = static_cast<u_char> ((uuid_state_.clockSequence + 1) & ACE_UUID_CLOCK_SEQ_MASK);
00422 
00423     // If the system time ticked since the last UUID was
00424     // generated. Set / the clock sequence back.
00425     else if (timestamp > timeLast_)
00426       uuid_state_.clockSequence = 0;
00427 
00428     timeLast_ = timestamp;
00429   }
00430 
00431   /**
00432    * ACE_Time_Value is in POSIX time, seconds since Jan 1, 1970. UUIDs use
00433    * time in 100ns ticks since 15 October 1582. The difference is:
00434    *   15 Oct 1582 - 1 Jan 1600: 17 days in Oct, 30 in Nov,  31 in Dec +
00435    *       17 years and 4 leap days (1584, 88, 92 and 96)
00436    *   1 Jan 1600 - 1 Jan 1900: 3 centuries + 73 leap days ( 25 in 17th cent.
00437    *       and 24 each in 18th and 19th centuries)
00438    *   1 Jan 1900 - 1 Jan 1970: 70 years + 17 leap days.
00439    * This adds up, in days: (17+30+31+365*17+4)+(365*300+73)+(365*70+17) or
00440    * 122192928000000000U (0x1B21DD213814000) 100 ns ticks.
00441    */
00442   void
00443   UUID_Generator::get_systemtime (UUID_time & timestamp)
00444   {
00445     const UUID_time timeOffset = ACE_UINT64_LITERAL (0x1B21DD213814000);
00446 
00447     /// Get the time of day, convert to 100ns ticks then add the offset.
00448     ACE_Time_Value now = ACE_OS::gettimeofday();
00449     ACE_UINT64 time;
00450     now.to_usec (time);
00451     time = time * 10;
00452     timestamp = time + timeOffset;
00453 }
00454 
00455   ACE_SYNCH_MUTEX*
00456   UUID_Generator::lock (void)
00457   {
00458     return this->lock_;
00459   }
00460 
00461   ACE_SYNCH_MUTEX*
00462   UUID_Generator::lock (ACE_SYNCH_MUTEX* lock,
00463                         int release_lock_)
00464   {
00465     if (destroy_lock_)
00466       delete lock_;
00467 
00468     ACE_SYNCH_MUTEX* prev_lock = this->lock_;
00469     this->lock_ = lock;
00470     this->destroy_lock_ = release_lock_;
00471     return prev_lock;
00472   }
00473 
00474 }
00475 
00476 #if defined (ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION)
00477 template ACE_Singleton<ACE_Utils::UUID_Generator, ACE_SYNCH_MUTEX> *
00478   ACE_Singleton<ACE_Utils::UUID_Generator, ACE_SYNCH_MUTEX>::singleton_;
00479 #endif /* ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION */
00480 
00481 ACE_END_VERSIONED_NAMESPACE_DECL

Generated on Thu Nov 9 09:42:09 2006 for ACE by doxygen 1.3.6