Package org.globus.workspace.accounting.impls.dbdefault

Source Code of org.globus.workspace.accounting.impls.dbdefault.DBAccountingPersistence

/*
* Copyright 1999-2008 University of Chicago
*
* 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 org.globus.workspace.accounting.impls.dbdefault;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.globus.workspace.Lager;
import org.globus.workspace.WorkspaceException;
import org.globus.workspace.accounting.ElapsedAndReservedMinutes;
import org.globus.workspace.persistence.WorkspaceDatabaseException;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Calendar;

/**
* package-private class, all access is from DBAccountingAdapter
*/
class DBAccountingPersistence implements DBAccountingConstants {

    private static final Log logger =
        LogFactory.getLog(DBAccountingPersistence.class.getName());

    private boolean initialized;

    private final DateFormat localFormat = DateFormat.getDateTimeInstance();

    private final DataSource dataSource;

    private final Lager lager;

    DBAccountingPersistence(DataSource dataSourceImpl,
                            Lager lagerImpl) {
       
        if (dataSourceImpl == null) {
            throw new IllegalArgumentException("dataSourceImpl may not be null");
        }
        this.dataSource = dataSourceImpl;

        if (lagerImpl == null) {
            throw new IllegalArgumentException("lagerImpl may not be null");
        }
        this.lager = lagerImpl;
    }

    /* ******** */
    /* DB setup */
    /* ******** */


    public void initialize() throws Exception {
       
        try {
            this.prepareStatements();
        } catch (SQLException sql) {
            throw new Exception("Problem preparing DB statements: ", sql);
        }

        this.initialized = true;
    }

    public boolean isInitialized() {
        return this.initialized;
    }

    /**
     * This moves significant prepared statement setup times to service
     * initialization instead of the first time they're used.
     *
     * Documentation states that PreparedStatement caches are per pool
     * connection but testing indicates with Derby (in embedded mode),
     * this is OK using one connection.
     *
     * @throws SQLException problem
     */
    private void prepareStatements() throws SQLException {

        if (this.lager.accounting) {
            logger.debug("prepareStatements()");
        }

        // String[] ins = INSENSITIVE_PREPARED_STATEMENTS;

        String[] pstmts = PREPARED_STATEMENTS;

        Connection c = null;
        PreparedStatement pstmt = null;
        try {
            c = getConnection();

            //for (int i = 0; i < ins.length; i++) {
            //    pstmt = c.prepareStatement(ins[i],
            //                               ResultSet.TYPE_SCROLL_INSENSITIVE,
            //                               ResultSet.CONCUR_UPDATABLE);
            //    pstmt.close();
            //}

            for (int i = 0; i < pstmts.length; i++) {
                pstmt = c.prepareStatement(pstmts[i]);
                pstmt.close();
            }

            pstmt = null;

        } catch(SQLException e) {
            logger.error("",e);
            throw e;
        } finally {
            try {
                if (pstmt != null) {
                    pstmt.close();
                }
                if (c != null) {
                    returnConnection(c);
                }
            } catch (SQLException sql) {
                logger.error("SQLException in finally cleanup", sql);
            }
        }
    }

    public int forceAllInactive() throws WorkspaceDatabaseException {
       
        if (this.lager.accounting) {
            logger.trace("forceAllInactive()");
        }

        int updated = -1;

        Connection c = null;
        PreparedStatement pstmt = null;
        try {
            c = getConnection();
            pstmt = c.prepareStatement(SQL_FORCE_ALL_INACTIVE);
            updated = pstmt.executeUpdate();

            if (this.lager.accounting) {
                logger.trace("updated " + updated + " rows");
            }

        } catch(SQLException e) {
            logger.error("",e);
            throw new WorkspaceDatabaseException(e);
        } finally {
            try {
                if (pstmt != null) {
                    pstmt.close();
                }
                if (c != null) {
                    returnConnection(c);
                }
            } catch (SQLException sql) {
                logger.error("SQLException in finally cleanup", sql);
            }
        }

        return updated;
    }

    /* ****** */
    /* Common */
    /* ****** */

    /**
     * @return Connection conn
     * @throws SQLException problem
     */
    private Connection getConnection() throws SQLException {
        return this.dataSource.getConnection();
    }

    private static void returnConnection(Connection connection) {
        if(connection != null) {
            try {
                connection.close();
            } catch(SQLException e) {
                logger.error("",e);
            }
        }
    }


    /* ****************** */
    /* Add/End Operations */
    /* ****************** */

    public synchronized void add(String uuid,
                                 int id,
                                 String ownerDN,
                                 long minutesRequested,
                                 Calendar creationTime,
                                 int CPUCores,
                                 int memory)
            throws WorkspaceDatabaseException {

        if (this.lager.accounting) {
            logger.trace("add(): uuid = '" + uuid + "', id = " + id + ", " +
                    "ownerDN = '" + ownerDN + "', minutesRequest = " +
                    minutesRequested + ", creationTime = " +
                    creationTime.getTimeInMillis() + ", cpu cores = " +
                    CPUCores + ", memory = " + memory
                    );
        }

        Connection c = null;
        PreparedStatement pstmt = null;
        try {
            c = getConnection();
            pstmt = c.prepareStatement(SQL_INSERT_DEPLOYMENT);

            pstmt.setString(1, uuid);
            pstmt.setInt(2, id);
            pstmt.setString(3, ownerDN);
            pstmt.setObject(4, new Long(creationTime.getTimeInMillis()));
            pstmt.setObject(5, new Long(minutesRequested));
            pstmt.setInt(6, 1);
            pstmt.setNull(7, Types.INTEGER);
            pstmt.setInt(8, CPUCores);
            pstmt.setInt(9, memory);
           
            int inserted = pstmt.executeUpdate();
            if (this.lager.accounting) {
                logger.trace(Lager.id(id) + ": inserted " + inserted + " rows");  
            }

        } catch(SQLException e) {
            logger.error("",e);
            throw new WorkspaceDatabaseException(e);
        } finally {
            try {
                if (pstmt != null) {
                    pstmt.close();
                }
                if (c != null) {
                    returnConnection(c);
                }
            } catch (SQLException sql) {
                logger.error("SQLException in finally cleanup", sql);
            }
        }

        if (this.lager.accounting) {
            logger.trace(Lager.id(id) + ": add() done (uuid: " + uuid + ")");
        }
       
    }

    public synchronized String end(int id,
                                 String ownerDN,
                                 long minutesElapsed)
            throws WorkspaceDatabaseException {

        if (this.lager.accounting) {
            logger.trace("end(): " + Lager.id(id) + ", ownerDN = '" + ownerDN +
                    "', minutesElapsed = " + minutesElapsed);
        }

        Connection c = null;
        PreparedStatement pstmt = null;
        PreparedStatement pstmt2 = null;
        ResultSet rs = null;
        String uuid;
        try {
            c = getConnection();
           
            // begin transaction
            c.setAutoCommit(false);

            // check consistency of destroy request
            // & retrieve necessary items for subsequent sql
           
            String creatorDN;
            Calendar creationTime;
            long t;
            int requestedDuration;
            int CPUCores;
            int memory;

            pstmt = c.prepareStatement(SQL_LOAD_DEPLOYMENT);
            pstmt.setInt(1, id);
            rs = pstmt.executeQuery();

            if (rs == null || !rs.next()) {
                String err = "active deployment with id " + id + " not found";
                logger.error(err);
                throw new WorkspaceDatabaseException(err);
            } else {
                uuid = rs.getString(1);
                creatorDN = rs.getString(2);
                t = rs.getLong(3);
                creationTime = Calendar.getInstance();
                creationTime.setTimeInMillis(t);
                requestedDuration = rs.getInt(4);
                CPUCores = rs.getInt(5);
                memory = rs.getInt(6);
            }

            if (this.lager.accounting) {
                logger.trace("end(): found " + Lager.id(id) +
                             ": uuid = " + uuid +
                             ", creation time = " + t +
                             ", requestedDuration = " + requestedDuration +
                             ", CPU cores = " + CPUCores +
                             ", memory = " + memory +
                             ", creator DN = " + creatorDN);
            }

            rs.close();
            rs = null;

            if (ownerDN.equals(creatorDN)) {
                if (this.lager.accounting) {
                    logger.trace(Lager.id(id) + ": creatorDN in DB matches " +
                            "destroy request");
                }
            } else {
                String err = "active deployment with id " + id + " had " +
                        "non-matching creatorDN.  Expected '" + ownerDN + "'," +
                        " stored was '" + creatorDN + "'";
                logger.error(err);
                throw new WorkspaceDatabaseException(err);
            }

            // log elapsed time

            pstmt2 = c.prepareStatement(SQL_UPDATE_END_DEPLOYMENT);
            pstmt2.setObject(1, new Long(minutesElapsed));
            pstmt2.setString(2, uuid);
           
            int updated = pstmt2.executeUpdate();

            c.commit();

            if (this.lager.accounting) {
                logger.trace(Lager.id(id) + ": updated " + updated + " rows");
            }


        } catch(SQLException e) {
            logger.error("",e);
            throw new WorkspaceDatabaseException(e);
        } finally {
            try {
                if (rs != null) {
                    rs.close();
                }
                if (pstmt != null) {
                    pstmt.close();
                }
                if (pstmt2 != null) {
                    pstmt2.close();
                }
                if (c != null) {
                    c.setAutoCommit(true);
                    returnConnection(c);
                }
            } catch (SQLException sql) {
                logger.error("SQLException in finally cleanup", sql);
            }
        }

        return uuid;
    }

    /* **************** */
    /* Query Operations */
    /* **************** */

    public long totalElapsedMinutes(String ownerDN)
            throws WorkspaceException {

        Connection c = null;
        try {
            c = getConnection();
            return totalElapsedMinutesImpl(ownerDN, c);
        } catch(SQLException e) {
            logger.error("",e);
            throw new WorkspaceException(e);
        } finally {
            if (c != null) {
                returnConnection(c);
            }
        }
    }

    public long currentReservedMinutes(String ownerDN)
            throws WorkspaceException {
       
        Connection c = null;
        try {
            c = getConnection();
            return this.currentReservedMinutesImpl(ownerDN, c);
        } catch(SQLException e) {
            logger.error("",e);
            throw new WorkspaceException(e);
        } finally {
            if (c != null) {
                returnConnection(c);
            }
        }
    }

    public ElapsedAndReservedMinutes totalElapsedAndReservedMinutesTuple(
                                                        String ownerDN)
            throws WorkspaceException {

        Connection c = null;
        try {
            c = getConnection();
            long reserved = this.currentReservedMinutesImpl(ownerDN, c);
            long elapsed = totalElapsedMinutesImpl(ownerDN, c);
            return new ElapsedAndReservedMinutes(elapsed, reserved);
        } catch(SQLException e) {
            logger.error("",e);
            throw new WorkspaceException(e);
        } finally {
            if (c != null) {
                returnConnection(c);
            }
        }
    }

    /**
     * Returns a list of lines to log, one for each current reservation.
     * Embedding line formatting in this method as a shortcut even though
     * formatting is more appropriately the caller's concern.
     * 
     * @return list of strings to log
     * @throws WorkspaceException problem
     */
    public ArrayList allActiveReservations() throws WorkspaceException {

        Connection c = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            c = getConnection();
            pstmt = c.prepareStatement(SQL_ALL_CURRENT_RESERVATIONS);
            rs = pstmt.executeQuery();

            ArrayList reservations = new ArrayList();

            if (rs == null) {
                if (this.lager.accounting) {
                    logger.trace("null result for current reservations query");
                }
                return reservations;
            }

            while (rs.next()) {
                String uuid = rs.getString(1);
                int id = rs.getInt(2);
                String dn = rs.getString(3);
                long t = rs.getLong(4);
                Calendar creationTime = Calendar.getInstance();
                creationTime.setTimeInMillis(t);
                int duration = rs.getInt(5);

                StringBuffer buf = new StringBuffer();
                buf.append("dn=\"")
                   .append(dn)
                   .append("\", minutes=")
                   .append(duration)
                   .append(", uuid=\"")
                   .append(uuid)
                   .append("\", eprkey=")
                   .append(id)
                   .append(", creation=\"")
                   .append(this.localFormat.format(creationTime.getTime()))
                   .append('"');

                reservations.add(buf.toString());
            }

            if (this.lager.accounting) {
                logger.trace("sizeof(reservations) = " + reservations.size());
            }

            return reservations;

        } catch(SQLException e) {
            logger.error("",e);
            throw new WorkspaceException(e);
        } finally {
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    logger.error(e.getMessage(), e);
                }
            }
            if (pstmt != null) {
                try {
                    pstmt.close();
                } catch (SQLException e) {
                    logger.error(e.getMessage(), e);
                }
            }
            if (c != null) {
                returnConnection(c);
            }
        }
    }

    private static long totalElapsedMinutesImpl(String ownerDN, Connection c)
            throws WorkspaceException {

        PreparedStatement pstmt = null;
        ResultSet rs = null;
        long time = 0;
       
        try {

            pstmt = c.prepareStatement(SQL_SUM_ELAPSED);
            pstmt.setString(1, ownerDN);
            rs = pstmt.executeQuery();

            if (rs == null || !rs.next()) {
                logger.debug("no result from sum (DN not seen before)");
                return time;
            } else {
                time = rs.getLong(1);
            }

        } catch(SQLException e) {
            logger.error("",e);
            throw new WorkspaceException(e);
        } finally {
            try {
                if (rs != null) {
                    rs.close();
                }
                if (pstmt != null) {
                    pstmt.close();
                }
            } catch (SQLException sql) {
                logger.error("SQLException in finally cleanup", sql);
            }
        }

        return time;
    }

    private long currentReservedMinutesImpl(String ownerDN, Connection c)
            throws WorkspaceException {

        PreparedStatement pstmt = null;
        ResultSet rs = null;
        long time = 0;

        try {

            pstmt = c.prepareStatement(SQL_SUM_RESERVED);
            pstmt.setString(1, ownerDN);
            rs = pstmt.executeQuery();

            if (rs == null || !rs.next()) {
                logger.debug("no result from sum (DN not seen before)");
                return time;
            } else {
                time = rs.getLong(1);
            }
           
        } catch(SQLException e) {
            logger.error("",e);
            throw new WorkspaceException(e);
        } finally {
            try {
                if (rs != null) {
                    rs.close();
                }
                if (pstmt != null) {
                    pstmt.close();
                }
            } catch (SQLException sql) {
                logger.error("SQLException in finally cleanup", sql);
            }
        }

        return time;
    }
}
TOP

Related Classes of org.globus.workspace.accounting.impls.dbdefault.DBAccountingPersistence

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.