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 ju...@apache.org on 2013/02/08 18:54:51 UTC
svn commit: r1444166 - in
/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment:
SegmentBlob.java SegmentNodeState.java SegmentPropertyState.java
SegmentStream.java SegmentWriter.java
Author: jukka
Date: Fri Feb 8 17:54:50 2013
New Revision: 1444166
URL: http://svn.apache.org/r1444166
Log:
OAK-593: Segment-based MK
Initial segment-based node and property state implementations.
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentBlob.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeState.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentPropertyState.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentStream.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentWriter.java
Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentBlob.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentBlob.java?rev=1444166&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentBlob.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentBlob.java Fri Feb 8 17:54:50 2013
@@ -0,0 +1,78 @@
+/*
+ * 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.oak.plugins.segment;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import javax.annotation.Nonnull;
+
+import org.apache.jackrabbit.oak.api.Blob;
+
+public class SegmentBlob implements Blob {
+
+ private final SegmentReader reader;
+
+ private final RecordId recordId;
+
+ SegmentBlob(SegmentReader reader, RecordId recordId) {
+ this.reader = checkNotNull(reader);
+ this.recordId = checkNotNull(recordId);
+ }
+
+ @Override @Nonnull
+ public SegmentStream getNewStream() {
+ return reader.readStream(recordId);
+ }
+
+ @Override
+ public long length() {
+ SegmentStream stream = getNewStream();
+ try {
+ return stream.getLength();
+ } finally {
+ stream.close();
+ }
+ }
+
+ @Override
+ public byte[] sha256() {
+ SegmentStream stream = getNewStream();
+ try {
+ MessageDigest digest = MessageDigest.getInstance("SHA-256");
+
+ byte[] buffer = new byte[1024];
+ for (int n = stream.read(buffer); n != -1; n = stream.read(buffer)) {
+ digest.update(buffer, 0, n);
+ }
+
+ return digest.digest();
+ } catch (NoSuchAlgorithmException e) {
+ throw new UnsupportedOperationException("SHA256 not supported", e);
+ } finally {
+ stream.close();
+ }
+ }
+
+ @Override
+ public int compareTo(Blob that) {
+ throw new UnsupportedOperationException();
+ }
+
+}
Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeState.java?rev=1444166&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeState.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeState.java Fri Feb 8 17:54:50 2013
@@ -0,0 +1,114 @@
+/*
+ * 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.oak.plugins.segment;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
+
+class SegmentNodeState implements NodeState {
+
+ private final SegmentReader reader;
+
+ private final MapRecord properties;
+
+ private final MapRecord childNodes;
+
+ SegmentNodeState(SegmentReader reader, RecordId id) {
+ this.reader = checkNotNull(reader);
+
+ checkNotNull(id);
+ this.properties = new MapRecord(reader.readRecordId(id, 0));
+ this.childNodes = new MapRecord(reader.readRecordId(id, 4));
+ }
+
+ @Override
+ public long getPropertyCount() {
+ return properties.size(reader);
+ }
+
+ @Override @CheckForNull
+ public PropertyState getProperty(String name) {
+ checkNotNull(name);
+ RecordId propertyId = properties.getEntry(reader, name);
+ if (propertyId != null) {
+ return new SegmentPropertyState(reader, name, propertyId);
+ } else {
+ return null;
+ }
+ }
+
+ @Override @Nonnull
+ public Iterable<? extends PropertyState> getProperties() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public long getChildNodeCount() {
+ return childNodes.size(reader);
+ }
+
+ @Override
+ public boolean hasChildNode(String name) {
+ checkNotNull(name);
+ return childNodes.getEntry(reader, name) != null;
+ }
+
+ @Override @CheckForNull
+ public NodeState getChildNode(String name) {
+ checkNotNull(name);
+ RecordId childNodeId = childNodes.getEntry(reader, name);
+ if (childNodeId != null) {
+ return new SegmentNodeState(reader, childNodeId);
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public Iterable<String> getChildNodeNames() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override @Nonnull
+ public Iterable<? extends ChildNodeEntry> getChildNodeEntries() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override @Nonnull
+ public NodeBuilder builder() {
+ return new MemoryNodeBuilder(this);
+ }
+
+ @Override
+ public void compareAgainstBaseState(NodeState base, NodeStateDiff diff) {
+ // TODO Auto-generated method stub
+
+ }
+
+}
Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentPropertyState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentPropertyState.java?rev=1444166&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentPropertyState.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentPropertyState.java Fri Feb 8 17:54:50 2013
@@ -0,0 +1,158 @@
+/*
+ * 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.oak.plugins.segment;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import javax.annotation.Nonnull;
+import javax.jcr.PropertyType;
+
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.plugins.value.Conversions;
+
+class SegmentPropertyState implements PropertyState {
+
+ private final SegmentReader reader;
+
+ private final String name;
+
+ private final int tag;
+
+ private final int count;
+
+ private final ListRecord values;
+
+ SegmentPropertyState(SegmentReader reader, String name, RecordId id) {
+ this.reader = checkNotNull(reader);
+ this.name = checkNotNull(name);
+
+ checkNotNull(id);
+ this.tag = reader.readInt(id, 0);
+ this.count = reader.readInt(id, 4);
+ this.values = new ListRecord(reader.readRecordId(id, 8), count());
+ }
+
+ @Override @Nonnull
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public boolean isArray() {
+ return count != -1;
+ }
+
+ @Override
+ public int count() {
+ if (isArray()) {
+ return count;
+ } else {
+ return 1;
+ }
+ }
+
+ @Override
+ public Type<?> getType() {
+ return Type.fromTag(tag, isArray());
+ }
+
+ @Override @Nonnull @SuppressWarnings("unchecked")
+ public <T> T getValue(Type<T> type) {
+ if (type.isArray()) {
+ final Type<?> base = type.getBaseType();
+ return (T) new Iterable<Object>() {
+ @Override
+ public Iterator<Object> iterator() {
+ return new Iterator<Object>() {
+ private int index = 0;
+ @Override
+ public boolean hasNext() {
+ return index < count();
+ }
+ @Override
+ public Object next() {
+ if (hasNext()) {
+ return getValue(base, index++);
+ } else {
+ throw new NoSuchElementException();
+ }
+ }
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+ };
+ } else {
+ return getValue(type, 0);
+ }
+ }
+
+ @Override
+ public long size() {
+ return size(0);
+ }
+
+ @Override @Nonnull @SuppressWarnings("unchecked")
+ public <T> T getValue(Type<T> type, int index) {
+ checkNotNull(type);
+ checkArgument(!type.isArray(), "Type must not be an array type");
+
+ RecordId valueId = values.getEntry(reader, index);
+ if (type == Type.BINARY) {
+ return (T) new SegmentBlob(reader, valueId);
+ } else {
+ String value = reader.readString(valueId);
+ switch (type.tag()) {
+ case PropertyType.BOOLEAN:
+ return (T) Boolean.valueOf(Conversions.convert(value).toBoolean());
+ case PropertyType.DATE:
+ return (T) Conversions.convert(value).toDate();
+ case PropertyType.DECIMAL:
+ return (T) Conversions.convert(value).toDecimal();
+ case PropertyType.DOUBLE:
+ return (T) Double.valueOf(Conversions.convert(value).toDouble());
+ case PropertyType.LONG:
+ return (T) Long.valueOf(Conversions.convert(value).toLong());
+ case PropertyType.NAME:
+ case PropertyType.PATH:
+ case PropertyType.REFERENCE:
+ case PropertyType.STRING:
+ case PropertyType.URI:
+ case PropertyType.WEAKREFERENCE:
+ return (T) value;
+ case PropertyType.UNDEFINED:
+ throw new IllegalArgumentException("Undefined type");
+ default:
+ throw new UnsupportedOperationException("Unknown type: " + type);
+ }
+ }
+ }
+
+ @Override
+ public long size(int index) {
+ RecordId valueId = values.getEntry(reader, index);
+ return reader.readLong(valueId, 0);
+ }
+
+}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentStream.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentStream.java?rev=1444166&r1=1444165&r2=1444166&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentStream.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentStream.java Fri Feb 8 17:54:50 2013
@@ -1,116 +1,120 @@
-/*
- * 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.oak.plugins.segment;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkPositionIndexes;
-import static org.apache.jackrabbit.oak.plugins.segment.SegmentWriter.BLOCK_SIZE;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-public class SegmentStream extends InputStream {
-
- private final SegmentReader reader;
-
- private final ListRecord blocks;
-
- private final long length;
-
- private long position = 0;
-
- private long mark = 0;
-
- SegmentStream(SegmentReader reader, ListRecord blocks, long length) {
- this.reader = reader;
- this.blocks = blocks;
- this.length = length;
- }
-
- public long getLength() {
- return length;
- }
-
- @Override
- public boolean markSupported() {
- return true;
- }
-
- @Override
- public synchronized void mark(int readlimit) {
- mark = position;
- }
-
- @Override
- public synchronized void reset() {
- position = mark;
- }
-
- @Override
- public int read() throws IOException {
- byte[] b = new byte[1];
- if (read(b) != -1) {
- return b[0] & 0xff;
- } else {
- return -1;
- }
- }
-
- @Override
- public int read(byte[] b, int off, int len) throws IOException {
- checkNotNull(b);
- checkPositionIndexes(off, off + len, b.length);
- if (len == 0) {
- return 0;
- } else if (position == length) {
- return -1;
- } else {
- int blockIndex = (int) (position / SegmentWriter.BLOCK_SIZE);
- int blockOffset = (int) (position % SegmentWriter.BLOCK_SIZE);
-
- if (blockOffset + len > SegmentWriter.BLOCK_SIZE) {
- len = SegmentWriter.BLOCK_SIZE - blockOffset;
- }
- if (position + len > length) {
- len = (int) (length - position);
- }
-
- BlockRecord block = reader.readBlock(
- blocks.getEntry(reader, blockIndex), BLOCK_SIZE);
- len = block.read(reader, blockOffset, b, off, len);
- position += len;
- return len;
- }
- }
-
- @Override
- public long skip(long n) {
- if (position + n > length) {
- n = length - position;
- } else if (position + n < 0) {
- n = -position;
- }
- position += n;
- return n;
- }
-
- @Override
- public void close() {
- position = length;
- }
-
-}
+/*
+ * 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.oak.plugins.segment;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkPositionIndexes;
+import static org.apache.jackrabbit.oak.plugins.segment.SegmentWriter.BLOCK_SIZE;
+
+import java.io.InputStream;
+
+public class SegmentStream extends InputStream {
+
+ private final SegmentReader reader;
+
+ private final ListRecord blocks;
+
+ private final long length;
+
+ private long position = 0;
+
+ private long mark = 0;
+
+ SegmentStream(SegmentReader reader, ListRecord blocks, long length) {
+ this.reader = reader;
+ this.blocks = blocks;
+ this.length = length;
+ }
+
+ public long getLength() {
+ return length;
+ }
+
+ @Override
+ public boolean markSupported() {
+ return true;
+ }
+
+ @Override
+ public synchronized void mark(int readlimit) {
+ mark = position;
+ }
+
+ @Override
+ public synchronized void reset() {
+ position = mark;
+ }
+
+ @Override
+ public int read() {
+ byte[] b = new byte[1];
+ if (read(b) != -1) {
+ return b[0] & 0xff;
+ } else {
+ return -1;
+ }
+ }
+
+ @Override
+ public int read(byte[] b) {
+ return read(b, 0, b.length);
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) {
+ checkNotNull(b);
+ checkPositionIndexes(off, off + len, b.length);
+ if (len == 0) {
+ return 0;
+ } else if (position == length) {
+ return -1;
+ } else {
+ int blockIndex = (int) (position / SegmentWriter.BLOCK_SIZE);
+ int blockOffset = (int) (position % SegmentWriter.BLOCK_SIZE);
+
+ if (blockOffset + len > SegmentWriter.BLOCK_SIZE) {
+ len = SegmentWriter.BLOCK_SIZE - blockOffset;
+ }
+ if (position + len > length) {
+ len = (int) (length - position);
+ }
+
+ BlockRecord block = reader.readBlock(
+ blocks.getEntry(reader, blockIndex), BLOCK_SIZE);
+ len = block.read(reader, blockOffset, b, off, len);
+ position += len;
+ return len;
+ }
+ }
+
+ @Override
+ public long skip(long n) {
+ if (position + n > length) {
+ n = length - position;
+ } else if (position + n < 0) {
+ n = -position;
+ }
+ position += n;
+ return n;
+ }
+
+ @Override
+ public void close() {
+ position = length;
+ }
+
+}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentWriter.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentWriter.java?rev=1444166&r1=1444165&r2=1444166&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentWriter.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentWriter.java Fri Feb 8 17:54:50 2013
@@ -31,8 +31,17 @@ import java.util.Map;
import java.util.Set;
import java.util.UUID;
+import javax.jcr.PropertyType;
+
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
import com.google.common.base.Charsets;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
import com.google.common.io.ByteStreams;
public class SegmentWriter {
@@ -357,4 +366,53 @@ public class SegmentWriter {
}
}
+ private RecordId writeProperty(PropertyState state) {
+ Type<?> type = state.getType();
+ int count = state.count();
+
+ List<RecordId> valueIds = Lists.newArrayList();
+ for (int i = 0; i < count; i++) {
+ if (type.tag() == PropertyType.BINARY) {
+ try {
+ valueIds.add(writeStream(
+ state.getValue(Type.BINARY, i).getNewStream()));
+ } catch (IOException e) {
+ throw new IllegalStateException("Unexpected IOException", e);
+ }
+ } else {
+ valueIds.add(writeString(state.getValue(Type.STRING, i)));
+ }
+ }
+ RecordId valueId = writeList(valueIds);
+
+ RecordId propertyId = prepare(8, Collections.singleton(valueId));
+ buffer.putInt(type.tag());
+ if (state.isArray()) {
+ buffer.putInt(count);
+ } else {
+ buffer.putInt(-1);
+ }
+ writeRecordId(valueId);
+ return propertyId;
+ }
+
+ public RecordId writeNode(NodeState state) {
+ Map<String, RecordId> childNodes = Maps.newHashMap();
+ for (ChildNodeEntry entry : state.getChildNodeEntries()) {
+ childNodes.put(entry.getName(), writeNode(entry.getNodeState()));
+ }
+ RecordId childNodesId = writeMap(childNodes);
+
+ Map<String, RecordId> properties = Maps.newHashMap();
+ for (PropertyState property : state.getProperties()) {
+ properties.put(property.getName(), writeProperty(property));
+ }
+ RecordId propertiesId = writeMap(properties);
+
+ RecordId id = prepare(0, ImmutableList.of(propertiesId, childNodesId));
+ writeRecordId(propertiesId);
+ writeRecordId(childNodesId);
+ return id;
+ }
+
}