/*******************************************************************************
* /***
* *
* * Copyright 2013 Netflix, Inc.
* *
* * 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.netflix.paas.cassandra.provider.impl;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.commons.configuration.AbstractConfiguration;
import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
import com.google.inject.Inject;
import com.netflix.astyanax.AstyanaxContext;
import com.netflix.astyanax.Cluster;
import com.netflix.astyanax.thrift.ThriftFamilyFactory;
import com.netflix.paas.cassandra.keys.ClusterKey;
import com.netflix.paas.cassandra.provider.AstyanaxConfigurationProvider;
import com.netflix.paas.cassandra.provider.AstyanaxConnectionPoolConfigurationProvider;
import com.netflix.paas.cassandra.provider.AstyanaxConnectionPoolMonitorProvider;
import com.netflix.paas.cassandra.provider.ClusterClientProvider;
import com.netflix.paas.cassandra.provider.HostSupplierProvider;
public class DefaultAstyanaxClusterClientProvider implements ClusterClientProvider {
/**
* Track cluster references
*
* @author elandau
*
*/
public static class ClusterContextHolder {
private AstyanaxContext<Cluster> context;
private AtomicLong refCount = new AtomicLong(0);
public ClusterContextHolder(AstyanaxContext<Cluster> context) {
this.context = context;
}
public Cluster getKeyspace() {
return context.getClient();
}
public void start() {
context.start();
}
public void shutdown() {
context.shutdown();
}
public long addRef() {
return refCount.incrementAndGet();
}
public long releaseRef() {
return refCount.decrementAndGet();
}
}
private final Map<String, ClusterContextHolder> contextMap = Maps.newHashMap();
private final AstyanaxConfigurationProvider configurationProvider;
private final AstyanaxConnectionPoolConfigurationProvider cpProvider;
private final AstyanaxConnectionPoolMonitorProvider monitorProvider;
private final Map<String, HostSupplierProvider> hostSupplierProviders;
private final AbstractConfiguration configuration;
@Inject
public DefaultAstyanaxClusterClientProvider(
AbstractConfiguration configuration,
Map<String, HostSupplierProvider> hostSupplierProviders,
AstyanaxConfigurationProvider configurationProvider,
AstyanaxConnectionPoolConfigurationProvider cpProvider,
AstyanaxConnectionPoolMonitorProvider monitorProvider) {
this.configurationProvider = configurationProvider;
this.cpProvider = cpProvider;
this.monitorProvider = monitorProvider;
this.hostSupplierProviders = hostSupplierProviders;
this.configuration = configuration;
}
@Override
public synchronized Cluster acquireCluster(ClusterKey clusterKey) {
String clusterName = clusterKey.getClusterName().toLowerCase();
Preconditions.checkNotNull(clusterName, "Invalid cluster name 'null'");
ClusterContextHolder holder = contextMap.get(clusterName);
if (holder == null) {
HostSupplierProvider hostSupplierProvider = hostSupplierProviders.get(clusterKey.getDiscoveryType());
Preconditions.checkNotNull(hostSupplierProvider, String.format("Unknown host supplier provider '%s' for cluster '%s'", clusterKey.getDiscoveryType(), clusterName));
AstyanaxContext<Cluster> context = new AstyanaxContext.Builder()
.forCluster(clusterName)
.withAstyanaxConfiguration(configurationProvider.get(clusterName))
.withConnectionPoolConfiguration(cpProvider.get(clusterName))
.withConnectionPoolMonitor(monitorProvider.get(clusterName))
.withHostSupplier(hostSupplierProvider.getSupplier(clusterName))
.buildCluster(ThriftFamilyFactory.getInstance());
holder = new ClusterContextHolder(context);
holder.start();
}
holder.addRef();
return holder.getKeyspace();
}
@Override
public synchronized void releaseCluster(ClusterKey clusterKey) {
String clusterName = clusterKey.getClusterName().toLowerCase();
ClusterContextHolder holder = contextMap.get(clusterName);
if (holder.releaseRef() == 0) {
contextMap.remove(clusterName);
holder.shutdown();
}
}
}