Package org.jnode.apps.vmware.disk.handler.sparse

Source Code of org.jnode.apps.vmware.disk.handler.sparse.SparseDiskFactory

/*
* $Id$
*
* Copyright (C) 2003-2014 JNode.org
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jnode.apps.vmware.disk.handler.sparse;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.log4j.Logger;
import org.jnode.apps.vmware.disk.ExtentDeclaration;
import org.jnode.apps.vmware.disk.IOUtils;
import org.jnode.apps.vmware.disk.descriptor.AdapterType;
import org.jnode.apps.vmware.disk.descriptor.CreateType;
import org.jnode.apps.vmware.disk.descriptor.Descriptor;
import org.jnode.apps.vmware.disk.descriptor.DiskDatabase;
import org.jnode.apps.vmware.disk.descriptor.Header;
import org.jnode.apps.vmware.disk.extent.Access;
import org.jnode.apps.vmware.disk.extent.Extent;
import org.jnode.apps.vmware.disk.extent.ExtentType;
import org.jnode.apps.vmware.disk.tools.DiskFactory;
import org.jnode.driver.bus.ide.IDEConstants;

/**
* Wrote from the 'Virtual Disk Format 1.0' specifications (from VMWare).
*
* @author Fabien DUMINY (fduminy at jnode dot org)
*
*/
public class SparseDiskFactory extends DiskFactory {
    private static final Logger LOG = Logger.getLogger(SparseDiskFactory.class);

    @Override
    protected File createDiskImpl(File directory, String name, long size) throws IOException {
        File mainFile = createMainFile(directory, name, size);
        return mainFile;
    }

    protected File createMainFile(File directory, String name, long size) throws IOException {
        File mainFile = new File(directory, createDiskFileName(name, 0));
        RandomAccessFile raf = new RandomAccessFile(mainFile, "rw");
        @SuppressWarnings("unused")
        FileChannel channel = raf.getChannel();

        @SuppressWarnings("unused")
        Descriptor descriptor = buildDescriptor(mainFile, size);
        @SuppressWarnings("unused")
        SparseExtentHeader header = new SparseExtentHeader();

        return mainFile;
    }

    protected Descriptor buildDescriptor(File mainFile, long size) {
        LOG.info("buildDescriptor: wanted size=" + size);
        long sizeInSectors = size / IDEConstants.SECTOR_SIZE;
        if ((size % IDEConstants.SECTOR_SIZE) != 0) {
            LOG.debug("buildDescriptor: adding 1 more sector to fit size");
            sizeInSectors++;
        }

        // build DiskDatabase
        DiskDatabase ddb = new DiskDatabase();
        ddb.setAdapterType(AdapterType.ide);
        ddb.setSectors(64);
        ddb.setHeads(32);

        int cylinderCapacity = ddb.getSectors() * ddb.getHeads();
        int cylinders = (int) (sizeInSectors / cylinderCapacity);
        if ((sizeInSectors % cylinderCapacity) != 0) {
            LOG.debug("buildDescriptor: adding 1 more cylinder to fit size");
            cylinders++;
        }
        ddb.setCylinders(cylinders);

        int nbSectors = ddb.getCylinders() * ddb.getHeads() * ddb.getSectors();
        LOG.info("buildDescriptor: allocated size=" + (nbSectors * IDEConstants.SECTOR_SIZE));

        // build Header
        Header header = new Header();
        header.setVersion("1");
        header.setContentID(0);
        header.setParentContentID(Header.CID_NOPARENT);
        header.setCreateType(CreateType.monolithicSparse);
        header.setParentFileNameHint("");

        // build extents
        List<Extent> extents = new ArrayList<Extent>();
        SparseExtent mainExtent = createMainExtent(mainFile, nbSectors);
        extents.add(mainExtent);

        Descriptor descriptor = new Descriptor(mainFile, header, extents, ddb);
        mainExtent.setDescriptor(descriptor);
        return descriptor;
    }

    private SparseExtent createMainExtent(File mainFile, int nbSectors) {
        long offset = 0L; // TODO should be changed ?
        ExtentDeclaration extentDecl =
                IOUtils.createExtentDeclaration(mainFile, mainFile.getName(), Access.RW, nbSectors,
                        ExtentType.SPARSE, offset);

        // create extent header
        SparseExtentHeader sparseHeader = new SparseExtentHeader();
        sparseHeader.setValidNewLineDetectionTest(true);
        sparseHeader.setRedundantGrainTableWillBeUsed(false);

        sparseHeader.setGrainSize(16);
        sparseHeader.setDescriptorOffset(0); // TODO set value
        sparseHeader.setDescriptorSize(0); // TODO set value
        sparseHeader.setRgdOffset(0); // TODO set value

        sparseHeader.setNumGTEsPerGT(512);
        sparseHeader.setGdOffset(0); // TODO set value
        sparseHeader.setOverHead(0); // TODO set value
        sparseHeader.setUncleanShutdown(false);

        int nbGrains = (int) (nbSectors / sparseHeader.getGrainSize());
        int modulo = (int) (nbSectors % sparseHeader.getGrainSize());
        if (modulo != 0) {
            nbGrains++;
            nbSectors += (sparseHeader.getGrainSize() - modulo);
        }
        sparseHeader.setCapacity(nbSectors);

        IOUtils.computeGrainTableCoverage(sparseHeader);

        // create allocation table
        int nbEntries = (int) (nbSectors / sparseHeader.getGrainTableCoverage());
        int[] entries = new int[nbEntries];
        Arrays.fill(entries, 0);
        GrainDirectory gd = new GrainDirectory(entries);
        GrainTable[] gTables = null;
        AllocationTable allocationTable = new AllocationTable(gd, gTables);

        SparseExtent mainExtent =
                new SparseExtent(null, extentDecl, sparseHeader, allocationTable, allocationTable);
        return mainExtent;
    }

    protected String createDiskFileName(String name, int index) {
        return name + "-" + index + ".vmdk";
    }
}
TOP

Related Classes of org.jnode.apps.vmware.disk.handler.sparse.SparseDiskFactory

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.