| /* |
| * 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.geode.internal.cache; |
| |
| /** |
| * Keeps track of redundancy status for a bucket in a PartitionedRegion and update the region's |
| * {@link PartitionedRegionRedundancyTracker} of the bucket's status for the region. |
| */ |
| class BucketRedundancyTracker { |
| // if true decrement allowed; if false increment allowed |
| private boolean noCopiesDecrementOkay = false; |
| // if true decrement allowed; if false increment allowed |
| private boolean lowRedundancyDecrementOkay = false; |
| private boolean hasEverHadCopies = false; |
| private boolean redundancyEverSatisfied = false; |
| private volatile int currentRedundancy = -1; |
| private final int targetRedundancy; |
| private final PartitionedRegionRedundancyTracker regionRedundancyTracker; |
| |
| /** |
| * Creates a new BucketRedundancyTracker |
| * |
| * @param redundantCopies the number of redundant copies specified for the |
| * {@link PartitionedRegion} of this bucket |
| * @param regionRedundancyTracker the redundancy tracker for the {@link PartitionedRegion} of this |
| * bucket |
| */ |
| BucketRedundancyTracker(int redundantCopies, |
| PartitionedRegionRedundancyTracker regionRedundancyTracker) { |
| targetRedundancy = redundantCopies; |
| this.regionRedundancyTracker = regionRedundancyTracker; |
| } |
| |
| /** |
| * Adjust statistics based on closing a bucket |
| */ |
| synchronized void closeBucket() { |
| decrementLowRedundancy(); |
| decrementNoCopies(); |
| } |
| |
| /** |
| * Determines if there has been a change in current redundancy and updates statistics on |
| * redundancy for the region of the bucket for this tracker |
| * |
| * @param currentBucketHosts number of current hosts for the bucket |
| */ |
| synchronized void updateStatistics(int currentBucketHosts) { |
| updateRedundancyStatistics(currentBucketHosts); |
| updateNoCopiesStatistics(currentBucketHosts); |
| } |
| |
| /** |
| * Provides the current redundancy of the bucket for this tracker |
| * |
| * @return number of redundant copies of the bucket for this tracker |
| */ |
| int getCurrentRedundancy() { |
| return currentRedundancy; |
| } |
| |
| private void updateNoCopiesStatistics(int currentBucketHosts) { |
| if (currentBucketHosts == 0 && hasEverHadCopies) { |
| incrementNoCopies(); |
| } else if (currentBucketHosts > 0) { |
| hasEverHadCopies = true; |
| decrementNoCopies(); |
| } |
| } |
| |
| private void decrementNoCopies() { |
| if (noCopiesDecrementOkay) { |
| noCopiesDecrementOkay = false; |
| regionRedundancyTracker.decrementNoCopiesBucketCount(); |
| } |
| } |
| |
| private void incrementNoCopies() { |
| if (!noCopiesDecrementOkay) { |
| noCopiesDecrementOkay = true; |
| regionRedundancyTracker.incrementNoCopiesBucketCount(); |
| } |
| } |
| |
| private void updateRedundancyStatistics(int updatedBucketHosts) { |
| int updatedRedundancy = updatedBucketHosts - 1; |
| updateCurrentRedundancy(updatedRedundancy); |
| if (updatedRedundancy < targetRedundancy) { |
| reportUpdatedBucketCount(updatedBucketHosts); |
| incrementLowRedundancy(); |
| } else if (updatedRedundancy == targetRedundancy) { |
| decrementLowRedundancy(); |
| redundancyEverSatisfied = true; |
| } |
| } |
| |
| private void decrementLowRedundancy() { |
| if (lowRedundancyDecrementOkay) { |
| lowRedundancyDecrementOkay = false; |
| regionRedundancyTracker.decrementLowRedundancyBucketCount(); |
| } |
| } |
| |
| private void incrementLowRedundancy() { |
| if (!lowRedundancyDecrementOkay) { |
| lowRedundancyDecrementOkay = true; |
| regionRedundancyTracker.incrementLowRedundancyBucketCount(); |
| } |
| } |
| |
| private void updateCurrentRedundancy(int updatedRedundancy) { |
| if (updatedRedundancy != currentRedundancy) { |
| regionRedundancyTracker.setActualRedundancy(updatedRedundancy); |
| currentRedundancy = updatedRedundancy; |
| } |
| } |
| |
| private void reportUpdatedBucketCount(int updatedBucketHosts) { |
| if (redundancyEverSatisfied) { |
| regionRedundancyTracker.reportBucketCount(updatedBucketHosts); |
| } |
| } |
| } |