001: /*
002: This source file is part of Smyle, a database library.
003: For up-to-date information, see http://www.drjava.de/smyle
004: Copyright (C) 2001 Stefan Reich (doc@drjava.de)
005:
006: This library is free software; you can redistribute it and/or
007: modify it under the terms of the GNU Lesser General Public
008: License as published by the Free Software Foundation; either
009: version 2.1 of the License, or (at your option) any later version.
010:
011: This library is distributed in the hope that it will be useful,
012: but WITHOUT ANY WARRANTY; without even the implied warranty of
013: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: Lesser General Public License for more details.
015:
016: You should have received a copy of the GNU Lesser General Public
017: License along with this library; if not, write to the Free Software
018: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019:
020: For full license text, see doc/license/lgpl.txt in this distribution
021: */
022:
023: package drjava.smyle.core;
024:
025: import java.io.*;
026: import java.util.*;
027: import junit.framework.*;
028: import org.artsProject.mcop.*;
029: import drjava.smyle.*;
030:
031: public class MemoryDisk implements Disk {
032: long idCounter = 0, master = 0, bytesWritten = 0;
033: int clusterSize = 16;
034: HashMap<Long, FileImpl> files = new HashMap<Long, FileImpl>();
035: public boolean sabotageMasterWrite = false, readOnly = false;
036:
037: class FileImpl implements Disk.NewFile {
038: long id = ++idCounter;
039: byte[] data = null;
040: boolean isMaster, sabotage;
041:
042: OutputStream out = new ByteArrayOutputStream() {
043: public void close() throws IOException {
044: super .close();
045: if (sabotage) {
046: data = new byte[0];
047: throw new SmyleIOException("sabotage");
048: } else {
049: data = toByteArray();
050: bytesWritten += (data.length + clusterSize - 1)
051: / clusterSize * clusterSize;
052: if (isMaster)
053: master = id;
054: }
055: }
056: };
057:
058: public long getId() {
059: return id;
060: }
061:
062: public OutputStream getOutputStream() {
063: if (out == null)
064: Assert.fail("getOutputStream may only be called once");
065: OutputStream result = out;
066: out = null;
067: return result;
068: }
069: }
070:
071: FileImpl _createFile() {
072: FileImpl file = new FileImpl();
073: files.put(new Long(file.id), file);
074: return file;
075: }
076:
077: public Disk.NewFile createFile() {
078: assertWritable();
079: return _createFile();
080: }
081:
082: public long saveMaster(Buffer data) {
083: assertWritable();
084: FileImpl file = _createFile();
085: file.isMaster = true;
086: file.sabotage = sabotageMasterWrite;
087: DiskUtil.bufferToFile(file, data);
088: return file.getId();
089: }
090:
091: public long getMasterFile() {
092: return master;
093: }
094:
095: public int getFileLength(long id) {
096: try {
097: FileImpl file = getFile(id);
098: return file.data.length;
099: } catch (IOException e) {
100: throw new SmyleIOException(e);
101: }
102: }
103:
104: public InputStream readFile(long id) throws IOException {
105: FileImpl file = getFile(id);
106: return new ByteArrayInputStream(file.data);
107: }
108:
109: FileImpl getFile(long id) throws IOException {
110: FileImpl file = files.get(new Long(id));
111: if (file == null)
112: throw new FileNotFoundException(String.valueOf(id));
113: if (file.data == null)
114: throw new SmyleIOException(
115: "File was not closed or is still being written");
116: return file;
117: }
118:
119: public void deleteEverything() {
120: assertWritable();
121: files.clear();
122: idCounter = master = 0;
123: }
124:
125: public int numberOfFiles() {
126: return files.size();
127: }
128:
129: public void deleteEverythingBut(Set<FileRef> whiteList) {
130: assertWritable();
131: for (Iterator<Long> i = files.keySet().iterator(); i.hasNext();) {
132: long nr = i.next().longValue();
133: if (!whiteList.contains(new FileRef(nr))) {
134: //System.out.println("MemoryDisk: removing file "+nr+" (whitelist length: "+whiteList.size()+")");
135: /*for (Iterator<FileRef> it = whiteList.iterator(); it.hasNext(); )
136: System.out.println("Whitelist entry: "+it.next().id);*/
137: i.remove();
138: }
139: }
140: }
141:
142: public long totalBytes() {
143: long total = 0;
144: for (Iterator<FileImpl> i = files.values().iterator(); i
145: .hasNext();) {
146: byte[] data = i.next().data;
147: if (data != null)
148: total += data.length;
149: }
150: return total;
151: }
152:
153: /** this is just for generating test cases, so 32-bit ids are ok */
154: public void marshal(Buffer buffer) {
155: buffer.writeLong(files.size());
156: for (Iterator<FileImpl> i = files.values().iterator(); i
157: .hasNext();) {
158: FileImpl f = i.next();
159: buffer.writeLong((int) f.id);
160: buffer.writeLong(f.data.length);
161: buffer.writeBytes(f.data);
162: }
163: buffer.writeLong((int) master);
164: buffer.writeLong((int) idCounter);
165: }
166:
167: public MemoryDisk(Buffer buffer) {
168: int n = buffer.readLong();
169: for (int i = 0; i < n; i++) {
170: FileImpl f = new FileImpl();
171: f.id = buffer.readLong();
172: int len = buffer.readLong();
173: f.data = buffer.readBytes(len);
174: files.put(new Long(f.id), f);
175: }
176: master = buffer.readLong();
177: idCounter = buffer.readLong();
178: }
179:
180: public MemoryDisk() {
181: }
182:
183: public synchronized long totalBytesWritten() {
184: return bytesWritten;
185: }
186:
187: public synchronized void setClusterSize(int bytes) {
188: clusterSize = bytes;
189: }
190:
191: public synchronized void release() {
192: }
193:
194: private void assertWritable() {
195: if (readOnly)
196: throw new RuntimeException("Read only disk");
197: }
198: }
|