/*
* 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 org.apache.geode.cache.AttributesFactory;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.DataPolicy;
import org.apache.geode.cache.PartitionAttributes;
import org.apache.geode.cache.PartitionAttributesFactory;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.RegionAttributes;
import org.apache.geode.cache.RegionShortcut;
import org.apache.geode.cache.asyncqueue.AsyncEventQueue;
import org.apache.geode.cache.asyncqueue.internal.AsyncEventQueueFactoryImpl;
import org.apache.geode.cache.execute.FunctionService;
import org.apache.geode.cache.execute.ResultCollector;
import org.apache.geode.cache.lucene.internal.directory.DumpDirectoryFiles;
import org.apache.geode.cache.lucene.internal.filesystem.ChunkKey;
import org.apache.geode.cache.lucene.internal.filesystem.File;
import org.apache.geode.cache.lucene.internal.filesystem.FileSystemStats;
import org.apache.geode.cache.lucene.internal.repository.RepositoryManager;
import org.apache.geode.cache.lucene.internal.repository.serializer.HeterogeneousLuceneSerializer;
import org.apache.geode.cache.partition.PartitionListener;
import org.apache.geode.distributed.internal.DM;
import org.apache.geode.internal.cache.GemFireCacheImpl;
import org.apache.geode.internal.cache.PartitionedRegion;
/* wrapper of IndexWriter */
public class LuceneIndexForPartitionedRegion extends LuceneIndexImpl {
protected Region<String, File> fileRegion;
protected Region<ChunkKey, byte[]> chunkRegion;
protected final FileSystemStats fileSystemStats;
public LuceneIndexForPartitionedRegion(String indexName, String regionPath, Cache cache) {
super(indexName, regionPath, cache);
final String statsName = indexName + "-" + regionPath;
this.fileSystemStats = new FileSystemStats(cache.getDistributedSystem(), statsName);
}
protected RepositoryManager createRepositoryManager() {
RegionShortcut regionShortCut;
final boolean withPersistence = withPersistence();
RegionAttributes regionAttributes = dataRegion.getAttributes();
final boolean withStorage = regionAttributes.getPartitionAttributes().getLocalMaxMemory() > 0;
// TODO: 1) dataRegion should be withStorage
// 2) Persistence to Persistence
// 3) Replicate to Replicate, Partition To Partition
// 4) Offheap to Offheap
if (!withStorage) {
regionShortCut = RegionShortcut.PARTITION_PROXY;
} else if (withPersistence) {
// TODO: add PartitionedRegionAttributes instead
regionShortCut = RegionShortcut.PARTITION_PERSISTENT;
} else {
regionShortCut = RegionShortcut.PARTITION;
}
// create PR fileRegion, but not to create its buckets for now
final String fileRegionName = createFileRegionName();
PartitionAttributes partitionAttributes = dataRegion.getPartitionAttributes();
if (!fileRegionExists(fileRegionName)) {
fileRegion =
createFileRegion(regionShortCut, fileRegionName, partitionAttributes, regionAttributes);
}
// create PR chunkRegion, but not to create its buckets for now
final String chunkRegionName = createChunkRegionName();
// we will create RegionDirectories on the fly when data comes in
HeterogeneousLuceneSerializer mapper = new HeterogeneousLuceneSerializer(getFieldNames());
PartitionedRepositoryManager partitionedRepositoryManager =
new PartitionedRepositoryManager(this, mapper);
DM dm = ((GemFireCacheImpl) getCache()).getDistributedSystem().getDistributionManager();
LucenePrimaryBucketListener lucenePrimaryBucketListener =
new LucenePrimaryBucketListener(partitionedRepositoryManager, dm);
if (!chunkRegionExists(chunkRegionName)) {
chunkRegion = createChunkRegion(regionShortCut, fileRegionName, partitionAttributes,
chunkRegionName, regionAttributes, lucenePrimaryBucketListener);
}
fileSystemStats.setFileSupplier(() -> (int) getFileRegion().getLocalSize());
fileSystemStats.setChunkSupplier(() -> (int) getChunkRegion().getLocalSize());
fileSystemStats.setBytesSupplier(() -> getChunkRegion().getPrStats().getDataStoreBytesInUse());
return partitionedRepositoryManager;
}
public PartitionedRegion getFileRegion() {
return (PartitionedRegion) fileRegion;
}
public PartitionedRegion getChunkRegion() {
return (PartitionedRegion) chunkRegion;
}
public FileSystemStats getFileSystemStats() {
return fileSystemStats;
}
boolean fileRegionExists(String fileRegionName) {
return cache.<String, File>getRegion(fileRegionName) != null;
}
Region createFileRegion(final RegionShortcut regionShortCut, final String fileRegionName,
final PartitionAttributes partitionAttributes, final RegionAttributes regionAttributes) {
return createRegion(fileRegionName, regionShortCut, this.regionPath, partitionAttributes,
regionAttributes, null);
}
public String createFileRegionName() {
return LuceneServiceImpl.getUniqueIndexName(indexName, regionPath) + ".files";
}
boolean chunkRegionExists(String chunkRegionName) {
return cache.<ChunkKey, byte[]>getRegion(chunkRegionName) != null;
}
Region<ChunkKey, byte[]> createChunkRegion(final RegionShortcut regionShortCut,
final String fileRegionName, final PartitionAttributes partitionAttributes,
final String chunkRegionName, final RegionAttributes regionAttributes,
final PartitionListener lucenePrimaryBucketListener) {
return createRegion(chunkRegionName, regionShortCut, fileRegionName, partitionAttributes,
regionAttributes, lucenePrimaryBucketListener);
}
public String createChunkRegionName() {
return LuceneServiceImpl.getUniqueIndexName(indexName, regionPath) + ".chunks";
}
private PartitionAttributesFactory configureLuceneRegionAttributesFactory(
PartitionAttributesFactory attributesFactory,
PartitionAttributes<?, ?> dataRegionAttributes) {
attributesFactory.setTotalNumBuckets(dataRegionAttributes.getTotalNumBuckets());
attributesFactory.setRedundantCopies(dataRegionAttributes.getRedundantCopies());
return attributesFactory;
}
protected <K, V> Region<K, V> createRegion(final String regionName,
final RegionShortcut regionShortCut, final String colocatedWithRegionName,
final PartitionAttributes partitionAttributes, final RegionAttributes regionAttributes,
PartitionListener lucenePrimaryBucketListener) {
PartitionAttributesFactory partitionAttributesFactory =
new PartitionAttributesFactory<String, File>();
if (lucenePrimaryBucketListener != null) {
partitionAttributesFactory.addPartitionListener(lucenePrimaryBucketListener);
}
partitionAttributesFactory.setColocatedWith(colocatedWithRegionName);
configureLuceneRegionAttributesFactory(partitionAttributesFactory, partitionAttributes);
// Create AttributesFactory based on input RegionShortcut
RegionAttributes baseAttributes = this.cache.getRegionAttributes(regionShortCut.toString());
AttributesFactory factory = new AttributesFactory(baseAttributes);
factory.setPartitionAttributes(partitionAttributesFactory.create());
factory.setDiskStoreName(regionAttributes.getDiskStoreName());
RegionAttributes<K, V> attributes = factory.create();
return createRegion(regionName, attributes);
}
public void close() {
// TODO Auto-generated method stub
}
@Override
public void dumpFiles(final String directory) {
ResultCollector results = FunctionService.onRegion(getDataRegion())
.withArgs(new String[] {directory, indexName}).execute(DumpDirectoryFiles.ID);
results.getResult();
}
}