Index: oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java =================================================================== --- oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java (revision 1758900) +++ oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java (working copy) @@ -129,7 +129,7 @@ private static final Pattern FILE_NAME_PATTERN = Pattern.compile("(data|bulk)((0|[1-9][0-9]*)[0-9]{4})([a-z])?.tar"); - private static final String FILE_NAME_FORMAT = "data%05d%s.tar"; + static final String FILE_NAME_FORMAT = "data%05d%s.tar"; private static final String LOCK_FILE_NAME = "repo.lock"; @@ -165,10 +165,6 @@ private volatile List readers; - private int writeNumber; - - private volatile File writeFile; - private volatile TarWriter tarWriter; private final RandomAccessFile lockFile; @@ -318,14 +314,13 @@ this.stats = new FileStoreStats(builder.getStatsProvider(), this, size()); if (!readOnly) { + int writeNumber = 0; if (indices.length > 0) { - this.writeNumber = indices[indices.length - 1] + 1; - } else { - this.writeNumber = 0; + writeNumber = indices[indices.length - 1] + 1; } - this.writeFile = new File(directory, format( - FILE_NAME_FORMAT, writeNumber, "a")); - this.tarWriter = new TarWriter(writeFile, stats); + this.tarWriter = new TarWriter(directory, stats, writeNumber); + } else { + this.tarWriter = null; } if (!readOnly) { @@ -671,7 +666,7 @@ fileStoreLock.readLock().lock(); try { readersSnapshot = ImmutableList.copyOf(readers); - writeFileSnapshotSize = writeFile != null ? writeFile.length() : 0; + writeFileSnapshotSize = tarWriter != null ? tarWriter.fileLength() : 0; } finally { fileStoreLock.readLock().unlock(); } @@ -1468,20 +1463,15 @@ * @throws IOException */ private void newWriter() throws IOException { - if (tarWriter.isDirty()) { - tarWriter.close(); - + TarWriter newWriter = tarWriter.renew(); + if (newWriter != tarWriter) { + File writeFile = tarWriter.getFile(); List list = newArrayListWithCapacity(1 + readers.size()); list.add(TarReader.open(writeFile, memoryMapping)); list.addAll(readers); readers = list; - - writeNumber++; - writeFile = new File( - directory, - format(FILE_NAME_FORMAT, writeNumber, "a")); - tarWriter = new TarWriter(writeFile, stats); + tarWriter = newWriter; } } Index: oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/TarWriter.java =================================================================== --- oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/TarWriter.java (revision 1758900) +++ oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/TarWriter.java (working copy) @@ -27,6 +27,8 @@ import static com.google.common.collect.Maps.newHashMap; import static com.google.common.collect.Maps.newLinkedHashMap; import static com.google.common.collect.Sets.newHashSet; +import static java.lang.String.format; +import static org.apache.jackrabbit.oak.segment.file.FileStore.FILE_NAME_FORMAT; import java.io.Closeable; import java.io.File; @@ -110,6 +112,8 @@ } } + private final int writeIndex; + /** * The file being written. This instance is also used as an additional * synchronization point by {@link #flush()} and {@link #close()} to @@ -157,13 +161,20 @@ */ private final Map> graph = newHashMap(); + /** + * Used for maintenance operations (GC or recovery) via the TarReader and tests + */ TarWriter(File file) { - this(file, FileStoreMonitor.DEFAULT); + this.file = file; + this.monitor = FileStoreMonitor.DEFAULT; + this.writeIndex = -1; } - TarWriter(File file, FileStoreMonitor monitor) { - this.file = file; + TarWriter(File directory, FileStoreMonitor monitor, int writeIndex) { + this.file = new File(directory, format(FILE_NAME_FORMAT, writeIndex, + "a")); this.monitor = monitor; + this.writeIndex = writeIndex; } /** @@ -308,10 +319,6 @@ } } - boolean isDirty() { - return access != null; - } - /** * Closes this tar file. * @@ -352,6 +359,17 @@ monitor.written(currentPosition - initialPosition); } + TarWriter renew() throws IOException { + checkState(writeIndex >= 0); + // If nothing was written to this file, then we're already done. + if (access == null) { + return this; + } + close(); + int newIndex = writeIndex + 1; + return new TarWriter(file.getParentFile(), monitor, newIndex); + } + private void writeBinaryReferences() throws IOException { int binaryReferenceSize = 0; @@ -625,6 +643,14 @@ } } + synchronized long fileLength() { + return file.length(); + } + + synchronized File getFile() { + return file; + } + //------------------------------------------------------------< Object >-- @Override Index: oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/FileStoreStatsTest.java =================================================================== --- oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/FileStoreStatsTest.java (revision 1758900) +++ oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/FileStoreStatsTest.java (working copy) @@ -73,31 +73,30 @@ @Test public void tarWriterIntegration() throws Exception{ StatisticsProvider statsProvider = new DefaultStatisticsProvider(executor); - FileStore store = fileStoreBuilder(segmentFolder.newFolder()) + File directory = segmentFolder.newFolder(); + FileStore store = fileStoreBuilder(directory) .withStatisticsProvider(statsProvider) .build(); - FileStoreStats stats = new FileStoreStats(statsProvider, store, 0); - try { long initialSize = stats.getApproximateSize(); - UUID id = UUID.randomUUID(); long msb = id.getMostSignificantBits(); long lsb = id.getLeastSignificantBits() & (-1 >>> 4); // OAK-1672 byte[] data = "Hello, World!".getBytes(UTF_8); - File file = segmentFolder.newFile(); - try (TarWriter writer = new TarWriter(file, stats)) { + TarWriter writer = null; + try { + writer = new TarWriter(directory, stats, 0); writer.writeEntry(msb, lsb, data, 0, data.length, 0); + } finally { + writer.close(); } - - assertEquals(stats.getApproximateSize() - initialSize, file.length()); - + assertEquals(stats.getApproximateSize() - initialSize, + writer.fileLength()); } finally { store.close(); } - assertEquals(1, stats.getJournalWriteStatsAsCount()); }