run.set(false);
try {
+ ((SshCommandFactory) sshd.getCommandFactory()).stop();
sshd.stop();
} catch (InterruptedException e) {
log.error("SSH Daemon stop interrupted", e);
private static final Logger log = LoggerFactory.getLogger(BaseCommand.class);
+ private static final int PRIVATE_STATUS = 1 << 30;
+
+ public final static int STATUS_CANCEL = PRIVATE_STATUS | 1;
+
+ public final static int STATUS_NOT_FOUND = PRIVATE_STATUS | 2;
+
+ public final static int STATUS_NOT_ADMIN = PRIVATE_STATUS | 3;
+
protected InputStream in;
protected OutputStream out;
@Override
public void destroy() {
+ log.debug("destroying " + getClass().getName());
+ session = null;
ctx = null;
}
private List<String> args = new ArrayList<String>();
private final Set<Class<? extends BaseCommand>> commands;
+ private final Map<String, DispatchCommand> dispatchers;
+ private final List<BaseCommand> instantiated;
private Map<String, Class<? extends BaseCommand>> map;
- private Map<String, BaseCommand> dispatchers;
protected DispatchCommand() {
commands = new HashSet<Class<? extends BaseCommand>>();
+ dispatchers = Maps.newHashMap();
+ instantiated = new ArrayList<BaseCommand>();
+ }
+
+ @Override
+ public void destroy() {
+ super.destroy();
+ commands.clear();
+ map = null;
+
+ for (BaseCommand command : instantiated) {
+ command.destroy();
+ }
+ for (DispatchCommand dispatcher : dispatchers.values()) {
+ dispatcher.destroy();
+ }
}
protected void registerDispatcher(UserModel user, Class<? extends DispatchCommand> cmd) {
throw new RuntimeException(MessageFormat.format("{0} must be annotated with {1}!", cmd.getName(),
CommandMetaData.class.getName()));
}
- if (dispatchers == null) {
- dispatchers = Maps.newHashMap();
- }
CommandMetaData meta = cmd.getAnnotation(CommandMetaData.class);
if (meta.admin() && !user.canAdmin()) {
CommandMetaData meta = cmd.getAnnotation(CommandMetaData.class);
map.put(meta.name(), cmd);
}
- if (dispatchers != null) {
- for (Map.Entry<String, BaseCommand> entry : dispatchers.entrySet()) {
- map.put(entry.getKey(), entry.getValue().getClass());
- }
+
+ for (Map.Entry<String, DispatchCommand> entry : dispatchers.entrySet()) {
+ map.put(entry.getKey(), entry.getValue().getClass());
}
}
return map;
BaseCommand cmd = null;
try {
cmd = c.newInstance();
+ instantiated.add(cmd);
} catch (Exception e) {
throw new UnloggedFailure(1, MessageFormat.format("Failed to instantiate {0} command", commandName));
}
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.atomic.AtomicBoolean;
import com.gitblit.utils.IdGenerator;
import com.gitblit.utils.WorkQueue;
import com.google.common.util.concurrent.Atomics;
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
/**
*
private final IGitblit gitblit;
private final ScheduledExecutorService startExecutor;
+ private final ExecutorService destroyExecutor;
public SshCommandFactory(IGitblit gitblit, IdGenerator idGenerator) {
this.gitblit = gitblit;
int threads = 2;// cfg.getInt("sshd","commandStartThreads", 2);
WorkQueue workQueue = new WorkQueue(idGenerator);
startExecutor = workQueue.createQueue(threads, "SshCommandStart");
+ destroyExecutor = Executors.newSingleThreadExecutor(
+ new ThreadFactoryBuilder()
+ .setNameFormat("SshCommandDestroy-%s")
+ .setDaemon(true)
+ .build());
+ }
+
+ public void stop() {
+ destroyExecutor.shutdownNow();
}
public RootDispatcher createRootDispatcher(SshDaemonClient client, String commandLine) {
}
private int translateExit(final int rc) {
- return rc;
- //
- // switch (rc) {
- // case BaseCommand.STATUS_NOT_ADMIN:
- // return 1;
- //
- // case BaseCommand.STATUS_CANCEL:
- // return 15 /* SIGKILL */;
- //
- // case BaseCommand.STATUS_NOT_FOUND:
- // return 127 /* POSIX not found */;
- //
- // default:
- // return rc;
- // }
+ switch (rc) {
+ case BaseCommand.STATUS_NOT_ADMIN:
+ return 1;
+
+ case BaseCommand.STATUS_CANCEL:
+ return 15 /* SIGKILL */;
+
+ case BaseCommand.STATUS_NOT_FOUND:
+ return 127 /* POSIX not found */;
+ default:
+ return rc;
+ }
}
private void log(final int rc) {
if (logged.compareAndSet(false, true)) {
- // log.onExecute(cmd, rc);
logger.info("onExecute: {} exits with: {}", cmd.getClass().getSimpleName(), rc);
}
}
Future<?> future = task.getAndSet(null);
if (future != null) {
future.cancel(true);
- // destroyExecutor.execute(new Runnable() {
- // @Override
- // public void run() {
- // onDestroy();
- // }
- // });
+ destroyExecutor.execute(new Runnable() {
+ @Override
+ public void run() {
+ onDestroy();
+ }
+ });
}
}
- @SuppressWarnings("unused")
private void onDestroy() {
synchronized (this) {
if (cmd != null) {
- // final Context old = sshScope.set(ctx);
try {
cmd.destroy();
- // log(BaseCommand.STATUS_CANCEL);
} finally {
- // ctx = null;
cmd = null;
- // sshScope.set(old);
}
}
}
protected Repository repo;
+ @Override
+ public void destroy() {
+ super.destroy();
+
+ repositoryResolver = null;
+ receivePackFactory = null;
+ uploadPackFactory = null;
+ repo = null;
+ }
+
@Override
public void start(final Environment env) {
startThread(new RepositoryCommandRunnable() {
receivePackFactory = new GitblitReceivePackFactory<SshDaemonClient>(gitblit);
}
+ @Override
+ public void destroy() {
+ super.destroy();
+
+ repositoryResolver = null;
+ receivePackFactory = null;
+ uploadPackFactory = null;
+ }
+
@Override
protected void registerCommands(UserModel user) {
registerCommand(user, Upload.class);