BitSetIDFactory.java 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /*
  2. * $Header: BitSetIDFactory.java, 24/08/2005 22:44:26 luisantonioa Exp $
  3. *
  4. * $Author: luisantonioa $
  5. * $Date: 24/08/2005 22:44:26 $
  6. * $Revision: 1 $
  7. * $Log: BitSetIDFactory.java,v $
  8. * Revision 1 24/08/2005 22:44:26 luisantonioa
  9. * Added copyright notice
  10. *
  11. *
  12. * This program is free software: you can redistribute it and/or modify it under
  13. * the terms of the GNU General Public License as published by the Free Software
  14. * Foundation, either version 3 of the License, or (at your option) any later
  15. * version.
  16. *
  17. * This program is distributed in the hope that it will be useful, but WITHOUT
  18. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  19. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  20. * details.
  21. *
  22. * You should have received a copy of the GNU General Public License along with
  23. * this program. If not, see <http://www.gnu.org/licenses/>.
  24. */
  25. package com.l2jserver.gameserver.idfactory;
  26. import java.util.BitSet;
  27. import java.util.concurrent.atomic.AtomicInteger;
  28. import java.util.logging.Level;
  29. import java.util.logging.Logger;
  30. import com.l2jserver.gameserver.ThreadPoolManager;
  31. import com.l2jserver.util.PrimeFinder;
  32. /**
  33. * This class ..
  34. *
  35. * @version $Revision: 1.2 $ $Date: 2004/06/27 08:12:59 $
  36. */
  37. public class BitSetIDFactory extends IdFactory
  38. {
  39. private static Logger _log = Logger.getLogger(BitSetIDFactory.class.getName());
  40. private BitSet _freeIds;
  41. private AtomicInteger _freeIdCount;
  42. private AtomicInteger _nextFreeId;
  43. protected class BitSetCapacityCheck implements Runnable
  44. {
  45. public void run()
  46. {
  47. synchronized (BitSetIDFactory.this)
  48. {
  49. if (reachingBitSetCapacity())
  50. increaseBitSetCapacity();
  51. }
  52. }
  53. }
  54. protected BitSetIDFactory()
  55. {
  56. super();
  57. synchronized(BitSetIDFactory.class)
  58. {
  59. ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new BitSetCapacityCheck(), 30000, 30000);
  60. initialize();
  61. }
  62. _log.info("IDFactory: " + _freeIds.size() + " id's available.");
  63. }
  64. public void initialize()
  65. {
  66. try
  67. {
  68. _freeIds = new BitSet(PrimeFinder.nextPrime(100000));
  69. _freeIds.clear();
  70. _freeIdCount = new AtomicInteger(FREE_OBJECT_ID_SIZE);
  71. for (int usedObjectId : extractUsedObjectIDTable())
  72. {
  73. int objectID = usedObjectId - FIRST_OID;
  74. if (objectID < 0)
  75. {
  76. _log.warning("Object ID " + usedObjectId + " in DB is less than minimum ID of " + FIRST_OID);
  77. continue;
  78. }
  79. _freeIds.set(usedObjectId - FIRST_OID);
  80. _freeIdCount.decrementAndGet();
  81. }
  82. _nextFreeId = new AtomicInteger(_freeIds.nextClearBit(0));
  83. _initialized = true;
  84. }
  85. catch (Exception e)
  86. {
  87. _initialized = false;
  88. _log.log(Level.SEVERE, "BitSet ID Factory could not be initialized correctly: " + e.getMessage(), e);
  89. }
  90. }
  91. /**
  92. *
  93. * @see com.l2jserver.gameserver.idfactory.IdFactory#releaseId(int)
  94. */
  95. @Override
  96. public synchronized void releaseId(int objectID)
  97. {
  98. if ((objectID - FIRST_OID) > -1)
  99. {
  100. _freeIds.clear(objectID - FIRST_OID);
  101. _freeIdCount.incrementAndGet();
  102. }
  103. else
  104. _log.warning("BitSet ID Factory: release objectID " + objectID + " failed (< " + FIRST_OID + ")");
  105. }
  106. /**
  107. *
  108. * @see com.l2jserver.gameserver.idfactory.IdFactory#getNextId()
  109. */
  110. @Override
  111. public synchronized int getNextId()
  112. {
  113. int newID = _nextFreeId.get();
  114. _freeIds.set(newID);
  115. _freeIdCount.decrementAndGet();
  116. int nextFree = _freeIds.nextClearBit(newID);
  117. if (nextFree < 0)
  118. {
  119. nextFree = _freeIds.nextClearBit(0);
  120. }
  121. if (nextFree < 0)
  122. {
  123. if (_freeIds.size() < FREE_OBJECT_ID_SIZE)
  124. {
  125. increaseBitSetCapacity();
  126. }
  127. else
  128. {
  129. throw new NullPointerException("Ran out of valid Id's.");
  130. }
  131. }
  132. _nextFreeId.set(nextFree);
  133. return newID + FIRST_OID;
  134. }
  135. /**
  136. *
  137. * @see com.l2jserver.gameserver.idfactory.IdFactory#size()
  138. */
  139. @Override
  140. public synchronized int size()
  141. {
  142. return _freeIdCount.get();
  143. }
  144. /**
  145. *
  146. * @return
  147. */
  148. protected synchronized int usedIdCount()
  149. {
  150. return (size() - FIRST_OID);
  151. }
  152. /**
  153. *
  154. * @return
  155. */
  156. protected synchronized boolean reachingBitSetCapacity()
  157. {
  158. return PrimeFinder.nextPrime(usedIdCount() * 11 / 10) > _freeIds.size();
  159. }
  160. protected synchronized void increaseBitSetCapacity()
  161. {
  162. BitSet newBitSet = new BitSet(PrimeFinder.nextPrime(usedIdCount() * 11 / 10));
  163. newBitSet.or(_freeIds);
  164. _freeIds = newBitSet;
  165. }
  166. }