You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-issues@jackrabbit.apache.org by "Chetan Mehrotra (JIRA)" <ji...@apache.org> on 2014/08/18 08:29:18 UTC

[jira] [Created] (OAK-2039) SegmentNodeStore might not create a checkpoint

Chetan Mehrotra created OAK-2039:
------------------------------------

             Summary: SegmentNodeStore might not create a checkpoint
                 Key: OAK-2039
                 URL: https://issues.apache.org/jira/browse/OAK-2039
             Project: Jackrabbit Oak
          Issue Type: Bug
          Components: segmentmk
            Reporter: Chetan Mehrotra
            Priority: Minor


As per [~edivad] in the {{SegmentNodeStore.checkpoint(long)}} the invocation might return a checkpoint even though it has not been created

Starting from 

{code:java|title=AsyncIndexUpdate.java#235}
// there are some recent changes, so let's create a new checkpoint
String afterCheckpoint = store.checkpoint(lifetime);
NodeState after = store.retrieve(afterCheckpoint);
if (after == null) {
    log.warn("Unable to retrieve newly created checkpoint {},"
            + " skipping the {} index update", afterCheckpoint, name);
    return;
}

String checkpointToRelease = afterCheckpoint;
try {
    updateIndex(before, beforeCheckpoint, after, afterCheckpoint);

    // the update succeeded, i.e. it no longer fails
{code}

and then

{code:java|title=SegmentNodeStore.java#205}
public synchronized String checkpoint(long lifetime) {
    checkArgument(lifetime > 0);
    String name = UUID.randomUUID().toString();
    long now = System.currentTimeMillis();

    // try 5 times
    for (int i = 0; i < 5; i++) {
        if (commitSemaphore.tryAcquire()) { 
            try {
                refreshHead();

                SegmentNodeState state = head.get();
                SegmentNodeBuilder builder = state.builder();

                NodeBuilder checkpoints = builder.child("checkpoints");
                for (String n : checkpoints.getChildNodeNames()) {
                    NodeBuilder cp = checkpoints.getChildNode(n);
                    PropertyState ts = cp.getProperty("timestamp");
                    if (ts == null
                            || ts.getType() != Type.LONG
                            || now > ts.getValue(Type.LONG)) {
                        cp.remove();
                    }
                }

                NodeBuilder cp = checkpoints.child(name);
                cp.setProperty("timestamp",  now + lifetime);
                cp.setChildNode(ROOT, state.getChildNode(ROOT));

                SegmentNodeState newState = builder.getNodeState();
                if (store.setHead(state, newState)) {
                    refreshHead();
                    return name;
                }

            } finally {
                commitSemaphore.release();
            }
        }
    }

    return name;
}
{code}

we can see that it always return a checkpoint name even if it fails to create it (as by {{@Nonnull}} contract I would say). But if it fails to acquire lock for 5 times (no sleep in the meanwhile?) it does it silently and thus return a checkpoint which is not valid.

This might cause indexing to not work properly as it relies on the fact that it can access previous version of content through the returned checkpoint



--
This message was sent by Atlassian JIRA
(v6.2#6252)