/* * Copyright 2012 Future Systems * * 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 org.krakenapps.eventstorage.engine; import java.util.ArrayList; import java.util.Collection; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicInteger; import org.apache.felix.ipojo.annotations.Component; import org.apache.felix.ipojo.annotations.Provides; import org.apache.felix.ipojo.annotations.Requires; import org.krakenapps.confdb.Config; import org.krakenapps.confdb.ConfigCollection; import org.krakenapps.confdb.ConfigDatabase; import org.krakenapps.confdb.ConfigIterator; import org.krakenapps.confdb.ConfigService; import org.krakenapps.confdb.Predicates; import org.krakenapps.eventstorage.EventTableNotFoundException; import org.krakenapps.eventstorage.EventTableRegistry; @Component(name = "eventstorage-table-registry") @Provides public class EventTableRegistryImpl implements EventTableRegistry { private static final String COMMITTER = "kraken-eventstorage"; @Requires private ConfigService conf; private AtomicInteger nextTableId; private ConcurrentMap<Integer, String> tableNames; private ConcurrentMap<String, EventTableSchema> tableSchemas; public EventTableRegistryImpl() { this.tableSchemas = new ConcurrentHashMap<String, EventTableSchema>(); this.tableNames = new ConcurrentHashMap<Integer, String>(); ConfigDatabase db = getDatabase(); ConfigCollection col = db.ensureCollection(EventTableSchema.class); int maxId = 0; ConfigIterator it = col.findAll(); for (EventTableSchema t : it.getDocuments(EventTableSchema.class)) { tableNames.put(t.getId(), t.getName()); tableSchemas.put(t.getName(), t); if (maxId < t.getId()) maxId = t.getId(); } this.nextTableId = new AtomicInteger(maxId + 1); } @Override public boolean exists(String tableName) { return tableSchemas.containsKey(tableName); } @Override public Collection<String> getTableNames() { return new ArrayList<String>(tableSchemas.keySet()); } @Override public int getTableId(String tableName) { return getTableSchema(tableName).getId(); } @Override public String getTableName(int tableId) { return tableNames.get(tableId); } @Override public int createTable(String tableName, Map<String, String> tableMetadata) { if (tableSchemas.containsKey(tableName)) throw new IllegalStateException("table already exists: " + tableName); int newId = nextTableId.getAndIncrement(); EventTableSchema table = new EventTableSchema(newId, tableName); if (tableMetadata != null) table.getMetadata().putAll(tableMetadata); ConfigDatabase db = getDatabase(); db.add(table, COMMITTER, "create table [" + tableName + "]"); tableNames.put(table.getId(), table.getName()); tableSchemas.put(tableName, table); return newId; } @Override public void renameTable(String currentName, String newName) { if (tableSchemas.containsKey(newName)) throw new IllegalStateException("table already exists: " + newName); ConfigDatabase db = getDatabase(); Config c = getConfig(db, currentName); EventTableSchema schema = c.getDocument(EventTableSchema.class); schema.setName(newName); db.update(c, schema, false, COMMITTER, "rename table [" + currentName + "] to [" + newName + "]"); tableSchemas.remove(currentName); tableSchemas.putIfAbsent(newName, schema); tableNames.put(schema.getId(), newName); } @Override public void dropTable(String tableName) { getTableSchema(tableName); ConfigDatabase db = getDatabase(); db.remove(getConfig(db, tableName), false, COMMITTER, "drop table [" + tableName + "]"); EventTableSchema t = tableSchemas.remove(tableName); if (t != null) tableNames.remove(t.getId()); } @Override public Set<String> getTableMetadataKeys(String tableName) { EventTableSchema t = getTableSchema(tableName); return t.getMetadata().keySet(); } @Override public String getTableMetadata(String tableName, String key) { EventTableSchema t = getTableSchema(tableName); return (String) t.getMetadata().get(key); } @Override public void setTableMetadata(String tableName, String key, String value) { ConfigDatabase db = getDatabase(); Config c = getConfig(db, tableName); EventTableSchema t = getTableSchema(tableName); t.getMetadata().put(key, value); db.update(c, t, false, COMMITTER, "set table [" + tableName + "] metadata [" + key + "] to [" + value + "]"); } @Override public void unsetTableMetadata(String tableName, String key) { ConfigDatabase db = getDatabase(); Config c = getConfig(db, tableName); EventTableSchema t = getTableSchema(tableName); t.getMetadata().remove(key); db.update(c, t, false, COMMITTER, "unset table [" + tableName + "] metadata [" + key + "]"); } private EventTableSchema getTableSchema(String tableName) { EventTableSchema t = tableSchemas.get(tableName); if (t == null) throw new EventTableNotFoundException(tableName); return t; } private ConfigDatabase getDatabase() { return conf.ensureDatabase("kraken-eventstorage"); } private Config getConfig(ConfigDatabase db, String tableName) { Config config = db.findOne(EventTableSchema.class, Predicates.field("name", tableName)); if (config == null) throw new EventTableNotFoundException(tableName); return config; } }