Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* 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.druid.server.coordinator.rules;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;

import javax.annotation.Nullable;

/**
* Controls what happens when a {@link PartialLoadRule}'s {@link PartialLoadMatcher} does not apply to a given segment,
* for example, a {@link ProjectionPartialLoadMatcher} when faced with a segment that doesn't have projections.
* <p>
* Unknown values deserialize to {@code null} so that an older coordinator encountering a rule authored on a newer
* version that introduces a new behavior falls back to the constructor's default ({@link #FULL_LOAD}) rather than
* failing to parse the rule.
*/
public enum CannotMatchBehavior
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO it'd be nicer to define the enums like FALL_THROUGH("fallThrough") and have the "fallThrough" be how they serialize in JSON. SImilar to JoinAlgorithm and CloneQueryMode. Most Druid stuff uses thatStyle rather than THIS_ONE.

{
/**
* The rule does not apply; the cascade continues to the next rule.
*/
FALL_THROUGH("fallThrough"),

/**
* The rule applies and the segment is loaded in full on this tier.
*/
FULL_LOAD("fullLoad");

private final String id;

CannotMatchBehavior(String id)
{
this.id = id;
}

@JsonCreator
@Nullable
public static CannotMatchBehavior fromString(final String id)
{
if (id == null) {
return null;
}
for (CannotMatchBehavior behavior : values()) {
if (behavior.id.equals(id)) {
return behavior;
}
}

return null;
}

@JsonValue
public String getId()
{
return id;
}

@Override
public String toString()
{
return id;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* 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.druid.server.coordinator.rules;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.apache.druid.error.InvalidInput;
import org.apache.druid.timeline.DataSegment;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;

/**
* Selects partial load of projections whose names appear in the configured {@link #names} list.
*/
public class ExactProjectionPartialLoadMatcher extends ProjectionPartialLoadMatcher
{
public static final String TYPE = "exactProjection";

private final List<String> names;

@JsonCreator
public ExactProjectionPartialLoadMatcher(@JsonProperty("names") List<String> names)
{
if (names == null || names.isEmpty()) {
throw InvalidInput.exception("names must not be null or empty for exactProjection matcher");
}
this.names = List.copyOf(names);
}

@JsonProperty
public List<String> getNames()
{
return names;
}

@Override
protected List<String> resolveProjectionNames(DataSegment segment)
{
final List<String> segmentProjections = segment.getProjections();
if (segmentProjections == null || segmentProjections.isEmpty()) {
return Collections.emptyList();
}
final Set<String> present = new HashSet<>(segmentProjections);
final TreeSet<String> intersected = new TreeSet<>();
for (String name : names) {
if (present.contains(name)) {
intersected.add(name);
}
}
return new ArrayList<>(intersected);
}

@Override
public boolean equals(Object o)
{
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ExactProjectionPartialLoadMatcher that = (ExactProjectionPartialLoadMatcher) o;
return Objects.equals(names, that.names);
}

@Override
public int hashCode()
{
return Objects.hash(names);
}

@Override
public String toString()
{
return "ExactProjectionPartialLoadMatcher{names=" + names + "}";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* 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.druid.server.coordinator.rules;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.joda.time.DateTime;
import org.joda.time.Interval;

import javax.annotation.Nullable;
import java.util.Map;

/**
* Forever variant of {@link PartialLoadRule}. Mirrors {@link ForeverLoadRule} (always load) and layers on
* {@link PartialLoadMatcher} for selection.
*/
public class ForeverPartialLoadRule extends PartialLoadRule
{
public static final String TYPE = "loadPartialForever";

@JsonCreator
public ForeverPartialLoadRule(
@JsonProperty("tieredReplicants") Map<String, Integer> tieredReplicants,
@JsonProperty("useDefaultTierForNull") @Nullable Boolean useDefaultTierForNull,
@JsonProperty("matcher") PartialLoadMatcher matcher,
@JsonProperty("onCannotMatch") @Nullable CannotMatchBehavior onCannotMatch
)
{
super(tieredReplicants, useDefaultTierForNull, matcher, onCannotMatch);
}

@Override
@JsonProperty
public String getType()
{
return TYPE;
}

@Override
public boolean appliesTo(Interval interval, DateTime referenceTimestamp)
{
return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* 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.druid.server.coordinator.rules;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.joda.time.DateTime;
import org.joda.time.Interval;

import javax.annotation.Nullable;
import java.util.Map;
import java.util.Objects;

/**
* Interval-based variant of {@link PartialLoadRule}. Mirrors {@link IntervalLoadRule} for time-window semantics and
* layers on {@link PartialLoadMatcher} for selection.
*/
public class IntervalPartialLoadRule extends PartialLoadRule
{
public static final String TYPE = "loadPartialByInterval";

private final Interval interval;

@JsonCreator
public IntervalPartialLoadRule(
@JsonProperty("interval") Interval interval,
@JsonProperty("tieredReplicants") Map<String, Integer> tieredReplicants,
@JsonProperty("useDefaultTierForNull") @Nullable Boolean useDefaultTierForNull,
@JsonProperty("matcher") PartialLoadMatcher matcher,
@JsonProperty("onCannotMatch") @Nullable CannotMatchBehavior onCannotMatch
)
{
super(tieredReplicants, useDefaultTierForNull, matcher, onCannotMatch);
this.interval = interval;
}

@Override
@JsonProperty
public String getType()
{
return TYPE;
}

@JsonProperty
public Interval getInterval()
{
return interval;
}

@Override
public boolean appliesTo(Interval theInterval, DateTime referenceTimestamp)
{
return Rules.eligibleForLoad(interval, theInterval);
}

@Override
public boolean equals(Object o)
{
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.equals(o)) {
return false;
}
IntervalPartialLoadRule that = (IntervalPartialLoadRule) o;
return Objects.equals(interval, that.interval);
}

@Override
public int hashCode()
{
return Objects.hash(super.hashCode(), interval);
}
}
Loading
Loading