/* * Licensed to CRATE Technology GmbH ("Crate") under one or more contributor * license agreements. See the NOTICE file distributed with this work for * additional information regarding copyright ownership. Crate 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. * * However, if you have executed another commercial license agreement * with Crate these terms will supersede the license and you may use the * software solely pursuant to the terms of the relevant commercial agreement. */ package io.crate.metadata.blob; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.util.concurrent.UncheckedExecutionException; import io.crate.blob.v2.BlobIndex; import io.crate.exceptions.ResourceUnknownException; import io.crate.exceptions.UnhandledServerException; import io.crate.metadata.TableIdent; import io.crate.metadata.table.SchemaInfo; import io.crate.metadata.table.TableInfo; import org.elasticsearch.cluster.ClusterChangedEvent; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Iterator; import java.util.concurrent.ExecutionException; import java.util.function.Function; import java.util.stream.Stream; public class BlobSchemaInfo implements SchemaInfo { public static final String NAME = "blob"; private final ClusterService clusterService; private final BlobTableInfoFactory blobTableInfoFactory; private final LoadingCache<String, BlobTableInfo> cache = CacheBuilder.newBuilder() .maximumSize(10000) .build( new CacheLoader<String, BlobTableInfo>() { @Override public BlobTableInfo load(@Nonnull String key) throws Exception { return innerGetTableInfo(key); } } ); private final Function<String, TableInfo> tableInfoFunction; @Inject public BlobSchemaInfo(ClusterService clusterService, BlobTableInfoFactory blobTableInfoFactory) { this.clusterService = clusterService; this.blobTableInfoFactory = blobTableInfoFactory; tableInfoFunction = new Function<String, TableInfo>() { @Nullable @Override public TableInfo apply(@Nullable String input) { return getTableInfo(input); } }; } private BlobTableInfo innerGetTableInfo(String name) { return blobTableInfoFactory.create(new TableIdent(NAME, name), clusterService); } @Override public BlobTableInfo getTableInfo(String name) { try { return cache.get(name); } catch (ExecutionException e) { throw new UnhandledServerException("Failed to get TableInfo", e.getCause()); } catch (UncheckedExecutionException e) { if (e.getCause() instanceof ResourceUnknownException) { return null; } throw e; } } @Override public String name() { return NAME; } @Override public void invalidateTableCache(String tableName) { cache.invalidate(tableName); } @Override public void update(ClusterChangedEvent event) { if (event.metaDataChanged()) { cache.invalidateAll(); } } @Override public Iterator<TableInfo> iterator() { return Stream.of(clusterService.state().metaData().getConcreteAllOpenIndices()) .filter(BlobIndex::isBlobIndex) .map(BlobIndex::stripPrefix) .map(tableInfoFunction) .iterator(); } @Override public void close() throws Exception { } }