Skip to content

Commit 640428a

Browse files
SOLR-18083: Fix replication and other general operations in readOnly mode (#4088)
1 parent d766e9e commit 640428a

File tree

13 files changed

+62
-20
lines changed

13 files changed

+62
-20
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# See https://github.com/apache/solr/blob/main/dev-docs/changelog.adoc
2+
title: Fix operational issues with readOnly collections, such as restarting SolrNodes and replicating from the leader.
3+
type: fixed # added, changed, fixed, deprecated, removed, dependency_update, security, other
4+
authors:
5+
- name: Houston Putman
6+
nick: HoustonPutman
7+
links:
8+
- name: SOLR-18083
9+
url: https://issues.apache.org/jira/browse/SOLR-18083

solr/core/src/java/org/apache/solr/cloud/RecoveryStrategy.java

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,8 @@ private void commitOnLeader(String leaderBaseUrl, String coreName)
303303
// ureq.getParams().set(UpdateParams.OPEN_SEARCHER, onlyLeaderIndexes);
304304
// Why do we need to open searcher if "onlyLeaderIndexes"?
305305
ureq.getParams().set(UpdateParams.OPEN_SEARCHER, false);
306+
// If the leader is readOnly, do not fail since the core is already committed.
307+
ureq.getParams().set(UpdateParams.FAIL_ON_READ_ONLY, false);
306308
ureq.setAction(AbstractUpdateRequest.ACTION.COMMIT, false, true).process(client);
307309
}
308310
}
@@ -657,15 +659,17 @@ public final void doSyncOrReplicateRecovery(SolrCore core) throws Exception {
657659
break;
658660
}
659661

660-
// we wait a bit so that any updates on the leader
661-
// that started before they saw recovering state
662-
// are sure to have finished (see SOLR-7141 for
663-
// discussion around current value)
664-
// TODO since SOLR-11216, we probably won't need this
665-
try {
666-
Thread.sleep(waitForUpdatesWithStaleStatePauseMilliSeconds);
667-
} catch (InterruptedException e) {
668-
Thread.currentThread().interrupt();
662+
if (!core.readOnly) {
663+
// we wait a bit so that any updates on the leader
664+
// that started before they saw recovering state
665+
// are sure to have finished (see SOLR-7141 for
666+
// discussion around current value)
667+
// TODO since SOLR-11216, we probably won't need this
668+
try {
669+
Thread.sleep(waitForUpdatesWithStaleStatePauseMilliSeconds);
670+
} catch (InterruptedException e) {
671+
Thread.currentThread().interrupt();
672+
}
669673
}
670674

671675
// first thing we just try to sync

solr/core/src/java/org/apache/solr/cloud/ShardLeaderElectionContext.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ void runLeaderProcess(boolean weAreReplacement) throws KeeperException, Interrup
195195
// first cancel any current recovery
196196
core.getUpdateHandler().getSolrCoreState().cancelRecovery();
197197

198-
if (weAreReplacement) {
198+
if (weAreReplacement && !core.readOnly) {
199199
// wait a moment for any floating updates to finish
200200
try {
201201
Thread.sleep(2500);

solr/core/src/java/org/apache/solr/core/SolrCore.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2476,7 +2476,7 @@ public RefCounted<SolrIndexSearcher> openNewSearcher(
24762476
true,
24772477
directoryFactory);
24782478
} else {
2479-
RefCounted<IndexWriter> writer = getSolrCoreState().getIndexWriter(this);
2479+
RefCounted<IndexWriter> writer = getSolrCoreState().getIndexWriter(this, false);
24802480
DirectoryReader newReader = null;
24812481
try {
24822482
newReader = indexReaderFactory.newReader(writer.get(), this);

solr/core/src/java/org/apache/solr/handler/IndexFetcher.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -530,14 +530,14 @@ IndexFetchResult fetchLatestIndex(boolean forceReplication, boolean forceCoreRel
530530
// we just clear ours and commit
531531
log.info("New index in Leader. Deleting mine...");
532532
RefCounted<IndexWriter> iw =
533-
solrCore.getUpdateHandler().getSolrCoreState().getIndexWriter(solrCore);
533+
solrCore.getUpdateHandler().getSolrCoreState().getIndexWriter(solrCore, false);
534534
try {
535535
iw.get().deleteAll();
536536
} finally {
537537
iw.decref();
538538
}
539539
assert TestInjection.injectDelayBeforeFollowerCommitRefresh();
540-
if (skipCommitOnLeaderVersionZero) {
540+
if (skipCommitOnLeaderVersionZero || solrCore.readOnly) {
541541
openNewSearcherAndUpdateCommitPoint();
542542
} else {
543543
SolrQueryRequest req = new LocalSolrQueryRequest(solrCore, new ModifiableSolrParams());
@@ -624,7 +624,7 @@ IndexFetchResult fetchLatestIndex(boolean forceReplication, boolean forceCoreRel
624624
// are successfully deleted
625625
solrCore.getUpdateHandler().newIndexWriter(true);
626626
RefCounted<IndexWriter> writer =
627-
solrCore.getUpdateHandler().getSolrCoreState().getIndexWriter(null);
627+
solrCore.getUpdateHandler().getSolrCoreState().getIndexWriter(null, false);
628628
try {
629629
IndexWriter indexWriter = writer.get();
630630
int c = 0;

solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1378,7 +1378,7 @@ public void inform(SolrCore core) {
13781378

13791379
// ensure the writer is initialized so that we have a list of commit points
13801380
RefCounted<IndexWriter> iw =
1381-
core.getUpdateHandler().getSolrCoreState().getIndexWriter(core);
1381+
core.getUpdateHandler().getSolrCoreState().getIndexWriter(core, false);
13821382
iw.decref();
13831383

13841384
} catch (IOException e) {

solr/core/src/java/org/apache/solr/handler/RequestHandlerUtils.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ public static void updateCommit(CommitUpdateCommand cmd, SolrParams params) {
9999
cmd.maxOptimizeSegments =
100100
params.getInt(UpdateParams.MAX_OPTIMIZE_SEGMENTS, cmd.maxOptimizeSegments);
101101
cmd.prepareCommit = params.getBool(UpdateParams.PREPARE_COMMIT, cmd.prepareCommit);
102+
cmd.failOnReadOnly = params.getBool(UpdateParams.FAIL_ON_READ_ONLY, cmd.failOnReadOnly);
102103
}
103104

104105
/**

solr/core/src/java/org/apache/solr/update/CommitUpdateCommand.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public class CommitUpdateCommand extends UpdateCommand {
3939
public boolean expungeDeletes = false;
4040
public boolean softCommit = false;
4141
public boolean prepareCommit = false;
42+
public boolean failOnReadOnly = true; // fail the commit if the core or collection is readOnly
4243

4344
/**
4445
* User provided commit data. Can be let to null if there is none. It is possible to commit this
@@ -98,6 +99,9 @@ public String toString() {
9899
.append(softCommit)
99100
.append(",prepareCommit=")
100101
.append(prepareCommit);
102+
if (!failOnReadOnly) {
103+
sb.append(",failOnReadOnly=").append(failOnReadOnly);
104+
}
101105
if (commitData != null) {
102106
sb.append(",commitData=").append(commitData);
103107
}

solr/core/src/java/org/apache/solr/update/DefaultSolrCoreState.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,9 @@ private void closeIndexWriter(IndexWriterCloser closer) {
106106
}
107107

108108
@Override
109-
public RefCounted<IndexWriter> getIndexWriter(SolrCore core) throws IOException {
110-
if (core != null && (!core.indexEnabled || core.readOnly)) {
109+
public RefCounted<IndexWriter> getIndexWriter(SolrCore core, boolean failOnReadOnly)
110+
throws IOException {
111+
if (core != null && (!core.indexEnabled || (core.readOnly && failOnReadOnly))) {
111112
throw new SolrException(
112113
SolrException.ErrorCode.SERVICE_UNAVAILABLE, "Indexing is temporarily disabled");
113114
}

solr/core/src/java/org/apache/solr/update/SolrCoreState.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,19 @@ public void deregisterInFlightUpdate() {
178178
*
179179
* @throws IOException If there is a low-level I/O error.
180180
*/
181-
public abstract RefCounted<IndexWriter> getIndexWriter(SolrCore core) throws IOException;
181+
public RefCounted<IndexWriter> getIndexWriter(SolrCore core) throws IOException {
182+
return getIndexWriter(core, true);
183+
}
184+
185+
/**
186+
* Get the current IndexWriter. If a new IndexWriter must be created, use the settings from the
187+
* given {@link SolrCore}. Be very careful using the {@code failOnReadOnly=false} flag, by default
188+
* it should be true if the returned indexWriter will be used for writing.
189+
*
190+
* @throws IOException If there is a low-level I/O error.
191+
*/
192+
public abstract RefCounted<IndexWriter> getIndexWriter(SolrCore core, boolean failOnReadOnly)
193+
throws IOException;
182194

183195
/**
184196
* Rollback the current IndexWriter. When creating the new IndexWriter use the settings from the

0 commit comments

Comments
 (0)