/** * 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.store; import com.github.ambry.utils.Utils; import java.util.HashSet; import java.util.List; import java.util.Set; /** * Holds status of a blob from the perspective of an Index. If multiple index entries are found for the same blob, * everything is captured in a single instance of this class */ class BlobStatus { private final Set<String> available = new HashSet<>(); private final Set<String> deletedOrExpired = new HashSet<>(); private final Set<String> unavailable = new HashSet<>(); private long earliestPutTimeMs = Utils.Infinite_Time; private long earliestDeleteTimeMs = Utils.Infinite_Time; private boolean isDeletedOrExpired; private boolean belongsToRecentIndexSegment = false; /** * Initializes a {@link BlobStatus} with a list of Replica. ConsistencyChecker uses the {@link BlobStatus} to keep * track of the status of a blob in every replica. "Replica" refers to a directory name where all replicas for a given * partition is present. * @param replicaList {@link List} of replicas for which blob status needs to be collected */ BlobStatus(List<String> replicaList) { if (replicaList != null) { unavailable.addAll(replicaList); } } Set<String> getAvailableReplicaSet() { return available; } void addAvailable(String replica, long opTimeMs) { this.available.add(replica); this.unavailable.remove(replica); if (earliestPutTimeMs == Utils.Infinite_Time || opTimeMs < earliestPutTimeMs) { earliestPutTimeMs = opTimeMs; } } Set<String> getDeletedOrExpiredReplicaSet() { return deletedOrExpired; } Set<String> getUnavailableReplicaSet() { return unavailable; } boolean belongsToRecentIndexSegment() { return belongsToRecentIndexSegment; } void setBelongsToRecentIndexSegment(boolean belongsToRecentIndexSegment) { this.belongsToRecentIndexSegment = this.belongsToRecentIndexSegment || belongsToRecentIndexSegment; } void addDeletedOrExpired(String replica, long opTimeMs) { this.deletedOrExpired.add(replica); this.isDeletedOrExpired = true; this.unavailable.remove(replica); this.available.remove(replica); if (earliestDeleteTimeMs == Utils.Infinite_Time || opTimeMs < earliestDeleteTimeMs) { earliestDeleteTimeMs = opTimeMs; } } boolean isDeletedOrExpired() { return isDeletedOrExpired; } long getOpTime() { return Math.max(earliestPutTimeMs, earliestDeleteTimeMs); } public String toString() { int totalReplicas = available.size() + deletedOrExpired.size() + unavailable.size(); return "Available size: " + available.size() + ", Available :: " + available + "\nDeleted/Expired size: " + deletedOrExpired.size() + " Deleted/Expired :: " + deletedOrExpired + "\nUnavailable size: " + unavailable.size() + " Unavailable :: " + unavailable + "\nTotal Replica count: " + totalReplicas; } }