org.apache.roller.weblogger.business.jpa.JPAThreadManagerImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.roller.weblogger.business.jpa.JPAThreadManagerImpl.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  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.  For additional information regarding
 * copyright in this work, please see the NOTICE file in the top level
 * directory of this distribution.
 */

package org.apache.roller.weblogger.business.jpa;

import java.sql.Timestamp;
import java.util.Date;
import javax.persistence.NoResultException;
import javax.persistence.Query;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.roller.util.DateUtil;
import org.apache.roller.weblogger.WebloggerException;
import org.apache.roller.weblogger.business.Weblogger;
import org.apache.roller.weblogger.business.runnable.ThreadManagerImpl;
import org.apache.roller.weblogger.business.runnable.RollerTask;
import org.apache.roller.weblogger.pojos.TaskLock;

/**
 * JPA implementation of the TaskLockManager interface.
 *
 * This implementation extends the base ThreadManagerImpl class and provides
 * locking abilities which are managed through the database.
 */
@com.google.inject.Singleton
public class JPAThreadManagerImpl extends ThreadManagerImpl {

    private static final Log log = LogFactory.getLog(JPAThreadManagerImpl.class);

    private final Weblogger roller;
    private final JPAPersistenceStrategy strategy;

    @com.google.inject.Inject
    protected JPAThreadManagerImpl(Weblogger roller, JPAPersistenceStrategy strat) {
        super();

        log.debug("Instantiating JPA Thread Manager");

        this.roller = roller;
        this.strategy = strat;
    }

    /**
     * Try to aquire a lock for a given RollerTask.
     */
    @Override
    public boolean registerLease(RollerTask task) {

        log.debug("Attempting to register lease for task - " + task.getName());

        // keep a copy of the current time
        Date currentTime = new Date();

        // query for existing lease record first
        TaskLock taskLock = null;
        try {
            taskLock = getTaskLockByName(task.getName());
            if (taskLock == null) {
                log.warn("Cannot acquire lease when no tasklock record exists for task - " + task.getName());
            }
        } catch (WebloggerException ex) {
            log.warn("Error getting TaskLock", ex);
            return false;
        }

        // try to acquire lease
        if (taskLock != null)
            try {
                // calculate lease expiration time
                Date leaseExpiration = taskLock.getLeaseExpiration();

                // calculate run time for task, this is expected time, not actual time
                // i.e. if a task is meant to run daily at midnight this should
                // reflect 00:00:00 on the current day
                Date runTime = currentTime;
                if ("startOfDay".equals(task.getStartTimeDesc())) {
                    // start of today
                    runTime = DateUtil.getStartOfDay(currentTime);
                } else if ("startOfHour".equals(task.getStartTimeDesc())) {
                    // start of this hour
                    runTime = DateUtil.getStartOfHour(currentTime);
                } else {
                    // start of this minute
                    runTime = DateUtil.getStartOfMinute(currentTime);
                }

                if (log.isDebugEnabled()) {
                    log.debug("last run = " + taskLock.getLastRun());
                    log.debug("new run time = " + runTime);
                    log.debug("last acquired = " + taskLock.getTimeAquired());
                    log.debug("time leased = " + taskLock.getTimeLeased());
                    log.debug("lease expiration = " + leaseExpiration);
                }

                Query q = strategy
                        .getNamedUpdate("TaskLock.updateClient&Timeacquired&Timeleased&LastRunByName&Timeacquired");
                q.setParameter(1, task.getClientId());
                q.setParameter(2, Integer.valueOf(task.getLeaseTime()));
                q.setParameter(3, new Timestamp(runTime.getTime()));
                q.setParameter(4, task.getName());
                q.setParameter(5, taskLock.getTimeAquired());
                q.setParameter(6, new Timestamp(leaseExpiration.getTime()));
                int result = q.executeUpdate();

                if (result == 1) {
                    strategy.flush();
                    return true;
                }

            } catch (Exception e) {
                log.warn("Error obtaining lease, assuming race condition.", e);
                return false;
            }

        return false;
    }

    /**
     * Try to release the lock for a given RollerTask.
     */
    @Override
    public boolean unregisterLease(RollerTask task) {

        // query for existing lease record first
        TaskLock taskLock = null;
        try {
            taskLock = this.getTaskLockByName(task.getName());

            if (taskLock == null) {
                return false;
            }

        } catch (WebloggerException ex) {
            if (log.isDebugEnabled()) {
                log.debug("Error getting TaskLock", ex);
            } else {
                log.warn("Error getting TaskLock, enable debug for more info");
            }
            return false;
        }

        // try to release lease, just set lease time to 0
        try {
            Query q = strategy.getNamedUpdate("TaskLock.updateTimeLeasedByName&Client");
            q.setParameter(1, Integer.valueOf(0));
            q.setParameter(2, task.getName());
            q.setParameter(3, task.getClientId());
            int result = q.executeUpdate();

            if (result == 1) {
                strategy.flush();
                return true;
            }

        } catch (Exception e) {
            if (log.isDebugEnabled()) {
                log.debug("Error releasing lease", e);
            } else {
                log.warn("Error releasing lease, enable debug for more info");
            }
            return false;
        }

        return false;

    }

    /**
     * @inheritDoc
     */
    public TaskLock getTaskLockByName(String name) throws WebloggerException {
        // do lookup
        Query q = strategy.getNamedQuery("TaskLock.getByName");
        q.setParameter(1, name);
        try {
            return (TaskLock) q.getSingleResult();
        } catch (NoResultException e) {
            return null;
        }
    }

    /**
     * @inheritDoc
     */
    public void saveTaskLock(TaskLock data) throws WebloggerException {
        this.strategy.store(data);
    }

}