Author: frm
Date: Tue Apr 11 11:40:07 2017
New Revision: 1790957
URL: http://svn.apache.org/viewvc?rev=1790957&view=rev
Log:
OAK-6052 - Refactor iteration over nodes in a distinct Iterable implementation
Contribution by Julian Sedding.
Modified:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/TarFiles.java
Modified:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/TarFiles.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/TarFiles.java?rev=1790957&r1=1790956&r2=1790957&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/TarFiles.java
(original)
+++
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/TarFiles.java
Tue Apr 11 11:40:07 2017
@@ -20,6 +20,7 @@ package org.apache.jackrabbit.oak.segmen
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Maps.newHashMap;
import static com.google.common.collect.Sets.newHashSet;
import static org.apache.commons.io.FileUtils.listFiles;
@@ -32,9 +33,11 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.NoSuchElementException;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.locks.ReadWriteLock;
@@ -44,6 +47,7 @@ import java.util.regex.Pattern;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
+import com.google.common.collect.Iterables;
import org.apache.jackrabbit.oak.plugins.blob.ReferenceCollector;
import org.apache.jackrabbit.oak.segment.SegmentGraph.SegmentGraphVisitor;
import org.slf4j.Logger;
@@ -61,6 +65,7 @@ class TarFiles implements Closeable {
this.reader = reader;
this.next = next;
}
+
}
static class CleanupResult {
@@ -171,6 +176,41 @@ class TarFiles implements Closeable {
return r;
}
+ private static Iterable<TarReader> iterable(final Node head) {
+ return new Iterable<TarReader>() {
+
+ @Override
+ public Iterator<TarReader> iterator() {
+ return new Iterator<TarReader>() {
+
+ private Node next = head;
+
+ @Override
+ public boolean hasNext() {
+ return next != null;
+ }
+
+ @Override
+ public TarReader next() {
+ if (!hasNext()) {
+ throw new NoSuchElementException();
+ }
+ Node current = next;
+ next = current.next;
+ return current.reader;
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException("not
implemented");
+ }
+
+ };
+ }
+
+ };
+ }
+
private static Map<Integer, Map<Character, File>> collectFiles(File
directory) {
Map<Integer, Map<Character, File>> dataFiles = newHashMap();
for (File file : listFiles(directory, null, false)) {
@@ -196,13 +236,11 @@ class TarFiles implements Closeable {
Set<UUID> references = newHashSet(referencedIds);
do {
// Add direct forward references
- Node n = head;
- while (n != null) {
- n.reader.calculateForwardReferences(references);
+ for (TarReader reader : iterable(head)) {
+ reader.calculateForwardReferences(references);
if (references.isEmpty()) {
break; // Optimisation: bail out if no references left
}
- n = n.next;
}
// ... as long as new forward references are found.
} while (referencedIds.addAll(references));
@@ -279,30 +317,30 @@ class TarFiles implements Closeable {
public void close() throws IOException {
shutdown = true;
- TarWriter writer;
- Node n;
+ TarWriter w;
+ Node head;
lock.writeLock().lock();
try {
- writer = this.writer;
- n = this.readers;
+ w = writer;
+ head = readers;
} finally {
lock.writeLock().unlock();
}
IOException exception = null;
- if (writer != null) {
+ if (w != null) {
try {
- writer.close();
+ w.close();
} catch (IOException e) {
exception = e;
}
}
- while (n != null) {
+ for (TarReader reader : iterable(head)) {
try {
- n.reader.close();
+ reader.close();
} catch (IOException e) {
if (exception == null) {
exception = e;
@@ -310,7 +348,6 @@ class TarFiles implements Closeable {
exception.addSuppressed(e);
}
}
- n = n.next;
}
if (exception != null) {
@@ -321,64 +358,52 @@ class TarFiles implements Closeable {
@Override
public String toString() {
String w = null;
- Node n;
+ Node head;
lock.readLock().lock();
try {
if (writer != null) {
w = writer.toString();
}
- n = readers;
+ head = readers;
} finally {
lock.readLock().unlock();
}
- List<TarReader> rs = new ArrayList<>();
- while (n != null) {
- rs.add(n.reader);
- n = n.next;
- }
- return String.format("TarFiles{readers=%s,writer=%s", rs, w);
+ return String.format("TarFiles{readers=%s,writer=%s}",
newArrayList(iterable(head)), w);
}
long size() {
long size = 0;
- Node readers;
+ Node head;
lock.readLock().lock();
try {
if (writer != null) {
size = writer.fileLength();
}
- readers = this.readers;
+ head = readers;
} finally {
lock.readLock().unlock();
}
- Node n = readers;
- while (n != null) {
- size += n.reader.size();
- n = n.next;
+ for (TarReader reader : iterable(head)) {
+ size += reader.size();
}
return size;
}
int readerCount() {
- Node n;
+ Node head;
lock.readLock().lock();
try {
- n = readers;
+ head = readers;
} finally {
lock.readLock().unlock();
}
- int count = 0;
- while (n != null) {
- count++;
- n = n.next;
- }
- return count;
+ return Iterables.size(iterable(head));
}
void flush() throws IOException {
@@ -391,7 +416,7 @@ class TarFiles implements Closeable {
}
boolean containsSegment(long msb, long lsb) {
- Node n;
+ Node head;
lock.readLock().lock();
try {
@@ -400,23 +425,22 @@ class TarFiles implements Closeable {
return true;
}
}
- n = this.readers;
+ head = readers;
} finally {
lock.readLock().unlock();
}
- while (n != null) {
- if (n.reader.containsEntry(msb, lsb)) {
+ for (TarReader reader : iterable(head)) {
+ if (reader.containsEntry(msb, lsb)) {
return true;
}
- n = n.next;
}
return false;
}
ByteBuffer readSegment(long msb, long lsb) {
try {
- Node n;
+ Node head;
lock.readLock().lock();
try {
@@ -426,17 +450,16 @@ class TarFiles implements Closeable {
return b;
}
}
- n = readers;
+ head = readers;
} finally {
lock.readLock().unlock();
}
- while (n != null) {
- ByteBuffer b = n.reader.readEntry(msb, lsb);
+ for (TarReader reader : iterable(head)) {
+ ByteBuffer b = reader.readEntry(msb, lsb);
if (b != null) {
return b;
}
- n = n.next;
}
} catch (IOException e) {
log.warn("Unable to read from TAR file", e);
@@ -499,18 +522,17 @@ class TarFiles implements Closeable {
result.reclaimedSegmentIds = new HashSet<>();
Set<UUID> references;
- Node readers;
+ Node head;
lock.writeLock().lock();
lock.readLock().lock();
- ;
try {
try {
newWriter();
} finally {
lock.writeLock().unlock();
}
- readers = this.readers;
+ head = readers;
references = referencesSupplier.get();
} finally {
lock.readLock().unlock();
@@ -518,13 +540,9 @@ class TarFiles implements Closeable {
Map<TarReader, TarReader> cleaned = new LinkedHashMap<>();
- {
- Node n = readers;
- while (n != null) {
- cleaned.put(n.reader, n.reader);
- result.reclaimedSize += n.reader.size();
- n = n.next;
- }
+ for (TarReader reader : iterable(head)) {
+ cleaned.put(reader, reader);
+ result.reclaimedSize += reader.size();
}
Set<UUID> reclaim = newHashSet();
@@ -553,15 +571,14 @@ class TarFiles implements Closeable {
reclaimed = 0;
Node swept = null;
- Node n = readers;
// The following loops creates a modified version of `readers` and
// saves it into `swept`. Some TAR readers in `readers` have been
// swept by the previous code and must be replaced with a slimmer
// TAR reader with the same index but a higher generation.
- while (n != null) {
- if (cleaned.containsKey(n.reader)) {
+ for (TarReader reader : iterable(head)) {
+ if (cleaned.containsKey(reader)) {
// We distinguish three cases. First, the original TAR
// reader is unmodified. This happens with no content or
not
@@ -571,25 +588,24 @@ class TarFiles implements Closeable {
// index and a higher generation was created. Third, all
the
// content from the original TAR reader could be swept.
- TarReader r = cleaned.get(n.reader);
-
- if (r != null) {
+ TarReader cleandedReader = cleaned.get(reader);
+ if (cleandedReader != null) {
// We are either in the first or in the second case.
// Save the TAR reader (either the original or the one
// with a higher generation) in the resulting linked
list.
- swept = new Node(r, swept);
- reclaimed += r.size();
+ swept = new Node(cleandedReader, swept);
+ reclaimed += cleandedReader.size();
}
- if (r != n.reader) {
+ if (cleandedReader != reader) {
// We are either in the second or third case. Save the
// original TAR reader in a list of TAR readers that
// will be closed at the end of this methods.
- closeables = new Node(n.reader, closeables);
+ closeables = new Node(reader, closeables);
}
} else {
@@ -598,9 +614,8 @@ class TarFiles implements Closeable {
// first, when we re-read `readers` and recompute `swept`
// all over again.
- swept = new Node(n.reader, swept);
+ swept = new Node(reader, swept);
}
- n = n.next;
}
// `swept` is in the reverse order because we prepended new nodes
@@ -616,11 +631,11 @@ class TarFiles implements Closeable {
lock.writeLock().lock();
try {
- if (this.readers == readers) {
- this.readers = swept;
+ if (readers == head) {
+ readers = swept;
break;
} else {
- readers = this.readers;
+ head = readers;
}
} finally {
lock.writeLock().unlock();
@@ -629,65 +644,59 @@ class TarFiles implements Closeable {
result.reclaimedSize -= reclaimed;
- {
- Node n = closeables;
- while (n != null) {
- try {
- n.reader.close();
- } catch (IOException e) {
- log.warn("Unable to close swept TAR reader", e);
- }
- result.removableFiles.add(n.reader.getFile());
- n = n.next;
+ for (TarReader closeable : iterable(closeables)) {
+ try {
+ closeable.close();
+ } catch (IOException e) {
+ log.warn("Unable to close swept TAR reader", e);
}
+ result.removableFiles.add(closeable.getFile());
}
return result;
}
void collectBlobReferences(ReferenceCollector collector, int
minGeneration) throws IOException {
- Node n;
+ Node head;
lock.writeLock().lock();
try {
if (writer != null) {
newWriter();
}
- n = readers;
+ head = readers;
} finally {
lock.writeLock().unlock();
}
- while (n != null) {
- n.reader.collectBlobReferences(collector, minGeneration);
- n = n.next;
+ for (TarReader reader : iterable(head)) {
+ reader.collectBlobReferences(collector, minGeneration);
}
}
Iterable<UUID> getSegmentIds() {
- Node n;
+ Node head;
lock.readLock().lock();
try {
- n = readers;
+ head = readers;
} finally {
lock.readLock().unlock();
}
List<UUID> ids = new ArrayList<>();
- while (n != null) {
- ids.addAll(n.reader.getUUIDs());
- n = n.next;
+ for (TarReader reader : iterable(head)) {
+ ids.addAll(reader.getUUIDs());
}
return ids;
}
Map<UUID, List<UUID>> getGraph(String fileName) throws IOException {
- Node n;
+ Node head;
lock.readLock().lock();
try {
- n = readers;
+ head = readers;
} finally {
lock.readLock().unlock();
}
@@ -695,14 +704,12 @@ class TarFiles implements Closeable {
Set<UUID> index = null;
Map<UUID, List<UUID>> graph = null;
- while (n != null) {
- TarReader r = n.reader;
- if (fileName.equals(r.getFile().getName())) {
- index = r.getUUIDs();
- graph = r.getGraph(false);
+ for (TarReader reader : iterable(head)) {
+ if (fileName.equals(reader.getFile().getName())) {
+ index = reader.getUUIDs();
+ graph = reader.getGraph(false);
break;
}
- n = n.next;
}
Map<UUID, List<UUID>> result = new HashMap<>();
@@ -718,37 +725,35 @@ class TarFiles implements Closeable {
}
Map<String, Set<UUID>> getIndices() {
- Node n;
+ Node head;
lock.readLock().lock();
try {
- n = readers;
+ head = readers;
} finally {
lock.readLock().unlock();
}
Map<String, Set<UUID>> index = new HashMap<>();
- while (n != null) {
- index.put(n.reader.getFile().getAbsolutePath(),
n.reader.getUUIDs());
- n = n.next;
+ for (TarReader reader : iterable(head)) {
+ index.put(reader.getFile().getAbsolutePath(), reader.getUUIDs());
}
return index;
}
void traverseSegmentGraph(Set<UUID> roots, SegmentGraphVisitor visitor)
throws IOException {
- Node n;
+ Node head;
lock.readLock().lock();
try {
- n = readers;
+ head = readers;
} finally {
lock.readLock().unlock();
}
- includeForwardReferences(n, roots);
- while (n != null) {
- n.reader.traverseSegmentGraph(roots, visitor);
- n = n.next;
+ includeForwardReferences(head, roots);
+ for (TarReader reader : iterable(head)) {
+ reader.traverseSegmentGraph(roots, visitor);
}
}