org.sakaiproject.search.journal.impl.DbJournalManager.java Source code

Java tutorial

Introduction

Here is the source code for org.sakaiproject.search.journal.impl.DbJournalManager.java

Source

/**********************************************************************************
 * $URL: https://source.sakaiproject.org/svn/search/trunk/search-impl/impl/src/java/org/sakaiproject/search/journal/impl/DbJournalManager.java $
 * $Id: DbJournalManager.java 105078 2012-02-24 23:00:38Z ottenhoff@longsight.com $
 ***********************************************************************************
 *
 * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008 The Sakai Foundation
 *
 * Licensed under the Educational Community 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.opensource.org/licenses/ECL-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.sakaiproject.search.journal.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.sql.DataSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.component.api.ServerConfigurationService;
import org.sakaiproject.search.indexer.api.IndexJournalException;
import org.sakaiproject.search.journal.api.JournalErrorException;
import org.sakaiproject.search.journal.api.JournalExhausetedException;
import org.sakaiproject.search.journal.api.JournalManager;
import org.sakaiproject.search.journal.api.JournalManagerState;
import org.sakaiproject.search.transaction.api.IndexTransaction;

/**
 * A database backed Journal Manager
 * 
 * @author ieb Unit test
 * @see org.sakaiproject.search.indexer.impl.test.TransactionalIndexWorkerTest
 *      Unit test
 * @see org.sakaiproject.search.indexer.impl.test.DbJournalManagerTest
 */
public class DbJournalManager implements JournalManager {

    /**
     * @author ieb
     */
    private static class JournalManagerStateImpl implements JournalManagerState {

        private long transactionId;

        /*
         * Normally its not safe to hold onto a connection for any length of
         * time, but here it is ok since the transaction is connected to the
         * transaction id. The danger of not detaching is connection is that if
         * there is a machine failure I dont journal to be update.
         */
        public Connection connection;

        /**
         * @param transactionId
         */
        public JournalManagerStateImpl(long transactionId) {
            this.transactionId = transactionId;
        }

        /**
         * @return the transactionId
         */
        public long getTransactionId() {
            return transactionId;
        }

    }

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

    private DataSource datasource;

    private String serverId;

    private ServerConfigurationService serverConfigurationService;

    public void init() {
        serverId = serverConfigurationService.getServerId();
    }

    public void destroy() {

    }

    /**
     * @return the datasource
     */
    public DataSource getDatasource() {
        return datasource;
    }

    /**
     * @param datasource
     *        the datasource to set
     */
    public void setDatasource(DataSource datasource) {
        this.datasource = datasource;
    }

    /**
     * @throws JournalErrorException
     * @see org.sakaiproject.search.journal.api.JournalManager#getLaterSavePoints(long)
     */
    public long getNextSavePoint(long savePoint) throws JournalErrorException {
        Connection connection = null;
        PreparedStatement listLaterSavePoints = null;
        ResultSet rs = null;
        try {
            connection = datasource.getConnection();
            listLaterSavePoints = connection.prepareStatement(
                    "select txid from search_journal where txid > ? and (status = 'commited' or status = 'committed') order by txid asc ");
            listLaterSavePoints.clearParameters();
            listLaterSavePoints.setLong(1, savePoint);
            try {
                rs = listLaterSavePoints.executeQuery();
                if (rs.next()) {
                    return rs.getLong(1);
                }
            } catch (Exception ex) {
                log.warn("Shared Index Optimization in progress, pausing updates to this index :" + ex);
            }
            throw new JournalExhausetedException("No More savePoints available");
        } catch (SQLException ex) {
            log.error("Failed to retrieve list of journal items ", ex);
            throw new JournalErrorException("Journal Error ", ex);
        } finally {
            try {
                rs.close();
            } catch (Exception ex) {
                log.debug(ex);
            }
            try {
                listLaterSavePoints.close();
            } catch (Exception ex) {
                log.debug(ex);
            }
            try {
                connection.close();
            } catch (Exception ex) {
                log.debug(ex);
            }
        }
    }

    /**
     * @see org.sakaiproject.search.journal.api.JournalManager#prepareSave(long)
     */
    public JournalManagerState prepareSave(long transactionId) throws IndexJournalException {
        PreparedStatement insertPst = null;
        JournalManagerStateImpl jms = new JournalManagerStateImpl(transactionId);
        try {

            Connection connection = datasource.getConnection();
            jms.connection = connection;

            insertPst = connection.prepareStatement(
                    "insert into search_journal (txid, txts, indexwriter, status) values ( ?,?,?,?)");
            insertPst.clearParameters();
            insertPst.setLong(1, transactionId);
            insertPst.setLong(2, System.currentTimeMillis());
            insertPst.setString(3, serverId);
            insertPst.setString(4, "prepare");
            if (insertPst.executeUpdate() != 1) {
                throw new IndexJournalException("Failed to update index journal");
            }

        } catch (IndexJournalException ijex) {
            throw ijex;
        } catch (Exception ex) {
            throw new IndexJournalException("Failed to transfer index ", ex);
        } finally {
            try {
                insertPst.close();
            } catch (Exception ex) {
                log.debug(ex);
            }
        }
        return jms;
    }

    /**
     * @see org.sakaiproject.search.journal.api.JournalManager#commitSave()
     */
    public void commitSave(JournalManagerState jms) throws IndexJournalException {
        Connection connection = ((JournalManagerStateImpl) jms).connection;
        PreparedStatement success = null;
        try {
            success = connection.prepareStatement("update search_journal set status = 'committed' where txid = ? ");
            success.clearParameters();
            success.setLong(1, ((JournalManagerStateImpl) jms).getTransactionId());
            if (success.executeUpdate() != 1) {
                throw new IndexJournalException("Failed to update index journal");
            }

            connection.commit();
        } catch (Exception ex) {
            try {
                connection.rollback();
            } catch (Exception ex2) {
                log.debug(ex);
            }
            throw new IndexJournalException("Failed to commit index ", ex);
        } finally {
            try {
                success.close();
            } catch (Exception ex) {
                log.debug(ex);
            }
            try {
                connection.close();
            } catch (Exception ex) {
                log.debug(ex);
            }
        }

    }

    /**
     * @see org.sakaiproject.search.journal.api.JournalManager#rollbackSave(org.sakaiproject.search.journal.api.JournalManagerState)
     */
    public void rollbackSave(JournalManagerState jms) {
        if (jms != null) {
            Connection connection = ((JournalManagerStateImpl) jms).connection;
            try {

                connection.rollback();

            } catch (Exception ex) {
                log.error("Failed to Rollback");
            } finally {
                try {
                    connection.close();
                } catch (Exception ex) {
                    log.debug(ex);
                }

            }
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.sakaiproject.search.journal.api.JournalManager#doOpenTransaction(org.sakaiproject.search.transaction.api.IndexTransaction)
     */
    public void doOpenTransaction(IndexTransaction transaction) {
    }

    /**
     * @return the serverConfigurationService
     */
    public ServerConfigurationService getServerConfigurationService() {
        return serverConfigurationService;
    }

    /**
     * @param serverConfigurationService
     *        the serverConfigurationService to set
     */
    public void setServerConfigurationService(ServerConfigurationService serverConfigurationService) {
        this.serverConfigurationService = serverConfigurationService;
    }

}