| /* |
| * 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.cassandra.thrift; |
| |
| import java.nio.ByteBuffer; |
| import java.util.*; |
| |
| import com.google.common.annotations.VisibleForTesting; |
| import com.google.common.base.Strings; |
| import com.google.common.collect.Maps; |
| |
| import org.apache.cassandra.cache.CachingOptions; |
| import org.apache.cassandra.config.*; |
| import org.apache.cassandra.cql3.ColumnIdentifier; |
| import org.apache.cassandra.cql3.Operator; |
| import org.apache.cassandra.cql3.UntypedResultSet; |
| import org.apache.cassandra.db.ColumnFamilyType; |
| import org.apache.cassandra.schema.LegacySchemaTables; |
| import org.apache.cassandra.db.WriteType; |
| import org.apache.cassandra.db.composites.CellNameType; |
| import org.apache.cassandra.db.composites.CellNames; |
| import org.apache.cassandra.db.marshal.*; |
| import org.apache.cassandra.exceptions.*; |
| import org.apache.cassandra.io.compress.CompressionParameters; |
| import org.apache.cassandra.locator.AbstractReplicationStrategy; |
| import org.apache.cassandra.locator.LocalStrategy; |
| import org.apache.cassandra.serializers.MarshalException; |
| import org.apache.cassandra.utils.ByteBufferUtil; |
| import org.apache.cassandra.utils.UUIDGen; |
| |
| /** |
| * Static utility methods to convert internal structure to and from thrift ones. |
| */ |
| public class ThriftConversion |
| { |
| public static org.apache.cassandra.db.ConsistencyLevel fromThrift(ConsistencyLevel cl) |
| { |
| switch (cl) |
| { |
| case ANY: return org.apache.cassandra.db.ConsistencyLevel.ANY; |
| case ONE: return org.apache.cassandra.db.ConsistencyLevel.ONE; |
| case TWO: return org.apache.cassandra.db.ConsistencyLevel.TWO; |
| case THREE: return org.apache.cassandra.db.ConsistencyLevel.THREE; |
| case QUORUM: return org.apache.cassandra.db.ConsistencyLevel.QUORUM; |
| case ALL: return org.apache.cassandra.db.ConsistencyLevel.ALL; |
| case LOCAL_QUORUM: return org.apache.cassandra.db.ConsistencyLevel.LOCAL_QUORUM; |
| case EACH_QUORUM: return org.apache.cassandra.db.ConsistencyLevel.EACH_QUORUM; |
| case SERIAL: return org.apache.cassandra.db.ConsistencyLevel.SERIAL; |
| case LOCAL_SERIAL: return org.apache.cassandra.db.ConsistencyLevel.LOCAL_SERIAL; |
| case LOCAL_ONE: return org.apache.cassandra.db.ConsistencyLevel.LOCAL_ONE; |
| } |
| throw new AssertionError(); |
| } |
| |
| public static ConsistencyLevel toThrift(org.apache.cassandra.db.ConsistencyLevel cl) |
| { |
| switch (cl) |
| { |
| case ANY: return ConsistencyLevel.ANY; |
| case ONE: return ConsistencyLevel.ONE; |
| case TWO: return ConsistencyLevel.TWO; |
| case THREE: return ConsistencyLevel.THREE; |
| case QUORUM: return ConsistencyLevel.QUORUM; |
| case ALL: return ConsistencyLevel.ALL; |
| case LOCAL_QUORUM: return ConsistencyLevel.LOCAL_QUORUM; |
| case EACH_QUORUM: return ConsistencyLevel.EACH_QUORUM; |
| case SERIAL: return ConsistencyLevel.SERIAL; |
| case LOCAL_SERIAL: return ConsistencyLevel.LOCAL_SERIAL; |
| case LOCAL_ONE: return ConsistencyLevel.LOCAL_ONE; |
| } |
| throw new AssertionError(); |
| } |
| |
| // We never return, but returning a RuntimeException allows to write "throw rethrow(e)" without java complaining |
| // for methods that have a return value. |
| public static RuntimeException rethrow(RequestExecutionException e) throws UnavailableException, TimedOutException |
| { |
| if (e instanceof RequestFailureException) |
| throw toThrift((RequestFailureException)e); |
| else if (e instanceof RequestTimeoutException) |
| throw toThrift((RequestTimeoutException)e); |
| else |
| throw new UnavailableException(); |
| } |
| |
| public static InvalidRequestException toThrift(RequestValidationException e) |
| { |
| return new InvalidRequestException(e.getMessage()); |
| } |
| |
| public static UnavailableException toThrift(org.apache.cassandra.exceptions.UnavailableException e) |
| { |
| return new UnavailableException(); |
| } |
| |
| public static AuthenticationException toThrift(org.apache.cassandra.exceptions.AuthenticationException e) |
| { |
| return new AuthenticationException(e.getMessage()); |
| } |
| |
| public static TimedOutException toThrift(RequestTimeoutException e) |
| { |
| TimedOutException toe = new TimedOutException(); |
| if (e instanceof WriteTimeoutException) |
| { |
| WriteTimeoutException wte = (WriteTimeoutException)e; |
| toe.setAcknowledged_by(wte.received); |
| if (wte.writeType == WriteType.BATCH_LOG) |
| toe.setAcknowledged_by_batchlog(false); |
| else if (wte.writeType == WriteType.BATCH) |
| toe.setAcknowledged_by_batchlog(true); |
| else if (wte.writeType == WriteType.CAS) |
| toe.setPaxos_in_progress(true); |
| } |
| return toe; |
| } |
| |
| // Thrift does not support RequestFailureExceptions, so we translate them into timeouts |
| public static TimedOutException toThrift(RequestFailureException e) |
| { |
| return new TimedOutException(); |
| } |
| |
| public static List<org.apache.cassandra.db.IndexExpression> indexExpressionsFromThrift(List<IndexExpression> exprs) |
| { |
| if (exprs == null) |
| return null; |
| |
| if (exprs.isEmpty()) |
| return Collections.emptyList(); |
| |
| List<org.apache.cassandra.db.IndexExpression> converted = new ArrayList<>(exprs.size()); |
| for (IndexExpression expr : exprs) |
| { |
| converted.add(new org.apache.cassandra.db.IndexExpression(expr.column_name, |
| Operator.valueOf(expr.op.name()), |
| expr.value)); |
| } |
| return converted; |
| } |
| |
| public static KSMetaData fromThrift(KsDef ksd, CFMetaData... cfDefs) throws ConfigurationException |
| { |
| Class<? extends AbstractReplicationStrategy> cls = AbstractReplicationStrategy.getClass(ksd.strategy_class); |
| if (cls.equals(LocalStrategy.class)) |
| throw new ConfigurationException("Unable to use given strategy class: LocalStrategy is reserved for internal use."); |
| |
| return new KSMetaData(ksd.name, |
| cls, |
| ksd.strategy_options == null ? Collections.<String, String>emptyMap() : ksd.strategy_options, |
| ksd.durable_writes, |
| Arrays.asList(cfDefs)); |
| } |
| |
| public static KsDef toThrift(KSMetaData ksm) |
| { |
| List<CfDef> cfDefs = new ArrayList<>(ksm.cfMetaData().size()); |
| for (CFMetaData cfm : ksm.cfMetaData().values()) |
| if (cfm.isThriftCompatible()) // Don't expose CF that cannot be correctly handle by thrift; see CASSANDRA-4377 for further details |
| cfDefs.add(toThrift(cfm)); |
| |
| KsDef ksdef = new KsDef(ksm.name, ksm.strategyClass.getName(), cfDefs); |
| ksdef.setStrategy_options(ksm.strategyOptions); |
| ksdef.setDurable_writes(ksm.durableWrites); |
| |
| return ksdef; |
| } |
| |
| public static CFMetaData fromThrift(CfDef cf_def) |
| throws org.apache.cassandra.exceptions.InvalidRequestException, ConfigurationException |
| { |
| return internalFromThrift(cf_def, Collections.<ColumnDefinition>emptyList()); |
| } |
| |
| public static CFMetaData fromThriftForUpdate(CfDef cf_def, CFMetaData toUpdate) |
| throws org.apache.cassandra.exceptions.InvalidRequestException, ConfigurationException |
| { |
| return internalFromThrift(cf_def, toUpdate.allColumns()); |
| } |
| |
| // Convert a thrift CfDef, given a list of ColumnDefinitions to copy over to the created CFMetadata before the CQL metadata are rebuild |
| private static CFMetaData internalFromThrift(CfDef cf_def, Collection<ColumnDefinition> previousCQLMetadata) |
| throws org.apache.cassandra.exceptions.InvalidRequestException, ConfigurationException |
| { |
| ColumnFamilyType cfType = ColumnFamilyType.create(cf_def.column_type); |
| if (cfType == null) |
| throw new org.apache.cassandra.exceptions.InvalidRequestException("Invalid column type " + cf_def.column_type); |
| |
| applyImplicitDefaults(cf_def); |
| |
| try |
| { |
| AbstractType<?> rawComparator = TypeParser.parse(cf_def.comparator_type); |
| AbstractType<?> subComparator = cfType == ColumnFamilyType.Standard |
| ? null |
| : cf_def.subcomparator_type == null ? BytesType.instance : TypeParser.parse(cf_def.subcomparator_type); |
| |
| AbstractType<?> fullRawComparator = CFMetaData.makeRawAbstractType(rawComparator, subComparator); |
| |
| AbstractType<?> keyValidator = cf_def.isSetKey_validation_class() ? TypeParser.parse(cf_def.key_validation_class) : null; |
| |
| // Convert the REGULAR definitions from the input CfDef |
| List<ColumnDefinition> defs = fromThrift(cf_def.keyspace, cf_def.name, rawComparator, subComparator, cf_def.column_metadata); |
| |
| // Add the keyAlias if there is one, since that's on CQL metadata that thrift can actually change (for |
| // historical reasons) |
| boolean hasKeyAlias = cf_def.isSetKey_alias() && keyValidator != null && !(keyValidator instanceof CompositeType); |
| if (hasKeyAlias) |
| defs.add(ColumnDefinition.partitionKeyDef(cf_def.keyspace, cf_def.name, cf_def.key_alias, keyValidator, null)); |
| |
| // for Thrift updates, we should be calculating denseness from just the regular columns & comparator |
| boolean isDense = CFMetaData.calculateIsDense(fullRawComparator, defs); |
| |
| // Now add any CQL metadata that we want to copy, skipping the keyAlias if there was one |
| for (ColumnDefinition def : previousCQLMetadata) |
| { |
| // skip all pre-existing REGULAR columns |
| if (def.kind == ColumnDefinition.Kind.REGULAR) |
| continue; |
| |
| // skip previous PARTITION_KEY column def if key_alias has been set by this update already (overwritten) |
| if (def.kind == ColumnDefinition.Kind.PARTITION_KEY && hasKeyAlias) |
| continue; |
| |
| // the table switched from DENSE to SPARSE by adding one or more REGULAR columns; |
| // in this case we should now drop the COMPACT_VALUE column |
| if (def.kind == ColumnDefinition.Kind.COMPACT_VALUE && !isDense) |
| continue; |
| |
| // skip CLUSTERING_COLUMN column(s) of a sparse table, if: |
| // a) this is a Standard columnfamily *OR* b) it's a Super columnfamily and the second (subcolumn) component; |
| // in other words, only keep the clustering column in sparse tables if it's the first (super) component |
| // of a super column family |
| if (def.kind == ColumnDefinition.Kind.CLUSTERING_COLUMN && !isDense) |
| if (cfType == ColumnFamilyType.Standard || def.position() != 0) |
| continue; |
| |
| defs.add(def); |
| } |
| |
| CellNameType comparator = CellNames.fromAbstractType(fullRawComparator, CFMetaData.calculateIsDense(fullRawComparator, defs)); |
| |
| UUID cfId = Schema.instance.getId(cf_def.keyspace, cf_def.name); |
| if (cfId == null) |
| cfId = UUIDGen.getTimeUUID(); |
| |
| // set isDense now so that it doesn't get re-calculated incorrectly later in rebuild() b/c of defined clusterings |
| CFMetaData newCFMD = new CFMetaData(cf_def.keyspace, cf_def.name, cfType, comparator, cfId).isDense(isDense); |
| |
| newCFMD.addAllColumnDefinitions(defs); |
| |
| if (keyValidator != null) |
| newCFMD.keyValidator(keyValidator); |
| if (cf_def.isSetGc_grace_seconds()) |
| newCFMD.gcGraceSeconds(cf_def.gc_grace_seconds); |
| if (cf_def.isSetMin_compaction_threshold()) |
| newCFMD.minCompactionThreshold(cf_def.min_compaction_threshold); |
| if (cf_def.isSetMax_compaction_threshold()) |
| newCFMD.maxCompactionThreshold(cf_def.max_compaction_threshold); |
| if (cf_def.isSetCompaction_strategy()) |
| newCFMD.compactionStrategyClass(CFMetaData.createCompactionStrategy(cf_def.compaction_strategy)); |
| if (cf_def.isSetCompaction_strategy_options()) |
| newCFMD.compactionStrategyOptions(new HashMap<>(cf_def.compaction_strategy_options)); |
| if (cf_def.isSetBloom_filter_fp_chance()) |
| newCFMD.bloomFilterFpChance(cf_def.bloom_filter_fp_chance); |
| if (cf_def.isSetMemtable_flush_period_in_ms()) |
| newCFMD.memtableFlushPeriod(cf_def.memtable_flush_period_in_ms); |
| if (cf_def.isSetCaching() || cf_def.isSetCells_per_row_to_cache()) |
| newCFMD.caching(CachingOptions.fromThrift(cf_def.caching, cf_def.cells_per_row_to_cache)); |
| if (cf_def.isSetRead_repair_chance()) |
| newCFMD.readRepairChance(cf_def.read_repair_chance); |
| if (cf_def.isSetDefault_time_to_live()) |
| newCFMD.defaultTimeToLive(cf_def.default_time_to_live); |
| if (cf_def.isSetDclocal_read_repair_chance()) |
| newCFMD.dcLocalReadRepairChance(cf_def.dclocal_read_repair_chance); |
| if (cf_def.isSetMin_index_interval()) |
| newCFMD.minIndexInterval(cf_def.min_index_interval); |
| if (cf_def.isSetMax_index_interval()) |
| newCFMD.maxIndexInterval(cf_def.max_index_interval); |
| if (cf_def.isSetSpeculative_retry()) |
| newCFMD.speculativeRetry(CFMetaData.SpeculativeRetry.fromString(cf_def.speculative_retry)); |
| if (cf_def.isSetTriggers()) |
| newCFMD.triggers(triggerDefinitionsFromThrift(cf_def.triggers)); |
| |
| return newCFMD.comment(cf_def.comment) |
| .defaultValidator(TypeParser.parse(cf_def.default_validation_class)) |
| .compressionParameters(CompressionParameters.create(cf_def.compression_options)) |
| .rebuild(); |
| } |
| catch (SyntaxException | MarshalException e) |
| { |
| throw new ConfigurationException(e.getMessage()); |
| } |
| } |
| |
| /** applies implicit defaults to cf definition. useful in updates */ |
| private static void applyImplicitDefaults(org.apache.cassandra.thrift.CfDef cf_def) |
| { |
| if (!cf_def.isSetComment()) |
| cf_def.setComment(""); |
| if (!cf_def.isSetMin_compaction_threshold()) |
| cf_def.setMin_compaction_threshold(CFMetaData.DEFAULT_MIN_COMPACTION_THRESHOLD); |
| if (!cf_def.isSetMax_compaction_threshold()) |
| cf_def.setMax_compaction_threshold(CFMetaData.DEFAULT_MAX_COMPACTION_THRESHOLD); |
| if (cf_def.compaction_strategy == null) |
| cf_def.compaction_strategy = CFMetaData.DEFAULT_COMPACTION_STRATEGY_CLASS.getSimpleName(); |
| if (cf_def.compaction_strategy_options == null) |
| cf_def.compaction_strategy_options = Collections.emptyMap(); |
| if (!cf_def.isSetCompression_options()) |
| cf_def.setCompression_options(Collections.singletonMap(CompressionParameters.SSTABLE_COMPRESSION, CFMetaData.DEFAULT_COMPRESSOR)); |
| if (!cf_def.isSetDefault_time_to_live()) |
| cf_def.setDefault_time_to_live(CFMetaData.DEFAULT_DEFAULT_TIME_TO_LIVE); |
| if (!cf_def.isSetDclocal_read_repair_chance()) |
| cf_def.setDclocal_read_repair_chance(CFMetaData.DEFAULT_DCLOCAL_READ_REPAIR_CHANCE); |
| |
| // if index_interval was set, use that for the min_index_interval default |
| if (!cf_def.isSetMin_index_interval()) |
| { |
| if (cf_def.isSetIndex_interval()) |
| cf_def.setMin_index_interval(cf_def.getIndex_interval()); |
| else |
| cf_def.setMin_index_interval(CFMetaData.DEFAULT_MIN_INDEX_INTERVAL); |
| } |
| |
| if (!cf_def.isSetMax_index_interval()) |
| { |
| // ensure the max is at least as large as the min |
| cf_def.setMax_index_interval(Math.max(cf_def.min_index_interval, CFMetaData.DEFAULT_MAX_INDEX_INTERVAL)); |
| } |
| } |
| |
| /** |
| * Create CFMetaData from thrift {@link CqlRow} that contains columns from schema_columnfamilies. |
| * |
| * @param columnsRes CqlRow containing columns from schema_columnfamilies. |
| * @return CFMetaData derived from CqlRow |
| */ |
| public static CFMetaData fromThriftCqlRow(CqlRow cf, CqlResult columnsRes) |
| { |
| UntypedResultSet.Row cfRow = new UntypedResultSet.Row(convertThriftCqlRow(cf)); |
| |
| List<Map<String, ByteBuffer>> cols = new ArrayList<>(columnsRes.rows.size()); |
| for (CqlRow row : columnsRes.rows) |
| cols.add(convertThriftCqlRow(row)); |
| UntypedResultSet colsRows = UntypedResultSet.create(cols); |
| |
| return LegacySchemaTables.createTableFromTableRowAndColumnRows(cfRow, colsRows); |
| } |
| |
| private static Map<String, ByteBuffer> convertThriftCqlRow(CqlRow row) |
| { |
| Map<String, ByteBuffer> m = new HashMap<>(); |
| for (org.apache.cassandra.thrift.Column column : row.getColumns()) |
| m.put(UTF8Type.instance.getString(column.bufferForName()), column.value); |
| return m; |
| } |
| |
| public static CfDef toThrift(CFMetaData cfm) |
| { |
| CfDef def = new CfDef(cfm.ksName, cfm.cfName); |
| def.setColumn_type(cfm.cfType.name()); |
| |
| if (cfm.isSuper()) |
| { |
| def.setComparator_type(cfm.comparator.subtype(0).toString()); |
| def.setSubcomparator_type(cfm.comparator.subtype(1).toString()); |
| } |
| else |
| { |
| def.setComparator_type(cfm.comparator.toString()); |
| } |
| |
| def.setComment(Strings.nullToEmpty(cfm.getComment())); |
| def.setRead_repair_chance(cfm.getReadRepairChance()); |
| def.setDclocal_read_repair_chance(cfm.getDcLocalReadRepairChance()); |
| def.setGc_grace_seconds(cfm.getGcGraceSeconds()); |
| def.setDefault_validation_class(cfm.getDefaultValidator().toString()); |
| def.setKey_validation_class(cfm.getKeyValidator().toString()); |
| def.setMin_compaction_threshold(cfm.getMinCompactionThreshold()); |
| def.setMax_compaction_threshold(cfm.getMaxCompactionThreshold()); |
| // We only return the alias if only one is set since thrift don't know about multiple key aliases |
| if (cfm.partitionKeyColumns().size() == 1) |
| def.setKey_alias(cfm.partitionKeyColumns().get(0).name.bytes); |
| def.setColumn_metadata(columnDefinitionsToThrift(cfm.allColumns())); |
| def.setCompaction_strategy(cfm.compactionStrategyClass.getName()); |
| def.setCompaction_strategy_options(new HashMap<>(cfm.compactionStrategyOptions)); |
| def.setCompression_options(cfm.compressionParameters.asThriftOptions()); |
| def.setBloom_filter_fp_chance(cfm.getBloomFilterFpChance()); |
| def.setMin_index_interval(cfm.getMinIndexInterval()); |
| def.setMax_index_interval(cfm.getMaxIndexInterval()); |
| def.setMemtable_flush_period_in_ms(cfm.getMemtableFlushPeriod()); |
| def.setCaching(cfm.getCaching().toThriftCaching()); |
| def.setCells_per_row_to_cache(cfm.getCaching().toThriftCellsPerRow()); |
| def.setDefault_time_to_live(cfm.getDefaultTimeToLive()); |
| def.setSpeculative_retry(cfm.getSpeculativeRetry().toString()); |
| def.setTriggers(triggerDefinitionsToThrift(cfm.getTriggers().values())); |
| |
| return def; |
| } |
| |
| public static ColumnDefinition fromThrift(String ksName, |
| String cfName, |
| AbstractType<?> thriftComparator, |
| AbstractType<?> thriftSubcomparator, |
| ColumnDef thriftColumnDef) |
| throws SyntaxException, ConfigurationException |
| { |
| // For super columns, the componentIndex is 1 because the ColumnDefinition applies to the column component. |
| Integer componentIndex = thriftSubcomparator != null ? 1 : null; |
| AbstractType<?> comparator = thriftSubcomparator == null ? thriftComparator : thriftSubcomparator; |
| try |
| { |
| comparator.validate(thriftColumnDef.name); |
| } |
| catch (MarshalException e) |
| { |
| throw new ConfigurationException(String.format("Column name %s is not valid for comparator %s", ByteBufferUtil.bytesToHex(thriftColumnDef.name), comparator)); |
| } |
| |
| return new ColumnDefinition(ksName, |
| cfName, |
| new ColumnIdentifier(ByteBufferUtil.clone(thriftColumnDef.name), comparator), |
| TypeParser.parse(thriftColumnDef.validation_class), |
| thriftColumnDef.index_type == null ? null : org.apache.cassandra.config.IndexType.valueOf(thriftColumnDef.index_type.name()), |
| thriftColumnDef.index_options, |
| thriftColumnDef.index_name, |
| componentIndex, |
| ColumnDefinition.Kind.REGULAR); |
| } |
| |
| private static List<ColumnDefinition> fromThrift(String ksName, |
| String cfName, |
| AbstractType<?> thriftComparator, |
| AbstractType<?> thriftSubcomparator, |
| List<ColumnDef> thriftDefs) |
| throws SyntaxException, ConfigurationException |
| { |
| if (thriftDefs == null) |
| return new ArrayList<>(); |
| |
| List<ColumnDefinition> defs = new ArrayList<>(thriftDefs.size()); |
| for (ColumnDef thriftColumnDef : thriftDefs) |
| defs.add(fromThrift(ksName, cfName, thriftComparator, thriftSubcomparator, thriftColumnDef)); |
| |
| return defs; |
| } |
| |
| @VisibleForTesting |
| public static ColumnDef toThrift(ColumnDefinition column) |
| { |
| ColumnDef cd = new ColumnDef(); |
| |
| cd.setName(ByteBufferUtil.clone(column.name.bytes)); |
| cd.setValidation_class(column.type.toString()); |
| cd.setIndex_type(column.getIndexType() == null ? null : org.apache.cassandra.thrift.IndexType.valueOf(column.getIndexType().name())); |
| cd.setIndex_name(column.getIndexName()); |
| cd.setIndex_options(column.getIndexOptions() == null ? null : Maps.newHashMap(column.getIndexOptions())); |
| |
| return cd; |
| } |
| |
| private static List<ColumnDef> columnDefinitionsToThrift(Collection<ColumnDefinition> columns) |
| { |
| List<ColumnDef> thriftDefs = new ArrayList<>(columns.size()); |
| for (ColumnDefinition def : columns) |
| if (def.kind == ColumnDefinition.Kind.REGULAR) |
| thriftDefs.add(ThriftConversion.toThrift(def)); |
| return thriftDefs; |
| } |
| |
| private static Map<String, TriggerDefinition> triggerDefinitionsFromThrift(List<TriggerDef> thriftDefs) |
| { |
| Map<String, TriggerDefinition> triggerDefinitions = new HashMap<>(); |
| for (TriggerDef thriftDef : thriftDefs) |
| triggerDefinitions.put(thriftDef.getName(), |
| new TriggerDefinition(thriftDef.getName(), thriftDef.getOptions().get(TriggerDefinition.CLASS))); |
| return triggerDefinitions; |
| } |
| |
| private static List<TriggerDef> triggerDefinitionsToThrift(Collection<TriggerDefinition> triggers) |
| { |
| List<TriggerDef> thriftDefs = new ArrayList<>(triggers.size()); |
| for (TriggerDefinition def : triggers) |
| { |
| TriggerDef td = new TriggerDef(); |
| td.setName(def.name); |
| td.setOptions(Collections.singletonMap(TriggerDefinition.CLASS, def.classOption)); |
| thriftDefs.add(td); |
| } |
| return thriftDefs; |
| } |
| } |