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

com.sleepycat.persist.impl.PersistComparator Maven / Gradle / Ivy

There is a newer version: 18.3.12
Show newest version
/*-
 * See the file LICENSE for redistribution information.
 *
 * Copyright (c) 2002, 2013 Oracle and/or its affiliates.  All rights reserved.
 *
 */

package com.sleepycat.persist.impl;

import java.io.Serializable;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;

import com.sleepycat.compat.DbCompat;
/*  */
import com.sleepycat.je.DatabaseComparator;
/*  */

/**
 * The btree comparator for persistent key classes.  The serialized form of
 * this comparator is stored in the BDB JE database descriptor so that the
 * comparator can be re-created during recovery.
 *
 * @author Mark Hayes
 */
public class PersistComparator implements
    /*  */
    DatabaseComparator,
    /*  */
    Comparator, Serializable {

    private static final long serialVersionUID = 5221576538843355317L;

    private String keyClassName;
    private String[] comositeFieldOrder;
    private Map fieldFormatData;
    private transient PersistKeyBinding binding;

    public PersistComparator(PersistKeyBinding binding) {
        this.binding = binding;
        /* Save info necessary to recreate binding during deserialization. */
        final CompositeKeyFormat format =
            (CompositeKeyFormat) binding.keyFormat;
        keyClassName = format.getClassName();
        comositeFieldOrder = CompositeKeyFormat.getFieldNameArray
            (format.getClassMetadata().getCompositeKeyFields());
        /* Currently only enum formats have per-class data. */
        for (FieldInfo field : format.getFieldInfo()) {
            Format fieldFormat = field.getType();
            if (fieldFormat.isEnum()) {
                EnumFormat enumFormat = (EnumFormat) fieldFormat;
                if (fieldFormatData == null) {
                    fieldFormatData = new HashMap();
                }
                fieldFormatData.put(enumFormat.getClassName(),
                                    enumFormat.getFormatData());
            }
        }
    }

    /**
     * In BDB JE this method will be called after the comparator is
     * deserialized, including during recovery.  We must construct the binding
     * here, without access to the stored catalog since recovery is not
     * complete.
     */
    public void initialize(ClassLoader loader) {
        final Catalog catalog;
        if (fieldFormatData == null) {
            catalog = new ComparatorCatalog(loader, null);
        } else {
            final Map enumFormats =
                new HashMap();
            catalog = new ComparatorCatalog(loader, enumFormats);
            for (Map.Entry entry :
                 fieldFormatData.entrySet()) {
                final String fldClassName = entry.getKey();
                final String[] enumNames = entry.getValue();
                final Class fldClass;
                try {
                    fldClass = catalog.resolveClass(fldClassName);
                } catch (ClassNotFoundException e) {
                    throw new IllegalStateException(e);
                }
                enumFormats.put(fldClassName,
                                new EnumFormat(catalog, fldClass, enumNames));
            }
            for (Format fldFormat : enumFormats.values()) {
                fldFormat.initializeIfNeeded(catalog, null /*model*/);
            }
        }
        final Class keyClass;
        try {
            keyClass = catalog.resolveClass(keyClassName);
        } catch (ClassNotFoundException e) {
            throw new IllegalStateException(e);
        }
        binding = new PersistKeyBinding(catalog, keyClass,
                                        comositeFieldOrder);
    }

    public int compare(byte[] b1, byte[] b2) {

        /*
         * In BDB JE, the binding is initialized by the initialize method.  In
         * BDB, the binding is intialized by the constructor.
         */
        if (binding == null) {
            throw DbCompat.unexpectedState("Not initialized");
        }

        try {
            Comparable k1 =
                (Comparable) binding.bytesToObject(b1, 0, b1.length);
            Comparable k2 =
                (Comparable) binding.bytesToObject(b2, 0, b2.length);

            return k1.compareTo(k2);
        } catch (RefreshException e) {

            /*
             * Refresh is not applicable to PersistComparator, which is used
             * during recovery.  All field formats used by the comparator are
             * guaranteed to be predefined, because they must be primitive or
             * primitive wrapper types.  So they are always present in the
             * catalog, and cannot change as the result of class evolution or
             * replication.
             */
            throw DbCompat.unexpectedException(e);
        }
    }

    @Override
    public String toString() {
        StringBuilder b = new StringBuilder();
        b.append("[DPL comparator ");
        b.append(" keyClassName = ").append(keyClassName);
        b.append(" comositeFieldOrder = [");
        for (String s : comositeFieldOrder) {
            b.append(s).append(',');
        }
        b.append(']');
        b.append(" fieldFormatData = {");
        for (Map.Entry entry : fieldFormatData.entrySet()) {
            b.append(entry.getKey()).append(": [");
            for (String s : entry.getValue()) {
                b.append(s).append(',');
            }
            b.append(']');
        }
        b.append('}');
        b.append(']');
        return b.toString();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy