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 2011/09/09 18:49:50 UTC
svn commit: r1167288 - in /jackrabbit/sandbox/microkernel/src:
main/java/org/apache/jackrabbit/mk/blobs/
main/java/org/apache/jackrabbit/mk/mem/
test/java/org/apache/jackrabbit/mk/concurrent/
Author: thomasm
Date: Fri Sep 9 16:49:50 2011
New Revision: 1167288
URL: http://svn.apache.org/viewvc?rev=1167288&view=rev
Log:
Fix concurrency problems, use the new cache
Added:
jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/concurrent/ConcurrentBlobTest.java
jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/concurrent/ConcurrentTest.java
Modified:
jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/blobs/AbstractBlobStore.java
jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/blobs/DbBlobStore.java
jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/blobs/FileBlobStore.java
jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/blobs/MemoryBlobStore.java
jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/MemoryKernelImpl.java
jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeImpl.java
jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeList.java
jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeListLarge.java
jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeListSmall.java
jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeMap.java
jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/Revision.java
Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/blobs/AbstractBlobStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/blobs/AbstractBlobStore.java?rev=1167288&r1=1167287&r2=1167288&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/blobs/AbstractBlobStore.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/blobs/AbstractBlobStore.java Fri Sep 9 16:49:50 2011
@@ -18,7 +18,7 @@ package org.apache.jackrabbit.mk.blobs;
import org.apache.jackrabbit.mk.util.ExceptionFactory;
import org.apache.jackrabbit.mk.util.IOUtils;
-import org.apache.jackrabbit.mk.util.SimpleLRUCache;
+import org.apache.jackrabbit.mk.util.Cache;
import org.apache.jackrabbit.mk.util.StringUtils;
import java.io.ByteArrayInputStream;
@@ -53,7 +53,7 @@ import java.security.MessageDigest;
* long), size of data store id (variable size long), hash code length (variable
* size int), hash code.
*/
-public abstract class AbstractBlobStore implements BlobStore {
+public abstract class AbstractBlobStore implements BlobStore, Cache.Backend<String, AbstractBlobStore.Data> {
protected static final int TYPE_DATA = 0;
protected static final int TYPE_HASH = 1;
@@ -73,8 +73,7 @@ public abstract class AbstractBlobStore
*/
private int blockSize = 2 * 1024 * 1024;
- private SimpleLRUCache<String, byte[]> cache = SimpleLRUCache
- .newInstance(5);
+ private Cache<String, Data> cache = Cache.newInstance(this, 8 * 1024 * 1024);
public void setBlockSizeMin(int x) {
this.blockSizeMin = x;
@@ -202,12 +201,15 @@ public abstract class AbstractBlobStore
private byte[] readBlock(byte[] digest) throws Exception {
String id = StringUtils.convertBytesToHex(digest);
- byte[] block = cache.get(id);
- if (block == null) {
- block = readBlockFromBackend(digest);
- cache.put(id, block);
+ return cache.get(id).data;
+ }
+
+ public Data load(String id) {
+ try {
+ return new Data(readBlockFromBackend(StringUtils.convertHexToBytes(id)));
+ } catch (Exception e) {
+ throw ExceptionFactory.convert(e);
}
- return block;
}
protected abstract byte[] readBlockFromBackend(byte[] blockId) throws Exception;
@@ -247,4 +249,17 @@ public abstract class AbstractBlobStore
public abstract void clear();
+ public static class Data implements Cache.Value {
+
+ final byte[] data;
+
+ Data(byte[] data) {
+ this.data = data;
+ }
+
+ public int getMemory() {
+ return data.length;
+ }
+ }
+
}
Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/blobs/DbBlobStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/blobs/DbBlobStore.java?rev=1167288&r1=1167287&r2=1167288&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/blobs/DbBlobStore.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/blobs/DbBlobStore.java Fri Sep 9 16:49:50 2011
@@ -45,7 +45,7 @@ public class DbBlobStore extends Abstrac
}
@Override
- protected void storeBlock(byte[] blockId, int level, byte[] data) throws SQLException {
+ protected synchronized void storeBlock(byte[] blockId, int level, byte[] data) throws SQLException {
Connection conn = cp.getConnection();
try {
String id = StringUtils.convertBytesToHex(blockId);
Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/blobs/FileBlobStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/blobs/FileBlobStore.java?rev=1167288&r1=1167287&r2=1167288&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/blobs/FileBlobStore.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/blobs/FileBlobStore.java Fri Sep 9 16:49:50 2011
@@ -37,7 +37,7 @@ public class FileBlobStore extends Abstr
}
@Override
- protected void storeBlock(byte[] blockId, int level, byte[] data) throws IOException {
+ protected synchronized void storeBlock(byte[] blockId, int level, byte[] data) throws IOException {
File f = getFile(blockId);
if (f.exists()) {
return;
Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/blobs/MemoryBlobStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/blobs/MemoryBlobStore.java?rev=1167288&r1=1167287&r2=1167288&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/blobs/MemoryBlobStore.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/blobs/MemoryBlobStore.java Fri Sep 9 16:49:50 2011
@@ -28,7 +28,7 @@ public class MemoryBlobStore extends Abs
private HashMap<String, byte[]> map = new HashMap<String, byte[]>();
@Override
- protected byte[] readBlockFromBackend(byte[] blockId) {
+ protected synchronized byte[] readBlockFromBackend(byte[] blockId) {
return map.get(getId(blockId));
}
@@ -37,12 +37,12 @@ public class MemoryBlobStore extends Abs
}
@Override
- protected void storeBlock(byte[] blockId, int level, byte[] data) {
+ protected synchronized void storeBlock(byte[] blockId, int level, byte[] data) {
map.put(getId(blockId), data);
}
@Override
- public void clear() {
+ public synchronized void clear() {
map.clear();
}
Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/MemoryKernelImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/MemoryKernelImpl.java?rev=1167288&r1=1167287&r2=1167288&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/MemoryKernelImpl.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/MemoryKernelImpl.java Fri Sep 9 16:49:50 2011
@@ -22,11 +22,11 @@ import org.apache.jackrabbit.mk.blobs.Fi
import org.apache.jackrabbit.mk.blobs.MemoryBlobStore;
import org.apache.jackrabbit.mk.json.JsopBuilder;
import org.apache.jackrabbit.mk.json.JsopTokenizer;
+import org.apache.jackrabbit.mk.util.Cache;
import org.apache.jackrabbit.mk.util.CommitGate;
import org.apache.jackrabbit.mk.util.ExceptionFactory;
import org.apache.jackrabbit.mk.util.NonDescendingClock;
import org.apache.jackrabbit.mk.util.PathUtils;
-import org.apache.jackrabbit.mk.util.SimpleLRUCache;
import java.io.InputStream;
import java.util.ArrayList;
@@ -65,8 +65,8 @@ public class MemoryKernelImpl implements
private final AbstractBlobStore ds;
private final NonDescendingClock clock = new NonDescendingClock(System.currentTimeMillis());
private final CommitGate gate = new CommitGate();
- private final SimpleLRUCache<Long, Revision> revisionCache = SimpleLRUCache.newInstance(1000);
- private long headRevId;
+ private final Cache<Long, Revision> revisionCache = Cache.newInstance(null, 1024 * 1024);
+ private volatile long headRevId;
private NodeMap nodeMap;
private String lastJournalRevRange, lastJournal;
@@ -100,7 +100,7 @@ public class MemoryKernelImpl implements
return instance;
}
- public void clear() {
+ public synchronized void clear() {
if (DEBUG) {
log("clear");
}
@@ -308,13 +308,13 @@ public class MemoryKernelImpl implements
}
NodeImpl node = getRoot();
ArrayList<Revision> revisions = new ArrayList<Revision>();
- Revision r = Revision.get(revisionCache, node.getNode("head"));
+ Revision r = Revision.get(node.getNode("head"));
if (since < r.getTime()) {
revisions.add(r);
while (node.exists("old")) {
node = node.getNode("old");
for (Iterator<String> it = node.getChildNodeNames(Integer.MAX_VALUE); it.hasNext();) {
- r = Revision.get(revisionCache, node.getNode(it.next()));
+ r = Revision.get(node.getNode(it.next()));
if (r != null) {
revisions.add(r);
}
@@ -356,15 +356,16 @@ public class MemoryKernelImpl implements
long toRev = Revision.parseId(toRevisionId);
NodeImpl node = getRoot();
ArrayList<Revision> revisions = new ArrayList<Revision>();
- Revision r = Revision.get(revisionCache, node.getNode("head"));
+ Revision r = Revision.get(node.getNode("head"));
if (r.getId() >= fromRev) {
revisions.add(r);
}
while (r.getId() > fromRev && node.exists("old")) {
node = node.getNode("old");
for (Iterator<String> it = node.getChildNodeNames(Integer.MAX_VALUE); it.hasNext();) {
- r = Revision.get(revisionCache, node.getNode(it.next()));
+ r = Revision.get(node.getNode(it.next()));
if (r != null && r.getId() >= fromRev && r.getId() <= toRev) {
+ r = revisionCache.replace(r.getId(), r);
revisions.add(r);
}
}
@@ -434,10 +435,13 @@ public class MemoryKernelImpl implements
}
private NodeImpl getRevision(String revisionId) {
- long revId = Revision.parseId(revisionId);
NodeImpl node = getRoot();
- if (revId == headRevId) {
- node = node.getNode("head");
+ NodeImpl head = node.getNode("head");
+ String headRev = head.getProperty("rev");
+ headRev = headRev == null ? null : JsopTokenizer.decodeQuoted(headRev);
+ // we can't rely on headRevId, as it's a volatile field
+ if (revisionId.equals(headRev)) {
+ node = head;
} else {
if (DEBUG) {
log("getRevision " + revisionId);
@@ -492,7 +496,7 @@ public class MemoryKernelImpl implements
return ds.writeBlob(in);
}
- public void dispose() {
+ public synchronized void dispose() {
if (DEBUG) {
log("dispose");
}
Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeImpl.java?rev=1167288&r1=1167287&r2=1167288&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeImpl.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeImpl.java Fri Sep 9 16:49:50 2011
@@ -24,11 +24,12 @@ import org.apache.jackrabbit.mk.json.Jso
import org.apache.jackrabbit.mk.util.ExceptionFactory;
import org.apache.jackrabbit.mk.util.PathUtils;
import org.apache.jackrabbit.mk.util.StringCache;
+import org.apache.jackrabbit.mk.util.Cache;
/**
* An in-memory node, including all child nodes.
*/
-public class NodeImpl {
+public class NodeImpl implements Cache.Value {
private final long revId;
private final NodeMap map;
@@ -36,6 +37,7 @@ public class NodeImpl {
private NodeList childNodes;
private String path;
private long id;
+ private int memory;
public NodeImpl(NodeMap map, long revId) {
this.map = map;
@@ -485,4 +487,19 @@ public class NodeImpl {
void accept(long childId);
}
+ public int getMemory() {
+ if (memory == 0) {
+ String[] pv = propertyValuePairs;
+ if (pv != null) {
+ for (int i = 0; i < pv.length; i++) {
+ memory += pv[i].length() * 2;
+ }
+ }
+ if (childNodes != null) {
+ memory += childNodes.getMemory();
+ }
+ }
+ return memory;
+ }
+
}
Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeList.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeList.java?rev=1167288&r1=1167287&r2=1167288&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeList.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeList.java Fri Sep 9 16:49:50 2011
@@ -45,4 +45,6 @@ interface NodeList {
byte[] getNameFilter(NodeMap map);
+ int getMemory();
+
}
Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeListLarge.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeListLarge.java?rev=1167288&r1=1167287&r2=1167288&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeListLarge.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeListLarge.java Fri Sep 9 16:49:50 2011
@@ -270,4 +270,8 @@ public class NodeListLarge implements No
return data;
}
+ public int getMemory() {
+ return children.size() * 100;
+ }
+
}
Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeListSmall.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeListSmall.java?rev=1167288&r1=1167287&r2=1167288&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeListSmall.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeListSmall.java Fri Sep 9 16:49:50 2011
@@ -182,4 +182,12 @@ public class NodeListSmall implements No
return data;
}
+ public int getMemory() {
+ int memory = 100;
+ for (int i = 0; i < names.length; i++) {
+ memory += names[i].length() * 2 + 8;
+ }
+ return memory;
+ }
+
}
Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeMap.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeMap.java?rev=1167288&r1=1167287&r2=1167288&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeMap.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeMap.java Fri Sep 9 16:49:50 2011
@@ -16,7 +16,10 @@
*/
package org.apache.jackrabbit.mk.mem;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicLong;
import org.apache.jackrabbit.mk.util.ExceptionFactory;
public class NodeMap {
@@ -24,15 +27,15 @@ public class NodeMap {
private static final String MAX_MEMORY_CHILDREN = "maxMemoryChildren";
private static final int DEFAULT_MAX_MEMORY_CHILDREN = Integer.MAX_VALUE;
- private HashMap<Long, NodeImpl> nodes = new HashMap<Long, NodeImpl>();
- private long nextId = 1;
- private long rootId;
+ private Map<Long, NodeImpl> nodes = Collections.synchronizedMap(new HashMap<Long, NodeImpl>());
+ private AtomicLong nextId = new AtomicLong();
+ private AtomicLong rootId = new AtomicLong();
private int maxMemoryChildren = DEFAULT_MAX_MEMORY_CHILDREN;
public long addNode(NodeImpl node) {
long x = node.getId();
if (x == 0) {
- x = nextId++;
+ x = nextId.incrementAndGet();
node.setId(x);
nodes.put(x, node);
}
@@ -45,7 +48,7 @@ public class NodeMap {
public void clear() {
nodes.clear();
- nextId = 1;
+ nextId.set(0);
}
public void setSetting(String key, String value) {
@@ -73,11 +76,13 @@ public class NodeMap {
}
public long commit(NodeImpl root) {
- return rootId = addNode(root);
+ long x = addNode(root);
+ rootId.set(x);
+ return x;
}
public long getRootId() {
- return rootId;
+ return rootId.get();
}
public String formatId(long id) {
Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/Revision.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/Revision.java?rev=1167288&r1=1167287&r2=1167288&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/Revision.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/Revision.java Fri Sep 9 16:49:50 2011
@@ -17,13 +17,13 @@
package org.apache.jackrabbit.mk.mem;
import org.apache.jackrabbit.mk.json.JsopBuilder;
+import org.apache.jackrabbit.mk.util.Cache;
import org.apache.jackrabbit.mk.json.JsopTokenizer;
-import org.apache.jackrabbit.mk.util.SimpleLRUCache;
/**
* A revision, including pointer to the root node of that revision.
*/
-public class Revision implements Comparable<Revision> {
+public class Revision implements Comparable<Revision>, Cache.Value {
private NodeImpl node;
private final long id;
@@ -38,24 +38,20 @@ public class Revision implements Compara
this.msg = msg == null ? "" : msg;
}
- private Revision(NodeImpl node, long id) {
- this.node = node;
+ Revision(long id, long time, NodeImpl node) {
this.id = id;
- time = Long.parseLong(node.getProperty("time"));
+ this.time = time;
+ this.node = node;
}
- static Revision get(SimpleLRUCache<Long, Revision>cache, NodeImpl node) {
+ static Revision get(NodeImpl node) {
String rev = node.getProperty("rev");
if (rev == null) {
return null;
}
long id = parseId(JsopTokenizer.decodeQuoted(rev));
- Revision r = cache.get(id);
- if (r == null) {
- r = new Revision(node, id);
- cache.put(id, r);
- }
- return r;
+ long time = Long.parseLong(node.getProperty("time"));
+ return new Revision(id, time, node);
}
long getId() {
@@ -128,4 +124,8 @@ public class Revision implements Compara
endObject().newline();
}
+ public int getMemory() {
+ return (getDiff().length() + getMsg().length()) * 2;
+ }
+
}
Added: jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/concurrent/ConcurrentBlobTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/concurrent/ConcurrentBlobTest.java?rev=1167288&view=auto
==============================================================================
--- jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/concurrent/ConcurrentBlobTest.java (added)
+++ jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/concurrent/ConcurrentBlobTest.java Fri Sep 9 16:49:50 2011
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.mk.concurrent;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import org.apache.jackrabbit.mk.blobs.MemoryBlobStore;
+import org.apache.jackrabbit.mk.util.IOUtils;
+import org.apache.jackrabbit.mk.util.IOUtilsTest;
+
+/**
+ * Test concurrent access to the blob store.
+ */
+public class ConcurrentBlobTest extends ConcurrentTest {
+
+ private static final byte[] EMPTY = new byte[50];
+
+ MemoryBlobStore store = new MemoryBlobStore();
+
+ public void setUp() throws Exception {
+ store.setBlockSizeMin(50);
+ }
+
+ public void tearDown() throws InterruptedException {
+ store.clear();
+ }
+
+ void access() {
+ try {
+ int i = id.getAndIncrement();
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ IOUtils.writeLong(out, i);
+ out.write(EMPTY);
+ byte[] data = out.toByteArray();
+ String id = store.writeBlob(new ByteArrayInputStream(data));
+ assertEquals(58, store.getBlobLength(id));
+ byte[] test = out.toByteArray();
+ assertEquals(8, store.readBlob(id, 0, test, 0, 8));
+ IOUtilsTest.assertEquals(data, test);
+ } catch (Throwable t) {
+ lastException = new Exception(t);
+ }
+ }
+
+}
Added: jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/concurrent/ConcurrentTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/concurrent/ConcurrentTest.java?rev=1167288&view=auto
==============================================================================
--- jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/concurrent/ConcurrentTest.java (added)
+++ jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/concurrent/ConcurrentTest.java Fri Sep 9 16:49:50 2011
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.mk.concurrent;
+
+import java.util.concurrent.atomic.AtomicInteger;
+import junit.framework.TestCase;
+import org.apache.jackrabbit.mk.MicroKernelFactory;
+import org.apache.jackrabbit.mk.api.MicroKernel;
+
+/**
+ * Test concurrent access to nodes, the journal, and revision.
+ */
+public class ConcurrentTest extends TestCase {
+
+ // private static final String URL = "fs:{homeDir}/target;clean";
+ private static final String URL = "mem:";
+ // private static final String URL = "mem:fs:target/temp;clean";
+
+ protected MicroKernel mk;
+ protected AtomicInteger id = new AtomicInteger();
+ protected Exception lastException;
+ boolean stop;
+
+ public void setUp() throws Exception {
+ mk = MicroKernelFactory.getInstance(URL);
+ }
+
+ public void tearDown() throws InterruptedException {
+ mk.dispose();
+ }
+
+ public void test() throws Exception {
+ Thread t = new Thread("Test") {
+ public void run() {
+ while (!stop) {
+ access();
+ }
+ }
+ };
+ t.start();
+ long start = System.currentTimeMillis();
+ for (int i = 0; i < 100000; i++) {
+ if (i % 100 == 0 && System.currentTimeMillis() - start > 1000) {
+ break;
+ }
+ access();
+ }
+ stop = true;
+ t.join();
+ if (lastException != null) {
+ throw lastException;
+ }
+
+ }
+
+ void access() {
+ try {
+ long start = System.currentTimeMillis();
+ String rev = mk.getHeadRevision();
+ int i = id.getAndIncrement();
+ String newRev = mk.commit("/", "+\"" + i + "\":{\"x\": " + i + "}", rev, "");
+ assertTrue(!newRev.equals(rev));
+ mk.getJournal(rev, newRev);
+ mk.getRevisions(start, 100);
+ mk.getNodes("/" + i, newRev);
+ mk.getNodes("/" + i, newRev, 0, 0, 0);
+ assertFalse(mk.nodeExists("/" + i, rev));
+ assertTrue(mk.nodeExists("/" + i, newRev));
+ rev = newRev;
+ newRev = mk.commit("/", "-\"" + i + "\"", rev, "");
+ assertTrue(mk.nodeExists("/" + i, rev));
+ assertFalse(mk.nodeExists("/" + i, newRev));
+ } catch (Throwable t) {
+ lastException = new Exception(t);
+ }
+ }
+
+}