Package org.xtreemfs.babudb.conversion

Source Code of org.xtreemfs.babudb.conversion.AutoConverter$IndexFileIterator

/*
* Copyright (c) 2009, Jan Stender, Bjoern Kolbeck, Mikael Hoegqvist,
*                     Felix Hupfeld, Felix Langner, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/

package org.xtreemfs.babudb.conversion;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.Iterator;
import java.util.Map.Entry;

import org.xtreemfs.babudb.BabuDBImpl;
import org.xtreemfs.babudb.api.database.Database;
import org.xtreemfs.babudb.api.exception.BabuDBException;
import org.xtreemfs.babudb.api.exception.BabuDBException.ErrorCode;
import org.xtreemfs.babudb.config.BabuDBConfig;
import org.xtreemfs.foundation.logging.Logging;
import org.xtreemfs.foundation.logging.Logging.Category;
import org.xtreemfs.foundation.util.FSUtils;
import org.xtreemfs.foundation.util.OutputUtils;

import static org.xtreemfs.babudb.BabuDBFactory.*;

public class AutoConverter {
   
    static class IndexFileIterator implements Iterator<Entry<byte[], byte[]>> {
       
        private InputStream in;
       
        private ByteBuffer  lenBytes;
       
        public IndexFileIterator(File file) {
           
            try {
                in = new FileInputStream(file);
                lenBytes = ByteBuffer.wrap(new byte[4]);
               
            } catch (IOException exc) {
                Logging.logMessage(Logging.LEVEL_ERROR, Category.storage, this,
                    "an error occurred while trying to convert the database: "
                        + OutputUtils.stackTraceToString(exc));
            }
           
        }
       
        @Override
        public boolean hasNext() {
           
            try {
                return in.available() > 0;
               
            } catch (IOException exc) {
               
                Logging.logMessage(Logging.LEVEL_ERROR, Category.storage, this,
                    "an error occurred while trying to convert the database: "
                        + OutputUtils.stackTraceToString(exc));
               
                return false;
            }
        }
       
        @Override
        public Entry<byte[], byte[]> next() {
           
            try {
               
                // read the key
               
                int tmp = in.read(lenBytes.array());
                if (tmp != 4) {
                    Logging
                            .logMessage(
                                Logging.LEVEL_ERROR,
                                Category.storage,
                                this,
                                "an error occurred while trying to convert the database; database dump corrupted (only %d bytes read, available: %d)",
                                tmp, in.available());
                    return null;
                }
               
                int len = lenBytes.getInt();
                lenBytes.position(0);
               
                final byte[] key = new byte[len];
                int num = in.read(key);
               
                if (num != len) {
                    Logging
                            .logMessage(
                                Logging.LEVEL_ERROR,
                                Category.storage,
                                this,
                                "an error occurred while trying to convert the database; expected key length: %d, actual key length: %d",
                                len, num);
                    return null;
                }
               
                // read the value
                tmp = in.read(lenBytes.array());
                if (tmp != 4) {
                    Logging
                            .logMessage(
                                Logging.LEVEL_ERROR,
                                Category.storage,
                                this,
                                "an error occurred while trying to convert the database; database dump corrupted (only %d bytes read, available: %d)",
                                tmp, in.available());
                    return null;
                }
               
                len = lenBytes.getInt();
                lenBytes.position(0);
               
                final byte[] val = new byte[len];
                num = in.read(val);
               
                if (num != len) {
                   
                    System.out.println("remaining: " + in.available());
                   
                    Logging
                            .logMessage(
                                Logging.LEVEL_ERROR,
                                Category.storage,
                                this,
                                "an error occurred while trying to convert the database; expected value length: %d, actual value length: %d",
                                len, num);
                    return null;
                }
               
                return new Entry<byte[], byte[]>() {
                   
                    @Override
                    public byte[] setValue(byte[] value) {
                        throw new UnsupportedOperationException();
                    }
                   
                    @Override
                    public byte[] getValue() {
                        return val;
                    }
                   
                    @Override
                    public byte[] getKey() {
                        return key;
                    }
                };
               
            } catch (IOException exc) {
               
                Logging.logMessage(Logging.LEVEL_ERROR, Category.storage, this,
                    "an error occurred while trying to convert the database: "
                        + OutputUtils.stackTraceToString(exc));
               
                return null;
            }
           
        }
       
        @Override
        public void remove() {
            throw new UnsupportedOperationException();
        }
       
        public void destroy() throws IOException {
            in.close();
        }
       
    }
   
    public static void initiateConversion(int dbVer, final BabuDBConfig cfg) throws BabuDBException {
       
        if (!DBWriter.checkVersionSupport(dbVer))
            throw new BabuDBException(ErrorCode.IO_ERROR, "on-disk format (version " + dbVer
                + ") is incompatible with this BabuDB release (version " + BABUDB_DB_FORMAT_VERSION
                + "); no automatic conversion possible");
       
        else
            Logging
                    .logMessage(Logging.LEVEL_INFO, Category.storage, (Object) null,
                        "starting database conversion");
       
        final File dbDir = new File(cfg.getBaseDir());
        final File dbLogDir = new File(cfg.getDbLogDir());
        final File targetDir = new File(dbDir, ".conversion");
        final File cfgFile = new File(dbDir, cfg.getDbCfgFile());
        final File backupDir = new File(cfg.getBaseDir(), ".backup-" + dbVer);
        final File backupDBDir = new File(backupDir, "database");
        final File backupLogDir = new File(backupDir, "db-log");
       
        if (targetDir.exists())
            FSUtils.delTree(targetDir);
       
        try {
           
            // write version independent database representation
            DBWriter.writeDB(cfg, dbVer, targetDir.getAbsolutePath());
           
            // move everything except for the temporary dump and the config file
            // to a backup directory
            File[] dbFilesToMove = dbDir.listFiles(new FileFilter() {
                public boolean accept(File pathname) {
                    return !(pathname.equals(targetDir) || pathname.equals(cfgFile) || pathname
                            .equals(backupDir) || pathname.equals(dbLogDir));
                }
            });
           
            File[] logFilesToMove = dbLogDir.equals(dbDir) ? new File[0] : dbLogDir.listFiles();
           
            backupDBDir.mkdirs();
            backupLogDir.mkdirs();
            if (backupDBDir.exists() && backupLogDir.exists()) {
                // move all files to a backup directory
                for (File f : dbFilesToMove)
                    if (!f.renameTo(new File(backupDBDir, f.getName())))
                        throw new BabuDBException(ErrorCode.IO_ERROR,
                            "an error occurred while trying to convert the database: '" + f.getAbsolutePath()
                                + "' could not be moved");
               
                for (File f : logFilesToMove)
                    if (!f.renameTo(new File(backupLogDir, f.getName())))
                        throw new BabuDBException(ErrorCode.IO_ERROR,
                            "an error occurred while trying to convert the database: '" + f.getAbsolutePath()
                                + "' could not be moved");
               
            } else
                throw new BabuDBException(ErrorCode.IO_ERROR,
                    "an error occurred while trying to convert the database: backup directory could not be created");
           
            // copy the config file to the backup directory
            FSUtils.copyTree(cfgFile, new File(backupDir, cfgFile.getName()));
           
        } catch (IOException exc) {
            throw new BabuDBException(ErrorCode.IO_ERROR,
                "an error occurred while trying to convert the database", exc);
        }
       
    }
   
    public static void completeConversion(BabuDBImpl babuDB) throws BabuDBException {
       
        final File targetDir = new File(babuDB.getConfig().getBaseDir(), "/.conversion");
       
        // get all databases to restore
        File[] dbsToRestore = targetDir.listFiles();
       
        try {
           
            // for each database directory ...
            for (File dbDir : dbsToRestore) {
               
                // get all nested index files
                File[] indexFiles = dbDir.listFiles(new FileFilter() {
                    public boolean accept(File pathname) {
                        return !pathname.isDirectory();
                    }
                });
               
                Database db = babuDB.getDatabaseManager().createDatabase(dbDir.getName(), indexFiles.length);
                for (File indexFile : indexFiles) {
                   
                    int indexId = Integer.parseInt(indexFile.getName());
                   
                    IndexFileIterator it = new IndexFileIterator(indexFile);
                    while (it.hasNext()) {
                        Entry<byte[], byte[]> next = it.next();
                        if (next == null) {
                            throw new BabuDBException(ErrorCode.INTERNAL_ERROR,
                                "database conversion failed, dump corrupted");
                        }
                       
                        db.singleInsert(indexId, next.getKey(), next.getValue(), null).get();
                    }
                   
                    it.destroy();
                }
               
                // retrieve all nested snapshot directories
                File snapRootDir = new File(dbDir, DBWriter.SNAPSHOT_DIR_NAME);
                File[] snapDirs = snapRootDir.listFiles();
                if (snapDirs == null)
                    continue;
               
                // for each snapshot directory ...
                for (File snapDir : snapDirs) {
                   
                    // TODO: restore snapshots
                   
                }
            }
           
        } catch (IOException exc) {
            throw new BabuDBException(ErrorCode.IO_ERROR,
                "an error has occurred while trying to convert the database", exc);
        }
       
        // delete the version-independent dump
        FSUtils.delTree(targetDir);
       
        Logging.logMessage(Logging.LEVEL_INFO, Category.storage, (Object) null, "conversion completed");
    }
   
}
TOP

Related Classes of org.xtreemfs.babudb.conversion.AutoConverter$IndexFileIterator

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.