001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.jca;
031:
032: import java.util.AbstractSet;
033: import java.util.Collection;
034: import java.util.Iterator;
035:
036: import javax.resource.spi.ManagedConnection;
037:
038: /**
039: * Stack (fifo) ordered set, used by the JCA code so recent
040: * connections are used first.
041: */
042: public class IdlePoolSet extends AbstractSet<ManagedConnection> {
043: private final int _capacity;
044:
045: private final ManagedConnection[] _entries;
046: private final int _entriesLength;
047:
048: private int _head;
049: private int _tail;
050:
051: IdlePoolSet(int capacity) {
052: _capacity = capacity;
053: _entries = new ManagedConnection[2 * capacity];
054: _entriesLength = _entries.length;
055: }
056:
057: /**
058: * Returns the number of elements in the set.
059: */
060: public int size() {
061: return (_head - _tail + _entriesLength) % _entriesLength;
062: }
063:
064: /**
065: * Returns true if empty.
066: */
067: public boolean isEmpty() {
068: return _head == _tail;
069: }
070:
071: /**
072: * Peeks the first item.
073: */
074: public ManagedConnection first() {
075: if (_head != _tail)
076: return _entries[_tail];
077: else
078: return null;
079: }
080:
081: /**
082: * Adds an element.
083: */
084: public boolean add(ManagedConnection o) {
085: if (_capacity <= size())
086: return false;
087:
088: for (int i = _tail; i != _head; i = (i + 1) % _entriesLength) {
089: if (_entries[i] == o)
090: return false;
091: }
092:
093: _entries[_head] = o;
094: _head = (_head + 1) % _entriesLength;
095:
096: return true;
097: }
098:
099: /**
100: * Clears the set.
101: */
102: public void clear() {
103: _head = _tail = 0;
104:
105: for (int i = 0; i < _entriesLength; i++)
106: _entries[i] = null;
107: }
108:
109: /**
110: * Returns true if the item is in the set.
111: */
112: public boolean contains(Object o) {
113: for (int i = _tail; i != _head; i = (i + 1) % _entriesLength) {
114: if (_entries[i] == o)
115: return true;
116: }
117:
118: return false;
119: }
120:
121: /**
122: * Returns true if the item is in the set.
123: */
124: public boolean containsAll(Collection<?> c) {
125: Iterator iter = c.iterator();
126:
127: while (iter.hasNext()) {
128: if (!contains(iter.next()))
129: return false;
130: }
131:
132: return true;
133: }
134:
135: /**
136: * Returns an iterator to the set.
137: */
138: public Iterator<ManagedConnection> iterator() {
139: return new IdlePoolIterator();
140: }
141:
142: /**
143: * Removes an element of the set.
144: */
145: public boolean remove(Object o) {
146: for (int i = _tail; i != _head; i = (i + 1) % _entriesLength) {
147: if (_entries[i] == o) {
148: return removeEntry(i);
149: }
150: }
151:
152: return false;
153: }
154:
155: /**
156: * Removes an element of the set.
157: */
158: public boolean removeAll(Collection<?> c) {
159: Iterator iter = c.iterator();
160: boolean result = true;
161:
162: while (iter.hasNext()) {
163: if (!remove(iter.next()))
164: result = false;
165: }
166:
167: return result;
168: }
169:
170: /**
171: * Removes an element of the set.
172: */
173: public boolean retainAll(Collection<?> c) {
174: throw new UnsupportedOperationException(getClass().getName());
175: }
176:
177: /**
178: * Returns an array of the elements in the set.
179: */
180: public Object[] toArray() {
181: Object[] values = new Object[size()];
182: int j = 0;
183:
184: for (int i = _tail; i != _head; i = (i + 1) % _entriesLength) {
185: values[j++] = _entries[i];
186: }
187:
188: return values;
189: }
190:
191: /**
192: * Returns an array of the elements in the set.
193: */
194: public ManagedConnection[] toArray(ManagedConnection[] values) {
195: int j = 0;
196:
197: for (int i = _tail; i != _head; i = (i + 1) % _entriesLength) {
198: values[j++] = _entries[i];
199: }
200:
201: return values;
202: }
203:
204: boolean removeEntry(int i) {
205: if (i == _head)
206: return false;
207:
208: if (i == _tail) {
209: _entries[_tail] = null;
210: } else if (_tail < i) {
211: // ... _tail xxx i xxx _head ...
212:
213: System.arraycopy(_entries, _tail, _entries, _tail + 1, i
214: - _tail);
215: } else {
216: // xxx i xxx _head ... _tail xxx
217:
218: if (i > 0)
219: System.arraycopy(_entries, 0, _entries, 1, i);
220:
221: _entries[0] = _entries[_entriesLength - 1];
222:
223: System.arraycopy(_entries, _tail, _entries, _tail + 1,
224: _entriesLength - _tail - 1);
225: }
226:
227: _entries[_tail] = null;
228: _tail = (_tail + 1) % _entriesLength;
229:
230: return true;
231: }
232:
233: /**
234: * Returns the hash code.
235: */
236: public int hashCode() {
237: return System.identityHashCode(_entries);
238: }
239:
240: /**
241: * Test for equality
242: */
243: public boolean equals(Object o) {
244: return this == o;
245: }
246:
247: class IdlePoolIterator implements Iterator<ManagedConnection> {
248: private int _head;
249: private int _tail;
250: private int _i;
251:
252: IdlePoolIterator() {
253: _head = IdlePoolSet.this ._head;
254: _tail = IdlePoolSet.this ._tail;
255: _i = _tail;
256: }
257:
258: public boolean hasNext() {
259: return _i != _head;
260: }
261:
262: public ManagedConnection next() {
263: if (_i == _head)
264: return null;
265:
266: ManagedConnection value = _entries[_i];
267:
268: _i = (_i + 1) % _entriesLength;
269:
270: return value;
271: }
272:
273: public void remove() {
274: int i = (_i + _entriesLength - 1) % _entriesLength;
275:
276: removeEntry(i);
277:
278: _tail = IdlePoolSet.this._tail;
279: }
280: }
281: }
|