/* * Copyright 2011 Shunsuke Nakamura, and contributors. * * 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.apache.cassandra.db.engine; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.util.Map; import java.util.HashMap; import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.db.ColumnFamily; import org.apache.cassandra.db.DecoratedKey; import org.apache.cassandra.io.util.FileUtils; import kyotocabinet.*; public class KyotoCabinetInstance extends DBSchemalessInstance { DB db; String defaultDBFormat = "kch"; String dbFormat; Map<String, String> dbClassFormatMap = new HashMap() { { put("ProtoHashDB", "kcph"); put("ProtoTreeDB", "kcpt"); put("StashDB", "kcs"); put("CacheDB", "kcc"); put("GrassDB", "kcg"); put("HashDB", "kch"); put("TreeDB", "kct"); put("DirDB", "kcd"); put("ForestDB", "kcf"); } }; final String KEYSEPARATOR = ":"; public KyotoCabinetInstance(String ksName, String cfName, String dbClass) { setup(ksName, cfName, dbClass); } public KyotoCabinetInstance(String ksName, String cfName) { setup(ksName, cfName, null); } private void setup(String ksName, String cfName, String dbClass) { engineName = "KyotoCabinet"; this.ksName = ksName; this.cfName = cfName; setConfiguration(); db = new DB(); dbFormat = dbClass != null ? getFileFormatForDBClass(dbClass) : getFileFormatForDBClass(this.kcclass); try { FileUtils.createDirectory(kcdir); } catch (IOException e) { System.err.println("DB connection error" + db.error()); System.exit(1); } String dbFile = kcdir + "/" + this.ksName + "-" + this.cfName + "." + dbFormat; if(!db.open(dbFile, DB.OWRITER | DB.OCREATE | DB.OTRYLOCK)) { System.err.println("DB connection Error: " + db.error()); System.exit(1); } } private String getFileFormatForDBClass(String dbClass) { return dbClassFormatMap.containsKey(dbClass) ? dbClassFormatMap.get(dbClass) : defaultDBFormat; } @Override public int update(String rowKey, ColumnFamily newcf) { return doUpdate(makeRowKey(rowKey), newcf.toBytes()); } @Override public int insert(String rowKey, ColumnFamily cf) { return doInsert(makeRowKey(rowKey), cf.toBytes()); } @Override public byte[] select(String rowKey) { return db.get(makeRowKey(rowKey)); } @Override public synchronized int delete(String rowKey) { return db.remove(makeRowKey(rowKey)) ? SUCCESS : FAILURE; } @Override public int dropDB() { return FAILURE; } @Override public int dropTable() { return db.clear() ? SUCCESS : FAILURE; } @Override public Map<ByteBuffer, ColumnFamily> getRangeSlice(DecoratedKey startWith, DecoratedKey stopAt, int maxResults) { return null; } @Override public int truncate() { return dropTable(); } private synchronized int doInsert(byte[] rowKey, byte[] cfValue) { return db.append(rowKey, cfValue) ? SUCCESS : FAILURE; } private synchronized int doUpdate(byte[] rowKey, byte[] cfValue) { return db.replace(rowKey, cfValue) ? SUCCESS : FAILURE; } public byte[] makeRowKey(String rowKey) { try { return rowKey.getBytes("UTF-8"); } catch (UnsupportedEncodingException e) { errorMsg("makeRowKey encoding error", e); return null; } } }