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

org.xadisk.filesystem.virtual.NativeXAFileOutputStream Maven / Gradle / Ivy

There is a newer version: 1.2.2
Show newest version
/*
Copyright © 2010-2011, Nitin Verma (project owner for XADisk https://xadisk.dev.java.net/). All rights reserved.

This source code is being made available to the public under the terms specified in the license
"Eclipse Public License 1.0" located at http://www.opensource.org/licenses/eclipse-1.0.php.
*/


package org.xadisk.filesystem.virtual;

import org.xadisk.filesystem.workers.GatheringDiskWriter;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.concurrent.locks.ReentrantLock;
import org.xadisk.bridge.proxies.interfaces.XAFileOutputStream;
import org.xadisk.filesystem.Buffer;
import org.xadisk.filesystem.NativeSession;
import org.xadisk.filesystem.NativeXAFileSystem;
import org.xadisk.filesystem.TransactionLogEntry;
import org.xadisk.filesystem.TransactionInformation;
import org.xadisk.filesystem.exceptions.ClosedStreamException;
import org.xadisk.filesystem.exceptions.FileUnderUseException;
import org.xadisk.filesystem.exceptions.NoTransactionAssociatedException;

public class NativeXAFileOutputStream implements XAFileOutputStream {

    private final String destination;
    private ByteBuffer byteBuffer;
    private Buffer buffer;
    private final NativeXAFileSystem xaFileSystem;
    private final TransactionInformation xid;
    private final GatheringDiskWriter theGatheringDiskWriter;
    private long filePosition;
    private boolean closed = false;
    private final VirtualViewFile vvf;
    private final boolean heavyWrite;
    private final NativeSession owningSession;
    private final ReentrantLock asynchronousRollbackLock;

    public NativeXAFileOutputStream(VirtualViewFile vvf, TransactionInformation xid, boolean heavyWrite,
            NativeSession owningSession, NativeXAFileSystem xaFileSystem) {
        this.xaFileSystem = xaFileSystem;
        this.destination = vvf.getFileName().getAbsolutePath();
        this.xid = xid;
        this.theGatheringDiskWriter = this.xaFileSystem.getTheGatheringDiskWriter();
        this.vvf = vvf;
        this.filePosition = vvf.getLength();
        vvf.setBeingWritten(true);
        if (heavyWrite) {
            if (!vvf.isUsingHeavyWriteOptimization()) {
                try {
                    vvf.setUpForHeavyWriteOptimization();
                } catch (IOException ioe) {
                    xaFileSystem.notifySystemFailure(ioe);
                }
            }
        }
        this.heavyWrite = vvf.isUsingHeavyWriteOptimization();
        allocateByteBuffer();
        setUpNewBuffer();
        this.owningSession = owningSession;
        this.asynchronousRollbackLock = owningSession.getAsynchronousRollbackLock();
    }

    public void write(byte[] b) throws ClosedStreamException, NoTransactionAssociatedException {
        write(b, 0, b.length);
    }

    public void write(int b) throws ClosedStreamException, NoTransactionAssociatedException {
        byte b1[] = {(byte) b};
        write(b1, 0, 1);
    }

    public void write(byte[] b, int off, int len) throws ClosedStreamException, NoTransactionAssociatedException {
        try {
            asynchronousRollbackLock.lock();
            checkIfCanContinue();
            int len1 = len;
            if (byteBuffer.remaining() < len) {
                len1 = byteBuffer.remaining();
            }
            byteBuffer.put(b, off, len1);
            filePosition += len1;
            if (byteBuffer.remaining() == 0) {
                submitBuffer();
                setUpNewBuffer();
            }
            if (len1 < len) {
                write(b, off + len1, len - len1);
            }
        } finally {
            asynchronousRollbackLock.unlock();
        }
    }

    public void flush() throws ClosedStreamException, NoTransactionAssociatedException {
        try {
            asynchronousRollbackLock.lock();
            checkIfCanContinue();
            submitBuffer();
            setUpNewBuffer();
        } finally {
            asynchronousRollbackLock.unlock();
        }
    }

    public void close() throws NoTransactionAssociatedException {
        if (closed) {
            return;
        }
        try {
            asynchronousRollbackLock.lock();
            owningSession.checkIfCanContinue();
            submitBuffer();
            vvf.setBeingWritten(false);
            closed = true;
        } finally {
            asynchronousRollbackLock.unlock();
        }
    }

    private void allocateByteBuffer() {
        buffer = xaFileSystem.getBufferPool().checkOut();
        if (buffer != null) {
            this.byteBuffer = buffer.getBuffer();
        } else {
            this.buffer = new Buffer(xaFileSystem.getConfiguredBufferSize(), false, xaFileSystem);
            this.byteBuffer = buffer.getBuffer();
        }
        this.byteBuffer.clear();
    }

    private void setUpNewBuffer() {
        if (heavyWrite) {
            this.byteBuffer.clear();
        } else {
            allocateByteBuffer();
            byte temp[] = TransactionLogEntry.getLogEntry(xid, destination, filePosition, 21, TransactionLogEntry.FILE_APPEND);
            byteBuffer.put(temp);
            buffer.setFileContentPosition(filePosition);
            buffer.setHeaderLength(temp.length);
        }
    }

    private void submitBuffer() {
        try {
            if (heavyWrite) {
                byteBuffer.flip();
                vvf.appendContentBuffer(buffer);
            } else {
                int contentLength = byteBuffer.position() - buffer.getHeaderLength();
                TransactionLogEntry.updateContentLength(byteBuffer, contentLength);
                buffer.setFileContentLength(contentLength);
                byteBuffer.flip();
                vvf.appendContentBuffer(buffer);
                theGatheringDiskWriter.submitBuffer(buffer, xid);
            }
        } catch (IOException ioe) {
            xaFileSystem.notifySystemFailure(ioe);
        }
    }

    public File getDestinationFile() {
        return new File(destination);
    }

    private void checkIfCanContinue() throws NoTransactionAssociatedException, ClosedStreamException {
        if (closed) {
            throw new ClosedStreamException();
        }
        owningSession.checkIfCanContinue();
    }

    public boolean isClosed() {
        return closed;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy