blob: 88d713c19abaedaffe296421a62443b301f63b75 [file] [log] [blame]
/*
* 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.client;
import org.apache.druid.client.cache.Cache;
import org.apache.druid.client.cache.CacheConfig;
import org.apache.druid.java.util.common.StringUtils;
import org.apache.druid.query.CacheStrategy;
import org.apache.druid.query.Query;
import org.apache.druid.query.QueryContexts;
import org.apache.druid.query.QueryToolChest;
import org.apache.druid.query.SegmentDescriptor;
import org.joda.time.Interval;
import javax.annotation.Nullable;
import java.nio.ByteBuffer;
public class CacheUtil
{
public enum ServerType
{
BROKER {
@Override
boolean willMergeRunners()
{
return false;
}
},
DATA {
@Override
boolean willMergeRunners()
{
return true;
}
};
/**
* Same meaning as the "willMergeRunners" parameter to {@link CacheStrategy#isCacheable}.
*/
abstract boolean willMergeRunners();
}
public static Cache.NamedKey computeResultLevelCacheKey(String resultLevelCacheIdentifier)
{
return new Cache.NamedKey(resultLevelCacheIdentifier, StringUtils.toUtf8(resultLevelCacheIdentifier));
}
public static void populateResultCache(
Cache cache,
Cache.NamedKey key,
byte[] resultBytes
)
{
cache.put(key, resultBytes);
}
public static Cache.NamedKey computeSegmentCacheKey(
String segmentId,
SegmentDescriptor descriptor,
byte[] queryCacheKey
)
{
final Interval segmentQueryInterval = descriptor.getInterval();
final byte[] versionBytes = StringUtils.toUtf8(descriptor.getVersion());
return new Cache.NamedKey(
segmentId,
ByteBuffer
.allocate(16 + versionBytes.length + 4 + queryCacheKey.length)
.putLong(segmentQueryInterval.getStartMillis())
.putLong(segmentQueryInterval.getEndMillis())
.put(versionBytes)
.putInt(descriptor.getPartitionNumber())
.put(queryCacheKey)
.array()
);
}
/**
* Returns whether the segment-level cache should be checked for a particular query.
*
* @param query the query to check
* @param cacheStrategy result of {@link QueryToolChest#getCacheStrategy} on this query
* @param cacheConfig current active cache config
* @param serverType BROKER or DATA
*/
public static <T> boolean isUseSegmentCache(
Query<T> query,
@Nullable CacheStrategy<T, Object, Query<T>> cacheStrategy,
CacheConfig cacheConfig,
ServerType serverType
)
{
return isQueryCacheable(query, cacheStrategy, cacheConfig, serverType)
&& QueryContexts.isUseCache(query)
&& cacheConfig.isUseCache();
}
/**
* Returns whether the result-level cache should be populated for a particular query.
*
* @param query the query to check
* @param cacheStrategy result of {@link QueryToolChest#getCacheStrategy} on this query
* @param cacheConfig current active cache config
* @param serverType BROKER or DATA
*/
public static <T> boolean isPopulateSegmentCache(
Query<T> query,
@Nullable CacheStrategy<T, Object, Query<T>> cacheStrategy,
CacheConfig cacheConfig,
ServerType serverType
)
{
return isQueryCacheable(query, cacheStrategy, cacheConfig, serverType)
&& QueryContexts.isPopulateCache(query)
&& cacheConfig.isPopulateCache();
}
/**
* Returns whether the result-level cache should be checked for a particular query.
*
* @param query the query to check
* @param cacheStrategy result of {@link QueryToolChest#getCacheStrategy} on this query
* @param cacheConfig current active cache config
* @param serverType BROKER or DATA
*/
public static <T> boolean isUseResultCache(
Query<T> query,
@Nullable CacheStrategy<T, Object, Query<T>> cacheStrategy,
CacheConfig cacheConfig,
ServerType serverType
)
{
return isQueryCacheable(query, cacheStrategy, cacheConfig, serverType)
&& QueryContexts.isUseResultLevelCache(query)
&& cacheConfig.isUseResultLevelCache();
}
/**
* Returns whether the result-level cache should be populated for a particular query.
*
* @param query the query to check
* @param cacheStrategy result of {@link QueryToolChest#getCacheStrategy} on this query
* @param cacheConfig current active cache config
* @param serverType BROKER or DATA
*/
public static <T> boolean isPopulateResultCache(
Query<T> query,
@Nullable CacheStrategy<T, Object, Query<T>> cacheStrategy,
CacheConfig cacheConfig,
ServerType serverType
)
{
return isQueryCacheable(query, cacheStrategy, cacheConfig, serverType)
&& QueryContexts.isPopulateResultLevelCache(query)
&& cacheConfig.isPopulateResultLevelCache();
}
/**
* Returns whether a particular query is cacheable. Does not check whether we are actually configured to use or
* populate the cache; that should be done separately.
*
* @param query the query to check
* @param cacheStrategy result of {@link QueryToolChest#getCacheStrategy} on this query
* @param cacheConfig current active cache config
* @param serverType BROKER or DATA
*/
static <T> boolean isQueryCacheable(
final Query<T> query,
@Nullable final CacheStrategy<T, Object, Query<T>> cacheStrategy,
final CacheConfig cacheConfig,
final ServerType serverType
)
{
return cacheStrategy != null
&& cacheStrategy.isCacheable(query, serverType.willMergeRunners())
&& cacheConfig.isQueryCacheable(query)
&& query.getDataSource().isCacheable(serverType == ServerType.BROKER);
}
}