mirror of https://github.com/apache/lucene.git
SOLR-14219: Revert changes in OverseerSolrRespose and move serialization (#1227)
SOLR-14095 Introduced an issue for rolling restarts (Incompatible Java serialization). This change fixes the compatibility issue while keeping the functionality in SOLR-14095
This commit is contained in:
parent
d7859097ee
commit
37d4121770
|
@ -181,6 +181,9 @@ Bug Fixes
|
||||||
|
|
||||||
* SOLR-14090: Handle the case in `delete-copy-field` when source is a dynamic field (Frank Iversen, Munendra S N)
|
* SOLR-14090: Handle the case in `delete-copy-field` when source is a dynamic field (Frank Iversen, Munendra S N)
|
||||||
|
|
||||||
|
* SOLR-14219: SOLR-14095 Introduced an issue for rolling restarts (Incompatible Java serialization). This change
|
||||||
|
Fixes the compatibility issue while keeping the functionality in SOLR-14095. (Andy Webb, Tomás Fernández Löbbe)
|
||||||
|
|
||||||
Other Changes
|
Other Changes
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
|
|
|
@ -16,19 +16,12 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.solr.cloud;
|
package org.apache.solr.cloud;
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
|
||||||
import org.apache.solr.client.solrj.SolrResponse;
|
import org.apache.solr.client.solrj.SolrResponse;
|
||||||
import org.apache.solr.common.SolrException;
|
|
||||||
import org.apache.solr.common.SolrException.ErrorCode;
|
|
||||||
import org.apache.solr.common.util.NamedList;
|
import org.apache.solr.common.util.NamedList;
|
||||||
import org.apache.solr.common.util.Utils;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public class OverseerSolrResponse extends SolrResponse {
|
public class OverseerSolrResponse extends SolrResponse {
|
||||||
|
|
||||||
NamedList<Object> responseList = null;
|
NamedList responseList = null;
|
||||||
|
|
||||||
private long elapsedTime;
|
private long elapsedTime;
|
||||||
|
|
||||||
|
@ -56,49 +49,4 @@ public class OverseerSolrResponse extends SolrResponse {
|
||||||
return responseList;
|
return responseList;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This method serializes the content of an {@code OverseerSolrResponse}. Note that:
|
|
||||||
* <ul>
|
|
||||||
* <li>The elapsed time is not serialized</li>
|
|
||||||
* <li>"Unknown" elements for the Javabin format will be serialized as Strings. See {@link org.apache.solr.common.util.JavaBinCodec#writeVal}</li>
|
|
||||||
* </ul>
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public static byte[] serialize(OverseerSolrResponse responseObject) {
|
|
||||||
Objects.requireNonNull(responseObject);
|
|
||||||
if (useUnsafeSerialization()) {
|
|
||||||
return SolrResponse.serializable(responseObject);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return IOUtils.toByteArray(Utils.toJavabin(responseObject.getResponse()));
|
|
||||||
} catch (IOException|RuntimeException e) {
|
|
||||||
throw new SolrException(ErrorCode.SERVER_ERROR, "Exception serializing response to Javabin", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static boolean useUnsafeSerialization() {
|
|
||||||
String useUnsafeOverseerResponse = System.getProperty("solr.useUnsafeOverseerResponse");
|
|
||||||
return useUnsafeOverseerResponse != null && ("true".equals(useUnsafeOverseerResponse));
|
|
||||||
}
|
|
||||||
|
|
||||||
static boolean useUnsafeDeserialization() {
|
|
||||||
String useUnsafeOverseerResponse = System.getProperty("solr.useUnsafeOverseerResponse");
|
|
||||||
return useUnsafeOverseerResponse != null && ("true".equals(useUnsafeOverseerResponse) || "deserialization".equals(useUnsafeOverseerResponse));
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public static OverseerSolrResponse deserialize(byte[] responseBytes) {
|
|
||||||
Objects.requireNonNull(responseBytes);
|
|
||||||
try {
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
NamedList<Object> response = (NamedList<Object>) Utils.fromJavabin(responseBytes);
|
|
||||||
return new OverseerSolrResponse(response);
|
|
||||||
} catch (IOException|RuntimeException e) {
|
|
||||||
if (useUnsafeDeserialization()) {
|
|
||||||
return (OverseerSolrResponse) SolrResponse.deserialize(responseBytes);
|
|
||||||
}
|
|
||||||
throw new SolrException(ErrorCode.SERVER_ERROR, "Exception deserializing response from Javabin", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You 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 org.apache.solr.cloud;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.apache.solr.client.solrj.SolrResponse;
|
||||||
|
import org.apache.solr.common.SolrException;
|
||||||
|
import org.apache.solr.common.SolrException.ErrorCode;
|
||||||
|
import org.apache.solr.common.util.NamedList;
|
||||||
|
import org.apache.solr.common.util.Utils;
|
||||||
|
|
||||||
|
public class OverseerSolrResponseSerializer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method serializes the content of an {@code OverseerSolrResponse}. Note that:
|
||||||
|
* <ul>
|
||||||
|
* <li>The elapsed time is not serialized</li>
|
||||||
|
* <li>"Unknown" elements for the Javabin format will be serialized as Strings. See {@link org.apache.solr.common.util.JavaBinCodec#writeVal}</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
public static byte[] serialize(OverseerSolrResponse responseObject) {
|
||||||
|
Objects.requireNonNull(responseObject);
|
||||||
|
if (useUnsafeSerialization()) {
|
||||||
|
return SolrResponse.serializable(responseObject);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return IOUtils.toByteArray(Utils.toJavabin(responseObject.getResponse()));
|
||||||
|
} catch (IOException|RuntimeException e) {
|
||||||
|
throw new SolrException(ErrorCode.SERVER_ERROR, "Exception serializing response to Javabin", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean useUnsafeSerialization() {
|
||||||
|
String useUnsafeOverseerResponse = System.getProperty("solr.useUnsafeOverseerResponse");
|
||||||
|
return useUnsafeOverseerResponse != null && ("true".equals(useUnsafeOverseerResponse));
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean useUnsafeDeserialization() {
|
||||||
|
String useUnsafeOverseerResponse = System.getProperty("solr.useUnsafeOverseerResponse");
|
||||||
|
return useUnsafeOverseerResponse != null && ("true".equals(useUnsafeOverseerResponse) || "deserialization".equals(useUnsafeOverseerResponse));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
public static OverseerSolrResponse deserialize(byte[] responseBytes) {
|
||||||
|
Objects.requireNonNull(responseBytes);
|
||||||
|
try {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
NamedList<Object> response = (NamedList<Object>) Utils.fromJavabin(responseBytes);
|
||||||
|
return new OverseerSolrResponse(response);
|
||||||
|
} catch (IOException|RuntimeException e) {
|
||||||
|
if (useUnsafeDeserialization()) {
|
||||||
|
return (OverseerSolrResponse) SolrResponse.deserialize(responseBytes);
|
||||||
|
}
|
||||||
|
throw new SolrException(ErrorCode.SERVER_ERROR, "Exception deserializing response from Javabin", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -510,14 +510,14 @@ public class OverseerTaskProcessor implements Runnable, Closeable {
|
||||||
if (asyncId != null) {
|
if (asyncId != null) {
|
||||||
if (response != null && (response.getResponse().get("failure") != null
|
if (response != null && (response.getResponse().get("failure") != null
|
||||||
|| response.getResponse().get("exception") != null)) {
|
|| response.getResponse().get("exception") != null)) {
|
||||||
failureMap.put(asyncId, OverseerSolrResponse.serialize(response));
|
failureMap.put(asyncId, OverseerSolrResponseSerializer.serialize(response));
|
||||||
log.debug("Updated failed map for task with zkid:[{}]", head.getId());
|
log.debug("Updated failed map for task with zkid:[{}]", head.getId());
|
||||||
} else {
|
} else {
|
||||||
completedMap.put(asyncId, OverseerSolrResponse.serialize(response));
|
completedMap.put(asyncId, OverseerSolrResponseSerializer.serialize(response));
|
||||||
log.debug("Updated completed map for task with zkid:[{}]", head.getId());
|
log.debug("Updated completed map for task with zkid:[{}]", head.getId());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
head.setBytes(OverseerSolrResponse.serialize(response));
|
head.setBytes(OverseerSolrResponseSerializer.serialize(response));
|
||||||
log.debug("Completed task:[{}]", head.getId());
|
log.debug("Completed task:[{}]", head.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ import org.apache.solr.client.solrj.request.CoreAdminRequest.RequestSyncShard;
|
||||||
import org.apache.solr.client.solrj.response.RequestStatusState;
|
import org.apache.solr.client.solrj.response.RequestStatusState;
|
||||||
import org.apache.solr.client.solrj.util.SolrIdentifierValidator;
|
import org.apache.solr.client.solrj.util.SolrIdentifierValidator;
|
||||||
import org.apache.solr.cloud.OverseerSolrResponse;
|
import org.apache.solr.cloud.OverseerSolrResponse;
|
||||||
|
import org.apache.solr.cloud.OverseerSolrResponseSerializer;
|
||||||
import org.apache.solr.cloud.OverseerTaskQueue;
|
import org.apache.solr.cloud.OverseerTaskQueue;
|
||||||
import org.apache.solr.cloud.OverseerTaskQueue.QueueEvent;
|
import org.apache.solr.cloud.OverseerTaskQueue.QueueEvent;
|
||||||
import org.apache.solr.cloud.ZkController;
|
import org.apache.solr.cloud.ZkController;
|
||||||
|
@ -368,7 +369,7 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission
|
||||||
.getOverseerCollectionQueue()
|
.getOverseerCollectionQueue()
|
||||||
.offer(Utils.toJSON(m), timeout);
|
.offer(Utils.toJSON(m), timeout);
|
||||||
if (event.getBytes() != null) {
|
if (event.getBytes() != null) {
|
||||||
return OverseerSolrResponse.deserialize(event.getBytes());
|
return OverseerSolrResponseSerializer.deserialize(event.getBytes());
|
||||||
} else {
|
} else {
|
||||||
if (System.nanoTime() - time >= TimeUnit.NANOSECONDS.convert(timeout, TimeUnit.MILLISECONDS)) {
|
if (System.nanoTime() - time >= TimeUnit.NANOSECONDS.convert(timeout, TimeUnit.MILLISECONDS)) {
|
||||||
throw new SolrException(ErrorCode.SERVER_ERROR, operation
|
throw new SolrException(ErrorCode.SERVER_ERROR, operation
|
||||||
|
@ -874,11 +875,11 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission
|
||||||
final NamedList<Object> results = new NamedList<>();
|
final NamedList<Object> results = new NamedList<>();
|
||||||
if (zkController.getOverseerCompletedMap().contains(requestId)) {
|
if (zkController.getOverseerCompletedMap().contains(requestId)) {
|
||||||
final byte[] mapEntry = zkController.getOverseerCompletedMap().get(requestId);
|
final byte[] mapEntry = zkController.getOverseerCompletedMap().get(requestId);
|
||||||
rsp.getValues().addAll(OverseerSolrResponse.deserialize(mapEntry).getResponse());
|
rsp.getValues().addAll(OverseerSolrResponseSerializer.deserialize(mapEntry).getResponse());
|
||||||
addStatusToResponse(results, COMPLETED, "found [" + requestId + "] in completed tasks");
|
addStatusToResponse(results, COMPLETED, "found [" + requestId + "] in completed tasks");
|
||||||
} else if (zkController.getOverseerFailureMap().contains(requestId)) {
|
} else if (zkController.getOverseerFailureMap().contains(requestId)) {
|
||||||
final byte[] mapEntry = zkController.getOverseerFailureMap().get(requestId);
|
final byte[] mapEntry = zkController.getOverseerFailureMap().get(requestId);
|
||||||
rsp.getValues().addAll(OverseerSolrResponse.deserialize(mapEntry).getResponse());
|
rsp.getValues().addAll(OverseerSolrResponseSerializer.deserialize(mapEntry).getResponse());
|
||||||
addStatusToResponse(results, FAILED, "found [" + requestId + "] in failed tasks");
|
addStatusToResponse(results, FAILED, "found [" + requestId + "] in failed tasks");
|
||||||
} else if (zkController.getOverseerRunningMap().contains(requestId)) {
|
} else if (zkController.getOverseerRunningMap().contains(requestId)) {
|
||||||
addStatusToResponse(results, RUNNING, "found [" + requestId + "] in running tasks");
|
addStatusToResponse(results, RUNNING, "found [" + requestId + "] in running tasks");
|
||||||
|
|
|
@ -33,6 +33,7 @@ import org.apache.hadoop.fs.Path;
|
||||||
import org.apache.solr.api.Api;
|
import org.apache.solr.api.Api;
|
||||||
import org.apache.solr.client.solrj.SolrResponse;
|
import org.apache.solr.client.solrj.SolrResponse;
|
||||||
import org.apache.solr.cloud.OverseerSolrResponse;
|
import org.apache.solr.cloud.OverseerSolrResponse;
|
||||||
|
import org.apache.solr.cloud.OverseerSolrResponseSerializer;
|
||||||
import org.apache.solr.cloud.OverseerTaskQueue.QueueEvent;
|
import org.apache.solr.cloud.OverseerTaskQueue.QueueEvent;
|
||||||
import org.apache.solr.common.SolrException;
|
import org.apache.solr.common.SolrException;
|
||||||
import org.apache.solr.common.SolrException.ErrorCode;
|
import org.apache.solr.common.SolrException.ErrorCode;
|
||||||
|
@ -212,7 +213,7 @@ public class ConfigSetsHandler extends RequestHandlerBase implements PermissionN
|
||||||
.getOverseerConfigSetQueue()
|
.getOverseerConfigSetQueue()
|
||||||
.offer(Utils.toJSON(m), timeout);
|
.offer(Utils.toJSON(m), timeout);
|
||||||
if (event.getBytes() != null) {
|
if (event.getBytes() != null) {
|
||||||
SolrResponse response = OverseerSolrResponse.deserialize(event.getBytes());
|
SolrResponse response = OverseerSolrResponseSerializer.deserialize(event.getBytes());
|
||||||
rsp.getValues().addAll(response.getResponse());
|
rsp.getValues().addAll(response.getResponse());
|
||||||
SimpleOrderedMap exp = (SimpleOrderedMap) response.getResponse().get("exception");
|
SimpleOrderedMap exp = (SimpleOrderedMap) response.getResponse().get("exception");
|
||||||
if (exp != null) {
|
if (exp != null) {
|
||||||
|
|
|
@ -564,7 +564,7 @@ public class OverseerCollectionConfigSetProcessorTest extends SolrTestCaseJ4 {
|
||||||
QueueEvent qe = new QueueEvent("id", Utils.toJSON(props), null){
|
QueueEvent qe = new QueueEvent("id", Utils.toJSON(props), null){
|
||||||
@Override
|
@Override
|
||||||
public void setBytes(byte[] bytes) {
|
public void setBytes(byte[] bytes) {
|
||||||
lastProcessMessageResult = OverseerSolrResponse.deserialize(bytes);
|
lastProcessMessageResult = OverseerSolrResponseSerializer.deserialize(bytes);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
queue.add(qe);
|
queue.add(qe);
|
||||||
|
|
|
@ -62,7 +62,7 @@ public class OverseerSolrResponseTest extends SolrTestCaseJ4 {
|
||||||
exceptionNl.add("msg", e.getMessage());
|
exceptionNl.add("msg", e.getMessage());
|
||||||
exceptionNl.add("rspCode", e.code());
|
exceptionNl.add("rspCode", e.code());
|
||||||
responseNl.add("exception", exceptionNl);
|
responseNl.add("exception", exceptionNl);
|
||||||
OverseerSolrResponse deserialized = OverseerSolrResponse.deserialize(OverseerSolrResponse.serialize(new OverseerSolrResponse(responseNl)));
|
OverseerSolrResponse deserialized = OverseerSolrResponseSerializer.deserialize(OverseerSolrResponseSerializer.serialize(new OverseerSolrResponse(responseNl)));
|
||||||
assertNotNull("Expecting an exception", deserialized.getException());
|
assertNotNull("Expecting an exception", deserialized.getException());
|
||||||
assertEquals("Unexpected exception type in deserialized response", SolrException.class, deserialized.getException().getClass());
|
assertEquals("Unexpected exception type in deserialized response", SolrException.class, deserialized.getException().getClass());
|
||||||
assertEquals("Unexpected exception code in deserialized response", e.code(), ((SolrException)deserialized.getException()).code());
|
assertEquals("Unexpected exception code in deserialized response", e.code(), ((SolrException)deserialized.getException()).code());
|
||||||
|
@ -71,8 +71,8 @@ public class OverseerSolrResponseTest extends SolrTestCaseJ4 {
|
||||||
|
|
||||||
private void assertSerializeDeserialize(NamedList<Object> content) {
|
private void assertSerializeDeserialize(NamedList<Object> content) {
|
||||||
OverseerSolrResponse response = new OverseerSolrResponse(content);
|
OverseerSolrResponse response = new OverseerSolrResponse(content);
|
||||||
byte[] serialized = OverseerSolrResponse.serialize(response);
|
byte[] serialized = OverseerSolrResponseSerializer.serialize(response);
|
||||||
OverseerSolrResponse deserialized = OverseerSolrResponse.deserialize(serialized);
|
OverseerSolrResponse deserialized = OverseerSolrResponseSerializer.deserialize(serialized);
|
||||||
assertEquals("Deserialized response is different than original", response.getResponse(), deserialized.getResponse());
|
assertEquals("Deserialized response is different than original", response.getResponse(), deserialized.getResponse());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,8 +49,8 @@ public class OverseerSolrResponseUnsafeSerializationTest extends OverseerSolrRes
|
||||||
} else {
|
} else {
|
||||||
System.setProperty("solr.useUnsafeOverseerResponse", propertyValue);
|
System.setProperty("solr.useUnsafeOverseerResponse", propertyValue);
|
||||||
}
|
}
|
||||||
assertEquals("Unexpected serialization toggle for value: " + propertyValue, serializationEnabled, OverseerSolrResponse.useUnsafeSerialization());
|
assertEquals("Unexpected serialization toggle for value: " + propertyValue, serializationEnabled, OverseerSolrResponseSerializer.useUnsafeSerialization());
|
||||||
assertEquals("Unexpected serialization toggle for value: " + propertyValue, deserializationEnabled, OverseerSolrResponse.useUnsafeDeserialization());
|
assertEquals("Unexpected serialization toggle for value: " + propertyValue, deserializationEnabled, OverseerSolrResponseSerializer.useUnsafeDeserialization());
|
||||||
} finally {
|
} finally {
|
||||||
if (previousValue != null) {
|
if (previousValue != null) {
|
||||||
System.setProperty("solr.useUnsafeOverseerResponse", previousValue);
|
System.setProperty("solr.useUnsafeOverseerResponse", previousValue);
|
||||||
|
|
Loading…
Reference in New Issue