UUIDGenerator.cpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. //
  2. // UUIDGenerator.cpp
  3. //
  4. // $Id: //poco/1.4/Foundation/src/UUIDGenerator.cpp#1 $
  5. //
  6. // Library: Foundation
  7. // Package: UUID
  8. // Module: UUID
  9. //
  10. // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
  11. // and Contributors.
  12. //
  13. // SPDX-License-Identifier: BSL-1.0
  14. //
  15. #include "Poco/UUIDGenerator.h"
  16. #include "Poco/Thread.h"
  17. #include "Poco/RandomStream.h"
  18. #include "Poco/DigestEngine.h"
  19. #include "Poco/MD5Engine.h"
  20. #include "Poco/SingletonHolder.h"
  21. #include <cstring>
  22. namespace Poco {
  23. UUIDGenerator::UUIDGenerator(): _ticks(0), _haveNode(false)
  24. {
  25. }
  26. UUIDGenerator::~UUIDGenerator()
  27. {
  28. }
  29. UUID UUIDGenerator::create()
  30. {
  31. FastMutex::ScopedLock lock(_mutex);
  32. if (!_haveNode)
  33. {
  34. Environment::nodeId(_node);
  35. _haveNode = true;
  36. }
  37. Timestamp::UtcTimeVal tv = timeStamp();
  38. UInt32 timeLow = UInt32(tv & 0xFFFFFFFF);
  39. UInt16 timeMid = UInt16((tv >> 32) & 0xFFFF);
  40. UInt16 timeHiAndVersion = UInt16((tv >> 48) & 0x0FFF) + (UUID::UUID_TIME_BASED << 12);
  41. UInt16 clockSeq = (UInt16(_random.next() >> 4) & 0x3FFF) | 0x8000;
  42. return UUID(timeLow, timeMid, timeHiAndVersion, clockSeq, _node);
  43. }
  44. UUID UUIDGenerator::createFromName(const UUID& nsid, const std::string& name)
  45. {
  46. MD5Engine md5;
  47. return createFromName(nsid, name, md5);
  48. }
  49. UUID UUIDGenerator::createFromName(const UUID& nsid, const std::string& name, DigestEngine& de)
  50. {
  51. poco_assert_dbg (de.digestLength() >= 16);
  52. UUID netNsid = nsid;
  53. netNsid.toNetwork();
  54. de.reset();
  55. de.update(&netNsid._timeLow, sizeof(netNsid._timeLow));
  56. de.update(&netNsid._timeMid, sizeof(netNsid._timeMid));
  57. de.update(&netNsid._timeHiAndVersion, sizeof(netNsid._timeHiAndVersion));
  58. de.update(&netNsid._clockSeq, sizeof(netNsid._clockSeq));
  59. de.update(&netNsid._node[0], sizeof(netNsid._node));
  60. de.update(name);
  61. char buffer[16];
  62. const DigestEngine::Digest& d = de.digest();
  63. for (int i = 0; i < 16; ++i)
  64. {
  65. buffer[i] = d[i];
  66. }
  67. return UUID(buffer, UUID::UUID_NAME_BASED);
  68. }
  69. UUID UUIDGenerator::createRandom()
  70. {
  71. char buffer[16];
  72. RandomInputStream ris;
  73. ris.read(buffer, sizeof(buffer));
  74. return UUID(buffer, UUID::UUID_RANDOM);
  75. }
  76. Timestamp::UtcTimeVal UUIDGenerator::timeStamp()
  77. {
  78. Timestamp now;
  79. for (;;)
  80. {
  81. if (now != _lastTime)
  82. {
  83. _lastTime = now;
  84. _ticks = 0;
  85. break;
  86. }
  87. if (_ticks < 100)
  88. {
  89. ++_ticks;
  90. break;
  91. }
  92. now.update();
  93. }
  94. Timestamp::UtcTimeVal tv = now.utcTime();
  95. return tv + _ticks;
  96. }
  97. UUID UUIDGenerator::createOne()
  98. {
  99. try
  100. {
  101. return create();
  102. }
  103. catch (Exception&)
  104. {
  105. return createRandom();
  106. }
  107. }
  108. namespace
  109. {
  110. static SingletonHolder<UUIDGenerator> sh;
  111. }
  112. UUIDGenerator& UUIDGenerator::defaultGenerator()
  113. {
  114. return *sh.get();
  115. }
  116. } // namespace Poco