001: /***
002: * jwma Java WebMail
003: * Copyright (c) 2000-2003 jwma team
004: *
005: * jwma is free software; you can distribute and use this source
006: * under the terms of the BSD-style license received along with
007: * the distribution.
008: ***/package dtw.webmail.util;
009:
010: import java.util.*;
011:
012: import org.apache.log4j.Logger;
013: import org.exolab.castor.jdo.*;
014:
015: /**
016: * Class that implements a pool for <tt>CastorDatabase</tt>
017: * instances.
018: * <br>
019: * The factory method is used for creating pools of the
020: * given database and size, using the database's factory method
021: * to create the requested amount of instances.
022: *
023: * @author Dieter Wimberger
024: * @version 0.9.7 07/02/2003
025: */
026: public class CastorDatabasePool {
027:
028: //logging
029: private static Logger log = Logger
030: .getLogger(CastorDatabasePool.class);
031:
032: //Instance attributes
033: private List m_Pool;
034: private boolean m_Serving = false;
035: private CastorDatabase m_Database;
036: private int m_Size;
037:
038: /**
039: * Private, and empty to disallow any form of construction
040: * via new.
041: */
042: private CastorDatabasePool() {
043: }//CastorDatabasePool
044:
045: /**
046: * Constructs a <tt>CastorDatabasePool</tt> instance.
047: */
048: private CastorDatabasePool(int size, CastorDatabase database) {
049: m_Size = size;
050: m_Database = database;
051: }//CastorDatabasePool
052:
053: /**
054: * Returns a leased <tt>CastorDatabase</tt> instance
055: * from this pool.
056: *
057: * @return the leased <tt>CastorDatabase</tt> from this pool.
058: */
059: public synchronized CastorDatabase leaseDatabase() {
060: if (!m_Serving) {
061: return null;
062: }
063: boolean served = false;
064: CastorDatabase freeDatabase = null;
065: while (!served) {
066: if (m_Pool.size() == 0) {
067: try {
068: wait();
069: } catch (Exception ex) {
070: //do nothing but wait again :)
071: }
072: } else {
073: freeDatabase = (CastorDatabase) m_Pool.get(0);
074: m_Pool.remove(0);
075: served = true;
076: }
077: }
078: return freeDatabase;
079: }//leaseDatabase
080:
081: /**
082: * Releases a formerly leased <tt>CastorDatabase</tt>, returning
083: * it into this pool.
084: *
085: * @param database the formerly leased <tt>CastorDatabase</tt>
086: * to be released.
087: */
088: public synchronized void releaseDatabase(CastorDatabase database) {
089: //ensure the last transaction has been commited:
090: if (database.isActive()) {
091: try {
092: database.commit();
093: } catch (PersistenceException ex) {
094: try {
095: database.rollback();
096: } catch (TransactionNotInProgressException tex) {
097: //do nothing, should not happen, just satisfy compiler
098: }
099: }
100: }
101: if (database.isClosed()) {
102: //replace with another one
103: try {
104: database = m_Database.createCastorDatabase();
105: } catch (Exception ex) {
106: notifyAll();
107: return;
108: }
109: }
110: m_Pool.add(database);
111: notifyAll();
112: }//releaseDatabase
113:
114: /**
115: * Returns the ceiling (in terms of size) of this pool.
116: *
117: * @return the ceiling size of this pool as <tt>int</tt>.
118: */
119: public int getCeiling() {
120: return m_Size;
121: }//getCeiling
122:
123: /**
124: * Returns the size of this pool.
125: *
126: * @return the actual size of this pool as <tt>int</tt>.
127: */
128: public int size() {
129: return m_Pool.size();
130: }//size
131:
132: /**
133: * Resizes the pool.
134: *
135: * @param size the new size as <tt>int</tt>.
136: */
137: public void resize(int size) {
138: //FIXME: not very efficient
139: synchronized (m_Pool) {
140: clear();
141: m_Size = size;
142: initPool();
143: }
144: }//resize
145:
146: /**
147: * Removes all <tt>CastorDatabase</tt> references from
148: * this pool.
149: * Note that it will do so gracefully, waiting for
150: * leased <tt>CastorDatabases</tt>.
151: */
152: public void clear() {
153: m_Serving = false;
154: //wait until pool complete
155: while (m_Pool.size() != m_Size) {
156: try {
157: wait();
158: } catch (Exception ex) {
159: //do nothing but wait again :)
160: }
161: }
162: //remove all elements
163: m_Pool.clear();
164: }//clearPool
165:
166: /**
167: * Initializes a pool of <tt>CastorDatabases</tt> instances.
168: */
169: protected void initPool() {
170: m_Pool = new ArrayList(m_Size);
171: for (int i = 0; i < m_Size; i++) {
172: try {
173: m_Pool.add(m_Database.createCastorDatabase());
174: log.debug("Added new database");
175: } catch (Exception ex) {
176: //log probably
177: ex.printStackTrace();
178: }
179: }
180: m_Serving = true;
181: }//initPool
182:
183: /**
184: * Creates a <tt>CastorDatabasePool</tt> with the given size,
185: * containing the given <tt>CastorDatabase</tt> instances.
186: *
187: * @param size the size as <tt>int</tt>.
188: * @param CastorDatabase the <tt>CastorDatabase</tt> to be pooled.
189: */
190: public static CastorDatabasePool createCastorDatabasePool(int size,
191: CastorDatabase database) {
192:
193: CastorDatabasePool pool = new CastorDatabasePool(size, database);
194: pool.initPool();
195: return pool;
196: }//createCastorDatabasePool
197:
198: }//class CastorDatabasePool
|