File D:\maven-qcr-plugin-testsunitaires\qcr4java\h2-1.3.170-sources\target\site\qc\lecode\mvstore\cache\FilePathCache.java.html

1 /*
2 * Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
3 * Version 1.0, and under the Eclipse Public License, Version 1.0
4 * (http://h2database.com/html/license.html).
5 * Initial Developer: H2 Group
6 */
7 package org.h2.mvstore.cache;
8
9 import java.io.IOException;
10 import java.nio.ByteBuffer;
11 import java.nio.channels.FileChannel;
12 import java.nio.channels.FileLock;
13 import org.h2.store.fs.FileBase;
14 import org.h2.store.fs.FilePathWrapper;
15
16 /**
17 * A file with a read cache.
18 */
19 public class FilePathCache extends FilePathWrapper {
20
21 public static FileChannel wrap(FileChannel f) {
22 return new FileCache(f);
23 }
24
25 public FileChannel open(String mode) throws IOException {
26 return new FileCache(getBase().open(mode));
27 }
28
29 public String getScheme() {
30 return "cache";
31 }
32
33 /**
34 * A file with a read cache.
35 */
36 public static class FileCache extends FileBase {
37
38 private static final int CACHE_BLOCK_SIZE = 4 * 1024;
39 private final FileChannel base;
40 // 1 MB (256 * 4 * 1024)
41 private final CacheLongKeyLIRS<ByteBuffer> cache =
42 CacheLongKeyLIRS.newInstance(256);
43
44 FileCache(FileChannel base) {
45 this.base = base;
46 }
47
48 protected void implCloseChannel() throws IOException {
49 base.close();
50 }
51
52 public FileChannel position(long newPosition) throws IOException {
53 base.position(newPosition);
54 return this;
55 }
56
57 public long position() throws IOException {
58 return base.position();
59 }
60
61 public int read(ByteBuffer dst) throws IOException {
62 return base.read(dst);
63 }
64
65 public int read(ByteBuffer dst, long position) throws IOException {
66 long cachePos = getCachePos(position);
67 int off = (int) (position - cachePos);
68 int len = CACHE_BLOCK_SIZE - off;
69 ByteBuffer buff = cache.get(cachePos);
70 if (buff == null) {
71 buff = ByteBuffer.allocate(CACHE_BLOCK_SIZE);
72 int read = base.read(buff, cachePos);
73 if (read == CACHE_BLOCK_SIZE) {
74 cache.put(cachePos, buff);
75 } else {
76 if (read < 0) {
77 return -1;
78 }
79 len = Math.min(len, read);
80 }
81 }
82 len = Math.min(len, dst.remaining());
83 System.arraycopy(buff.array(), off, dst.array(), dst.position(), len);
84 dst.position(dst.position() + len);
85 return len;
86 }
87
88 private static long getCachePos(long pos) {
89 return (pos / CACHE_BLOCK_SIZE) * CACHE_BLOCK_SIZE;
90 }
91
92 public long size() throws IOException {
93 return base.size();
94 }
95
96 public FileChannel truncate(long newSize) throws IOException {
97 cache.clear();
98 base.truncate(newSize);
99 return this;
100 }
101
102 public int write(ByteBuffer src, long position) throws IOException {
103 if (cache.size() > 0) {
104 int len = src.remaining();
105 long p = getCachePos(position);
106 while (len > 0) {
107 cache.remove(p);
108 p += CACHE_BLOCK_SIZE;
109 len -= CACHE_BLOCK_SIZE;
110 }
111 }
112 return base.write(src, position);
113 }
114
115 public int write(ByteBuffer src) throws IOException {
116 throw new UnsupportedOperationException();
117 // return base.write(src);
118 }
119
120 public void force(boolean metaData) throws IOException {
121 base.force(metaData);
122 }
123
124 public FileLock tryLock(long position, long size, boolean shared) throws IOException {
125 return base.tryLock(position, size, shared);
126 }
127
128 public String toString() {
129 return "cache:" + base.toString();
130 }
131
132 }
133
134 }
135