Package org.locationtech.geogig.web.api.commands

Source Code of org.locationtech.geogig.web.api.commands.PushManager

/* Copyright (c) 2013-2014 Boundless and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/org/documents/edl-v10.html
*
* Contributors:
* Gabriel Roldan (Boundless) - initial implementation
*/
package org.locationtech.geogig.web.api.commands;

import static com.google.common.base.Preconditions.checkState;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import org.locationtech.geogig.api.GeoGIG;
import org.locationtech.geogig.api.GeogigTransaction;
import org.locationtech.geogig.api.ObjectId;
import org.locationtech.geogig.api.Ref;
import org.locationtech.geogig.api.SymRef;
import org.locationtech.geogig.api.plumbing.RefParse;
import org.locationtech.geogig.api.plumbing.ResolveTreeish;
import org.locationtech.geogig.api.plumbing.TransactionBegin;
import org.locationtech.geogig.api.plumbing.UpdateRef;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Optional;
import com.google.common.base.Throwables;

/**
* Provides a safety net for remote pushes. This class keeps track of the IP addresses of remotes
* that have pushed contents to this repository. If every object is successfully transfered, a
* message will be sent to the PushManager to update the local references as indicated by the
* remote.
*/
public class PushManager {

    private static final Logger LOGGER = LoggerFactory.getLogger(PushManager.class);

    private Set<String> incomingIPs;

    private static PushManager instance = new PushManager();

    private PushManager() {
        incomingIPs = Collections.synchronizedSet(new HashSet<String>());
    }

    /**
     * @return the singleton instance of the {@code PushManager}
     */
    public static PushManager get() {
        return instance;
    }

    /**
     * Begins tracking incoming objects from the specified ip address.
     *
     * @param ipAddress the remote machine that is pushing objects
     */
    public void connectionBegin(String ipAddress) {
        if (incomingIPs.contains(ipAddress)) {
            incomingIPs.remove(ipAddress);
        }
        if (incomingIPs.size() > 0) {
            // Fail?
        }
        incomingIPs.add(ipAddress);
    }

    /**
     * This is called when the machine at the specified ip address is finished pushing objects to
     * the server. This causes the ref given by {@code refSpec} to be updated to point to the given
     * {@code newCommit} object id, as well as the {@link Ref#WORK_HEAD WORK_HEAD} and
     * {@link Ref#STAGE_HEAD STAGE_HEAD} refs if {@code refSpec} is the current branch.
     *
     * @param geogig the geogig of the local repository
     * @param ipAddress the remote machine that is pushing objects
     */
    public void connectionSucceeded(final GeoGIG geogig, final String ipAddress,
            final String refspec, final ObjectId newCommit) {

        if (!incomingIPs.remove(ipAddress)) {// remove and check for existence in one shot
            throw new RuntimeException("Tried to end a connection that didn't exist.");
        }

        // Do not use the geogig instance after this, but the tx one!
        GeogigTransaction tx = geogig.command(TransactionBegin.class).call();
        try {
            Optional<Ref> oldRef = tx.command(RefParse.class).setName(refspec).call();
            Optional<Ref> headRef = tx.command(RefParse.class).setName(Ref.HEAD).call();
            String refName = refspec;
            if (oldRef.isPresent()) {
                if (oldRef.get().getObjectId().equals(newCommit)) {
                    LOGGER.info("ref '{}' -> {} not updated, got same id", refName, newCommit);
                    return;
                }
                LOGGER.info("Updating ref '{}'[{}] -> {}", refName, oldRef.get().getObjectId(),
                        newCommit);
                refName = oldRef.get().getName();
            } else {
                LOGGER.info("Creating new ref '{}' -> {}", refName, newCommit);
            }
            if (headRef.isPresent() && headRef.get() instanceof SymRef) {
                if (((SymRef) headRef.get()).getTarget().equals(refName)) {
                    Optional<ObjectId> commitTreeId = tx.command(ResolveTreeish.class)
                            .setTreeish(newCommit).call();
                    checkState(commitTreeId.isPresent(), "Commit %s not found", newCommit);

                    tx.command(UpdateRef.class).setName(Ref.WORK_HEAD)
                            .setNewValue(commitTreeId.get()).call();
                    tx.command(UpdateRef.class).setName(Ref.STAGE_HEAD)
                            .setNewValue(commitTreeId.get()).call();
                }
            }
            tx.command(UpdateRef.class).setName(refName).setNewValue(newCommit).call();

            tx.commit();
        } catch (Exception e) {
            tx.abort();
            throw Throwables.propagate(e);
        }
    }
}
TOP

Related Classes of org.locationtech.geogig.web.api.commands.PushManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.