You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by th...@apache.org on 2012/04/24 11:05:25 UTC
svn commit: r1329600 - in /jackrabbit/oak/trunk/oak-mk/src:
main/java/org/apache/jackrabbit/mk/util/MicroKernelInputStream.java
test/java/org/apache/jackrabbit/mk/util/MicroKernelInputStreamTest.java
Author: thomasm
Date: Tue Apr 24 09:05:24 2012
New Revision: 1329600
URL: http://svn.apache.org/viewvc?rev=1329600&view=rev
Log:
OAK-70 MicroKernelInputStream test and optimization
Added:
jackrabbit/oak/trunk/oak-mk/src/test/java/org/apache/jackrabbit/mk/util/MicroKernelInputStreamTest.java
Modified:
jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/util/MicroKernelInputStream.java
Modified: jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/util/MicroKernelInputStream.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/util/MicroKernelInputStream.java?rev=1329600&r1=1329599&r2=1329600&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/util/MicroKernelInputStream.java (original)
+++ jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/util/MicroKernelInputStream.java Tue Apr 24 09:05:24 2012
@@ -17,19 +17,20 @@
package org.apache.jackrabbit.mk.util;
import org.apache.jackrabbit.mk.api.MicroKernel;
+import org.apache.jackrabbit.mk.util.IOUtils;
import java.io.IOException;
import java.io.InputStream;
/**
- * An input stream to simplify reading a blob from the micro kernel.
- * See also BlobStoreInputStream.
+ * An input stream to simplify reading a blob from a {@code MicroKernel}.
*/
public class MicroKernelInputStream extends InputStream {
private final MicroKernel mk;
private final String id;
private long pos;
+ private long length = -1;
private byte[] oneByteBuff;
public MicroKernelInputStream(MicroKernel mk, String id) {
@@ -37,6 +38,20 @@ public class MicroKernelInputStream exte
this.id = id;
}
+ @Override
+ public long skip(long n) {
+ if (n < 0) {
+ return 0;
+ }
+ if (length == -1) {
+ length = mk.getLength(id);
+ }
+ n = Math.min(n, length - pos);
+ pos += n;
+ return n;
+ }
+
+ @Override
public int read(byte[] b, int off, int len) {
int l = mk.read(id, pos, b, off, len);
if (l < 0) {
@@ -46,6 +61,7 @@ public class MicroKernelInputStream exte
return l;
}
+ @Override
public int read() throws IOException {
if (oneByteBuff == null) {
oneByteBuff = new byte[1];
Added: jackrabbit/oak/trunk/oak-mk/src/test/java/org/apache/jackrabbit/mk/util/MicroKernelInputStreamTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk/src/test/java/org/apache/jackrabbit/mk/util/MicroKernelInputStreamTest.java?rev=1329600&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-mk/src/test/java/org/apache/jackrabbit/mk/util/MicroKernelInputStreamTest.java (added)
+++ jackrabbit/oak/trunk/oak-mk/src/test/java/org/apache/jackrabbit/mk/util/MicroKernelInputStreamTest.java Tue Apr 24 09:05:24 2012
@@ -0,0 +1,146 @@
+/*
+ * 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.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Random;
+import org.apache.jackrabbit.mk.api.MicroKernel;
+import org.apache.jackrabbit.mk.core.MicroKernelImpl;
+import org.junit.Test;
+
+/**
+ * Tests the {@code MicroKernelInputStream}.
+ */
+public class MicroKernelInputStreamTest {
+
+ MicroKernel mk = new MicroKernelImpl();
+
+ @Test
+ public void small() throws IOException {
+ doTest(10, 10);
+ }
+
+ @Test
+ public void medium() throws IOException {
+ doTest(1000, 10);
+ }
+
+ @Test
+ public void large() throws IOException {
+ doTest(100000, 1);
+ }
+
+ private void doTest(int maxLength, int count) throws IOException {
+ String[] s = new String[count * 2];
+ Random r = new Random(0);
+ for (int i = 0; i < s.length;) {
+ int len = count == 1 ? maxLength : r.nextInt(maxLength);
+ byte[] data = new byte[len];
+ r.nextBytes(data);
+ s[i++] = mk.write(new ByteArrayInputStream(data));
+ s[i++] = mk.write(new ByteArrayInputStream(data));
+ }
+ r.setSeed(0);
+ for (int i = 0; i < s.length;) {
+ int len = count == 1 ? maxLength : r.nextInt(maxLength);
+ byte[] expectedData = new byte[len];
+ r.nextBytes(expectedData);
+ assertEquals(len, mk.getLength(s[i++]));
+
+ String id = s[i++];
+ doTestReadFully(expectedData, len, id);
+ doTestRead(expectedData, len, id);
+ }
+ }
+
+ private void doTestReadFully(byte[] expectedData, int expectedLen, String id)
+ throws IOException {
+ byte[] got = MicroKernelInputStream.readFully(mk, id);
+ assertByteArrayEquals(expectedData, expectedLen, got);
+ }
+
+ private void assertByteArrayEquals(byte[] expected, int expectedLen, byte[] got) {
+ assertEquals(expectedLen, got.length);
+ for (int j = 0; j < expectedLen; j++) {
+ if (expected[j] != got[j]) {
+ assertEquals("j:" + j, expected[j], got[j]);
+ }
+ }
+ }
+
+ private void doTestRead(byte[] expectedData, int expectedLen, String id) throws IOException {
+ InputStream in = new MicroKernelInputStream(mk, id);
+ Random r = new Random(1);
+ ByteArrayOutputStream buff = new ByteArrayOutputStream();
+ int minLen = 0;
+ if (expectedLen > 1000000) {
+ minLen = 4000;
+ }
+ int pos = 0;
+ while (true) {
+ int op = r.nextInt(5);
+ if (op == 0) {
+ // read one byte
+ int x = in.read();
+ if (x < 0) {
+ break;
+ }
+ buff.write(x);
+ pos++;
+ } else if (op == 1) {
+ // skip a large number of bytes
+ long n = minLen + r.nextInt(5000);
+ long skipped = in.skip(n);
+ assertTrue(skipped >= 0);
+ buff.write(expectedData, pos, (int) skipped);
+ pos += skipped;
+ } else if (op == 2) {
+ // skip a small number of bytes (possibly negative)
+ long n = r.nextInt(10) - 3;
+ long skipped = in.skip(n);
+ assertTrue(skipped >= 0);
+ buff.write(expectedData, pos, (int) skipped);
+ pos += skipped;
+ } else if (op == 3) {
+ // read a large number of bytes
+ byte[] x = new byte[minLen + r.nextInt(5000)];
+ int l = in.read(x);
+ if (l < 0) {
+ break;
+ }
+ buff.write(x, 0, l);
+ pos += l;
+ } else {
+ // read a small number of bytes
+ int offset = r.nextInt(10);
+ int len = minLen + r.nextInt(1000);
+ byte[] x = new byte[offset + len];
+ int l = in.read(x, offset, len);
+ if (l < 0) {
+ break;
+ }
+ buff.write(x, offset, l);
+ pos += l;
+ }
+ }
+ byte[] got = buff.toByteArray();
+ assertByteArrayEquals(expectedData, expectedLen, got);
+ }
+
+}