View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.id.uuid;
18  
19  import java.io.IOException;
20  import java.util.Iterator;
21  import java.util.Set;
22  
23  import org.apache.commons.id.uuid.clock.Clock;
24  import org.apache.commons.id.uuid.state.Node;
25  import org.apache.commons.id.uuid.state.State;
26  import org.apache.commons.id.uuid.state.StateHelper;
27  
28  /**
29   * <p>Class is responsible for managing the <code>Node</code>s identified for
30   * this system (JVM instance), as well as the state management for the
31   * <code>Node</code>s.</p>
32   *
33   * @author Commons-Id team
34   * @version $Revision: 480488 $ $Date: 2006-11-29 08:57:26 +0000 (Wed, 29 Nov 2006) $
35   *
36   */
37  public final class NodeManagerImpl implements NodeManager {
38      /** Reference to the State implementation to use for loading and storing */
39      private State nodeState;
40      /** The current array index for the Node in use. */
41      private int currentNodeIndex = 0;
42      /** Flag indicating the node state has been initialized. */
43      private boolean isInit = false;
44      /** Set that references all instances. */
45      private Set nodesSet;
46      /** Array of the Nodes */
47      private Node[] allNodes;
48      /** UUID timestamp of last call to State.store */
49      private long lastUUIDTimeStored = 0;
50      /** Single instance of this class */
51      //private NodeManagerImpl instance;
52  
53      /** Constructor for class. */
54      public NodeManagerImpl() {
55          super();
56      }
57  
58      /** Initialization */
59      public void init() {
60          nodeState = StateHelper.getStateImpl();
61          try {
62              nodeState.load();
63          } catch (Exception ex) {
64            throw new RuntimeException(ex);
65          }
66          nodesSet = nodeState.getNodes();
67          Iterator it = nodesSet.iterator();
68          allNodes = new Node[nodesSet.size()];
69          int i = 0;
70          while (it.hasNext()) {
71              allNodes[i++] = (Node) it.next();
72          }
73          isInit = true;
74      }
75      /*
76       * <p>Returns the singleton instance of this class.</p>
77       *
78       * @return the singleton instance of this class.
79  
80      public NodeManager getInstance() {
81          if (instance == null) {
82              instance = new NodeManagerImpl();
83          }
84          return instance;
85      }
86      */
87      /**
88       * <p>Returns the current node in use for uuid generation. Calls to this
89       * method also signal the NodeManagerImpl when to store uuid state information.
90       * </p>
91       *
92       * @return the current node in use for uuid generation.
93       */
94      public Node currentNode() {
95          if (!isInit) {
96              init();
97          }
98          // See if we need to store state information.
99          if ((lastUUIDTimeStored + nodeState.getSynchInterval()) > (findMaxTimestamp() / Clock.INTERVALS_PER_MILLI)) {
100             try {
101                 nodeState.store(nodesSet);
102             } catch (IOException ioe) {
103                //@TODO add listener and send notify
104             }
105         }
106         return allNodes[currentNodeIndex];
107     }
108 
109     /**
110      * <p>Returns the next available <code>Node</code> for uuid generation.</p>
111      *
112      * @return the next available <code>Node</code> for uuid generation.
113      */
114     public Node nextAvailableNode() {
115         if (!isInit) {
116             init();
117         }
118         currentNodeIndex++;
119         if (currentNodeIndex >= allNodes.length) {
120             currentNodeIndex = 0;
121         }
122         return currentNode();
123     }
124 
125     /**
126      * <p>Returns the maximum uuid timestamp generated from all <code>Node</code>s</p>
127      *
128      * @return maximum uuid timestamp generated from all <code>Node</code>s.
129      */
130     private long findMaxTimestamp() {
131         if (!isInit) {
132             init();
133         }
134         long max = 0;
135         for (int i = 0; i < allNodes.length; i++) {
136             if (allNodes[i] != null && allNodes[i].getLastTimestamp() > max) {
137                 max = allNodes[i].getLastTimestamp();
138             }
139         }
140         return max;
141     }
142 
143     /**
144      * <p>Locks a node for use by a generator.</p>
145      *
146      * @param node the Node to lock.
147      */
148     public void lockNode(Node node) {
149         //Not implemented in this version.
150     }
151 
152     /**
153      * <p>Releases a node locked by a generator.</p>
154      *
155      * @param node the Node to release.
156      */
157     public void releaseNode(Node node) {
158         //Not implemented in this version.
159     }
160 
161     /**
162      * <p>Asks the State implementation to store.</p>
163      *
164      * @see Object#finalize
165      */
166     protected void finalize() throws Throwable {
167         nodeState.store(nodesSet);
168         super.finalize();
169     }
170 }