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

org.apache.ode.bpel.engine.InstanceLockManager Maven / Gradle / Ivy

There is a newer version: 1.3.5-wso4v18
Show newest version
/*
 * 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.ode.bpel.engine;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

/**
 *
 * WARNING --- EXPERIMENTAL
 *
 * Mechanism for obtaining instance-level locks. Very simple implementation at the moment, that is only valid
 * for a single processing node. To move to multi-processor setup we'll need to implement this lock in the database.
 *
 * @author Maciej Szefler - m s z e f l e r @ g m a i l . c o m
 */
public class InstanceLockManager extends AbstractInstanceLockManager {
    private static final Log __log = LogFactory.getLog(InstanceLockManager.class);

    private final Lock _mutex = new java.util.concurrent.locks.ReentrantLock();
    private final Map _locks = new HashMap ();

    public void lock(Long iid, int time, TimeUnit tu) throws InterruptedException, TimeoutException {
        if (iid == null) return;

        String thrd = Thread.currentThread().toString();
        if (__log.isDebugEnabled())
            __log.debug(thrd + ": lock(iid=" + iid + ", time=" + time + tu+")");

        InstanceInfo li;

        _mutex.lock();
        try {

            while (true) {
                li = _locks.get(iid);
                if (li == null) {
                    li = new InstanceInfo(iid, Thread.currentThread());
                    _locks.put(iid, li);
                    if (__log.isDebugEnabled())
                        __log.debug(thrd + ": lock(iid=" + iid + ", time=" + time + tu+")-->GRANTED");
                    return;
                } else {
                    if (__log.isDebugEnabled())
                        __log.debug(thrd + ": lock(iid=" + iid + ", time=" + time + tu+")-->WAITING(held by " + li.acquierer + ")");

                    if (!li.available.await(time, tu)) {
                        if (__log.isDebugEnabled())
                            __log.debug(thrd + ": lock(iid=" + iid + ", time=" + time + tu+")-->TIMEOUT (held by " + li.acquierer + ")");
                        throw new TimeoutException();
                    }
                }
            }

        } finally {
            _mutex.unlock();
        }

    }

    public void unlock(Long iid)  {
        if (iid == null) return;

        String thrd = Thread.currentThread().toString();
        if (__log.isDebugEnabled())
            __log.debug(thrd + ": unlock(iid=" + iid + ")");

        _mutex.lock();
        try {
            InstanceInfo li = _locks.get(iid);
            if (li == null)
                throw new IllegalStateException("Instance not locked, cannot unlock!");

            _locks.remove(iid);

            // Note, that we have to signall all threads, because new holder will create a new
            // instance of "available" condition variable, so all the waiters need to try again
            li.available.signalAll();

        } finally {
            _mutex.unlock();
        }

    }


    @Override
    public String toString() {
        return "{InstanceLockManager: " + _locks +  "}";
    }

    /**
     * Information about the lock state for a particular instance.
     * @author Maciej Szefler - m s z e f l e r @ g m a i l . c o m
     */
    private class InstanceInfo {
        final long iid;

        /** Thread that acquired the lock. */
        final Thread acquierer;

        /** Condition-Variable indicating that the lock has become available. */
        Condition available = _mutex.newCondition();


        InstanceInfo(long iid, Thread t) {
            this.iid = iid;
            this.acquierer = t;
        }

        @Override
        public String toString() {
            return "{Lock for Instance #" + iid +", acquired by " +  acquierer + "}";
        }
    }

//    /** Exception class indicating a time-out occured while obtaining a lock. */
//    public static final class TimeoutException extends Exception {
//        private static final long serialVersionUID = 7247629086692580285L;
//    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy