Source code: org/apache/derby/impl/store/raw/data/RFResource.java
1 /*
2
3 Derby - Class org.apache.derby.impl.store.raw.data.RFResource
4
5 Copyright 1998, 2004 The Apache Software Foundation or its licensors, as applicable.
6
7 Licensed under the Apache License, Version 2.0 (the "License");
8 you may not use this file except in compliance with the License.
9 You may obtain a copy of the License at
10
11 http://www.apache.org/licenses/LICENSE-2.0
12
13 Unless required by applicable law or agreed to in writing, software
14 distributed under the License is distributed on an "AS IS" BASIS,
15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 See the License for the specific language governing permissions and
17 limitations under the License.
18
19 */
20
21 package org.apache.derby.impl.store.raw.data;
22
23 import org.apache.derby.iapi.reference.SQLState;
24
25 import org.apache.derby.iapi.services.context.ContextService;
26 import org.apache.derby.iapi.services.context.ContextManager;
27 import org.apache.derby.iapi.services.daemon.Serviceable;
28 import org.apache.derby.iapi.services.sanity.SanityManager;
29 import org.apache.derby.iapi.error.StandardException;
30 import org.apache.derby.iapi.store.access.FileResource;
31 import org.apache.derby.iapi.store.raw.Transaction;
32 import org.apache.derby.iapi.store.access.AccessFactoryGlobals;
33 import org.apache.derby.iapi.store.access.DatabaseInstant;
34
35 import org.apache.derby.io.StorageFactory;
36 import org.apache.derby.io.WritableStorageFactory;
37 import org.apache.derby.io.StorageFile;
38 import org.apache.derby.io.StorageRandomAccessFile;
39
40 import java.io.InputStream;
41 import java.io.OutputStream;
42 import java.io.FileNotFoundException;
43 import java.io.IOException;
44
45 public class RFResource implements FileResource {
46
47 protected final BaseDataFileFactory factory;
48
49 public RFResource(BaseDataFileFactory dataFactory) {
50 this.factory = dataFactory;
51 }
52
53 /**
54 @see FileResource#add
55 @exception StandardException Oops
56 */
57 public long add(String name, InputStream source)
58 throws StandardException
59 {
60 OutputStream os = null;
61
62 if (factory.isReadOnly())
63 {
64 throw StandardException.newException(SQLState.FILE_READ_ONLY);
65 }
66
67 long generationId = factory.getNextId();
68
69 try
70 {
71 StorageFile file = getAsFile(name, generationId);
72 if (file.exists())
73 {
74 throw StandardException.newException(
75 SQLState.FILE_EXISTS, file);
76 }
77
78 StorageFile directory = file.getParentDir();
79 if (!directory.exists())
80 {
81 if (!directory.mkdirs())
82 {
83 throw StandardException.newException(
84 SQLState.FILE_CANNOT_CREATE_SEGMENT, directory);
85 }
86 }
87
88 os = file.getOutputStream();
89 byte[] data = new byte[4096];
90 int len;
91
92 factory.writeInProgress();
93 try
94 {
95 while ((len = source.read(data)) != -1) {
96 os.write(data, 0, len);
97 }
98 factory.writableStorageFactory.sync( os, false);
99 }
100 finally
101 {
102 factory.writeFinished();
103 }
104 }
105
106 catch (IOException ioe)
107 {
108 throw StandardException.newException(
109 SQLState.FILE_UNEXPECTED_EXCEPTION, ioe);
110 }
111
112 finally
113 {
114 try {
115 if (os != null) {
116 os.close();
117 }
118 } catch (IOException ioe2) {/*RESOLVE: Why ignore this?*/}
119
120 try {
121 if (source != null)source.close();
122 } catch (IOException ioe2) {/* RESOLVE: Why ignore this?*/}
123 }
124
125 return generationId;
126 }
127
128 /**
129 @see FileResource#remove
130 @exception StandardException Oops
131 */
132 public void remove(String name, long currentGenerationId, boolean purgeOnCommit)
133 throws StandardException
134 {
135 if (factory.isReadOnly())
136 throw StandardException.newException(SQLState.FILE_READ_ONLY);
137
138
139 ContextManager cm = ContextService.getFactory().getCurrentContextManager();
140
141 Transaction tran =
142 factory.getRawStoreFactory().findUserTransaction(
143 cm, AccessFactoryGlobals.USER_TRANS_NAME);
144
145 tran.logAndDo(privRemoveFileOperation(name, currentGenerationId, purgeOnCommit));
146
147 if (purgeOnCommit) {
148
149 Serviceable s = privRemoveFile(getAsFile(name, currentGenerationId));
150
151 tran.addPostCommitWork(s);
152 }
153 }
154
155 /**
156 @see FileResource#replace
157 @exception StandardException Oops
158 */
159 public long replace(String name, long currentGenerationId, InputStream source, boolean purgeOnCommit)
160 throws StandardException
161 {
162 if (factory.isReadOnly())
163 throw StandardException.newException(SQLState.FILE_READ_ONLY);
164
165 remove(name, currentGenerationId, purgeOnCommit);
166
167 long generationId = add(name, source);
168
169 return generationId;
170 }
171
172
173 /**
174 @see FileResource#getAsFile
175 */
176 public StorageFile getAsFile(String name, long generationId)
177 {
178 String versionedFileName = factory.getVersionedName(name, generationId);
179
180 return factory.storageFactory.newStorageFile( versionedFileName);
181 }
182
183 /**
184 @see FileResource#getAsFile
185 */
186 public StorageFile getAsFile(String name)
187 {
188 return factory.storageFactory.newStorageFile( name);
189 }
190
191 /**
192 @see FileResource#getAsStream
193 @exception IOException trouble accessing file.
194 */
195 public InputStream getAsStream(String name, long generationId)
196 throws IOException
197 {
198 return getAsFile(name, generationId).getInputStream();
199 }
200
201 /**
202 @see FileResource#getAsStream
203 @exception IOException trouble accessing file.
204 */
205 public InputStream getAsStream(String name)
206 throws IOException
207 {
208 return getAsFile(name).getInputStream();
209 }
210
211 /**
212 @see FileResource#purgeOldGenerations
213 */
214 public void purgeOldGenerations(DatabaseInstant purgeTo)
215 {
216
217 // search from the start of the log until now
218 // remove any generation files that have been
219 // logged for removal and their transaction committed.
220
221 if (SanityManager.DEBUG)
222 SanityManager.THROWASSERT("purgeOldGenerations is not implemented");
223 }
224
225 public char getSeparatorChar()
226 {
227 return factory.storageFactory.getSeparator();
228 }
229
230 protected Serviceable privRemoveFile(StorageFile file)
231 {
232 return new RemoveFile(file);
233 }
234
235 protected RemoveFileOperation privRemoveFileOperation(
236 String name, long generationId, boolean removeAtOnce)
237 {
238 return new RemoveFileOperation(name,generationId,removeAtOnce);
239 }
240 } // end of class RFResource
241
242
243 class RemoveFile implements Serviceable
244 {
245 private final StorageFile fileToGo;
246
247 RemoveFile(StorageFile fileToGo)
248 {
249 this.fileToGo = fileToGo;
250 }
251
252 public int performWork(ContextManager context)
253 throws StandardException
254 {
255 // SECURITY PERMISSION - MP1, OP5
256 if (fileToGo.exists())
257 {
258 if (!fileToGo.delete())
259 {
260 throw StandardException.newException(
261 SQLState.FILE_CANNOT_REMOVE_FILE, fileToGo);
262 }
263 }
264 return Serviceable.DONE;
265 }
266
267 public boolean serviceASAP()
268 {
269 return false;
270 }
271
272
273 // @return true, if this work needs to be done on a user thread immediately
274 public boolean serviceImmediately()
275 {
276 return false;
277 }
278 }