PageRenderTime 107ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/tags/release-0.0.0-rc0/hive/external/hwi/src/java/org/apache/hadoop/hive/hwi/HWISessionItem.java

#
Java | 585 lines | 347 code | 62 blank | 176 comment | 55 complexity | 195f990796168e0a8827c3529c851f28 MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause, JSON, CPL-1.0
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. package org.apache.hadoop.hive.hwi;
  19. import java.io.File;
  20. import java.io.FileOutputStream;
  21. import java.io.IOException;
  22. import java.io.PrintStream;
  23. import java.util.ArrayList;
  24. import java.util.List;
  25. import org.apache.commons.logging.Log;
  26. import org.apache.commons.logging.LogFactory;
  27. import org.apache.hadoop.hive.cli.CliSessionState;
  28. import org.apache.hadoop.hive.cli.OptionsProcessor;
  29. import org.apache.hadoop.hive.conf.HiveConf;
  30. import org.apache.hadoop.hive.ql.Driver;
  31. import org.apache.hadoop.hive.ql.history.HiveHistoryViewer;
  32. import org.apache.hadoop.hive.ql.processors.CommandProcessor;
  33. import org.apache.hadoop.hive.ql.processors.CommandProcessorFactory;
  34. import org.apache.hadoop.hive.ql.session.SessionState;
  35. /**
  36. * HWISessionItem can be viewed as a wrapper for a Hive shell. With it the user
  37. * has a session on the web server rather then in a console window.
  38. *
  39. */
  40. public class HWISessionItem implements Runnable, Comparable<HWISessionItem> {
  41. protected static final Log l4j = LogFactory.getLog(HWISessionItem.class
  42. .getName());
  43. /** Represents the state a session item can be in. */
  44. public enum WebSessionItemStatus {
  45. NEW, READY, QUERY_SET, QUERY_RUNNING, DESTROY, KILL_QUERY
  46. };
  47. /** The Web Interface sessionName this is used to identify the session. */
  48. private final String sessionName;
  49. /**
  50. * Respresents the current status of the session. Used by components to
  51. * determine state. Operations will throw exceptions if the item is not in the
  52. * correct state.
  53. */
  54. private HWISessionItem.WebSessionItemStatus status;
  55. private CliSessionState ss;
  56. /** Standard out from the session will be written to this local file. */
  57. private String resultFile;
  58. /** Standard error from the session will be written to this local file. */
  59. private String errorFile;
  60. /**
  61. * The results from the Driver. This is used for storing the most result
  62. * results from the driver in memory.
  63. */
  64. private ArrayList<ArrayList<String>> resultBucket;
  65. /** Limits the resultBucket to be no greater then this size. */
  66. private int resultBucketMaxSize;
  67. /** List of queries that this item should/has operated on. */
  68. private List<String> queries;
  69. /** status code results of queries. */
  70. private List<Integer> queryRet;
  71. /** Reference to the configuration. */
  72. private HiveConf conf;
  73. /** User privileges. */
  74. private HWIAuth auth;
  75. public Thread runnable;
  76. /**
  77. * Threading SessionState issues require us to capture a reference to the hive
  78. * history file and store it.
  79. */
  80. private String historyFile;
  81. /**
  82. * Creates an instance of WebSessionItem, sets status to NEW.
  83. */
  84. public HWISessionItem(HWIAuth auth, String sessionName) {
  85. this.auth = auth;
  86. this.sessionName = sessionName;
  87. l4j.debug("HWISessionItem created");
  88. status = WebSessionItemStatus.NEW;
  89. queries = new ArrayList<String>();
  90. queryRet = new ArrayList<Integer>();
  91. resultBucket = new ArrayList<ArrayList<String>>();
  92. resultBucketMaxSize = 1000;
  93. runnable = new Thread(this);
  94. runnable.start();
  95. l4j.debug("Wait for NEW->READY transition");
  96. synchronized (runnable) {
  97. if (status != WebSessionItemStatus.READY) {
  98. try {
  99. runnable.wait();
  100. } catch (Exception ex) {
  101. }
  102. }
  103. }
  104. l4j.debug("NEW->READY transition complete");
  105. }
  106. /**
  107. * This is the initialization process that is carried out for each
  108. * SessionItem. The goal is to emulate the startup of CLIDriver.
  109. */
  110. private void itemInit() {
  111. l4j.debug("HWISessionItem itemInit start " + getSessionName());
  112. OptionsProcessor oproc = new OptionsProcessor();
  113. if (System.getProperty("hwi-args") != null) {
  114. String[] parts = System.getProperty("hwi-args").split("\\s+");
  115. if (!oproc.process_stage1(parts)) {
  116. }
  117. }
  118. SessionState.initHiveLog4j();
  119. conf = new HiveConf(SessionState.class);
  120. ss = new CliSessionState(conf);
  121. SessionState.start(ss);
  122. queries.add("set hadoop.job.ugi=" + auth.getUser() + ","
  123. + auth.getGroups()[0]);
  124. queries.add("set user.name=" + auth.getUser());
  125. /*
  126. * HiveHistoryFileName will not be accessible outside this thread. We must
  127. * capture this now.
  128. */
  129. historyFile = SessionState.get().getHiveHistory().getHistFileName();
  130. l4j.debug("HWISessionItem itemInit Complete " + getSessionName());
  131. status = WebSessionItemStatus.READY;
  132. synchronized (runnable) {
  133. runnable.notifyAll();
  134. }
  135. }
  136. /**
  137. * HWISessionItem is a Runnable instance. Calling this method will change the
  138. * status to QUERY_SET and notify(). The run method detects this and then
  139. * continues processing.
  140. */
  141. public void clientStart() throws HWIException {
  142. if (status == WebSessionItemStatus.QUERY_RUNNING) {
  143. throw new HWIException("Query already running");
  144. }
  145. status = WebSessionItemStatus.QUERY_SET;
  146. synchronized (runnable) {
  147. runnable.notifyAll();
  148. }
  149. l4j.debug(getSessionName() + " Query is set to start");
  150. }
  151. public void clientKill() throws HWIException {
  152. if (status != WebSessionItemStatus.QUERY_RUNNING) {
  153. throw new HWIException("Can not kill that which is not running.");
  154. }
  155. status = WebSessionItemStatus.KILL_QUERY;
  156. l4j.debug(getSessionName() + " Query is set to KILL_QUERY");
  157. }
  158. /** This method clears the private member variables. */
  159. public void clientRenew() throws HWIException {
  160. throwIfRunning();
  161. queries = new ArrayList<String>();
  162. queryRet = new ArrayList<Integer>();
  163. resultBucket = new ArrayList<ArrayList<String>>();
  164. resultFile = null;
  165. errorFile = null;
  166. // this.conf = null;
  167. // this.ss = null;
  168. status = WebSessionItemStatus.NEW;
  169. l4j.debug(getSessionName() + " Query is renewed to start");
  170. }
  171. /**
  172. * This is a callback style function used by the HiveSessionManager. The
  173. * HiveSessionManager notices this and attempts to stop the query.
  174. */
  175. protected void killIt() {
  176. l4j.debug(getSessionName() + " Attempting kill.");
  177. if (runnable != null) {
  178. try {
  179. runnable.join(1000);
  180. l4j.debug(getSessionName() + " Thread join complete");
  181. } catch (InterruptedException e) {
  182. l4j.error(getSessionName() + " killing session caused exception ", e);
  183. }
  184. }
  185. }
  186. /**
  187. * Helper function to get configuration variables.
  188. *
  189. * @param wanted
  190. * a ConfVar
  191. * @return Value of the configuration variable.
  192. */
  193. public String getHiveConfVar(HiveConf.ConfVars wanted) throws HWIException {
  194. String result = null;
  195. try {
  196. result = ss.getConf().getVar(wanted);
  197. } catch (Exception ex) {
  198. throw new HWIException(ex);
  199. }
  200. return result;
  201. }
  202. public String getHiveConfVar(String s) throws HWIException {
  203. String result = null;
  204. try {
  205. result = conf.get(s);
  206. } catch (Exception ex) {
  207. throw new HWIException(ex);
  208. }
  209. return result;
  210. }
  211. /*
  212. * mapred.job.tracker could be host:port or just local
  213. * mapred.job.tracker.http.address could be host:port or just host In some
  214. * configurations http.address is set to 0.0.0.0 we are combining the two
  215. * variables to provide a url to the job tracker WUI if it exists. If hadoop
  216. * chose the first available port for the JobTracker HTTP port will can not
  217. * determine it.
  218. */
  219. public String getJobTrackerURL(String jobid) throws HWIException {
  220. String jt = this.getHiveConfVar("mapred.job.tracker");
  221. String jth = this.getHiveConfVar("mapred.job.tracker.http.address");
  222. String[] jtparts = null;
  223. String[] jthttpParts = null;
  224. if (jt.equalsIgnoreCase("local")) {
  225. jtparts = new String[2];
  226. jtparts[0] = "local";
  227. jtparts[1] = "";
  228. } else {
  229. jtparts = jt.split(":");
  230. }
  231. if (jth.contains(":")) {
  232. jthttpParts = jth.split(":");
  233. } else {
  234. jthttpParts = new String[2];
  235. jthttpParts[0] = jth;
  236. jthttpParts[1] = "";
  237. }
  238. return jtparts[0] + ":" + jthttpParts[1] + "/jobdetails.jsp?jobid=" + jobid
  239. + "&refresh=30";
  240. }
  241. @Override
  242. /*
  243. * HWISessionItem uses a wait() notify() system. If the thread detects conf to
  244. * be null, control is transfered to initItem(). A status of QUERY_SET causes
  245. * control to transfer to the runQuery() method. DESTROY will cause the run
  246. * loop to end permanently.
  247. */
  248. public void run() {
  249. synchronized (runnable) {
  250. while (status != HWISessionItem.WebSessionItemStatus.DESTROY) {
  251. if (status == WebSessionItemStatus.NEW) {
  252. itemInit();
  253. }
  254. if (status == WebSessionItemStatus.QUERY_SET) {
  255. runQuery();
  256. }
  257. try {
  258. runnable.wait();
  259. } catch (InterruptedException e) {
  260. l4j.error("in wait() state ", e);
  261. }
  262. } // end while
  263. } // end sync
  264. } // end run
  265. /**
  266. * runQuery iterates the list of queries executing each query.
  267. */
  268. public void runQuery() {
  269. FileOutputStream fos = null;
  270. if (getResultFile() != null) {
  271. try {
  272. fos = new FileOutputStream(new File(resultFile));
  273. ss.out = new PrintStream(fos, true, "UTF-8");
  274. } catch (java.io.FileNotFoundException fex) {
  275. l4j.error(getSessionName() + " opening resultfile " + resultFile, fex);
  276. } catch (java.io.UnsupportedEncodingException uex) {
  277. l4j.error(getSessionName() + " opening resultfile " + resultFile, uex);
  278. }
  279. } else {
  280. l4j.debug(getSessionName() + " Output file was not specified");
  281. }
  282. l4j.debug(getSessionName() + " state is now QUERY_RUNNING.");
  283. status = WebSessionItemStatus.QUERY_RUNNING;
  284. // expect one return per query
  285. queryRet = new ArrayList<Integer>(queries.size());
  286. for (int i = 0; i < queries.size(); i++) {
  287. String cmd = queries.get(i);
  288. String cmd_trimmed = cmd.trim();
  289. String[] tokens = cmd_trimmed.split("\\s+");
  290. String cmd_1 = cmd_trimmed.substring(tokens[0].length()).trim();
  291. CommandProcessor proc = CommandProcessorFactory.get(tokens[0]);
  292. if (proc != null) {
  293. if (proc instanceof Driver) {
  294. Driver qp = (Driver) proc;
  295. queryRet.add(new Integer(qp.run(cmd).getResponseCode()));
  296. ArrayList<String> res = new ArrayList<String>();
  297. try {
  298. while (qp.getResults(res)) {
  299. ArrayList<String> resCopy = new ArrayList<String>();
  300. resCopy.addAll(res);
  301. resultBucket.add(resCopy);
  302. if (resultBucket.size() > resultBucketMaxSize) {
  303. resultBucket.remove(0);
  304. }
  305. for (String row : res) {
  306. if (ss != null) {
  307. if (ss.out != null) {
  308. ss.out.println(row);
  309. }
  310. } else {
  311. throw new RuntimeException("ss was null");
  312. }
  313. }
  314. res.clear();
  315. }
  316. } catch (IOException ex) {
  317. l4j.error(getSessionName() + " getting results " + getResultFile()
  318. + " caused exception.", ex);
  319. }
  320. qp.close();
  321. } else {
  322. queryRet.add(new Integer(proc.run(cmd_1).getResponseCode()));
  323. }
  324. } else {
  325. // processor was null
  326. l4j.error(getSessionName()
  327. + " query processor was not found for query " + cmd);
  328. }
  329. } // end for
  330. // cleanup
  331. try {
  332. if (fos != null) {
  333. fos.close();
  334. }
  335. } catch (IOException ex) {
  336. l4j.error(getSessionName() + " closing result file " + getResultFile()
  337. + " caused exception.", ex);
  338. }
  339. status = WebSessionItemStatus.READY;
  340. l4j.debug(getSessionName() + " state is now READY");
  341. synchronized (runnable) {
  342. runnable.notifyAll();
  343. }
  344. }
  345. /**
  346. * This is a chained call to SessionState.setIsSilent(). Use this if you do
  347. * not want the result file to have information status
  348. */
  349. public void setSSIsSilent(boolean silent) throws HWIException {
  350. if (ss == null) {
  351. throw new HWIException("Session State is null");
  352. }
  353. ss.setIsSilent(silent);
  354. }
  355. /**
  356. * This is a chained call to SessionState.getIsSilent().
  357. */
  358. public boolean getSSIsSilent() throws HWIException {
  359. if (ss == null) {
  360. throw new HWIException("Session State is null");
  361. }
  362. return ss.getIsSilent();
  363. }
  364. /** to support sorting/Set. */
  365. public int compareTo(HWISessionItem other) {
  366. if (other == null) {
  367. return -1;
  368. }
  369. return getSessionName().compareTo(other.getSessionName());
  370. }
  371. /**
  372. *
  373. * @return the HiveHistoryViewer for the session
  374. * @throws HWIException
  375. */
  376. public HiveHistoryViewer getHistoryViewer() throws HWIException {
  377. if (ss == null) {
  378. throw new HWIException("Session state was null");
  379. }
  380. /*
  381. * we can not call this.ss.get().getHiveHistory().getHistFileName() directly
  382. * as this call is made from a a Jetty thread and will return null
  383. */
  384. HiveHistoryViewer hv = new HiveHistoryViewer(historyFile);
  385. return hv;
  386. }
  387. /**
  388. * Uses the sessionName property to compare to sessions.
  389. *
  390. * @return true if sessionNames are equal false otherwise
  391. */
  392. @Override
  393. public boolean equals(Object other) {
  394. if (other == null) {
  395. return false;
  396. }
  397. if (!(other instanceof HWISessionItem)) {
  398. return false;
  399. }
  400. HWISessionItem o = (HWISessionItem) other;
  401. if (getSessionName().equals(o.getSessionName())) {
  402. return true;
  403. } else {
  404. return false;
  405. }
  406. }
  407. public String getResultFile() {
  408. return resultFile;
  409. }
  410. public void setResultFile(String resultFile) {
  411. this.resultFile = resultFile;
  412. }
  413. /**
  414. * The session name is an identifier to recognize the session.
  415. *
  416. * @return the session's name
  417. */
  418. public String getSessionName() {
  419. return sessionName;
  420. }
  421. /**
  422. * Used to represent to the user and other components what state the
  423. * HWISessionItem is in. Certain commands can only be run when the application
  424. * is in certain states.
  425. *
  426. * @return the current status of the session
  427. */
  428. public WebSessionItemStatus getStatus() {
  429. return status;
  430. }
  431. /**
  432. * Currently unused.
  433. *
  434. * @return a String with the full path to the error file.
  435. */
  436. public String getErrorFile() {
  437. return errorFile;
  438. }
  439. /**
  440. * Currently unused.
  441. *
  442. * @param errorFile
  443. * the full path to the file for results.
  444. */
  445. public void setErrorFile(String errorFile) {
  446. this.errorFile = errorFile;
  447. }
  448. /**
  449. * @return the auth
  450. */
  451. public HWIAuth getAuth() {
  452. return auth;
  453. }
  454. /**
  455. * @param auth
  456. * the auth to set
  457. */
  458. protected void setAuth(HWIAuth auth) {
  459. this.auth = auth;
  460. }
  461. /** Returns an unmodifiable list of queries. */
  462. public List<String> getQueries() {
  463. return java.util.Collections.unmodifiableList(queries);
  464. }
  465. /**
  466. * Adds a new query to the execution list.
  467. *
  468. * @param query
  469. * query to be added to the list
  470. */
  471. public void addQuery(String query) throws HWIException {
  472. throwIfRunning();
  473. queries.add(query);
  474. }
  475. /**
  476. * Removes a query from the execution list.
  477. *
  478. * @param item
  479. * the 0 based index of the item to be removed
  480. */
  481. public void removeQuery(int item) throws HWIException {
  482. throwIfRunning();
  483. queries.remove(item);
  484. }
  485. public void clearQueries() throws HWIException {
  486. throwIfRunning();
  487. queries.clear();
  488. }
  489. /** returns the value for resultBucketMaxSize. */
  490. public int getResultBucketMaxSize() {
  491. return resultBucketMaxSize;
  492. }
  493. /**
  494. * sets the value for resultBucketMaxSize.
  495. *
  496. * @param size
  497. * the new size
  498. */
  499. public void setResultBucketMaxSize(int size) {
  500. resultBucketMaxSize = size;
  501. }
  502. /** gets the value for resultBucket. */
  503. public ArrayList<ArrayList<String>> getResultBucket() {
  504. return resultBucket;
  505. }
  506. /**
  507. * The HWISessionItem stores the result of each query in an array.
  508. *
  509. * @return unmodifiable list of return codes
  510. */
  511. public List<Integer> getQueryRet() {
  512. return java.util.Collections.unmodifiableList(queryRet);
  513. }
  514. /**
  515. * If the ItemStatus is QueryRunning most of the configuration is in a read
  516. * only state.
  517. */
  518. private void throwIfRunning() throws HWIException {
  519. if (status == WebSessionItemStatus.QUERY_RUNNING) {
  520. throw new HWIException("Query already running");
  521. }
  522. }
  523. }