UUIDGenerator.cpp
Go to the documentation of this file.
1 #include <rms/util/UUIDGenerator.h>
2 
3 #include <iostream>
4 #include <cstring> /* memcpy */
5 
6 namespace gov {
7 
8 namespace fnal {
9 
10 namespace cd {
11 
12 namespace rms {
13 
14 namespace util {
15 
16 /**
17  * UUID constructor. Takes the nodename, and generates the
18  * hash. Also sets up the clock sequence.
19  *
20  * @param nodeName The name of the node generating the UUIDs.
21  * This should be unique.
22  */
24  _nodeName = nodeName;
26  unsigned int randomNumber;
27 
28  gettimeofday(&_previousTime, NULL);
29 
30  sha1_forRMS_starts(&ctx);
31  sha1_forRMS_update(&ctx, (unsigned char *)_nodeName.c_str(),
32  _nodeName.size());
34 
35  boost::minstd_rand generator(_previousTime.tv_usec);
36  boost::uniform_int<> uniformDistribution(0, 65536);
37  boost::variate_generator<boost::minstd_rand&, boost::uniform_int<> >
38  uniformDistributionGenerator(generator, uniformDistribution);
39 
40  randomNumber = uniformDistributionGenerator() & 0xffff;
41 
42  _clockSequence[0] = randomNumber & 0xff;
43  _clockSequence[1] = (randomNumber >> 8) & 0xff;
44 
45  return;
46 }
47 
48 /**
49  * Get a human readable UUID from the generator.
50  *
51  * @return A universal unique identifier.
52  */
54  unsigned char uuid[16];
55  unsigned char uuidHex[37];
56  struct timeval currentTime;
57  unsigned long timeHigh;
58  unsigned long timeLow;
59  unsigned long version = 0x1;
60  int i = 0;
61  int j = 0;
62 
63  gettimeofday(&currentTime, NULL);
64 
65  if (_previousTime.tv_sec == currentTime.tv_sec &&
66  _previousTime.tv_usec == currentTime.tv_usec) {
68  }
69  else {
70  _overrunCounter = 0;
71  }
72 
73  timeHigh = currentTime.tv_sec;
74  timeLow = (currentTime.tv_usec << 10) | (_overrunCounter & 0x3ff);
75 
76  timeHigh = timeHigh | (version << 28);
77 
78  uuid[8] = _clockSequence[0];
79  uuid[9] = _clockSequence[1];
80 
81  memcpy(uuid, &timeLow, sizeof(unsigned int));
82  memcpy(uuid + (4 * sizeof(char)), &timeHigh, sizeof(unsigned int));
83 
84  for (int i = 10; i < 16; i++) {
85  uuid[i] = _nodeNameHash[i];
86  }
87 
88  unsigned int upper, lower;
89 
90  for (i = 0; i < 16; i++) {
91  upper = (uuid[i] >> 4) & 0x0f;
92  lower = uuid[i] & 0x0f;
93 
94  if (j == 8 || j == 13 || j == 18 || j == 23) {
95  uuidHex[j] = '-';
96  j++;
97  }
98 
99  if (upper < 10) {
100  uuidHex[j] = upper + 48;
101  }
102  else {
103  uuidHex[j] = upper + 87;
104  }
105 
106  j++;
107 
108  if (lower < 10) {
109  uuidHex[j] = lower + 48;
110  }
111  else {
112  uuidHex[j] = lower + 87;
113  }
114 
115  j++;
116  }
117 
118  uuidHex[36] = '\0';
119  const std::string result((const char*)uuidHex);
120 
121  return result;
122 }
123 
124 /**
125  * Get a UUID from the generator.
126  *
127  * @return A universal unique identifier.
128  */
129 const char *UUIDGenerator::getUUID() {
130  char *uuid;
131  struct timeval currentTime;
132  unsigned long timeHigh;
133  unsigned long timeLow;
134  unsigned long version = 0x1;
135 
136  gettimeofday(&currentTime, NULL);
137 
138  if (_previousTime.tv_sec == currentTime.tv_sec &&
139  _previousTime.tv_usec == currentTime.tv_usec) {
140  _overrunCounter++;
141  }
142  else {
143  _overrunCounter = 0;
144  }
145 
146  timeHigh = currentTime.tv_sec;
147  timeLow = (currentTime.tv_usec << 10) | (_overrunCounter & 0x3ff);
148 
149  timeHigh = timeHigh | (version << 28);
150 
151  uuid = new char[16];
152 
153  uuid[8] = _clockSequence[0];
154  uuid[9] = _clockSequence[1];
155 
156  memcpy(uuid, &timeLow, sizeof(unsigned int));
157  memcpy(uuid + (4 * sizeof(char)), &timeHigh, sizeof(unsigned int));
158 
159  for (int i = 10; i < 16; i++) {
160  uuid[i] = _nodeNameHash[i];
161  }
162 
163  // 10-Sep-2009, KAB - ensure that the first byte is not NULL.
164  // This is needed because we don't always bother with a UUID in single-
165  // fragment messages on the Java side, and the way that we tell if
166  // a UUID is empty on the C++ side is to check for a NULL first byte.
167  // So, we need to avoid the case in which the full UUID is not NULL
168  // but appears to be because its first byte is NULL.
169  if (uuid[0] == '\0') {uuid[0] = '\1';}
170 
171  return uuid;
172 }
173 
174 } // end of namespace util
175 
176 } // end of namespace rms
177 
178 } // end of namespace cd
179 
180 } // end of namespace fnal
181 
182 } // end of namespace gov
void sha1_forRMS_update(sha1_forRMS_context *ctx, unsigned char *input, int ilen)
SHA-1 process buffer.
Definition: Sha1.cpp:232
Filter events based on their run/event numbers.
SHA-1 context structure.
Definition: Sha1.h:14
const double j
Definition: BetheBloch.cxx:29
void sha1_forRMS_starts(sha1_forRMS_context *ctx)
SHA-1 context setup.
Definition: Sha1.cpp:60
Definition: fnal.py:1
void sha1_forRMS_finish(sha1_forRMS_context *ctx, unsigned char output[20])
SHA-1 final digest.
Definition: Sha1.cpp:285
const XML_Char * version
Definition: expat.h:187
::xsd::cxx::tree::string< char, simple_type > string
Definition: Database.h:154
c cd(1)