001: /*
002: * Copyright 2004-2008 H2 Group. Licensed under the H2 License, Version 1.0
003: * (http://h2database.com/html/license.html).
004: * Initial Developer: H2 Group
005: */
006: package org.h2.store.fs;
007:
008: import java.io.IOException;
009: import java.io.InputStream;
010: import java.io.OutputStream;
011: import java.sql.SQLException;
012: import java.util.HashMap;
013:
014: import org.h2.message.Message;
015: import org.h2.util.IOUtils;
016:
017: /**
018: * This file system keeps files fully in memory.
019: * There is an option to compress file blocks to safe memory.
020: */
021: public class FileSystemMemory extends FileSystem {
022:
023: private static final FileSystemMemory INSTANCE = new FileSystemMemory();
024: private static final HashMap MEMORY_FILES = new HashMap();
025:
026: public static FileSystemMemory getInstance() {
027: return INSTANCE;
028: }
029:
030: private FileSystemMemory() {
031: }
032:
033: public long length(String fileName) {
034: return getMemoryFile(fileName).length();
035: }
036:
037: public void rename(String oldName, String newName)
038: throws SQLException {
039: FileObjectMemory f = getMemoryFile(oldName);
040: f.setName(newName);
041: synchronized (MEMORY_FILES) {
042: MEMORY_FILES.remove(oldName);
043: MEMORY_FILES.put(newName, f);
044: }
045: }
046:
047: public boolean createNewFile(String fileName) throws SQLException {
048: if (exists(fileName)) {
049: return false;
050: }
051: // creates the file (not thread safe)
052: getMemoryFile(fileName);
053: return true;
054: }
055:
056: public boolean exists(String fileName) {
057: synchronized (MEMORY_FILES) {
058: return MEMORY_FILES.get(fileName) != null;
059: }
060: }
061:
062: public void delete(String fileName) throws SQLException {
063: synchronized (MEMORY_FILES) {
064: MEMORY_FILES.remove(fileName);
065: }
066: }
067:
068: public boolean tryDelete(String fileName) {
069: synchronized (MEMORY_FILES) {
070: MEMORY_FILES.remove(fileName);
071: }
072: return true;
073: }
074:
075: public String createTempFile(String name, String suffix,
076: boolean deleteOnExit, boolean inTempDir) throws IOException {
077: name += ".";
078: for (int i = 0;; i++) {
079: String n = name + i + suffix;
080: if (!exists(n)) {
081: // creates the file (not thread safe)
082: getMemoryFile(n);
083: return n;
084: }
085: }
086: }
087:
088: public String[] listFiles(String path) throws SQLException {
089: synchronized (MEMORY_FILES) {
090: String[] list = new String[MEMORY_FILES.size()];
091: FileObjectMemory[] l = new FileObjectMemory[MEMORY_FILES
092: .size()];
093: MEMORY_FILES.values().toArray(l);
094: for (int i = 0; i < list.length; i++) {
095: list[i] = l[i].getName();
096: }
097: return list;
098: }
099: }
100:
101: public void deleteRecursive(String fileName) throws SQLException {
102: throw Message.getUnsupportedException();
103: }
104:
105: public boolean isReadOnly(String fileName) {
106: return false;
107: }
108:
109: public String normalize(String fileName) throws SQLException {
110: return fileName;
111: }
112:
113: public String getParent(String fileName) {
114: int idx = Math.max(fileName.indexOf(':'), fileName
115: .lastIndexOf('/'));
116: return fileName.substring(0, idx);
117: }
118:
119: public boolean isDirectory(String fileName) {
120: // TODO in memory file system currently doesn't support directories
121: return false;
122: }
123:
124: public boolean isAbsolute(String fileName) {
125: // TODO relative files are not supported
126: return true;
127: }
128:
129: public String getAbsolutePath(String fileName) {
130: // TODO relative files are not supported
131: return fileName;
132: }
133:
134: public long getLastModified(String fileName) {
135: return getMemoryFile(fileName).getLastModified();
136: }
137:
138: public boolean canWrite(String fileName) {
139: return true;
140: }
141:
142: public void copy(String original, String copy) throws SQLException {
143: try {
144: OutputStream out = openFileOutputStream(copy, false);
145: InputStream in = openFileInputStream(original);
146: IOUtils.copyAndClose(in, out);
147: } catch (IOException e) {
148: throw Message.convertIOException(e, "Can not copy "
149: + original + " to " + copy);
150: }
151: }
152:
153: public void createDirs(String fileName) throws SQLException {
154: // TODO directories are not really supported
155: }
156:
157: public String getFileName(String name) throws SQLException {
158: // TODO directories are not supported
159: return name;
160: }
161:
162: public boolean fileStartsWith(String fileName, String prefix) {
163: return fileName.startsWith(prefix);
164: }
165:
166: public OutputStream openFileOutputStream(String fileName,
167: boolean append) throws SQLException {
168: try {
169: return new FileObjectOutputStream(getMemoryFile(fileName),
170: append);
171: } catch (IOException e) {
172: throw Message.convertIOException(e, fileName);
173: }
174: }
175:
176: public InputStream openFileInputStream(String fileName)
177: throws IOException {
178: return new FileObjectInputStream(getMemoryFile(fileName));
179: }
180:
181: public FileObject openFileObject(String fileName, String mode)
182: throws IOException {
183: return getMemoryFile(fileName);
184: }
185:
186: private FileObjectMemory getMemoryFile(String fileName) {
187: synchronized (MEMORY_FILES) {
188: FileObjectMemory m = (FileObjectMemory) MEMORY_FILES
189: .get(fileName);
190: if (m == null) {
191: boolean compress = fileName
192: .startsWith(FileSystem.MEMORY_PREFIX_LZF);
193: m = new FileObjectMemory(fileName, compress);
194: MEMORY_FILES.put(fileName, m);
195: }
196: // TODO the memory file only supports one pointer
197: m.seek(0);
198: return m;
199: }
200: }
201:
202: }
|