Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

UniqueId.C

Go to the documentation of this file.
00001 // Copyright (C) 2001, Compaq Computer Corporation
00002 // 
00003 // This file is part of Vesta.
00004 // 
00005 // Vesta is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public
00007 // License as published by the Free Software Foundation; either
00008 // version 2.1 of the License, or (at your option) any later version.
00009 // 
00010 // Vesta is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // Lesser General Public License for more details.
00014 // 
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with Vesta; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 
00019 // Last modified on Sun May 22 23:03:38 EDT 2005 by ken@xorian.net
00020 //      modified on Wed Jan 15 17:38:11 PST 1997 by heydon
00021 
00022 #include <time.h>
00023 #include <Basics.H>
00024 #include <OS.H>
00025 #include "FP.H"
00026 #include "UniqueId.H"
00027 
00028 using std::cerr;
00029 using std::endl;
00030 
00031 // const after initialization
00032 static FP::Tag UniqueId_Prefix;
00033 
00034 // Invocation counter.  (Becuase of the way this is used, it's
00035 // important that this be 64 bits in size.)
00036 static Bit64 UniqueId_count = 0UL;
00037 
00038 // Mutex protecting the above count.
00039 Basics::mutex UniqueId_count_mu;
00040 
00041 FP::Tag UniqueId() throw ()
00042 {
00043     FP::Tag res(UniqueId_Prefix);
00044 
00045     UniqueId_count_mu.lock();
00046     Bit64 UniqueId_num = UniqueId_count++;
00047     UniqueId_count_mu.unlock();
00048 
00049 #if BYTE_ORDER == BIG_ENDIAN
00050     // We really want the bits that change frequently to come first in
00051     // what we extend the prefix by.  So, on big-endian systems, we
00052     // reverse the bytes before extending the tag.
00053     UniqueId_num = Basics::swab64(UniqueId_num);
00054 #endif
00055 
00056     res.Extend((char *)(&UniqueId_num), sizeof(UniqueId_num));
00057 
00058     return res;
00059 }
00060 
00061 class UniqueIdInit {
00062   public:
00063     UniqueIdInit() throw ();
00064 };
00065 
00066 // invoke the constructor to initialize this module
00067 static UniqueIdInit UniqueId_init;
00068 
00069 #if defined(__digital__) && defined(__DECCXX_VER)
00070 # if __DECCXX_VER >= 60290033
00071 // Workaround for mysteriously missing declararion in new Tru64 build
00072 // environment.  See messages with subjects "cxx problems" and
00073 // "Summary: cxx problems (not resolved)" from the alpha-osf-managers
00074 // mailing list:
00075 
00076 // http://groups.yahoo.com/group/alpha-osf-managers/message/12093
00077 // http://www.ornl.gov/cts/archives/mailing-lists/tru64-unix-managers/1998/07/msg00569.html
00078 extern "C"
00079 {
00080   long gethostid(void);
00081 }
00082 # endif
00083 #endif
00084 
00085 UniqueIdInit::UniqueIdInit() throw ()
00086 {
00087     // (Using gethostid() and gethostname() and the IP address it
00088     // resolves to may seem like overkill, but in some cases even all
00089     // three of these may not be enough to guarantee that different
00090     // hosts will get a different prefix.  gethostid() may return a
00091     // default value if the system hasn't been explicitly given a
00092     // hostid.  gethostname() could return something generic like
00093     // "localhost.localdomain", which could in turn resolve to an
00094     // equally generic IP address.  Hopefully not all three of these
00095     // will be the case, so we try to include all three values in
00096     // UniqueId_Prefix.)
00097 
00098     // extend by unique host identifier
00099     long int hostid = gethostid();
00100     UniqueId_Prefix.Extend((char *)(&hostid), sizeof(hostid));
00101 
00102     // Try to get our hostname.  Continue anyway even if this fails.
00103     char my_hostname[MAXHOSTNAMELEN+1];
00104     if (gethostname(my_hostname, sizeof(my_hostname)-1) == 0)
00105       {
00106         // Extend by hostname
00107         UniqueId_Prefix.Extend(my_hostname, strlen(my_hostname));
00108 
00109         // Try to look up the IP address of our hotname.
00110         try
00111           {
00112             in_addr my_ip = TCP_sock::host_to_addr(my_hostname);
00113 
00114             // Extend by the IP address our hostname resolves to.
00115             UniqueId_Prefix.Extend((char *)(&my_ip), sizeof(my_ip));
00116           }
00117         catch(...)
00118           {
00119             // Couldn't resolve our hostname?
00120           }
00121       }
00122 
00123     // (Similarly, it may seem like overkill to use the pid, ppid, and
00124     // pgid.  In the event that two hosts happen to have the same
00125     // prefix up to this point, this makes it slightly less likely
00126     // that they will have the same prefix after this point.)
00127 
00128     // extend by unique process identifier
00129     pid_t pid = getpid();
00130     UniqueId_Prefix.Extend((char *)(&pid), sizeof(pid));
00131 
00132     // extend by parent process identifier
00133     pid_t ppid = getppid();
00134     UniqueId_Prefix.Extend((char *)(&ppid), sizeof(ppid));
00135 
00136     // extend by process group identifier
00137     pid_t pgid = getpgrp();
00138     UniqueId_Prefix.Extend((char *)(&pgid), sizeof(pgid));
00139 
00140     // extend by current time of day
00141     time_t tm;
00142     if (time(&tm) < 0) {
00143         cerr << "UniqueId: fatal error " << errno <<
00144           " getting time of day; aborting..." << endl;
00145         assert(false);
00146     }
00147     UniqueId_Prefix.Extend((char *)(&tm), sizeof(time_t));
00148 }

Generated on Mon May 8 00:48:41 2006 for Vesta by  doxygen 1.4.2