Package com.foundationdb.qp.storeadapter

Source Code of com.foundationdb.qp.storeadapter.TempVolume$TempVolumeState

/**
* Copyright (C) 2009-2013 FoundationDB, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package com.foundationdb.qp.storeadapter;

import com.foundationdb.server.service.session.Session;
import com.foundationdb.server.store.PersistitStore;
import com.persistit.Exchange;
import com.persistit.Persistit;
import com.persistit.Volume;
import com.persistit.exception.PersistitException;
import com.persistit.exception.PersistitIOException;
import com.persistit.exception.RollbackException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

public class TempVolume
{
    public static Exchange takeExchange(PersistitStore store, Session session, String treeName)
    {
        boolean success = false;
        try {
            Persistit persistit = store.getDb();
            TempVolumeState tempVolumeState = session.get(TEMP_VOLUME_STATE);
            if (tempVolumeState == null) {
                // Persistit creates a temp volume per "Persistit session", and these are currently one-to-one with threads.
                // Conveniently, server sessions and threads are also one-to-one. If either of these relationships ever
                // change, then the use of session resources and temp volumes will need to be revisited. But for now,
                // persistit.createTemporaryVolume creates a temp volume that is private to the persistit session and
                // therefore to the server session.
                Volume volume = persistit.createTemporaryVolume();
                tempVolumeState = new TempVolumeState(volume);
                session.put(TEMP_VOLUME_STATE, tempVolumeState);
            }
            tempVolumeState.acquire();
            if(injectIOException) {
                throw new PersistitIOException(new IOException());
            }
            Exchange ex = new Exchange(persistit, tempVolumeState.volume(), treeName, true);
            success = true;
            return ex;
        } catch (PersistitException | RollbackException e) {
            if (!PersistitAdapter.isFromInterruption(e))
                LOG.debug("Caught exception while getting exchange for sort", e);
            throw PersistitAdapter.wrapPersistitException(session, e);
        } finally {
            if (!success)
                releaseAndCloseIfUnshared(session);
        }
    }

    public static void returnExchange(Session session, Exchange exchange)
    {
        if (exchange != null) {
            releaseAndCloseIfUnshared(session);
            // Don't return the exchange to the adapter. TreeServiceImpl caches it for the tree, and we're done
            // with the tree. Calling adapter.returnExchange would cause a leak of exchanges.
        }
    }

    private static void releaseAndCloseIfUnshared(Session session) {
        TempVolumeState tempVolumeState = session.get(TEMP_VOLUME_STATE);
        tempVolumeState.release();
        if (!tempVolumeState.isShared())
        {
            session.remove(TEMP_VOLUME_STATE);
            try {
                // Returns disk space used by the volume
                tempVolumeState.volume().close();
            } catch(PersistitException | RollbackException e) {
                throw PersistitAdapter.wrapPersistitException(session, e);
            }
        }
    }

    // Public for tests

    public static boolean hasTempState(Session session)
    {
        return session.get(TEMP_VOLUME_STATE) != null;
    }

    public static void setInjectIOException(boolean injectIOException)
    {
        TempVolume.injectIOException = injectIOException;
    }

    private static final Logger LOG = LoggerFactory.getLogger(TempVolume.class);
    private static final Session.Key<TempVolumeState> TEMP_VOLUME_STATE = Session.Key.named("TEMP_VOLUME_STATE");
    private static volatile boolean injectIOException = false;

    private static class TempVolumeState
    {
        public TempVolumeState(Volume volume)
        {
            this.volume = volume;
            refCount = 0;
        }

        public Volume volume()
        {
            return volume;
        }

        public void acquire()
        {
            ++refCount;
        }

        public boolean isShared()
        {
            return refCount > 0;
        }

        public void release()
        {
            --refCount;
            assert refCount >= 0;
        }

        private final Volume volume;
        private int refCount;
    }
}
TOP

Related Classes of com.foundationdb.qp.storeadapter.TempVolume$TempVolumeState

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.