Package com.hmsonline.virgil

Source Code of com.hmsonline.virgil.CassandraStorage

/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF 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
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* 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.hmsonline.virgil;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.charset.CharacterCodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.cassandra.thrift.CfDef;
import org.apache.cassandra.thrift.Column;
import org.apache.cassandra.thrift.ColumnDef;
import org.apache.cassandra.thrift.ColumnOrSuperColumn;
import org.apache.cassandra.thrift.ColumnParent;
import org.apache.cassandra.thrift.ColumnPath;
import org.apache.cassandra.thrift.ConsistencyLevel;
import org.apache.cassandra.thrift.IndexClause;
import org.apache.cassandra.thrift.IndexExpression;
import org.apache.cassandra.thrift.IndexOperator;
import org.apache.cassandra.thrift.IndexType;
import org.apache.cassandra.thrift.InvalidRequestException;
import org.apache.cassandra.thrift.KeyRange;
import org.apache.cassandra.thrift.KeySlice;
import org.apache.cassandra.thrift.KsDef;
import org.apache.cassandra.thrift.Mutation;
import org.apache.cassandra.thrift.NotFoundException;
import org.apache.cassandra.thrift.SchemaDisagreementException;
import org.apache.cassandra.thrift.SlicePredicate;
import org.apache.cassandra.thrift.SliceRange;
import org.apache.cassandra.thrift.TimedOutException;
import org.apache.cassandra.thrift.UnavailableException;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.lang.StringUtils;
import org.apache.thrift.TException;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
//import com.hmsonline.cassandra.triggers.dao.CommitLog;
//import com.hmsonline.cassandra.triggers.dao.ConfigurationStore;
//import com.hmsonline.cassandra.triggers.dao.TriggerStore;
import com.hmsonline.virgil.config.VirgilConfiguration;
import com.hmsonline.virgil.index.Indexer;
import com.hmsonline.virgil.pool.ConnectionPool;
import com.hmsonline.virgil.pool.ConnectionPoolClient;
import com.hmsonline.virgil.pool.PooledConnection;

public class CassandraStorage extends ConnectionPoolClient {
    private static final int MAX_COLUMNS = 1000;
    private static final int MAX_ROWS = 20;
    private Indexer indexer = null;
    private VirgilConfiguration config = null;

    // TODO: Come back and make indexing AOP
    public CassandraStorage(VirgilConfiguration config, Indexer indexer) throws Exception {
        this.indexer = indexer;
        // CassandraStorage.server = server;
        this.config = config;
        ConnectionPool.initializePool();
        if (VirgilConfiguration.isEmbedded()) {
            // Force instantiation of the singletons
            //ConfigurationStore.getStore().create();
            //TriggerStore.getStore().create();
            //CommitLog.getCommitLog().create();
        }
    }

    @PooledConnection
    public JSONArray getKeyspaces() throws InvalidRequestException, TException, UnsupportedEncodingException {
        List<KsDef> keyspaces = getConnection(null).describe_keyspaces();
        return JsonMarshaller.marshallKeyspaces(keyspaces, true);
    }

    @PooledConnection
    public void addKeyspace(String keyspace) throws InvalidRequestException, TException, SchemaDisagreementException {
        // TODO: Take key space in via JSON/XML. (Replace hard-coded values)
        List<CfDef> cfDefList = new ArrayList<CfDef>();
        KsDef ksDef = new KsDef(keyspace, "org.apache.cassandra.locator.SimpleStrategy", cfDefList);
        ksDef.putToStrategy_options("replication_factor", "1");
        getConnection(null).system_add_keyspace(ksDef);
    }

    @PooledConnection
    public void dropColumnFamily(String keyspace, String columnFamily) throws InvalidRequestException, TException,
            SchemaDisagreementException {
        getConnection(keyspace).system_drop_column_family(columnFamily);
    }

    @PooledConnection
    public void dropKeyspace(String keyspace) throws InvalidRequestException, SchemaDisagreementException, TException {
        getConnection(keyspace).system_drop_keyspace(keyspace);
    }

    @PooledConnection
    public void createColumnFamily(String keyspace, String columnFamilyName, JSONArray indexedColumnsJson)
            throws InvalidRequestException, SchemaDisagreementException, TException {
        // TODO: Take column family definition in via JSON/XML. (Replace
        // hard-coded values)
        CfDef columnFamily = new CfDef(keyspace, columnFamilyName);
        columnFamily.setKey_validation_class("UTF8Type");
        columnFamily.setComparator_type("UTF8Type");
        columnFamily.setDefault_validation_class("UTF8Type");

        // add indexes on columns
        if (indexedColumnsJson != null && CollectionUtils.isNotEmpty(indexedColumnsJson)) {
            for (Object indexedColumn : indexedColumnsJson) {
                if (indexedColumn != null) {
                    String indexedColumnStr = indexedColumn.toString();
                    if (StringUtils.isNotBlank(indexedColumnStr)) {
                        List<ColumnDef> columnMetadata = columnFamily.getColumn_metadata();
                        columnMetadata = columnMetadata != null ? columnMetadata : new ArrayList<ColumnDef>();
                        ColumnDef colDef = new ColumnDef();
                        colDef.setName(indexedColumnStr.getBytes());
                        colDef.index_type = IndexType.KEYS;
                        colDef.setIndex_name(keyspace + "_" + columnFamilyName + "_" + indexedColumnStr + "_INDEX");
                        columnMetadata.add(colDef);
                        columnFamily.setColumn_metadata(columnMetadata);
                    }
                }
            }
        }
        getConnection(keyspace).system_add_column_family(columnFamily);
    }

    @SuppressWarnings("unchecked")
    @PooledConnection
    public void addColumn(String keyspace, String column_family, String rowkey, String column_name, String value,
            ConsistencyLevel consistency_level, boolean index) throws InvalidRequestException, UnavailableException,
            TimedOutException, TException, HttpException, IOException {
        JSONObject json = new JSONObject();
        json.put(column_name, value);
        this.setColumn(keyspace, column_family, rowkey, json, consistency_level, index);

        // TODO: Revisit adding a single field because it requires a fetch
        // first.
        if (this.config.isIndexingEnabled() && index) {
            JSONObject indexJson = this.getSlice(keyspace, column_family, rowkey, consistency_level);
            indexJson.put(column_name, value);
            indexer.index(column_family, rowkey, indexJson);
        }
    }

    @PooledConnection
    public void setColumn(String keyspace, String column_family, String key, JSONObject json,
            ConsistencyLevel consistency_level, boolean index) throws InvalidRequestException, UnavailableException,
            TimedOutException, TException, HttpException, IOException {
        this.setColumn(keyspace, column_family, key, json, consistency_level, index, System.currentTimeMillis() * 1000);
    }

    @PooledConnection
    public void setColumn(String keyspace, String column_family, String key, JSONObject json,
            ConsistencyLevel consistency_level, boolean index, long timestamp) throws InvalidRequestException,
            UnavailableException, TimedOutException, TException, HttpException, IOException {
        List<Mutation> slice = new ArrayList<Mutation>();
        for (Object field : json.keySet()) {
            String name = (String) field;
            String value = (String) json.get(name);
            Column c = new Column();
            c.setName(ByteBufferUtil.bytes(name));
            c.setValue(ByteBufferUtil.bytes(value));
            c.setTimestamp(timestamp);

            Mutation m = new Mutation();
            ColumnOrSuperColumn cc = new ColumnOrSuperColumn();
            cc.setColumn(c);
            m.setColumn_or_supercolumn(cc);
            slice.add(m);
        }
        Map<ByteBuffer, Map<String, List<Mutation>>> mutationMap = new HashMap<ByteBuffer, Map<String, List<Mutation>>>();
        Map<String, List<Mutation>> cfMutations = new HashMap<String, List<Mutation>>();
        cfMutations.put(column_family, slice);
        mutationMap.put(ByteBufferUtil.bytes(key), cfMutations);
        getConnection(keyspace).batch_mutate(mutationMap, consistency_level);

        if (config.isIndexingEnabled() && index)
            indexer.index(column_family, key, json);
    }

    @PooledConnection
    public void deleteColumn(String keyspace, String column_family, String key, String column,
            ConsistencyLevel consistency_level, boolean purgeIndex) throws InvalidRequestException,
            UnavailableException, TimedOutException, TException, HttpException, IOException {
        ColumnPath path = new ColumnPath(column_family);
        path.setColumn(ByteBufferUtil.bytes(column));
        getConnection(keyspace).remove(ByteBufferUtil.bytes(key), path, System.currentTimeMillis() * 1000,
                consistency_level);

        // TODO: Revisit deleting a single field because it requires a fetch
        // first.
        // Evidently it is impossible to remove just a field from a document in
        // SOLR
        // http://stackoverflow.com/questions/4802620/can-you-delete-a-field-from-a-document-in-solr-index
        if (config.isIndexingEnabled() && purgeIndex) {
            indexer.delete(column_family, key);
            JSONObject json = this.getSlice(keyspace, column_family, key, consistency_level);
            json.remove(column);
            indexer.index(column_family, key, json);
        }
    }

    @PooledConnection
    public long deleteRow(String keyspace, String column_family, String key, ConsistencyLevel consistency_level,
            boolean purgeIndex) throws InvalidRequestException, UnavailableException, TimedOutException, TException,
            HttpException, IOException {
        long deleteTime = System.currentTimeMillis() * 1000;
        ColumnPath path = new ColumnPath(column_family);
        getConnection(keyspace).remove(ByteBufferUtil.bytes(key), path, deleteTime, consistency_level);

        // Update Index
        if (config.isIndexingEnabled() && purgeIndex) {
            indexer.delete(column_family, key);
        }
        return deleteTime;
    }

    @PooledConnection
    public String getColumn(String keyspace, String columnFamily, String key, String column,
            ConsistencyLevel consistencyLevel) throws InvalidRequestException, NotFoundException, UnavailableException,
            TimedOutException, TException, UnsupportedEncodingException {
        ColumnPath path = new ColumnPath(columnFamily);
        path.setColumn(ByteBufferUtil.bytes(column));
        ColumnOrSuperColumn column_result = getConnection(keyspace).get(ByteBufferUtil.bytes(key), path,
                consistencyLevel);
        return new String(column_result.getColumn().getValue(), "UTF8");
    }

    @PooledConnection
    public JSONArray getRows(String keyspace, String columnFamily, String queryStr, ConsistencyLevel consistencyLevel)
            throws InvalidRequestException, UnavailableException, TimedOutException, TException,
            CharacterCodingException {
      if(StringUtils.isNotBlank(queryStr)) {
        return getRowsWithQuery(keyspace, columnFamily, queryStr, consistencyLevel);
      }
        SlicePredicate predicate = new SlicePredicate();
        SliceRange range = new SliceRange(ByteBufferUtil.bytes(""), ByteBufferUtil.bytes(""), false, MAX_COLUMNS);
        predicate.setSlice_range(range);

        KeyRange keyRange = new KeyRange(MAX_ROWS);
        keyRange.setStart_key(ByteBufferUtil.bytes(""));
        keyRange.setEnd_key(ByteBufferUtil.EMPTY_BYTE_BUFFER);
        ColumnParent parent = new ColumnParent(columnFamily);
        List<KeySlice> rows = getConnection(keyspace).get_range_slices(parent, predicate, keyRange, consistencyLevel);
        return JsonMarshaller.marshallRows(rows, true);
    }
   
    @PooledConnection
    public JSONArray getRowsWithQuery(String keyspace, String columnFamily, String queryStr, ConsistencyLevel consistencyLevel)
            throws InvalidRequestException, UnavailableException, TimedOutException, TException,
            CharacterCodingException {
        Query query = QueryParser.parse(queryStr);
        SlicePredicate predicate = new SlicePredicate();
        SliceRange range = new SliceRange(ByteBufferUtil.bytes(""), ByteBufferUtil.bytes(""), false, MAX_COLUMNS);
        predicate.setSlice_range(range);

        ColumnParent parent = new ColumnParent(columnFamily);
       
        IndexClause indexClause = new IndexClause();
        indexClause.setCount(MAX_ROWS);
        indexClause.setStart_key(new byte[0]);
        for(String keyName : query.getEqStmt().keySet()) {
          indexClause.addToExpressions(new IndexExpression(ByteBufferUtil.bytes(keyName),
                                                           IndexOperator.EQ, ByteBufferUtil.bytes(query.getEqStmt().get(keyName))));
        }
       
        List<KeySlice> rows = getConnection(keyspace).get_indexed_slices(parent, indexClause, predicate,
                ConsistencyLevel.QUORUM);
        return JsonMarshaller.marshallRows(rows, true);
    }

    @PooledConnection
    public JSONObject getSlice(String keyspace, String columnFamily, String key, ConsistencyLevel consistencyLevel)
            throws InvalidRequestException, UnavailableException, TimedOutException, TException,
            UnsupportedEncodingException {
        SlicePredicate predicate = new SlicePredicate();
        SliceRange range = new SliceRange(ByteBufferUtil.bytes(""), ByteBufferUtil.bytes(""), false, MAX_COLUMNS);
        predicate.setSlice_range(range);
        ColumnParent parent = new ColumnParent(columnFamily);
        List<ColumnOrSuperColumn> slice = getConnection(keyspace).get_slice(ByteBufferUtil.bytes(key), parent,
                predicate, consistencyLevel);
        if (slice.size() > 0)
            return JsonMarshaller.marshallSlice(slice);
        else
            return null;
    }

}
TOP

Related Classes of com.hmsonline.virgil.CassandraStorage

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.