Beispiel #1
0
 private void writeHeader(LogSegment segment, byte[] buf) throws IOException {
   FileChannel channel = segment.getView().getSecond();
   ByteBuffer buffer = ByteBuffer.wrap(buf);
   while (buffer.hasRemaining()) {
     channel.write(buffer, 0);
   }
 }
Beispiel #2
0
 /**
  * Closes the {@code segment} and deletes the backing file.
  *
  * @param segment the {@link LogSegment} that needs to be closed and whose backing file needs to
  *     be deleted.
  * @throws IOException
  */
 private void closeSegmentAndDeleteFile(LogSegment segment) throws IOException {
   segment.close();
   assertFalse("File channel is not closed", segment.getView().getSecond().isOpen());
   File segmentFile = new File(tempDir, segment.getName());
   assertTrue(
       "The segment file [" + segmentFile.getAbsolutePath() + "] could not be deleted",
       segmentFile.delete());
 }
Beispiel #3
0
 /**
  * Gets a view of the given {@code segment} and verifies the ref count and the data obtained from
  * the view against {@code expectedRefCount} and {@code dataInSegment} respectively.
  *
  * @param segment the {@link LogSegment} to get a view from.
  * @param writeStartOffset the offset at which write was started on the segment.
  * @param offset the offset for which a view is required.
  * @param dataInSegment the entire data in the {@link LogSegment}.
  * @param expectedRefCount the expected return value of {@link LogSegment#refCount()} once the
  *     view is obtained from the {@code segment}
  * @throws IOException
  */
 private void getAndVerifyView(
     LogSegment segment,
     long writeStartOffset,
     int offset,
     byte[] dataInSegment,
     long expectedRefCount)
     throws IOException {
   Random random = new Random();
   Pair<File, FileChannel> view = segment.getView();
   assertNotNull("File object received in view is null", view.getFirst());
   assertNotNull("FileChannel object received in view is null", view.getSecond());
   assertEquals("Ref count is not as expected", expectedRefCount, segment.refCount());
   int sizeToRead = random.nextInt(dataInSegment.length - offset + 1);
   ByteBuffer buffer = ByteBuffer.wrap(new byte[sizeToRead]);
   view.getSecond().read(buffer, writeStartOffset + offset);
   assertArrayEquals(
       "Data read from file does not match data written",
       Arrays.copyOfRange(dataInSegment, offset, offset + sizeToRead),
       buffer.array());
 }
Beispiel #4
0
  /**
   * Tests setting end offset - makes sure legal values are set correctly and illegal values are
   * rejected.
   *
   * @throws IOException
   */
  @Test
  public void endOffsetTest() throws IOException {
    String segmentName = "log_current";
    LogSegment segment = getSegment(segmentName, STANDARD_SEGMENT_SIZE, true);
    try {
      long writeStartOffset = segment.getStartOffset();
      int segmentSize = 500;
      appendRandomData(segment, segmentSize);
      assertEquals(
          "End offset is not as expected", writeStartOffset + segmentSize, segment.getEndOffset());

      // should be able to set end offset to something >= initial offset and <= file size
      int[] offsetsToSet = {(int) (writeStartOffset), segmentSize / 2, segmentSize};
      for (int offset : offsetsToSet) {
        segment.setEndOffset(offset);
        assertEquals("End offset is not equal to what was set", offset, segment.getEndOffset());
        assertEquals(
            "File channel positioning is incorrect",
            offset,
            segment.getView().getSecond().position());
      }

      // cannot set end offset to illegal values (< initial offset or > file size)
      int[] invalidOffsets = {(int) (writeStartOffset - 1), (int) (segment.sizeInBytes() + 1)};
      for (int offset : invalidOffsets) {
        try {
          segment.setEndOffset(offset);
          fail("Setting log end offset an invalid offset [" + offset + "] should have failed");
        } catch (IllegalArgumentException e) {
          // expected. Nothing to do.
        }
      }
    } finally {
      closeSegmentAndDeleteFile(segment);
    }
  }
Beispiel #5
0
 private byte[] getHeader(LogSegment segment) throws IOException {
   FileChannel channel = segment.getView().getSecond();
   ByteBuffer header = ByteBuffer.allocate(LogSegment.HEADER_SIZE);
   channel.read(header, 0);
   return header.array();
 }
Beispiel #6
0
  /**
   * Tests for bad construction cases of {@link LogSegment}.
   *
   * @throws IOException
   */
  @Test
  public void badConstructionTest() throws IOException {
    // try to construct with a file that does not exist.
    String name = "log_non_existent";
    File file = new File(tempDir, name);
    try {
      new LogSegment(name, file, STANDARD_SEGMENT_SIZE, metrics, true);
      fail("Construction should have failed because the backing file does not exist");
    } catch (IllegalArgumentException e) {
      // expected. Nothing to do.
    }

    try {
      new LogSegment(name, file, metrics);
      fail("Construction should have failed because the backing file does not exist");
    } catch (IllegalArgumentException e) {
      // expected. Nothing to do.
    }

    // try to construct with a file that is a directory
    name = tempDir.getName();
    file = new File(tempDir.getParent(), name);
    try {
      new LogSegment(name, file, STANDARD_SEGMENT_SIZE, metrics, true);
      fail("Construction should have failed because the backing file does not exist");
    } catch (IllegalArgumentException e) {
      // expected. Nothing to do.
    }

    name = tempDir.getName();
    file = new File(tempDir.getParent(), name);
    try {
      new LogSegment(name, file, metrics);
      fail("Construction should have failed because the backing file does not exist");
    } catch (IllegalArgumentException e) {
      // expected. Nothing to do.
    }

    // unknown version
    LogSegment segment = getSegment("dummy_log", STANDARD_SEGMENT_SIZE, true);
    file = segment.getView().getFirst();
    byte[] header = getHeader(segment);
    byte savedByte = header[0];
    // mess with version
    header[0] = (byte) (header[0] + 10);
    writeHeader(segment, header);
    try {
      new LogSegment(name, file, metrics);
      fail("Construction should have failed because version is unknown");
    } catch (IllegalArgumentException e) {
      // expected. Nothing to do.
    }

    // bad CRC
    // fix version but mess with data after version
    header[0] = savedByte;
    header[2] = header[2] == (byte) 1 ? (byte) 0 : (byte) 1;
    writeHeader(segment, header);
    try {
      new LogSegment(name, file, metrics);
      fail("Construction should have failed because crc check should have failed");
    } catch (IllegalStateException e) {
      // expected. Nothing to do.
    }
    closeSegmentAndDeleteFile(segment);
  }