Merge branch 'cassandra-2.1' into cassandra-2.2
Conflicts:
CHANGES.txt
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/35292846
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/35292846
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/35292846
Branch: refs/heads/cassandra-3.0
Commit: 352928467b4ee3e42d96455b5c2d040d9728b060
Parents: 3573faf f87e34e
Author: Benedict Elliott Smith <[email protected]>
Authored: Sat Oct 10 09:22:46 2015 +0100
Committer: Benedict Elliott Smith <[email protected]>
Committed: Sat Oct 10 09:22:46 2015 +0100
----------------------------------------------------------------------
CHANGES.txt | 1 +
.../cassandra/io/util/ByteBufferDataInput.java | 8 +--
.../io/util/ByteBufferDataInputTest.java | 67 ++++++++++++++++++++
3 files changed, 69 insertions(+), 7 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/35292846/CHANGES.txt
----------------------------------------------------------------------
diff --cc CHANGES.txt
index d57cc07,20529e8..ea0a2db
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -1,7 -1,5 +1,8 @@@
-2.1.11
+2.2.3
+ * cqlsh pg-style-strings broken (CASSANDRA-10484)
+ * Make Hadoop CF splits more polite to custom orderered partitioners
(CASSANDRA-10400)
+Merged from 2.1:
+ * Fix mmap file segment seeking to EOF (CASSANDRA-10478)
* Allow LOCAL_JMX to be easily overridden (CASSANDRA-10275)
* Mark nodes as dead even if they've already left (CASSANDRA-10205)
* Update internal python driver used by cqlsh (CASSANDRA-10161)
http://git-wip-us.apache.org/repos/asf/cassandra/blob/35292846/src/java/org/apache/cassandra/io/util/ByteBufferDataInput.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/io/util/ByteBufferDataInput.java
index 2f00687,0000000..bf926e9
mode 100644,000000..100644
--- a/src/java/org/apache/cassandra/io/util/ByteBufferDataInput.java
+++ b/src/java/org/apache/cassandra/io/util/ByteBufferDataInput.java
@@@ -1,177 -1,0 +1,171 @@@
+/*
+ * 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.cassandra.io.util;
+
+import java.io.*;
+import java.nio.ByteBuffer;
+
+import org.apache.cassandra.utils.ByteBufferUtil;
+
+public class ByteBufferDataInput extends AbstractDataInput implements
FileDataInput, DataInput
+{
+ private final ByteBuffer buffer;
+ private final String filename;
+ private final long segmentOffset;
+ private int position;
+
+ public ByteBufferDataInput(ByteBuffer buffer, String filename, long
segmentOffset, int position)
+ {
+ assert buffer != null;
+ this.buffer = buffer;
+ this.filename = filename;
+ this.segmentOffset = segmentOffset;
+ this.position = position;
+ }
+
+ // Only use when we know the seek in within the mapped segment. Throws an
+ // IOException otherwise.
+ public void seek(long pos) throws IOException
+ {
+ long inSegmentPos = pos - segmentOffset;
- if (!contains(pos))
++ if (inSegmentPos < 0 || inSegmentPos > buffer.capacity())
+ throw new IOException(String.format("Seek position %d is not
within mmap segment (seg offs: %d, length: %d)", pos, segmentOffset,
buffer.capacity()));
+
+ position = (int) inSegmentPos;
+ }
+
- public boolean contains(long pos)
- {
- long inSegmentPos = pos - segmentOffset;
- return inSegmentPos >= 0 && inSegmentPos < buffer.capacity();
- }
-
+ public long getFilePointer()
+ {
+ return segmentOffset + position;
+ }
+
+ public long getPosition()
+ {
+ return segmentOffset + position;
+ }
+
+ public long getPositionLimit()
+ {
+ return segmentOffset + buffer.capacity();
+ }
+
+ @Override
+ public boolean markSupported()
+ {
+ return false;
+ }
+
+ public void reset(FileMark mark) throws IOException
+ {
+ assert mark instanceof MappedFileDataInputMark;
+ position = ((MappedFileDataInputMark) mark).position;
+ }
+
+ public FileMark mark()
+ {
+ return new MappedFileDataInputMark(position);
+ }
+
+ public long bytesPastMark(FileMark mark)
+ {
+ assert mark instanceof MappedFileDataInputMark;
+ assert position >= ((MappedFileDataInputMark) mark).position;
+ return position - ((MappedFileDataInputMark) mark).position;
+ }
+
+ public boolean isEOF() throws IOException
+ {
+ return position == buffer.capacity();
+ }
+
+ public long bytesRemaining() throws IOException
+ {
+ return buffer.capacity() - position;
+ }
+
+ public String getPath()
+ {
+ return filename;
+ }
+
+ public int read() throws IOException
+ {
+ if (isEOF())
+ return -1;
+ return buffer.get(position++) & 0xFF;
+ }
+
+ /**
+ * Does the same thing as <code>readFully</code> do but without copying
data (thread safe)
+ * @param length length of the bytes to read
+ * @return buffer with portion of file content
+ * @throws IOException on any fail of I/O operation
+ */
+ public ByteBuffer readBytes(int length) throws IOException
+ {
+ int remaining = buffer.remaining() - position;
+ if (length > remaining)
+ throw new IOException(String.format("mmap segment underflow;
remaining is %d but %d requested",
+ remaining, length));
+
+ if (length == 0)
+ return ByteBufferUtil.EMPTY_BYTE_BUFFER;
+
+ ByteBuffer bytes = buffer.duplicate();
+ bytes.position(buffer.position() + position).limit(buffer.position()
+ position + length);
+ position += length;
+
+ // we have to copy the data in case we unreference the underlying
sstable. See CASSANDRA-3179
+ ByteBuffer clone = ByteBuffer.allocate(bytes.remaining());
+ clone.put(bytes);
+ clone.flip();
+ return clone;
+ }
+
+ @Override
+ public final void readFully(byte[] bytes) throws IOException
+ {
+ ByteBufferUtil.arrayCopy(buffer, buffer.position() + position, bytes,
0, bytes.length);
+ position += bytes.length;
+ }
+
+ @Override
+ public final void readFully(byte[] bytes, int offset, int count) throws
IOException
+ {
+ ByteBufferUtil.arrayCopy(buffer, buffer.position() + position, bytes,
offset, count);
+ position += count;
+ }
+
+ private static class MappedFileDataInputMark implements FileMark
+ {
+ int position;
+
+ MappedFileDataInputMark(int position)
+ {
+ this.position = position;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + "(" +
+ "filename='" + filename + "'" +
+ ", position=" + position +
+ ")";
+ }
+}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/35292846/test/unit/org/apache/cassandra/io/util/ByteBufferDataInputTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/io/util/ByteBufferDataInputTest.java
index 0000000,0000000..af2d1dc
new file mode 100644
--- /dev/null
+++ b/test/unit/org/apache/cassandra/io/util/ByteBufferDataInputTest.java
@@@ -1,0 -1,0 +1,67 @@@
++/*
++* 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.cassandra.io.util;
++
++import java.io.IOException;
++import java.nio.ByteBuffer;
++import java.nio.MappedByteBuffer;
++
++import org.junit.Test;
++
++import junit.framework.Assert;
++
++public class ByteBufferDataInputTest
++{
++
++ @Test
++ public void testPositionAndSeek() throws IOException
++ {
++ ByteBufferDataInput bbdi = new
ByteBufferDataInput(ByteBuffer.allocate(100), "", 15, 1);
++ Assert.assertEquals(99, bbdi.bytesRemaining());
++ Assert.assertEquals(16, bbdi.getPosition());
++ Assert.assertEquals(16, bbdi.getFilePointer());
++// Assert.assertTrue(bbdi.markSupported());
++ FileMark mark = bbdi.mark();
++ bbdi.seek(115);
++ Assert.assertEquals(115, bbdi.getFilePointer());
++ Assert.assertEquals(115, bbdi.getPosition());
++ Assert.assertEquals(99, bbdi.bytesPastMark(mark));
++ Assert.assertTrue(bbdi.isEOF());
++ bbdi.seek(15);
++ Assert.assertEquals(15, bbdi.getFilePointer());
++ Assert.assertEquals(15, bbdi.getPosition());
++ try
++ {
++ bbdi.seek(14);
++ Assert.assertTrue(false);
++ }
++ catch (IOException t)
++ {
++ }
++ try
++ {
++ bbdi.seek(116);
++ Assert.assertTrue(false);
++ }
++ catch (IOException t)
++ {
++ }
++ }
++
++}