/*
* Copyright (c) 2008-2017, Hazelcast, Inc. 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hazelcast.internal.nearcache.impl.invalidation;
import com.hazelcast.util.ConstructorFunction;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicLongArray;
import static com.hazelcast.util.ConcurrencyUtil.getOrPutIfAbsent;
import static com.hazelcast.util.UuidUtil.newUnsecureUUID;
/**
* Responsible for partition-sequence and partition-uuid generation.
* Used by invalidator to generate metadata for invalidation events.
*
* This metadata is used by {@link RepairingHandler} and {@link RepairingTask}
* to act against possible invalidation-miss and partition-loss.
*
* One instance per service is created. Used on member side.
*/
public class MetaDataGenerator {
final ConcurrentMap<String, AtomicLongArray> sequenceGenerators = new ConcurrentHashMap<String, AtomicLongArray>();
private final int partitionCount;
private final ConstructorFunction<String, AtomicLongArray> sequenceGeneratorConstructor
= new ConstructorFunction<String, AtomicLongArray>() {
@Override
public AtomicLongArray createNew(String arg) {
return new AtomicLongArray(partitionCount);
}
};
private final ConcurrentMap<Integer, UUID> uuids = new ConcurrentHashMap<Integer, UUID>();
private final ConstructorFunction<Integer, UUID> uuidConstructor
= new ConstructorFunction<Integer, UUID>() {
@Override
public UUID createNew(Integer partitionId) {
return newUnsecureUUID();
}
};
public MetaDataGenerator(int partitionCount) {
assert partitionCount > 0;
this.partitionCount = partitionCount;
}
public long currentSequence(String name, int partitionId) {
AtomicLongArray sequences = sequenceGenerators.get(name);
if (sequences == null) {
return 0;
}
return sequences.get(partitionId);
}
public long nextSequence(String name, int partitionId) {
return sequenceGenerator(name).incrementAndGet(partitionId);
}
public void setCurrentSequence(String name, int partitionId, long sequence) {
sequenceGenerator(name).set(partitionId, sequence);
}
private AtomicLongArray sequenceGenerator(String name) {
return getOrPutIfAbsent(sequenceGenerators, name, sequenceGeneratorConstructor);
}
public UUID getOrCreateUuid(int partitionId) {
return getOrPutIfAbsent(uuids, partitionId, uuidConstructor);
}
public UUID getUuidOrNull(int partitionId) {
return uuids.get(partitionId);
}
public void setUuid(int partitionId, UUID uuid) {
uuids.put(partitionId, uuid);
}
public void removeUuidAndSequence(final int partitionId) {
// remove uuid.
uuids.remove(partitionId);
// reset data-structures' sequence numbers
for (AtomicLongArray sequences : sequenceGenerators.values()) {
sequences.set(partitionId, 0);
}
}
public void destroyMetaDataFor(String dataStructureName) {
sequenceGenerators.remove(dataStructureName);
}
public void regenerateUuid(int partitionId) {
uuids.put(partitionId, uuidConstructor.createNew(partitionId));
}
}