1 | /* |
2 | |
3 | Derby - Class org.apache.derby.impl.io.BaseStorageFactory |
4 | |
5 | Copyright 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.io; |
22 | |
23 | import org.apache.derby.iapi.store.raw.data.DataFactory; |
24 | |
25 | import org.apache.derby.io.StorageFactory; |
26 | import org.apache.derby.io.StorageFile; |
27 | |
28 | import java.io.File; |
29 | import java.io.IOException; |
30 | |
31 | /** |
32 | * This class provides a base for implementations of the StorageFactory interface. It is used by the |
33 | * database engine to access persistent data and transaction logs under the directory (default) subsubprotocol. |
34 | */ |
35 | |
36 | abstract class BaseStorageFactory implements StorageFactory |
37 | { |
38 | |
39 | String home; |
40 | protected StorageFile tempDir; |
41 | protected String tempDirPath; |
42 | protected String dataDirectory; |
43 | protected String separatedDataDirectory; // dataDirectory + separator |
44 | protected String uniqueName; |
45 | protected String canonicalName; |
46 | private static final String TEMP_DIR_PREFIX = "derbytmp_"; |
47 | |
48 | /** |
49 | * Most of the initialization is done in the init method. |
50 | */ |
51 | BaseStorageFactory() |
52 | {} |
53 | |
54 | /** |
55 | * Classes implementing the StorageFactory interface must have a null |
56 | * constructor. This method is called when the database is booted up to |
57 | * initialize the class. It should perform all actions necessary to start the |
58 | * basic storage, such as creating a temporary file directory. |
59 | * |
60 | * The init method will be called once, before any other method is called, and will not |
61 | * be called again. |
62 | * |
63 | * @param home The name of the directory containing the database. It comes from the system.home system property. |
64 | * It may be null. A storage factory may decide to ignore this parameter. (For instance the classpath |
65 | * storage factory ignores it. |
66 | * @param databaseName The name of the database (directory). All relative pathnames are relative to this directory. |
67 | * If null then the storage factory will only be used to deal with the directory containing |
68 | * the databases. |
69 | * @param tempDirName The name of the temporary file directory set in properties. If null then a default |
70 | * directory should be used. Each database should get a separate temporary file |
71 | * directory within this one to avoid collisions. |
72 | * @param uniqueName A unique name that can be used to create the temporary file directory for this database. |
73 | * |
74 | * @exception IOException on an error (unexpected). |
75 | */ |
76 | public void init( String home, String databaseName, String tempDirName, String uniqueName) |
77 | throws IOException |
78 | { |
79 | if( databaseName != null) |
80 | { |
81 | dataDirectory = databaseName; |
82 | separatedDataDirectory = databaseName + getSeparator(); |
83 | } |
84 | this.home = home; |
85 | this.uniqueName = uniqueName; |
86 | tempDirPath = tempDirName; |
87 | doInit(); |
88 | } // end of init |
89 | |
90 | abstract void doInit() throws IOException; |
91 | |
92 | public void shutdown() |
93 | { |
94 | } |
95 | |
96 | |
97 | /** |
98 | * Get the canonical name of the database. This is a name that uniquely identifies it. It is system dependent. |
99 | * |
100 | * The normal, disk based implementation uses method java.io.File.getCanonicalPath on the directory holding the |
101 | * database to construct the canonical name. |
102 | * |
103 | * @return the canonical name |
104 | * |
105 | * @exception IOException if an IO error occurred during the construction of the name. |
106 | */ |
107 | public String getCanonicalName() throws IOException |
108 | { |
109 | return canonicalName; |
110 | } |
111 | |
112 | /** |
113 | * Construct a StorageFile from a path name. |
114 | * |
115 | * @param path The path name of the file |
116 | * |
117 | * @return A corresponding StorageFile object |
118 | */ |
119 | public StorageFile newStorageFile( String path) |
120 | { |
121 | if( path != null && tempDirPath != null && path.startsWith( tempDirPath)) |
122 | return new DirFile( path); |
123 | return newPersistentFile( path); |
124 | } |
125 | |
126 | /** |
127 | * Construct a StorageFile from a directory and file name. |
128 | * |
129 | * @param directoryName The directory part of the path name. |
130 | * @param fileName The name of the file within the directory. |
131 | * |
132 | * @return A corresponding StorageFile object |
133 | */ |
134 | public StorageFile newStorageFile( String directoryName, String fileName) |
135 | { |
136 | if( directoryName == null) |
137 | return newStorageFile( fileName); |
138 | else if( tempDirPath != null && directoryName.startsWith( tempDirPath)) |
139 | return new DirFile(directoryName, fileName); |
140 | else |
141 | return newPersistentFile( directoryName, fileName); |
142 | } |
143 | |
144 | /** |
145 | * Construct a StorageFile from a directory and file name. |
146 | * |
147 | * @param directoryName The directory part of the path name. |
148 | * @param fileName The name of the file within the directory. |
149 | * |
150 | * @return A corresponding StorageFile object |
151 | */ |
152 | public StorageFile newStorageFile( StorageFile directoryName, String fileName) |
153 | { |
154 | if( directoryName == null) |
155 | return newStorageFile( fileName); |
156 | if( fileName == null) |
157 | return directoryName; |
158 | else if (tempDirPath != null && directoryName.getPath().startsWith(tempDirPath)) |
159 | return new DirFile( (DirFile) directoryName, fileName); |
160 | return newPersistentFile( directoryName, fileName); |
161 | } |
162 | |
163 | /** |
164 | * Construct a persistent StorageFile from a path name. |
165 | * |
166 | * @param path The path name of the file. Guaranteed not to be in the temporary file directory. If null |
167 | * then the database directory should be returned. |
168 | * |
169 | * @return A corresponding StorageFile object |
170 | */ |
171 | abstract StorageFile newPersistentFile( String path); |
172 | |
173 | /** |
174 | * Construct a persistent StorageFile from a directory and path name. |
175 | * |
176 | * @param directoryName The path name of the directory. Guaranteed not to be in the temporary file directory. |
177 | * Guaranteed not to be null |
178 | * @param fileName The name of the file within the directory. Guaranteed not to be null. |
179 | * |
180 | * @return A corresponding StorageFile object |
181 | */ |
182 | abstract StorageFile newPersistentFile( String directoryName, String fileName); |
183 | |
184 | /** |
185 | * Construct a persistent StorageFile from a directory and path name. |
186 | * |
187 | * @param directoryName The path name of the directory. Guaranteed not to be to be null. Guaranteed to be |
188 | * created by a call to one of the newPersistentFile methods. |
189 | * @param fileName The name of the file within the directory. Guaranteed not to be null. |
190 | * |
191 | * @return A corresponding StorageFile object |
192 | */ |
193 | abstract StorageFile newPersistentFile( StorageFile directoryName, String fileName); |
194 | |
195 | /** |
196 | * Get the pathname separator character used by the StorageFile implementation. |
197 | * |
198 | * @return the pathname separator character. (Normally '/' or '\'). |
199 | */ |
200 | public char getSeparator() |
201 | { |
202 | // Temp files are always java.io.File's and use its separator. |
203 | return File.separatorChar; |
204 | } |
205 | |
206 | /** |
207 | * Get the abstract name of the directory that holds temporary files. |
208 | * |
209 | * @return a directory name |
210 | */ |
211 | public StorageFile getTempDir() |
212 | { |
213 | return tempDir; |
214 | } |
215 | |
216 | /** |
217 | * This method is used to determine whether the storage is fast (RAM based) or slow (disk based). |
218 | * It may be used by the database engine to determine the default size of the page cache. |
219 | * |
220 | * @return <b>true</b> if the storage is fast, <b>false</b> if it is slow. |
221 | */ |
222 | public boolean isFast() |
223 | { |
224 | return false; |
225 | } |
226 | |
227 | public boolean isReadOnlyDatabase() |
228 | { |
229 | return true; |
230 | } |
231 | |
232 | /** |
233 | * Determine whether the storage supports random access. If random access is not supported then |
234 | * it will only be accessed using InputStreams and OutputStreams (if the database is writable). |
235 | * |
236 | * @return <b>true</b> if the storage supports random access, <b>false</b> if it is writable. |
237 | */ |
238 | public boolean supportsRandomAccess() |
239 | { |
240 | return false; |
241 | } |
242 | |
243 | void createTempDir() throws java.io.IOException |
244 | { |
245 | if( uniqueName == null) |
246 | return; |
247 | |
248 | if( tempDirPath != null) |
249 | tempDir = new DirFile( tempDirPath, TEMP_DIR_PREFIX.concat(uniqueName)); |
250 | else if( isReadOnlyDatabase()) |
251 | tempDir = new DirFile( readOnlyTempRoot(), TEMP_DIR_PREFIX.concat(uniqueName)); |
252 | else |
253 | tempDir = new DirFile( canonicalName, DataFactory.TEMP_SEGMENT_NAME); |
254 | |
255 | // blow away any temporary directory |
256 | tempDir.deleteAll(); |
257 | |
258 | tempDir.mkdirs(); |
259 | tempDirPath = tempDir.getPath(); |
260 | } // end of createTempDir |
261 | |
262 | private String readOnlyTempRoot() throws java.io.IOException |
263 | { |
264 | // return the system temp dir by creating a temp file |
265 | // and finding its parent. |
266 | File temp = File.createTempFile("derby", "tmp"); |
267 | String parent = temp.getParent(); |
268 | temp.delete(); |
269 | |
270 | return parent; |
271 | } |
272 | |
273 | public int getStorageFactoryVersion() |
274 | { |
275 | return StorageFactory.VERSION_NUMBER; |
276 | } |
277 | } |