Package com.alvazan.ssql.cmdline

Source Code of com.alvazan.ssql.cmdline.CmdIndex$Counter

package com.alvazan.ssql.cmdline;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alvazan.orm.api.base.NoSqlEntityManager;
import com.alvazan.orm.api.z3api.NoSqlTypedSession;
import com.alvazan.orm.api.z3api.QueryResult;
import com.alvazan.orm.api.z5api.IndexPoint;
import com.alvazan.orm.api.z8spi.KeyValue;
import com.alvazan.orm.api.z8spi.action.IndexColumn;
import com.alvazan.orm.api.z8spi.conv.StandardConverters;
import com.alvazan.orm.api.z8spi.iter.Cursor;
import com.alvazan.orm.api.z8spi.meta.DboColumnMeta;
import com.alvazan.orm.api.z8spi.meta.DboColumnToOneMeta;
import com.alvazan.orm.api.z8spi.meta.DboTableMeta;
import com.alvazan.orm.api.z8spi.meta.TypedColumn;
import com.alvazan.orm.api.z8spi.meta.TypedRow;

public class CmdIndex {
  private static final Logger log = LoggerFactory.getLogger(CmdIndex.class);
  private static final int BATCH_SIZE = 200;
  private Integer totalRowCount = null;
  //private static final int TIME_TO_REPORT = 10000;
 
  public void reindex(String cmd, NoSqlEntityManager mgr) {
    String oldCommand = cmd.substring(8);
    String command = oldCommand.trim();
    ColFamilyData data = parseData(mgr, command);
   
    NoSqlTypedSession s = mgr.getTypedSession();
    String cf = data.getColFamily();
    String field = data.getColumn();
    String by = data.getPartitionBy();
    String id = data.getPartitionId();
    Cursor<IndexPoint> indexView = s.indexView(cf, field, by, id);
    Cursor<IndexPoint> indexView2 = s.indexView(cf, field, by, id);
   
    DboTableMeta meta = data.getTableMeta();
    DboColumnMeta colMeta = data.getColumnMeta();
    System.out.println("indexed value type="+colMeta.getStorageType());
    System.out.println("row key type="+meta.getIdColumnMeta().getStorageType());
    System.out.println("It is safe to kill this process at any time since it only removes duplicates");
    System.out.println("Beginning re-index");

    int totalChanges = 0;
    int rowCountProcessed = 0;
    while(true) {
      Map<Object, KeyValue<TypedRow>> keyToRow = findNextSetOfData(s, cf, indexView);
      rowCountProcessed += keyToRow.size();
      if(keyToRow.size() == 0) {
        break; //finished
      }
     
      Counter c = processAllColumns(s, data, keyToRow, indexView2);
      totalChanges += c.getChangedCounter();
     
      if(rowCountProcessed % 1000 == 0) {
        System.out.println("#Rows processed="+rowCountProcessed+" totalRows to process="+totalRowCount+" totalChanges so far="+totalChanges);
      }
    }
   
    System.out.println("#Rows processed="+rowCountProcessed+" totalRows to process="+totalRowCount+" totalChanges="+totalChanges);
  }

  private Counter processAllColumns(NoSqlTypedSession s, ColFamilyData data, Map<Object, KeyValue<TypedRow>> keyToRow,
      Cursor<IndexPoint> indexView2) {
    String colName = data.getColumn();
   
    indexView2.beforeFirst();
    int rowCounter = 0;
    int changedCounter = 0;
    while(indexView2.next()) {
      rowCounter++;
      IndexPoint pt = indexView2.getCurrent();
     
      KeyValue<TypedRow> row = keyToRow.get(pt.getKey());
      if(row == null) {
        if(log.isDebugEnabled())
          log.debug("row is null for key="+pt.getKey());
        //We are iterating over two views in batch mode soooo
        //one batch may not have any of the keys of the other batch.  This is very normal
      } else if(row.getException() != null || row.getValue() == null) {
        removeIndexPt(s, data, pt);
        changedCounter++;
      } else {
        TypedRow val = row.getValue();
        if (processColumn(s, data, val, pt)) {
          changedCounter++;
        }
      }

      if(changedCounter > 50) {
        s.flush();
        //System.out.println("Successfully flushed all previous changes.  row="+rowCounter);
      }
      if(rowCounter % 20000 == 0) {
        System.out.println("reindexing.  row count so far="+rowCounter+" num index points changed="+changedCounter);
      }
    }
   
    if(totalRowCount == null)
      totalRowCount = rowCounter;
    s.flush();
    return new Counter(rowCounter, changedCounter);
  }

  private boolean processColumn(NoSqlTypedSession s, ColFamilyData data,TypedRow typedRow,
      IndexPoint pt) {
    String colName = data.getColumn();
    TypedColumn column = typedRow.getColumn(colName);
    if (column == null) {
      //It means column was deleted by user. Doing nothing as of now
      return false;
    }
    else {
      Object value = column.getValue();
      DboColumnMeta colMeta = data.getColumnMeta();
      if (value == null && colMeta instanceof DboColumnToOneMeta) {
        DboColumnToOneMeta one = (DboColumnToOneMeta) colMeta;
        value = one.convertFromStorage2(column.getCompositeSubName());
      }
      if(!valuesEqual(pt.getIndexedValue(), value)) {
        System.out.println("Entity with rowkey="+pt.getKeyAsString()+" has extra incorrect index point with value="+pt.getIndexedValueAsString()+" correct value should be= "+value);
        s.removeIndexPoint(pt, data.getPartitionBy(), data.getPartitionId());
        IndexColumn col = new IndexColumn();
        col.setColumnName(colName);
        col.setPrimaryKey(pt.getRawKey());
        byte[] indValue = StandardConverters.convertToBytes(value);
        col.setIndexedValue(indValue);
        IndexPoint newPoint = new IndexPoint(pt.getRowKeyMeta(), col,data.getColumnMeta());
        s.addIndexPoint(newPoint, data.getPartitionBy(), data.getPartitionId());
        return true;
      }
    }
    return false;
  }

  private void removeIndexPt(NoSqlTypedSession s, ColFamilyData data,
      IndexPoint pt) {
    System.out.println("Entity with rowkey="+pt.getKeyAsString()+" does not exist, WILL remove from index");
    s.removeIndexPoint(pt, data.getPartitionBy(), data.getPartitionBy());
  }

  private boolean valuesEqual(Object indexedValue, Object value) {
    if(indexedValue == null) {
      if(value == null)
        return true;
      return false;
    } else if(indexedValue.equals(value))
      return true;
   
    return false;
  }

  private static class Counter {
    private int rowCounter;
    private int changedCounter;
    public Counter(int rowCounter, int changedCounter) {
      super();
      this.rowCounter = rowCounter;
      this.changedCounter = changedCounter;
    }
    public int getRowCounter() {
      return rowCounter;
    }
    public int getChangedCounter() {
      return changedCounter;
    }
  }
 
  private Map<Object, KeyValue<TypedRow>> findNextSetOfData(
      NoSqlTypedSession s, String cf, Cursor<IndexPoint> indexView) {
    int batchCounter = 0;
    List<Object> keys = new ArrayList<Object>();
    while(batchCounter < BATCH_SIZE && indexView.next()) {
      IndexPoint current = indexView.getCurrent();
      keys.add(current.getKey());
      batchCounter++;
    }
   
    Map<Object, KeyValue<TypedRow>> keyToRow = new HashMap<Object, KeyValue<TypedRow>>();
    Cursor<KeyValue<TypedRow>> cursor = s.createFindCursor(cf, keys, BATCH_SIZE);
    while(cursor.next()) {
      KeyValue<TypedRow> current = cursor.getCurrent();
      keyToRow.put(current.getKey(), current);
    }
    return keyToRow;
  }
 
  public void processIndex(String cmd, NoSqlEntityManager mgr) {
    String oldCommand = cmd.substring(10);
    String command = oldCommand.trim();
   
    ColFamilyData data = parseData(mgr, command);
    NoSqlTypedSession s = mgr.getTypedSession();
   
    String cf = data.getColFamily();
    String field = data.getColumn();
    String by = data.getPartitionBy();
    String id = data.getPartitionId();

    Cursor<IndexPoint> indexView = s.indexView(cf, field, by, id);

    DboTableMeta meta = data.getTableMeta();
    DboColumnMeta colMeta = data.getColumnMeta();
    System.out.println("indexed value type="+colMeta.getStorageType());
    System.out.println("row key type="+meta.getIdColumnMeta().getStorageType());
    System.out.println("<indexed value>.<row key>");

    int count = 0;
    while(indexView.next()) {
      IndexPoint current = indexView.getCurrent();
      String indVal = current.getIndexedValueAsString();
      if(indVal == null)
        indVal = "";
      String key = current.getKeyAsString();
      System.out.println(count+" "+indVal+"."+key);
      count++;
    }
    System.out.println(count+" Columns Total")
  }
 
  public ColFamilyData parseData(NoSqlEntityManager mgr, String command) {
    int index = command.indexOf("/");
    if(index != 0) {
      throw new InvalidCommand("Index must start with '/' and does not");
    }
    String withoutSlash = command.substring(1);
    index = withoutSlash.indexOf("/");
    if(index < 0) {
      throw new InvalidCommand("Index requires two '/'");
    }

    String cf = withoutSlash.substring(0, index);
    String lastPart = withoutSlash.substring(index+1);
    return goMore(mgr, cf, lastPart);
  }

  private ColFamilyData goMore(NoSqlEntityManager mgr, String cf, String lastPart) {
    ColFamilyData data = new ColFamilyData();
   
    int index = lastPart.indexOf("/");
    String field = null;
    String partitionBy = null;
    String partitionId = null;
    if(index < 0) {
      field = lastPart;
    } else {
      field = lastPart.substring(0, index);
      String partitionPart = lastPart.substring(index);
      index = partitionPart.indexOf("/");
      if(index < 0)
        throw new InvalidCommand("Must have two or four '/' characters");

      partitionBy = partitionPart.substring(0, index);
      partitionId = partitionPart.substring(index);
    }
   
    DboTableMeta meta = mgr.find(DboTableMeta.class, cf);
    if (meta == null) {
      System.out.println("Column family meta not found for " + cf);
      System.out.println("You can select from following tables:");
      QueryResult result = mgr.getTypedSession().createQueryCursor("select * from DboTableMeta", 100);
      Cursor<List<TypedRow>> cursor = result.getAllViewsCursor();
      while (cursor.next()) {
        List<TypedRow> joinedRow = cursor.getCurrent();
        for (TypedRow r : joinedRow) {
          System.out.println(r.getRowKeyString());
        }
      }
      System.out.println("");
      throw new InvalidCommand("Column family meta not found for " + cf);
    }
   
    DboColumnMeta colMeta = meta.getColumnMeta(field);
    if(colMeta == null) {
      colMeta = meta.getIdColumnMeta();
      if(!(colMeta != null && colMeta.getColumnName().equals(field))) {
        System.out.println("Column= "+field+" not found on table "+cf);
        System.out.println("You can view index for following columns:");
        for(DboColumnMeta colMetaOther : meta.getIndexedColumns()) {
          System.out.println(colMetaOther.getColumnName());
        }
        System.out.println("");
        throw new InvalidCommand("Column= "+field+" not found on table "+cf);
      }
    }
   
    data.setColFamily(cf);
    data.setColumn(field);
    data.setPartitionBy(partitionBy);
    data.setPartitionId(partitionId);
    data.setTableMeta(meta);
    data.setColumnMeta(colMeta);
   
    return data;
  }

}
TOP

Related Classes of com.alvazan.ssql.cmdline.CmdIndex$Counter

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.