001: /* ----- BEGIN LICENSE BLOCK -----
002: * Version: MPL 1.1
003: *
004: * The contents of this file are subject to the Mozilla Public License Version
005: * 1.1 (the "License"); you may not use this file except in compliance with
006: * the License. You may obtain a copy of the License at
007: * http://www.mozilla.org/MPL/
008: *
009: * Software distributed under the License is distributed on an "AS IS" basis,
010: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
011: * for the specific language governing rights and limitations under the
012: * License.
013: *
014: * The Original Code is the DataShare server.
015: *
016: * The Initial Developer of the Original Code is
017: * Ball Aerospace & Technologies Corp, Fairborn, Ohio
018: * Portions created by the Initial Developer are Copyright (C) 2001
019: * the Initial Developer. All Rights Reserved.
020: *
021: * Contributor(s): Charles Wood <cwood@ball.com>
022: *
023: * ----- END LICENSE BLOCK ----- */
024: /* RCS $Id: RetreiveDataBeans.java,v 1.6 2002/02/21 13:20:13 lizellaman Exp $
025: * $Log: RetreiveDataBeans.java,v $
026: * Revision 1.6 2002/02/21 13:20:13 lizellaman
027: * correct problem of not getting history finished object
028: *
029: * Revision 1.5 2002/02/20 14:27:54 lizellaman
030: * changes to improve history retrieval
031: *
032: * Revision 1.4 2002/02/11 20:02:10 lizellaman
033: * Correct problem with retreiving non-cached EJBs, and update version/date
034: *
035: * Revision 1.3 2002/01/29 20:50:17 lizellaman
036: * Added LoggingInterface, modified the PropertiesInterface implementation
037: *
038: * Revision 1.2 2002/01/03 03:37:36 lizellaman
039: * periodic update of changes I have made
040: *
041: * Revision 1.1.1.1 2001/10/23 13:37:18 lizellaman
042: * initial sourceforge release
043: *
044: */
045:
046: package org.datashare;
047:
048: import java.util.Enumeration;
049: import java.util.Vector;
050: import java.util.List;
051: import org.datashare.objects.DataShareObject;
052: import org.datashare.PersistenceInterface;
053:
054: /**
055: * This class is used to retreive the DataShare Data (DataShareObjects) for
056: * the specified Channel, and the count of Data objects in the channel. Note
057: * that data is stored as byte arrays that represent a DataShareObject instance.
058: *
059: * @date September 21, 2001
060: * @version 2.0
061: * @author Chuck Wood
062: */
063: public class RetreiveDataBeans {
064: //private boolean firsttime = true;
065: //private Object[] allChannelData = new Object[0];
066: private boolean cancelHistory = false;
067: private Vector dataObjects = new Vector();
068: private boolean historyAvailable = false;
069: private Object waitForHistory = new Object();
070: private boolean allHistoryRetreived = false;
071:
072: /**
073: * constructor, not required as this class also has static methods
074: */
075: public RetreiveDataBeans() {
076: }
077:
078: public void cancelHistory() {
079: cancelHistory = true;
080: }
081:
082: /**
083: * retrieves the DataShareObject for a channel that has the specified sequence number,
084: * and returns null if no bean by that number is available (i.e. no more beans)
085: */
086: public static DataShareObject
087: getData(PersistenceInterface p0, String channelKeyForData, int sequenceNumber)
088: {
089: //DSData myBean = null;
090: DataShareObject dso = null;
091: int count = 0;
092: SessionUtilities.getLoggingInterface().debugMsg(SessionUtilities.getLoggingInterface().DEBUG,
093: SessionUtilities.getLoggingInterface().DATABASE,
094: "RetreiveDataBeans.getData() called for channelID " + channelKeyForData + ", sequence # " + sequenceNumber);
095:
096:// Enumeration enum = EjbUtil.findByQuery("DSDataHome",
097:// "getChannelKey()='"+channelKeyForData+
098:// "' AND getSequence()='" + sequenceNumber+"'");
099:// enum = EjbUtil.findByQuery(home, "getID()='"+theKey+"'" );
100:// Enumeration enum = EjbUtil.findByQuery("ADSSpaceEntityHome", "getOwnerID()='"+id+"' AND getName()='"+domain+"'");
101:// Enumeration enum = EjbUtil.findByQuery("ECATripletHome", "getEvent()='"+eventName+"' and "+
102:// "getOwner()='"+enterpriseID+"' Order By getEventPriority()");
103:
104: Enumeration enum = p0.searchForUserObjects("DSData3Home",
105: "getChannelKey()='"+channelKeyForData+
106: "' AND getSequence()='" + sequenceNumber+"'");
107:
108: // enum should contain only one element, or be null
109: if(enum != null)
110: {
111: for(; enum.hasMoreElements(); )
112: {
113: count++;
114: try
115: {
116: Object object = enum.nextElement();
117: if(object instanceof PersistenceDataInterface) // all our objects should be of this type
118: {
119: PersistenceDataInterface pdi = (PersistenceDataInterface)object;
120: dso = (DataShareObject)SessionUtilities.retrieveObject((byte[])pdi.getUserObject());
121: dso.isFromHistory = true;
122: }
123: else
124: SessionUtilities.getLoggingInterface().debugMsg(SessionUtilities.getLoggingInterface().DEBUG,
125: SessionUtilities.getLoggingInterface().DATABASE,
126: "RetreiveDataBeans did not find DataShareObject in ChannelData!!");
127: }
128: catch(Exception e)
129: {
130: SessionUtilities.getLoggingInterface().debugMsg(SessionUtilities.getLoggingInterface().ERROR,
131: SessionUtilities.getLoggingInterface().DATABASE,
132: "Problems in RetreiveDataBeans.getData(seqNo): ");
133: e.printStackTrace();
134: }
135: }
136: if(count > 1)
137: {
138: SessionUtilities.getLoggingInterface().debugMsg(SessionUtilities.getLoggingInterface().DEBUG,
139: SessionUtilities.getLoggingInterface().DATABASE,
140: "*** Unexpected result! 2 EJBs in channel with same sequence number!!");
141: }
142: }
143: else
144: {
145: SessionUtilities.getLoggingInterface().debugMsg(SessionUtilities.getLoggingInterface().DEBUG,
146: SessionUtilities.getLoggingInterface().DATABASE,
147: "RetreiveDataBeans.getData() returned an empty enumeration (no Data with that sequence number?)");
148: }
149:
150: if(dso != null)
151: {
152: SessionUtilities.getLoggingInterface().debugMsg(SessionUtilities.getLoggingInterface().DEBUG,
153: SessionUtilities.getLoggingInterface().DATABASE,
154: "RetrieveDataBeans.getData() found DataShareObject " + sequenceNumber);
155: }
156:
157: return dso;
158: }
159:
160: /**
161: * should be called only once to retrieve all the Data (stored locally) currently
162: * available for the channel, then subsequent calls to getNextData will actually
163: * return the data. Subsequent calls on an instance will cause the getNextData call to
164: * start back at the beginning of the data.
165: */
166: public synchronized void retrieveAllData(PersistenceInterface p0,
167: String channelKeyForData) {
168: dataObjects = new Vector();
169: historyAvailable = false;
170: final PersistenceInterface pi = p0;
171: final String key = channelKeyForData;
172: final Runnable getTheData = new Runnable() {
173: public void run() {
174: Thread.currentThread().setName(
175: "GetTheHistoryForChannel" + key);
176: getTheDataLoop(pi, key);
177: }
178: };
179: Thread shortLivedThread = new Thread(getTheData);
180: //shortLivedThread.setPriority(Thread.currentThread().getPriority()+1);
181: shortLivedThread.start();
182: Thread.currentThread().yield();
183: }
184:
185: /**
186: * will go get the data and make if available as it is retreived, assumes sequence numbers
187: * start at zero!
188: */
189: private void
190: getTheDataLoop(PersistenceInterface p0, String channelKeyForData)
191: {
192: int count = 0; // also first sequence number
193: final int increment = 1000; // how many objects to get for each loop
194: boolean finished = false;
195: try{
196: SessionUtilities.getLoggingInterface().debugMsg(SessionUtilities.getLoggingInterface().DEBUG,
197: SessionUtilities.getLoggingInterface().DATABASE,
198: "RetrieveDataBeans.retrieveAllData() looking for all " + channelKeyForData + " data objects");
199: while(!finished && !cancelHistory)
200: {
201: try{
202: SessionUtilities.getLoggingInterface().debugMsg(SessionUtilities.getLoggingInterface().DEBUG,
203: SessionUtilities.getLoggingInterface().DATABASE,
204: "Looking for EJB-> getChannelKey()='"+channelKeyForData+"' AND (getSequence() >= '"+count+"' AND getSequence() < '"+(count+increment)+"') Order By getSequence()");
205: Enumeration enum = p0.searchForUserObjects("DSData3Home",
206: "getChannelKey()='"+channelKeyForData+"' AND (getSequence() >= '"+count+"' AND getSequence() < '"+(count+increment)+"') Order By getSequence()"); // data comes back in sequence
207:
208: if(!enum.hasMoreElements())
209: finished = true; // no more data
210:
211: int countThisLoop = 0; // so we can stop getting history if it is still getting created (live data going on now)
212: while(enum.hasMoreElements())
213: {
214: Object object = enum.nextElement();
215: synchronized(dataObjects)
216: {
217: DataShareObject dso = null;
218: if(object instanceof byte[]) // all our objects should be of this type
219: {
220: dso = (DataShareObject)SessionUtilities.retrieveObject((byte[])object);
221: dso.isFromHistory = true;
222: dataObjects.add(dso);
223: count++;
224: countThisLoop++;
225: }
226: else if(object instanceof DataShareObject) // we've been cached!
227: {
228: dso = (DataShareObject)object;
229: dso.isFromHistory = true;
230: dataObjects.add(dso);
231: count++;
232: countThisLoop++;
233: }
234: else
235: {
236: SessionUtilities.getLoggingInterface().debugMsg(SessionUtilities.getLoggingInterface().WARNING,
237: SessionUtilities.getLoggingInterface().DATABASE,
238: "RetreiveDataBeans.retrieveAllData found object that is not a byte[] or DataShareObject -> " + object);
239: }
240: }
241: }
242: if(countThisLoop < increment) // then we are getting history as it is getting created, stop history
243: finished = true;
244: }
245: catch(Exception e)
246: {
247: SessionUtilities.getLoggingInterface().debugMsg(SessionUtilities.getLoggingInterface().ERROR,
248: SessionUtilities.getLoggingInterface().DATABASE,
249: "Problem in RetreiveDataBeans: ->");
250: e.printStackTrace();
251: if(e instanceof java.io.InvalidClassException) // probably serialVersionUID problems, abort
252: {
253: finished = true;
254: allHistoryRetreived = true;
255: }
256: }
257: historyAvailable = true;
258: synchronized(waitForHistory)
259: {
260: waitForHistory.notifyAll();
261: }
262: Thread.currentThread().yield();
263: } // end of while !finished
264: SessionUtilities.getLoggingInterface().debugMsg(SessionUtilities.getLoggingInterface().DEBUG,
265: SessionUtilities.getLoggingInterface().DATABASE,
266: "RetrieveDataBeans.retrieveAllData() found " + count + " data objects for " + channelKeyForData);
267: }
268: catch(Exception e2)
269: {
270: SessionUtilities.getLoggingInterface().debugMsg(SessionUtilities.getLoggingInterface().ERROR,
271: SessionUtilities.getLoggingInterface().DATABASE,
272: "Problem in RetreiveDataBeans: ->");
273: e2.printStackTrace();
274: }
275: allHistoryRetreived = true;
276: synchronized(waitForHistory)
277: {
278: waitForHistory.notifyAll();
279: }
280: }
281:
282: /**
283: * retreives the DataShareObjects for a channel, note that retrieveAllData must have been
284: * called before this method. The data is returned in order, subsequent calls just
285: * return the next 'chunk' of data.
286: * @param count the number of DataShareObjects to return
287: * @return an array of DataShareObjects, should contain 'count' number, may be less if
288: * there is not enough data less, may be zero size if there is no data left.
289: *
290: */
291: public synchronized DataShareObject[] getNextData(int count) {
292: // special cases are no data left, not enough data left, exactly enough data left
293:
294: int returnArrayLength = 0;
295: DataShareObject[] returnArray = new DataShareObject[0];
296:
297: // wait for first of the data to show up...
298: if (!cancelHistory && !historyAvailable
299: || (!allHistoryRetreived && dataObjects.size() == 0)) // set to true first time only, from then on it is true
300: {
301: SessionUtilities
302: .getLoggingInterface()
303: .debugMsg(
304: SessionUtilities.getLoggingInterface().DEBUG,
305: SessionUtilities.getLoggingInterface().DATABASE,
306: "Waiting for history to be made available by retrieval Thread...");
307: synchronized (waitForHistory) {
308: try {
309: waitForHistory.wait();
310: } catch (Exception e) {
311: e.printStackTrace();
312: }
313: }
314: }
315:
316: synchronized (dataObjects) {
317: // determine size of return array: smaller of data remaining and requested count
318: if (dataObjects.size() < count)
319: returnArrayLength = dataObjects.size();
320: else
321: returnArrayLength = count;
322:
323: if (returnArrayLength > 0) {
324: SessionUtilities
325: .getLoggingInterface()
326: .debugMsg(
327: SessionUtilities.getLoggingInterface().DEBUG,
328: SessionUtilities.getLoggingInterface().DATABASE,
329: "Retrieval Thread retrieving some data for history : "
330: + returnArrayLength
331: + " objects");
332: returnArray = new DataShareObject[returnArrayLength];
333: List list = dataObjects.subList(0, returnArrayLength);
334: Object[] temp = list.toArray();
335:
336: // copy requested data into the array we will return
337: System.arraycopy(temp, 0, returnArray, 0,
338: returnArrayLength);
339: List remainingStuff = dataObjects.subList(
340: returnArrayLength, dataObjects.size());
341: dataObjects = new Vector(remainingStuff);
342: } else if (allHistoryRetreived) {
343: returnArray = null;
344: }
345: }
346:
347: if (cancelHistory)
348: returnArray = null;
349:
350: return returnArray;
351: }
352:
353: /**
354: * retreives the number of all the Data EJB objects for the Channel Key that was provided.
355: *
356: * @param channelKeyForData the ADSkey value for the Channel whose data should
357: * be retreived
358: * @return a count of the Data objects that would be retrieved by a
359: * getData() call
360: */
361: public static int getDataCount(PersistenceInterface p0,
362: String channelKeyForData) {
363: SessionUtilities.getLoggingInterface().debugMsg(
364: SessionUtilities.getLoggingInterface().DEBUG,
365: SessionUtilities.getLoggingInterface().DATABASE,
366: "RetreiveDataBeans.getDataCount() called for channelID "
367: + channelKeyForData);
368:
369: return p0.findCount("DSData3Home", "getChannelKey()='"
370: + channelKeyForData + "'");
371: }
372:
373: }
|