package com.twitter.search.common.schema; import java.util.Collection; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; import javax.annotation.Nullable; import com.google.common.base.Preconditions; import com.google.common.base.Predicate; import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableMap; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.facet.FacetsConfig; import org.apache.lucene.index.FieldInfos; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.twitter.search.common.features.thrift.ThriftSearchFeatureSchema; import com.twitter.search.common.schema.base.FeatureConfiguration; import com.twitter.search.common.schema.base.FieldWeightDefault; import com.twitter.search.common.schema.base.ImmutableSchemaInterface; import com.twitter.search.common.schema.base.Schema; import com.twitter.search.common.schema.thriftjava.ThriftAnalyzer; import com.twitter.search.common.schema.thriftjava.ThriftCSFType; import com.twitter.search.common.schema.thriftjava.ThriftFieldConfiguration; /** * A schema implementation that allow minor version increments at run time. */ public class DynamicSchema implements Schema { private static final Logger LOG = LoggerFactory.getLogger(DynamicSchema.class); private final AtomicReference schema; public DynamicSchema(ImmutableSchema schema) { this.schema = new AtomicReference<>(schema); } public ImmutableSchemaInterface getSchemaSnapshot() { return schema.get(); } /** * Update the schema reference inside this DynamicSchema. */ public synchronized void updateSchema(ImmutableSchema newSchema) throws SchemaUpdateException { ImmutableSchema oldSchema = schema.get(); if (newSchema.getMajorVersionNumber() != oldSchema.getMajorVersionNumber()) { throw new SchemaUpdateException("Dynamic major version update is not supported."); } else { if (newSchema.getMinorVersionNumber() <= oldSchema.getMinorVersionNumber()) { throw new SchemaUpdateException("Dynamic backward minor version update is not supported."); } else { LOG.info("DynamicSchema accepted update. Old version is {}.{}; new version is {}.{}", oldSchema.getMajorVersionNumber(), oldSchema.getMinorVersionNumber(), newSchema.getMajorVersionNumber(), newSchema.getMinorVersionNumber()); schema.set(newSchema); } } } public static class SchemaUpdateException extends Exception { public SchemaUpdateException(String message) { super(message); } } // The below are all methods in the Schema interface delegated to the underlying ImmutableSchema. // The below is generated by IntelliJ, and reviewers can stop reviewing this file here. // If you are adding logic into this class, please do so above this line. @Override public FieldInfos getLuceneFieldInfos( Predicate acceptedFields) { return schema.get().getLuceneFieldInfos(acceptedFields); } @Override public FacetsConfig getFacetsConfig() { return schema.get().getFacetsConfig(); } @Override public Analyzer getDefaultAnalyzer( ThriftAnalyzer override) { return schema.get().getDefaultAnalyzer(override); } @Override public ImmutableCollection getFieldInfos() { return schema.get().getFieldInfos(); } @Override public boolean hasField(int fieldConfigId) { return schema.get().hasField(fieldConfigId); } @Override public boolean hasField(String fieldName) { return schema.get().hasField(fieldName); } @Override @Nullable public FieldInfo getFieldInfo(int fieldConfigId) { return schema.get().getFieldInfo(fieldConfigId); } @Override @Nullable public FieldInfo getFieldInfo(String fieldName) { return schema.get().getFieldInfo(fieldName); } @Override public String getFieldName(int fieldConfigId) { return schema.get().getFieldName(fieldConfigId); } @Override public FieldInfo getFieldInfo(int fieldConfigId, ThriftFieldConfiguration override) { return schema.get().getFieldInfo(fieldConfigId, override); } @Override public int getNumFacetFields() { return schema.get().getNumFacetFields(); } @Override public FieldInfo getFacetFieldByFacetName( String facetName) { return schema.get().getFacetFieldByFacetName(facetName); } @Override public FieldInfo getFacetFieldByFieldName( String fieldName) { return schema.get().getFacetFieldByFieldName(fieldName); } @Override public Collection getFacetFields() { return schema.get().getFacetFields(); } @Override public Collection getCsfFacetFields() { return schema.get().getCsfFacetFields(); } @Override public String getVersionDescription() { return schema.get().getVersionDescription(); } @Override public int getMajorVersionNumber() { return schema.get().getMajorVersionNumber(); } @Override public int getMinorVersionNumber() { return schema.get().getMinorVersionNumber(); } @Override public boolean isVersionOfficial() { return schema.get().isVersionOfficial(); } @Override public Map getFieldWeightMap() { return schema.get().getFieldWeightMap(); } @Override public FeatureConfiguration getFeatureConfigurationByName( String featureName) { return schema.get().getFeatureConfigurationByName(featureName); } @Override public FeatureConfiguration getFeatureConfigurationById(int featureFieldId) { return Preconditions.checkNotNull(schema.get().getFeatureConfigurationById(featureFieldId)); } @Override @Nullable public ThriftCSFType getCSFFieldType( String fieldName) { return schema.get().getCSFFieldType(fieldName); } @Override public ThriftSearchFeatureSchema getSearchFeatureSchema() { return schema.get().getSearchFeatureSchema(); } @Override public ImmutableMap getFeatureIdToFeatureConfig() { return schema.get().getFeatureIdToFeatureConfig(); } @Override public ImmutableMap getFeatureNameToFeatureConfig() { return schema.get().getFeatureNameToFeatureConfig(); } }