/*
* 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.cache.lucene.internal;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.geode.InternalGemFireError;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.execute.RegionFunctionContext;
import org.apache.geode.cache.lucene.internal.repository.IndexRepository;
import org.apache.geode.cache.lucene.internal.repository.RepositoryManager;
import org.apache.geode.cache.lucene.internal.repository.serializer.LuceneSerializer;
import org.apache.geode.internal.cache.BucketNotFoundException;
import org.apache.geode.internal.cache.BucketRegion;
import org.apache.geode.internal.cache.PartitionedRegion;
import org.apache.geode.internal.cache.execute.InternalRegionFunctionContext;
public abstract class AbstractPartitionedRepositoryManager implements RepositoryManager {
/**
* map of the parent bucket region to the index repository
*
* This is based on the BucketRegion in case a bucket is rebalanced, we don't want to return a
* stale index repository. If a bucket moves off of this node and comes back, it will have a new
* BucketRegion object.
*
* It is weak so that the old BucketRegion will be garbage collected.
*/
protected final ConcurrentHashMap<Integer, IndexRepository> indexRepositories =
new ConcurrentHashMap<Integer, IndexRepository>();
/** The user region for this index */
protected final PartitionedRegion userRegion;
protected final LuceneSerializer serializer;
protected final LuceneIndexImpl index;
public AbstractPartitionedRepositoryManager(LuceneIndexImpl index, LuceneSerializer serializer) {
this.index = index;
this.userRegion = (PartitionedRegion) index.getCache().getRegion(index.getRegionPath());
this.serializer = serializer;
}
@Override
public IndexRepository getRepository(Region region, Object key, Object callbackArg)
throws BucketNotFoundException {
BucketRegion userBucket = userRegion.getBucketRegion(key, callbackArg);
if (userBucket == null) {
throw new BucketNotFoundException("User bucket was not found for region " + region + "key "
+ key + " callbackarg " + callbackArg);
}
return getRepository(userBucket.getId());
}
@Override
public Collection<IndexRepository> getRepositories(RegionFunctionContext ctx)
throws BucketNotFoundException {
Region<Object, Object> region = ctx.getDataSet();
Set<Integer> buckets = ((InternalRegionFunctionContext) ctx).getLocalBucketSet(region);
ArrayList<IndexRepository> repos = new ArrayList<IndexRepository>(buckets.size());
for (Integer bucketId : buckets) {
BucketRegion userBucket = userRegion.getDataStore().getLocalBucketById(bucketId);
if (userBucket == null) {
throw new BucketNotFoundException(
"User bucket was not found for region " + region + "bucket id " + bucketId);
} else {
repos.add(getRepository(userBucket.getId()));
}
}
return repos;
}
public abstract IndexRepository createOneIndexRepository(final Integer bucketId,
LuceneSerializer serializer, LuceneIndexImpl index, PartitionedRegion userRegion)
throws IOException;
/**
* Return the repository for a given user bucket
*/
protected IndexRepository getRepository(Integer bucketId) throws BucketNotFoundException {
IndexRepository repo = indexRepositories.get(bucketId);
if (repo != null && !repo.isClosed()) {
return repo;
}
repo = indexRepositories.compute(bucketId, (key, oldRepository) -> {
if (oldRepository != null && !oldRepository.isClosed()) {
return oldRepository;
}
if (oldRepository != null) {
oldRepository.cleanup();
}
try {
return createOneIndexRepository(bucketId, serializer, index, userRegion);
} catch (IOException e) {
throw new InternalGemFireError("Unable to create index repository", e);
}
});
if (repo == null) {
throw new BucketNotFoundException(
"Colocated index buckets not found for bucket id " + bucketId);
}
return repo;
}
}