Package org.apache.xindice.tools

Source Code of org.apache.xindice.tools.DatabaseRebuild$CopyCallback

/*
* 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.
*
* $Id: DatabaseRebuild.java 533253 2007-04-27 23:12:12Z vgritsenko $
*/

package org.apache.xindice.tools;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xindice.core.Collection;
import org.apache.xindice.core.DBException;
import org.apache.xindice.core.Database;
import org.apache.xindice.core.data.Key;
import org.apache.xindice.core.data.Value;
import org.apache.xindice.core.filer.BTreeCallback;
import org.apache.xindice.core.filer.BTreeException;
import org.apache.xindice.core.filer.BTreeFiler;
import org.apache.xindice.core.filer.Filer;
import org.apache.xindice.core.filer.HashFiler;
import org.apache.xindice.core.indexer.Indexer;
import org.apache.xindice.util.Configuration;
import org.apache.xindice.util.XindiceException;
import org.apache.xindice.xml.dom.DOMParser;
import org.apache.xindice.server.Xindice;

import java.io.File;
import java.io.IOException;

/**
* Command line utility to re-build all btree and hash filer based collections
* of the database, and re-index.
*
* @version $Revision: 533253 $, $Date: 2007-04-27 19:12:12 -0400 (Fri, 27 Apr 2007) $
*/
public class DatabaseRebuild {

    private static final Log log = LogFactory.getLog(DatabaseRebuild.class);

    private static final int CMD_ALL   = 0;
    private static final int CMD_COPY  = 1;
    private static final int CMD_INDEX = 2;

    private static final char NOT_RAN = '_';
    private static final char SUCCESS = '*';
    private static final char ERROR   = '!';


    public static void main(String[] args) throws Exception {
        if (args.length < 2 || args[1] == null || args[1].length() == 0 ||
            !("copy".equals(args[0]) || "index".equals(args[0]) || "rebuild".equals(args[0]))) {
            usage();
            System.exit(1);
        }

        int command;
        if ("copy".equals(args[0])) {
            command = CMD_COPY;
        } else if ("index".equals(args[0])) {
            command = CMD_INDEX;
        } else {
            command = CMD_ALL;
        }

        File location = new File(args[1]);
        String path = location.getAbsolutePath();
        String name = location.getName();

        if ("".equals(name) || !location.exists() || !location.isDirectory()) {
            System.out.println("Database path must point to existing database directory");
            System.exit(1);
        }

        // create minimal database configuration instead of trying to locate system.xml
        String config = "<root-collection dbroot='" + path + "/' name='" + name + "'/>";
        Database db = new Database();

        boolean success = true;
        try {
            System.out.println("Processing database " + path);
            System.out.println();
            System.out.println("DI\tCollection name");

            db.setConfig(new Configuration(DOMParser.toDocument(config)));

            if (log.isInfoEnabled()) {
                log.info("Rebuilding collections...");
            }
            success = processCollection(db, command);
        } finally {
            db.close();

            System.out.println();
            System.out.println("Legend:");
            System.out.println("    D Data file");
            System.out.println("    I Index files");
            System.out.println("    _ File was skipped");
            System.out.println("    * File was processed successfuly");
            System.out.println("    ! File processing failed");

            System.out.println();
            if (success) {
                System.out.println("Rebuilding database was successfull.");
            } else {
                System.out.println("Rebuilding database failed. Please check logs for more detail.");
            }

            System.exit(success ? 0 : 2);
        }

    }

    private static void usage() {
        System.out.println("Xindice " + Xindice.Version + " Database Rebuild Utility");
        System.out.println("Usage:");
        System.out.println("    xindice_rebuild copy    <db location>");
        System.out.println("    xindice_rebuild index   <db location>");
        System.out.println("    xindice_rebuild rebuild <db location>");
        System.out.println();
        System.out.println("DB Location should point to the directory containing Xindice database files.");
        System.out.println();
        System.out.println("Important: Shutdown and backup database before proceeding!");
        System.out.println();
    }

    private static boolean processCollection(Collection col, int command) {
        String name = col.getCanonicalName();
        boolean status;

        try {
            if (log.isInfoEnabled()) {
                log.info("Processing collection " + name);
            }

            char copy = NOT_RAN;
            char index = NOT_RAN;
            switch (command) {
                case CMD_COPY:
                    status = rebuildCollection(col);
                    copy = status ? SUCCESS : ERROR;
                    break;

                case CMD_INDEX:
                    status = rebuildIndex(col);
                    index = status ? SUCCESS : ERROR;
                    break;
                default:
                    status = rebuildCollection(col);
                    copy = status ? SUCCESS : ERROR;
                    if (status) {
                        status = rebuildIndex(col);
                        index = status ? SUCCESS : ERROR;
                    }
                    break;
            }

            System.out.println(String.valueOf(copy) + String.valueOf(index) + "\t" + name);

            String[] colNames = col.listCollections();
            for (int i = 0; i < colNames.length; i++) {
                boolean result = processCollection(col.getCollection(colNames[i]), command);
                status = status && result;
            }
        } catch (DBException e) {
            log.error("Got an exception when processing collection " + name, e);

            return false;
        }

        return status;
    }

    private static boolean rebuildCollection(Collection col) {
        String canonicalName = col.getCanonicalName();

        // close collection's filer
        try {
            if (col.getFiler() != null) {
                col.getFiler().close();
            }
        } catch (DBException e) {
            log.error("Could not close filer for collection " + canonicalName, e);
            return false;
        }

        // prepare
        Filer itsFiler = col.getFiler();
        FilerCopy oldFiler;
        FilerCopy newFiler;
        if (itsFiler == null) {
            if (log.isInfoEnabled()) {
                log.info("Collection " + col.getCanonicalName() + " has no filer. Skipping...");
            }

            return true;
        } if (itsFiler instanceof BTreeFiler) {
            oldFiler = new BTreeCopy();
            newFiler = new BTreeCopy();
        } else if (itsFiler instanceof HashFiler) {
            oldFiler = new HashCopy();
            newFiler = new HashCopy();
        } else {
            if (log.isInfoEnabled()) {
                log.info("Collection " + col.getCanonicalName() + " has unrecognized filer '" + itsFiler.getClass().getName() + "'. Skipping...");
            }

            return true;
        }

        String oldFileName;
        String newFileName;
        try {
            oldFiler.setLocation(col.getCollectionRoot(), col.getName());
            oldFiler.setConfig(col.getFiler().getConfig());
            oldFileName = oldFiler.getFilerFile().getAbsolutePath();
            if (!oldFiler.exists()) {
                log.error("Filer for " + oldFileName + " does not exists");
                return false;
            }

            newFiler.setLocation(col.getCollectionRoot(), col.getName() + ".rebuild");
            newFiler.setConfig(col.getFiler().getConfig());
            newFileName = newFiler.getFilerFile().getAbsolutePath();
            if (newFiler.exists()) {
                log.error("Filer for " + newFileName + " already exists");
                return false;
            }
        } catch (XindiceException e) {
            log.error("Got an exception when preparing to rebuild " + canonicalName, e);
            return false;
        }

        // copy
        if (!copy(oldFiler, newFiler, canonicalName)) {
            newFiler.deleteFile();
            return false;
        }

        oldFiler.deleteFile();
        if (!newFiler.getFilerFile().renameTo(oldFiler.getFilerFile())) {
            log.error("Could not rename successfully rebuilt file " + newFileName + " to " + oldFileName);
            return false;
        }

        try {
            col.getFiler().open();
        } catch (DBException e) {
            log.error("Could not open new file " + oldFileName, e);
            return false;
        }

        return true;
    }

    private static boolean copy(FilerCopy oldFiler, FilerCopy newFiler, String canonicalName) {
        try {
            newFiler.create();
            oldFiler.open();
            newFiler.open();
            oldFiler.copy(newFiler);
        } catch (Exception e) {
            log.error("Error copying collection " + canonicalName, e);
            return false;
        } finally {
            try {
                oldFiler.close();
            } catch (DBException e) {
                if (log.isWarnEnabled()) log.warn(e);
            }
            try {
                newFiler.close();
            } catch (DBException e) {
                if (log.isWarnEnabled()) log.warn(e);
            }
        }

        return true;
    }

    private static boolean rebuildIndex(Collection col) {
        if (col.getFiler() == null) {
            return true;
        }

        try {
            String[] list = col.listIndexers();
            for (int i = 0; i < list.length; i++) {
                Indexer idx = col.getIndexer(list[i]);
                Configuration idxConf = idx.getConfig();
                if (log.isInfoEnabled()) {
                    log.info("Rebuilding index " + list[i] + " for collection " + col.getCanonicalName());
                }
                col.dropIndexer(idx);
                col.createIndexer(idxConf);
            }
        } catch (DBException e) {
            log.error("Could not rebuild index for collection " + col.getCanonicalName(), e);
            return false;
        }

        return true;
    }

    private interface FilerCopy extends Filer {
        public Value getValue(long pointer) throws IOException;

        public void copy(Filer newFiler) throws IOException, DBException;

        public boolean deleteFile();

        public File getFilerFile();
    }

    private static class BTreeCopy extends BTreeFiler implements FilerCopy {
        public Value getValue(long pointer) throws IOException {
            return super.readValue(pointer);
        }

        public void copy(Filer newFiler) throws IOException, BTreeException {
            query(null, new CopyCallback(this, newFiler));
        }

        public boolean deleteFile() {
            return getFile().delete();
        }

        public File getFilerFile() {
            return getFile();
        }
    }

    private static class HashCopy extends HashFiler implements FilerCopy {
        public Value getValue(long pointer) throws IOException {
            return super.readValue(pointer);
        }

        public void copy(Filer newFiler) throws IOException, DBException {
            long hashSize = getFileHeader().getPageCount();

            for (long i = 0; i < hashSize; i++) {
                Page page = getPage(i);

                while (true) {
                    HashPageHeader ph = (HashPageHeader) page.getPageHeader();

                    if (ph.getStatus() == RECORD) {
                        Value value = readValue(page);
                        newFiler.writeRecord(page.getKey(), value);

                        long next = ph.getNextCollision();
                        if (next != NO_PAGE) {
                            page = getPage(ph.getNextCollision());
                        } else {
                            break;
                        }
                    } else {
                        break;
                    }
                }
            }
        }

        public boolean deleteFile() {
            return getFile().delete();
        }

        public File getFilerFile() {
            return getFile();
        }
    }

    private static class CopyCallback implements BTreeCallback {
        private BTreeCopy filer;
        private Filer newFiler;

        public CopyCallback(BTreeCopy filer, Filer newFiler) {
            this.filer = filer;
            this.newFiler = newFiler;
        }

        public boolean indexInfo(Value value, long pointer) {
            try {
                Value v = filer.getValue(pointer);
                newFiler.writeRecord(new Key(value), v);
            } catch (Exception e) {
                log.error(e);
            }

            return true;
        }
    }
}
TOP

Related Classes of org.apache.xindice.tools.DatabaseRebuild$CopyCallback

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.