Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* 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.phoenix.exception;

/**
* CAS write to the legacy {@code /phoenix/ha} CRR znode failed (BadVersion or NodeExists); the
* caller should re-read and retry. Analog of {@link StaleHAGroupStoreRecordVersionException}.
*/
public class StaleClusterRoleRecordVersionException extends Exception {
private static final long serialVersionUID = 1L;

public StaleClusterRoleRecordVersionException(String msg) {
super(msg);
}

public StaleClusterRoleRecordVersionException(String msg, Throwable cause) {
super(msg, cause);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Objects;
import java.util.Optional;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
Expand Down Expand Up @@ -126,40 +127,31 @@ public enum RegistryType {
private final long version;

/**
* To handle backward compatibility with old ClusterRoleRecords which had zk1 and zk2 as keys for
* zk urls, This constructor is only being used {@link ClusterRoleRecord#fromJson} when we
* deserialize Cluster Role Record read from ZooKeeper ZNode. If CRR is in old format we will read
* zk1 and zk2 and url1 and url2 will be null and if it is in new format zk1 and zk2 will be null
* in both cases final url is being stored in url1 and url2 url will be stored in normalized forms
* which looks like zk1\\:port1,zk2\\:port2,zk3\\:port3, zk4\\:port4,zk5\\:port5::znode or
* master1\\:port1,master2\\:port2,master3\\:port3, master4\\:port4,master5\\:port5
* @param haGroupName HighAvailability Group name / CRR name
* @param policy Policy used by give CRR
* @param url1 ZK/HMaster url based on registry type for first cluster
* @param role1 {@link ClusterRole} which describes the current state of first cluster
* @param url2 ZK/HMaster url based on registry type for second cluster
* @param role2 {@link ClusterRole} which describes the current state of second cluster
* @param version version of a given CRR
* Convenience constructor: defaults {@code registryType} to
* {@link #DEFAULT_PHOENIX_HA_CRR_REGISTRY_TYPE} (RPC). Use the explicit overload below to write
* {@link RegistryType#ZK} records for the legacy {@code /phoenix/ha} znode.
*/
public ClusterRoleRecord(String haGroupName, HighAvailabilityPolicy policy, String url1,
ClusterRole role1, String url2, ClusterRole role2, long version) {
this(haGroupName, policy, DEFAULT_PHOENIX_HA_CRR_REGISTRY_TYPE, url1, role1, url2, role2,
version);
}

/**
* Canonical / {@code @JsonCreator} constructor. A {@code null} {@code registryType} defaults to
* {@link #DEFAULT_PHOENIX_HA_CRR_REGISTRY_TYPE} (RPC).
*/
@JsonCreator
public ClusterRoleRecord(@JsonProperty("haGroupName") String haGroupName,
@JsonProperty("policy") HighAvailabilityPolicy policy, @JsonProperty("url1") String url1,
@JsonProperty("policy") HighAvailabilityPolicy policy,
@JsonProperty("registryType") RegistryType registryType, @JsonProperty("url1") String url1,
@JsonProperty("role1") ClusterRole role1, @JsonProperty("url2") String url2,
@JsonProperty("role2") ClusterRole role2, @JsonProperty("version") long version) {
this.haGroupName = haGroupName;
this.policy = policy;
this.registryType = registryType != null ? registryType : DEFAULT_PHOENIX_HA_CRR_REGISTRY_TYPE;

// Default registry type is RPC from Consistent Cluster Failover onwards
this.registryType = DEFAULT_PHOENIX_HA_CRR_REGISTRY_TYPE;

// Do we really need to normalize here ?
// We are normalizing to have urls in specific formats for each registryType for getting
// accurate comparisons. We are passing registryType as these url most probably won't have
// protocol in url, and it might be normalized based to wrong registry type, as we normalize
// w.r.t {@link ConnectionInfo.CLIENT_CONNECTION_REGISTRY_IMPL_CONF_KEY},
// As we are expecting only master URLs as Consistent Cluster Failover onwards we only will
// allow RPC registry type url will be in form :-
// master1\\:port1,master2\\:port2,master3\\:port3,master4\\:port4,master5\\:port5
// Normalize URLs to the registry-specific canonical form for accurate comparisons.
url1 = JDBCUtil.formatUrl(url1, this.registryType);
url2 = JDBCUtil.formatUrl(url2, this.registryType);

Expand Down Expand Up @@ -221,6 +213,20 @@ public boolean hasSameInfo(ClusterRoleRecord other) {
return haGroupName.equals(other.haGroupName) && policy.equals(other.policy);
}

/**
* Equality on the six identity/role fields ({@code haGroupName, policy, url1, url2, role1,
* role2}); ignores {@code version} (always bumps) and {@code registryType} (avoids RPC->ZK
* thrash). Returns {@code false} if {@code other} is {@code null}.
*/
public boolean isLogicallyEqualIgnoringVersionAndRegistry(ClusterRoleRecord other) {
if (other == null) {
return false;
}
return Objects.equals(haGroupName, other.haGroupName) && Objects.equals(policy, other.policy)
&& Objects.equals(url1, other.url1) && Objects.equals(url2, other.url2)
&& role1 == other.role1 && role2 == other.role2;
}

/** Returns true if CRR has any url in UNKNOWN role/state. */
public boolean hasUnknownRole() {
return role1 == ClusterRole.UNKNOWN || role2 == ClusterRole.UNKNOWN;
Expand Down
Loading