Author: frm
Date: Wed Nov 1 10:35:39 2017
New Revision: 1813959
URL: http://svn.apache.org/viewvc?rev=1813959&view=rev
Log:
OAK-6888 - Force data to be persisted to disk when flushing
Added:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/Flusher.java
(with props)
Modified:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/TarRevisions.java
Modified:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java?rev=1813959&r1=1813958&r2=1813959&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java
(original)
+++
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java
Wed Nov 1 10:35:39 2017
@@ -212,10 +212,9 @@ public class FileStore extends AbstractF
return;
}
try {
- flush();
+ maybeFlush();
} catch (IOException e) {
- log.warn("Failed to flush the TarMK at {}",
- directory, e);
+ log.warn("Failed to flush the TarMK at {}",
directory, e);
}
}
});
@@ -314,6 +313,24 @@ public class FileStore extends AbstractF
return stats;
}
+ private void doMaybeFlush() throws IOException {
+ if (revisions == null) {
+ log.debug("No TarRevisions available, skipping flush");
+ return;
+ }
+ revisions.maybeFlush(() -> {
+ segmentWriter.flush();
+ tarFiles.flush();
+ stats.flushed();
+ });
+ }
+
+ private void maybeFlush() throws IOException {
+ try (ShutDownCloser ignored = shutDown.keepAlive()) {
+ doMaybeFlush();
+ }
+ }
+
private void doFlush() throws IOException {
if (revisions == null) {
log.debug("No TarRevisions available, skipping flush");
@@ -323,7 +340,6 @@ public class FileStore extends AbstractF
segmentWriter.flush();
tarFiles.flush();
stats.flushed();
- return null;
});
}
Added:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/Flusher.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/Flusher.java?rev=1813959&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/Flusher.java
(added)
+++
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/Flusher.java
Wed Nov 1 10:35:39 2017
@@ -0,0 +1,26 @@
+/*
+ * 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.segment.file;
+
+import java.io.IOException;
+
+interface Flusher {
+
+ void flush() throws IOException;
+
+}
Propchange:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/Flusher.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/TarRevisions.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/TarRevisions.java?rev=1813959&r1=1813958&r2=1813959&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/TarRevisions.java
(original)
+++
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/TarRevisions.java
Wed Nov 1 10:35:39 2017
@@ -21,8 +21,6 @@ package org.apache.jackrabbit.oak.segmen
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.base.Throwables.propagate;
-import static com.google.common.base.Throwables.propagateIfInstanceOf;
import static java.lang.Long.MAX_VALUE;
import static java.util.concurrent.TimeUnit.DAYS;
import static
org.apache.jackrabbit.oak.segment.file.FileStoreUtil.findPersistedRecordId;
@@ -54,7 +52,7 @@ import org.slf4j.LoggerFactory;
/**
* This implementation of {@code Revisions} is backed by a
* {@link #JOURNAL_FILE_NAME journal} file where the current head is persisted
- * by calling {@link #flush(Callable)}.
+ * by calling {@link #maybeFlush(Callable)}.
* <p>
* The {@link #setHead(Function, Option...)} method supports a timeout
* {@link Option}, which can be retrieved through factory methods of this
class.
@@ -181,26 +179,45 @@ public class TarRevisions implements Rev
}
/**
- * Flush the id of the current head to the journal after a call to
- * {@code persisted}. This method does nothing and returns immediately if
- * called concurrently and a call is already in progress.
- * @param persisted call back for upstream dependencies to ensure
- * the current head state is actually persisted before
- * its id is written to the head state.
- * @throws IOException
+ * Flush the id of the current head to the journal after a call to {@code
+ * persisted}. Differently from {@link #maybeFlush(Flusher)}, this method
+ * does not return early if a concurrent call is in progress. Instead, it
+ * blocks the caller until the requested flush operation is performed.
+ *
+ * @param flusher call back for upstream dependencies to ensure the current
+ * head state is actually persisted before its id is written
+ * to the head state.
*/
- public void flush(@Nonnull Callable<Void> persisted) throws IOException {
+ void flush(Flusher flusher) throws IOException {
+ if (head.get() == null) {
+ LOG.debug("No head available, skipping flush");
+ return;
+ }
+ journalFileLock.lock();
+ try {
+ doFlush(flusher);
+ } finally {
+ journalFileLock.unlock();
+ }
+ }
+
+ /**
+ * Flush the id of the current head to the journal after a call to {@code
+ * persisted}. This method does nothing and returns immediately if called
+ * concurrently and a call is already in progress.
+ *
+ * @param flusher call back for upstream dependencies to ensure the current
+ * head state is actually persisted before its id is written
+ * to the head state.
+ */
+ void maybeFlush(Flusher flusher) throws IOException {
if (head.get() == null) {
LOG.debug("No head available, skipping flush");
return;
}
if (journalFileLock.tryLock()) {
try {
- if (journalFile == null) {
- LOG.debug("No journal file available, skipping flush");
- return;
- }
- doFlush(persisted);
+ doFlush(flusher);
} finally {
journalFileLock.unlock();
}
@@ -209,23 +226,22 @@ public class TarRevisions implements Rev
}
}
- private void doFlush(Callable<Void> persisted) throws IOException {
- try {
- RecordId before = persistedHead.get();
- RecordId after = getHead();
- if (after.equals(before)) {
- LOG.debug("Head state did not change, skipping flush");
- } else {
- persisted.call();
- LOG.debug("TarMK journal update {} -> {}", before, after);
- journalFile.writeBytes(after.toString10() + " root " +
System.currentTimeMillis() + "\n");
- journalFile.getChannel().force(false);
- persistedHead.set(after);
- }
- } catch (Exception e) {
- propagateIfInstanceOf(e, IOException.class);
- propagate(e);
+ private void doFlush(Flusher flusher) throws IOException {
+ if (journalFile == null) {
+ LOG.debug("No journal file available, skipping flush");
+ return;
+ }
+ RecordId before = persistedHead.get();
+ RecordId after = getHead();
+ if (after.equals(before)) {
+ LOG.debug("Head state did not change, skipping flush");
+ return;
}
+ flusher.flush();
+ LOG.debug("TarMK journal update {} -> {}", before, after);
+ journalFile.writeBytes(after.toString10() + " root " +
System.currentTimeMillis() + "\n");
+ journalFile.getChannel().force(false);
+ persistedHead.set(after);
}
@Nonnull