/**
* Copyright 2016 Hortonworks.
*
* Licensed 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 com.hortonworks.registries.cache.view.service;
import com.hortonworks.registries.cache.view.config.DataStoreConfig;
import com.hortonworks.registries.cache.view.datastore.DataStoreWriter;
import com.hortonworks.registries.cache.view.Factory;
import com.hortonworks.registries.cache.view.config.CacheConfig;
import com.hortonworks.registries.cache.view.config.ConnectionConfig;
import com.hortonworks.registries.cache.view.config.ExpiryPolicy;
import com.hortonworks.registries.cache.view.config.TypeConfig;
import com.hortonworks.registries.cache.view.datastore.DataStoreReader;
import com.hortonworks.registries.cache.view.datastore.phoenix.PhoenixDataStore;
import com.hortonworks.registries.cache.view.impl.redis.connection.RedisConnectionFactory;
import com.hortonworks.registries.cache.view.impl.redis.connection.RedisConnectionPoolFactory;
import com.hortonworks.registries.cache.view.io.loader.CacheLoaderAsyncFactory;
import com.hortonworks.registries.cache.view.io.loader.CacheLoaderFactory;
import com.hortonworks.registries.cache.view.io.loader.CacheLoaderSyncFactory;
import com.hortonworks.registries.cache.view.io.writer.CacheWriter;
import com.hortonworks.registries.cache.view.io.writer.CacheWriterAsync;
import com.hortonworks.registries.cache.view.io.writer.CacheWriterSync;
import com.hortonworks.registries.cache.view.service.registry.CacheServiceLocalRegistry;
import com.hortonworks.registries.common.util.ReflectionHelper;
import com.lambdaworks.redis.RedisClient;
import com.lambdaworks.redis.RedisConnection;
import com.lambdaworks.redis.codec.RedisCodec;
import com.lambdaworks.redis.codec.Utf8StringCodec;
import java.util.Arrays;
public class RedisCacheServiceBuilder {
private final CacheConfig cacheConfig;
public RedisCacheServiceBuilder(CacheConfig cacheConfig) {
this.cacheConfig = cacheConfig;
}
public void register() {
CacheServiceLocalRegistry.INSTANCE.register(new CacheServiceId(cacheConfig.getId()), getCacheService());
}
private <T extends CacheService> T getCacheService() {
TypeConfig.Cache cacheType = cacheConfig.getCacheType();
switch (cacheType) {
case REDIS:
return (T) getRedisCacheService();
case GUAVA:
return (T) getGuavaCacheService();
case MEMCACHED:
default:
throw new IllegalStateException("Invalid cache option. " + cacheType
+ ". Valid options are " + Arrays.toString(TypeConfig.Cache.values()));
}
}
private RedisCacheService getRedisCacheService() {
final String cacheServiceId = cacheConfig.getId();
final TypeConfig.Cache cacheType = cacheConfig.getCacheType();
return (RedisCacheService) new RedisCacheService.Builder(cacheServiceId, cacheType, getRedisConnectionFactory())
.setCacheLoaderFactory(getCacheLoaderFactory())
.setCacheWriter(getCacheWriter(getDataStoreWriter(getNamespace())))
.setDataStoreReader(getDataStoreReader(getNamespace()))
.setExpiryPolicy(getExpiryPolicy())
.build();
}
private CacheService getGuavaCacheService() {
throw new UnsupportedOperationException("Must implement Guava Cache Service");
}
private ExpiryPolicy getExpiryPolicy() {
return cacheConfig.getExpiryPolicy();
}
private String getNamespace() {
return cacheConfig.getDataStore().getNamespace();
}
private DataStoreWriter getDataStoreWriter(String namespace) {
final TypeConfig.DataStore dataStoreType = cacheConfig.getDataStore().getDataStoreType();
switch (dataStoreType) {
case PHOENIX:
return new PhoenixDataStore<>(namespace);
case MYSQL:
return null;
case HBASE:
return null;
default:
throw new IllegalStateException("Invalid DataStore option. " + dataStoreType
+ ". Valid options are " + Arrays.toString(TypeConfig.DataStore.values()));
}
}
private DataStoreReader<Object, Object> getDataStoreReader(String namespace) {
final TypeConfig.DataStore dataStoreType = cacheConfig.getDataStore().getDataStoreType();
switch (dataStoreType) {
case PHOENIX:
return new PhoenixDataStore<>(namespace);
case MYSQL:
return null;
case HBASE:
return null;
default:
throw new IllegalStateException("Invalid DataStore option. " + dataStoreType
+ ". Valid options are " + Arrays.toString(TypeConfig.DataStore.values()));
}
}
private CacheWriter getCacheWriter(DataStoreWriter dataStoreWriter) {
final TypeConfig.CacheWriter cacheWriterType = cacheConfig.getDataStore().getCacheWriterType();
switch (cacheWriterType) {
case SYNC:
return new CacheWriterSync(dataStoreWriter);
case ASYNC:
return new CacheWriterAsync(dataStoreWriter);
default:
throw new IllegalStateException("Invalid CacheWriter option. " + cacheWriterType
+ ". Valid options are " + Arrays.toString(TypeConfig.CacheWriter.values()));
}
}
private CacheLoaderFactory getCacheLoaderFactory() {
final DataStoreConfig dataStore = cacheConfig.getDataStore();
if (dataStore != null) {
final TypeConfig.CacheLoader cacheLoaderType = dataStore.getCacheLoaderType();
switch (cacheLoaderType) {
case SYNC:
return new CacheLoaderSyncFactory<>();
case ASYNC:
return new CacheLoaderAsyncFactory<>();
default:
throw new IllegalStateException("Invalid CacheLoader option. " + cacheLoaderType
+ ". Valid options are " + Arrays.toString(TypeConfig.CacheLoader.values()));
}
}
return null;
}
private Factory<RedisConnection> getRedisConnectionFactory() {
final ConnectionConfig.RedisConnectionConfig connectionConfig = (ConnectionConfig.RedisConnectionConfig) cacheConfig.getConnectionConfig();
if (connectionConfig != null) {
if (connectionConfig.getPool() != null) {
return new RedisConnectionPoolFactory(RedisClient.create(getRedisUri()), getRedisCodec());
} else {
return new RedisConnectionFactory(RedisClient.create(getRedisUri()), getRedisCodec());
}
}
return null;
}
private RedisCodec getRedisCodec() {
final String codec = cacheConfig.getCacheEntry().getCodec();
if (codec != null) {
return new Utf8StringCodec();
} else {
try {
return ReflectionHelper.newInstance(codec);
} catch (Exception e) {
throw new RuntimeException("Exception occurred creating codec", e);
}
}
}
private String getRedisUri() {
ConnectionConfig.RedisConnectionConfig rcc = (ConnectionConfig.RedisConnectionConfig) cacheConfig.getConnectionConfig();
return "redis://" + rcc.getHost() + ":" + rcc.getPort();
}
}