org.globus.workspace.scheduler.defaults.pilot.PilotSlotManagementDB.java Source code

Java tutorial

Introduction

Here is the source code for org.globus.workspace.scheduler.defaults.pilot.PilotSlotManagementDB.java

Source

/*
 * 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.scheduler.defaults.pilot;

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

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.util.ArrayList;

public class PilotSlotManagementDB implements PilotSlotManagementConstants {

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

    private final DataSource dataSource;
    private final Lager lager;

    private static final int[] zeroLen = new int[0];

    private int numActiveSlotsCache;

    /* ************ */
    /* Construction */
    /* ************ */

    PilotSlotManagementDB(DataSource dsrc, Lager lagerImpl) throws Exception {
        if (dsrc == null) {
            throw new IllegalArgumentException("dsrc may not be null");
        }
        this.dataSource = dsrc;

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

        try {
            this.prepareStatements();
        } catch (WorkspaceDatabaseException e) {
            throw new Exception("Problem preparing DB statements: ", e);
        }

        this.numActiveSlotsCache = this.countSlots();
    }

    /* ****** */
    /* Caches */
    /* ****** */

    /**
     * @param adjusted if true, we are telling the cache to update itself
     * @return number of current slots
     * @throws org.globus.workspace.persistence.WorkspaceDatabaseException problem updating cache
     */
    synchronized int numSlotsCached(boolean adjusted) throws WorkspaceDatabaseException {
        if (adjusted) {
            this.numActiveSlotsCache = this.countSlots();
        }
        return this.numActiveSlotsCache;
    }

    /* **************** */
    /* Database methods */
    /* **************** */

    PilotSlot getSlotAndAssignVMImpl(String uuid, String hostname)
            throws WorkspaceDatabaseException, SlotNotFoundException {

        Connection c = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            c = getConnection();
            pstmt = c.prepareStatement(SQL_LOAD_SLOTS_NOHOSTNAME);
            pstmt.setString(1, uuid);

            rs = pstmt.executeQuery();

            if (rs == null || !rs.next()) {
                throw new SlotNotFoundException(
                        "There are no slot " + "entries with this UUID and no hostname yet. " + "UUID='" + uuid
                                + "', hostname='" + hostname + "'");
            }

            int vmid = rs.getInt(1);
            boolean terminal = rs.getBoolean(2);
            String lrmhandle = rs.getString(3);
            int duration = rs.getInt(4);
            boolean partofgroup = rs.getBoolean(5);
            boolean pendingRemove = rs.getBoolean(6);

            pstmt.close();
            pstmt = null;

            pstmt = c.prepareStatement(SQL_UPDATE_SLOT_NODENAME);
            pstmt.setString(1, hostname);
            pstmt.setString(2, uuid);
            pstmt.setInt(3, vmid);

            pstmt.executeUpdate();

            logger.debug("Assigned vm id " + vmid + " to hostname = '" + hostname + "', uuid = '" + uuid + "'");

            return new PilotSlot(uuid, vmid, false, terminal, lrmhandle, duration, hostname, partofgroup,
                    pendingRemove);

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

    PilotSlot getSlot(String uuid, String hostname) throws WorkspaceDatabaseException, SlotNotFoundException {

        Connection c = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            c = getConnection();
            pstmt = c.prepareStatement(SQL_LOAD_SLOT);
            pstmt.setString(1, uuid);
            pstmt.setString(2, hostname);

            rs = pstmt.executeQuery();

            if (rs == null || !rs.next()) {
                throw new SlotNotFoundException(uuid, hostname);
            }

            int vmid = rs.getInt(1);
            boolean pending = rs.getBoolean(2);
            boolean terminal = rs.getBoolean(3);
            String lrmhandle = rs.getString(4);
            int duration = rs.getInt(5);
            boolean partofgroup = rs.getBoolean(6);
            boolean pendingRemove = rs.getBoolean(7);

            return new PilotSlot(uuid, vmid, pending, terminal, lrmhandle, duration, hostname, partofgroup,
                    pendingRemove);

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

    // assumes no slotid-vmid one-to-many relation yet, just one to one
    PilotSlot getSlot(int vmid) throws WorkspaceDatabaseException, SlotNotFoundException {

        Connection c = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            c = getConnection();
            pstmt = c.prepareStatement(SQL_LOAD_SLOT_BY_VM);
            pstmt.setInt(1, vmid);

            rs = pstmt.executeQuery();

            if (rs == null || !rs.next()) {
                throw new SlotNotFoundException(vmid);
            }

            String uuid = rs.getString(1);
            boolean pending = rs.getBoolean(2);
            boolean terminal = rs.getBoolean(3);
            String lrmhandle = rs.getString(4);
            int duration = rs.getInt(5);
            boolean partOfGroup = rs.getBoolean(6);
            boolean pendingRemove = rs.getBoolean(7);
            String nodename = rs.getString(8);

            return new PilotSlot(uuid, vmid, pending, terminal, lrmhandle, duration, nodename, partOfGroup,
                    pendingRemove);

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

    int countSlots() throws WorkspaceDatabaseException {

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

            rs = pstmt.executeQuery();

            if (rs == null || !rs.next()) {
                return 0;
            }

            return rs.getInt(1);

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

    void setSlotPendingRemove(PilotSlot slot) throws WorkspaceDatabaseException, SlotNotFoundException {

        Connection c = null;
        PreparedStatement pstmt = null;
        try {
            c = getConnection();
            pstmt = c.prepareStatement(SQL_UPDATE_SLOT_PENDING_REMOVE_SET_TRUE);
            pstmt.setString(1, slot.uuid);
            pstmt.setString(2, slot.nodename);

            final int updated = pstmt.executeUpdate();

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

            if (updated == 0) {
                throw new SlotNotFoundException(slot.uuid, slot.nodename);
            }

        } 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);
            }
        }
    }

    void setSlotTerminal(PilotSlot slot) throws WorkspaceDatabaseException, SlotNotFoundException {

        Connection c = null;
        PreparedStatement pstmt = null;
        try {
            c = getConnection();
            pstmt = c.prepareStatement(SQL_UPDATE_SLOT_TERMINAL_SET_TRUE);
            pstmt.setString(1, slot.uuid);
            pstmt.setString(2, slot.nodename);

            final int updated = pstmt.executeUpdate();

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

            if (updated == 0) {
                throw new SlotNotFoundException(slot.uuid, slot.nodename);
            }

        } 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);
            }
        }
    }

    void newGroupMember(String groupid, int vmid) throws WorkspaceDatabaseException {

        Connection c = null;
        PreparedStatement pstmt = null;
        try {
            c = getConnection();
            pstmt = c.prepareStatement(SQL_INSERT_GROUP_MEMBER);
            pstmt.setString(1, groupid);
            pstmt.setInt(2, vmid);

            final int inserted = pstmt.executeUpdate();

            if (this.lager.dbLog) {
                logger.trace("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);
            }
        }
    }

    int[] findVMsInGroup(String groupID)

            throws WorkspaceDatabaseException {

        if (groupID == null) {
            throw new WorkspaceDatabaseException("groupID is null");
        }

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

            pstmt = c.prepareStatement(SQL_SELECT_ALL_VMS_IN_GROUP);
            pstmt.setString(1, groupID);

            rs = pstmt.executeQuery();

            if (rs == null || !rs.next()) {
                logger.debug("no VMs found with groupID = " + groupID);
                return zeroLen;
            }

            final ArrayList vmidsList = new ArrayList(64);
            do {
                vmidsList.add(new Integer(rs.getInt(1)));
            } while (rs.next());

            // can't use toArray without converting to Integer[]
            final int[] ret = new int[vmidsList.size()];
            for (int i = 0; i < ret.length; i++) {
                ret[i] = ((Number) vmidsList.get(i)).intValue();
            }
            return ret;

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

    void newSlot(String uuid, int vmid, String lrmid, long duration) throws WorkspaceDatabaseException {

        Connection c = null;
        PreparedStatement pstmt = null;
        try {
            c = getConnection();
            pstmt = c.prepareStatement(SQL_INSERT_SLOT);
            pstmt.setString(1, uuid);
            pstmt.setInt(2, vmid);
            pstmt.setString(3, lrmid);
            pstmt.setLong(4, duration);
            pstmt.setNull(5, Types.VARCHAR);

            final int inserted = pstmt.executeUpdate();

            if (this.lager.dbLog) {
                logger.trace("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);
            }
        }

        // newSlot affects slotnum
        this.numSlotsCached(true);
    }

    void newSlotGroup(String uuid, int[] vmids, String lrmid, long duration) throws WorkspaceDatabaseException {

        Connection c = null;
        PreparedStatement pstmt = null;
        try {
            c = getConnection();
            for (int i = 0; i < vmids.length; i++) {
                pstmt = c.prepareStatement(SQL_INSERT_GROUP_SLOT);
                pstmt.setString(1, uuid);
                pstmt.setInt(2, vmids[i]);
                pstmt.setString(3, lrmid);
                pstmt.setLong(4, duration);
                pstmt.setNull(5, Types.VARCHAR);

                pstmt.executeUpdate();
            }

        } 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);
            }
        }

        // newSlot affects slotnum
        this.numSlotsCached(true);
    }

    void removeSlot(String uuid) throws WorkspaceDatabaseException {

        Connection c = null;
        PreparedStatement pstmt = null;
        try {
            c = getConnection();
            pstmt = c.prepareStatement(SQL_DELETE_SLOT);
            pstmt.setString(1, uuid);

            final int deleted = pstmt.executeUpdate();

            if (this.lager.dbLog) {
                logger.trace("deleted " + deleted + " 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);
            }
        }

        // removeSlot affects slotnum
        this.numSlotsCached(true);
    }

    void updateCursorPosition(long filepos) throws WorkspaceDatabaseException {

        Connection c = null;
        PreparedStatement pstmt = null;
        try {
            c = getConnection();
            pstmt = c.prepareStatement(SQL_UPDATE_CURSOR_POSITION);
            pstmt.setLong(1, filepos);
            pstmt.executeUpdate();
        } 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);
            }
        }
    }

    long currentCursorPosition() throws WorkspaceDatabaseException {

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

            rs = pstmt.executeQuery();

            if (rs == null || !rs.next()) {
                pstmt2 = c.prepareStatement(SQL_INSERT_CURSOR_POSITION);
                pstmt2.executeUpdate();
                return 0;
            }

            return rs.getLong(1);

        } 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) {
                    returnConnection(c);
                }
            } catch (SQLException sql) {
                logger.error("SQLException in finally cleanup", sql);
            }
        }
    }

    // DB utility methods:

    /**
     * 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 preliminary testing indicates it is effective to
     * just use the first one from the pool.
     *
     * @throws org.globus.workspace.persistence.WorkspaceDatabaseException exc
     */
    private void prepareStatements() throws WorkspaceDatabaseException {

        //String[] ins =
        //    PilotSlotManagementConstants.INSENSITIVE_PREPARED_STATEMENTS;

        final 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 new WorkspaceDatabaseException(e);
        } finally {
            try {
                if (pstmt != null) {
                    pstmt.close();
                }
                if (c != null) {
                    returnConnection(c);
                }
            } catch (SQLException e) {
                logger.error("SQLException in finally cleanup", e);
            }
        }
    }

    private Connection getConnection() throws WorkspaceDatabaseException {
        try {
            return this.dataSource.getConnection();
        } catch (SQLException e) {
            throw new WorkspaceDatabaseException(e);
        }
    }

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

}