You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by th...@apache.org on 2012/01/25 09:24:05 UTC
svn commit: r1235674 - in
/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/fs:
FileCache.java FilePathCache.java FileUtils.java
Author: thomasm
Date: Wed Jan 25 08:24:04 2012
New Revision: 1235674
URL: http://svn.apache.org/viewvc?rev=1235674&view=rev
Log:
Write-behind cache
Modified:
jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/fs/FileCache.java
jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/fs/FilePathCache.java
jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/fs/FileUtils.java
Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/fs/FileCache.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/fs/FileCache.java?rev=1235674&r1=1235673&r2=1235674&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/fs/FileCache.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/fs/FileCache.java Wed Jan 25 08:24:04 2012
@@ -16,11 +16,13 @@
*/
package org.apache.jackrabbit.mk.fs;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
import org.apache.jackrabbit.mk.util.SimpleLRUCache;
/**
@@ -28,12 +30,22 @@ import org.apache.jackrabbit.mk.util.Sim
*/
public class FileCache extends FileBase {
+ private static final boolean APPEND_BUFFER = !Boolean.getBoolean("mk.disableAppendBuffer");
+ private static final int APPEND_BUFFER_SIZE_INIT = 8 * 1024;
+ private static final int APPEND_BUFFER_SIZE = 8 * 1024;
+
private static final int BLOCK_SIZE = 4 * 1024;
+ private final String name;
private final Map<Long, ByteBuffer> readCache = SimpleLRUCache.newInstance(16);
private final FileChannel base;
private long pos, size;
- FileCache(FileChannel base) throws IOException {
+ private AtomicReference<ByteArrayOutputStream> appendBuffer;
+ private int appendOperations;
+ private Thread appendFlushThread;
+
+ FileCache(String name, FileChannel base) throws IOException {
+ this.name = name;
this.base = base;
this.size = base.size();
}
@@ -47,7 +59,28 @@ public class FileCache extends FileBase
return this;
}
+ boolean flush() throws IOException {
+ if (appendBuffer == null) {
+ return false;
+ }
+ synchronized (this) {
+ ByteArrayOutputStream newBuff = new ByteArrayOutputStream(APPEND_BUFFER_SIZE_INIT);
+ ByteArrayOutputStream buff = appendBuffer.getAndSet(newBuff);
+ if (buff.size() > 0) {
+ try {
+ base.position(size - buff.size());
+ base.write(ByteBuffer.wrap(buff.toByteArray()));
+ } catch (IOException e) {
+ close();
+ throw e;
+ }
+ }
+ }
+ return true;
+ }
+
public int read(ByteBuffer dst) throws IOException {
+ flush();
long readPos = (pos / BLOCK_SIZE) * BLOCK_SIZE;
int off = (int) (pos - readPos);
int len = BLOCK_SIZE - off;
@@ -77,6 +110,7 @@ public class FileCache extends FileBase
}
public FileChannel truncate(long newSize) throws IOException {
+ flush();
readCache.clear();
base.truncate(newSize);
pos = Math.min(pos, newSize);
@@ -85,8 +119,51 @@ public class FileCache extends FileBase
}
public int write(ByteBuffer src) throws IOException {
+ if (readCache.size() > 0) {
+ readCache.clear();
+ }
+ // append operations are buffered, but
+ // only if there was at least one successful write operation
+ // (to detect trying to write to a read-only file and such early on)
+ // (in addition to that, the first few append operations are not buffered
+ // to avoid starting a thread unnecessarily)
+ if (APPEND_BUFFER && pos == size && ++appendOperations >= 4) {
+ int len = src.remaining();
+ if (len > APPEND_BUFFER_SIZE) {
+ flush();
+ } else {
+ if (appendBuffer == null) {
+ ByteArrayOutputStream buff = new ByteArrayOutputStream(APPEND_BUFFER_SIZE_INIT);
+ appendBuffer = new AtomicReference<ByteArrayOutputStream>(buff);
+ appendFlushThread = new Thread("Flush " + name) {
+ public void run() {
+ try {
+ do {
+ Thread.sleep(500);
+ if (flush()) {
+ continue;
+ }
+ } while (!Thread.interrupted());
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ };
+ appendFlushThread.setDaemon(true);
+ appendFlushThread.start();
+ }
+ ByteArrayOutputStream buff = appendBuffer.get();
+ if (buff.size() > APPEND_BUFFER_SIZE) {
+ flush();
+ buff = appendBuffer.get();
+ }
+ buff.write(src.array(), src.position(), len);
+ pos += len;
+ size += len;
+ return len;
+ }
+ }
base.position(pos);
- readCache.clear();
int len = base.write(src);
pos += len;
size = Math.max(size, pos);
@@ -94,14 +171,25 @@ public class FileCache extends FileBase
}
protected void implCloseChannel() throws IOException {
+ if (appendBuffer != null) {
+ appendFlushThread.interrupt();
+ try {
+ appendFlushThread.join();
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ flush();
+ }
base.close();
}
public void force(boolean metaData) throws IOException {
+ flush();
base.force(metaData);
}
public FileLock tryLock(long position, long size, boolean shared) throws IOException {
+ flush();
return base.tryLock(position, size, shared);
}
Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/fs/FilePathCache.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/fs/FilePathCache.java?rev=1235674&r1=1235673&r2=1235674&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/fs/FilePathCache.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/fs/FilePathCache.java Wed Jan 25 08:24:04 2012
@@ -25,7 +25,7 @@ import java.nio.channels.FileChannel;
public class FilePathCache extends FilePathWrapper {
public FileChannel open(String mode) throws IOException {
- return new FileCache(getBase().open(mode));
+ return new FileCache(getBase().name, getBase().open(mode));
}
public String getScheme() {
Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/fs/FileUtils.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/fs/FileUtils.java?rev=1235674&r1=1235673&r2=1235674&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/fs/FileUtils.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/fs/FileUtils.java Wed Jan 25 08:24:04 2012
@@ -367,5 +367,4 @@ public class FileUtils {
} while (src.remaining() > 0);
}
-
}