1 /***
2 *
3 * Copyright 2004 Hiram Chirino
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 **/
18 package org.activeio.journal.howl;
19
20 import java.io.IOException;
21 import java.io.InterruptedIOException;
22
23 import org.activeio.Packet;
24 import org.activeio.journal.InvalidRecordLocationException;
25 import org.activeio.journal.Journal;
26 import org.activeio.journal.JournalEventListener;
27 import org.activeio.journal.RecordLocation;
28 import org.activeio.packet.ByteArrayPacket;
29 import org.objectweb.howl.log.Configuration;
30 import org.objectweb.howl.log.InvalidFileSetException;
31 import org.objectweb.howl.log.InvalidLogBufferException;
32 import org.objectweb.howl.log.InvalidLogKeyException;
33 import org.objectweb.howl.log.LogConfigurationException;
34 import org.objectweb.howl.log.LogEventListener;
35 import org.objectweb.howl.log.LogRecord;
36 import org.objectweb.howl.log.Logger;
37
38 /***
39 * An implementation of the Journal interface using a HOWL logger. This is is a thin
40 * wrapper around a HOWL logger.
41 *
42 * This implementation can be used to write records but not to retreive them
43 * yet. Once the HOWL logger implements the methods needed to retreive
44 * previously stored records, this class can be completed.
45 *
46 * @version $Revision: 1.2 $
47 */
48 public class HowlJournal implements Journal {
49
50 private final Logger logger;
51
52 private RecordLocation lastMark;
53
54 public HowlJournal(Configuration configuration)
55 throws InvalidFileSetException, LogConfigurationException,
56 InvalidLogBufferException, ClassNotFoundException, IOException,
57 InterruptedException {
58 this.logger = new Logger(configuration);
59 this.logger.open();
60 lastMark = new LongRecordLocation(logger.getActiveMark());
61 }
62
63 /***
64 * @see org.activeio.journal.Journal#write(byte[], boolean)
65 */
66 public RecordLocation write(Packet packet, boolean sync) throws IOException {
67 try {
68 return new LongRecordLocation(logger.put(packet.sliceAsBytes(), sync));
69 } catch (InterruptedException e) {
70 throw (InterruptedIOException) new InterruptedIOException()
71 .initCause(e);
72 } catch (IOException e) {
73 throw e;
74 } catch (Exception e) {
75 throw (IOException) new IOException("Journal write failed: " + e)
76 .initCause(e);
77 }
78 }
79
80 /***
81 * @see org.activeio.journal.Journal#setMark(org.codehaus.activemq.journal.RecordLocation, boolean)
82 */
83 public void setMark(RecordLocation recordLocator, boolean force)
84 throws InvalidRecordLocationException, IOException {
85 try {
86 long location = toLong(recordLocator);
87 logger.mark(location, force);
88 lastMark = recordLocator;
89
90 } catch (InterruptedException e) {
91 throw (InterruptedIOException) new InterruptedIOException()
92 .initCause(e);
93 } catch (IOException e) {
94 throw e;
95 } catch (InvalidLogKeyException e) {
96 throw new InvalidRecordLocationException(e.getMessage(), e);
97 } catch (Exception e) {
98 throw (IOException) new IOException("Journal write failed: " + e)
99 .initCause(e);
100 }
101 }
102
103 /***
104 * @param recordLocator
105 * @return
106 * @throws InvalidRecordLocationException
107 */
108 private long toLong(RecordLocation recordLocator) throws InvalidRecordLocationException {
109 if (recordLocator == null
110 || recordLocator.getClass() != LongRecordLocation.class)
111 throw new InvalidRecordLocationException();
112
113 long location = ((LongRecordLocation) recordLocator)
114 .getLongLocation();
115 return location;
116 }
117
118 /***
119 * @see org.activeio.journal.Journal#getMark()
120 */
121 public RecordLocation getMark() {
122 return lastMark;
123 }
124
125 /***
126 * @see org.activeio.journal.Journal#close()
127 */
128 public void close() throws IOException {
129 try {
130 logger.close();
131 } catch (IOException e) {
132 throw e;
133 } catch (InterruptedException e) {
134 throw (InterruptedIOException) new InterruptedIOException()
135 .initCause(e);
136 } catch (Exception e) {
137 throw (IOException) new IOException("Journal close failed: " + e)
138 .initCause(e);
139 }
140 }
141
142 /***
143 * @see org.activeio.journal.Journal#setJournalEventListener(org.codehaus.activemq.journal.JournalEventListener)
144 */
145 public void setJournalEventListener(final JournalEventListener eventListener) {
146 logger.setLogEventListener(new LogEventListener() {
147 public void logOverflowNotification(long key) {
148 eventListener.overflowNotification(new LongRecordLocation(key));
149 }
150 });
151 }
152
153 /***
154 * @see org.activeio.journal.Journal#getNextRecordLocation(org.codehaus.activemq.journal.RecordLocation)
155 */
156 public RecordLocation getNextRecordLocation(RecordLocation lastLocation)
157 throws InvalidRecordLocationException {
158
159 if( lastLocation ==null ) {
160 if( this.lastMark !=null ) {
161 lastLocation = lastMark;
162 } else {
163 return null;
164 }
165 }
166
167 try {
168 while(true) {
169 LogRecord record = logger.get(null, toLong(lastLocation));
170
171 LogRecord next = logger.getNext(record);
172 if( next==null || next.length == 0 )
173 return null;
174 lastLocation = new LongRecordLocation(next.key);
175 if( !next.isCTRL() )
176 return lastLocation;
177 }
178 } catch (Exception e) {
179 throw (InvalidRecordLocationException)new InvalidRecordLocationException().initCause(e);
180 }
181
182 }
183
184 /***
185 * @see org.activeio.journal.Journal#read(org.codehaus.activemq.journal.RecordLocation)
186 */
187 public Packet read(RecordLocation location)
188 throws InvalidRecordLocationException, IOException {
189
190 try {
191 LogRecord record = logger.get(null, toLong(location));
192 return new ByteArrayPacket(record.data);
193 } catch (InvalidLogKeyException e) {
194 throw new InvalidRecordLocationException(e.getMessage(), e);
195 } catch (Exception e) {
196 throw (IOException) new IOException("Journal write failed: " + e)
197 .initCause(e);
198 }
199
200 }
201
202 }