All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hmsonline.cassandra.index.CassandraIndexAspect Maven / Gradle / Ivy

package com.hmsonline.cassandra.index;

import static com.hmsonline.cassandra.index.util.IndexUtil.INDEXING_KEYSPACE;
import static com.hmsonline.cassandra.index.util.IndexUtil.buildIndex;
import static com.hmsonline.cassandra.index.util.IndexUtil.fetchRow;
import static com.hmsonline.cassandra.index.util.IndexUtil.getLogEntries;
import static com.hmsonline.cassandra.index.util.IndexUtil.getNewRow;
import static com.hmsonline.cassandra.index.util.IndexUtil.indexChanged;
import static com.hmsonline.cassandra.index.util.IndexUtil.isEmptyIndex;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.cassandra.db.ColumnFamily;
import org.apache.cassandra.db.IMutation;
import org.apache.cassandra.db.RowMutation;
import org.apache.cassandra.thrift.ConsistencyLevel;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.hmsonline.cassandra.index.LogEntry.Status;
import com.hmsonline.cassandra.index.dao.CommitLogDAO;
import com.hmsonline.cassandra.index.dao.ConfigurationDAO;
import com.hmsonline.cassandra.index.dao.DAOFactory;
import com.hmsonline.cassandra.index.dao.IndexDAO;

/**
 * Aspect class used to handle wide row indexing for Cassandra.
 * 
 * @author pnguyen
 */
@Aspect
public class CassandraIndexAspect {
  private static Logger logger = LoggerFactory
          .getLogger(CassandraIndexAspect.class);
  private IndexDAO indexDao = DAOFactory.getIndexDAO();
  private ConfigurationDAO configurationDao = DAOFactory.getConfigurationDAO();
  private CommitLogDAO commitLogDao = DAOFactory.getCommitLogDAO();

  @Around("execution(* org.apache.cassandra.thrift.CassandraServer.doInsert(..))")
  public void process(ProceedingJoinPoint joinPoint) throws Throwable {
    ConsistencyLevel consistency = (ConsistencyLevel) joinPoint.getArgs()[0];
    List mutations = (List) joinPoint.getArgs()[1];
    List logEntries = getLogEntries(mutations);

    try {
      writeCommitLog(logEntries, consistency);
      index(mutations, consistency);
      joinPoint.proceed(joinPoint.getArgs());
      removeCommitLog(logEntries, consistency);
    }
    catch (Throwable t) {
      logger.error("An error occurred while handling indexing.", t);
      writeCommitLog1(logEntries, consistency, t);
    }
  }

  private void index(List mutations, ConsistencyLevel consistency)
          throws Throwable {
    Configuration conf = configurationDao.getConfiguration();

    for (IMutation mutation : mutations) {
      String keyspace = mutation.getTable();
      String rowKey = ByteBufferUtil.string(mutation.key());
      Collection cfs = ((RowMutation) mutation)
              .getColumnFamilies();
      if (INDEXING_KEYSPACE.equals(keyspace)) {
        continue;
      }

      // Iterate over mutated column families and create indexes for each
      for (ColumnFamily cf : cfs) {
        String cfName = cf.metadata().cfName;
        Map> configuredIndexes = conf.getIndexes(keyspace,
                cfName);
        if (configuredIndexes.isEmpty()) {
          continue;
        }

        // Get current and new values for all index columns
        Set allIndexColumns = new HashSet();
        for (Set columns : configuredIndexes.values()) {
          allIndexColumns.addAll(columns);
        }
        Map currentRow = fetchRow(keyspace, cfName, rowKey,
                allIndexColumns);
        Map newRow = getNewRow(currentRow, cf, allIndexColumns);

        // Iterate over configured indexes and create index for each
        for (String indexName : configuredIndexes.keySet()) {
          Set indexColumns = configuredIndexes.get(indexName);

          if (cf.isMarkedForDelete()) {
            indexDao.deleteIndex(indexName,
                    buildIndex(indexColumns, rowKey, currentRow), consistency);
          }
          else if (indexChanged(indexColumns, cf)) {
            if (!isEmptyIndex(indexColumns, currentRow)) {
              indexDao.deleteIndex(indexName,
                      buildIndex(indexColumns, rowKey, currentRow), consistency);
            }
            if (!isEmptyIndex(indexColumns, newRow)) {
              indexDao.insertIndex(indexName,
                      buildIndex(indexColumns, rowKey, newRow), consistency);
            }
          }
        }
      }
    }
  }

  private void writeCommitLog(List entries,
          ConsistencyLevel consistency) {
    for (LogEntry entry : entries) {
      commitLogDao.writeEntry(entry, consistency);
    }
  }

  private void writeCommitLog1(List entries,
          ConsistencyLevel consistency, Throwable t) {
    Writer writer = new StringWriter();
    t.printStackTrace(new PrintWriter(writer));
    String msg = writer.toString();

    for (LogEntry entry : entries) {
      entry.setStatus(Status.ERROR);
      entry.setMessage(msg);
    }
    writeCommitLog(entries, consistency);
  }

  private void removeCommitLog(List logEntries,
          ConsistencyLevel consistency) {
    for (LogEntry entry : logEntries) {
      commitLogDao.removeEntry(entry, consistency);
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy