Package com.persistit

Source Code of com.persistit.CleanupManager$CleanupIndexHole

/**
* Copyright © 2011-2012 Akiban Technologies, Inc.  All rights reserved.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v1.0 which
* accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* This program may also be available under different license terms.
* For more information, see www.akiban.com or contact licensing@akiban.com.
*
* Contributors:
* Akiban Technologies, Inc.
*/

package com.persistit;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;

import com.persistit.AlertMonitor.AlertLevel;
import com.persistit.AlertMonitor.Event;
import com.persistit.exception.PersistitException;
import com.persistit.mxbeans.CleanupManagerMXBean;

class CleanupManager extends IOTaskRunnable implements CleanupManagerMXBean {

    interface CleanupAction extends Comparable<CleanupAction> {

        void performAction(Persistit persistit) throws PersistitException;
    }

    final static long DEFAULT_CLEANUP_INTERVAL_MS = 1000;

    final static int DEFAULT_QUEUE_SIZE = 50000;

    private final static int WORKLIST_LENGTH = 500;

    private final static long MINIMUM_MAINTENANCE_INTERVAL_NS = 1000000000L;

    private final static long MINIMUM_PRUNE_OBSOLETE_TRANSACTIONS_INTERVAL_NS = 50000000000L;

    private final static long DEFAULT_MINIMUM_PRUNING_DELAY_NS = 1000;

    private final Queue<CleanupAction> _cleanupActionQueue = new ArrayBlockingQueue<CleanupAction>(DEFAULT_QUEUE_SIZE);

    private final AtomicBoolean _closed = new AtomicBoolean();

    private final AtomicLong _accepted = new AtomicLong();

    private final AtomicLong _refused = new AtomicLong();

    private final AtomicLong _performed = new AtomicLong();

    private final AtomicLong _errors = new AtomicLong();

    private final AtomicLong _minimumPruningDelay = new AtomicLong(DEFAULT_MINIMUM_PRUNING_DELAY_NS);

    private long _lastMaintenance;

    private long _lastPruneObsoleteTransactions;

    CleanupManager(final Persistit persistit) {
        super(persistit);
    }

    public void start() {
        _closed.set(false);
        final long now = System.nanoTime();
        _lastMaintenance = now;
        _lastPruneObsoleteTransactions = now;
        start("CLEANUP_MANAGER", DEFAULT_CLEANUP_INTERVAL_MS);
    }

    public void close(final boolean flush) throws PersistitException {
        _closed.set(true);
    }

    @Override
    protected void runTask() throws Exception {
        poll();
    }

    @Override
    protected boolean shouldStop() {
        return _closed.get();
    }

    synchronized boolean offer(final CleanupAction action) {
        final boolean accepted = _cleanupActionQueue.offer(action);
        if (accepted) {
            _accepted.incrementAndGet();
        } else {
            _refused.incrementAndGet();
            kick();
        }
        return accepted;
    }

    @Override
    public long getAcceptedCount() {
        return _accepted.get();
    }

    @Override
    public long getRefusedCount() {
        return _refused.get();
    }

    @Override
    public long getPerformedCount() {
        return _performed.get();
    }

    @Override
    public long getErrorCount() {
        return _errors.get();
    }

    @Override
    public long getEnqueuedCount() {
        return _cleanupActionQueue.size();
    }

    @Override
    public long getMinimumPruningDelay() {
        return _minimumPruningDelay.get();
    }

    @Override
    public void setMinimumPruningDelay(final long delay) {
        _minimumPruningDelay.set(delay);
    }

    @Override
    public long pollInterval() {
        if (_cleanupActionQueue.size() < DEFAULT_QUEUE_SIZE / 2) {
            return super.getPollInterval();
        } else {
            return 0;
        }
    }

    @Override
    public void poll() throws Exception {

        final long now = System.nanoTime();
        if (now - _lastMaintenance > MINIMUM_MAINTENANCE_INTERVAL_NS) {
            _persistit.getIOMeter().poll();
            _persistit.cleanup();
            _lastMaintenance = now;
        }

        if (now - _lastPruneObsoleteTransactions > MINIMUM_PRUNE_OBSOLETE_TRANSACTIONS_INTERVAL_NS) {
            _persistit.getJournalManager().pruneObsoleteTransactions();
            _lastPruneObsoleteTransactions = now;
        }

        final List<CleanupAction> workList = new ArrayList<CleanupAction>(WORKLIST_LENGTH);
        synchronized (this) {
            while (workList.size() < WORKLIST_LENGTH) {
                final CleanupAction action;
                action = _cleanupActionQueue.poll();
                if (action == null) {
                    break;
                }
                workList.add(action);
            }
        }
        Collections.sort(workList);

        for (final CleanupAction action : workList) {
            try {
                action.performAction(_persistit);
                _performed.incrementAndGet();
            } catch (final PersistitException e) {
                lastException(e);
                _persistit.getAlertMonitor().post(
                        new Event(AlertLevel.ERROR, _persistit.getLogBase().cleanupException, e, action),
                        AlertMonitor.CLEANUP_CATEGORY);
                _errors.incrementAndGet();
            }
        }
    }

    @Override
    public synchronized void clear() {
        _cleanupActionQueue.clear();
    }

    @Override
    public synchronized String toString() {
        final StringBuilder sb = new StringBuilder("[");
        for (final CleanupAction a : _cleanupActionQueue) {
            if (sb.length() > 1) {
                sb.append(",\n ");
            }
            sb.append(a);
        }
        sb.append("]");
        return sb.toString();
    }

    abstract static class CleanupTreePage implements CleanupAction {

        private final static ThreadLocal<WeakReference<Exchange>> _exchangeThreadLocal = new ThreadLocal<WeakReference<Exchange>>();

        final int _treeHandle;
        final long _page;

        protected CleanupTreePage(final int treeHandle, final long page) {
            _treeHandle = treeHandle;
            _page = page;
        }

        @Override
        public boolean equals(final Object other) {
            if (other instanceof CleanupTreePage) {
                final CleanupTreePage a = (CleanupTreePage) other;
                return a._page == _page && a._treeHandle == _treeHandle && getClass().equals(a.getClass());
            } else {
                return false;
            }

        }

        @Override
        public int compareTo(final CleanupAction other) {
            if (other instanceof CleanupTreePage) {
                final CleanupTreePage a = (CleanupTreePage) other;
                final int d = _treeHandle - a._treeHandle;
                if (d != 0) {
                    return d;
                }
                return _page > a._page ? 1 : _page < a._page ? -1 : 0;
            } else {
                return -1;
            }
        }

        @Override
        public String toString() {
            return String.format("%s on page %,d tree handle [%,d]", getClass().getSimpleName(), _page, _treeHandle);
        }

        protected Exchange getExchange(final Persistit persistit) throws PersistitException {
            final Tree tree = persistit.getJournalManager().treeForHandle(_treeHandle);
            if (tree == null) {
                return null;
            }
            final WeakReference<Exchange> ref = _exchangeThreadLocal.get();
            if (ref != null) {
                final Exchange exchange = ref.get();
                if (exchange != null) {
                    exchange.init(tree);
                    return exchange;
                }
            }
            final Exchange exchange = new Exchange(tree);
            _exchangeThreadLocal.set(new WeakReference<Exchange>(exchange));
            return exchange;
        }
    }

    static class CleanupAntiValue extends CleanupTreePage {

        CleanupAntiValue(final int treeHandle, final long page) {
            super(treeHandle, page);
        }

        @Override
        public void performAction(final Persistit persistit) throws PersistitException {
            final Exchange exchange = getExchange(persistit);
            if (exchange != null) {
                exchange.pruneLeftEdgeValue(_page);
            }
        }
    }

    static class CleanupPruneAction extends CleanupTreePage {

        CleanupPruneAction(final int treeHandle, final long page) {
            super(treeHandle, page);
        }

        @Override
        public void performAction(final Persistit persistit) throws PersistitException {
            final Exchange exchange = getExchange(persistit);
            if (exchange != null) {
                exchange.prune(_page);
            }
        }
    }

    static class CleanupIndexHole extends CleanupTreePage {
        int _level;

        CleanupIndexHole(final int treeHandle, final long page, final int level) {
            super(treeHandle, page);
            _level = level;
        }

        @Override
        public void performAction(final Persistit persistit) throws PersistitException {
            final Exchange exchange = getExchange(persistit);
            if (exchange != null) {
                exchange.fixIndexHole(_page, _level);
            }
        }
    }

}
TOP

Related Classes of com.persistit.CleanupManager$CleanupIndexHole

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.