// Copyright (c) 1999, 2000 Oracle Corporation package oracle.jbo.common.ampool; import java.util.Vector; import java.util.Hashtable; import javax.naming.*; import oracle.jbo.*; class AMInfoEntry { boolean isCheckedOut = false; Object cookie = null; long timeToCreateMillis = -1; long creationTimeMillis = -1; } class LoadBalanceInfo { private AMHomeDesc[] mDescs; private int mCreationPolicy = ApplicationPoolImpl.CREATION_POLICY_SERIAL; private int mMaxHandlePolicy = ApplicationPoolImpl.MAX_HANDLE_POLICY_SPILL; private boolean mBalanced = false; private int mIndex = -1; private Vector[] mAMInstVecs; LoadBalanceInfo(AMHomeDesc[] descs) { mDescs = descs; mAMInstVecs = new Vector[descs.length]; } int getCreationPolicy() { return mCreationPolicy; } void setCreationPolicy(int creationPolicy) { mCreationPolicy = creationPolicy; } int getMaxHandlePolicy() { return mMaxHandlePolicy; } void setMaxHandlePolicy(int maxHandlePolicy) { mMaxHandlePolicy = maxHandlePolicy; } boolean isBalanced() { return mBalanced; } void setBalanced(boolean balanced) { mBalanced = balanced; } AMHomeDesc getNextHomeDescForCreate() { if (mDescs == null || mDescs.length == 0) { return null; } AMHomeDesc hDesc = null; int tryIndex = mIndex; if (tryIndex < 0) { tryIndex = 0; } else if (getCreationPolicy() == ApplicationPoolImpl.CREATION_POLICY_ROUND_ROBIN) { tryIndex++; } int j; for (j = 0; j < mDescs.length; j++) { if (tryIndex >= mDescs.length) { tryIndex = 0; } if (mAMInstVecs[tryIndex] == null) { mAMInstVecs[tryIndex] = new Vector(); } int numOfInsts = mAMInstVecs[tryIndex].size(); hDesc = mDescs[tryIndex]; if (hDesc.getMaxNumOfInsts() < 0 || numOfInsts < hDesc.getMaxNumOfInsts()) { break; } tryIndex++; } if (j >= mDescs.length) { // All home descs are full return null; } return hDesc; } } /** * This class provides the default implementation of the ApplicationPool interface. * * View definition of ApplicationPool * View Implementation of ApplicationPoolImpl *
* @author Juan Oropeza */ public class ApplicationPoolImpl extends Object implements ApplicationPool { // static final String IS_CHECKED_OUT = "Yes"; // static final String IS_NOT_CHECKED_OUT = "No"; public static int CREATION_POLICY_SERIAL = 0; public static int CREATION_POLICY_ROUND_ROBIN = 1; public static int MAX_HANDLE_POLICY_SPILL = 0; public static int MAX_HANDLE_POLICY_ERROR = 1; private long signature; private Hashtable env; private String poolName; private Vector instances = new Vector(10); private Hashtable userData; private String sConnectString; private String sApplicationModule; private Hashtable instanceInfo = new Hashtable(10); private Hashtable cookieInfo = new Hashtable(10); private int cookieNum = 0; private String sUserName; private String sPassword; private LoadBalanceInfo mLBInfo = null; /** * Constructor */ public ApplicationPoolImpl() { signature = System.currentTimeMillis(); } long getSignature() { return signature; } int getNextCookieNum() { return cookieNum++; } public void initialize(String sPoolName , String sApplicationModule, String sConnectString, Hashtable env) { this.poolName = sPoolName; this.env = env; this.sConnectString = sConnectString; this.sApplicationModule = sApplicationModule; } public String getApplicationModuleClass() { return this.sApplicationModule; } public String getConnectString() { return this.sConnectString; } public Hashtable getEnvironment() { return this.env; } public synchronized void checkin(ApplicationModule instance) { setAvailable(instance , true); } public long getTimeToCreateMillis(ApplicationModule instance) { AMInfoEntry infoEntry = (AMInfoEntry) instanceInfo.get(instance); return infoEntry.timeToCreateMillis; } public long getCreationTimeMillis(ApplicationModule instance) { AMInfoEntry infoEntry = (AMInfoEntry) instanceInfo.get(instance); return infoEntry.creationTimeMillis; } public boolean isAvailable(ApplicationModule instance) { AMInfoEntry infoEntry = (AMInfoEntry) instanceInfo.get(instance); return (!infoEntry.isCheckedOut); } public void setAvailable(ApplicationModule instance, boolean bSet) { AMInfoEntry infoEntry = (AMInfoEntry) instanceInfo.get(instance); infoEntry .isCheckedOut = (!bSet); } public synchronized ApplicationModule createNewInstance() throws Exception { // create a new instance using the connect info InitialContext initialContext = new InitialContext(env); ApplicationModuleHome home = (ApplicationModuleHome) initialContext.lookup(sApplicationModule); long start = System.currentTimeMillis(); ApplicationModule am = home.create(); long end = System.currentTimeMillis(); am.getTransaction().connect(this.sConnectString, this.sUserName, this.sPassword); AMInfoEntry infoEntry = new AMInfoEntry(); infoEntry.cookie = new AMInstanceCookie(this); infoEntry.timeToCreateMillis = end - start; infoEntry.creationTimeMillis = end; instanceInfo.put(am, infoEntry); cookieInfo.put(infoEntry.cookie, am); // add instance to collection instances.addElement(am); setAvailable(am, true); return am; } public synchronized ApplicationModule checkout() throws Exception { ApplicationModule available = null; ApplicationModule current = null; for (int i = 0 ; i < instances.size(); i ++) { current = (ApplicationModule) instances.elementAt(i); if (isAvailable(current)) { setAvailable(current, false); available = current; return available; } } if (available == null) { available = createNewInstance(); setAvailable(available, false); } return available; } public synchronized void releaseInstances() { int nSize = instances.size(); for (int i = 0; i < nSize; i++) { ApplicationModule instance = (ApplicationModule) instances.elementAt(i); instance.remove(); } for (int i = nSize - 1; i >= 0; i--) { instances.removeElementAt(i); } instanceInfo.clear(); cookieInfo.clear(); } public synchronized int getAvailableNumPools() { int count = 0; ApplicationModule current = null; for(int i = 0 ; i < instances.size(); i++) { current = (ApplicationModule) instances.elementAt(i); if (isAvailable(current)) { count++; } } return count; } public synchronized int getInstanceCount() { return instances.size(); } public synchronized ApplicationModule getInstance(int nIndex) { return (ApplicationModule) instances.elementAt(nIndex); } public synchronized ApplicationModule getInstanceByCookie(Object cookie, boolean checkout) { if (cookie == null || !(cookie instanceof AMInstanceCookie)) { throw new ApplicationPoolException(AMPoolMessageBundle.class, AMPoolMessageBundle.EXC_AMPOOL_INVALID_COOKIE, new Object[] { cookie }); } if (((AMInstanceCookie) cookie).getPoolSignature() != signature) { throw new ApplicationPoolException(AMPoolMessageBundle.class, AMPoolMessageBundle.EXC_AMPOOL_INVALID_POOL_SIGNATURE, null); } ApplicationModule instance = (ApplicationModule) cookieInfo.get(cookie); if (instance != null) { if (checkout) { if (isAvailable(instance)) { setAvailable(instance, false); return instance; } } else { return instance; } } return null; } public Object getCookie(ApplicationModule instance) { Object obj = instanceInfo.get(instance); if (obj != null) { return ((AMInfoEntry) obj).cookie; } return null; } public synchronized String getPoolName() { return poolName; } /** * returns the User Data hashtable. This is a generic container for * any settings the user would like to associate with this application instance. */ public Hashtable getUserData() { return userData; } /** * Replaces the userData with the new Hashtable. */ public void setUserData(Hashtable data) { this.userData = data; } /** * returns the user name **/ public String getUserName() { return this.sUserName; } public void setUserName(String sUser) { this.sUserName = sUser; } public void setPassword(String sPassword) { this.sPassword = sPassword; } /** * returns the password **/ public String getPassword() { return this.sPassword; } public void commitAndSyncCache(ApplicationModule instance) { int snapId = instance.getTransaction().commitAndSnap(); if (snapId >= 0) { for(int i = 0 ; i < instances.size(); i++) { ApplicationModule current = (ApplicationModule) instances.elementAt(i); if (current != instance) { current.getTransaction().applyChangeSet(snapId); } } instance.getTransaction().removeChangeSet(snapId); } } }