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 }