diff options
author | Shawn Pearce <spearce@spearce.org> | 2016-01-12 21:55:43 -0800 |
---|---|---|
committer | Shawn Pearce <spearce@spearce.org> | 2016-01-19 23:05:28 -0800 |
commit | da5ef91ad0c7021142f184bf24abafc0895e3446 (patch) | |
tree | 14e8fc3ebb8993108f27f718c51ae6ba553bbd10 | |
parent | 1f9d2050434f7ad25e06f44c1842dd365d6ec539 (diff) | |
download | jgit-da5ef91ad0c7021142f184bf24abafc0895e3446.tar.gz jgit-da5ef91ad0c7021142f184bf24abafc0895e3446.zip |
daemon: Add --ketch=LEADER flag
Experimental flag to turn on the KetchLeader within this daemon JVM.
This is a manually elected leader process, set from the command line.
Remote followers for each repository are configured per-repository
using remote sections with ketch-type = FULL. For example:
Manually elected leader's $GIT_DIR/config:
[ketch]
name = A
[remote "A"]
ketch-type = FULL
[remote "B"]
url = git://127.0.0.1:9421/sample.git
ketch-type = FULL
[remote "C"]
url = git://127.0.0.1:9422/sample.git
ketch-type = FULL
Replica B and C daemons:
git daemon \
--export-all \
--enable=receive-pack \
--listen=127.0.0.1 --port=9421 \
--base-path=$HOME/ketch_test/follower_one \
$HOME/ketch_test/follower_one &
git daemon \
--export-all \
--enable=receive-pack \
--listen=127.0.0.1 --port=9422 \
--base-path=$HOME/ketch_test/follower_two \
$HOME/ketch_test/follower_two &
Change-Id: I165f85970a77e16b5263115290d685d8a00566f5
5 files changed, 59 insertions, 1 deletions
diff --git a/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF b/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF index 9dc6aea16f..bc9205c7ce 100644 --- a/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF @@ -19,6 +19,7 @@ Import-Package: org.apache.commons.compress.archivers;version="[1.3,2.0)", org.eclipse.jgit.dircache;version="[4.2.0,4.3.0)", org.eclipse.jgit.errors;version="[4.2.0,4.3.0)", org.eclipse.jgit.gitrepo;version="[4.2.0,4.3.0)", + org.eclipse.jgit.internal.ketch;version="[4.2.0,4.3.0)", org.eclipse.jgit.internal.storage.file;version="[4.2.0,4.3.0)", org.eclipse.jgit.internal.storage.pack;version="[4.2.0,4.3.0)", org.eclipse.jgit.internal.storage.reftree;version="[4.2.0,4.3.0)", diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Daemon.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Daemon.java index 04182d6dbe..03f3fac0b6 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Daemon.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Daemon.java @@ -45,18 +45,29 @@ package org.eclipse.jgit.pgm; import java.io.File; import java.net.InetSocketAddress; +import java.net.URISyntaxException; import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executors; +import org.eclipse.jgit.internal.ketch.KetchLeader; +import org.eclipse.jgit.internal.ketch.KetchLeaderCache; +import org.eclipse.jgit.internal.ketch.KetchPreReceive; +import org.eclipse.jgit.internal.ketch.KetchSystem; +import org.eclipse.jgit.internal.ketch.KetchText; +import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.pgm.internal.CLIText; import org.eclipse.jgit.storage.file.FileBasedConfig; import org.eclipse.jgit.storage.file.WindowCacheConfig; import org.eclipse.jgit.storage.pack.PackConfig; import org.eclipse.jgit.transport.DaemonClient; import org.eclipse.jgit.transport.DaemonService; +import org.eclipse.jgit.transport.ReceivePack; import org.eclipse.jgit.transport.resolver.FileResolver; +import org.eclipse.jgit.transport.resolver.ReceivePackFactory; +import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException; +import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException; import org.eclipse.jgit.util.FS; import org.kohsuke.args4j.Argument; import org.kohsuke.args4j.Option; @@ -90,6 +101,13 @@ class Daemon extends TextBuiltin { @Option(name = "--export-all", usage = "usage_exportWithoutGitDaemonExportOk") boolean exportAll; + @Option(name = "--ketch") + KetchServerType ketchServerType; + + enum KetchServerType { + LEADER; + } + @Argument(required = true, metaVar = "metaVar_directory", usage = "usage_directoriesToExport") final List<File> directory = new ArrayList<File>(); @@ -146,7 +164,9 @@ class Daemon extends TextBuiltin { service(d, n).setOverridable(true); for (final String n : forbidOverride) service(d, n).setOverridable(false); - + if (ketchServerType == KetchServerType.LEADER) { + startKetchLeader(d); + } d.start(); outw.println(MessageFormat.format(CLIText.get().listeningOn, d.getAddress())); } @@ -159,4 +179,29 @@ class Daemon extends TextBuiltin { throw die(MessageFormat.format(CLIText.get().serviceNotSupported, n)); return svc; } + + private void startKetchLeader(org.eclipse.jgit.transport.Daemon daemon) { + KetchSystem system = new KetchSystem(); + final KetchLeaderCache leaders = new KetchLeaderCache(system); + final ReceivePackFactory<DaemonClient> factory; + + factory = daemon.getReceivePackFactory(); + daemon.setReceivePackFactory(new ReceivePackFactory<DaemonClient>() { + @Override + public ReceivePack create(DaemonClient req, Repository repo) + throws ServiceNotEnabledException, + ServiceNotAuthorizedException { + ReceivePack rp = factory.create(req, repo); + KetchLeader leader; + try { + leader = leaders.get(repo); + } catch (URISyntaxException err) { + throw new ServiceNotEnabledException( + KetchText.get().invalidFollowerUri, err); + } + rp.setPreReceiveHook(new KetchPreReceive(leader)); + return rp; + } + }); + } }
\ No newline at end of file diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/ketch/KetchText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/ketch/KetchText.properties index 3817fb93cc..1fbb7cb3b5 100644 --- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/ketch/KetchText.properties +++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/ketch/KetchText.properties @@ -1,6 +1,7 @@ accepted=accepted. cannotFetchFromLocalReplica=cannot fetch from LocalReplica failed=failed! +invalidFollowerUri=invalid follower URI leaderFailedToStore=leader failed to store localReplicaRequired=LocalReplica instance is required mismatchedTxnNamespace=mismatched txnNamespace; expected {0} found {1} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/KetchText.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/KetchText.java index da85c0112d..b6c3bc92c5 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/KetchText.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/KetchText.java @@ -57,6 +57,7 @@ public class KetchText extends TranslationBundle { /***/ public String accepted; /***/ public String cannotFetchFromLocalReplica; /***/ public String failed; + /***/ public String invalidFollowerUri; /***/ public String leaderFailedToStore; /***/ public String localReplicaRequired; /***/ public String mismatchedTxnNamespace; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/Daemon.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/Daemon.java index d9e0b937e8..2593ba556d 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/Daemon.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/Daemon.java @@ -256,6 +256,16 @@ public class Daemon { } /** + * Get the factory used to construct per-request ReceivePack. + * + * @return the factory. + * @since 4.2 + */ + public ReceivePackFactory<DaemonClient> getReceivePackFactory() { + return receivePackFactory; + } + + /** * Set the factory to construct and configure per-request ReceivePack. * * @param factory |