KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > transaction > file > FileSequence


1 /*
2  * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//transaction/src/java/org/apache/commons/transaction/file/FileSequence.java,v 1.1 2004/11/18 23:27:19 ozeigermann Exp $
3 <<<<<<< .mine
4  * $Revision: 1.1 $
5  * $Date: 2005-02-26 14:16:14 +0100 (Sa, 26 Feb 2005) $
6 =======
7  * $Revision$
8  * $Date: 2005-02-26 14:16:14 +0100 (Sa, 26 Feb 2005) $
9 >>>>>>> .r168169
10  *
11  * ====================================================================
12  *
13  * Copyright 1999-2002 The Apache Software Foundation
14  *
15  * Licensed under the Apache License, Version 2.0 (the "License");
16  * you may not use this file except in compliance with the License.
17  * You may obtain a copy of the License at
18  *
19  * http://www.apache.org/licenses/LICENSE-2.0
20  *
21  * Unless required by applicable law or agreed to in writing, software
22  * distributed under the License is distributed on an "AS IS" BASIS,
23  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24  * See the License for the specific language governing permissions and
25  * limitations under the License.
26  *
27  */

28
29 package org.apache.commons.transaction.file;
30
31 import java.io.BufferedReader JavaDoc;
32 import java.io.BufferedWriter JavaDoc;
33 import java.io.File JavaDoc;
34 import java.io.FileInputStream JavaDoc;
35 import java.io.FileNotFoundException JavaDoc;
36 import java.io.FileOutputStream JavaDoc;
37 import java.io.IOException JavaDoc;
38 import java.io.InputStream JavaDoc;
39 import java.io.InputStreamReader JavaDoc;
40 import java.io.OutputStream JavaDoc;
41 import java.io.OutputStreamWriter JavaDoc;
42 import java.io.UnsupportedEncodingException JavaDoc;
43
44 import org.apache.commons.transaction.util.FileHelper;
45 import org.apache.commons.transaction.util.LoggerFacade;
46
47 /**
48  * Fail-Safe sequence store implementation using the file system. Works by versioning
49  * values of sequences and throwing away all versions, but the current and the previous one.
50  *
51  * @version $Revision$
52  */

53 public class FileSequence {
54
55     protected final String JavaDoc storeDir;
56     protected final LoggerFacade logger;
57
58     /**
59      * Creates a new resouce manager operation on the specified directories.
60      *
61      * @param storeDir directory where sequence information is stored
62      * @param logger logger used for warnings only
63      */

64     public FileSequence(String JavaDoc storeDir, LoggerFacade logger) throws ResourceManagerException {
65         this.storeDir = storeDir;
66         this.logger = logger;
67         File JavaDoc file = new File JavaDoc(storeDir);
68         file.mkdirs();
69         if (!file.exists()) {
70             throw new ResourceManagerException("Can not create working directory " + storeDir);
71         }
72     }
73
74     /**
75      * Checks if the sequence already exists.
76      *
77      * @param sequenceName the name of the sequence you want to check
78      * @return <code>true</code> if the sequence already exists, <code>false</code> otherwise
79      */

80     public synchronized boolean exists(String JavaDoc sequenceName) {
81         String JavaDoc pathI = getPathI(sequenceName);
82         String JavaDoc pathII = getPathII(sequenceName);
83
84         return (FileHelper.fileExists(pathI) || FileHelper.fileExists(pathII));
85     }
86
87     /**
88      * Creates a sequence if it does not already exist.
89      *
90      * @param sequenceName the name of the sequence you want to create
91      * @return <code>true</code> if the sequence has been created, <code>false</code> if it already existed
92      * @throws ResourceManagerException if anything goes wrong while accessing the sequence
93      */

94     public synchronized boolean create(String JavaDoc sequenceName, long initialValue) throws ResourceManagerException {
95         if (exists(sequenceName))
96             return false;
97         write(sequenceName, initialValue);
98         return true;
99     }
100
101     /**
102      * Deletes a sequence if it exists.
103      *
104      * @param sequenceName the name of the sequence you want to delete
105      * @return <code>true</code> if the sequence has been deleted, <code>false</code> if not
106      */

107     public synchronized boolean delete(String JavaDoc sequenceName) {
108         if (!exists(sequenceName))
109             return false;
110         String JavaDoc pathI = getPathI(sequenceName);
111         String JavaDoc pathII = getPathII(sequenceName);
112
113         // XXX be careful no to use shortcut eval with || might not delete second file
114
boolean res1 = FileHelper.deleteFile(pathI);
115         boolean res2 = FileHelper.deleteFile(pathII);
116
117         return (res1 || res2);
118     }
119
120     /**
121      * Gets the next value of the sequence.
122      *
123      * @param sequenceName the name of the sequence you want the next value for
124      * @param increment the increment for the sequence, i.e. how much to add to the sequence with this call
125      * @return the next value of the sequence <em>not yet incremented</em>, i.e. the increment is recorded
126      * internally, but not returned with the next call to this method
127      * @throws ResourceManagerException if anything goes wrong while accessing the sequence
128      */

129     public synchronized long nextSequenceValueBottom(String JavaDoc sequenceName, long increment)
130         throws ResourceManagerException {
131         if (!exists(sequenceName)) {
132             throw new ResourceManagerException("Sequence " + sequenceName + " does not exist");
133         }
134         if (increment <= 0) {
135             throw new IllegalArgumentException JavaDoc("Increment must be greater than 0, was " + increment);
136         }
137         long value = read(sequenceName);
138         long newValue = value + increment;
139         write(sequenceName, newValue);
140         return value;
141     }
142
143     protected long read(String JavaDoc sequenceName) throws ResourceManagerException {
144         String JavaDoc pathI = getPathI(sequenceName);
145         String JavaDoc pathII = getPathII(sequenceName);
146
147         long returnValue = -1;
148
149         long valueI = -1;
150         if (FileHelper.fileExists(pathI)) {
151             try {
152                 valueI = readFromPath(pathI);
153             } catch (NumberFormatException JavaDoc e) {
154                 throw new ResourceManagerException("Fatal internal error: Backup sequence value corrupted");
155             } catch (FileNotFoundException JavaDoc e) {
156                 throw new ResourceManagerException("Fatal internal error: Backup sequence vanished");
157             } catch (IOException JavaDoc e) {
158                 throw new ResourceManagerException("Fatal internal error: Backup sequence value corrupted");
159             }
160         }
161
162         long valueII = -1;
163         if (FileHelper.fileExists(pathII)) {
164             try {
165                 valueII = readFromPath(pathII);
166                 if (valueII > valueI) {
167                     returnValue = valueII;
168                 } else {
169                     // if it is smaller than previous this *must* be an error as we constantly increment
170
logger.logWarning("Latest sequence value smaller than previous, reverting to previous");
171                     FileHelper.deleteFile(pathII);
172                     returnValue = valueI;
173                 }
174             } catch (NumberFormatException JavaDoc e) {
175                 logger.logWarning("Latest sequence value corrupted, reverting to previous");
176                 FileHelper.deleteFile(pathII);
177                 returnValue = valueI;
178             } catch (FileNotFoundException JavaDoc e) {
179                 logger.logWarning("Can not find latest sequence value, reverting to previous");
180                 FileHelper.deleteFile(pathII);
181                 returnValue = valueI;
182             } catch (IOException JavaDoc e) {
183                 logger.logWarning("Can not read latest sequence value, reverting to previous");
184                 FileHelper.deleteFile(pathII);
185                 returnValue = valueI;
186             }
187         } else {
188             logger.logWarning("Can not read latest sequence value, reverting to previous");
189             returnValue = valueI;
190         }
191
192         if (returnValue != -1) {
193             return returnValue;
194         } else {
195             throw new ResourceManagerException("Fatal internal error: Could not compute valid sequence value");
196         }
197     }
198
199     protected void write(String JavaDoc sequenceName, long value) throws ResourceManagerException {
200         String JavaDoc pathII = getPathII(sequenceName);
201
202         File JavaDoc f2 = new File JavaDoc(pathII);
203         // by contract when this method is called an f2 exists it must be valid
204
if (f2.exists()) {
205             // move previous value to backup position
206
String JavaDoc pathI = getPathI(sequenceName);
207             File JavaDoc f1 = new File JavaDoc(pathI);
208             f1.delete();
209             if (!f2.renameTo(f1)) {
210                 throw new ResourceManagerException("Fatal internal error: Can not create backup value at" + pathI);
211             }
212         }
213         try {
214             if (!f2.createNewFile()) {
215                 throw new ResourceManagerException("Fatal internal error: Can not create new value at" + pathII);
216             }
217         } catch (IOException JavaDoc e) {
218             throw new ResourceManagerException("Fatal internal error: Can not create new value at" + pathII, e);
219         }
220         writeToPath(pathII, value);
221     }
222
223     protected String JavaDoc getPathI(String JavaDoc sequenceName) {
224         return storeDir + "/" + sequenceName + "_1.seq";
225     }
226
227     protected String JavaDoc getPathII(String JavaDoc sequenceName) {
228         return storeDir + "/" + sequenceName + "_2.seq";
229     }
230
231     protected long readFromPath(String JavaDoc path)
232         throws ResourceManagerException, NumberFormatException JavaDoc, FileNotFoundException JavaDoc, IOException JavaDoc {
233         File JavaDoc file = new File JavaDoc(path);
234         BufferedReader JavaDoc reader = null;
235         try {
236             InputStream JavaDoc is = new FileInputStream JavaDoc(file);
237
238             // we do not care for encoding as we only have numbers
239
reader = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(is, "UTF-8"));
240             String JavaDoc valueString = reader.readLine();
241             long value = Long.parseLong(valueString);
242             return value;
243         } catch (UnsupportedEncodingException JavaDoc e) {
244             throw new ResourceManagerException("Fatal internal error, encoding UTF-8 unknown");
245         } finally {
246             if (reader != null) {
247                 try {
248                     reader.close();
249                 } catch (IOException JavaDoc e) {
250                 }
251
252             }
253         }
254     }
255
256     protected void writeToPath(String JavaDoc path, long value) throws ResourceManagerException {
257         File JavaDoc file = new File JavaDoc(path);
258         BufferedWriter JavaDoc writer = null;
259         try {
260             OutputStream JavaDoc os = new FileOutputStream JavaDoc(file);
261             writer = new BufferedWriter JavaDoc(new OutputStreamWriter JavaDoc(os, "UTF-8"));
262             String JavaDoc valueString = Long.toString(value);
263             writer.write(valueString);
264             writer.write('\n');
265         } catch (FileNotFoundException JavaDoc e) {
266             throw new ResourceManagerException("Fatal internal error: Can not find sequence at " + path);
267         } catch (IOException JavaDoc e) {
268             throw new ResourceManagerException("Fatal internal error: Can not write to sequence at " + path);
269         } finally {
270             if (writer != null) {
271                 try {
272                     writer.close();
273                 } catch (IOException JavaDoc e) {
274                 }
275
276             }
277         }
278     }
279 }
280
Popular Tags