From 7b4de90ae18a722c57a55eeeacb91e437b636272 Mon Sep 17 00:00:00 2001 From: yamuna Date: Mon, 21 Jul 2003 06:01:30 +0000 Subject: ChangelogTag: Mon Jul 21 01:56:44 2003 Yamuna Krishnamurthy --- ace/Makefile.ace | 10 + ace/OS.cpp | 225 +++++++++++++++++++- ace/OS.h | 19 ++ ace/UUID.cpp | 513 ++++++++++++++++++++++++++++++++++++++++++++++ ace/UUID.h | 232 +++++++++++++++++++++ ace/UUID.i | 211 +++++++++++++++++++ ace/config-win32-common.h | 9 + 7 files changed, 1218 insertions(+), 1 deletion(-) create mode 100644 ace/UUID.cpp create mode 100644 ace/UUID.h create mode 100644 ace/UUID.i (limited to 'ace') diff --git a/ace/Makefile.ace b/ace/Makefile.ace index 8a3452dd3a7..924d3a494df 100644 --- a/ace/Makefile.ace +++ b/ace/Makefile.ace @@ -250,6 +250,8 @@ TOKEN_FILES = \ Token_Request_Reply CODECS_FILES = \ Codecs +UUID_FILES = \ + UUID OTHER_FILES = \ Local_Name_Space \ Name_Proxy \ @@ -370,6 +372,7 @@ ifndef ACE_COMPONENTS Timer \ Token \ Codecs \ + UUID \ Other endif # ACE_COMPONENTS @@ -388,6 +391,7 @@ ifeq (FOR_TAO,$(ACE_COMPONENTS)) Streams \ Memory \ Timer \ + UUID \ Codecs else # ! FOR_TAO #### TAO doesn't need Filecache. It costs 14 Kb. @@ -463,6 +467,12 @@ else # ! Other FILES += $(OTHER_FILES) endif # ! Other +ifeq (,$(findstring UUID,$(ACE_COMPONENTS))) + CCFLAGS += -DACE_LACKS_ACE_UUID +else # ! UUID + FILES += $(UUID_FILES) +endif # ! UUID + ifeq ($(AIX_TEMPLATE_HACK),1) FILES = 0_ACE_All_Src TEMPLATE_FILES = 0_ACE_All_Tmp diff --git a/ace/OS.cpp b/ace/OS.cpp index bd6375d8ced..8a1c3fbd21f 100644 --- a/ace/OS.cpp +++ b/ace/OS.cpp @@ -1,5 +1,6 @@ // $Id$ + #include "ace/OS.h" #include "ace/Sched_Params.h" #include "ace/OS_Thread_Adapter.h" @@ -1551,7 +1552,8 @@ ACE_OS::sched_params (const ACE_Sched_Params &sched_params, // Set the priority class of this process to the REALTIME process class // _if_ the policy is ACE_SCHED_FIFO. Otherwise, set to NORMAL. if (!::SetPriorityClass (::GetCurrentProcess (), - sched_params.policy () == ACE_SCHED_FIFO + (sched_params.policy () == ACE_SCHED_FIFO || + sched_params.policy () == ACE_SCHED_RR) ? REALTIME_PRIORITY_CLASS : NORMAL_PRIORITY_CLASS)) { @@ -4802,6 +4804,72 @@ ACE_Thread_ID::handle (ACE_hthread_t thread_handle) this->thread_handle_ = thread_handle; } +void +ACE_Thread_ID::to_string (char* thr_id) +{ + + ACE_TCHAR format[128]; // Converted format string + ACE_TCHAR *fp; // Current format pointer + fp = format; + *fp++ = '%'; // Copy in the % + +#if defined (ACE_WIN32) + ACE_OS::strcpy (fp, ACE_LIB_TEXT ("u")); + ACE_OS::sprintf (thr_id, + format, + ACE_static_cast(unsigned, + ACE_OS::thr_self ())); +#elif defined (ACE_AIX_VERS) && (ACE_AIX_VERS <= 402) + // AIX's pthread_t (ACE_hthread_t) is a pointer, and it's + // a little ugly to send that through a %u format. So, + // get the kernel thread ID (tid_t) via thread_self() and + // display that instead. + // This isn't conditionalized on ACE_HAS_THREAD_SELF because + // 1. AIX 4.2 doesn't have that def anymore (it messes up + // other things) + // 2. OSF/1 V3.2 has that def, and I'm not sure what affect + // this would have on that. + // -Steve Huston, 19-Aug-97 + ACE_OS::strcpy (fp, ACE_LIB_TEXT ("u")); + ACE_OS::sprintf (thr_id, format, thread_self()); +#elif defined (DIGITAL_UNIX) + ACE_OS::strcpy (fp, ACE_LIB_TEXT ("u")); + ACE_OS::sprintf (thr_id, format, +# if defined (ACE_HAS_THREADS) + pthread_getselfseq_np () +# else + ACE_Thread::self () +# endif /* ACE_HAS_THREADS */ + ); +#else + ACE_hthread_t t_id; + ACE_OS::thr_self (t_id); + +# if defined (ACE_HAS_PTHREADS_DRAFT4) && defined (HPUX_10) + ACE_OS::strcpy (fp, ACE_LIB_TEXT ("u")); + // HP-UX 10.x DCE's thread ID is a pointer. Grab the + // more meaningful, readable, thread ID. This will match + // the one seen in the debugger as well. + ACE_OS::sprintf (thr_id, format, + pthread_getunique_np(&t_id)); +# elif defined (ACE_MVS) + // MVS's pthread_t is a struct... yuck. So use the ACE 5.0 + // code for it. + ACE_OS::strcpy (fp, ACE_LIB_TEXT ("u")); + ACE_OS::sprintf (thr_id, format, t_id); +# else + // Yes, this is an ugly C-style cast, but the correct + // C++ cast is different depending on whether the t_id + // is an integral type or a pointer type. FreeBSD uses + // a pointer type, but doesn't have a _np function to + // get an integral type, like the OSes above. + ACE_OS::strcpy (fp, ACE_LIB_TEXT ("lu")); + ACE_OS::sprintf (thr_id, format, (unsigned long)t_id); +# endif /* ACE_HAS_PTHREADS_DRAFT4 && HPUX_10 */ + +#endif /* ACE_WIN32 */ +} + int ACE_Thread_ID::operator== (const ACE_Thread_ID &rhs) const { @@ -7639,3 +7707,158 @@ ACE_OS::num_processors_online (void) ACE_NOTSUP_RETURN (-1); #endif } + + +int +ACE_OS::getmacaddress (struct macaddr_node_t *node) +{ + ACE_OS_TRACE ("getmacaddr"); + +#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE) + + /** Define a structure for use with the netbios routine */ + struct ADAPTERSTAT + { + ADAPTER_STATUS adapt; + NAME_BUFFER NameBuff [30]; + }; + + NCB ncb; + LANA_ENUM lenum; + unsigned char result; + + ACE_OS::memset( &ncb, 0, sizeof(ncb) ); + ncb.ncb_command = NCBENUM; + ncb.ncb_buffer = ACE_reinterpret_cast (unsigned char*,&lenum); + ncb.ncb_length = sizeof(lenum); + + result = Netbios( &ncb ); + + for(int i=0; i < lenum.length ;i++) + { + ACE_OS::memset( &ncb, 0, sizeof(ncb)); + ncb.ncb_command = NCBRESET; + ncb.ncb_lana_num = lenum.lana[i]; + + /** Reset the netbios */ + result = Netbios( &ncb ); + + if (ncb.ncb_retcode != NRC_GOODRET) + { + return -1; + } + + ADAPTERSTAT adapter; + ACE_OS::memset( &ncb, 0, sizeof (ncb) ); + ACE_OS::strcpy(ACE_static_cast(char*,ncb.ncb_callname), "*"); + ncb.ncb_command = NCBASTAT; + ncb.ncb_lana_num = lenum.lana[i]; + ncb.ncb_buffer = ACE_reinterpret_cast (unsigned char*,&adapter); + ncb.ncb_length = sizeof(adapter); + + result = Netbios( &ncb ); + + if ( result == 0 ) + { + ACE_OS::memcpy ( + node->node, + adapter.adapt.adapter_address, + 6); + return 0; + } + } + return 0; +#elif defined (sun) + + int result = 0; + + /** obtain the local host name */ + char hostname[MAXHOSTNAMELEN]; + ACE_OS::hostname (hostname, sizeof (hostname)); + + /** Get the hostent to use with ioctl */ + struct hostent *phost = + ACE_OS::gethostbyname (hostname); + + if (phost == 0) + { + return -1; + } + + ACE_HANDLE handle = + ACE_OS::socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP); + + if (handle == ACE_INVALID_HANDLE) + { + return -1; + } + + char **paddrs = phost->h_addr_list; + + struct arpreq ar; + + struct sockaddr_in *psa = + (struct sockaddr_in *)&(ar.arp_pa); + + ACE_OS::memset ( + &ar, + 0, + sizeof (struct arpreq)); + + psa->sin_family = AF_INET; + + ACE_OS::memcpy ( + &(psa->sin_addr), + *paddrs, + sizeof( struct in_addr)); + + if (ACE_OS::ioctl ( handle, + SIOCGARP, + &ar) == -1) + { + return -1; + } + + ACE_OS::close (handle); + + ACE_OS::memcpy ( + node->node, + ar.arp_ha.sa_data, + 6); + + return 0; + +#elif defined (linux) + + struct ifreq ifr; + + ACE_HANDLE handle = + ACE_OS::socket(PF_INET, SOCK_DGRAM, 0); + + if (handle == ACE_INVALID_HANDLE) + { + return -1; + } + + ACE_OS::strcpy (ifr.ifr_name, "eth0"); + + if (ACE_OS::ioctl(handle/*s*/, SIOCGIFHWADDR, &ifr) < 0) + { + ACE_OS::close(handle); + return -1; + } + + struct sockaddr* sa = + (struct sockaddr *) &ifr.ifr_addr; + + ACE_OS::memcpy ( + node->node, + sa->sa_data, 6); + + return 0; + +#elif + ACE_UNUSED_ARG (node); + ACE_NOTSUP_RETURN (-1); +#endif +} diff --git a/ace/OS.h b/ace/OS.h index 1d4f1192be1..e976dffe15e 100644 --- a/ace/OS.h +++ b/ace/OS.h @@ -1836,6 +1836,9 @@ public: ACE_hthread_t handle (void); void handle (ACE_hthread_t); + void to_string (char*); + + // != Comparison operator. int operator== (const ACE_Thread_ID &) const; int operator!= (const ACE_Thread_ID &) const; @@ -2337,6 +2340,21 @@ public: // = A set of wrappers for miscellaneous operations. static int atoi (const char *s); + + // Include if_arp so that getmacaddr can use the + // arp structure. +# if defined (sun) +# include /**/ +# endif + + struct macaddr_node_t { + unsigned char node[6]; + }; + + /** + * Get the first adapter found on the machine. + */ + static int getmacaddress (struct macaddr_node_t *node); # if defined (ACE_HAS_WCHAR) static int atoi (const wchar_t *s); @@ -4700,3 +4718,4 @@ extern ACE_OS_Export int sys_nerr; #include /**/ "ace/post.h" #endif /* ACE_OS_H */ + diff --git a/ace/UUID.cpp b/ace/UUID.cpp new file mode 100644 index 00000000000..a7aafe8cba4 --- /dev/null +++ b/ace/UUID.cpp @@ -0,0 +1,513 @@ +//$Id$ +#include "ace/OS.h" +#include "ace/UUID.h" + +UUID_node::UUID_node (void) +{ + for (int i = 0; i < 6; i++) + { + nodeID_ [i] = 0; + } +} + +UUID_node::NodeID& +UUID_node::nodeID (void) +{ + return nodeID_; +} + +void +UUID_node::nodeID (NodeID& nodeID) +{ + for (int i = 0; i < 6; i++) + { + nodeID_ [i] = nodeID [i]; + } +} + +ACE_UUID ACE_UUID::NIL_UUID; + +/// Construct a nil UUID. Such a UUID has every one of it's data +/// elements set to zero. +ACE_UUID::ACE_UUID() + : timeLow_ (0), + timeMid_ (0), + timeHiAndVersion_ (0), + clockSeqHiAndReserved_ (0), + clockSeqLow_ (0), + as_string_ (0) +{ + ACE_NEW (node_, + UUID_node); + + node_release_ = 1; +} + +ACE_UUID::ACE_UUID(const ACE_UUID &right) + : timeLow_ (0), + timeMid_ (0), + timeHiAndVersion_ (0), + clockSeqHiAndReserved_ (0), + clockSeqLow_ (0), + as_string_ (0) +{ + node_release_ = 0; + *this = right; +} + +/// Construct a UUID from a string representation of an UUID. +ACE_UUID::ACE_UUID (const ACE_CString& uuid_string) + : timeLow_ (0), + timeMid_ (0), + timeHiAndVersion_ (0), + clockSeqHiAndReserved_ (0), + clockSeqLow_ (0), + as_string_ (0) +{ + ACE_NEW (node_, + UUID_node); + + node_release_ = 1; + + ACE_TRACE ("ACE_UUID::ACE_UUID"); + + if (uuid_string.length() < NIL_UUID.to_string()->length()) + { + ACE_DEBUG ((LM_DEBUG, + "%N ACE_UUID::ACE_UUID - " + "IllegalArgument(incorrect string length)")); + return; + } + + /// Special case for the nil UUID. + if (uuid_string == *NIL_UUID.to_string()) + { + *this = NIL_UUID; + return; + } + + int timeLow; + int timeMid; + int timeHiAndVersion; + int clockSeqHiAndReserved; + int clockSeqLow; + int node [UUID_node::NODE_ID_SIZE]; + char thr_pid_buf [BUFSIZ]; + + if (uuid_string.length() == NIL_UUID.to_string()->length()) + { + // This might seem quite strange this being in ACE, but it seems to + // be a bit difficult to write a facade for ::sscanf because some + // compilers dont support vsscanf, including MSVC. It appears that + // most platforms support sscanf though so we need to use it + // directly. +#if defined (ACE_HAS_PACE) + int nScanned = ::pace_sscanf(uuid_string.c_str(), + "%8x-%4x-%4x-%2x%2x-%2x%2x%2x%2x%2x%2x", + &timeLow, + &timeMid, + &timeHiAndVersion, + &clockSeqHiAndReserved, + &clockSeqLow, + &node[0], + &node[1], + &node[2], + &node[3], + &node[4], + &node[5] + ); + +#else + + int nScanned = ::sscanf(uuid_string.c_str(), + "%8x-%4x-%4x-%2x%2x-%2x%2x%2x%2x%2x%2x", + &timeLow, + &timeMid, + &timeHiAndVersion, + &clockSeqHiAndReserved, + &clockSeqLow, + &node[0], + &node[1], + &node[2], + &node[3], + &node[4], + &node[5] + ); +#endif + if (nScanned != 11) + { + ACE_DEBUG ((LM_DEBUG, + "ACE_UUID::ACE_UUID - " + "IllegalArgument(invalid string representation)")); + return; + } + } + else + { +#if defined (ACE_HAS_PACE) + int nScanned = ::pace_sscanf(uuid_string.c_str(), + "%8x-%4x-%4x-%2x%2x-%2x%2x%2x%2x%2x%2x-%s", + &timeLow, + &timeMid, + &timeHiAndVersion, + &clockSeqHiAndReserved, + &clockSeqLow, + &node[0], + &node[1], + &node[2], + &node[3], + &node[4], + &node[5], + thr_pid_buf + ); + +#else + + int nScanned = ::sscanf(uuid_string.c_str(), + "%8x-%4x-%4x-%2x%2x-%2x%2x%2x%2x%2x%2x-%s", + &timeLow, + &timeMid, + &timeHiAndVersion, + &clockSeqHiAndReserved, + &clockSeqLow, + &node[0], + &node[1], + &node[2], + &node[3], + &node[4], + &node[5], + thr_pid_buf + ); +#endif + if (nScanned != 12) + { + ACE_DEBUG ((LM_DEBUG, + "ACE_UUID::ACE_UUID - " + "IllegalArgument(invalid string representation)")); + return; + } + } + + this->timeLow_ = ACE_static_cast (ACE_UINT64, timeLow); + this->timeMid_ = ACE_static_cast (ACE_UINT16, timeMid); + this->timeHiAndVersion_ = ACE_static_cast (ACE_UINT16, timeHiAndVersion); + this->clockSeqHiAndReserved_ = ACE_static_cast (u_char, clockSeqHiAndReserved); + this->clockSeqLow_ = ACE_static_cast (u_char, clockSeqLow); + + UUID_node::NodeID nodeID; + for (int i = 0; i < UUID_node::NODE_ID_SIZE; i++) + nodeID [i] = ACE_static_cast (u_char, node[i]); + + this->node_->nodeID (nodeID); + + // Support varient 10- only + if ((this->clockSeqHiAndReserved_ & 0xc0) != 0x80 && (this->clockSeqHiAndReserved_ & 0xc0) != 0xc0) + { + ACE_DEBUG ((LM_DEBUG, + "ACE_UUID_Impl::ACE_UUID_Impl - " + "IllegalArgument(unsupported variant)")); + return; + } + + /// Support versions 1, 3, and 4 only + ACE_UINT16 V1 = this->timeHiAndVersion_; + + if ((V1 & 0xF000) != 0x1000 && + (V1 & 0xF000) != 0x3000 && + (V1 & 0xF000) != 0x4000) + { + ACE_DEBUG ((LM_DEBUG, + "ACE_UUID::ACE_UUID - " + "IllegalArgument(unsupported version)")); + return; + } + if ((this->clockSeqHiAndReserved_ & 0xc0) == 0xc0) + { + if (uuid_string.length() == NIL_UUID.to_string()->length()) + { + ACE_DEBUG ((LM_DEBUG, + "ACE_UUID::ACE_UUID - " + "IllegalArgument (Missing Thread and Process Id)")); + return; + } + ACE_CString thr_pid_str (thr_pid_buf); + int pos = thr_pid_str.find ('-'); + if (pos == -1) + ACE_DEBUG ((LM_DEBUG, + "ACE_UUID::ACE_UUID - " + "IllegalArgument (Thread and Process Id format incorrect)")); + + this->thr_id_ = thr_pid_str.substr (0, pos); + this->pid_ = thr_pid_str.substr (pos+1, thr_pid_str.length ()-pos-1); + } +} + +ACE_UUID::~ACE_UUID (void) +{ + if (node_release_) + delete node_; + + if (as_string_ != 0) + delete as_string_; +} + +const ACE_CString* +ACE_UUID::to_string (void) +{ + /// Only compute the string representation once. + if (as_string_ == 0) + { + // Get a buffer exactly the correct size. Use the nil UUID as a + // gauge. Don't forget the trailing nul. + int UUID_STRING_LENGTH = 36 + thr_id_.length () + pid_.length (); + char *buf; + + if ((thr_id_.length () != 0) && (pid_.length () != 0)) + { + UUID_STRING_LENGTH += 2; //for '-' + ACE_NEW_RETURN (buf, + char[UUID_STRING_LENGTH + 1], + 0); + + ACE_OS::sprintf(buf, + "%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x-%s-%s", + this->timeLow_, + this->timeMid_, + this->timeHiAndVersion_, + this->clockSeqHiAndReserved_, + this->clockSeqLow_, + (this->node_->nodeID ()) [0], + (this->node_->nodeID ()) [1], + (this->node_->nodeID ()) [2], + (this->node_->nodeID ()) [3], + (this->node_->nodeID ()) [4], + (this->node_->nodeID ()) [5], + thr_id_.c_str (), + pid_.c_str () + ); + } + else + { + ACE_NEW_RETURN (buf, + char[UUID_STRING_LENGTH + 1], + 0); + + ACE_OS::sprintf(buf, + "%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x", + this->timeLow_, + this->timeMid_, + this->timeHiAndVersion_, + this->clockSeqHiAndReserved_, + this->clockSeqLow_, + (this->node_->nodeID ()) [0], + (this->node_->nodeID ()) [1], + (this->node_->nodeID ()) [2], + (this->node_->nodeID ()) [3], + (this->node_->nodeID ()) [4], + (this->node_->nodeID ()) [5] + ); + } + ACE_NEW_RETURN (this->as_string_, + ACE_CString (buf, UUID_STRING_LENGTH), + 0); + delete buf; + } + + return as_string_; +} + +ACE_UUID_Generator::ACE_UUID_Generator () + : timeLast_ (0) +{ + ACE_NEW (lock_, + ACE_SYNCH_MUTEX); + destroy_lock_ = 1; +} + +ACE_UUID_Generator::~ACE_UUID_Generator() +{ + if (destroy_lock_) + delete lock_; +} + +void +ACE_UUID_Generator::init (void) +{ + ACE_OS::macaddr_node_t macaddress; + int result = + ACE_OS::getmacaddress (&macaddress); + + UUID_node::NodeID nodeID; + if (result != -1) + { + ACE_DEBUG ((LM_DEBUG, + "%02X-%02X-%02X-%02X-%02X-%02X\n", + macaddress.node [0], + macaddress.node [1], + macaddress.node [2], + macaddress.node [3], + macaddress.node [4], + macaddress.node [5])); + + ACE_OS::memcpy (&nodeID, + macaddress.node, + sizeof (nodeID)); + } + else + { + nodeID [0] = ACE_static_cast (u_char, ACE_OS::rand()); + nodeID [1] = ACE_static_cast (u_char, ACE_OS::rand()); + nodeID [2] = ACE_static_cast (u_char, ACE_OS::rand()); + nodeID [3] = ACE_static_cast (u_char, ACE_OS::rand()); + nodeID [4] = ACE_static_cast (u_char, ACE_OS::rand()); + nodeID [5] = ACE_static_cast (u_char, ACE_OS::rand()); + } + + this->get_timestamp (timeLast_); + + { + ACE_GUARD (ACE_SYNCH_MUTEX, ace_mon, *lock_); + uuid_state_.timestamp = timeLast_; + uuid_state_.node.nodeID (nodeID); + } +} + + +void +ACE_UUID_Generator::generateUUID (ACE_UUID& uuid,ACE_UINT16 version, u_char variant) +{ + UUID_time timestamp; + this->get_timestamp (timestamp); + + + // Construct a Version 1 UUID with the information in the arguements. + uuid.timeLow (ACE_static_cast (ACE_UINT32, timestamp & 0xFFFFFFFF)); + uuid.timeMid (ACE_static_cast(ACE_UINT16, (timestamp >> 32) & 0xFFFF)); + + + ACE_UINT16 tHAV = ACE_static_cast (ACE_UINT16, (timestamp >> 48) & 0xFFFF); + tHAV |= (version << 12); + uuid.timeHiAndVersion (tHAV); + + u_char cseqHAV; + { + ACE_GUARD (ACE_SYNCH_MUTEX, mon, *lock_); + uuid.clockSeqLow (uuid_state_.clockSequence & 0xFF); + cseqHAV = (uuid_state_.clockSequence & 0x3f00) >> 8; + uuid_state_.timestamp = timestamp; + } + + cseqHAV |= variant; + uuid.clockSeqHiAndReserved (cseqHAV); + uuid.node (&(uuid_state_.node)); + + if (variant == 0xc0) + { + ACE_thread_t thr_id = ACE_OS::thr_self (); + ACE_hthread_t thr_handle; + ACE_OS::thr_self (thr_handle); + ACE_Thread_ID thread_id (thr_id, thr_handle); + char buf [BUFSIZ]; + thread_id.to_string (buf); + uuid.thr_id (buf); + + ACE_OS::sprintf (buf, + "%d", + ACE_static_cast (int, ACE_OS::getpid ())); + uuid.pid (buf); + } +} + +ACE_UUID* +ACE_UUID_Generator::generateUUID (ACE_UINT16 version, u_char variant) +{ + ACE_UUID* uuid; + ACE_NEW_RETURN (uuid, + ACE_UUID, + 0); + + this->generateUUID (*uuid, version, variant); + return uuid; +} + +/// Obtain a new timestamp. If UUID's are being generated too quickly +/// the clock sequence will be incremented +void +ACE_UUID_Generator::get_timestamp (UUID_time& timestamp) +{ + this->get_systemtime(timestamp); + + /// Account for the clock being set back. Increment the clock + /// sequence. + if (timestamp <= timeLast_) + { + { + ACE_GUARD (ACE_SYNCH_MUTEX, mon, *lock_); + uuid_state_.clockSequence = (uuid_state_.clockSequence + 1) & ACE_UUID_CLOCK_SEQ_MASK; + } + } + + /// If the system time ticked since the last UUID was generated. Set + /// the clock sequence back. + else if (timestamp > timeLast_) + { + { + ACE_GUARD (ACE_SYNCH_MUTEX, mon, *lock_); + uuid_state_.clockSequence = 0; + } + } + + timeLast_ = timestamp; +} + +/** + * 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. + */ +void +ACE_UUID_Generator::get_systemtime(UUID_time& timestamp) +{ + const UUID_time timeOffset = 0x1B21DD213814000; + + /// Get the time of day, convert to 100ns ticks then add the offset. + ACE_Time_Value now = ACE_OS::gettimeofday(); + UUID_time time = now.sec() * 10000000 + now.usec() * 10; + timestamp = time + timeOffset; +} + +ACE_SYNCH_MUTEX* +ACE_UUID_Generator::lock (void) +{ + return this->lock_; +} + +ACE_SYNCH_MUTEX* +ACE_UUID_Generator::lock (ACE_SYNCH_MUTEX* lock, + int release_lock_) +{ + if (destroy_lock_) + delete lock_; + + ACE_SYNCH_MUTEX* prev_lock = this->lock_; + this->lock_ = lock; + this->destroy_lock_ = release_lock_; + return prev_lock; +} + +#if !defined (__ACE_INLINE__) +#include "ace/UUID.i" +#endif /* __ACE_INLINE__ */ + +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) +template class ACE_Singleton ; +#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) +#pragma instantiate ACE_Singleton +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ + diff --git a/ace/UUID.h b/ace/UUID.h new file mode 100644 index 00000000000..1194a88bed5 --- /dev/null +++ b/ace/UUID.h @@ -0,0 +1,232 @@ +/* -*- C++ -*- */ +//============================================================================= +/** + * @file UUID.h + * + * $Id$ + * + * @author Andrew T. Finnel + * @author Yamuna Krishnmaurthy + */ +//============================================================================= + +#ifndef ACE_UUID_H +#define ACE_UUID_H + +#include "ace/pre.h" +#include "ace/OS.h" +#include "ace/SString.h" +#include "ace/Singleton.h" +#include "ace/Synch.h" + +/// Class to hold a MAC address +class ACE_Export UUID_node +{ + public: + + /// Constructor + UUID_node (void); + + typedef enum {NODE_ID_SIZE = 6}; + typedef u_char NodeID[NODE_ID_SIZE]; + + NodeID& nodeID (void); + void nodeID (NodeID&); + + /// Assignment Operation + UUID_node &operator=(const UUID_node &right); + + /// Equality Operations + bool operator == (const UUID_node& right) const; + bool operator != (const UUID_node& right) const; + + /// Relational Operations + bool operator < (const UUID_node& right) const; + + private: + NodeID nodeID_; +}; + + +/** + * @class ACE_UUID + * + * ACE_UUID represents a Universally Unique IDentifier (UUID) as + * described in (the expired) INTERNET-DRAFT specification entitled + * UUIDs and GUIDs. All instances of UUID are of the time-based + * variety. That is, the version number part of the timeHiAndVersion + * field is 1. + * + * The default constructor creates a nil UUID. + * + * UUIDs have value semantics. In addition, they may be compared for + * ordering and equality. + * + * Additionally in this implementation provisions have been made to include + * process and thread ids to make the UUIDs more unique. The variant 0xc0 + * has been added to facilitate this. + */ +class ACE_Export ACE_UUID +{ + public: + + /// Constructor + ACE_UUID(void); + + /// Copy constructor + ACE_UUID(const ACE_UUID &right); + + /// Constructs a UUID from a string representation. + ACE_UUID (const ACE_CString& uuidString); + + // Destructor + ~ACE_UUID (void); + + ACE_UINT32 timeLow (void); + void timeLow (ACE_UINT32); + + ACE_UINT16 timeMid (void); + void timeMid (ACE_UINT16); + + ACE_UINT16 timeHiAndVersion (void); + void timeHiAndVersion (ACE_UINT16); + + u_char clockSeqHiAndReserved (void); + void clockSeqHiAndReserved (u_char); + + u_char clockSeqLow (void); + void clockSeqLow (u_char); + + UUID_node* node (void); + void node (UUID_node*); + + ACE_CString* thr_id (void); + void thr_id (char*); + + ACE_CString* pid (void); + void pid (char*); + + /// Returns a string representation of the UUID + const ACE_CString* to_string (void); + + static ACE_UUID NIL_UUID; + + /// Assignment Operation + ACE_UUID & operator=(const ACE_UUID &right); + + /// Equality Operations + bool operator==(const ACE_UUID &right) const; + bool operator!=(const ACE_UUID &right) const; + + /// Relational Operations + bool operator< (const ACE_UUID &right) const; + bool operator> (const ACE_UUID &right) const; + bool operator<=(const ACE_UUID &right) const; + bool operator>=(const ACE_UUID &right) const; + + private: + + /// Data Members for Class Attributes + ACE_UINT32 timeLow_; + ACE_UINT16 timeMid_; + ACE_UINT16 timeHiAndVersion_; + u_char clockSeqHiAndReserved_; + u_char clockSeqLow_; + UUID_node* node_; + int node_release_; + ACE_CString thr_id_; + ACE_CString pid_; + + /// The string representation of the UUID. This is created and + /// updated only on demand. + ACE_CString *as_string_; +}; + + +/** + * @class ACE_UUID_Generator + * + * Singleton class that generates UUIDs. + * + */ +class ACE_Export ACE_UUID_Generator +{ + public: + + enum {ACE_UUID_CLOCK_SEQ_MASK = 0x3FFF}; + + ACE_UUID_Generator(); + ~ACE_UUID_Generator(); + + void init (void); + + /// Format timestamp, clockseq, and nodeID into an UUID of the + /// specified version and variant. For generating UUID's with + /// thread and process ids use variant=0xc0 + void generateUUID(ACE_UUID&, ACE_UINT16 version=0x0001, u_char variant=0x80); + + /// Format timestamp, clockseq, and nodeID into a VI UUID. For + /// generating UUID's with thread and process ids use variant=0xc0 + ACE_UUID* generateUUID (ACE_UINT16 version=0x0001, u_char variant=0x80); + + /// Type to represent UTC as a count of 100 nanosecond intervals + /// since 00:00:00.00, 15 October 1582. + typedef ACE_UINT64 UUID_time; + + /// The locking strategy prevents multiple generators from accessing + /// the UUID_state at the same time. Get the locking strategy. + ACE_SYNCH_MUTEX* lock (void); + + /// Set a new locking strategy and return the old one. + ACE_SYNCH_MUTEX* lock (ACE_SYNCH_MUTEX*lock, + int release_lock); + + + private: + + /// The system time when that last uuid was generated. + UUID_time timeLast_; + + /// Type to contain the UUID generator persistent state. This will + /// be kept in memory mapped shared memory + struct UUID_State + { + UUID_time timestamp; + UUID_node node; + ACE_UINT16 clockSequence; + }; + + /// Obtain a UUID timestamp. Compensate for the fact that the time + /// obtained from getSystem time has a resolution less than 100ns. + void get_timestamp (UUID_time& timestamp); + + /// Obtain the system time in UTC as a count of 100 nanosecond intervals + /// since 00:00:00.00, 15 October 1582 (the date of Gregorian reform to + /// the Christian calendar). + void get_systemtime( UUID_time& timeNow); + + /// The UUID generator persistent state. + UUID_State uuid_state_; + + ACE_SYNCH_MUTEX* lock_; + int destroy_lock_; +}; + +typedef ACE_Singleton ACE_UUID_GENERATOR; + +#if defined (__ACE_INLINE__) +#include "ace/UUID.i" +#endif /* __ACE_INLINE__ */ + +#include "ace/post.h" +#endif // ACE_UUID_H + + + + + + + + + + diff --git a/ace/UUID.i b/ace/UUID.i new file mode 100644 index 00000000000..29f22a517fb --- /dev/null +++ b/ace/UUID.i @@ -0,0 +1,211 @@ +//$Id$ +// -*- C++ -*- + +/// Data Members for Class Attributes +ACE_INLINE ACE_UINT32 +ACE_UUID::timeLow (void) +{ + return this->timeLow_; +} + +ACE_INLINE void +ACE_UUID::timeLow (ACE_UINT32 timelow) +{ + this->timeLow_ = timelow; +} + +ACE_INLINE ACE_UINT16 +ACE_UUID::timeMid (void) +{ + return this->timeMid_; +} + +ACE_INLINE void +ACE_UUID::timeMid (ACE_UINT16 time_mid) +{ + this->timeMid_ = time_mid; +} + +ACE_INLINE ACE_UINT16 +ACE_UUID::timeHiAndVersion (void) +{ + return this->timeHiAndVersion_; +} + +ACE_INLINE void +ACE_UUID::timeHiAndVersion (ACE_UINT16 timeHiAndVersion) +{ + this->timeHiAndVersion_ = timeHiAndVersion; +} + +ACE_INLINE u_char +ACE_UUID::clockSeqHiAndReserved (void) +{ + return this->clockSeqHiAndReserved_; +} + +ACE_INLINE void +ACE_UUID::clockSeqHiAndReserved (u_char clockSeqHiAndReserved) +{ + this->clockSeqHiAndReserved_ = clockSeqHiAndReserved; +} + +ACE_INLINE u_char +ACE_UUID::clockSeqLow (void) +{ + return this->clockSeqLow_; +} + +ACE_INLINE void +ACE_UUID::clockSeqLow (u_char clockSeqLow) +{ + this->clockSeqLow_ = clockSeqLow; +} + +ACE_INLINE UUID_node* +ACE_UUID::node (void) +{ + return this->node_; +} + +ACE_INLINE void +ACE_UUID::node (UUID_node* node) +{ + if (node_release_ == 1) + delete node_; + + this->node_ = node; + node_release_ = 0; +} + +ACE_INLINE ACE_CString* +ACE_UUID::thr_id (void) +{ + return &this->thr_id_; +} + +ACE_INLINE void +ACE_UUID::thr_id (char* thr_id) +{ + this->thr_id_ = thr_id; +} + +ACE_INLINE ACE_CString* +ACE_UUID::pid (void) +{ + return &this->pid_; +} + +ACE_INLINE void +ACE_UUID::pid (char* pid) +{ + this->pid_ = pid; +} + +ACE_INLINE ACE_UUID& +ACE_UUID::operator = (const ACE_UUID &right) +{ + *this = right; + return *this; +} + +ACE_INLINE bool +ACE_UUID::operator == (const ACE_UUID &right) const +{ + ACE_UUID rt (right); + if ((timeLow_ != rt.timeLow ()) || + (timeMid_ != rt.timeMid ()) || + (timeHiAndVersion_ != rt.timeHiAndVersion ()) || + (clockSeqHiAndReserved_ != rt.clockSeqHiAndReserved ()) || + (clockSeqLow_ != rt.clockSeqLow ()) || + (node_ != rt.node ())) + { + return false; + } + + return true; +} + +ACE_INLINE bool +ACE_UUID::operator != (const ACE_UUID &right) const +{ + return !(*this == right); +} + +ACE_INLINE bool +ACE_UUID::operator < (const ACE_UUID &rt) const +{ + ACE_UUID right (rt); + if ((timeLow_ < right.timeLow ()) || + (timeMid_ < right.timeMid ()) || + (timeHiAndVersion_ < right.timeHiAndVersion ()) || + (clockSeqHiAndReserved_ < right.clockSeqHiAndReserved ()) || + (clockSeqLow_ < right.clockSeqLow ()) || + (node_ < right.node ())) + { + return true; + } + + return false; +} + +ACE_INLINE bool +ACE_UUID::operator > (const ACE_UUID &right) const +{ + return right < *this; +} + +ACE_INLINE bool +ACE_UUID::operator <= (const ACE_UUID &right) const +{ + return !(*this > right); +} + +ACE_INLINE bool +ACE_UUID::operator >= (const ACE_UUID &right) const +{ + return !(*this < right); +} + +ACE_INLINE UUID_node& +UUID_node::operator = (const UUID_node &right) +{ + *this = right; + return *this; +} + +ACE_INLINE bool +UUID_node::operator == (const UUID_node& rt) const +{ + UUID_node right = rt; + for (size_t i = 0; i < NODE_ID_SIZE; ++i) + { + if (nodeID_ [i] != right.nodeID ()[i]) + { + return false; + } + } + return true; +} + +ACE_INLINE bool +UUID_node::operator != (const UUID_node& right) const +{ + return !(*this == right); +} + +ACE_INLINE bool +UUID_node::operator < (const UUID_node& rt) const +{ + UUID_node right = rt; + for (size_t i = 0; i < NODE_ID_SIZE; ++i) + if (nodeID_ [i] < right.nodeID ()[i]) + return true; + + return false; +} + + + + + diff --git a/ace/config-win32-common.h b/ace/config-win32-common.h index 73c2a82cd7f..798f42b6a42 100644 --- a/ace/config-win32-common.h +++ b/ace/config-win32-common.h @@ -1,6 +1,7 @@ /* -*- C++ -*- */ // $Id$ + #ifndef ACE_CONFIG_WIN32_COMMON_H #define ACE_CONFIG_WIN32_COMMON_H #include /**/ "ace/pre.h" @@ -575,5 +576,13 @@ typedef unsigned long long ACE_UINT64; # define ACE_HAS_LOG_MSG_NT_EVENT_LOG #endif /* !ACE_HAS_WINCE && !ACE_HAS_PHARLAP */ +// Needed for obtaining the MAC address +// I dont believe this will work under CE, notice the +// check for UNDER_CE. +# if defined (_MSC_VER) && !defined (UNDER_CE) +# include +# pragma comment(lib, "netapi32.lib") // needed for obtaing MACaddress +# endif /* _MSC_VER */ + #include /**/ "ace/post.h" #endif /* ACE_CONFIG_WIN32_COMMON_H */ -- cgit v1.2.1