Package org.apache.qpid.server.store

Source Code of org.apache.qpid.server.store.SlowMessageStore$SlowTransaction

/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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 org.apache.qpid.server.store;

import java.util.Collections;
import java.util.Map;
import java.util.UUID;
import org.apache.log4j.Logger;

import org.apache.qpid.server.message.EnqueueableMessage;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.model.VirtualHost;
import org.apache.qpid.server.util.ServerScopedRuntimeException;

import java.nio.ByteBuffer;
import java.util.HashMap;

public class SlowMessageStore implements MessageStore, DurableConfigurationStore
{
    private static final Logger _logger = Logger.getLogger(SlowMessageStore.class);
    private static final String DELAYS = "delays";
    private HashMap<String, Long> _preDelays = new HashMap<String, Long>();
    private HashMap<String, Long> _postDelays = new HashMap<String, Long>();
    private long _defaultDelay = 0L;
    private MessageStore _realStore = new MessageStoreCreator().createMessageStore("Memory");
    private DurableConfigurationStore _durableConfigurationStore = (DurableConfigurationStore) _realStore;
    private static final String PRE = "pre";
    private static final String POST = "post";
    private String DEFAULT_DELAY = "default";

    // ***** MessageStore Interface.

    public void configureConfigStore(VirtualHost virtualHost, ConfigurationRecoveryHandler recoveryHandler)
    {
        _logger.info("Starting SlowMessageStore on Virtualhost:" + virtualHost.getName());

        Object delaysAttr = virtualHost.getAttribute("slowMessageStoreDelays");

        Map delays = (delaysAttr instanceof Map) ? (Map) delaysAttr : Collections.emptyMap();
        configureDelays(delays);

        final Object realStoreAttr = virtualHost.getAttribute("realStore");
        String messageStoreClass = realStoreAttr == null ? null : realStoreAttr.toString();

        if (delays.containsKey(DEFAULT_DELAY))
        {
            _defaultDelay = Long.parseLong(String.valueOf(delays.get(DEFAULT_DELAY)));
        }

        if (messageStoreClass != null)
        {
            try
            {
                Class<?> clazz = Class.forName(messageStoreClass);

                Object o = clazz.newInstance();

                if (!(o instanceof MessageStore))
                {
                    throw new ClassCastException("Message store class must implement " + MessageStore.class + ". Class " + clazz +
                                                 " does not.");
                }
                _realStore = (MessageStore) o;
                if(o instanceof DurableConfigurationStore)
                {
                    _durableConfigurationStore = (DurableConfigurationStore)o;
                }
            }
            catch (ClassNotFoundException e)
            {
                throw new ServerScopedRuntimeException("Unable to find message store class", e);
            }
            catch (InstantiationException e)
            {
                throw new ServerScopedRuntimeException("Unable to initialise message store class", e);
            }
            catch (IllegalAccessException e)
            {
                throw new ServerScopedRuntimeException("Unable to access message store class", e);
            }
        }
        _durableConfigurationStore.configureConfigStore(virtualHost, recoveryHandler);

    }

    private void configureDelays(Map<Object, Object> config)
    {

        for(Map.Entry<Object, Object> entry : config.entrySet())
        {
            String key = String.valueOf(entry.getKey());
            if (key.startsWith(PRE))
            {
                _preDelays.put(key.substring(PRE.length()), Long.parseLong(String.valueOf(entry.getValue())));
            }
            else if (key.startsWith(POST))
            {
                _postDelays.put(key.substring(POST.length()), Long.parseLong(String.valueOf(entry.getValue())));
            }
        }
    }

    private void doPostDelay(String method)
    {
        long delay = lookupDelay(_postDelays, method);
        doDelay(delay);
    }

    private void doPreDelay(String method)
    {
        long delay = lookupDelay(_preDelays, method);
        doDelay(delay);
    }

    private long lookupDelay(HashMap<String, Long> delays, String method)
    {
        Long delay = delays.get(method);
        return (delay == null) ? _defaultDelay : delay;
    }

    private void doDelay(long delay)
    {
        if (delay > 0)
        {
            long start = System.nanoTime();
            try
            {

                Thread.sleep(delay);
            }
            catch (InterruptedException e)
            {
                _logger.warn("Interrupted : " + e);
            }

            long slept = (System.nanoTime() - start) / 1000000;

            if (slept >= delay)
            {
                _logger.info("Done sleep for:" + slept+":"+delay);
            }
            else
            {
                _logger.info("Only sleep for:" + slept + " re-sleeping");
                doDelay(delay - slept);
            }
        }
    }


    public void configureMessageStore(VirtualHost virtualHost, MessageStoreRecoveryHandler messageRecoveryHandler,
                                      TransactionLogRecoveryHandler tlogRecoveryHandler)
    {
        _realStore.configureMessageStore(virtualHost, messageRecoveryHandler, tlogRecoveryHandler);
    }

    public void close()
    {
        doPreDelay("close");
        _realStore.close();
        doPostDelay("close");
    }

    public <M extends StorableMessageMetaData> StoredMessage<M> addMessage(M metaData)
    {
        return _realStore.addMessage(metaData);
    }


    @Override
    public void create(UUID id, String type, Map<String, Object> attributes) throws StoreException
    {
        doPreDelay("create");
        _durableConfigurationStore.create(id, type, attributes);
        doPostDelay("create");
    }

    @Override
    public void remove(UUID id, String type) throws StoreException
    {
        doPreDelay("remove");
        _durableConfigurationStore.remove(id, type);
        doPostDelay("remove");
    }

    @Override
    public UUID[] removeConfiguredObjects(final UUID... objects) throws StoreException
    {
        doPreDelay("remove");
        UUID[] removed = _durableConfigurationStore.removeConfiguredObjects(objects);
        doPostDelay("remove");
        return removed;
    }

    @Override
    public void update(UUID id, String type, Map<String, Object> attributes) throws StoreException
    {
        doPreDelay("update");
        _durableConfigurationStore.update(id, type, attributes);
        doPostDelay("update");
    }

    @Override
    public void update(boolean createIfNecessary, ConfiguredObjectRecord... records) throws StoreException
    {
        doPreDelay("update");
        _durableConfigurationStore.update(createIfNecessary, records);
        doPostDelay("update");
    }

    public Transaction newTransaction()
    {
        doPreDelay("beginTran");
        Transaction txn = new SlowTransaction(_realStore.newTransaction());
        doPostDelay("beginTran");
        return txn;
    }


    public boolean isPersistent()
    {
        return _realStore.isPersistent();
    }

    public void storeMessageHeader(Long messageNumber, ServerMessage message)
    {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    public void storeContent(Long messageNumber, long offset, ByteBuffer body)
    {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    public ServerMessage getMessage(Long messageNumber)
    {
        return null//To change body of implemented methods use File | Settings | File Templates.
    }

    private class SlowTransaction implements Transaction
    {
        private final Transaction _underlying;

        private SlowTransaction(Transaction underlying)
        {
            _underlying = underlying;
        }

        public void enqueueMessage(TransactionLogResource queue, EnqueueableMessage message)
        {
            doPreDelay("enqueueMessage");
            _underlying.enqueueMessage(queue, message);
            doPostDelay("enqueueMessage");
        }

        public void dequeueMessage(TransactionLogResource queue, EnqueueableMessage message)
        {
            doPreDelay("dequeueMessage");
            _underlying.dequeueMessage(queue, message);
            doPostDelay("dequeueMessage");
        }

        public void commitTran()
        {
            doPreDelay("commitTran");
            _underlying.commitTran();
            doPostDelay("commitTran");
        }

        public StoreFuture commitTranAsync()
        {
            doPreDelay("commitTran");
            StoreFuture future = _underlying.commitTranAsync();
            doPostDelay("commitTran");
            return future;
        }

        public void abortTran()
        {
            doPreDelay("abortTran");
            _underlying.abortTran();
            doPostDelay("abortTran");
        }

        public void removeXid(long format, byte[] globalId, byte[] branchId)
        {
            _underlying.removeXid(format, globalId, branchId);
        }

        public void recordXid(long format, byte[] globalId, byte[] branchId, Record[] enqueues, Record[] dequeues)
        {
            _underlying.recordXid(format, globalId, branchId, enqueues, dequeues);
        }
    }

    @Override
    public void activate()
    {
       _realStore.activate();
    }

    @Override
    public void addEventListener(EventListener eventListener, Event... events)
    {
        _realStore.addEventListener(eventListener, events);
    }

    @Override
    public String getStoreLocation()
    {
        return _realStore.getStoreLocation();
    }

    @Override
    public String getStoreType()
    {
        return "SLOW";
    }

    @Override
    public void onDelete()
    {
        _realStore.onDelete();
    }

}
TOP

Related Classes of org.apache.qpid.server.store.SlowMessageStore$SlowTransaction

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.