001: ///////////////////////////////////////////////////////////////////////////////
002: //
003: // Copyright (C) 2003-@year@ by Thomas M. Hazel, MyOODB (www.myoodb.org)
004: //
005: // All Rights Reserved
006: //
007: // This program is free software; you can redistribute it and/or modify
008: // it under the terms of the GNU General Public License and GNU Library
009: // General Public License as published by the Free Software Foundation;
010: // either version 2, or (at your option) any later version.
011: //
012: // This program is distributed in the hope that it will be useful,
013: // but WITHOUT ANY WARRANTY; without even the implied warranty of
014: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: // GNU General Public License and GNU Library General Public License
016: // for more details.
017: //
018: // You should have received a copy of the GNU General Public License
019: // and GNU Library General Public License along with this program; if
020: // not, write to the Free Software Foundation, 675 Mass Ave, Cambridge,
021: // MA 02139, USA.
022: //
023: ///////////////////////////////////////////////////////////////////////////////
024: package org.myoodb.event;
025:
026: import org.myoodb.core.*;
027: import org.myoodb.collectable.*;
028:
029: public class EventLogDbImpl extends LogStoreDbImpl implements EventLog {
030: private transient org.myoodb.util.EventSemaphore m_eventSemaphore = null;
031:
032: public EventLogDbImpl() {
033: }
034:
035: private boolean shouldEventBeAdded(
036: java.util.ArrayList listOfInterest,
037: org.myoodb.core.Identifier handle) {
038: boolean retval = false;
039:
040: if ((listOfInterest != null) && (listOfInterest.size() != 0)) {
041: java.util.Iterator objectIter = listOfInterest.iterator();
042: while (objectIter.hasNext()) {
043: if (objectIter.next().equals(handle) == true) {
044: retval = true;
045: break;
046: }
047: }
048: } else {
049: retval = true;
050: }
051:
052: return retval;
053: }
054:
055: private void yield(long timeout)
056: throws java.lang.InterruptedException {
057: if (m_eventSemaphore == null) {
058: synchronized (this ) {
059: if (m_eventSemaphore == null) {
060: m_eventSemaphore = new org.myoodb.util.EventSemaphore();
061: /*
062: m_eventSemaphore.setFungeFactorTime(1000);
063: m_eventSemaphore.setFungeFactorHoldDownTime(100);
064: */
065: }
066: }
067: }
068:
069: if (timeout != -1) {
070: m_eventSemaphore.yield(timeout);
071: } else {
072: m_eventSemaphore.yield();
073: }
074: }
075:
076: private void signalAll() {
077: if (m_eventSemaphore != null) {
078: m_eventSemaphore.signalAll();
079: }
080: }
081:
082: protected void finalize() throws Throwable {
083: if (m_eventSemaphore != null) {
084: m_eventSemaphore.signalAll();
085: }
086: }
087:
088: public void fixUpReference(long fixUpTime) {
089: if (referenceHasBeenFixedUp(fixUpTime) == true) {
090: return;
091: }
092:
093: super .fixUpReference(fixUpTime);
094: }
095:
096: public void cleanUpReference() {
097: super .cleanUpReference();
098: }
099:
100: public Event addEvent(Event event) {
101: event = (Event) super .addLogObject((LogObject) event);
102:
103: signalAll();
104:
105: return event;
106: }
107:
108: public Event removeEvent(Event event) {
109: event = (Event) super .removeLogObject((LogObject) event);
110:
111: signalAll();
112:
113: return event;
114: }
115:
116: public Event getFirstEvent() {
117: return (Event) super .getFirstLogObject();
118: }
119:
120: public Event getLastEvent() {
121: return (Event) super .getLastLogObject();
122: }
123:
124: public Event getEvent(long time) {
125: return (Event) super .getLogObject(time);
126: }
127:
128: public java.util.ArrayList getEvents() {
129: return super .getLogObjects();
130: }
131:
132: public java.util.ArrayList getEvents(long start, long end) {
133: return getEvents(start, end, Event.class);
134: }
135:
136: public java.util.ArrayList getEvents(long start, long end,
137: Collectable ofInterest) {
138: return getEvents(start, end, Event.class, ofInterest);
139: }
140:
141: public java.util.ArrayList getEvents(long start, long end,
142: java.util.ArrayList listOfInterest) {
143: return getEvents(start, end, Event.class, listOfInterest);
144: }
145:
146: public java.util.ArrayList getEvents(long start, long end,
147: Class type) {
148: return super .getLogObjects(start, end, type);
149: }
150:
151: public java.util.ArrayList getEvents(long start, long end,
152: Class type, Collectable ofInterest) {
153: java.util.ArrayList listOfInterest = new java.util.ArrayList();
154: listOfInterest.add(ofInterest);
155:
156: return getEvents(start, end, type, listOfInterest);
157: }
158:
159: public java.util.ArrayList getEvents(long start, long end,
160: Class type, java.util.ArrayList listOfInterest) {
161: if (start == 0) {
162: long first = getStoreSize() > 0 ? getFirstEvent().getTime()
163: : start;
164: start = first;
165: }
166:
167: if (end == 0) {
168: long last = getStoreSize() > 0 ? getLastEvent().getTime()
169: : end;
170: end = last;
171: }
172:
173: java.util.ArrayList retval = new java.util.ArrayList();
174: java.util.ArrayList events = getStoreObjectValues(getContainerIndexes(
175: start, end));
176:
177: for (int i = 0; i < events.size(); i++) {
178: Event event = (Event) events.get(i);
179: org.myoodb.core.Identifier handle = event
180: .getCollectableHandle();
181:
182: if ((handle == null)
183: || (type.isAssignableFrom(event.getClass()) == false)) {
184: continue;
185: }
186:
187: long value = event.getTime();
188:
189: if ((value >= start) && (value <= end)) {
190: if (shouldEventBeAdded(listOfInterest, handle) == true) {
191: retval.add(event);
192: }
193: }
194: }
195:
196: return retval;
197: }
198:
199: public java.util.ArrayList getEvents(long start, int number,
200: Direction direction) {
201: return getEvents(start, number, direction, Event.class);
202: }
203:
204: public java.util.ArrayList getEvents(long start, int number,
205: Direction direction, Collectable ofInterest) {
206: java.util.ArrayList listOfInterest = new java.util.ArrayList();
207: listOfInterest.add(ofInterest);
208: return getEvents(start, number, direction, Event.class,
209: listOfInterest);
210: }
211:
212: public java.util.ArrayList getEvents(long start, int number,
213: Direction direction, java.util.ArrayList listOfInterest) {
214: return getEvents(start, number, direction, Event.class,
215: listOfInterest);
216: }
217:
218: public java.util.ArrayList getEvents(long start, int number,
219: Direction direction, Class type) {
220: return super .getLogObjects(start, number, direction, type);
221: }
222:
223: public java.util.ArrayList getEvents(long start, int number,
224: Direction direction, Class type, Collectable ofInterest) {
225: java.util.ArrayList listOfInterest = new java.util.ArrayList();
226: listOfInterest.add(ofInterest);
227: return getEvents(start, number, direction, type, listOfInterest);
228: }
229:
230: public java.util.ArrayList getEvents(long start, int number,
231: Direction direction, Class type,
232: java.util.ArrayList listOfInterest) {
233: if (start == 0) {
234: long first = getStoreSize() > 0 ? getFirstEvent().getTime()
235: : start;
236: start = first;
237: }
238:
239: boolean done = false;
240: java.util.ArrayList retval = new java.util.ArrayList();
241: java.util.LinkedList indexes = new java.util.LinkedList(
242: getContainerOfContainersKeys());
243:
244: // TODO: auto-add all objects in middle indexes if type is Event ( performance enhancement )
245:
246: // walk forward
247: if (direction == LogStore.Direction.FORWARDS) {
248: java.util.ListIterator iter = indexes.listIterator();
249: while ((done == false) && iter.hasNext()) {
250: java.util.ArrayList events = getStoreObjectValues(iter
251: .next());
252:
253: for (int i = 0; (done == false) && (i < events.size()); i++) {
254: Event event = (Event) events.get(i);
255: org.myoodb.core.Identifier handle = event
256: .getCollectableHandle();
257:
258: if ((handle == null)
259: || (type.isAssignableFrom(event.getClass()) == false)) {
260: continue;
261: }
262:
263: long value = event.getTime();
264:
265: if (value >= start) {
266: if (shouldEventBeAdded(listOfInterest, handle) == true) {
267: retval.add(event);
268: }
269: }
270:
271: if (retval.size() >= number) {
272: done = true;
273: break;
274: }
275: }
276: }
277: }
278: // walk backwards
279: else {
280: java.util.ListIterator iter = indexes.listIterator(indexes
281: .size());
282: while ((done == false) && iter.hasPrevious()) {
283: java.util.ArrayList events = getStoreObjectValues(iter
284: .previous());
285:
286: for (int i = (events.size() - 1); (done == false)
287: && (i >= 0); i--) {
288: Event event = (Event) events.get(i);
289: org.myoodb.core.Identifier handle = event
290: .getCollectableHandle();
291:
292: if ((handle == null)
293: || (type.isAssignableFrom(event.getClass()) == false)) {
294: continue;
295: }
296:
297: long value = event.getTime();
298:
299: if (value <= start) {
300: if (shouldEventBeAdded(listOfInterest, handle) == true) {
301: retval.add(event);
302: }
303: }
304:
305: if (retval.size() >= number) {
306: done = true;
307: break;
308: }
309: }
310: }
311: }
312:
313: return retval;
314: }
315:
316: //
317: // The following methods are associated with:
318: //
319: // - Listening for Event notification
320: //
321:
322: public java.util.ArrayList listenForEvents(Class type) {
323: return listenForEvents(0, type, (java.util.ArrayList) null);
324: }
325:
326: public java.util.ArrayList listenForEvents(Class type,
327: Collectable ofInterest) {
328: java.util.ArrayList listOfInterest = null;
329:
330: if (ofInterest != null) {
331: listOfInterest = new java.util.ArrayList();
332: listOfInterest.add(ofInterest);
333: }
334:
335: return listenForEvents(0, type, listOfInterest, 0);
336: }
337:
338: public java.util.ArrayList listenForEvents(Class type,
339: java.util.ArrayList listOfInterest) {
340: return listenForEvents(0, type, listOfInterest, 0);
341: }
342:
343: public java.util.ArrayList listenForEvents(Class type, long timeout) {
344: return listenForEvents(0, type, new java.util.ArrayList(),
345: timeout);
346: }
347:
348: public java.util.ArrayList listenForEvents(Class type,
349: Collectable ofInterest, long timeout) {
350: java.util.ArrayList list = null;
351:
352: if (ofInterest != null) {
353: list = new java.util.ArrayList();
354: list.add(ofInterest);
355: }
356:
357: return listenForEvents(0, type, list, timeout);
358: }
359:
360: public java.util.ArrayList listenForEvents(Class type,
361: java.util.ArrayList listOfInterest, long timeout) {
362: return listenForEvents(0, type, listOfInterest, timeout);
363: }
364:
365: public java.util.ArrayList listenForEvents(long moment, Class type) {
366: return listenForEvents(moment, type, new java.util.ArrayList());
367: }
368:
369: public java.util.ArrayList listenForEvents(long moment, Class type,
370: Collectable ofInterest) {
371: java.util.ArrayList list = null;
372:
373: if (ofInterest != null) {
374: list = new java.util.ArrayList();
375: list.add(ofInterest);
376: }
377:
378: return listenForEvents(moment, type, list, 0);
379: }
380:
381: public java.util.ArrayList listenForEvents(long moment, Class type,
382: java.util.ArrayList listOfInterest) {
383: return listenForEvents(moment, type, listOfInterest, 0);
384: }
385:
386: public java.util.ArrayList listenForEvents(long moment, Class type,
387: long timeout) {
388: return listenForEvents(moment, type, new java.util.ArrayList(),
389: timeout);
390: }
391:
392: public java.util.ArrayList listenForEvents(long moment, Class type,
393: Collectable ofInterest, long timeout) {
394: java.util.ArrayList list = null;
395:
396: if (ofInterest != null) {
397: list = new java.util.ArrayList();
398: list.add(ofInterest);
399: }
400:
401: return listenForEvents(moment, type, list, timeout);
402: }
403:
404: public java.util.ArrayList listenForEvents(long moment, Class type,
405: java.util.ArrayList listOfInterest, long timeout) {
406: if (isExplicitLock() == true) {
407: throw new org.myoodb.exception.PermissionException(
408: "Invocation cannot be part of a transaction");
409: }
410:
411: if (moment == 0) {
412: moment = getLocalTime();
413: }
414:
415: if ((timeout != 0) && (timeout < 1000)) {
416: timeout = 1000;
417: }
418:
419: java.util.ArrayList list = new java.util.ArrayList();
420: DatabaseClient client = ((TransactionThread) Thread
421: .currentThread()).getClient();
422:
423: do {
424: // check first since moment might be back in time (requires looping twice in timeout case)
425: list = getEvents(moment, 0, type, listOfInterest);
426:
427: if ((timeout >= 0) && (list.size() == 0)) {
428: try {
429: long timeRemaining = 0;
430:
431: if (timeout == 0) {
432: yield(-1);
433: } else {
434: long startTime = getLocalTime();
435:
436: yield(timeout);
437:
438: long endTime = getLocalTime();
439:
440: timeRemaining = timeout - (endTime - startTime);
441: timeRemaining -= 500; // see Thread.sleep below
442:
443: if (timeRemaining <= 0) // greater than zero means keep going
444: {
445: timeRemaining = -1;
446: }
447: }
448:
449: timeout = timeRemaining;
450:
451: Thread.sleep(500); // encourage q-ing & reduce thrashing
452: } catch (Exception e) {
453: throw new org.myoodb.exception.InternalException(
454: "Internal Error", e);
455: }
456: } else {
457: break;
458: }
459: } while (client.isConnected() == true);
460:
461: return list;
462: }
463: }
|