This is an automated email from the ASF dual-hosted git repository. jmanno pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/accumulo.git
The following commit(s) were added to refs/heads/main by this push: new bbc0021 Handle case where manager isn't active due to upgrade (#2321) bbc0021 is described below commit bbc002116465be98acc09d30f9e4d1b9486fe944 Author: Jeffrey Manno <jeffreymann...@gmail.com> AuthorDate: Thu Oct 28 09:47:36 2021 -0400 Handle case where manager isn't active due to upgrade (#2321) * Add boolean to keep track of UpgradeStatus inside Manager * Create a isUpgrading function inside HighlyAvailableService to return that booleans value * Revise Thrift exception to include a description of the error. * Throw this exception if trying to access manager while it is upgrading. --- .../thrift/ThriftNotActiveServiceException.java | 220 ++++++++++++++++++++- core/src/main/thrift/client.thrift | 5 +- .../accumulo/server/HighlyAvailableService.java | 8 + .../HighlyAvailableServiceInvocationHandler.java | 11 +- .../java/org/apache/accumulo/manager/Manager.java | 14 ++ .../org/apache/accumulo/tserver/TabletServer.java | 1 - 6 files changed, 255 insertions(+), 4 deletions(-) diff --git a/core/src/main/thrift-gen-java/org/apache/accumulo/core/clientImpl/thrift/ThriftNotActiveServiceException.java b/core/src/main/thrift-gen-java/org/apache/accumulo/core/clientImpl/thrift/ThriftNotActiveServiceException.java index 0d86beb..845b8ca 100644 --- a/core/src/main/thrift-gen-java/org/apache/accumulo/core/clientImpl/thrift/ThriftNotActiveServiceException.java +++ b/core/src/main/thrift-gen-java/org/apache/accumulo/core/clientImpl/thrift/ThriftNotActiveServiceException.java @@ -28,14 +28,19 @@ package org.apache.accumulo.core.clientImpl.thrift; public class ThriftNotActiveServiceException extends org.apache.thrift.TException implements org.apache.thrift.TBase<ThriftNotActiveServiceException, ThriftNotActiveServiceException._Fields>, java.io.Serializable, Cloneable, Comparable<ThriftNotActiveServiceException> { private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("ThriftNotActiveServiceException"); + private static final org.apache.thrift.protocol.TField SERV_FIELD_DESC = new org.apache.thrift.protocol.TField("serv", org.apache.thrift.protocol.TType.STRING, (short)1); + private static final org.apache.thrift.protocol.TField DESCRIPTION_FIELD_DESC = new org.apache.thrift.protocol.TField("description", org.apache.thrift.protocol.TType.STRING, (short)2); private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new ThriftNotActiveServiceExceptionStandardSchemeFactory(); private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new ThriftNotActiveServiceExceptionTupleSchemeFactory(); + public @org.apache.thrift.annotation.Nullable java.lang.String serv; // required + public @org.apache.thrift.annotation.Nullable java.lang.String description; // required /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ public enum _Fields implements org.apache.thrift.TFieldIdEnum { -; + SERV((short)1, "serv"), + DESCRIPTION((short)2, "description"); private static final java.util.Map<java.lang.String, _Fields> byName = new java.util.HashMap<java.lang.String, _Fields>(); @@ -51,6 +56,10 @@ public class ThriftNotActiveServiceException extends org.apache.thrift.TExceptio @org.apache.thrift.annotation.Nullable public static _Fields findByThriftId(int fieldId) { switch(fieldId) { + case 1: // SERV + return SERV; + case 2: // DESCRIPTION + return DESCRIPTION; default: return null; } @@ -90,9 +99,15 @@ public class ThriftNotActiveServiceException extends org.apache.thrift.TExceptio return _fieldName; } } + + // isset id assignments public static final java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap; static { java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.SERV, new org.apache.thrift.meta_data.FieldMetaData("serv", org.apache.thrift.TFieldRequirementType.DEFAULT, + new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))); + tmpMap.put(_Fields.DESCRIPTION, new org.apache.thrift.meta_data.FieldMetaData("description", org.apache.thrift.TFieldRequirementType.DEFAULT, + new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))); metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(ThriftNotActiveServiceException.class, metaDataMap); } @@ -100,10 +115,25 @@ public class ThriftNotActiveServiceException extends org.apache.thrift.TExceptio public ThriftNotActiveServiceException() { } + public ThriftNotActiveServiceException( + java.lang.String serv, + java.lang.String description) + { + this(); + this.serv = serv; + this.description = description; + } + /** * Performs a deep copy on <i>other</i>. */ public ThriftNotActiveServiceException(ThriftNotActiveServiceException other) { + if (other.isSetServ()) { + this.serv = other.serv; + } + if (other.isSetDescription()) { + this.description = other.description; + } } public ThriftNotActiveServiceException deepCopy() { @@ -112,16 +142,90 @@ public class ThriftNotActiveServiceException extends org.apache.thrift.TExceptio @Override public void clear() { + this.serv = null; + this.description = null; + } + + @org.apache.thrift.annotation.Nullable + public java.lang.String getServ() { + return this.serv; + } + + public ThriftNotActiveServiceException setServ(@org.apache.thrift.annotation.Nullable java.lang.String serv) { + this.serv = serv; + return this; + } + + public void unsetServ() { + this.serv = null; + } + + /** Returns true if field serv is set (has been assigned a value) and false otherwise */ + public boolean isSetServ() { + return this.serv != null; + } + + public void setServIsSet(boolean value) { + if (!value) { + this.serv = null; + } + } + + @org.apache.thrift.annotation.Nullable + public java.lang.String getDescription() { + return this.description; + } + + public ThriftNotActiveServiceException setDescription(@org.apache.thrift.annotation.Nullable java.lang.String description) { + this.description = description; + return this; + } + + public void unsetDescription() { + this.description = null; + } + + /** Returns true if field description is set (has been assigned a value) and false otherwise */ + public boolean isSetDescription() { + return this.description != null; + } + + public void setDescriptionIsSet(boolean value) { + if (!value) { + this.description = null; + } } public void setFieldValue(_Fields field, @org.apache.thrift.annotation.Nullable java.lang.Object value) { switch (field) { + case SERV: + if (value == null) { + unsetServ(); + } else { + setServ((java.lang.String)value); + } + break; + + case DESCRIPTION: + if (value == null) { + unsetDescription(); + } else { + setDescription((java.lang.String)value); + } + break; + } } @org.apache.thrift.annotation.Nullable public java.lang.Object getFieldValue(_Fields field) { switch (field) { + case SERV: + return getServ(); + + case DESCRIPTION: + return getDescription(); + } throw new java.lang.IllegalStateException(); } @@ -133,6 +237,10 @@ public class ThriftNotActiveServiceException extends org.apache.thrift.TExceptio } switch (field) { + case SERV: + return isSetServ(); + case DESCRIPTION: + return isSetDescription(); } throw new java.lang.IllegalStateException(); } @@ -150,6 +258,24 @@ public class ThriftNotActiveServiceException extends org.apache.thrift.TExceptio if (this == that) return true; + boolean this_present_serv = true && this.isSetServ(); + boolean that_present_serv = true && that.isSetServ(); + if (this_present_serv || that_present_serv) { + if (!(this_present_serv && that_present_serv)) + return false; + if (!this.serv.equals(that.serv)) + return false; + } + + boolean this_present_description = true && this.isSetDescription(); + boolean that_present_description = true && that.isSetDescription(); + if (this_present_description || that_present_description) { + if (!(this_present_description && that_present_description)) + return false; + if (!this.description.equals(that.description)) + return false; + } + return true; } @@ -157,6 +283,14 @@ public class ThriftNotActiveServiceException extends org.apache.thrift.TExceptio public int hashCode() { int hashCode = 1; + hashCode = hashCode * 8191 + ((isSetServ()) ? 131071 : 524287); + if (isSetServ()) + hashCode = hashCode * 8191 + serv.hashCode(); + + hashCode = hashCode * 8191 + ((isSetDescription()) ? 131071 : 524287); + if (isSetDescription()) + hashCode = hashCode * 8191 + description.hashCode(); + return hashCode; } @@ -168,6 +302,26 @@ public class ThriftNotActiveServiceException extends org.apache.thrift.TExceptio int lastComparison = 0; + lastComparison = java.lang.Boolean.compare(isSetServ(), other.isSetServ()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetServ()) { + lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.serv, other.serv); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.compare(isSetDescription(), other.isSetDescription()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetDescription()) { + lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.description, other.description); + if (lastComparison != 0) { + return lastComparison; + } + } return 0; } @@ -189,6 +343,21 @@ public class ThriftNotActiveServiceException extends org.apache.thrift.TExceptio java.lang.StringBuilder sb = new java.lang.StringBuilder("ThriftNotActiveServiceException("); boolean first = true; + sb.append("serv:"); + if (this.serv == null) { + sb.append("null"); + } else { + sb.append(this.serv); + } + first = false; + if (!first) sb.append(", "); + sb.append("description:"); + if (this.description == null) { + sb.append("null"); + } else { + sb.append(this.description); + } + first = false; sb.append(")"); return sb.toString(); } @@ -232,6 +401,22 @@ public class ThriftNotActiveServiceException extends org.apache.thrift.TExceptio break; } switch (schemeField.id) { + case 1: // SERV + if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { + struct.serv = iprot.readString(); + struct.setServIsSet(true); + } else { + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 2: // DESCRIPTION + if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { + struct.description = iprot.readString(); + struct.setDescriptionIsSet(true); + } else { + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; default: org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); } @@ -247,6 +432,16 @@ public class ThriftNotActiveServiceException extends org.apache.thrift.TExceptio struct.validate(); oprot.writeStructBegin(STRUCT_DESC); + if (struct.serv != null) { + oprot.writeFieldBegin(SERV_FIELD_DESC); + oprot.writeString(struct.serv); + oprot.writeFieldEnd(); + } + if (struct.description != null) { + oprot.writeFieldBegin(DESCRIPTION_FIELD_DESC); + oprot.writeString(struct.description); + oprot.writeFieldEnd(); + } oprot.writeFieldStop(); oprot.writeStructEnd(); } @@ -264,11 +459,34 @@ public class ThriftNotActiveServiceException extends org.apache.thrift.TExceptio @Override public void write(org.apache.thrift.protocol.TProtocol prot, ThriftNotActiveServiceException struct) throws org.apache.thrift.TException { org.apache.thrift.protocol.TTupleProtocol oprot = (org.apache.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetServ()) { + optionals.set(0); + } + if (struct.isSetDescription()) { + optionals.set(1); + } + oprot.writeBitSet(optionals, 2); + if (struct.isSetServ()) { + oprot.writeString(struct.serv); + } + if (struct.isSetDescription()) { + oprot.writeString(struct.description); + } } @Override public void read(org.apache.thrift.protocol.TProtocol prot, ThriftNotActiveServiceException struct) throws org.apache.thrift.TException { org.apache.thrift.protocol.TTupleProtocol iprot = (org.apache.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(2); + if (incoming.get(0)) { + struct.serv = iprot.readString(); + struct.setServIsSet(true); + } + if (incoming.get(1)) { + struct.description = iprot.readString(); + struct.setDescriptionIsSet(true); + } } } diff --git a/core/src/main/thrift/client.thrift b/core/src/main/thrift/client.thrift index 424e30d..4833cd0 100644 --- a/core/src/main/thrift/client.thrift +++ b/core/src/main/thrift/client.thrift @@ -98,7 +98,10 @@ exception ThriftTableOperationException { 5:string description } -exception ThriftNotActiveServiceException {} +exception ThriftNotActiveServiceException { + 1:string serv + 2:string description +} struct TDiskUsage { 1:list<string> tables diff --git a/server/base/src/main/java/org/apache/accumulo/server/HighlyAvailableService.java b/server/base/src/main/java/org/apache/accumulo/server/HighlyAvailableService.java index b290b2e..a16b540 100644 --- a/server/base/src/main/java/org/apache/accumulo/server/HighlyAvailableService.java +++ b/server/base/src/main/java/org/apache/accumulo/server/HighlyAvailableService.java @@ -31,4 +31,12 @@ public interface HighlyAvailableService { */ boolean isActiveService(); + /** + * Is this service instance currently in the process of upgrading. + * + * @return True if the service is upgrading, false otherwise. + */ + default boolean isUpgrading() { + return false; + } } diff --git a/server/base/src/main/java/org/apache/accumulo/server/rpc/HighlyAvailableServiceInvocationHandler.java b/server/base/src/main/java/org/apache/accumulo/server/rpc/HighlyAvailableServiceInvocationHandler.java index 012f3d0..df48b0c 100644 --- a/server/base/src/main/java/org/apache/accumulo/server/rpc/HighlyAvailableServiceInvocationHandler.java +++ b/server/base/src/main/java/org/apache/accumulo/server/rpc/HighlyAvailableServiceInvocationHandler.java @@ -47,10 +47,19 @@ public class HighlyAvailableServiceInvocationHandler<I> implements InvocationHan @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + + // If the service is upgrading, throw an exception + if (service.isUpgrading()) { + LOG.trace("Service can not be accessed while it is upgrading."); + throw new ThriftNotActiveServiceException(service.toString(), + "Service can not be accessed while it is upgrading"); + } + // If the service is not active, throw an exception if (!service.isActiveService()) { LOG.trace("Denying access to RPC service as this instance is not the active instance."); - throw new ThriftNotActiveServiceException(); + throw new ThriftNotActiveServiceException(service.toString(), + "Denying access to RPC service as this instance is not the active instance"); } try { // Otherwise, call the real method diff --git a/server/manager/src/main/java/org/apache/accumulo/manager/Manager.java b/server/manager/src/main/java/org/apache/accumulo/manager/Manager.java index f07192c..d85cdc3 100644 --- a/server/manager/src/main/java/org/apache/accumulo/manager/Manager.java +++ b/server/manager/src/main/java/org/apache/accumulo/manager/Manager.java @@ -217,6 +217,7 @@ public class Manager extends AbstractServer final ServerBulkImportStatus bulkImportStatus = new ServerBulkImportStatus(); private final AtomicBoolean managerInitialized = new AtomicBoolean(false); + private final AtomicBoolean managerUpgrading = new AtomicBoolean(false); @Override public synchronized ManagerState getManagerState() { @@ -1042,6 +1043,12 @@ public class Manager extends AbstractServer throw new IllegalStateException("Exception getting manager lock", e); } + // If UpgradeStatus is not at complete by this moment, then things are currently + // upgrading. + if (upgradeCoordinator.getStatus() != UpgradeCoordinator.UpgradeStatus.COMPLETE) { + managerUpgrading.set(true); + } + try { MetricsUtil.initializeMetrics(getContext().getConfiguration(), this.applicationName, sa.getAddress()); @@ -1125,6 +1132,8 @@ public class Manager extends AbstractServer if (null != upgradeMetadataFuture) { upgradeMetadataFuture.get(); } + // Everything is fully upgraded by this point. + managerUpgrading.set(false); } catch (ExecutionException | InterruptedException e) { throw new IllegalStateException("Metadata upgrade failed", e); } @@ -1712,6 +1721,11 @@ public class Manager extends AbstractServer return managerInitialized.get(); } + @Override + public boolean isUpgrading() { + return managerUpgrading.get(); + } + void initializeBalancer() { var localTabletBalancer = Property.createInstanceFromPropertyName(getConfiguration(), Property.MANAGER_TABLET_BALANCER, TabletBalancer.class, new SimpleLoadBalancer()); diff --git a/server/tserver/src/main/java/org/apache/accumulo/tserver/TabletServer.java b/server/tserver/src/main/java/org/apache/accumulo/tserver/TabletServer.java index 6128240..086efee 100644 --- a/server/tserver/src/main/java/org/apache/accumulo/tserver/TabletServer.java +++ b/server/tserver/src/main/java/org/apache/accumulo/tserver/TabletServer.java @@ -848,7 +848,6 @@ public class TabletServer extends AbstractServer { } catch (InterruptedException e) { log.info("Interrupt Exception received, shutting down"); serverStopRequested = true; - } catch (Exception e) { // may have lost connection with manager // loop back to the beginning and wait for a new one