Merge branch 'stable-2.11'

* stable-2.11:
  Set version to 2.11.2 in dev-plugins.txt
  Release notes for Gerrit 2.11.2
  Bind OnlineReindexer.Factory in LuceneIndexModule
  Add ssh command to activate the latest index
  Add ssh command to restart online indexer
  PluginAPI: Don't convert to String in RestApi.get() method

Change-Id: I907e665b20568fce8563bf9e22a7a0ffc96fc847
This commit is contained in:
David Pursehouse 2015-07-14 11:33:11 +09:00
commit 03bc9996c7
16 changed files with 507 additions and 22 deletions

View File

@ -0,0 +1,32 @@
= gerrit index activate
== NAME
gerrit index activate - Activate the latest index version available
== SYNOPSIS
--
'ssh' -p @SSH_PORT@ @SSH_HOST@ 'gerrit index activate'
--
== DESCRIPTION
Gerrit supports online index schema upgrades. When starting Gerrit for the first
time after an upgrade that requires an index schema upgrade, the online indexer
will be started. If the schema upgrade is a success, the new index will be
activated and if it fails, a statement in the logs will be printed with the
number of successfully/failed indexed changes.
This command allows to activate the latest index even if there were some
failures.
== ACCESS
Caller must be a member of the privileged 'Administrators' group.
== SCRIPTING
This command is intended to be used in scripts.
GERRIT
------
Part of link:index.html[Gerrit Code Review]
SEARCHBOX
---------

View File

@ -0,0 +1,33 @@
= gerrit index start
== NAME
gerrit index start - Start the online indexer
== SYNOPSIS
--
'ssh' -p @SSH_PORT@ @SSH_HOST@ 'gerrit index start'
--
== DESCRIPTION
Gerrit supports online index schema upgrades. When starting Gerrit for the first
time after an upgrade that requires an index schema upgrade, the online indexer
will be started. If the schema upgrade is a success, the new index will be
activated and if it fails, a statement in the logs will be printed with the
number of successfully/failed indexed changes.
This command allows restarting the online indexer without having to restart
Gerrit. This command will not start the indexer if it is already running or if
the active index is the latest.
== ACCESS
Caller must be a member of the privileged 'Administrators' group.
== SCRIPTING
This command is intended to be used in scripts.
GERRIT
------
Part of link:index.html[Gerrit Code Review]
SEARCHBOX
---------

View File

@ -120,6 +120,12 @@ link:cmd-gc.html[gerrit gc]::
link:cmd-gsql.html[gerrit gsql]::
Administrative interface to active database.
link:cmd-index-index.html[gerrit index activate]::
Activate the latest index version available.
link:cmd-index-start.html[gerrit index start]::
Start the online indexer.
link:cmd-logging-ls-level.html[gerrit logging ls-level]::
List loggers and their logging level.

View File

@ -0,0 +1,97 @@
Release notes for Gerrit 2.11.2
===============================
Gerrit 2.11.2 is now available:
link:https://gerrit-releases.storage.googleapis.com/gerrit-2.11.2.war[
https://gerrit-releases.storage.googleapis.com/gerrit-2.11.2.war]
Gerrit 2.11.2 includes the bug fixes done with
link:ReleaseNotes-2.10.6.html[Gerrit 2.10.6]. These bug fixes are *not* listed
in these release notes.
There are no schema changes from link:ReleaseNotes-2.11.1.html[2.11.1].
New Features
------------
New SSH commands:
* link:https://gerrit-documentation.storage.googleapis.com/Documentation/2.11.2/cmd-index-start.html[
`index start`]
+
Allows to restart the online indexer without restarting the Gerrit server.
* link:https://gerrit-documentation.storage.googleapis.com/Documentation/2.11.2/cmd-index-activate.html[
`index activate`]
+
Allows to activate the latest index version even if the indexing encountered
problems.
Bug Fixes
---------
* link:link:https://code.google.com/p/gerrit/issues/detail?id=3460[Issue 3460]:
Fix regression in the search box auto-suggestions.
+
A change introduced in version 2.11 caused the auto-suggestions to not work
any more.
* link:https://code.google.com/p/gerrit/issues/detail?id=3355[Issue 3355]:
Fix corruption of database when deleting draft change ref fails.
* link:https://code.google.com/p/gerrit/issues/detail?id=3426[Issue 3426]:
Fix regression in the `%base` option.
+
A change introduced in version 2.11 caused the `%base` option to not work
any more, meaning it was not possible to push a commit, which is already merged
into a branch, for review to another branch of the same project.
* link:https://bugs.eclipse.org/bugs/show_bug.cgi?id=468024[JGit bug 468024]:
Fix data loss if a pack is pushed to a JGit based server and gc runs
concurrently on the same repository.
* link:https://code.google.com/p/gerrit/issues/detail?id=3371[Issue 3371]:
Fix wrong date/time for commits in `refs/meta/config` branch.
+
When the `refs/meta/config` branch was modified using the PutConfig REST endpoint
(e.g. when changing the project configuration in the web UI) the commit date/time
was wrong. Instead of the actual date/time the date/time of the last Gerrit server
start was used.
* Fix NullPointerException in the 'related changes' REST API endpoint.
* Make sure `/a` is not in the project name for git-over-http requests.
+
The `/a` prefix is used to trigger authentication but was not removed from the
request. Therefore, it was included in the project name and hence the project
wasn't found when performing, for example `git fetch http://server/a/project`.
* Fix disabling of git ssh commands.
+
The ssh commands were available even when ssh commands were disabled.
* Fix native string handling in Plugin API.
+
The results of REST API calls were incorrectly being converted from NativeString
to String when called from Javascript.
* link:https://code.google.com/p/gerrit/issues/detail?id=3440[Issue 3440]:
Include prettify source files in the documentation.
+
The prettify source files were being loaded from `cdnjs.cloudflare.com`, which
may cause trouble if the Gerrit instance is behind a firewall on a machine not
allowed to access the Internet at large.
+
Now those files are bundled with the documentation.
* Print proper name for project indexer tasks in `show-queue` command.
* Print proper name for reindex after update tasks in `show-queue` command.
Updates
-------
* Update JGit to 4.0.1.201506240215-r.

View File

@ -4,6 +4,7 @@ Gerrit Code Review - Release Notes
[[2_11]]
Version 2.11.x
--------------
* link:ReleaseNotes-2.11.2.html[2.11.2]
* link:ReleaseNotes-2.11.1.html[2.11.1]
* link:ReleaseNotes-2.11.html[2.11]

View File

@ -166,6 +166,14 @@ public class ActionContext extends JavaScriptObject {
api.get(wrap(cb));
}
/**
* The same as {@link #get(RestApi, JavaScriptObject)} but without converting
* a {@link NativeString} result to String.
*/
static final void getRaw(RestApi api, final JavaScriptObject cb) {
api.get(wrapRaw(cb));
}
static final void post(RestApi api, JavaScriptObject in, JavaScriptObject cb) {
if (NativeString.is(in)) {
post(api, ((NativeString) in).asString(), cb);
@ -174,14 +182,42 @@ public class ActionContext extends JavaScriptObject {
}
}
/**
* The same as {@link #post(RestApi, JavaScriptObject, JavaScriptObject)} but
* without converting a {@link NativeString} result to String.
*/
static final void postRaw(RestApi api, JavaScriptObject in, JavaScriptObject cb) {
if (NativeString.is(in)) {
postRaw(api, ((NativeString) in).asString(), cb);
} else {
api.post(in, wrapRaw(cb));
}
}
static final void post(RestApi api, String in, JavaScriptObject cb) {
api.post(in, wrap(cb));
}
/**
* The same as {@link #post(RestApi, String, JavaScriptObject)} but without
* converting a {@link NativeString} result to String.
*/
static final void postRaw(RestApi api, String in, JavaScriptObject cb) {
api.post(in, wrapRaw(cb));
}
static final void put(RestApi api, JavaScriptObject cb) {
api.put(wrap(cb));
}
/**
* The same as {@link #put(RestApi, JavaScriptObject)} but without converting
* a {@link NativeString} result to String.
*/
static final void putRaw(RestApi api, JavaScriptObject cb) {
api.put(wrapRaw(cb));
}
static final void put(RestApi api, JavaScriptObject in, JavaScriptObject cb) {
if (NativeString.is(in)) {
put(api, ((NativeString) in).asString(), cb);
@ -190,14 +226,42 @@ public class ActionContext extends JavaScriptObject {
}
}
/**
* The same as {@link #put(RestApi, JavaScriptObject, JavaScriptObject)} but
* without converting a {@link NativeString} result to String.
*/
static final void putRaw(RestApi api, JavaScriptObject in, JavaScriptObject cb) {
if (NativeString.is(in)) {
putRaw(api, ((NativeString) in).asString(), cb);
} else {
api.put(in, wrapRaw(cb));
}
}
static final void put(RestApi api, String in, JavaScriptObject cb) {
api.put(in, wrap(cb));
}
/**
* The same as {@link #put(RestApi, String, JavaScriptObject)} but without
* converting a {@link NativeString} result to String.
*/
static final void putRaw(RestApi api, String in, JavaScriptObject cb) {
api.put(in, wrapRaw(cb));
}
static final void delete(RestApi api, JavaScriptObject cb) {
api.delete(wrap(cb));
}
/**
* The same as {@link #delete(RestApi, JavaScriptObject)} but without
* converting a {@link NativeString} result to String.
*/
static final void deleteRaw(RestApi api, JavaScriptObject cb) {
api.delete(wrapRaw(cb));
}
private static GerritCallback<JavaScriptObject> wrap(final JavaScriptObject cb) {
return new GerritCallback<JavaScriptObject>() {
@Override
@ -211,4 +275,13 @@ public class ActionContext extends JavaScriptObject {
}
};
}
private static GerritCallback<JavaScriptObject> wrapRaw(final JavaScriptObject cb) {
return new GerritCallback<JavaScriptObject>() {
@Override
public void onSuccess(JavaScriptObject result) {
ApiGlue.invoke(cb, result);
}
};
}
}

View File

@ -102,6 +102,12 @@ public class ApiGlue {
Lcom/google/gwt/core/client/JavaScriptObject;)
(this._api(u), b);
},
get_raw: function(u,b) {
@com.google.gerrit.client.api.ActionContext::getRaw(
Lcom/google/gerrit/client/rpc/RestApi;
Lcom/google/gwt/core/client/JavaScriptObject;)
(this._api(u), b);
},
post: function(u,i,b) {
if (typeof i == 'string') {
@com.google.gerrit.client.api.ActionContext::post(
@ -117,6 +123,21 @@ public class ApiGlue {
(this._api(u), i, b);
}
},
post_raw: function(u,i,b) {
if (typeof i == 'string') {
@com.google.gerrit.client.api.ActionContext::postRaw(
Lcom/google/gerrit/client/rpc/RestApi;
Ljava/lang/String;
Lcom/google/gwt/core/client/JavaScriptObject;)
(this._api(u), i, b);
} else {
@com.google.gerrit.client.api.ActionContext::postRaw(
Lcom/google/gerrit/client/rpc/RestApi;
Lcom/google/gwt/core/client/JavaScriptObject;
Lcom/google/gwt/core/client/JavaScriptObject;)
(this._api(u), i, b);
}
},
put: function(u,i,b) {
if (b) {
if (typeof i == 'string') {
@ -139,6 +160,28 @@ public class ApiGlue {
(this._api(u), i);
}
},
put_raw: function(u,i,b) {
if (b) {
if (typeof i == 'string') {
@com.google.gerrit.client.api.ActionContext::putRaw(
Lcom/google/gerrit/client/rpc/RestApi;
Ljava/lang/String;
Lcom/google/gwt/core/client/JavaScriptObject;)
(this._api(u), i, b);
} else {
@com.google.gerrit.client.api.ActionContext::putRaw(
Lcom/google/gerrit/client/rpc/RestApi;
Lcom/google/gwt/core/client/JavaScriptObject;
Lcom/google/gwt/core/client/JavaScriptObject;)
(this._api(u), i, b);
}
} else {
@com.google.gerrit.client.api.ActionContext::putRaw(
Lcom/google/gerrit/client/rpc/RestApi;
Lcom/google/gwt/core/client/JavaScriptObject;)
(this._api(u), i);
}
},
'delete': function(u,b) {
@com.google.gerrit.client.api.ActionContext::delete(
Lcom/google/gerrit/client/rpc/RestApi;
@ -151,6 +194,12 @@ public class ApiGlue {
Lcom/google/gwt/core/client/JavaScriptObject;)
(this._api(u), b);
},
del_raw: function(u,b) {
@com.google.gerrit.client.api.ActionContext::deleteRaw(
Lcom/google/gerrit/client/rpc/RestApi;
Lcom/google/gwt/core/client/JavaScriptObject;)
(this._api(u), b);
},
};
}-*/;

View File

@ -48,6 +48,7 @@ public class LuceneIndexModule extends LifecycleModule {
@Override
protected void configure() {
factory(LuceneChangeIndex.Factory.class);
factory(OnlineReindexer.Factory.class);
install(new IndexModule(threads));
if (singleVersion == null && base == null) {
install(new MultiVersionModule());
@ -65,7 +66,6 @@ public class LuceneIndexModule extends LifecycleModule {
private static class MultiVersionModule extends LifecycleModule {
@Override
public void configure() {
factory(OnlineReindexer.Factory.class);
listener().to(LuceneVersionManager.class);
}
}

View File

@ -46,7 +46,7 @@ import java.util.List;
import java.util.TreeMap;
@Singleton
class LuceneVersionManager implements LifecycleListener {
public class LuceneVersionManager implements LifecycleListener {
private static final Logger log = LoggerFactory
.getLogger(LuceneVersionManager.class);
@ -95,6 +95,7 @@ class LuceneVersionManager implements LifecycleListener {
private final IndexCollection indexes;
private final OnlineReindexer.Factory reindexerFactory;
private final boolean onlineUpgrade;
private OnlineReindexer reindexer;
@Inject
LuceneVersionManager(
@ -165,7 +166,53 @@ class LuceneVersionManager implements LifecycleListener {
int latest = write.get(0).version;
if (onlineUpgrade && latest != search.version) {
reindexerFactory.create(latest).start();
reindexer = reindexerFactory.create(latest);
reindexer.start();
}
}
/**
* Start the online reindexer if the current index is not already the latest.
*
* @return true if started, otherwise false.
* @throws ReindexerAlreadyRunningException
*/
public synchronized boolean startReindexer()
throws ReindexerAlreadyRunningException {
validateReindexerNotRunning();
if (!isCurrentIndexVersionLatest()) {
reindexer.start();
return true;
}
return false;
}
/**
* Activate the latest index if the current index is not already the latest.
*
* @return true if index was activate, otherwise false.
* @throws ReindexerAlreadyRunningException
*/
public synchronized boolean activateLatestIndex()
throws ReindexerAlreadyRunningException {
validateReindexerNotRunning();
if (!isCurrentIndexVersionLatest()) {
reindexer.activateIndex();
return true;
}
return false;
}
private boolean isCurrentIndexVersionLatest() {
return reindexer == null
|| reindexer.getVersion() == indexes.getSearchIndex().getSchema()
.getVersion();
}
private void validateReindexerNotRunning()
throws ReindexerAlreadyRunningException {
if (reindexer != null && reindexer.isRunning()) {
throw new ReindexerAlreadyRunningException();
}
}

View File

@ -29,6 +29,7 @@ import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
public class OnlineReindexer {
private static final Logger log = LoggerFactory
@ -42,6 +43,8 @@ public class OnlineReindexer {
private final SiteIndexer batchIndexer;
private final ProjectCache projectCache;
private final int version;
private ChangeIndex index;
private final AtomicBoolean running = new AtomicBoolean();
@Inject
OnlineReindexer(
@ -56,15 +59,29 @@ public class OnlineReindexer {
}
public void start() {
Thread t = new Thread() {
@Override
public void run() {
reindex();
}
};
t.setName(String.format("Reindex v%d-v%d",
version(indexes.getSearchIndex()), version));
t.start();
if (running.compareAndSet(false, true)) {
Thread t = new Thread() {
@Override
public void run() {
try {
reindex();
} finally {
running.set(false);
}
}
};
t.setName(String.format("Reindex v%d-v%d",
version(indexes.getSearchIndex()), version));
t.start();
}
}
public boolean isRunning() {
return running.get();
}
public int getVersion() {
return version;
}
private static int version(ChangeIndex i) {
@ -72,7 +89,7 @@ public class OnlineReindexer {
}
private void reindex() {
ChangeIndex index = checkNotNull(indexes.getWriteIndex(version),
index = checkNotNull(indexes.getWriteIndex(version),
"not an active write schema version: %s", version);
log.info("Starting online reindex from schema version {} to {}",
version(indexes.getSearchIndex()), version(index));
@ -84,9 +101,13 @@ public class OnlineReindexer {
version(index), result.doneCount(), result.failedCount());
return;
}
log.info("Reindex to version {} complete", version(index));
activateIndex();
}
void activateIndex() {
indexes.setSearchIndex(index);
log.info("Reindex complete, using schema version {}", version(index));
log.info("Using schema version {}", version(index));
try {
index.markReady(true);
} catch (IOException e) {

View File

@ -0,0 +1,24 @@
// Copyright (C) 2015 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.lucene;
public class ReindexerAlreadyRunningException extends Exception {
private static final long serialVersionUID = 1L;
public ReindexerAlreadyRunningException() {
super("Reindexer is already running.");
}
}

View File

@ -110,7 +110,7 @@ public class RestApi {
}
private static native void get(String p, JavaScriptObject r)
/*-{ $wnd.Gerrit.get(p, r) }-*/;
/*-{ $wnd.Gerrit.get_raw(p, r) }-*/;
public <T extends JavaScriptObject>
void put(AsyncCallback<T> cb) {
@ -118,7 +118,7 @@ public class RestApi {
}
private static native void put(String p, JavaScriptObject r)
/*-{ $wnd.Gerrit.put(p, r) }-*/;
/*-{ $wnd.Gerrit.put_raw(p, r) }-*/;
public <T extends JavaScriptObject>
void put(String content, AsyncCallback<T> cb) {
@ -127,7 +127,7 @@ public class RestApi {
private static native
void put(String p, String c, JavaScriptObject r)
/*-{ $wnd.Gerrit.put(p, c, r) }-*/;
/*-{ $wnd.Gerrit.put_raw(p, c, r) }-*/;
public <T extends JavaScriptObject>
void put(JavaScriptObject content, AsyncCallback<T> cb) {
@ -136,7 +136,7 @@ public class RestApi {
private static native
void put(String p, JavaScriptObject c, JavaScriptObject r)
/*-{ $wnd.Gerrit.put(p, c, r) }-*/;
/*-{ $wnd.Gerrit.put_raw(p, c, r) }-*/;
public <T extends JavaScriptObject>
void post(String content, AsyncCallback<T> cb) {
@ -145,7 +145,7 @@ public class RestApi {
private static native
void post(String p, String c, JavaScriptObject r)
/*-{ $wnd.Gerrit.post(p, c, r) }-*/;
/*-{ $wnd.Gerrit.post_raw(p, c, r) }-*/;
public <T extends JavaScriptObject>
void post(JavaScriptObject content, AsyncCallback<T> cb) {
@ -154,14 +154,14 @@ public class RestApi {
private static native
void post(String p, JavaScriptObject c, JavaScriptObject r)
/*-{ $wnd.Gerrit.post(p, c, r) }-*/;
/*-{ $wnd.Gerrit.post_raw(p, c, r) }-*/;
public void delete(AsyncCallback<NoContent> cb) {
delete(path(), wrap(cb));
}
private static native void delete(String p, JavaScriptObject r)
/*-{ $wnd.Gerrit.del(p, r) }-*/;
/*-{ $wnd.Gerrit.del_raw(p, r) }-*/;
private static native <T extends JavaScriptObject>
JavaScriptObject wrap(AsyncCallback<T> b) /*-{

View File

@ -8,6 +8,7 @@ java_library(
'//gerrit-cache-h2:cache-h2',
'//gerrit-common:annotations',
'//gerrit-common:server',
'//gerrit-lucene:lucene',
'//gerrit-patch-jgit:server',
'//gerrit-reviewdb:server',
'//gerrit-server:server',

View File

@ -36,6 +36,7 @@ public class DefaultCommandModule extends CommandModule {
protected void configure() {
final CommandName git = Commands.named("git");
final CommandName gerrit = Commands.named("gerrit");
CommandName index = Commands.named(gerrit, "index");
final CommandName logging = Commands.named(gerrit, "logging");
final CommandName plugin = Commands.named(gerrit, "plugin");
final CommandName testSubmit = Commands.named(gerrit, "test-submit");
@ -56,8 +57,12 @@ public class DefaultCommandModule extends CommandModule {
command(gerrit, StreamEvents.class);
command(gerrit, VersionCommand.class);
command(gerrit, GarbageCollectionCommand.class);
command(gerrit, "plugin").toProvider(new DispatchCommandProvider(plugin));
command(index).toProvider(new DispatchCommandProvider(index));
command(index, IndexActivateCommand.class);
command(index, IndexStartCommand.class);
command(gerrit, "plugin").toProvider(new DispatchCommandProvider(plugin));
command(plugin, PluginLsCommand.class);
command(plugin, PluginEnableCommand.class);
command(plugin, PluginInstallCommand.class);

View File

@ -0,0 +1,49 @@
// Copyright (C) 2015 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.sshd.commands;
import static com.google.gerrit.sshd.CommandMetaData.Mode.MASTER;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.extensions.annotations.RequiresCapability;
import com.google.gerrit.lucene.LuceneVersionManager;
import com.google.gerrit.lucene.ReindexerAlreadyRunningException;
import com.google.gerrit.sshd.CommandMetaData;
import com.google.gerrit.sshd.SshCommand;
import com.google.inject.Inject;
@RequiresCapability(GlobalCapability.ADMINISTRATE_SERVER)
@CommandMetaData(name = "activate",
description = "Activate the latest index version available",
runsAt = MASTER)
public class IndexActivateCommand extends SshCommand {
@Inject
private LuceneVersionManager luceneVersionManager;
@Override
protected void run() throws UnloggedFailure {
try {
if (luceneVersionManager.activateLatestIndex()) {
stdout.println("Activated latest index version");
} else {
stdout.println("Not activating index, already using latest version");
}
} catch (ReindexerAlreadyRunningException e) {
throw new UnloggedFailure("Failed to activate latest index: "
+ e.getMessage());
}
}
}

View File

@ -0,0 +1,47 @@
// Copyright (C) 2015 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.sshd.commands;
import static com.google.gerrit.sshd.CommandMetaData.Mode.MASTER;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.extensions.annotations.RequiresCapability;
import com.google.gerrit.lucene.LuceneVersionManager;
import com.google.gerrit.lucene.ReindexerAlreadyRunningException;
import com.google.gerrit.sshd.CommandMetaData;
import com.google.gerrit.sshd.SshCommand;
import com.google.inject.Inject;
@RequiresCapability(GlobalCapability.ADMINISTRATE_SERVER)
@CommandMetaData(name = "start", description = "Start the online reindexer",
runsAt = MASTER)
public class IndexStartCommand extends SshCommand {
@Inject
private LuceneVersionManager luceneVersionManager;
@Override
protected void run() throws UnloggedFailure {
try {
if (luceneVersionManager.startReindexer()) {
stdout.println("Reindexer started");
} else {
stdout.println("Nothing to reindex, index is already the latest version");
}
} catch (ReindexerAlreadyRunningException e) {
throw new UnloggedFailure("Failed to start reindexer: " + e.getMessage());
}
}
}