/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. 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. */ package org.apache.hadoop.hive.hwi; import java.util.ArrayList; import java.util.Collection; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * HiveSessionManager is a Runnable started inside a web application context. * It's basic function is to hold a collection of SessionItem(s). It also works * as a facade, as jsp clients can not create a Hive Session directly. Hive * Sessions are long lived, unlike a traditional Query and Block system clients * set up the query to be started with an instance of this class. * */ public class HWISessionManager implements Runnable { protected static final Log l4j = LogFactory.getLog(HWISessionManager.class .getName()); private boolean goOn; private TreeMap<HWIAuth, Set<HWISessionItem>> items; protected HWISessionManager() { goOn = true; items = new TreeMap<HWIAuth, Set<HWISessionItem>>(); } /** * This method scans the SessionItem collection. If a SessionItem is in the * QUERY_SET state that signals that its thread should be started. If the * SessionItem is in the DESTROY state it should be cleaned up and removed * from the collection. Currently we are using a sleep. A wait/notify could be * implemented. Queries will run for a long time, a one second wait on start * will not be noticed. * */ public void run() { l4j.debug("Entered run() thread has started"); while (goOn) { l4j.debug("locking items"); synchronized (items) { for (HWIAuth a : items.keySet()) { for (HWISessionItem i : items.get(a)) { if (i.getStatus() == HWISessionItem.WebSessionItemStatus.DESTROY) { items.get(a).remove(i); } if (i.getStatus() == HWISessionItem.WebSessionItemStatus.KILL_QUERY) { l4j.debug("Killing item: " + i.getSessionName()); i.killIt(); l4j.debug("Killed item: " + i.getSessionName()); items.get(a).remove(i); } } } } // end sync try { Thread.sleep(100); } catch (InterruptedException ex) { l4j.error("Could not sleep ", ex); } } // end while l4j.debug("goOn is false. Loop has ended."); // Cleanup used here to stop all threads synchronized (items) { for (HWIAuth a : items.keySet()) { for (HWISessionItem i : items.get(a)) { try { if (i.getStatus() == HWISessionItem.WebSessionItemStatus.QUERY_RUNNING) { l4j.debug(i.getSessionName() + "Joining "); i.runnable.join(1000); l4j.debug(i.getSessionName() + "Joined "); } } catch (InterruptedException ex) { l4j.error(i.getSessionName() + "while joining ", ex); } } } } } // end run protected boolean isGoOn() { return goOn; } protected void setGoOn(boolean goOn) { this.goOn = goOn; } protected TreeMap<HWIAuth, Set<HWISessionItem>> getItems() { return items; } protected void setItems(TreeMap<HWIAuth, Set<HWISessionItem>> items) { this.items = items; } // client methods called from JSP /** * Rather then return the actual items we return a list copies. This enforces * our HWISessionManager by preventing the ability of the client(jsp) to * create SessionItems. * * @return A set of SessionItems this framework manages */ public ArrayList<HWISessionItem> findAllSessionItems() { ArrayList<HWISessionItem> otherItems = new ArrayList<HWISessionItem>(); for (HWIAuth a : items.keySet()) { otherItems.addAll(items.get(a)); } return otherItems; } /** * Here we handle creating the SessionItem, we do this for the JSP client * because we need to set parameters the client is not aware of. One such * parameter is the command line arguments the server was started with. * * @param a * Authenticated user * @param sessionName * Represents the session name * @return a new SessionItem or null if a session with that name already * exists */ public HWISessionItem createSession(HWIAuth a, String sessionName) { l4j.debug("Creating session: " + sessionName); HWISessionItem si = null; synchronized (items) { if (findSessionItemByName(a, sessionName) == null) { l4j.debug("Initializing session: " + sessionName + " a for " + a.getUser()); si = new HWISessionItem(a, sessionName); if (!items.containsKey(a)) { l4j.debug("SessionList is empty " + a.getUser()); TreeSet<HWISessionItem> list = new TreeSet<HWISessionItem>(); list.add(si); items.put(a, list); l4j.debug("Item added " + si.getSessionName() + " for user " + a.getUser()); } else { items.get(a).add(si); l4j.debug("Item added " + si.getSessionName() + " for user " + a.getUser()); } } else { l4j.debug("Creating session: " + sessionName + " already exists " + a.getUser()); } } return si; } /** * Helper method useful when you know the session name you wish to reference. * * @param sessionname * @return A SessionItem matching the sessionname or null if it does not * exists */ public HWISessionItem findSessionItemByName(HWIAuth auth, String sessionname) { Collection<HWISessionItem> sessForUser = items.get(auth); if (sessForUser == null) { return null; } for (HWISessionItem si : sessForUser) { if (si.getSessionName().equals(sessionname)) { return si; } } return null; } /** * Used to list all users that have at least one session. * * @return keySet of items all users that have any sessions */ public Set<HWIAuth> findAllUsersWithSessions() { return items.keySet(); } /** * Used to list all the sessions of a user. * * @param auth * the user being enquired about * @return all the sessions of that user */ public Set<HWISessionItem> findAllSessionsForUser(HWIAuth auth) { return items.get(auth); } }