Browse Source

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
tags/v4.3.0.201603230630-rc1
Shawn Pearce 8 years ago
parent
commit
da5ef91ad0

+ 1
- 0
org.eclipse.jgit.pgm/META-INF/MANIFEST.MF View File

@@ -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)",

+ 46
- 1
org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Daemon.java View File

@@ -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;
}
});
}
}

+ 1
- 0
org.eclipse.jgit/resources/org/eclipse/jgit/internal/ketch/KetchText.properties View File

@@ -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}

+ 1
- 0
org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/KetchText.java View File

@@ -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;

+ 10
- 0
org.eclipse.jgit/src/org/eclipse/jgit/transport/Daemon.java View File

@@ -255,6 +255,16 @@ public class Daemon {
uploadPackFactory = (UploadPackFactory<DaemonClient>) UploadPackFactory.DISABLED;
}

/**
* 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.
*

Loading…
Cancel
Save