/** * 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.Cache; import com.hortonworks.registries.cache.view.DataStoreBackedCache; import com.hortonworks.registries.cache.view.config.TypeConfig; import com.hortonworks.registries.cache.view.datastore.DataStoreReader; import com.hortonworks.registries.cache.view.datastore.DataStoreWriter; import com.hortonworks.registries.cache.view.io.loader.CacheLoaderFactory; import com.hortonworks.registries.cache.view.io.writer.CacheWriter; import com.hortonworks.registries.cache.view.io.loader.CacheLoader; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; public class DataStoreBackedCacheService<K,V> extends CacheService<K,V> { protected final CacheLoaderFactory<K, V> cacheLoaderFactory; // used to load cache sync or async protected final CacheWriter<K, V> cacheWriter; // used to write to db sync or async protected final DataStoreReader<K, V> dataStoreReader; // used for read through protected final ConcurrentMap<String, CacheLoader<K,V>> cacheLoaders = new ConcurrentHashMap<>(); protected DataStoreBackedCacheService(Builder<K, V> builder) { super(builder); this.cacheLoaderFactory = builder.cacheLoaderFactory; this.cacheWriter = builder.cacheWriter; this.dataStoreReader = builder.dataStoreReader; } public static class Builder<K,V> extends CacheService.Builder<K,V> { private CacheLoaderFactory<K, V> cacheLoaderFactory; private CacheWriter<K, V> cacheWriter; private DataStoreReader<K, V> dataStoreReader; public Builder(String id, TypeConfig.Cache cacheType) { super(id, cacheType); } public Builder<K,V> setCacheLoaderFactory(CacheLoaderFactory<K, V> cacheLoaderFactory) { this.cacheLoaderFactory = cacheLoaderFactory; return this; } public Builder<K,V> setCacheWriter(CacheWriter<K, V> cacheWriter) { this.cacheWriter = cacheWriter; return this; } public Builder<K,V> setDataStoreReader(DataStoreReader<K, V> dataStoreReader) { this.dataStoreReader = dataStoreReader; return this; } public DataStoreBackedCacheService<K,V> build() { return new DataStoreBackedCacheService<>(this); } } public void registerCache(String id, Cache<K,V> cache) { if (isDataStoreBacked()) { caches.putIfAbsent(this.id, createDataStoreBackedCache(id, cache)); } else { super.registerCache(id, cache); } } private DataStoreBackedCache<K, V> createDataStoreBackedCache(String id, Cache<K, V> cache) { final CacheLoader<K, V> cacheLoader = cacheLoaderFactory == null ? null : cacheLoaderFactory.create(cache, dataStoreReader); if (cacheLoader != null) { cacheLoaders.putIfAbsent(id, cacheLoader); } return new DataStoreBackedCache<>(cache, cacheLoader, dataStoreReader, cacheWriter); } public CacheLoader<K, V> getCacheLoader(String cacheId) { return cacheLoaders.get(cacheId); } public DataStoreWriter<K, V> getCacheWriter() { return cacheWriter; } public DataStoreReader<K, V> getDataStoreReader() { return dataStoreReader; } /** * @return true if the {@link Cache} is backed by a {@link DataStoreReader}, false otherwise */ public boolean isDataStoreBacked() { return dataStoreReader != null || cacheWriter != null || cacheLoaderFactory != null; } }