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 }