Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
nl.renarj.jasdb.storage.indexing.IndexManagerImpl Maven / Gradle / Ivy
/*
* The JASDB software and code is Copyright protected 2011 and owned by Renze de Vries
*
* All the code and design principals in the codebase are also Copyright 2011
* protected and owned Renze de Vries. Any unauthorized usage of the code or the
* design and principals as in this code is prohibited.
*/
package nl.renarj.jasdb.storage.indexing;
import com.google.common.collect.Lists;
import com.google.inject.assistedinject.Assisted;
import nl.renarj.core.utilities.configuration.Configuration;
import nl.renarj.jasdb.api.SimpleEntity;
import nl.renarj.jasdb.api.metadata.Bag;
import nl.renarj.jasdb.api.metadata.IndexDefinition;
import nl.renarj.jasdb.api.metadata.MetadataStore;
import nl.renarj.jasdb.api.model.IndexManager;
import nl.renarj.jasdb.core.ConfigurationLoader;
import nl.renarj.jasdb.core.exceptions.ConfigurationException;
import nl.renarj.jasdb.core.exceptions.JasDBStorageException;
import nl.renarj.jasdb.index.Index;
import nl.renarj.jasdb.index.btreeplus.BTreeIndex;
import nl.renarj.jasdb.index.keys.keyinfo.KeyInfo;
import nl.renarj.jasdb.index.keys.keyinfo.KeyInfoImpl;
import nl.renarj.jasdb.index.keys.types.UUIDKeyType;
import nl.renarj.jasdb.index.search.CompositeIndexField;
import nl.renarj.jasdb.index.search.IndexField;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.inject.Inject;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@Component("IndexManager")
@Scope("prototype")
final public class IndexManagerImpl implements IndexManager {
private Logger log = LoggerFactory.getLogger(IndexManagerImpl.class);
private static final String INDEX_CONFIG_XPATH = "/jasdb/Index";
private static final String BAG_INDEX_NAME_SPLITTER = "_";
private static final String INDEX_EXTENSION = ".idx";
private static final String INDEX_EXTENSION_MULTI = ".idxm";
private Map> indexes = new ConcurrentHashMap<>();
@Inject
private ConfigurationLoader configurationLoader;
@Inject
private MetadataStore metadataStore;
private final String instanceId;
@Inject
public IndexManagerImpl(@Assisted String instanceId) {
this.instanceId = instanceId;
}
@Override
public void shutdownIndexes() throws JasDBStorageException {
log.info("Shutting down {} indexes", indexes.size());
for(String bagName : indexes.keySet()) {
for(Index index : indexes.get(bagName).values()) {
log.debug("Closing index: {} on bag: {}", index.getKeyInfo().getKeyName(), bagName);
index.close();
}
}
indexes.clear();
}
@Override
public void flush() throws JasDBStorageException {
for(Map.Entry> entry : indexes.entrySet()) {
log.debug("Flushing index for bag: {}", entry.getKey());
for(Index index : entry.getValue().values()) {
log.debug("Flushing index: {}", index);
index.flushIndex();
}
}
}
@Override
public void flush(String bagName) throws JasDBStorageException {
for(Index index : getIndexes(bagName).values()) {
log.debug("Flushing index: {}", index);
index.flushIndex();
}
}
@Override
public List getLoadedIndexes() {
List loadedIndexes = new ArrayList<>();
Collection> allBagIndexes = indexes.values();
for(Map bagIndexes : allBagIndexes) {
loadedIndexes.addAll(bagIndexes.values());
}
return loadedIndexes;
}
@Override
public Index getBestMatchingIndex(String bagName, Set fields) throws JasDBStorageException {
Collection indexes = getIndexes(bagName).values();
int bestMatch = 0;
Index currentBestMatch = null;
for(Index index : indexes) {
int match = index.match(fields);
if(match > 0 && match > bestMatch) {
bestMatch = match;
currentBestMatch = index;
}
}
return currentBestMatch;
}
@Override
public Map getIndexes(String bagName) throws JasDBStorageException {
log.debug("Loading indexes for bag: {}", bagName);
if(!indexes.containsKey(bagName)) {
log.debug("Indexes where not loaded or not present yet for bag: {}, attempt load", bagName);
loadIndexes(bagName);
}
if(indexes.containsKey(bagName)) {
log.debug("Indexes are present and loaded returning for bag: {}", bagName);
return new HashMap<>(indexes.get(bagName));
} else {
throw new JasDBStorageException("No indexes found for bag: " + bagName);
}
}
@Override
public Index getIndex(String bagName, String keyName) throws JasDBStorageException {
log.debug("Loading indexes for bag: {} and key: {}", bagName, keyName);
if(!indexes.containsKey(bagName)) {
log.debug("Indexes where not loaded or not present yet for bag: {}, attempt load", bagName);
loadIndexes(bagName);
}
if(indexes.containsKey(bagName)) {
Map bagIndexes = indexes.get(bagName);
if(bagIndexes.containsKey(keyName)) {
log.debug("Index found for key: {} in bag: {}", keyName, bagName);
return bagIndexes.get(keyName);
} else {
throw new JasDBStorageException("No index found for key: " + keyName + " in bag: " + bagName);
}
} else {
throw new JasDBStorageException("No indexes found for bag: " + bagName);
}
}
@Override
public void removeIndex(String bagName, String keyName) throws JasDBStorageException {
Index index = getIndex(bagName, keyName);
if(index != null) {
Map bagIndexes = indexes.get(bagName);
bagIndexes.remove(keyName);
KeyInfo keyInfo = index.getKeyInfo();
IndexDefinition definition = new IndexDefinition(keyInfo.getKeyName(), keyInfo.keyAsHeader(), keyInfo.valueAsHeader(), index.getIndexType());
metadataStore.removeBagIndex(instanceId, bagName, definition);
index.removeIndex();
} else {
throw new JasDBStorageException("Could not remove index, does not exist");
}
}
@Override
public Index createIndex(String bagName, CompositeIndexField compositeIndexFields, boolean unique, IndexField... values) throws JasDBStorageException {
KeyInfo keyInfo;
if(unique) {
keyInfo = new KeyInfoImpl(compositeIndexFields.getIndexFields(), guaranteeIdKey(values));
} else {
List indexFields = Lists.newArrayList(compositeIndexFields.getIndexFields());
indexFields.add(new IndexField(SimpleEntity.DOCUMENT_ID, new UUIDKeyType()));
keyInfo = new KeyInfoImpl(indexFields, Lists.newArrayList(values));
}
return createInStore(bagName, keyInfo);
}
@Override
public Index createIndex(String bagName, IndexField indexField, boolean unique, IndexField... valueFields) throws JasDBStorageException {
KeyInfo keyInfo;
if(unique) {
keyInfo = new KeyInfoImpl(indexField, guaranteeIdKey(valueFields));
} else {
keyInfo = new KeyInfoImpl(Lists.newArrayList(indexField, new IndexField(SimpleEntity.DOCUMENT_ID, new UUIDKeyType())), Lists.newArrayList(valueFields));
}
return createInStore(bagName, keyInfo);
}
private Index createInStore(String bagName, KeyInfo keyInfo) throws JasDBStorageException {
if(!indexes.containsKey(bagName)) {
loadIndexes(bagName);
}
Map bagIndexes = this.indexes.get(bagName);
if(bagIndexes != null && !bagIndexes.containsKey(keyInfo.getKeyName())) {
File indexFile = createIndexFile(bagName, keyInfo.getKeyName(), false);
try {
Index index = new BTreeIndex(indexFile, keyInfo);
configureIndex(IndexTypes.BTREE, index);
IndexDefinition definition = new IndexDefinition(keyInfo.getKeyName(), keyInfo.keyAsHeader(), keyInfo.valueAsHeader(), index.getIndexType());
metadataStore.addBagIndex(instanceId, bagName, definition);
bagIndexes.put(keyInfo.getKeyName(), index);
return index;
} catch(ConfigurationException e) {
throw new JasDBStorageException("Unable to create index, configuration error", e);
}
} else if(bagIndexes != null){
return bagIndexes.get(keyInfo.getKeyName());
} else {
return null;
}
}
private List guaranteeIdKey(IndexField... valueFields) throws JasDBStorageException {
Set fields = new HashSet<>();
List indexFields = new ArrayList<>();
for(IndexField valueField : valueFields) {
fields.add(valueField.getField());
indexFields.add(valueField);
}
if(!fields.contains(SimpleEntity.DOCUMENT_ID)) {
indexFields.add(new IndexField(SimpleEntity.DOCUMENT_ID, new UUIDKeyType()));
}
return indexFields;
}
private synchronized void loadIndexes(final String bagName) throws JasDBStorageException {
log.debug("Loading indexes for bag: {}", bagName);
if(!indexes.containsKey(bagName)) {
Bag bag = metadataStore.getBag(instanceId, bagName);
if(bag != null) {
Set indexDefinitions = new HashSet<>(bag.getIndexDefinitions());
log.info("Found {} potential indexes for bag: {}", indexDefinitions.size(), bagName);
Map bagIndexes = new HashMap<>();
for(IndexDefinition indexDefinition : indexDefinitions) {
Index index = loadIndex(bagName, indexDefinition);
bagIndexes.put(index.getKeyInfo().getKeyName(), index);
}
this.indexes.put(bagName, bagIndexes);
}
}
}
private Index loadIndex(String bagName, IndexDefinition indexDefinition) throws JasDBStorageException {
try {
KeyInfo keyInfo = new KeyInfoImpl(indexDefinition.getHeaderDescriptor(), indexDefinition.getValueDescriptor());
File indexFile = createIndexFile(bagName, indexDefinition.getIndexName(), false);
switch(IndexTypes.getTypeFor(indexDefinition.getIndexType())) {
case BTREE:
log.debug("Loaded BTree Index for key: {}", indexDefinition.getIndexName());
Index btreeIndex = new BTreeIndex(indexFile, keyInfo);
return configureIndex(IndexTypes.BTREE, btreeIndex);
default:
throw new JasDBStorageException("Reading from this index type: " + indexDefinition.getIndexName() +
" is not supported");
}
} catch(ConfigurationException e) {
throw new JasDBStorageException("Unable to load index, invalid configuration", e);
}
}
private Index configureIndex(IndexTypes indexType, Index indexPersister) throws ConfigurationException {
Configuration configuration = configurationLoader.getConfiguration();
Configuration indexConfig = configuration.getChildConfiguration(INDEX_CONFIG_XPATH + "[@Type='" + indexType.getName() + "']");
if(indexConfig != null) {
log.info("Using configuration for index type: {}", indexType.getName());
indexPersister.configure(indexConfig);
} else {
log.info("There is no configuration for index type: {} using defaults", indexType.getName());
}
return indexPersister;
}
private File createIndexFile(String bagName, String indexName, boolean multi) throws JasDBStorageException {
StringBuilder indexFileNameBuilder = new StringBuilder();
String extension = multi ? INDEX_EXTENSION_MULTI : INDEX_EXTENSION;
indexFileNameBuilder.append(bagName).append(BAG_INDEX_NAME_SPLITTER);
indexFileNameBuilder.append(indexName).append(extension);
String instancePath = metadataStore.getInstance(instanceId).getPath();
return new File(instancePath, indexFileNameBuilder.toString());
}
}