Package com.persistit

Source Code of com.persistit.VolumeStorageT2

/**
* Copyright 2011-2012 Akiban Technologies, Inc.
*
* Licensed 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.
*/

package com.persistit;

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

import com.persistit.AlertMonitor.AlertLevel;
import com.persistit.AlertMonitor.Event;
import com.persistit.exception.InUseException;
import com.persistit.exception.InvalidPageAddressException;
import com.persistit.exception.PersistitException;
import com.persistit.exception.PersistitIOException;
import com.persistit.exception.PersistitInterruptedException;
import com.persistit.exception.ReadOnlyVolumeException;
import com.persistit.exception.VolumeClosedException;
import com.persistit.exception.VolumeFullException;

/**
* Manage all details of file I/O for a temporary <code>Volume</code> backing
* file. A temporary volume is intended to store data that does not need to be
* durable. All trees in a temporary volume are lost when Persistit shuts down,
* whether abruptly or gracefully. Therefore pages writes are not logged,
* buffers are not flushed on shutdown and there is no volume header page to
* hold metadata.
*
* @author peter
*/
class VolumeStorageT2 extends VolumeStorage {

    final static String TEMP_FILE_PREFIX = "persistit_tempvol_";
    private final File _tempDirectory;
    private long _maxPages;
    private volatile String _path;
    private volatile FileChannel _channel;

    private volatile long _nextAvailablePage;
    private volatile boolean _opened;
    private volatile boolean _closed;

    VolumeStorageT2(final Persistit persistit, final Volume volume, final File tempDirectory) {
        super(persistit, volume);
        _tempDirectory = tempDirectory;
    }

    /**
     * Returns the path name by which this volume was opened.
     *
     * @return The path name
     */
    @Override
    String getPath() {
        return _path;
    }

    /**
     * Indicate whether this <code>Volume</code> prohibits updates.
     *
     * @return <code>true</code> if this Volume prohibits updates.
     */
    @Override
    boolean isReadOnly() {
        return false;
    }

    /**
     * Indicate whether this is a temporary volume
     *
     * @return <code>true</code> if this volume is temporary
     */
    @Override
    boolean isTemp() {
        return true;
    }

    /**
     * @return the channel used to read and write pages of this volume.
     */
    @Override
    synchronized FileChannel getChannel() throws PersistitIOException {
        if (_channel == null) {
            try {
                final File file = File.createTempFile(TEMP_FILE_PREFIX, null, _tempDirectory);
                _path = file.getPath();
                _channel = new MediatedFileChannel(_path, "rw");
            } catch (final IOException ioe) {
                _persistit.getLogBase().tempVolumeCreateException.log(ioe, _path);
                throw new PersistitIOException(ioe);
            }
        }
        return _channel;
    }

    /**
     * Create a new <code>Volume</code> backing file according to the
     * {@link Volume}'s volume specification.
     *
     * @throws PersistitException
     */
    @Override
    void create() throws PersistitException {
        final long maxSize = _persistit.getConfiguration().getTmpVolMaxSize();
        _maxPages = maxSize / _volume.getStructure().getPageSize();
        _path = "";
        _channel = null;
        truncate();
        _opened = true;
    }

    /**
     * Open an existing <code>Volume</code> backing file.
     *
     * @throws PersistitException
     */
    @Override
    void open() throws PersistitException {
        throw new UnsupportedOperationException("Temporary volume can only be created.");
    }

    /**
     * @return <code>true</code> if a backing file exists on the specified path.
     * @throws PersistitException
     */
    @Override
    boolean exists() throws PersistitException {
        return false;
    }

    /**
     * Delete the backing file for this Volume if it exists.
     *
     * @return <code>true</code> if there was a file and it was successfully
     *         deleted
     * @throws PersistitException
     */
    @Override
    boolean delete() throws PersistitException {
        return false;
    }

    /**
     * Force all file system buffers to disk.
     *
     * @throws PersistitIOException
     */
    @Override
    void force() throws PersistitIOException {
        // No need to force a temporary Volume
    }

    /**
     * Close the file resources held by this <code>Volume</code>. After this
     * method is called no further file I/O is possible.
     *
     * @throws PersistitException
     */
    @Override
    void close() throws PersistitException {
        synchronized (this) {
            if (_closed) {
                return;
            }
            _closed = true;
        }

        PersistitException pe = null;

        try {
            closeChannel();
        } catch (final Exception e) {
            _persistit.getLogBase().exception.log(e);
            // has priority over Exception thrown by
            // releasing file lock.
            pe = new PersistitException(e);
        }
        try {
            if (_path != null) {
                final File file = new File(_path);
                file.delete();
            }
        } catch (final Exception e) {
            _persistit.getLogBase().exception.log(e);
            // has priority over Exception thrown by
            // releasing file lock.
            pe = new PersistitException(e);
        }

        if (pe != null) {
            throw pe;
        }
    }

    private void closeChannel() throws IOException {
        final FileChannel channel = _channel;
        _channel = null;
        if (channel != null) {
            channel.close();
        }
    }

    @Override
    void truncate() throws PersistitException {
        if (!claim(true, 0)) {
            throw new InUseException("Unable to acquire claim on " + this);
        }
        try {
            truncateInternal();
        } finally {
            release();
        }
    }

    protected void truncateInternal() throws PersistitException {
        final VolumeStatistics stat = _volume.getStatistics();
        final VolumeStructure struc = _volume.getStructure();

        final long now = System.currentTimeMillis();
        stat.setCreateTime(now);
        stat.setOpenTime(now);

        _nextAvailablePage = 1;

        struc.init(0, 0);
    }

    @Override
    boolean isOpened() {
        return _opened;
    }

    @Override
    boolean isClosed() {
        return _closed;
    }

    @Override
    long getExtentedPageCount() {
        return _nextAvailablePage;
    }

    @Override
    long getNextAvailablePage() {
        return _nextAvailablePage;
    }

    @Override
    void claimHeadBuffer() throws PersistitException {
    }

    @Override
    void releaseHeadBuffer() {
    }

    @Override
    void readPage(final Buffer buffer) throws PersistitIOException, InvalidPageAddressException, VolumeClosedException,
            InUseException, PersistitInterruptedException {
        // non-exclusive claim here intended to conflict with exclusive claim in
        // close and truncate
        if (!claim(false, 0)) {
            throw new InUseException("Unable to acquire claim on " + this);
        }
        try {
            final long page = buffer.getPageAddress();
            if (page < 1 || page >= _nextAvailablePage) {
                throw new InvalidPageAddressException("Page " + page + " out of bounds [0-" + _nextAvailablePage + "]");
            }
            try {
                final ByteBuffer bb = buffer.getByteBuffer();
                bb.position(0).limit(buffer.getBufferSize());
                int read = 0;
                while (read < buffer.getBufferSize()) {
                    final long position = (page - 1) * _volume.getStructure().getPageSize() + bb.position();
                    final int bytesRead = getChannel().read(bb, position);
                    if (bytesRead <= 0) {
                        throw new PersistitIOException("Unable to read bytes at position " + position + " in " + this);
                    }
                    read += bytesRead;
                }
                _persistit.getIOMeter().chargeReadPageFromVolume(this._volume, buffer.getPageAddress(),
                        buffer.getBufferSize(), buffer.getIndex());
                _volume.getStatistics().bumpReadCounter();
            } catch (final IOException ioe) {
                _persistit.getAlertMonitor().post(
                        new Event(AlertLevel.ERROR, _persistit.getLogBase().readException, ioe, _volume, page,
                                buffer.getIndex()), AlertMonitor.READ_PAGE_CATEGORY);
                throw new PersistitIOException(ioe);
            }
        } finally {
            release();
        }
    }

    @Override
    void writePage(final Buffer buffer) throws PersistitIOException, InvalidPageAddressException,
            ReadOnlyVolumeException, VolumeClosedException, InUseException, PersistitInterruptedException {
        final int pageSize = _volume.getStructure().getPageSize();
        final ByteBuffer bb = buffer.getByteBuffer();
        bb.position(0).limit(pageSize);
        writePage(bb, buffer.getPageAddress());
    }

    @Override
    void writePage(final ByteBuffer bb, final long page) throws PersistitIOException, InvalidPageAddressException,
            ReadOnlyVolumeException, VolumeClosedException, InUseException, PersistitInterruptedException {
        // non-exclusive claim here intended to conflict with exclusive claim in
        // close and truncate
        final int pageSize = _volume.getStructure().getPageSize();
        if (!claim(false, 0)) {
            throw new InUseException("Unable to acquire claim on " + this);
        }
        try {
            if (page < 0 || page >= _nextAvailablePage) {
                throw new InvalidPageAddressException("Page " + page + " out of bounds [0-" + _nextAvailablePage + "]");
            }

            try {
                getChannel().write(bb, (page - 1) * pageSize);

            } catch (final IOException ioe) {
                _persistit.getAlertMonitor().post(
                        new Event(AlertLevel.ERROR, _persistit.getLogBase().writeException, ioe, _volume, page),
                        AlertMonitor.WRITE_PAGE_CATEGORY);
                throw new PersistitIOException(ioe);
            }
        } finally {
            release();
        }
    }

    @Override
    synchronized long allocNewPage() throws PersistitException {
        if (_nextAvailablePage >= _maxPages) {
            throw new VolumeFullException(_volume.getName());
        }
        final long page = _nextAvailablePage++;
        _volume.getStatistics().setNextAvailablePage(page);
        return page;
    }

    @Override
    void flush() throws PersistitException {

    }

    @Override
    void flushMetaData() throws PersistitException {

    }

    @Override
    void extend(final long pageAddr) throws PersistitException {

    }

    @Override
    boolean updateMetaData(final byte[] bytes) {
        // Temporary volume has no head buffer
        return false;
    }

    @Override
    public String toString() {
        return _volume.toString();
    }
}
TOP

Related Classes of com.persistit.VolumeStorageT2

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.