Package com.foundationdb.server.store

Source Code of com.foundationdb.server.store.StoreGIHandler

/**
* Copyright (C) 2009-2013 FoundationDB, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package com.foundationdb.server.store;

import com.foundationdb.ais.model.Column;
import com.foundationdb.ais.model.GroupIndex;
import com.foundationdb.ais.model.IndexRowComposition;
import com.foundationdb.ais.model.Table;
import com.foundationdb.qp.rowtype.InternalIndexTypes;
import com.foundationdb.qp.rowtype.RowType;
import com.foundationdb.qp.rowtype.Schema;
import com.foundationdb.qp.row.Row;
import com.foundationdb.qp.row.WriteIndexRow;
import com.foundationdb.server.service.session.Session;
import com.foundationdb.server.types.TInstance;
import com.foundationdb.server.types.common.BigDecimalWrapper;
import com.foundationdb.server.types.value.Value;
import com.foundationdb.server.types.value.ValueSource;
import com.foundationdb.server.spatial.Spatial;
import com.foundationdb.util.ArgumentValidation;
import com.geophile.z.Space;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;

class StoreGIHandler<SType extends AbstractStore,SDType,SSDType extends StoreStorageDescription<SType,SDType>> {
    private static final TInstance NON_NULL_Z_TYPE = InternalIndexTypes.LONG.instance(false);

    public static enum GroupIndexPosition {
        ABOVE_SEGMENT,
        BELOW_SEGMENT,
        WITHIN_SEGMENT
    }

    public static enum Action {
        STORE,
        DELETE,
        CASCADE,
        CASCADE_STORE
    }

    private final AbstractStore<SType,SDType,SSDType> store;
    private final Session session;
    private final Table sourceTable;
    private final WriteIndexRow indexRow;
    private final Value zSource_t3 = new Value(InternalIndexTypes.LONG.instance(true));
    private final Collection<RowType> lockTypes;

    private StoreGIHandler(AbstractStore<SType,SDType,SSDType> store, Session session, Schema schema, Table sourceTable, Table lockLeaf) {
        this.store = store;
        this.session = session;
        this.indexRow = new WriteIndexRow(store);
        this.sourceTable = sourceTable;
        if(lockLeaf == null) {
            this.lockTypes = null;
        } else {
            this.lockTypes = new ArrayList<>(lockLeaf.getDepth());
            for(Table table = lockLeaf; table != null; table = table.getParentTable()) {
                lockTypes.add(schema.tableRowType(table));
            }
        }
    }

    public static <SType extends AbstractStore,SDType,SSDType extends StoreStorageDescription<SType,SDType>> StoreGIHandler forTable(AbstractStore<SType,SDType,SSDType> store,
                                                                                                               Session session,
                                                                                                               Table table) {
        ArgumentValidation.notNull("table", table);
        return new StoreGIHandler<>(store, session, null, table, null);
    }

    public static <SType extends AbstractStore,SDType,SSDType extends StoreStorageDescription<SType,SDType>> StoreGIHandler forBuilding(AbstractStore<SType,SDType,SSDType> store,
                                                                                                                  Session session,
                                                                                                                  Schema schema,
                                                                                                                  GroupIndex groupIndex) {
        return new StoreGIHandler<>(store, session, schema, null, groupIndex.leafMostTable());
    }

    public void handleRow(GroupIndex groupIndex, Row row, Action action) {
        GroupIndexPosition sourceRowPosition = positionWithinBranch(groupIndex, sourceTable);
        if (sourceRowPosition.equals(GroupIndexPosition.BELOW_SEGMENT)) {
            return; // nothing to do
        }

        if(lockTypes != null) {
            for(RowType type : lockTypes) {
                Row subRow = row.subRow(type);
                if(subRow != null) {
                   store.lock(session, subRow);
                }
            }
        }
        int firstSpatialColumn = groupIndex.isSpatial() ? groupIndex.firstSpatialArgument() : -1;
        SDType storeData = store.createStoreData(session, groupIndex);
        try {
            store.resetForWrite(storeData, groupIndex, indexRow);
            IndexRowComposition irc = groupIndex.indexRowComposition();
            int nFields = irc.getLength();
            int f = 0;
            while(f < nFields) {
                assert irc.isInRowData(f);
                assert ! irc.isInHKey(f);
                if(f == firstSpatialColumn) {
                    copyZValueToIndexRow(groupIndex, row, irc);
                    f += groupIndex.dimensions();
                } else {
                    copyFieldToIndexRow(groupIndex, row, irc.getFieldPosition(f++));
                }
            }
            // Non-null values only required for UNIQUE indexes, which GIs cannot be
            assert !groupIndex.isUnique() : "Unexpected unique index: " + groupIndex;
            indexRow.close(null, null, false);
            indexRow.tableBitmap(tableBitmap(groupIndex, row));
            switch (action) {
                case CASCADE_STORE:
                case STORE:
                    store.store(session, storeData);
                break;
                case CASCADE:
                case DELETE:
                    store.clear(session, storeData);
                break;
                default:
                    throw new UnsupportedOperationException(action.name());
            }
        } finally {
            store.releaseStoreData(session, storeData);
        }
    }

    public Table getSourceTable () {
        return sourceTable;
    }

    private void copyFieldToIndexRow(GroupIndex groupIndex, Row row, int flattenedIndex) {
        Column column = groupIndex.getColumnForFlattenedRow(flattenedIndex);
        indexRow.append(row.value(flattenedIndex), column.getType());
    }

    private void copyZValueToIndexRow(GroupIndex groupIndex, Row row, IndexRowComposition irc) {
        BigDecimal[] coords = new BigDecimal[Spatial.LAT_LON_DIMENSIONS];
        Space space = groupIndex.space();
        int firstSpatialColumn = groupIndex.firstSpatialArgument();
        boolean zNull = false;
        for(int d = 0; d < Spatial.LAT_LON_DIMENSIONS; d++) {
            if(!zNull) {
                ValueSource columnValue = row.value(irc.getFieldPosition(firstSpatialColumn + d));
                if (columnValue.isNull()) {
                    zNull = true;
                } else {
                    coords[d] = ((BigDecimalWrapper)columnValue.getObject()).asBigDecimal();
                }
            }
        }
        if (zNull) {
            zSource_t3.putNull();
            indexRow.append(zSource_t3, NON_NULL_Z_TYPE);
        } else {
            zSource_t3.putInt64(Spatial.shuffle(space, coords[0].doubleValue(), coords[1].doubleValue()));
            indexRow.append(zSource_t3, NON_NULL_Z_TYPE);
        }
    }

    // The group index row's value contains a bitmap indicating which of the tables covered by the index
    // have rows contributing to this index row. The leafmost table of the index is represented by bit
    // position 0.
    private long tableBitmap(GroupIndex groupIndex, Row row) {
        long result = 0;
        Table table = groupIndex.leafMostTable();
        Table end = groupIndex.rootMostTable().getParentTable();
        while(table != null && !table.equals(end)) {
            if(row.containsRealRowOf(table)) {
                result |= (1 << table.getDepth());
            }
            table = table.getParentTable();
        }
        return result;
    }

    private GroupIndexPosition positionWithinBranch(GroupIndex groupIndex, Table table) {
        final Table leafMost = groupIndex.leafMostTable();
        if(table == null) {
            return GroupIndexPosition.ABOVE_SEGMENT;
        }
        if(table.equals(leafMost)) {
            return GroupIndexPosition.WITHIN_SEGMENT;
        }
        if(table.isDescendantOf(leafMost)) {
            return GroupIndexPosition.BELOW_SEGMENT;
        }
        if(groupIndex.rootMostTable().equals(table)) {
            return GroupIndexPosition.WITHIN_SEGMENT;
        }
        return groupIndex.rootMostTable().isDescendantOf(table)
                ? GroupIndexPosition.ABOVE_SEGMENT
                : GroupIndexPosition.WITHIN_SEGMENT;
    }
}
TOP

Related Classes of com.foundationdb.server.store.StoreGIHandler

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.