/**
* Copyright 2016 LinkedIn Corp. All rights reserved.
*
* 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.
*/
package com.github.ambry.router;
import com.github.ambry.clustermap.ClusterMap;
import com.github.ambry.clustermap.ReplicaId;
import com.github.ambry.commons.BlobId;
import com.github.ambry.config.RouterConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This is a utility class used by Router.
*/
class RouterUtils {
private static Logger logger = LoggerFactory.getLogger(RouterUtils.class);
/**
* Get {@link BlobId} from a blob string.
* @param blobIdString The string of blobId.
* @param clusterMap The {@link ClusterMap} based on which to generate the {@link BlobId}.
* @return BlobId
* @throws RouterException If parsing a string blobId fails.
*/
static BlobId getBlobIdFromString(String blobIdString, ClusterMap clusterMap) throws RouterException {
BlobId blobId;
try {
blobId = new BlobId(blobIdString, clusterMap);
logger.trace("BlobId {} created with partitionId {}", blobId, blobId.getPartition());
} catch (Exception e) {
logger.trace("Caller passed in invalid BlobId {}", blobIdString);
throw new RouterException("BlobId is invalid " + blobIdString, RouterErrorCode.InvalidBlobId);
}
return blobId;
}
/**
* Checks if the given {@link ReplicaId} is in a different data center relative to a router with the
* given {@link RouterConfig}
* @param routerConfig the {@link RouterConfig} associated with a router
* @param replicaId the {@link ReplicaId} whose status (local/remote) is to be determined.
* @return true if the replica is remote, false otherwise.
*/
static boolean isRemoteReplica(RouterConfig routerConfig, ReplicaId replicaId) {
return !routerConfig.routerDatacenterName.equals(replicaId.getDataNodeId().getDatacenterName());
}
/**
* Determine if an error is indicative of the health of the system, and not a user error.
* @param exception The {@link Exception} to check.
* @return true if this is an internal error and not a user error; false otherwise.
*/
static boolean isSystemHealthError(Exception exception) {
boolean isSystemHealthError = true;
if (exception instanceof RouterException) {
RouterErrorCode routerErrorCode = ((RouterException) exception).getErrorCode();
switch (routerErrorCode) {
// The following are user errors. Only increment the respective error metric.
case InvalidBlobId:
case InvalidPutArgument:
case BlobTooLarge:
case BadInputChannel:
case BlobDeleted:
case BlobExpired:
case BlobDoesNotExist:
case RangeNotSatisfiable:
case ChannelClosed:
isSystemHealthError = false;
break;
}
}
return isSystemHealthError;
}
/**
* Return the number of data chunks for the given blob and chunk sizes.
* @param blobSize the size of the overall blob.
* @param chunkSize the size of each data chunk (except, possibly the last one).
* @return the number of data chunks for the given blob and chunk sizes.
*/
static int getNumChunksForBlobAndChunkSize(long blobSize, int chunkSize) {
return (int) (blobSize == 0 ? 1 : (blobSize - 1) / chunkSize + 1);
}
}