EMMA Coverage Report (generated Sun Mar 01 22:06:14 CET 2015)
[all classes][org.h2.mvstore]

COVERAGE SUMMARY FOR SOURCE FILE [FileStore.java]

nameclass, %method, %block, %line, %
FileStore.java100% (1/1)92%  (22/24)84%  (321/384)90%  (79/88)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class FileStore100% (1/1)92%  (22/24)84%  (321/384)90%  (79/88)
getReadBytes (): long 0%   (0/1)0%   (0/3)0%   (0/1)
getWriteBytes (): long 0%   (0/1)0%   (0/3)0%   (0/1)
sync (): void 100% (1/1)27%  (6/22)60%  (3/5)
truncate (long): void 100% (1/1)48%  (19/40)71%  (5/7)
open (String, boolean, char []): void 100% (1/1)87%  (135/155)91%  (30/33)
FileStore (): void 100% (1/1)100% (10/10)100% (2/2)
allocate (int): long 100% (1/1)100% (5/5)100% (1/1)
clear (): void 100% (1/1)100% (4/4)100% (2/2)
close (): void 100% (1/1)100% (42/42)100% (10/10)
free (long, int): void 100% (1/1)100% (6/6)100% (2/2)
getDefaultRetentionTime (): int 100% (1/1)100% (2/2)100% (1/1)
getEncryptedFile (): FileChannel 100% (1/1)100% (3/3)100% (1/1)
getFile (): FileChannel 100% (1/1)100% (3/3)100% (1/1)
getFileName (): String 100% (1/1)100% (3/3)100% (1/1)
getFillRate (): int 100% (1/1)100% (4/4)100% (1/1)
getFirstFree (): long 100% (1/1)100% (4/4)100% (1/1)
getReadCount (): long 100% (1/1)100% (3/3)100% (1/1)
getWriteCount (): long 100% (1/1)100% (3/3)100% (1/1)
isReadOnly (): boolean 100% (1/1)100% (3/3)100% (1/1)
markUsed (long, int): void 100% (1/1)100% (6/6)100% (2/2)
readFully (long, int): ByteBuffer 100% (1/1)100% (23/23)100% (5/5)
size (): long 100% (1/1)100% (3/3)100% (1/1)
toString (): String 100% (1/1)100% (3/3)100% (1/1)
writeFully (long, ByteBuffer): void 100% (1/1)100% (31/31)100% (6/6)

1/*
2 * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
3 * and the EPL 1.0 (http://h2database.com/html/license.html).
4 * Initial Developer: H2 Group
5 */
6package org.h2.mvstore;
7 
8import java.io.IOException;
9import java.nio.ByteBuffer;
10import java.nio.channels.FileChannel;
11import java.nio.channels.FileLock;
12import java.nio.channels.OverlappingFileLockException;
13 
14import org.h2.mvstore.cache.FilePathCache;
15import org.h2.store.fs.FilePath;
16import org.h2.store.fs.FilePathDisk;
17import org.h2.store.fs.FilePathEncrypt;
18import org.h2.store.fs.FilePathNio;
19 
20/**
21 * The default storage mechanism of the MVStore. This implementation persists
22 * data to a file. The file store is responsible to persist data and for free
23 * space management.
24 */
25public class FileStore {
26 
27    /**
28     * The number of read operations.
29     */
30    protected long readCount;
31 
32    /**
33     * The number of read bytes.
34     */
35    protected long readBytes;
36 
37    /**
38     * The number of write operations.
39     */
40    protected long writeCount;
41 
42    /**
43     * The number of written bytes.
44     */
45    protected long writeBytes;
46 
47    /**
48     * The free spaces between the chunks. The first block to use is block 2
49     * (the first two blocks are the store header).
50     */
51    protected final FreeSpaceBitSet freeSpace =
52            new FreeSpaceBitSet(2, MVStore.BLOCK_SIZE);
53 
54    /**
55     * The file name.
56     */
57    protected String fileName;
58 
59    /**
60     * Whether this store is read-only.
61     */
62    protected boolean readOnly;
63 
64    /**
65     * The file size (cached).
66     */
67    protected long fileSize;
68 
69    /**
70     * The file.
71     */
72    protected FileChannel file;
73 
74    /**
75     * The encrypted file (if encryption is used).
76     */
77    protected FileChannel encryptedFile;
78 
79    /**
80     * The file lock.
81     */
82    protected FileLock fileLock;
83 
84    @Override
85    public String toString() {
86        return fileName;
87    }
88 
89    /**
90     * Read from the file.
91     *
92     * @param pos the write position
93     * @param len the number of bytes to read
94     * @return the byte buffer
95     */
96    public ByteBuffer readFully(long pos, int len) {
97        ByteBuffer dst = ByteBuffer.allocate(len);
98        DataUtils.readFully(file, pos, dst);
99        readCount++;
100        readBytes += len;
101        return dst;
102    }
103 
104    /**
105     * Write to the file.
106     *
107     * @param pos the write position
108     * @param src the source buffer
109     */
110    public void writeFully(long pos, ByteBuffer src) {
111        int len = src.remaining();
112        fileSize = Math.max(fileSize, pos + len);
113        DataUtils.writeFully(file, pos, src);
114        writeCount++;
115        writeBytes += len;
116    }
117 
118    /**
119     * Try to open the file.
120     *
121     * @param fileName the file name
122     * @param readOnly whether the file should only be opened in read-only mode,
123     *            even if the file is writable
124     * @param encryptionKey the encryption key, or null if encryption is not
125     *            used
126     */
127    public void open(String fileName, boolean readOnly, char[] encryptionKey) {
128        if (file != null) {
129            return;
130        }
131        if (fileName != null) {
132            if (FilePath.get(fileName) instanceof FilePathDisk) {
133                // NIO is used, unless a different file system is specified the
134                // following line is to ensure the NIO file system is compiled
135                FilePathNio.class.getName();
136                fileName = "nio:" + fileName;
137            }
138        }
139        this.fileName = fileName;
140        FilePath f = FilePath.get(fileName);
141        FilePath parent = f.getParent();
142        if (parent != null && !parent.exists()) {
143            throw DataUtils.newIllegalArgumentException(
144                    "Directory does not exist: {0}", parent);
145        }
146        if (f.exists() && !f.canWrite()) {
147            readOnly = true;
148        }
149        this.readOnly = readOnly;
150        try {
151            file = f.open(readOnly ? "r" : "rw");
152            if (encryptionKey != null) {
153                byte[] key = FilePathEncrypt.getPasswordBytes(encryptionKey);
154                encryptedFile = file;
155                file = new FilePathEncrypt.FileEncrypt(fileName, key, file);
156            }
157            file = FilePathCache.wrap(file);
158            try {
159                if (readOnly) {
160                    fileLock = file.tryLock(0, Long.MAX_VALUE, true);
161                } else {
162                    fileLock = file.tryLock();
163                }
164            } catch (OverlappingFileLockException e) {
165                throw DataUtils.newIllegalStateException(
166                        DataUtils.ERROR_FILE_LOCKED,
167                        "The file is locked: {0}", fileName, e);
168            }
169            if (fileLock == null) {
170                throw DataUtils.newIllegalStateException(
171                        DataUtils.ERROR_FILE_LOCKED,
172                        "The file is locked: {0}", fileName);
173            }
174            fileSize = file.size();
175        } catch (IOException e) {
176            throw DataUtils.newIllegalStateException(
177                    DataUtils.ERROR_READING_FAILED,
178                    "Could not open file {0}", fileName, e);
179        }
180    }
181 
182    /**
183     * Close this store.
184     */
185    public void close() {
186        try {
187            if (fileLock != null) {
188                fileLock.release();
189                fileLock = null;
190            }
191            file.close();
192            freeSpace.clear();
193        } catch (Exception e) {
194            throw DataUtils.newIllegalStateException(
195                    DataUtils.ERROR_WRITING_FAILED,
196                    "Closing failed for file {0}", fileName, e);
197        } finally {
198            file = null;
199        }
200    }
201 
202    /**
203     * Flush all changes.
204     */
205    public void sync() {
206        try {
207            file.force(true);
208        } catch (IOException e) {
209            throw DataUtils.newIllegalStateException(
210                    DataUtils.ERROR_WRITING_FAILED,
211                    "Could not sync file {0}", fileName, e);
212        }
213    }
214 
215    /**
216     * Get the file size.
217     *
218     * @return the file size
219     */
220    public long size() {
221        return fileSize;
222    }
223 
224    /**
225     * Truncate the file.
226     *
227     * @param size the new file size
228     */
229    public void truncate(long size) {
230        try {
231            writeCount++;
232            file.truncate(size);
233            fileSize = Math.min(fileSize, size);
234        } catch (IOException e) {
235            throw DataUtils.newIllegalStateException(
236                    DataUtils.ERROR_WRITING_FAILED,
237                    "Could not truncate file {0} to size {1}",
238                    fileName, size, e);
239        }
240    }
241 
242    /**
243     * Get the file instance in use.
244     * <p>
245     * The application may read from the file (for example for online backup),
246     * but not write to it or truncate it.
247     *
248     * @return the file
249     */
250    public FileChannel getFile() {
251        return file;
252    }
253 
254    /**
255     * Get the encrypted file instance, if encryption is used.
256     * <p>
257     * The application may read from the file (for example for online backup),
258     * but not write to it or truncate it.
259     *
260     * @return the encrypted file, or null if encryption is not used
261     */
262    public FileChannel getEncryptedFile() {
263        return encryptedFile;
264    }
265 
266    /**
267     * Get the number of write operations since this store was opened.
268     * For file based stores, this is the number of file write operations.
269     *
270     * @return the number of write operations
271     */
272    public long getWriteCount() {
273        return writeCount;
274    }
275 
276    /**
277     * Get the number of written bytes since this store was opened.
278     *
279     * @return the number of write operations
280     */
281    public long getWriteBytes() {
282        return writeBytes;
283    }
284 
285    /**
286     * Get the number of read operations since this store was opened.
287     * For file based stores, this is the number of file read operations.
288     *
289     * @return the number of read operations
290     */
291    public long getReadCount() {
292        return readCount;
293    }
294 
295    /**
296     * Get the number of read bytes since this store was opened.
297     *
298     * @return the number of write operations
299     */
300    public long getReadBytes() {
301        return readBytes;
302    }
303 
304    public boolean isReadOnly() {
305        return readOnly;
306    }
307 
308    /**
309     * Get the default retention time for this store in milliseconds.
310     *
311     * @return the retention time
312     */
313    public int getDefaultRetentionTime() {
314        return 45000;
315    }
316 
317    /**
318     * Mark the space as in use.
319     *
320     * @param pos the position in bytes
321     * @param length the number of bytes
322     */
323    public void markUsed(long pos, int length) {
324        freeSpace.markUsed(pos, length);
325    }
326 
327    /**
328     * Allocate a number of blocks and mark them as used.
329     *
330     * @param length the number of bytes to allocate
331     * @return the start position in bytes
332     */
333    public long allocate(int length) {
334        return freeSpace.allocate(length);
335    }
336 
337    /**
338     * Mark the space as free.
339     *
340     * @param pos the position in bytes
341     * @param length the number of bytes
342     */
343    public void free(long pos, int length) {
344        freeSpace.free(pos, length);
345    }
346 
347    public int getFillRate() {
348        return freeSpace.getFillRate();
349    }
350 
351    long getFirstFree() {
352        return freeSpace.getFirstFree();
353    }
354 
355    /**
356     * Mark the file as empty.
357     */
358    public void clear() {
359        freeSpace.clear();
360    }
361 
362    /**
363     * Get the file name.
364     *
365     * @return the file name
366     */
367    public String getFileName() {
368        return fileName;
369    }
370 
371}

[all classes][org.h2.mvstore]
EMMA 2.0.5312 (C) Vladimir Roubtsov