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

com.deftlabs.lock.mongo.impl.SvcImpl Maven / Gradle / Ivy

The newest version!
/**
 * Copyright 2011, Deft Labs.
 *
 * 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.deftlabs.lock.mongo.impl;

// Lib
import com.deftlabs.lock.mongo.DistributedLock;
import com.deftlabs.lock.mongo.DistributedLockSvc;
import com.deftlabs.lock.mongo.DistributedLockOptions;
import com.deftlabs.lock.mongo.DistributedLockSvcOptions;
import com.deftlabs.lock.mongo.DistributedLockException;

// Mongo
import com.mongodb.Mongo;
import com.mongodb.MongoURI;

// Java
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * The distributed lock server implementation.
 */
public final class SvcImpl implements DistributedLockSvc {

    public SvcImpl(final DistributedLockSvcOptions pOptions) {
        _options = pOptions;
    }

    /**
     * Returns a new lock. If the name is already in use and the lock has been
     * created, it returns the existing lock.
     */
    @Override
    public DistributedLock create(  final String pLockName,
                                    final DistributedLockOptions pLockOptions) {
        if ( !isRunning() ) throw new IllegalStateException("cannot create lock when service not running");

        _lock.lock();
        try {
            if (_locks.containsKey(pLockName)) return _locks.get(pLockName);

            final LockImpl lock = new LockImpl(_mongo, pLockName, pLockOptions, _options);

            lock.init();

            _locks.put(pLockName, lock);

            return lock;

        } finally { _lock.unlock(); }
    }

    /**
     * Returns a new lock. If the name is already in use and the lock has been
     * created, it returns the existing lock.
     */
    @Override
    public DistributedLock create(final String pLockName) {
        return create(pLockName, new DistributedLockOptions());
    }

    @Override
    public void destroy(final DistributedLock pLock) {
        _lock.lock();
        try {
            if (!_locks.containsKey(pLock.getName()))
            { throw new DistributedLockException("Lock has already been destroyed: " + pLock.getName()); }

            // Make sure the lock isn't locked.
            if (pLock.isLocked())
            { throw new IllegalStateException("Lock is currently in use - must unlock before destroying"); }

            try { ((LockImpl)pLock).destroy(); } finally { _locks.remove(pLock.getName()); }

        } finally { _lock.unlock(); }
    }

    /**
     * Initialize the service.
     */
    @Override
    public void startup() {
        if (!_running.compareAndSet(false, true)) throw new IllegalStateException("startup called but already running");

        _lock.lock();
        try {
            _mongo = new Mongo(new MongoURI(_options.getMongoUri()));

            // Init the db/collection.
            LockDao.setup(_mongo, _options);
            if (_options.getEnableHistory()) LockHistoryDao.setup(_mongo, _options);

            // Init the monitor threads.
            _lockHeartbeat = new Monitor.LockHeartbeat(_mongo, _options, _locks);
            _lockHeartbeat.start();

            _lockTimeout = new Monitor.LockTimeout(_mongo, _options);
            _lockTimeout.start();

            _lockUnlocked = new Monitor.LockUnlocked(_mongo, _options, _locks);
            _lockUnlocked.start();


        } catch (final Throwable t) { throw new DistributedLockException(t);
        } finally { _lock.unlock(); }
    }

    /**
     * Initialize the service.
     */
    @Override
    public void shutdown() {
        if (!_running.compareAndSet(true, false)) throw new IllegalStateException("shutdown called but not running");

        _lock.lock();
        try {
            // Interrupt the locks.
            for (final String lockName : _locks.keySet()) {
                final DistributedLock lock = _locks.get(lockName);
                if (lock == null) continue;
                ((LockImpl)lock).destroy();
            }

            _lockTimeout.shutdown();
            _lockHeartbeat.shutdown();
            _lockUnlocked.shutdown();

            _locks.clear();
            _mongo.close();
        } catch (final Throwable t) { throw new DistributedLockException(t);
        } finally { _lock.unlock(); }
    }

    @Override
    public boolean isRunning() { return _running.get(); }

    private Mongo _mongo;

    private final ReentrantLock _lock = new ReentrantLock(true);
    private final DistributedLockSvcOptions _options;

    private final AtomicBoolean _running = new AtomicBoolean(false);

    private Monitor.LockHeartbeat _lockHeartbeat;
    private Monitor.LockTimeout _lockTimeout;
    private Monitor.LockUnlocked _lockUnlocked;

    private final Map _locks = new ConcurrentHashMap();

}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy