org.cloudata.core.tabletserver.RecordSearcher.java Source code

Java tutorial

Introduction

Here is the source code for org.cloudata.core.tabletserver.RecordSearcher.java

Source

/**
 * 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
 *
 *     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.cloudata.core.tabletserver;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.cloudata.core.client.Cell;
import org.cloudata.core.client.CellFilter;
import org.cloudata.core.client.Row;
import org.cloudata.core.client.RowFilter;
import org.cloudata.core.tablet.ColumnValue;
import org.cloudata.core.tablet.RowColumnValues;
import org.cloudata.core.tabletserver.DiskSSTable.ColumnValueEntry;

public class RecordSearcher {
    public static final Log LOG = LogFactory.getLog(RecordSearcher.class.getName());

    private MemorySSTable memorySSTable;
    private DiskSSTable diskSSTable;
    private int numOfVersion;

    public RecordSearcher(MemorySSTable memorySSTable, DiskSSTable diskSSTable, int numOfVersion) {
        this.memorySSTable = memorySSTable;
        this.diskSSTable = diskSSTable;
        this.numOfVersion = numOfVersion;
    }

    public RecordSearcher(Tablet tablet) {
        this(tablet.memorySSTable, tablet.diskSSTable.get(), tablet.getTable().getNumOfVersion());
    }

    private List<Searchable> initSearchsers(Row.Key rowKey, CellFilter cellFilter) throws IOException {
        // MemorySSTable add? .
        //  MinorCompaction ?? get  data ?  return  ?.
        List<Searchable> searchers = new ArrayList<Searchable>();
        searchers.add(memorySSTable.getSearcher(rowKey, cellFilter));
        searchers.addAll(diskSSTable.getSearchers(rowKey, cellFilter));
        return searchers;
    }

    public ColumnValue search(Row.Key rowKey, String columnName, Cell.Key cellKey) throws IOException {
        CellFilter cellFilter = new CellFilter();
        cellFilter.setColumn(columnName, cellKey);

        ColumnValue[] result = searchColumnValues(rowKey, cellFilter);
        if (result != null && result.length > 0) {
            ColumnValue columnValue = result[0];
            return columnValue;
        } else {
            return null;
        }
    }

    public ColumnValue[] search(Row.Key rowKey, String columnName) throws IOException {
        CellFilter cellFilter = new CellFilter(columnName);

        return searchColumnValues(rowKey, cellFilter);
    }

    /**
     * ? ?  ? .
     * ? Row.Key, ? ? ? ? ? ? 2?  .
     * @param rowKey
     * @param columnNames
     * @return
     * @throws IOException
     */
    public ColumnValue[][] search(Row.Key rowKey, String[] columnNames) throws IOException {
        if (rowKey == null) {
            throw new IOException("rowkey is null");
        }
        //TODO  RowKey  ?  merge ??  ? 
        //TODO ?? ? 
        ColumnValue[][] columnValues = new ColumnValue[columnNames.length][];

        for (int i = 0; i < columnNames.length; i++) {
            columnValues[i] = search(rowKey, columnNames[i]);
        }
        return columnValues;
    }

    public RowColumnValues[] search(RowFilter rowFilter) throws IOException {
        if (rowFilter.getRowKey() == null || rowFilter.getRowKey().isEmpty()) {
            throw new IOException("rowkey is null");
        }

        Row.Key rowKey = rowFilter.getRowKey();

        List<CellFilter> cellFilters = rowFilter.getCellFilters();
        RowColumnValues[] result = new RowColumnValues[cellFilters.size()];

        int index = 0;
        boolean hasData = false;
        for (CellFilter eachCellFilter : cellFilters) {
            RowColumnValues rowColumnValues = new RowColumnValues();
            rowColumnValues.setRowKey(rowKey);
            rowColumnValues.setColumnName(eachCellFilter.getColumnName());

            ColumnValue[] columnValues = searchColumnValues(rowKey, eachCellFilter);

            if (columnValues != null && columnValues.length > 0) {
                hasData = true;
            }
            rowColumnValues.setColumnRecords(columnValues);
            result[index++] = rowColumnValues;
        }

        if (!hasData) {
            return null;
        } else {
            return result;
        }
    }

    private ColumnValue[] searchColumnValues(Row.Key rowKey, CellFilter cellFilter) throws IOException {
        if (rowKey == null) {
            throw new IOException("rowkey is null");
        }

        List<Searchable> searchers = initSearchsers(rowKey, cellFilter);
        try {
            if (searchers.isEmpty()) {
                return null;
            }
            List<ColumnValue> columnValues = mergeColumnValueFromSearcher(searchers, cellFilter);

            if (columnValues == null || columnValues.isEmpty()) {
                return null;
            }

            ColumnValue[] result = new ColumnValue[columnValues.size()];
            columnValues.toArray(result);
            return result;
        } finally {
        }
    }

    private List<ColumnValue> mergeColumnValueFromSearcher(List<Searchable> searcherList, CellFilter cellFilter)
            throws IOException {
        LinkedList<ColumnValueEntry> workPlace = new LinkedList<ColumnValueEntry>();
        Searchable[] searchers = searcherList.toArray(new Searchable[] {});

        try {
            initWorkPlace(workPlace, searchers);

            int numOfValues = cellFilter.getNumOfValues();

            List<ColumnValue> result = new ArrayList<ColumnValue>();
            ValueCollection currentColumnValues = new ValueCollection();

            Cell.Key previousColumnKey = null;
            ColumnValue previousColumnValue = null;

            boolean end = false;

            while (!end) {
                int size = workPlace.size();
                if (size == 0) {
                    break;
                }
                Collections.sort(workPlace);
                ColumnValueEntry winner = workPlace.removeFirst();

                if (previousColumnKey == null) {
                    previousColumnKey = winner.columnValue.getCellKey();
                }

                //meets new ValueCollection
                if (!previousColumnKey.equals(winner.columnValue.getCellKey())) {
                    currentColumnValues.moveMatchedValues(cellFilter, result);
                    currentColumnValues = new ValueCollection();
                }

                if (previousColumnValue == null || !previousColumnValue.equals(winner.columnValue)) {
                    currentColumnValues.add(winner.columnValue, numOfVersion);
                    previousColumnKey = winner.columnValue.getCellKey();
                    previousColumnValue = winner.columnValue;
                }

                //fetch from winner, add workPlace
                end = !fetchFromWinner(workPlace, searchers, winner.index);

                if (result.size() >= numOfValues) {
                    break;
                }
            } //end of while

            if (result.size() < numOfValues) {
                //check last value in while loop
                if (currentColumnValues.getValueSize() > 0) {
                    currentColumnValues.moveMatchedValues(cellFilter, result);
                }
                return result;
            } else {
                return result.subList(0, numOfValues);
            }
        } finally {
            //scnner close
            for (int i = 0; i < searchers.length; i++) {
                if (searchers[i] != null) {
                    try {
                        searchers[i].close();
                    } catch (IOException e) {
                        LOG.error("Can't close scanner:" + searchers[i]);
                    }
                    searchers[i] = null;
                }
            }
        }
    }

    /**
     * @param workPlace
     * @param searchers
     * @throws IOException
     */
    private void initWorkPlace(LinkedList<ColumnValueEntry> workPlace, Searchable[] searchers) throws IOException {
        for (int i = 0; i < searchers.length; i++) {
            if (searchers[i] != null) {
                ColumnValue columnValue = searchers[i].next();

                if (columnValue != null) {
                    workPlace.add(new ColumnValueEntry(columnValue, i));
                } else {
                    searchers[i].close();
                    searchers[i] = null;
                }
            }
        }
    }

    private boolean fetchFromWinner(LinkedList<ColumnValueEntry> workPlace, Searchable[] searchers, int winnerIndex)
            throws IOException {
        ColumnValue columnValue = null;
        if (searchers[winnerIndex] != null) {
            columnValue = searchers[winnerIndex].next();
        }

        if (columnValue != null) {
            workPlace.add(new ColumnValueEntry(columnValue, winnerIndex));
            return true;
        } else {
            if (searchers[winnerIndex] != null) {
                searchers[winnerIndex].close();
            }
            searchers[winnerIndex] = null;

            boolean end = workPlace.isEmpty();
            for (int i = 0; i < searchers.length; i++) {
                if (searchers[i] != null) {
                    columnValue = searchers[i].next();
                    if (columnValue != null) {
                        workPlace.add(new ColumnValueEntry(columnValue, i));
                        end = false;
                        break;
                    } else {
                        searchers[i].close();
                        searchers[i] = null;
                    }
                }
            }
            return !end;
        }
    }

    public boolean hasValue(String columnName, Row.Key rowKey, Cell.Key cellKey) throws IOException {
        //List<Searchable> searchers = initSearchsers(rowKey, columnName, null);
        if (memorySSTable.hasValue(rowKey, columnName, cellKey)) {
            return true;
        }
        return diskSSTable.hasValue(rowKey, columnName, cellKey);
    }
}