/*
* Copyright 2015 Edward Capriolo
*
* 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 io.teknek.nibiru;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import io.teknek.nibiru.engine.DefaultColumnFamily;
import io.teknek.nibiru.metadata.StoreMetaData;
import io.teknek.nibiru.metadata.KeyspaceAndStoreMetaData;
import io.teknek.nibiru.metadata.KeyspaceMetaData;
import io.teknek.nibiru.metadata.MetaDataStorage;
import io.teknek.nibiru.partitioner.NaturalPartitioner;
import io.teknek.nibiru.router.LocalRouter;
public class MetaDataManager {
public static final String SYSTEM_KEYSPACE = "system";
private MetaDataStorage metaDataStorage;
private final Server server;
private final Configuration configuration;
public MetaDataManager(Configuration configuration, Server server){
this.configuration = configuration;
this.server = server;
}
public void init(){
try {
metaDataStorage = (MetaDataStorage) Class.forName(configuration.getMetaDataStorageClass()).newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
throw new RuntimeException(e);
}
createKeyspaces();
}
private void addSystemKeyspace(){
Keyspace system = new Keyspace(configuration);
KeyspaceMetaData ksmd = new KeyspaceMetaData();
ksmd.setName(SYSTEM_KEYSPACE);
ksmd.setPartitioner( new NaturalPartitioner());
ksmd.setRouter(new LocalRouter());
system.setKeyspaceMetadata(ksmd);
{
Map<String,Object> properties = new HashMap<>();
properties.put("implementing_class", DefaultColumnFamily.class.getName());
system.createStore("hints", properties);
}
server.getKeyspaces().put(SYSTEM_KEYSPACE, system);
}
private void createKeyspaces(){
Map<String,KeyspaceAndStoreMetaData> meta = read();
addSystemKeyspace();
if (!(meta == null)){
for (Entry<String, KeyspaceAndStoreMetaData> keyspaceEntry : meta.entrySet()){
Keyspace k = new Keyspace(configuration);
k.setKeyspaceMetadata(keyspaceEntry.getValue().getKeyspaceMetaData());
for (Map.Entry<String, StoreMetaData> columnFamilyEntry : keyspaceEntry.getValue().getColumnFamilies().entrySet()){
Store columnFamily = null;
try {
Class<?> cfClass = Class.forName(columnFamilyEntry.getValue().getImplementingClass());
Constructor<?> cons = cfClass.getConstructor(Keyspace.class, StoreMetaData.class);
columnFamily = (Store) cons.newInstance(k, columnFamilyEntry.getValue());
} catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new RuntimeException(e);
}
try {
columnFamily.init();
} catch (IOException e) {
throw new RuntimeException(e);
}
k.getStores().put(columnFamilyEntry.getKey(), columnFamily);
}
server.getKeyspaces().put(keyspaceEntry.getKey(), k);
}
}
}
public void createOrUpdateKeyspace(String keyspaceName, Map<String,Object> properties){
KeyspaceMetaData kmd = new KeyspaceMetaData(keyspaceName, properties);
Keyspace keyspace = new Keyspace(configuration);
keyspace.setKeyspaceMetadata(kmd);
kmd.setProperties(properties);
Keyspace result = server.getKeyspaces().putIfAbsent(keyspaceName, keyspace);
if (result != null){
result.getKeyspaceMetaData().setProperties(properties);
}
persistMetadata();
}
private void persistMetadata(){
Map<String,KeyspaceAndStoreMetaData> meta = new HashMap<>();
for (Map.Entry<String, Keyspace> entry : server.getKeyspaces().entrySet()){
KeyspaceAndStoreMetaData kfmd = new KeyspaceAndStoreMetaData();
kfmd.setKeyspaceMetaData(entry.getValue().getKeyspaceMetaData());
for (Map.Entry<String, Store> cfEntry : entry.getValue().getStores().entrySet()){
kfmd.getColumnFamilies().put(cfEntry.getKey(), cfEntry.getValue().getStoreMetadata());
}
meta.put(entry.getKey(), kfmd);
}
persist(meta);
}
public void createOrUpdateStore(String keyspaceName, String store, Map<String,Object> properties){
//server.getKeyspaces().get(keyspaceName).createStore(store, properties);
Store existingStore = server.getKeyspaces().get(keyspaceName).getStores().get(store);
if (existingStore == null){
server.getKeyspaces().get(keyspaceName).createStore(store, properties);
} else {
//TODO thread safe?
existingStore.getStoreMetadata().setProperties(properties);
}
persistMetadata();
}
public Collection<String> listKeyspaces(){
return server.getKeyspaces().keySet();
}
public Collection<String> listStores(String keyspace){
Keyspace ks = server.getKeyspaces().get(keyspace);
return ks.getStores().keySet();
}
public KeyspaceMetaData getKeyspaceMetadata(String keyspace){
return server.getKeyspaces().get(keyspace).getKeyspaceMetaData();
}
public StoreMetaData getStoreMetadata(String keyspace, String store){
return server.getKeyspaces().get(keyspace).getStores().get(store).getStoreMetadata();
}
public Map<String,KeyspaceAndStoreMetaData> read(){
return metaDataStorage.read(configuration);
}
public void persist(Map<String,KeyspaceAndStoreMetaData> meta){
metaDataStorage.persist(configuration, meta);
}
}