com.tesora.dve.distribution.DistributionRange.java Source code

Java tutorial

Introduction

Here is the source code for com.tesora.dve.distribution.DistributionRange.java

Source

package com.tesora.dve.distribution;

/*
 * #%L
 * Tesora Inc.
 * Database Virtualization Engine
 * %%
 * Copyright (C) 2011 - 2014 Tesora Inc.
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License, version 3,
 * as published by the Free Software Foundation.
 * 
 * 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/>.
 * #L%
 */

import java.sql.Types;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;

import org.hibernate.annotations.ForeignKey;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import com.tesora.dve.common.catalog.CatalogDAO;
import com.tesora.dve.common.catalog.CatalogEntity;
import com.tesora.dve.common.catalog.CatalogQueryOptions;
import com.tesora.dve.common.catalog.PersistentGroup;
import com.tesora.dve.common.catalog.PersistentSite;
import com.tesora.dve.common.catalog.StorageGroupGeneration;
import com.tesora.dve.exceptions.PEException;
import com.tesora.dve.resultset.ColumnSet;
import com.tesora.dve.resultset.ResultRow;
import com.tesora.dve.worker.WorkerGroup.MappingSolution;

@Entity
@Table(name = "distribution_range")
public class DistributionRange implements CatalogEntity {

    private static final long serialVersionUID = 1L;

    private static Logger logger = Logger.getLogger(DistributionRange.class);

    @Id
    @GeneratedValue
    @Column(name = "range_id")
    private int id;

    @Column(name = "name", nullable = false)
    private String name;

    @ForeignKey(name = "fk_range_group")
    @ManyToOne(optional = false)
    @JoinColumn(name = "persistent_group_id")
    private PersistentGroup storageGroup;

    @OneToMany(mappedBy = "distributionRange", cascade = CascadeType.ALL)
    @OrderBy("version")
    List<GenerationKeyRange> rangeGenerations = new ArrayList<GenerationKeyRange>();

    private String signature;

    private transient ColumnSet showColumnSet = null;

    public DistributionRange() {
    }

    public DistributionRange(String name, PersistentGroup sg, String signature) {
        this.name = name;
        this.storageGroup = sg;
        this.signature = signature;
    }

    /**
     * @throws PEException
     */
    public void fullyLoad() throws PEException {
        // a hibernate workaround to load the data structures  
        for (StorageGroupGeneration sgg : storageGroup.getGenerations())
            sgg.getStorageSites().size();
        rangeGenerations.size();
    }

    public MappingSolution mapKeyToGeneration(IKeyValue key) throws PEException {
        StorageGroupGeneration groupGen = storageGroup.getLastGen();

        setComparatorClass(key);
        ListIterator<GenerationKeyRange> i = rangeGenerations.listIterator(rangeGenerations.size());
        while (i.hasPrevious()) {
            //TODO: this traverses from youngest to oldest, but returns oldest match or lastGen(), which can be confusing.  -sgossard
            GenerationKeyRange genKeyRange = i.previous();
            if (genKeyRange.isInRange(key))
                groupGen = genKeyRange.getStorageGroupGeneration();
            else
                break;
        }
        if (logger.isDebugEnabled()) {
            logger.debug("Mapping key " + key.toString() + " to generation " + groupGen.getVersion()
                    + " using range " + this + " which has " + rangeGenerations.size()
                    + " generations and is rep'd by object " + System.identityHashCode(this));
        }

        return getMappingInGeneration(key, groupGen);
    }

    public MappingSolution getMappingInGeneration(IKeyValue key, StorageGroupGeneration groupGen) {
        List<PersistentSite> siteList = groupGen.getStorageSites();
        int selectedMember = Math.abs(key.hashCode()) % siteList.size();
        return new MappingSolution(siteList.get(selectedMember));
    }

    private void setComparatorClass(IKeyValue key) {
        Map<String, String> typesNeedingComparator = getSignatureComparatorMap(signature);

        if (typesNeedingComparator.size() > 0) {
            Map<String, ? extends IColumnDatum> vals = key.getValues();
            for (String colName : vals.keySet()) {
                IColumnDatum icd = vals.get(colName);
                String nativeType = icd.getNativeType();
                if (typesNeedingComparator.containsKey(nativeType)) {
                    icd.setComparatorClassName(typesNeedingComparator.get(nativeType));
                }
            }
        }
    }

    public String getName() {
        return name;
    }

    public String getSignature() {
        return signature;
    }

    public PersistentGroup getStorageGroup() {
        return storageGroup;
    }

    public void addRangeGeneration(GenerationKeyRange generationKeyRange) {
        rangeGenerations.add(generationKeyRange);
    }

    public GenerationKeyRange getRangeForGeneration(StorageGroupGeneration newGen) {
        GenerationKeyRange theKeyRange = null;
        for (GenerationKeyRange keyRange : rangeGenerations) {
            if (keyRange.getStorageGroupGeneration().equals(newGen)) {
                theKeyRange = keyRange;
                break;
            }
        }
        return theKeyRange;
    }

    public GenerationKeyRange removeRangeForGeneration(StorageGroupGeneration newGen) {
        GenerationKeyRange kr = getRangeForGeneration(newGen);
        if (kr == null)
            return null;
        rangeGenerations.remove(kr);
        return kr;
    }

    @Override
    public ColumnSet getShowColumnSet(CatalogQueryOptions cqo) {
        if (showColumnSet == null) {
            showColumnSet = new ColumnSet();
            showColumnSet.addColumn("Name", 255, "varchar", Types.VARCHAR);
            showColumnSet.addColumn("StorageGroup", 255, "varchar", Types.VARCHAR);
            showColumnSet.addColumn("Signature", 255, "varchar", Types.VARCHAR);
        }
        return showColumnSet;
    }

    @Override
    public ResultRow getShowResultRow(CatalogQueryOptions cqo) {
        ResultRow rr = new ResultRow();
        rr.addResultColumn(this.name, false);
        rr.addResultColumn(this.storageGroup.getName(), false);
        rr.addResultColumn(this.signature);
        return rr;
    }

    @Override
    public void removeFromParent() {
        // TODO Actually implement the removal of this instance from the parent
    }

    @Override
    public List<CatalogEntity> getDependentEntities(CatalogDAO c) throws Throwable {
        // TODO Return a valid list of dependents
        return Collections.emptyList();
    }

    @Override
    public String toString() {
        return "DistributionRange(" + id + ", " + name + ", " + signature + ")";
    }

    public int getId() {
        return id;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        DistributionRange other = (DistributionRange) obj;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }

    @Override
    public void onUpdate() {
        // do nothing
    }

    @Override
    public void onDrop() {
        // do nothing
    }

    private static Map<String, Map<String, String>> signatureComparatorMap = new ConcurrentHashMap<String, Map<String, String>>();

    public Map<String, String> getSignatureComparatorMap(String signatureKey) {
        Map<String, String> comparatorMap = signatureComparatorMap.get(signatureKey);
        if (comparatorMap == null) {
            comparatorMap = decodeSignatureIntoNativeTypeComparatorMap(signatureKey);
            signatureComparatorMap.put(signatureKey, comparatorMap);
        }
        return comparatorMap;
    }

    public static Map<String, String> decodeSignatureIntoNativeTypeComparatorMap(String signature) {
        Map<String, String> nativeTypeToComparatorMap = new HashMap<String, String>();
        String[] colSignatures = signature.split(",");
        for (String colSignature : colSignatures) {
            if (colSignature.contains(":")) {
                String[] parts = colSignature.split(":");
                if (!StringUtils.isEmpty(parts[1])) {
                    // modify key value with the name of the comparator to use
                    nativeTypeToComparatorMap.put(parts[0], parts[1]);
                }
            }
        }
        return nativeTypeToComparatorMap;
    }
}