You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@livy.apache.org by js...@apache.org on 2017/06/27 06:38:42 UTC

[01/50] [abbrv] incubator-livy git commit: LIVY-183. Deploy livy-main pom to maven repo.

Repository: incubator-livy
Updated Branches:
  refs/heads/branch-0.2 [created] 491de2126
  refs/heads/branch-0.3 [created] 0afee2301
  refs/heads/gh-pages [created] fd20a236a
  refs/heads/master [created] 9ae24d087
  refs/heads/rel-0.2.0-refresh [created] e9256c27f
  refs/heads/revert-237-LIVY-255 [created] 2da435ad1
Updated Tags:  refs/tags/v0.2.0 [created] dc3cbcad4
  refs/tags/v0.3.0 [created] e36b6f57c


LIVY-183. Deploy livy-main pom to maven repo.

This requires changing the default value of "skipDeploy" since it
cannot be overridden just for the root pom. Ah, maven.

Closes #160

(cherry picked from commit a5a09746c162c0e3ae5fb2bf6f53023f92722f35)


Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/e9256c27
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/e9256c27
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/e9256c27

Branch: refs/heads/rel-0.2.0-refresh
Commit: e9256c27f08af5616a38f7d8a8044c6dac83ce98
Parents: dc3cbca
Author: Marcelo Vanzin <va...@cloudera.com>
Authored: Tue Jul 5 10:26:23 2016 -0700
Committer: Marcelo Vanzin <va...@cloudera.com>
Committed: Tue Jul 5 13:00:18 2016 -0700

----------------------------------------------------------------------
 api/pom.xml              | 1 -
 assembly/pom.xml         | 1 +
 client-common/pom.xml    | 4 ----
 client-http/pom.xml      | 4 ----
 core/pom.xml             | 4 ++++
 integration-test/pom.xml | 1 +
 pom.xml                  | 6 +++---
 repl/pom.xml             | 4 ++++
 rsc/pom.xml              | 1 -
 server/pom.xml           | 4 ++++
 test-lib/pom.xml         | 4 ++++
 11 files changed, 21 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e9256c27/api/pom.xml
----------------------------------------------------------------------
diff --git a/api/pom.xml b/api/pom.xml
index e61bb96..af45309 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -30,7 +30,6 @@
 
   <properties>
     <copyright.header>${asf.copyright.header}</copyright.header>
-    <skipDeploy>false</skipDeploy>
   </properties>
 
   <dependencies>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e9256c27/assembly/pom.xml
----------------------------------------------------------------------
diff --git a/assembly/pom.xml b/assembly/pom.xml
index 44786d1..a483843 100644
--- a/assembly/pom.xml
+++ b/assembly/pom.xml
@@ -32,6 +32,7 @@
   <properties>
     <assembly.name>livy-server-${project.version}</assembly.name>
     <assembly.format>zip</assembly.format>
+    <skipDeploy>true</skipDeploy>
   </properties>
 
   <profiles>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e9256c27/client-common/pom.xml
----------------------------------------------------------------------
diff --git a/client-common/pom.xml b/client-common/pom.xml
index 13df3b1..d985e7e 100644
--- a/client-common/pom.xml
+++ b/client-common/pom.xml
@@ -29,10 +29,6 @@
   <version>0.2.0</version>
   <packaging>jar</packaging>
 
-  <properties>
-    <skipDeploy>false</skipDeploy>
-  </properties>
-
   <dependencies>
     <dependency>
       <groupId>com.cloudera.livy</groupId>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e9256c27/client-http/pom.xml
----------------------------------------------------------------------
diff --git a/client-http/pom.xml b/client-http/pom.xml
index f60830e..208f91b 100644
--- a/client-http/pom.xml
+++ b/client-http/pom.xml
@@ -29,10 +29,6 @@
   <version>0.2.0</version>
   <packaging>jar</packaging>
 
-  <properties>
-    <skipDeploy>false</skipDeploy>
-  </properties>
-
   <dependencies>
     <dependency>
       <groupId>com.cloudera.livy</groupId>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e9256c27/core/pom.xml
----------------------------------------------------------------------
diff --git a/core/pom.xml b/core/pom.xml
index ba57ac4..5a9294c 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -31,6 +31,10 @@
   <version>0.2.0</version>
   <packaging>jar</packaging>
 
+  <properties>
+    <skipDeploy>true</skipDeploy>
+  </properties>
+
   <dependencies>
     <dependency>
       <groupId>com.cloudera.livy</groupId>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e9256c27/integration-test/pom.xml
----------------------------------------------------------------------
diff --git a/integration-test/pom.xml b/integration-test/pom.xml
index f773681..a3b32ad 100644
--- a/integration-test/pom.xml
+++ b/integration-test/pom.xml
@@ -39,6 +39,7 @@
     -->
     <cluster.spec>default</cluster.spec>
     <skipITs>${skipTests}</skipITs>
+    <skipDeploy>true</skipDeploy>
   </properties>
 
   <dependencies>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e9256c27/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 9bd3fbd..e590e52 100644
--- a/pom.xml
+++ b/pom.xml
@@ -78,10 +78,10 @@
     -->
 
     <!--
-      By default artifacts are not deployed. Artifacts that should be deployed to a maven
-      repo should override the "skipDeploy" property in their pom.
+      Artifacts that should not be deployed to a maven repo should override the "skipDeploy"
+      property in their pom.
     -->
-    <skipDeploy>true</skipDeploy>
+    <skipDeploy>false</skipDeploy>
 
     <asf.copyright.header><![CDATA[/*
  * Licensed to the Apache Software Foundation (ASF) under one or more

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e9256c27/repl/pom.xml
----------------------------------------------------------------------
diff --git a/repl/pom.xml b/repl/pom.xml
index cc62a44..b7cf52d 100644
--- a/repl/pom.xml
+++ b/repl/pom.xml
@@ -31,6 +31,10 @@
     <version>0.2.0</version>
     <packaging>jar</packaging>
 
+    <properties>
+        <skipDeploy>true</skipDeploy>
+    </properties>
+
     <dependencies>
 
         <dependency>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e9256c27/rsc/pom.xml
----------------------------------------------------------------------
diff --git a/rsc/pom.xml b/rsc/pom.xml
index 847f420..960425d 100644
--- a/rsc/pom.xml
+++ b/rsc/pom.xml
@@ -31,7 +31,6 @@
 
   <properties>
     <copyright.header>${asf.copyright.header}</copyright.header>
-    <skipDeploy>false</skipDeploy>
   </properties>
 
   <dependencies>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e9256c27/server/pom.xml
----------------------------------------------------------------------
diff --git a/server/pom.xml b/server/pom.xml
index 339d81d..248d9e4 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -31,6 +31,10 @@
     <version>0.2.0</version>
     <packaging>jar</packaging>
 
+    <properties>
+        <skipDeploy>true</skipDeploy>
+    </properties>
+
     <dependencies>
 
         <dependency>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e9256c27/test-lib/pom.xml
----------------------------------------------------------------------
diff --git a/test-lib/pom.xml b/test-lib/pom.xml
index edfd820..ac91662 100644
--- a/test-lib/pom.xml
+++ b/test-lib/pom.xml
@@ -29,6 +29,10 @@
   <version>0.2.0</version>
   <packaging>jar</packaging>
 
+  <properties>
+    <skipDeploy>true</skipDeploy>
+  </properties>
+
   <dependencies>
     <dependency>
       <groupId>com.cloudera.livy</groupId>


[20/50] [abbrv] incubator-livy git commit: LIVY-320. Livy python-api client test failing. (#298)

Posted by js...@apache.org.
LIVY-320. Livy python-api client test failing. (#298)

Specified fields for client test. Travis CI looks to be defaulted to python 2.7, so it never came across this issue.

Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/6bfe1774
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/6bfe1774
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/6bfe1774

Branch: refs/heads/master
Commit: 6bfe17749c25da2145aac9eedbc6bedb1a4d33eb
Parents: a72bbff
Author: Alan Chin <ak...@us.ibm.com>
Authored: Tue Feb 21 17:30:12 2017 -0800
Committer: Alex Man <tc...@gmail.com>
Committed: Tue Feb 21 17:30:12 2017 -0800

----------------------------------------------------------------------
 python-api/src/test/python/livy-tests/client_test.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/6bfe1774/python-api/src/test/python/livy-tests/client_test.py
----------------------------------------------------------------------
diff --git a/python-api/src/test/python/livy-tests/client_test.py b/python-api/src/test/python/livy-tests/client_test.py
index bb1dbc5..bab958e 100644
--- a/python-api/src/test/python/livy-tests/client_test.py
+++ b/python-api/src/test/python/livy-tests/client_test.py
@@ -25,7 +25,7 @@ from livy.client import HttpClient
 
 session_id = 0
 job_id = 1
-base_uri = 'http://{}:{}'.format(socket.gethostname(), 8998)
+base_uri = 'http://{0}:{1}'.format(socket.gethostname(), 8998)
 client_test = None
 invoked_queued_callback = False
 invoked_running_callback = False


[10/50] [abbrv] incubator-livy git commit: LIVY-310. Kinit should be called before doing recovery check. (#285)

Posted by js...@apache.org.
LIVY-310. Kinit should be called before doing recovery check. (#285)



Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/807036af
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/807036af
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/807036af

Branch: refs/heads/master
Commit: 807036afe2d5aa8ff64ffb8f70632e993b626fcb
Parents: 9575d8f
Author: Saisai Shao <sa...@gmail.com>
Authored: Mon Feb 13 10:28:06 2017 +0800
Committer: Alex Man <tc...@gmail.com>
Committed: Sun Feb 12 21:28:06 2017 -0500

----------------------------------------------------------------------
 .../com/cloudera/livy/server/LivyServer.scala   | 55 +++++++++++---------
 1 file changed, 29 insertions(+), 26 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/807036af/server/src/main/scala/com/cloudera/livy/server/LivyServer.scala
----------------------------------------------------------------------
diff --git a/server/src/main/scala/com/cloudera/livy/server/LivyServer.scala b/server/src/main/scala/com/cloudera/livy/server/LivyServer.scala
index 71d7bea..938f3a6 100644
--- a/server/src/main/scala/com/cloudera/livy/server/LivyServer.scala
+++ b/server/src/main/scala/com/cloudera/livy/server/LivyServer.scala
@@ -25,7 +25,7 @@ import javax.servlet._
 import scala.concurrent.ExecutionContext.Implicits.global
 import scala.concurrent.Future
 
-import org.apache.hadoop.security.SecurityUtil
+import org.apache.hadoop.security.{SecurityUtil, UserGroupInformation}
 import org.apache.hadoop.security.authentication.server._
 import org.eclipse.jetty.servlet.FilterHolder
 import org.scalatra.metrics.MetricsBootstrap
@@ -86,6 +86,33 @@ class LivyServer extends Logging {
     livyConf.set(LIVY_SPARK_SCALA_VERSION.key,
       sparkScalaVersion(formattedSparkVersion, scalaVersionFromSparkSubmit, livyConf))
 
+    if (UserGroupInformation.isSecurityEnabled) {
+      // If Hadoop security is enabled, run kinit periodically. runKinit() should be called
+      // before any Hadoop operation, otherwise Kerberos exception will be thrown.
+      executor = Executors.newScheduledThreadPool(1,
+        new ThreadFactory() {
+          override def newThread(r: Runnable): Thread = {
+            val thread = new Thread(r)
+            thread.setName("kinit-thread")
+            thread.setDaemon(true)
+            thread
+          }
+        }
+      )
+      val launch_keytab = livyConf.get(LAUNCH_KERBEROS_KEYTAB)
+      val launch_principal = SecurityUtil.getServerPrincipal(
+        livyConf.get(LAUNCH_KERBEROS_PRINCIPAL), server.host)
+      require(launch_keytab != null,
+        s"Kerberos requires ${LAUNCH_KERBEROS_KEYTAB.key} to be provided.")
+      require(launch_principal != null,
+        s"Kerberos requires ${LAUNCH_KERBEROS_PRINCIPAL.key} to be provided.")
+      if (!runKinit(launch_keytab, launch_principal)) {
+        error("Failed to run kinit, stopping the server.")
+        sys.exit(1)
+      }
+      startKinitThread(launch_keytab, launch_principal)
+    }
+
     testRecovery(livyConf)
 
     // Initialize YarnClient ASAP to save time.
@@ -171,31 +198,7 @@ class LivyServer extends Logging {
         server.context.addFilter(holder, "/*", EnumSet.allOf(classOf[DispatcherType]))
         info(s"SPNEGO auth enabled (principal = $principal)")
 
-        // run kinit periodically
-        executor = Executors.newScheduledThreadPool(1,
-          new ThreadFactory() {
-            override def newThread(r: Runnable): Thread = {
-              val thread = new Thread(r)
-              thread.setName("kinit-thread")
-              thread.setDaemon(true)
-              thread
-            }
-          }
-        )
-        val launch_keytab = livyConf.get(LAUNCH_KERBEROS_KEYTAB)
-        val launch_principal = SecurityUtil.getServerPrincipal(
-          livyConf.get(LAUNCH_KERBEROS_PRINCIPAL), server.host)
-        require(launch_keytab != null,
-          s"Kerberos requires ${LAUNCH_KERBEROS_KEYTAB.key} to be provided.")
-        require(launch_principal != null,
-          s"Kerberos requires ${LAUNCH_KERBEROS_PRINCIPAL.key} to be provided.")
-        if (!runKinit(launch_keytab, launch_principal)) {
-          error("Failed to run kinit, stopping the server.")
-          sys.exit(1)
-        }
-        startKinitThread(launch_keytab, launch_principal)
-
-      case null =>
+     case null =>
         // Nothing to do.
 
       case other =>


[39/50] [abbrv] incubator-livy git commit: Fix two SparkR test issue regarding to different versions of R (#322)

Posted by js...@apache.org.
Fix two SparkR test issue regarding to different versions of R (#322)

Change-Id: Id301749a5e678666df771aa8f02cce149b56ff93

Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/f5ef4898
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/f5ef4898
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/f5ef4898

Branch: refs/heads/master
Commit: f5ef489816bb55c9ee3a9008c82e9015dbe58478
Parents: e8c3e06
Author: Saisai Shao <sa...@gmail.com>
Authored: Fri Apr 28 14:45:23 2017 +0800
Committer: Jeff Zhang <zj...@gmail.com>
Committed: Fri Apr 28 14:45:23 2017 +0800

----------------------------------------------------------------------
 .../cloudera/livy/repl/SparkRInterpreterSpec.scala    |  8 ++++----
 .../com/cloudera/livy/repl/SparkRSessionSpec.scala    | 14 +++++---------
 2 files changed, 9 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/f5ef4898/repl/src/test/scala/com/cloudera/livy/repl/SparkRInterpreterSpec.scala
----------------------------------------------------------------------
diff --git a/repl/src/test/scala/com/cloudera/livy/repl/SparkRInterpreterSpec.scala b/repl/src/test/scala/com/cloudera/livy/repl/SparkRInterpreterSpec.scala
index f4f709f..a513867 100644
--- a/repl/src/test/scala/com/cloudera/livy/repl/SparkRInterpreterSpec.scala
+++ b/repl/src/test/scala/com/cloudera/livy/repl/SparkRInterpreterSpec.scala
@@ -84,10 +84,10 @@ class SparkRInterpreterSpec extends BaseInterpreterSpec {
 
   it should "report an error if accessing an unknown variable" in withInterpreter { interpreter =>
     val response = interpreter.execute("x")
-    response should equal(Interpreter.ExecuteError(
-      "Error",
-      """[1] "Error in eval(expr, envir, enclos): object 'x' not found""""
-    ))
+    assert(response.isInstanceOf[Interpreter.ExecuteError])
+    val errorResponse = response.asInstanceOf[Interpreter.ExecuteError]
+    errorResponse.ename should be ("Error")
+    assert(errorResponse.evalue.contains("object 'x' not found"))
   }
 
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/f5ef4898/repl/src/test/scala/com/cloudera/livy/repl/SparkRSessionSpec.scala
----------------------------------------------------------------------
diff --git a/repl/src/test/scala/com/cloudera/livy/repl/SparkRSessionSpec.scala b/repl/src/test/scala/com/cloudera/livy/repl/SparkRSessionSpec.scala
index 4bbf87c..a6091d0 100644
--- a/repl/src/test/scala/com/cloudera/livy/repl/SparkRSessionSpec.scala
+++ b/repl/src/test/scala/com/cloudera/livy/repl/SparkRSessionSpec.scala
@@ -132,15 +132,11 @@ class SparkRSessionSpec extends BaseSessionSpec {
     statement.id should equal (0)
 
     val result = parse(statement.output)
-    val expectedResult = Extraction.decompose(Map(
-      "status" -> "error",
-      "execution_count" -> 0,
-      "ename" -> "Error",
-      "evalue" -> "[1] \"Error in eval(expr, envir, enclos): object 'x' not found\"",
-      "traceback" -> List()
-    ))
-
-    result should equal (expectedResult)
+    (result \ "status").extract[String] should be ("error")
+    (result \ "execution_count").extract[Int] should be (0)
+    (result \ "ename").extract[String] should be ("Error")
+    assert((result \ "evalue").extract[String].contains("object 'x' not found"))
+    (result \ "traceback").extract[List[String]] should be (List())
   }
 
 }


[15/50] [abbrv] incubator-livy git commit: Minor. Relax the permission constraint of recovery state store folder. (#291)

Posted by js...@apache.org.
Minor. Relax the permission constraint of recovery state store folder. (#291)

Emit warnings instead of throwing fatal errors.

Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/f7c434c8
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/f7c434c8
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/f7c434c8

Branch: refs/heads/master
Commit: f7c434c87bd7ea6fd3a410669a3160c2d1c463f9
Parents: b872978
Author: Saisai Shao <sa...@gmail.com>
Authored: Thu Feb 16 06:04:12 2017 +0800
Committer: Alex Man <tc...@gmail.com>
Committed: Wed Feb 15 17:04:12 2017 -0500

----------------------------------------------------------------------
 .../livy/server/recovery/FileSystemStateStore.scala       | 10 ++++++----
 .../livy/server/recovery/FileSystemStateStoreSpec.scala   |  6 +++---
 2 files changed, 9 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/f7c434c8/server/src/main/scala/com/cloudera/livy/server/recovery/FileSystemStateStore.scala
----------------------------------------------------------------------
diff --git a/server/src/main/scala/com/cloudera/livy/server/recovery/FileSystemStateStore.scala b/server/src/main/scala/com/cloudera/livy/server/recovery/FileSystemStateStore.scala
index 2008ef7..e4edc51 100644
--- a/server/src/main/scala/com/cloudera/livy/server/recovery/FileSystemStateStore.scala
+++ b/server/src/main/scala/com/cloudera/livy/server/recovery/FileSystemStateStore.scala
@@ -72,10 +72,12 @@ class FileSystemStateStore(
     val fileStatus = fileContext.getFileStatus(absPath("."))
     require(fileStatus.getPermission.getUserAction() == FsAction.ALL,
       s"Livy doesn't have permission to access state store: $fsUri.")
-    require(fileStatus.getPermission.getGroupAction() == FsAction.NONE,
-      s"Group users have permission to access state store: $fsUri. This is insecure.")
-    require(fileStatus.getPermission.getOtherAction() == FsAction.NONE,
-      s"Other users have permission to access state store: $fsUri. This is insecure.")
+    if (fileStatus.getPermission.getGroupAction != FsAction.NONE) {
+      warn(s"Group users have permission to access state store: $fsUri. This is insecure.")
+    }
+    if (fileStatus.getPermission.getOtherAction != FsAction.NONE) {
+      warn(s"Other users have permission to access state store: $fsUri. This is in secure.")
+    }
   }
 
   override def set(key: String, value: Object): Unit = {

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/f7c434c8/server/src/test/scala/com/cloudera/livy/server/recovery/FileSystemStateStoreSpec.scala
----------------------------------------------------------------------
diff --git a/server/src/test/scala/com/cloudera/livy/server/recovery/FileSystemStateStoreSpec.scala b/server/src/test/scala/com/cloudera/livy/server/recovery/FileSystemStateStoreSpec.scala
index 935911b..2b90a52 100644
--- a/server/src/test/scala/com/cloudera/livy/server/recovery/FileSystemStateStoreSpec.scala
+++ b/server/src/test/scala/com/cloudera/livy/server/recovery/FileSystemStateStoreSpec.scala
@@ -82,9 +82,9 @@ class FileSystemStateStoreSpec extends FunSpec with LivyBaseUnitTestSuite {
       }
       test("600")
       test("400")
-      test("777")
-      test("770")
-      test("707")
+      test("677")
+      test("670")
+      test("607")
     }
 
     it("set should write with an intermediate file") {


[45/50] [abbrv] incubator-livy git commit: LIVY-342. Create Livy UI: Create Web UI Servlet and All Sessions Page (#319)

Posted by js...@apache.org.
LIVY-342. Create Livy UI: Create Web UI Servlet and All Sessions Page (#319)

* squash of original ui poc code

* Initial All Sessions Page code

* finished all-sessions page and cleaned up code

* Moved metrics and added ui redirect, added no sessions message

* added conf to template, cleaned up missed code from last commit

* UI enable/disable no long configureable, always on

* nit

* Address review and fixed some html/css errors

* Fixed ITs and added a redirect to metrics when ui is disabled


Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/61b206e0
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/61b206e0
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/61b206e0

Branch: refs/heads/master
Commit: 61b206e0adc0b3efa52ef91283238c85cbe117fd
Parents: 0ddcaf6
Author: Alex Bozarth <aj...@us.ibm.com>
Authored: Tue May 9 14:02:22 2017 -0700
Committer: Jeff Zhang <zj...@gmail.com>
Committed: Tue May 9 14:02:22 2017 -0700

----------------------------------------------------------------------
 conf/livy.conf.template                         |   3 +
 .../livy/test/framework/MiniCluster.scala       |   2 +-
 server/pom.xml                                  |   3 +
 .../livy/server/ui/static/all-sessions.js       |  79 +++++++++++++++++++
 .../livy/server/ui/static/batches-table.html    |  37 +++++++++
 .../livy/server/ui/static/bootstrap.min.css     |  14 ++++
 .../livy/server/ui/static/bootstrap.min.js      |   7 ++
 .../livy/server/ui/static/jquery-3.2.1.min.js   |   4 +
 .../livy/server/ui/static/livy-mini-logo.png    | Bin 0 -> 1121 bytes
 .../cloudera/livy/server/ui/static/livy-ui.css  |  21 +++++
 .../livy/server/ui/static/sessions-table.html   |  53 +++++++++++++
 .../main/scala/com/cloudera/livy/LivyConf.scala |   2 +
 .../com/cloudera/livy/server/LivyServer.scala   |  27 ++++++-
 .../com/cloudera/livy/server/ui/UIServlet.scala |  76 ++++++++++++++++++
 14 files changed, 326 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/61b206e0/conf/livy.conf.template
----------------------------------------------------------------------
diff --git a/conf/livy.conf.template b/conf/livy.conf.template
index dd2f054..8bef995 100644
--- a/conf/livy.conf.template
+++ b/conf/livy.conf.template
@@ -97,3 +97,6 @@
 #
 # Days to keep Livy server request logs.
 # livy.server.request-log-retain.days = 5
+
+# If the Livy Web UI should be included in the Livy Server. Enabled by default.
+# livy.ui.enabled = true

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/61b206e0/integration-test/src/main/scala/com/cloudera/livy/test/framework/MiniCluster.scala
----------------------------------------------------------------------
diff --git a/integration-test/src/main/scala/com/cloudera/livy/test/framework/MiniCluster.scala b/integration-test/src/main/scala/com/cloudera/livy/test/framework/MiniCluster.scala
index 6aa02f1..973d7d7 100644
--- a/integration-test/src/main/scala/com/cloudera/livy/test/framework/MiniCluster.scala
+++ b/integration-test/src/main/scala/com/cloudera/livy/test/framework/MiniCluster.scala
@@ -302,7 +302,7 @@ class MiniCluster(config: Map[String, String]) extends Cluster with MiniClusterU
     // Wait until Livy server responds.
     val httpClient = new AsyncHttpClient()
     eventually(timeout(30 seconds), interval(1 second)) {
-      val res = httpClient.prepareGet(livyUrl).execute().get()
+      val res = httpClient.prepareGet(livyUrl + "/metrics").execute().get()
       assert(res.getStatusCode() == HttpServletResponse.SC_OK)
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/61b206e0/server/pom.xml
----------------------------------------------------------------------
diff --git a/server/pom.xml b/server/pom.xml
index 6846be9..3bca3fd 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -219,6 +219,9 @@
   <build>
     <resources>
       <resource>
+        <directory>${project.basedir}/src/main/resources</directory>
+      </resource>
+      <resource>
         <!-- Include the properties file to provide the build information. -->
         <directory>${project.build.directory}/extra-resources</directory>
         <filtering>true</filtering>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/61b206e0/server/src/main/resources/com/cloudera/livy/server/ui/static/all-sessions.js
----------------------------------------------------------------------
diff --git a/server/src/main/resources/com/cloudera/livy/server/ui/static/all-sessions.js b/server/src/main/resources/com/cloudera/livy/server/ui/static/all-sessions.js
new file mode 100644
index 0000000..b0c6904
--- /dev/null
+++ b/server/src/main/resources/com/cloudera/livy/server/ui/static/all-sessions.js
@@ -0,0 +1,79 @@
+/*
+ * Licensed to Cloudera, Inc. under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  Cloudera, Inc. 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.
+ */
+
+function tdWrap(str) {
+  return "<td>" + str + "</td>";
+}
+
+function loadSessionsTable(sessions) {
+  $.each(sessions, function(index, session) {
+    $("#interactive-sessions .sessions-table-body").append(
+      "<tr>" +
+        tdWrap(session.id) +
+        tdWrap(session.appId) +
+        tdWrap(session.owner) +
+        tdWrap(session.proxyUser) +
+        tdWrap(session.kind) +
+        tdWrap(session.state) +
+       "</tr>"
+    );
+  });
+}
+
+function loadBatchesTable(sessions) {
+  $.each(sessions, function(index, session) {
+    $("#batches .sessions-table-body").append(
+      "<tr>" +
+        tdWrap(session.id) +
+        tdWrap(session.appId) +
+        tdWrap(session.state) +
+       "</tr>"
+    );
+  });
+}
+
+var numSessions = 0;
+var numBatches = 0;
+
+$(document).ready(function () {
+  var sessionsReq = $.getJSON(location.origin + "/sessions", function(response) {
+    if (response && response.total > 0) {
+      $("#interactive-sessions").load("/static/sessions-table.html .sessions-template", function() {
+        loadSessionsTable(response.sessions);
+        $('#interactive-sessions [data-toggle="tooltip"]').tooltip();
+      });
+    }
+    numSessions = response.total;
+  });
+
+  var batchesReq = $.getJSON(location.origin + "/batches", function(response) {
+    if (response && response.total > 0) {
+      $("#batches").load("/static/batches-table.html .sessions-template", function() {
+        loadBatchesTable(response.sessions);
+        $('#batches [data-toggle="tooltip"]').tooltip();
+      });
+    }
+    numBatches = response.total;
+  });
+
+  $.when(sessionsReq, batchesReq).done(function () {
+    if (numSessions + numBatches == 0) {
+      $("#all-sessions").append('<h4>No Sessions or Batches have been created yet.</h4>');
+    }
+  });
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/61b206e0/server/src/main/resources/com/cloudera/livy/server/ui/static/batches-table.html
----------------------------------------------------------------------
diff --git a/server/src/main/resources/com/cloudera/livy/server/ui/static/batches-table.html b/server/src/main/resources/com/cloudera/livy/server/ui/static/batches-table.html
new file mode 100644
index 0000000..45efbd6
--- /dev/null
+++ b/server/src/main/resources/com/cloudera/livy/server/ui/static/batches-table.html
@@ -0,0 +1,37 @@
+<!--
+ Licensed to Cloudera, Inc. under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  Cloudera, Inc. 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.
+-->
+
+<h4 id="batches-header" class="sessions-template">Batch Sessions</h4>
+
+<table class="table table-striped sessions-table sessions-template">
+  <thead class="sessions-table-head">
+  <tr>
+    <th>Batch Id</th>
+    <th>Application Id</th>
+    <th>
+      <span data-toggle="tooltip"
+            title="Session State (not_started, starting, idle, busy,
+            shutting_down, error, dead, success)">
+        State
+      </span>
+    </th>
+  </tr>
+  </thead>
+  <tbody class="sessions-table-body">
+  </tbody>
+</table>
\ No newline at end of file


[35/50] [abbrv] incubator-livy git commit: LIVY-323. Fixed livy-repl doesn't start with a lot of spark packages. (#312)

Posted by js...@apache.org.
LIVY-323. Fixed livy-repl doesn't start with a lot of spark packages. (#312)

Some Spark packages are depending on scala-reflect 2.11.0 and it conflicts with Spark's scala version 2.11.8.
This's not Livy's fault actually but doesn't hurt to make Livy more fault tolerant.
Since the scala-reflect jar with the correct version must already be in CLASSPATH, fixed livy-repl to not load user supplied scala-reflect jars.

Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/07f6072f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/07f6072f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/07f6072f

Branch: refs/heads/master
Commit: 07f6072f9d90ec970a1f9fbaccf0452f3a783538
Parents: 221aa9c
Author: Alex Man <al...@users.noreply.github.com>
Authored: Sat Apr 8 17:12:37 2017 -0700
Committer: GitHub <no...@github.com>
Committed: Sat Apr 8 17:12:37 2017 -0700

----------------------------------------------------------------------
 .../src/main/scala/com/cloudera/livy/repl/SparkInterpreter.scala | 4 ++++
 .../src/main/scala/com/cloudera/livy/repl/SparkInterpreter.scala | 4 ++++
 2 files changed, 8 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/07f6072f/repl/scala-2.10/src/main/scala/com/cloudera/livy/repl/SparkInterpreter.scala
----------------------------------------------------------------------
diff --git a/repl/scala-2.10/src/main/scala/com/cloudera/livy/repl/SparkInterpreter.scala b/repl/scala-2.10/src/main/scala/com/cloudera/livy/repl/SparkInterpreter.scala
index ec12929..5ef5491 100644
--- a/repl/scala-2.10/src/main/scala/com/cloudera/livy/repl/SparkInterpreter.scala
+++ b/repl/scala-2.10/src/main/scala/com/cloudera/livy/repl/SparkInterpreter.scala
@@ -92,6 +92,10 @@ class SparkInterpreter(conf: SparkConf,
             .filter { u => u.getProtocol == "file" && new File(u.getPath).isFile }
             // Livy rsc and repl are also in the extra jars list. Filter them out.
             .filterNot { u => Paths.get(u.toURI).getFileName.toString.startsWith("livy-") }
+            // Some bad spark packages depend on the wrong version of scala-reflect. Blacklist it.
+            .filterNot { u =>
+              Paths.get(u.toURI).getFileName.toString.contains("org.scala-lang_scala-reflect")
+            }
 
           extraJarPath.foreach { p => debug(s"Adding $p to Scala interpreter's class path...") }
           sparkIMain.addUrlsToClassPath(extraJarPath: _*)

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/07f6072f/repl/scala-2.11/src/main/scala/com/cloudera/livy/repl/SparkInterpreter.scala
----------------------------------------------------------------------
diff --git a/repl/scala-2.11/src/main/scala/com/cloudera/livy/repl/SparkInterpreter.scala b/repl/scala-2.11/src/main/scala/com/cloudera/livy/repl/SparkInterpreter.scala
index bf2f680..6735b3a 100644
--- a/repl/scala-2.11/src/main/scala/com/cloudera/livy/repl/SparkInterpreter.scala
+++ b/repl/scala-2.11/src/main/scala/com/cloudera/livy/repl/SparkInterpreter.scala
@@ -78,6 +78,10 @@ class SparkInterpreter(conf: SparkConf,
             .filter { u => u.getProtocol == "file" && new File(u.getPath).isFile }
             // Livy rsc and repl are also in the extra jars list. Filter them out.
             .filterNot { u => Paths.get(u.toURI).getFileName.toString.startsWith("livy-") }
+            // Some bad spark packages depend on the wrong version of scala-reflect. Blacklist it.
+            .filterNot { u =>
+              Paths.get(u.toURI).getFileName.toString.contains("org.scala-lang_scala-reflect")
+            }
 
           extraJarPath.foreach { p => debug(s"Adding $p to Scala interpreter's class path...") }
           sparkILoop.addUrlsToClassPath(extraJarPath: _*)


[07/50] [abbrv] incubator-livy git commit: LIVY-311. Set classpath in MiniCluster only when it is not in real cluster (#286)

Posted by js...@apache.org.
LIVY-311. Set classpath in MiniCluster only when it is not in real cluster (#286)



Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/34f6c7f9
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/34f6c7f9
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/34f6c7f9

Branch: refs/heads/master
Commit: 34f6c7f9e46a656dd129057173994016b000df00
Parents: 69462b9
Author: Jeff Zhang <zj...@gmail.com>
Authored: Thu Feb 9 01:16:56 2017 +0800
Committer: Alex Man <tc...@gmail.com>
Committed: Wed Feb 8 09:16:56 2017 -0800

----------------------------------------------------------------------
 .../cloudera/livy/test/framework/MiniCluster.scala  | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/34f6c7f9/integration-test/src/main/scala/com/cloudera/livy/test/framework/MiniCluster.scala
----------------------------------------------------------------------
diff --git a/integration-test/src/main/scala/com/cloudera/livy/test/framework/MiniCluster.scala b/integration-test/src/main/scala/com/cloudera/livy/test/framework/MiniCluster.scala
index 3cc22c2..d520269 100644
--- a/integration-test/src/main/scala/com/cloudera/livy/test/framework/MiniCluster.scala
+++ b/integration-test/src/main/scala/com/cloudera/livy/test/framework/MiniCluster.scala
@@ -238,16 +238,16 @@ class MiniCluster(config: Map[String, String]) extends Cluster with MiniClusterU
     assert(tempDir.mkdir(), "Cannot create temp test dir.")
     sparkConfDir = mkdir("spark-conf")
 
-    val sparkScalaVersion = getSparkScalaVersion()
-    val classPathFile =
-      new File(s"minicluster-dependencies/scala-$sparkScalaVersion/target/classpath")
-    assert(classPathFile.isFile,
-      s"Cannot read MiniCluster classpath file: ${classPathFile.getCanonicalPath}")
-    val sparkClassPath =
-      FileUtils.readFileToString(classPathFile, Charset.defaultCharset())
-
     // When running a real Spark cluster, don't set the classpath.
     val extraCp = if (!isRealSpark()) {
+      val sparkScalaVersion = getSparkScalaVersion()
+      val classPathFile =
+        new File(s"minicluster-dependencies/scala-$sparkScalaVersion/target/classpath")
+      assert(classPathFile.isFile,
+        s"Cannot read MiniCluster classpath file: ${classPathFile.getCanonicalPath}")
+      val sparkClassPath =
+        FileUtils.readFileToString(classPathFile, Charset.defaultCharset())
+
       val dummyJar = Files.createTempFile(Paths.get(tempDir.toURI), "dummy", "jar").toFile
       Map(
         SparkLauncher.DRIVER_EXTRA_CLASSPATH -> sparkClassPath,


[28/50] [abbrv] incubator-livy git commit: LIVY-326. Change Hadoop dependencies to Apache Hadoop (#306)

Posted by js...@apache.org.
LIVY-326. Change Hadoop dependencies to Apache Hadoop (#306)

* Change Hadoop dependencies to Apache Hadoop

Change-Id: I5500cc0061b03af1587700b7b0a7a147bbf0a333

* Change to use Apache Hadoop 2.7.3

Change-Id: Ied6a69e28fb4a9e4d1dcd97595c7ab253f1eaf82


Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/fbccb694
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/fbccb694
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/fbccb694

Branch: refs/heads/master
Commit: fbccb694d2f4eda8b82323b64cba12eea95edfac
Parents: 70f23b9
Author: Saisai Shao <sa...@gmail.com>
Authored: Mon Mar 13 14:12:10 2017 +0800
Committer: Jeff Zhang <zj...@gmail.com>
Committed: Mon Mar 13 14:12:10 2017 +0800

----------------------------------------------------------------------
 pom.xml                                                            | 2 +-
 .../src/main/scala/com/cloudera/livy/sessions/SessionManager.scala | 2 --
 2 files changed, 1 insertion(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/fbccb694/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index fbc4d84..cb6d80f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -42,7 +42,7 @@
   </organization>
 
   <properties>
-    <hadoop.version>2.6.0-cdh5.5.0</hadoop.version>
+    <hadoop.version>2.7.3</hadoop.version>
     <hadoop.scope>compile</hadoop.scope>
     <spark.version>1.6.2</spark.version>
     <commons-codec.version>1.9</commons-codec.version>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/fbccb694/server/src/main/scala/com/cloudera/livy/sessions/SessionManager.scala
----------------------------------------------------------------------
diff --git a/server/src/main/scala/com/cloudera/livy/sessions/SessionManager.scala b/server/src/main/scala/com/cloudera/livy/sessions/SessionManager.scala
index e177108..edf61c7 100644
--- a/server/src/main/scala/com/cloudera/livy/sessions/SessionManager.scala
+++ b/server/src/main/scala/com/cloudera/livy/sessions/SessionManager.scala
@@ -134,8 +134,6 @@ class SessionManager[S <: Session, R <: RecoveryMetadata : ClassTag](
 
   def collectGarbage(): Future[Iterable[Unit]] = {
     def expired(session: Session): Boolean = {
-      val currentTime = System.nanoTime()
-      currentTime - session.lastActivity > sessionTimeout
       session.state match {
         case s: FinishedSessionState =>
           val currentTime = System.nanoTime()


[46/50] [abbrv] incubator-livy git commit: Minor. Add session information log when session is created (#325)

Posted by js...@apache.org.
Minor. Add session information log when session is created (#325)

* Add session information log when session is created

Change-Id: I8702ebe1d893cf328b4490e5b5d09f3afd02b7ce

* add more logs

Change-Id: I969edf4e680e59e3ecfbaa50431ae61bd03d4795

* simplify the code

Change-Id: If2c7876ddb6020ace3872c9ae639d69d58b02f48

* Address the comments

Change-Id: Iba5f10ad73ff67b97af8292769b254346b8ef7c8


Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/d51e9982
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/d51e9982
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/d51e9982

Branch: refs/heads/master
Commit: d51e998204e3a10f9207280951f98edc8755c433
Parents: 61b206e
Author: Saisai Shao <sa...@gmail.com>
Authored: Fri May 12 08:36:19 2017 +0800
Committer: Jeff Zhang <zj...@gmail.com>
Committed: Thu May 11 17:36:19 2017 -0700

----------------------------------------------------------------------
 .../cloudera/livy/server/batch/BatchSession.scala | 11 ++++++++---
 .../livy/server/batch/CreateBatchRequest.scala    | 17 +++++++++++++++++
 .../interactive/CreateInteractiveRequest.scala    | 18 ++++++++++++++++++
 .../server/interactive/InteractiveSession.scala   |  5 ++++-
 4 files changed, 47 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/d51e9982/server/src/main/scala/com/cloudera/livy/server/batch/BatchSession.scala
----------------------------------------------------------------------
diff --git a/server/src/main/scala/com/cloudera/livy/server/batch/BatchSession.scala b/server/src/main/scala/com/cloudera/livy/server/batch/BatchSession.scala
index 452a9d8..1a097b7 100644
--- a/server/src/main/scala/com/cloudera/livy/server/batch/BatchSession.scala
+++ b/server/src/main/scala/com/cloudera/livy/server/batch/BatchSession.scala
@@ -25,7 +25,7 @@ import scala.util.Random
 
 import com.fasterxml.jackson.annotation.JsonIgnoreProperties
 
-import com.cloudera.livy.LivyConf
+import com.cloudera.livy.{LivyConf, Logging}
 import com.cloudera.livy.server.recovery.SessionStore
 import com.cloudera.livy.sessions.{Session, SessionState}
 import com.cloudera.livy.sessions.Session._
@@ -41,7 +41,7 @@ case class BatchRecoveryMetadata(
     version: Int = 1)
   extends RecoveryMetadata
 
-object BatchSession {
+object BatchSession extends Logging {
   val RECOVERY_SESSION_TYPE = "batch"
 
   def create(
@@ -89,6 +89,8 @@ object BatchSession {
       SparkApp.create(appTag, None, Option(sparkSubmit), livyConf, Option(s))
     }
 
+    info(s"Creating batch session $id: [owner: $owner, request: $request]")
+
     new BatchSession(
       id,
       appTag,
@@ -153,7 +155,10 @@ class BatchSession(
     synchronized {
       debug(s"$this state changed from $oldState to $newState")
       newState match {
-        case SparkApp.State.RUNNING => _state = SessionState.Running()
+        case SparkApp.State.RUNNING =>
+          _state = SessionState.Running()
+          info(s"Batch session $id created [appid: ${appId.orNull}, state: ${state.toString}, " +
+            s"info: ${appInfo.asJavaMap}]")
         case SparkApp.State.FINISHED => _state = SessionState.Success()
         case SparkApp.State.KILLED | SparkApp.State.FAILED =>
           _state = SessionState.Dead()

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/d51e9982/server/src/main/scala/com/cloudera/livy/server/batch/CreateBatchRequest.scala
----------------------------------------------------------------------
diff --git a/server/src/main/scala/com/cloudera/livy/server/batch/CreateBatchRequest.scala b/server/src/main/scala/com/cloudera/livy/server/batch/CreateBatchRequest.scala
index 99459d5..29c269c 100644
--- a/server/src/main/scala/com/cloudera/livy/server/batch/CreateBatchRequest.scala
+++ b/server/src/main/scala/com/cloudera/livy/server/batch/CreateBatchRequest.scala
@@ -37,4 +37,21 @@ class CreateBatchRequest {
   var name: Option[String] = None
   var conf: Map[String, String] = Map()
 
+  override def toString: String = {
+    s"[proxyUser: $proxyUser, " +
+      s"file: $file, " +
+      (if (args.nonEmpty) s"args: ${args.mkString(",")}, " else "") +
+      (if (jars.nonEmpty) s"jars: ${jars.mkString(",")}, " else "") +
+      (if (pyFiles.nonEmpty) s"pyFiles: ${pyFiles.mkString(",")}, " else "") +
+      (if (files.nonEmpty) s"files: ${files.mkString(",")}, " else "") +
+      (if (archives.nonEmpty) s"archives: ${archives.mkString(",")}, " else "") +
+      (if (driverMemory.isDefined) s"driverMemory: ${driverMemory.get}, " else "") +
+      (if (driverCores.isDefined) s"driverCores: ${driverCores.get}, " else "") +
+      (if (executorMemory.isDefined) s"executorMemory: ${executorMemory.get}, " else "") +
+      (if (executorCores.isDefined) s"executorCores: ${executorCores.get}, " else "") +
+      (if (numExecutors.isDefined) s"numExecutors: ${numExecutors.get}, " else "") +
+      (if (queue.isDefined) s"queue: ${queue.get}, " else "") +
+      (if (name.isDefined) s"name: ${name.get}, " else "") +
+      (if (conf.nonEmpty) s"conf: ${conf.mkString(",")}]" else "]")
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/d51e9982/server/src/main/scala/com/cloudera/livy/server/interactive/CreateInteractiveRequest.scala
----------------------------------------------------------------------
diff --git a/server/src/main/scala/com/cloudera/livy/server/interactive/CreateInteractiveRequest.scala b/server/src/main/scala/com/cloudera/livy/server/interactive/CreateInteractiveRequest.scala
index a837527..7261199 100644
--- a/server/src/main/scala/com/cloudera/livy/server/interactive/CreateInteractiveRequest.scala
+++ b/server/src/main/scala/com/cloudera/livy/server/interactive/CreateInteractiveRequest.scala
@@ -36,4 +36,22 @@ class CreateInteractiveRequest {
   var name: Option[String] = None
   var conf: Map[String, String] = Map()
   var heartbeatTimeoutInSecond: Int = 0
+
+  override def toString: String = {
+    s"[kind: $kind, " +
+      s"proxyUser: $proxyUser, " +
+      (if (jars.nonEmpty) s"jars: ${jars.mkString(",")}, " else "") +
+      (if (pyFiles.nonEmpty) s"pyFiles: ${pyFiles.mkString(",")}, " else "") +
+      (if (files.nonEmpty) s"files: ${files.mkString(",")}, " else "") +
+      (if (archives.nonEmpty) s"archives: ${archives.mkString(",")}, " else "") +
+      (if (driverMemory.isDefined) s"driverMemory: ${driverMemory.get}, " else "") +
+      (if (driverCores.isDefined) s"driverCores: ${driverCores.get}, " else "") +
+      (if (executorMemory.isDefined) s"executorMemory: ${executorMemory.get}, " else "") +
+      (if (executorCores.isDefined) s"executorCores: ${executorCores.get}, " else "") +
+      (if (numExecutors.isDefined) s"numExecutors: ${numExecutors.get}, " else "") +
+      (if (queue.isDefined) s"queue: ${queue.get}, " else "") +
+      (if (name.isDefined) s"name: ${name.get}, " else "") +
+      (if (conf.nonEmpty) s"conf: ${conf.mkString(",")}, " else "") +
+      s"heartbeatTimeoutInSecond: $heartbeatTimeoutInSecond]"
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/d51e9982/server/src/main/scala/com/cloudera/livy/server/interactive/InteractiveSession.scala
----------------------------------------------------------------------
diff --git a/server/src/main/scala/com/cloudera/livy/server/interactive/InteractiveSession.scala b/server/src/main/scala/com/cloudera/livy/server/interactive/InteractiveSession.scala
index 6d10c57..05bc7be 100644
--- a/server/src/main/scala/com/cloudera/livy/server/interactive/InteractiveSession.scala
+++ b/server/src/main/scala/com/cloudera/livy/server/interactive/InteractiveSession.scala
@@ -98,7 +98,7 @@ object InteractiveSession extends Logging {
 
       builderProperties.getOrElseUpdate("spark.app.name", s"livy-session-$id")
 
-      info(s"Creating LivyClient for sessionId: $id")
+      info(s"Creating Interactive session $id: [owner: $owner, request: $request]")
       val builder = new LivyClientBuilder()
         .setAll(builderProperties.asJava)
         .setConf("livy.client.session-id", id.toString)
@@ -421,6 +421,9 @@ class InteractiveSession(
 
       override def onJobSucceeded(job: JobHandle[Void], result: Void): Unit = {
         transition(SessionState.Running())
+        info(s"Interactive session $id created [appid: ${appId.orNull}, owner: $owner, proxyUser:" +
+          s" $proxyUser, state: ${state.toString}, kind: ${kind.toString}, " +
+          s"info: ${appInfo.asJavaMap}]")
       }
 
       private def errorOut(): Unit = {


[33/50] [abbrv] incubator-livy git commit: LIVY-313. Fixed SparkRInterpreter always returning success. (#307)

Posted by js...@apache.org.
LIVY-313. Fixed SparkRInterpreter always returning success. (#307)

* LIVY-313. Fixed SparkRInterpreter always returning success.

- Stopped redirecting stderr to stdout.
- Continue to read ErrorStream (it was only being read once).
- Checking for any errors returned by stderr before returning success.

* Fixing scalastyle check error

* Changing the way errors are handled in SparkRInterpreter

* Fixing scalastyle check error

* Updating SparkRSessionSpec


Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/0de0e286
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/0de0e286
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/0de0e286

Branch: refs/heads/master
Commit: 0de0e28658d5490e289a290b3cdf8a9f12e19eb0
Parents: 5e6f9ed
Author: Jonathan Alter <jo...@users.noreply.github.com>
Authored: Wed Mar 22 23:56:57 2017 -0700
Committer: Jeff Zhang <zj...@gmail.com>
Committed: Thu Mar 23 14:56:57 2017 +0800

----------------------------------------------------------------------
 .../cloudera/livy/repl/SparkRInterpreter.scala  | 61 ++++++++++++++------
 .../livy/repl/SparkRInterpreterSpec.scala       | 13 ++---
 .../cloudera/livy/repl/SparkRSessionSpec.scala  |  8 +--
 3 files changed, 53 insertions(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0de0e286/repl/src/main/scala/com/cloudera/livy/repl/SparkRInterpreter.scala
----------------------------------------------------------------------
diff --git a/repl/src/main/scala/com/cloudera/livy/repl/SparkRInterpreter.scala b/repl/src/main/scala/com/cloudera/livy/repl/SparkRInterpreter.scala
index 8e5f3c0..7318b1e 100644
--- a/repl/src/main/scala/com/cloudera/livy/repl/SparkRInterpreter.scala
+++ b/repl/src/main/scala/com/cloudera/livy/repl/SparkRInterpreter.scala
@@ -37,9 +37,12 @@ import org.json4s.JsonDSL._
 import com.cloudera.livy.client.common.ClientConf
 import com.cloudera.livy.rsc.RSCConf
 
+private case class RequestResponse(content: String, error: Boolean)
+
 // scalastyle:off println
 object SparkRInterpreter {
   private val LIVY_END_MARKER = "----LIVY_END_OF_COMMAND----"
+  private val LIVY_ERROR_MARKER = "----LIVY_END_OF_ERROR----"
   private val PRINT_MARKER = f"""print("$LIVY_END_MARKER")"""
   private val EXPECTED_OUTPUT = f"""[1] "$LIVY_END_MARKER""""
 
@@ -188,18 +191,25 @@ class SparkRInterpreter(process: Process,
     }
 
     try {
-      var content: JObject = TEXT_PLAIN -> sendRequest(code)
-
-      // If we rendered anything, pass along the last image.
-      tempFile.foreach { case file =>
-        val bytes = Files.readAllBytes(file)
-        if (bytes.nonEmpty) {
-          val image = Base64.encodeBase64String(bytes)
-          content = content ~ (IMAGE_PNG -> image)
+      val response = sendRequest(code)
+
+      if (response.error) {
+        Interpreter.ExecuteError("Error", response.content)
+      } else {
+        var content: JObject = TEXT_PLAIN -> response.content
+
+        // If we rendered anything, pass along the last image.
+        tempFile.foreach { case file =>
+          val bytes = Files.readAllBytes(file)
+          if (bytes.nonEmpty) {
+            val image = Base64.encodeBase64String(bytes)
+            content = content ~ (IMAGE_PNG -> image)
+          }
         }
+
+        Interpreter.ExecuteSuccess(content)
       }
 
-      Interpreter.ExecuteSuccess(content)
     } catch {
       case e: Error =>
         Interpreter.ExecuteError("Error", e.output)
@@ -211,14 +221,16 @@ class SparkRInterpreter(process: Process,
 
   }
 
-  private def sendRequest(code: String): String = {
-    stdin.println(s"""try(eval(parse(text="${StringEscapeUtils.escapeJava(code)}")))""")
+  private def sendRequest(code: String): RequestResponse = {
+    stdin.println(s"""tryCatch(eval(parse(text="${StringEscapeUtils.escapeJava(code)}"))
+                     |,error = function(e) sprintf("%s%s", e, "${LIVY_ERROR_MARKER}"))
+                  """.stripMargin)
     stdin.flush()
 
     stdin.println(PRINT_MARKER)
     stdin.flush()
 
-    readTo(EXPECTED_OUTPUT)
+    readTo(EXPECTED_OUTPUT, LIVY_ERROR_MARKER)
   }
 
   override protected def sendShutdownRequest() = {
@@ -242,7 +254,10 @@ class SparkRInterpreter(process: Process,
   }
 
   @tailrec
-  private def readTo(marker: String, output: StringBuilder = StringBuilder.newBuilder): String = {
+  private def readTo(
+      marker: String,
+      errorMarker: String,
+      output: StringBuilder = StringBuilder.newBuilder): RequestResponse = {
     var char = readChar(output)
 
     // Remove any ANSI color codes which match the pattern "\u001b\\[[0-9;]*[mG]".
@@ -259,15 +274,25 @@ class SparkRInterpreter(process: Process,
     }
 
     if (output.endsWith(marker)) {
-      val result = output.toString()
-      result.substring(0, result.length - marker.length)
-        .stripPrefix("\n")
-        .stripSuffix("\n")
+      var result = stripMarker(output.toString(), marker)
+
+      if (result.endsWith(errorMarker + "\"")) {
+        result = stripMarker(result, "\\n" + errorMarker)
+        RequestResponse(result, error = true)
+      } else {
+        RequestResponse(result, error = false)
+      }
     } else {
-      readTo(marker, output)
+      readTo(marker, errorMarker, output)
     }
   }
 
+  private def stripMarker(result: String, marker: String): String = {
+    result.replace(marker, "")
+      .stripPrefix("\n")
+      .stripSuffix("\n")
+  }
+
   private def readChar(output: StringBuilder): Char = {
     val byte = stdout.read()
     if (byte == -1) {

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0de0e286/repl/src/test/scala/com/cloudera/livy/repl/SparkRInterpreterSpec.scala
----------------------------------------------------------------------
diff --git a/repl/src/test/scala/com/cloudera/livy/repl/SparkRInterpreterSpec.scala b/repl/src/test/scala/com/cloudera/livy/repl/SparkRInterpreterSpec.scala
index e9db106..f4f709f 100644
--- a/repl/src/test/scala/com/cloudera/livy/repl/SparkRInterpreterSpec.scala
+++ b/repl/src/test/scala/com/cloudera/livy/repl/SparkRInterpreterSpec.scala
@@ -84,19 +84,18 @@ class SparkRInterpreterSpec extends BaseInterpreterSpec {
 
   it should "report an error if accessing an unknown variable" in withInterpreter { interpreter =>
     val response = interpreter.execute("x")
-    response should equal(Interpreter.ExecuteSuccess(
-      TEXT_PLAIN -> "Error in eval(expr, envir, enclos) : object 'x' not found"
+    response should equal(Interpreter.ExecuteError(
+      "Error",
+      """[1] "Error in eval(expr, envir, enclos): object 'x' not found""""
     ))
   }
 
 
   it should "not hang when executing incomplete statements" in withInterpreter { interpreter =>
     val response = interpreter.execute("x[")
-    response should equal(Interpreter.ExecuteSuccess(
-      TEXT_PLAIN ->
-        """Error in parse(text = "x[") : <text>:2:0: unexpected end of input
-          |1: x[
-          |   ^""".stripMargin
+    response should equal(Interpreter.ExecuteError(
+      "Error",
+        """[1] "Error in parse(text = \"x[\"): <text>:2:0: unexpected end of input\n1: x[\n   ^""""
     ))
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0de0e286/repl/src/test/scala/com/cloudera/livy/repl/SparkRSessionSpec.scala
----------------------------------------------------------------------
diff --git a/repl/src/test/scala/com/cloudera/livy/repl/SparkRSessionSpec.scala b/repl/src/test/scala/com/cloudera/livy/repl/SparkRSessionSpec.scala
index 5592977..4bbf87c 100644
--- a/repl/src/test/scala/com/cloudera/livy/repl/SparkRSessionSpec.scala
+++ b/repl/src/test/scala/com/cloudera/livy/repl/SparkRSessionSpec.scala
@@ -133,11 +133,11 @@ class SparkRSessionSpec extends BaseSessionSpec {
 
     val result = parse(statement.output)
     val expectedResult = Extraction.decompose(Map(
-      "status" -> "ok",
+      "status" -> "error",
       "execution_count" -> 0,
-      "data" -> Map(
-        "text/plain" -> "Error in eval(expr, envir, enclos) : object 'x' not found"
-      )
+      "ename" -> "Error",
+      "evalue" -> "[1] \"Error in eval(expr, envir, enclos): object 'x' not found\"",
+      "traceback" -> List()
     ))
 
     result should equal (expectedResult)


[13/50] [abbrv] incubator-livy git commit: Fixed a typo in the README (#289)

Posted by js...@apache.org.
Fixed a typo in the README (#289)



Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/693a7959
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/693a7959
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/693a7959

Branch: refs/heads/master
Commit: 693a79594675e3c9cc19756ce5aca4a435f8ba8d
Parents: a36e44f
Author: Alex Bozarth <aj...@us.ibm.com>
Authored: Tue Feb 14 17:31:54 2017 -0800
Committer: Jeff Zhang <zj...@gmail.com>
Committed: Wed Feb 15 09:31:54 2017 +0800

----------------------------------------------------------------------
 README.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/693a7959/README.rst
----------------------------------------------------------------------
diff --git a/README.rst b/README.rst
index 1331bf7..b72dd0f 100644
--- a/README.rst
+++ b/README.rst
@@ -580,7 +580,7 @@ DELETE /sessions/{sessionId}
 Kills the `Session`_ job.
 
 
-GET /sessions/{sessionId}/logs
+GET /sessions/{sessionId}/log
 ------------------------------
 
 Gets the log lines from this session.


[47/50] [abbrv] incubator-livy git commit: LIVY-358. Make JettyServer Http request and response header size configurable (#329)

Posted by js...@apache.org.
LIVY-358. Make JettyServer Http request and response header size configurable (#329)

* Provide Jetty Http Request/Response Header Size Configuration

Kerberos over http requires larger header sizes than the default,
or the HTTP Error 413 Request entity too large will be returned.
This patch increases the default for Livy to 128K and also allows
this to be configurable.

* Change the conf key name

Change-Id: Id274c8cc60d30e5d778f9c447502b7e7a789a8f0


Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/59af39d7
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/59af39d7
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/59af39d7

Branch: refs/heads/master
Commit: 59af39d7e7c85e10603fb66ad2997384cab1dcd0
Parents: d51e998
Author: Saisai Shao <sa...@gmail.com>
Authored: Sat May 13 00:45:42 2017 +0800
Committer: Jeff Zhang <zj...@gmail.com>
Committed: Fri May 12 09:45:42 2017 -0700

----------------------------------------------------------------------
 .../main/scala/com/cloudera/livy/LivyConf.scala   | 18 +++++++++---------
 .../com/cloudera/livy/server/WebServer.scala      |  7 ++++++-
 2 files changed, 15 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/59af39d7/server/src/main/scala/com/cloudera/livy/LivyConf.scala
----------------------------------------------------------------------
diff --git a/server/src/main/scala/com/cloudera/livy/LivyConf.scala b/server/src/main/scala/com/cloudera/livy/LivyConf.scala
index 233aa63..b347c2d 100644
--- a/server/src/main/scala/com/cloudera/livy/LivyConf.scala
+++ b/server/src/main/scala/com/cloudera/livy/LivyConf.scala
@@ -62,10 +62,14 @@ object LivyConf {
 
   val SERVER_HOST = Entry("livy.server.host", "0.0.0.0")
   val SERVER_PORT = Entry("livy.server.port", 8998)
-  val CSRF_PROTECTION = LivyConf.Entry("livy.server.csrf-protection.enabled", false)
 
   val UI_ENABLED = Entry("livy.ui.enabled", true)
 
+  val REQUEST_HEADER_SIZE = Entry("livy.server.request-header.size", 131072)
+  val RESPONSE_HEADER_SIZE = Entry("livy.server.response-header.size", 131072)
+
+  val CSRF_PROTECTION = Entry("livy.server.csrf-protection.enabled", false)
+
   val IMPERSONATION_ENABLED = Entry("livy.impersonation.enabled", false)
   val SUPERUSERS = Entry("livy.superusers", null)
 
@@ -83,14 +87,10 @@ object LivyConf {
 
   val HEARTBEAT_WATCHDOG_INTERVAL = Entry("livy.server.heartbeat-watchdog.interval", "1m")
 
-  val LAUNCH_KERBEROS_PRINCIPAL =
-    LivyConf.Entry("livy.server.launch.kerberos.principal", null)
-  val LAUNCH_KERBEROS_KEYTAB =
-    LivyConf.Entry("livy.server.launch.kerberos.keytab", null)
-  val LAUNCH_KERBEROS_REFRESH_INTERVAL =
-    LivyConf.Entry("livy.server.launch.kerberos.refresh-interval", "1h")
-  val KINIT_FAIL_THRESHOLD =
-    LivyConf.Entry("livy.server.launch.kerberos.kinit-fail-threshold", 5)
+  val LAUNCH_KERBEROS_PRINCIPAL = Entry("livy.server.launch.kerberos.principal", null)
+  val LAUNCH_KERBEROS_KEYTAB = Entry("livy.server.launch.kerberos.keytab", null)
+  val LAUNCH_KERBEROS_REFRESH_INTERVAL = Entry("livy.server.launch.kerberos.refresh-interval", "1h")
+  val KINIT_FAIL_THRESHOLD = Entry("livy.server.launch.kerberos.kinit-fail-threshold", 5)
 
   /**
    * Recovery mode of Livy. Possible values:

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/59af39d7/server/src/main/scala/com/cloudera/livy/server/WebServer.scala
----------------------------------------------------------------------
diff --git a/server/src/main/scala/com/cloudera/livy/server/WebServer.scala b/server/src/main/scala/com/cloudera/livy/server/WebServer.scala
index 8f21180..298e696 100644
--- a/server/src/main/scala/com/cloudera/livy/server/WebServer.scala
+++ b/server/src/main/scala/com/cloudera/livy/server/WebServer.scala
@@ -36,10 +36,15 @@ class WebServer(livyConf: LivyConf, var host: String, var port: Int) extends Log
 
   val (connector, protocol) = Option(livyConf.get(LivyConf.SSL_KEYSTORE)) match {
     case None =>
-      (new ServerConnector(server), "http")
+      val http = new HttpConfiguration()
+      http.setRequestHeaderSize(livyConf.getInt(LivyConf.REQUEST_HEADER_SIZE))
+      http.setResponseHeaderSize(livyConf.getInt(LivyConf.RESPONSE_HEADER_SIZE))
+      (new ServerConnector(server, new HttpConnectionFactory(http)), "http")
 
     case Some(keystore) =>
       val https = new HttpConfiguration()
+      https.setRequestHeaderSize(livyConf.getInt(LivyConf.REQUEST_HEADER_SIZE))
+      https.setResponseHeaderSize(livyConf.getInt(LivyConf.RESPONSE_HEADER_SIZE))
       https.addCustomizer(new SecureRequestCustomizer())
 
       val sslContextFactory = new SslContextFactory()


[09/50] [abbrv] incubator-livy git commit: Bump the version of branch-0.3 to 0.3.1-SNAPSHOT. (#281)

Posted by js...@apache.org.
Bump the version of branch-0.3 to 0.3.1-SNAPSHOT. (#281)



Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/0afee230
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/0afee230
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/0afee230

Branch: refs/heads/branch-0.3
Commit: 0afee2301dd321888fb4cb67529f381ee494d669
Parents: e36b6f5
Author: Saisai Shao <sa...@gmail.com>
Authored: Sat Feb 11 00:47:55 2017 +0800
Committer: Alex Man <tc...@gmail.com>
Committed: Fri Feb 10 11:47:55 2017 -0500

----------------------------------------------------------------------
 api/pom.xml                                                  | 4 ++--
 assembly/pom.xml                                             | 4 ++--
 client-common/pom.xml                                        | 4 ++--
 client-http/pom.xml                                          | 4 ++--
 core/pom.xml                                                 | 4 ++--
 core/scala-2.10/pom.xml                                      | 4 ++--
 core/scala-2.11/pom.xml                                      | 4 ++--
 coverage/pom.xml                                             | 4 ++--
 examples/pom.xml                                             | 4 ++--
 integration-test/minicluster-dependencies/pom.xml            | 4 ++--
 integration-test/minicluster-dependencies/scala-2.10/pom.xml | 4 ++--
 integration-test/minicluster-dependencies/scala-2.11/pom.xml | 4 ++--
 integration-test/pom.xml                                     | 4 ++--
 pom.xml                                                      | 2 +-
 python-api/pom.xml                                           | 4 ++--
 python-api/setup.py                                          | 2 +-
 repl/pom.xml                                                 | 4 ++--
 repl/scala-2.10/pom.xml                                      | 4 ++--
 repl/scala-2.11/pom.xml                                      | 4 ++--
 rsc/pom.xml                                                  | 4 ++--
 scala-api/pom.xml                                            | 4 ++--
 scala-api/scala-2.10/pom.xml                                 | 4 ++--
 scala-api/scala-2.11/pom.xml                                 | 4 ++--
 scala/pom.xml                                                | 4 ++--
 server/pom.xml                                               | 4 ++--
 test-lib/pom.xml                                             | 4 ++--
 26 files changed, 50 insertions(+), 50 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0afee230/api/pom.xml
----------------------------------------------------------------------
diff --git a/api/pom.xml b/api/pom.xml
index 8873c61..93f16d6 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -20,12 +20,12 @@
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-main</artifactId>
-    <version>0.3.0</version>
+    <version>0.3.1-SNAPSHOT</version>
   </parent>
 
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-api</artifactId>
-  <version>0.3.0</version>
+  <version>0.3.1-SNAPSHOT</version>
   <packaging>jar</packaging>
 
   <properties>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0afee230/assembly/pom.xml
----------------------------------------------------------------------
diff --git a/assembly/pom.xml b/assembly/pom.xml
index fe1515a..b54a4f7 100644
--- a/assembly/pom.xml
+++ b/assembly/pom.xml
@@ -21,12 +21,12 @@
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-main</artifactId>
-    <version>0.3.0</version>
+    <version>0.3.1-SNAPSHOT</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
 
   <artifactId>livy-assembly</artifactId>
-  <version>0.3.0</version>
+  <version>0.3.1-SNAPSHOT</version>
   <packaging>pom</packaging>
 
   <properties>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0afee230/client-common/pom.xml
----------------------------------------------------------------------
diff --git a/client-common/pom.xml b/client-common/pom.xml
index c3202fb..026ed32 100644
--- a/client-common/pom.xml
+++ b/client-common/pom.xml
@@ -21,12 +21,12 @@
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-main</artifactId>
-    <version>0.3.0</version>
+    <version>0.3.1-SNAPSHOT</version>
   </parent>
 
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-client-common</artifactId>
-  <version>0.3.0</version>
+  <version>0.3.1-SNAPSHOT</version>
   <packaging>jar</packaging>
 
   <dependencies>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0afee230/client-http/pom.xml
----------------------------------------------------------------------
diff --git a/client-http/pom.xml b/client-http/pom.xml
index dd295c1..8a26983 100644
--- a/client-http/pom.xml
+++ b/client-http/pom.xml
@@ -21,12 +21,12 @@
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-main</artifactId>
-    <version>0.3.0</version>
+    <version>0.3.1-SNAPSHOT</version>
   </parent>
 
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-client-http</artifactId>
-  <version>0.3.0</version>
+  <version>0.3.1-SNAPSHOT</version>
   <packaging>jar</packaging>
 
   <dependencies>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0afee230/core/pom.xml
----------------------------------------------------------------------
diff --git a/core/pom.xml b/core/pom.xml
index e17d871..1aa377f 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -23,12 +23,12 @@
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>multi-scala-project-root</artifactId>
-    <version>0.3.0</version>
+    <version>0.3.1-SNAPSHOT</version>
     <relativePath>../scala/pom.xml</relativePath>
   </parent>
 
   <artifactId>livy-core-parent</artifactId>
-  <version>0.3.0</version>
+  <version>0.3.1-SNAPSHOT</version>
   <packaging>pom</packaging>
 
   <properties>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0afee230/core/scala-2.10/pom.xml
----------------------------------------------------------------------
diff --git a/core/scala-2.10/pom.xml b/core/scala-2.10/pom.xml
index 3708d88..4500975 100644
--- a/core/scala-2.10/pom.xml
+++ b/core/scala-2.10/pom.xml
@@ -20,13 +20,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-core_2.10</artifactId>
-  <version>0.3.0</version>
+  <version>0.3.1-SNAPSHOT</version>
   <packaging>jar</packaging>
 
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-core-parent</artifactId>
-    <version>0.3.0</version>
+    <version>0.3.1-SNAPSHOT</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0afee230/core/scala-2.11/pom.xml
----------------------------------------------------------------------
diff --git a/core/scala-2.11/pom.xml b/core/scala-2.11/pom.xml
index a47f9b4..b9d923e 100644
--- a/core/scala-2.11/pom.xml
+++ b/core/scala-2.11/pom.xml
@@ -20,13 +20,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-core_2.11</artifactId>
-  <version>0.3.0</version>
+  <version>0.3.1-SNAPSHOT</version>
   <packaging>jar</packaging>
 
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-core-parent</artifactId>
-    <version>0.3.0</version>
+    <version>0.3.1-SNAPSHOT</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0afee230/coverage/pom.xml
----------------------------------------------------------------------
diff --git a/coverage/pom.xml b/coverage/pom.xml
index f8123f8..c98e5bb 100644
--- a/coverage/pom.xml
+++ b/coverage/pom.xml
@@ -24,11 +24,11 @@
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-main</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>0.3.0</version>
+    <version>0.3.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>livy-coverage-report</artifactId>
-  <version>0.3.0</version>
+  <version>0.3.1-SNAPSHOT</version>
   <packaging>pom</packaging>
 
   <dependencies>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0afee230/examples/pom.xml
----------------------------------------------------------------------
diff --git a/examples/pom.xml b/examples/pom.xml
index a3470dc..d526bd3 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -24,13 +24,13 @@
     <parent>
         <groupId>com.cloudera.livy</groupId>
         <artifactId>livy-main</artifactId>
-        <version>0.3.0</version>
+        <version>0.3.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
 
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-examples</artifactId>
-    <version>0.3.0</version>
+    <version>0.3.1-SNAPSHOT</version>
     <packaging>jar</packaging>
 
     <properties>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0afee230/integration-test/minicluster-dependencies/pom.xml
----------------------------------------------------------------------
diff --git a/integration-test/minicluster-dependencies/pom.xml b/integration-test/minicluster-dependencies/pom.xml
index ad3fdf1..aa2db50 100644
--- a/integration-test/minicluster-dependencies/pom.xml
+++ b/integration-test/minicluster-dependencies/pom.xml
@@ -27,10 +27,10 @@
     <groupId>com.cloudera.livy</groupId>
     <artifactId>multi-scala-project-root</artifactId>
     <relativePath>../../scala/pom.xml</relativePath>
-    <version>0.3.0</version>
+    <version>0.3.1-SNAPSHOT</version>
   </parent>
   <artifactId>minicluster-dependencies-parent</artifactId>
-  <version>0.3.0</version>
+  <version>0.3.1-SNAPSHOT</version>
   <packaging>pom</packaging>
   <properties>
     <skipDeploy>true</skipDeploy>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0afee230/integration-test/minicluster-dependencies/scala-2.10/pom.xml
----------------------------------------------------------------------
diff --git a/integration-test/minicluster-dependencies/scala-2.10/pom.xml b/integration-test/minicluster-dependencies/scala-2.10/pom.xml
index ec5828a..e269e65 100644
--- a/integration-test/minicluster-dependencies/scala-2.10/pom.xml
+++ b/integration-test/minicluster-dependencies/scala-2.10/pom.xml
@@ -20,13 +20,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.cloudera.livy</groupId>
   <artifactId>minicluster-dependencies_2.10</artifactId>
-  <version>0.3.0</version>
+  <version>0.3.1-SNAPSHOT</version>
   <packaging>jar</packaging>
 
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>minicluster-dependencies-parent</artifactId>
-    <version>0.3.0</version>
+    <version>0.3.1-SNAPSHOT</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0afee230/integration-test/minicluster-dependencies/scala-2.11/pom.xml
----------------------------------------------------------------------
diff --git a/integration-test/minicluster-dependencies/scala-2.11/pom.xml b/integration-test/minicluster-dependencies/scala-2.11/pom.xml
index 42e4028..96a11d8 100644
--- a/integration-test/minicluster-dependencies/scala-2.11/pom.xml
+++ b/integration-test/minicluster-dependencies/scala-2.11/pom.xml
@@ -20,13 +20,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.cloudera.livy</groupId>
   <artifactId>minicluster-dependencies_2.11</artifactId>
-  <version>0.3.0</version>
+  <version>0.3.1-SNAPSHOT</version>
   <packaging>jar</packaging>
 
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>minicluster-dependencies-parent</artifactId>
-    <version>0.3.0</version>
+    <version>0.3.1-SNAPSHOT</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0afee230/integration-test/pom.xml
----------------------------------------------------------------------
diff --git a/integration-test/pom.xml b/integration-test/pom.xml
index ea15a6a..e196d58 100644
--- a/integration-test/pom.xml
+++ b/integration-test/pom.xml
@@ -24,11 +24,11 @@
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-main</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>0.3.0</version>
+    <version>0.3.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>livy-integration-test</artifactId>
-  <version>0.3.0</version>
+  <version>0.3.1-SNAPSHOT</version>
   <packaging>jar</packaging>
 
   <properties>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0afee230/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 630c1c5..ecbb4c4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -23,7 +23,7 @@
 
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-main</artifactId>
-  <version>0.3.0</version>
+  <version>0.3.1-SNAPSHOT</version>
   <packaging>pom</packaging>
 
   <name>livy-main</name>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0afee230/python-api/pom.xml
----------------------------------------------------------------------
diff --git a/python-api/pom.xml b/python-api/pom.xml
index 95d492e..de2c0ad 100644
--- a/python-api/pom.xml
+++ b/python-api/pom.xml
@@ -7,13 +7,13 @@
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-main</artifactId>
-    <version>0.3.0</version>
+    <version>0.3.1-SNAPSHOT</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
 
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-python-api</artifactId>
-  <version>0.3.0</version>
+  <version>0.3.1-SNAPSHOT</version>
   <packaging>pom</packaging>
 
   <build>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0afee230/python-api/setup.py
----------------------------------------------------------------------
diff --git a/python-api/setup.py b/python-api/setup.py
index f7c5c20..7427d23 100644
--- a/python-api/setup.py
+++ b/python-api/setup.py
@@ -40,7 +40,7 @@ requirements = [
 
 setup(
     name='livy-python-api',
-    version="0.3.0",
+    version="0.3.1-SNAPSHOT",
     packages=["livy", "livy-tests"],
     package_dir={
         "": "src/main/python",

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0afee230/repl/pom.xml
----------------------------------------------------------------------
diff --git a/repl/pom.xml b/repl/pom.xml
index 6470267..83ea17f 100644
--- a/repl/pom.xml
+++ b/repl/pom.xml
@@ -24,11 +24,11 @@
         <groupId>com.cloudera.livy</groupId>
         <artifactId>multi-scala-project-root</artifactId>
         <relativePath>../scala/pom.xml</relativePath>
-        <version>0.3.0</version>
+        <version>0.3.1-SNAPSHOT</version>
     </parent>
 
     <artifactId>livy-repl-parent</artifactId>
-    <version>0.3.0</version>
+    <version>0.3.1-SNAPSHOT</version>
     <packaging>pom</packaging>
 
     <properties>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0afee230/repl/scala-2.10/pom.xml
----------------------------------------------------------------------
diff --git a/repl/scala-2.10/pom.xml b/repl/scala-2.10/pom.xml
index dfdadb9..7c58787 100644
--- a/repl/scala-2.10/pom.xml
+++ b/repl/scala-2.10/pom.xml
@@ -22,13 +22,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-repl_2.10</artifactId>
-  <version>0.3.0</version>
+  <version>0.3.1-SNAPSHOT</version>
   <packaging>jar</packaging>
 
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-repl-parent</artifactId>
-    <version>0.3.0</version>
+    <version>0.3.1-SNAPSHOT</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0afee230/repl/scala-2.11/pom.xml
----------------------------------------------------------------------
diff --git a/repl/scala-2.11/pom.xml b/repl/scala-2.11/pom.xml
index d67da5f..1d9be1f 100644
--- a/repl/scala-2.11/pom.xml
+++ b/repl/scala-2.11/pom.xml
@@ -22,13 +22,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-repl_2.11</artifactId>
-  <version>0.3.0</version>
+  <version>0.3.1-SNAPSHOT</version>
   <packaging>jar</packaging>
 
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-repl-parent</artifactId>
-    <version>0.3.0</version>
+    <version>0.3.1-SNAPSHOT</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0afee230/rsc/pom.xml
----------------------------------------------------------------------
diff --git a/rsc/pom.xml b/rsc/pom.xml
index 35576a0..9e74930 100644
--- a/rsc/pom.xml
+++ b/rsc/pom.xml
@@ -21,12 +21,12 @@
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-main</artifactId>
-    <version>0.3.0</version>
+    <version>0.3.1-SNAPSHOT</version>
   </parent>
 
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-rsc</artifactId>
-  <version>0.3.0</version>
+  <version>0.3.1-SNAPSHOT</version>
   <packaging>jar</packaging>
 
   <properties>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0afee230/scala-api/pom.xml
----------------------------------------------------------------------
diff --git a/scala-api/pom.xml b/scala-api/pom.xml
index f902e5d..1279242 100644
--- a/scala-api/pom.xml
+++ b/scala-api/pom.xml
@@ -24,12 +24,12 @@
     <parent>
         <groupId>com.cloudera.livy</groupId>
         <artifactId>multi-scala-project-root</artifactId>
-        <version>0.3.0</version>
+        <version>0.3.1-SNAPSHOT</version>
         <relativePath>../scala/pom.xml</relativePath>
     </parent>
 
     <artifactId>livy-scala-api-parent</artifactId>
-    <version>0.3.0</version>
+    <version>0.3.1-SNAPSHOT</version>
     <packaging>pom</packaging>
 
     <dependencies>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0afee230/scala-api/scala-2.10/pom.xml
----------------------------------------------------------------------
diff --git a/scala-api/scala-2.10/pom.xml b/scala-api/scala-2.10/pom.xml
index 692bc64..44a27e2 100644
--- a/scala-api/scala-2.10/pom.xml
+++ b/scala-api/scala-2.10/pom.xml
@@ -20,13 +20,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-scala-api_2.10</artifactId>
-  <version>0.3.0</version>
+  <version>0.3.1-SNAPSHOT</version>
   <packaging>jar</packaging>
 
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-scala-api-parent</artifactId>
-    <version>0.3.0</version>
+    <version>0.3.1-SNAPSHOT</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0afee230/scala-api/scala-2.11/pom.xml
----------------------------------------------------------------------
diff --git a/scala-api/scala-2.11/pom.xml b/scala-api/scala-2.11/pom.xml
index e3a366b..c5be26c 100644
--- a/scala-api/scala-2.11/pom.xml
+++ b/scala-api/scala-2.11/pom.xml
@@ -20,13 +20,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-scala-api_2.11</artifactId>
-  <version>0.3.0</version>
+  <version>0.3.1-SNAPSHOT</version>
   <packaging>jar</packaging>
 
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-scala-api-parent</artifactId>
-    <version>0.3.0</version>
+    <version>0.3.1-SNAPSHOT</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0afee230/scala/pom.xml
----------------------------------------------------------------------
diff --git a/scala/pom.xml b/scala/pom.xml
index 54e9f51..985f89c 100644
--- a/scala/pom.xml
+++ b/scala/pom.xml
@@ -22,13 +22,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.cloudera.livy</groupId>
   <artifactId>multi-scala-project-root</artifactId>
-  <version>0.3.0</version>
+  <version>0.3.1-SNAPSHOT</version>
   <packaging>pom</packaging>
 
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-main</artifactId>
-    <version>0.3.0</version>
+    <version>0.3.1-SNAPSHOT</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0afee230/server/pom.xml
----------------------------------------------------------------------
diff --git a/server/pom.xml b/server/pom.xml
index e31c5ff..c391d2e 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -24,11 +24,11 @@
         <groupId>com.cloudera.livy</groupId>
         <artifactId>livy-main</artifactId>
         <relativePath>../pom.xml</relativePath>
-        <version>0.3.0</version>
+        <version>0.3.1-SNAPSHOT</version>
     </parent>
 
     <artifactId>livy-server</artifactId>
-    <version>0.3.0</version>
+    <version>0.3.1-SNAPSHOT</version>
     <packaging>jar</packaging>
 
     <properties>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0afee230/test-lib/pom.xml
----------------------------------------------------------------------
diff --git a/test-lib/pom.xml b/test-lib/pom.xml
index b509b63..f0353d3 100644
--- a/test-lib/pom.xml
+++ b/test-lib/pom.xml
@@ -21,12 +21,12 @@
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-main</artifactId>
-    <version>0.3.0</version>
+    <version>0.3.1-SNAPSHOT</version>
   </parent>
 
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-test-lib</artifactId>
-  <version>0.3.0</version>
+  <version>0.3.1-SNAPSHOT</version>
   <packaging>jar</packaging>
 
   <properties>


[14/50] [abbrv] incubator-livy git commit: LIVY-316. NPE when starting kinit thread (#292)

Posted by js...@apache.org.
LIVY-316. NPE when starting kinit thread (#292)



Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/b872978c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/b872978c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/b872978c

Branch: refs/heads/master
Commit: b872978cd7e0cd1e794233fbba958da805da98ab
Parents: 693a795
Author: Jeff Zhang <zj...@gmail.com>
Authored: Wed Feb 15 17:31:39 2017 +0800
Committer: GitHub <no...@github.com>
Committed: Wed Feb 15 17:31:39 2017 +0800

----------------------------------------------------------------------
 server/src/main/scala/com/cloudera/livy/server/LivyServer.scala | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/b872978c/server/src/main/scala/com/cloudera/livy/server/LivyServer.scala
----------------------------------------------------------------------
diff --git a/server/src/main/scala/com/cloudera/livy/server/LivyServer.scala b/server/src/main/scala/com/cloudera/livy/server/LivyServer.scala
index 938f3a6..a88f013 100644
--- a/server/src/main/scala/com/cloudera/livy/server/LivyServer.scala
+++ b/server/src/main/scala/com/cloudera/livy/server/LivyServer.scala
@@ -101,7 +101,7 @@ class LivyServer extends Logging {
       )
       val launch_keytab = livyConf.get(LAUNCH_KERBEROS_KEYTAB)
       val launch_principal = SecurityUtil.getServerPrincipal(
-        livyConf.get(LAUNCH_KERBEROS_PRINCIPAL), server.host)
+        livyConf.get(LAUNCH_KERBEROS_PRINCIPAL), host)
       require(launch_keytab != null,
         s"Kerberos requires ${LAUNCH_KERBEROS_KEYTAB.key} to be provided.")
       require(launch_principal != null,


[30/50] [abbrv] incubator-livy git commit: LIVY-331. Fix flaky test 'interactive session should not gc-ed if session timeout check is off'. (#310)

Posted by js...@apache.org.
LIVY-331. Fix flaky test 'interactive session should not gc-ed if session timeout check is off'. (#310)



Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/eb7e6ccf
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/eb7e6ccf
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/eb7e6ccf

Branch: refs/heads/master
Commit: eb7e6ccfd1809e5738573ce7f0761cd8f879d121
Parents: 2ff8f5c
Author: Saisai Shao <sa...@gmail.com>
Authored: Wed Mar 15 05:37:08 2017 +0800
Committer: Alex Man <al...@users.noreply.github.com>
Committed: Tue Mar 14 14:37:08 2017 -0700

----------------------------------------------------------------------
 .../scala/com/cloudera/livy/sessions/SessionManagerSpec.scala    | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/eb7e6ccf/server/src/test/scala/com/cloudera/livy/sessions/SessionManagerSpec.scala
----------------------------------------------------------------------
diff --git a/server/src/test/scala/com/cloudera/livy/sessions/SessionManagerSpec.scala b/server/src/test/scala/com/cloudera/livy/sessions/SessionManagerSpec.scala
index 241ba27..79f2482 100644
--- a/server/src/test/scala/com/cloudera/livy/sessions/SessionManagerSpec.scala
+++ b/server/src/test/scala/com/cloudera/livy/sessions/SessionManagerSpec.scala
@@ -23,7 +23,7 @@ import scala.concurrent.duration._
 import scala.language.postfixOps
 import scala.util.{Failure, Try}
 
-import org.mockito.Mockito.{never, verify, when}
+import org.mockito.Mockito.{doReturn, never, verify, when}
 import org.scalatest.{FunSpec, Matchers}
 import org.scalatest.concurrent.Eventually._
 import org.scalatest.mock.MockitoSugar.mock
@@ -83,7 +83,7 @@ class SessionManagerSpec extends FunSpec with Matchers with LivyBaseUnitTestSuit
     def testSessionGC(session: Session, sm: SessionManager[_, _]): Unit = {
 
       def changeStateAndCheck(s: SessionState)(fn: SessionManager[_, _] => Unit): Unit = {
-        when(session.state).thenReturn(s)
+        doReturn(s).when(session).state
         Await.result(sm.collectGarbage(), Duration.Inf)
         fn(sm)
       }


[26/50] [abbrv] incubator-livy git commit: LIVY-319. Unify the indent for all POM files. (#302)

Posted by js...@apache.org.
LIVY-319. Unify the indent for all POM files. (#302)

Updated pom files that used 4 space indent to use 2 space indent to match the remaining pom files.

Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/126b57e2
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/126b57e2
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/126b57e2

Branch: refs/heads/master
Commit: 126b57e225dfe3c555644558c04f44e416a5c5ec
Parents: 76d969e
Author: Alex Bozarth <aj...@us.ibm.com>
Authored: Fri Mar 3 16:57:17 2017 -0800
Committer: Alex Man <al...@users.noreply.github.com>
Committed: Fri Mar 3 16:57:17 2017 -0800

----------------------------------------------------------------------
 examples/pom.xml  |  96 ++++-----
 repl/pom.xml      | 450 +++++++++++++++++++++---------------------
 scala-api/pom.xml | 114 +++++------
 server/pom.xml    | 522 ++++++++++++++++++++++++-------------------------
 4 files changed, 591 insertions(+), 591 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/126b57e2/examples/pom.xml
----------------------------------------------------------------------
diff --git a/examples/pom.xml b/examples/pom.xml
index fccbe40..66a1c61 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -19,58 +19,58 @@
 <project xmlns="http://maven.apache.org/POM/4.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>com.cloudera.livy</groupId>
-        <artifactId>livy-main</artifactId>
-        <version>0.4.0-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
+  <modelVersion>4.0.0</modelVersion>
 
+  <parent>
     <groupId>com.cloudera.livy</groupId>
-    <artifactId>livy-examples</artifactId>
+    <artifactId>livy-main</artifactId>
     <version>0.4.0-SNAPSHOT</version>
-    <packaging>jar</packaging>
+    <relativePath>../pom.xml</relativePath>
+  </parent>
+
+  <groupId>com.cloudera.livy</groupId>
+  <artifactId>livy-examples</artifactId>
+  <version>0.4.0-SNAPSHOT</version>
+  <packaging>jar</packaging>
 
-    <properties>
-        <skipTests>true</skipTests>
-        <skip>true</skip>
-        <skipDeploy>true</skipDeploy>
-    </properties>
+  <properties>
+    <skipTests>true</skipTests>
+    <skip>true</skip>
+    <skipDeploy>true</skipDeploy>
+  </properties>
 
-    <dependencies>
-        <dependency>
-            <groupId>com.cloudera.livy</groupId>
-            <artifactId>livy-api</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>com.cloudera.livy</groupId>
-            <artifactId>livy-scala-api_${scala.binary.version}</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>com.cloudera.livy</groupId>
-            <artifactId>livy-client-http</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.spark</groupId>
-            <artifactId>spark-core_${scala.binary.version}</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.spark</groupId>
-            <artifactId>spark-sql_${scala.binary.version}</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.spark</groupId>
-            <artifactId>spark-hive_${scala.binary.version}</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.spark</groupId>
-            <artifactId>spark-streaming_${scala.binary.version}</artifactId>
-        </dependency>
-    </dependencies>
+  <dependencies>
+    <dependency>
+      <groupId>com.cloudera.livy</groupId>
+      <artifactId>livy-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.cloudera.livy</groupId>
+      <artifactId>livy-scala-api_${scala.binary.version}</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.cloudera.livy</groupId>
+      <artifactId>livy-client-http</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.spark</groupId>
+      <artifactId>spark-core_${scala.binary.version}</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.spark</groupId>
+      <artifactId>spark-sql_${scala.binary.version}</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.spark</groupId>
+      <artifactId>spark-hive_${scala.binary.version}</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.spark</groupId>
+      <artifactId>spark-streaming_${scala.binary.version}</artifactId>
+    </dependency>
+  </dependencies>
 
 </project>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/126b57e2/repl/pom.xml
----------------------------------------------------------------------
diff --git a/repl/pom.xml b/repl/pom.xml
index 5b67824..12675f7 100644
--- a/repl/pom.xml
+++ b/repl/pom.xml
@@ -19,231 +19,231 @@
 <project xmlns="http://maven.apache.org/POM/4.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <groupId>com.cloudera.livy</groupId>
-        <artifactId>multi-scala-project-root</artifactId>
-        <relativePath>../scala/pom.xml</relativePath>
-        <version>0.4.0-SNAPSHOT</version>
-    </parent>
-
-    <artifactId>livy-repl-parent</artifactId>
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>com.cloudera.livy</groupId>
+    <artifactId>multi-scala-project-root</artifactId>
+    <relativePath>../scala/pom.xml</relativePath>
     <version>0.4.0-SNAPSHOT</version>
-    <packaging>pom</packaging>
-
-    <properties>
-        <skipDeploy>true</skipDeploy>
-    </properties>
-
-    <dependencies>
-
-        <dependency>
-            <groupId>com.cloudera.livy</groupId>
-            <artifactId>livy-rsc</artifactId>
-            <version>${project.version}</version>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>com.cloudera.livy</groupId>
-            <artifactId>livy-core_${scala.binary.version}</artifactId>
-            <version>${project.version}</version>
-            <exclusions>
-                <!-- Provided and shaded by livy-rsc already. -->
-                <exclusion>
-                    <groupId>com.cloudera.livy</groupId>
-                    <artifactId>livy-client-common</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-
-        <dependency>
-            <groupId>${project.groupId}</groupId>
-            <artifactId>livy-core_${scala.binary.version}</artifactId>
-            <version>${project.version}</version>
-            <type>test-jar</type>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>com.fasterxml.jackson.core</groupId>
-            <artifactId>jackson-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>com.fasterxml.jackson.module</groupId>
-            <artifactId>jackson-module-scala_${scala.binary.version}</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>com.fasterxml.jackson.core</groupId>
-            <artifactId>jackson-databind</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>commons-codec</groupId>
-            <artifactId>commons-codec</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>log4j</groupId>
-            <artifactId>log4j</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.spark</groupId>
-            <artifactId>spark-repl_${scala.binary.version}</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.spark</groupId>
-            <artifactId>spark-core_${scala.binary.version}</artifactId>
-            <version>${spark.version}</version>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.spark</groupId>
-            <artifactId>spark-hive_${scala.binary.version}</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.json4s</groupId>
-            <artifactId>json4s-ast_${scala.binary.version}</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.json4s</groupId>
-            <artifactId>json4s-core_${scala.binary.version}</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.json4s</groupId>
-            <artifactId>json4s-jackson_${scala.binary.version}</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.scala-lang</groupId>
-            <artifactId>scala-compiler</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.scala-lang</groupId>
-            <artifactId>scala-library</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.scala-lang</groupId>
-            <artifactId>scala-reflect</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>net.sf.py4j</groupId>
-            <artifactId>py4j</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-    </dependencies>
-
-    <build>
-        <plugins>
-
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-shade-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>shade</id>
-                        <phase>package</phase>
-                        <goals>
-                            <goal>shade</goal>
-                        </goals>
-                        <configuration>
-                            <shadedArtifactAttached>false</shadedArtifactAttached>
-                            <artifactSet>
-                                <includes>
-                                    <include>org.json4s:json4s-ast_${scala.binary.version}</include>
-                                    <include>org.json4s:json4s-core_${scala.binary.version}</include>
-                                    <include>org.json4s:json4s-jackson_${scala.binary.version}</include>
-                                </includes>
-                            </artifactSet>
-                            <filters>
-                                <filter>
-                                    <artifact>*:*</artifact>
-                                    <excludes>
-                                        <exclude>*.jar</exclude>
-                                        <exclude>META-INF/maven/**</exclude>
-                                    </excludes>
-                                </filter>
-                            </filters>
-                            <relocations>
-                                <relocation>
-                                    <pattern>org.json4s</pattern>
-                                    <shadedPattern>com.cloudera.livy.shaded.json4s</shadedPattern>
-                                </relocation>
-                            </relocations>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-dependency-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <phase>package</phase>
-                        <goals>
-                            <goal>copy-dependencies</goal>
-                        </goals>
-                        <configuration>
-                            <excludeArtifactIds>
-                                json4s-ast_${scala.binary.version},
-                                json4s-core_${scala.binary.version},
-                                json4s-jackson_${scala.binary.version},
-                                paranamer,
-                                scalap
-                            </excludeArtifactIds>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-jar-plugin</artifactId>
-                <configuration>
-                    <outputDirectory>${project.build.directory}/jars</outputDirectory>
-                </configuration>
-            </plugin>
-
-            <plugin>
-                <groupId>org.scalatest</groupId>
-                <artifactId>scalatest-maven-plugin</artifactId>
-                <configuration>
-                    <systemProperties>
-                        <spark.app.name>Livy</spark.app.name>
-                        <spark.master>local</spark.master>
-                    </systemProperties>
-                </configuration>
-            </plugin>
-
-        </plugins>
-    </build>
+  </parent>
+
+  <artifactId>livy-repl-parent</artifactId>
+  <version>0.4.0-SNAPSHOT</version>
+  <packaging>pom</packaging>
+
+  <properties>
+    <skipDeploy>true</skipDeploy>
+  </properties>
+
+  <dependencies>
+
+    <dependency>
+      <groupId>com.cloudera.livy</groupId>
+      <artifactId>livy-rsc</artifactId>
+      <version>${project.version}</version>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>com.cloudera.livy</groupId>
+      <artifactId>livy-core_${scala.binary.version}</artifactId>
+      <version>${project.version}</version>
+      <exclusions>
+        <!-- Provided and shaded by livy-rsc already. -->
+        <exclusion>
+          <groupId>com.cloudera.livy</groupId>
+          <artifactId>livy-client-common</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>livy-core_${scala.binary.version}</artifactId>
+      <version>${project.version}</version>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-core</artifactId>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>com.fasterxml.jackson.module</groupId>
+      <artifactId>jackson-module-scala_${scala.binary.version}</artifactId>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-databind</artifactId>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>commons-codec</groupId>
+      <artifactId>commons-codec</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>log4j</groupId>
+      <artifactId>log4j</artifactId>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.spark</groupId>
+      <artifactId>spark-repl_${scala.binary.version}</artifactId>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.spark</groupId>
+      <artifactId>spark-core_${scala.binary.version}</artifactId>
+      <version>${spark.version}</version>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.spark</groupId>
+      <artifactId>spark-hive_${scala.binary.version}</artifactId>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.json4s</groupId>
+      <artifactId>json4s-ast_${scala.binary.version}</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.json4s</groupId>
+      <artifactId>json4s-core_${scala.binary.version}</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.json4s</groupId>
+      <artifactId>json4s-jackson_${scala.binary.version}</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.scala-lang</groupId>
+      <artifactId>scala-compiler</artifactId>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.scala-lang</groupId>
+      <artifactId>scala-library</artifactId>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.scala-lang</groupId>
+      <artifactId>scala-reflect</artifactId>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>net.sf.py4j</groupId>
+      <artifactId>py4j</artifactId>
+      <scope>provided</scope>
+    </dependency>
+
+  </dependencies>
+
+  <build>
+    <plugins>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-shade-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>shade</id>
+            <phase>package</phase>
+            <goals>
+              <goal>shade</goal>
+            </goals>
+            <configuration>
+              <shadedArtifactAttached>false</shadedArtifactAttached>
+              <artifactSet>
+                <includes>
+                  <include>org.json4s:json4s-ast_${scala.binary.version}</include>
+                  <include>org.json4s:json4s-core_${scala.binary.version}</include>
+                  <include>org.json4s:json4s-jackson_${scala.binary.version}</include>
+                </includes>
+              </artifactSet>
+              <filters>
+                <filter>
+                  <artifact>*:*</artifact>
+                  <excludes>
+                    <exclude>*.jar</exclude>
+                    <exclude>META-INF/maven/**</exclude>
+                  </excludes>
+                </filter>
+              </filters>
+              <relocations>
+                <relocation>
+                  <pattern>org.json4s</pattern>
+                  <shadedPattern>com.cloudera.livy.shaded.json4s</shadedPattern>
+                </relocation>
+              </relocations>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-dependency-plugin</artifactId>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>copy-dependencies</goal>
+            </goals>
+            <configuration>
+              <excludeArtifactIds>
+                json4s-ast_${scala.binary.version},
+                json4s-core_${scala.binary.version},
+                json4s-jackson_${scala.binary.version},
+                paranamer,
+                scalap
+              </excludeArtifactIds>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <outputDirectory>${project.build.directory}/jars</outputDirectory>
+        </configuration>
+      </plugin>
+
+      <plugin>
+        <groupId>org.scalatest</groupId>
+        <artifactId>scalatest-maven-plugin</artifactId>
+        <configuration>
+          <systemProperties>
+            <spark.app.name>Livy</spark.app.name>
+            <spark.master>local</spark.master>
+          </systemProperties>
+        </configuration>
+      </plugin>
+
+    </plugins>
+  </build>
 
 </project>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/126b57e2/scala-api/pom.xml
----------------------------------------------------------------------
diff --git a/scala-api/pom.xml b/scala-api/pom.xml
index 3d67128..91b2e9c 100644
--- a/scala-api/pom.xml
+++ b/scala-api/pom.xml
@@ -19,65 +19,65 @@
 <project xmlns="http://maven.apache.org/POM/4.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
+  <modelVersion>4.0.0</modelVersion>
 
-    <parent>
-        <groupId>com.cloudera.livy</groupId>
-        <artifactId>multi-scala-project-root</artifactId>
-        <version>0.4.0-SNAPSHOT</version>
-        <relativePath>../scala/pom.xml</relativePath>
-    </parent>
-
-    <artifactId>livy-scala-api-parent</artifactId>
+  <parent>
+    <groupId>com.cloudera.livy</groupId>
+    <artifactId>multi-scala-project-root</artifactId>
     <version>0.4.0-SNAPSHOT</version>
-    <packaging>pom</packaging>
+    <relativePath>../scala/pom.xml</relativePath>
+  </parent>
+
+  <artifactId>livy-scala-api-parent</artifactId>
+  <version>0.4.0-SNAPSHOT</version>
+  <packaging>pom</packaging>
 
-    <dependencies>
-        <dependency>
-            <groupId>com.cloudera.livy</groupId>
-            <artifactId>livy-api</artifactId>
-            <version>${project.version}</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>com.cloudera.livy</groupId>
-            <artifactId>livy-rsc</artifactId>
-            <version>${project.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>com.cloudera.livy</groupId>
-            <artifactId>livy-core_${scala.binary.version}</artifactId>
-            <version>${project.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>com.cloudera.livy</groupId>
-            <artifactId>livy-core_${scala.binary.version}</artifactId>
-            <version>${project.version}</version>
-            <type>test-jar</type>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.spark</groupId>
-            <artifactId>spark-core_${scala.binary.version}</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.spark</groupId>
-            <artifactId>spark-sql_${scala.binary.version}</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.spark</groupId>
-            <artifactId>spark-hive_${scala.binary.version}</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.spark</groupId>
-            <artifactId>spark-streaming_${scala.binary.version}</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
+  <dependencies>
+    <dependency>
+      <groupId>com.cloudera.livy</groupId>
+      <artifactId>livy-api</artifactId>
+      <version>${project.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.cloudera.livy</groupId>
+      <artifactId>livy-rsc</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.cloudera.livy</groupId>
+      <artifactId>livy-core_${scala.binary.version}</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.cloudera.livy</groupId>
+      <artifactId>livy-core_${scala.binary.version}</artifactId>
+      <version>${project.version}</version>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.spark</groupId>
+      <artifactId>spark-core_${scala.binary.version}</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.spark</groupId>
+      <artifactId>spark-sql_${scala.binary.version}</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.spark</groupId>
+      <artifactId>spark-hive_${scala.binary.version}</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.spark</groupId>
+      <artifactId>spark-streaming_${scala.binary.version}</artifactId>
+      <scope>provided</scope>
+    </dependency>
+  </dependencies>
 </project>
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/126b57e2/server/pom.xml
----------------------------------------------------------------------
diff --git a/server/pom.xml b/server/pom.xml
index 3226b6e..7ca8c65 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -19,268 +19,268 @@
 <project xmlns="http://maven.apache.org/POM/4.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <groupId>com.cloudera.livy</groupId>
-        <artifactId>livy-main</artifactId>
-        <relativePath>../pom.xml</relativePath>
-        <version>0.4.0-SNAPSHOT</version>
-    </parent>
-
-    <artifactId>livy-server</artifactId>
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>com.cloudera.livy</groupId>
+    <artifactId>livy-main</artifactId>
+    <relativePath>../pom.xml</relativePath>
     <version>0.4.0-SNAPSHOT</version>
-    <packaging>jar</packaging>
-
-    <properties>
-        <skipDeploy>true</skipDeploy>
-    </properties>
-
-    <dependencies>
-
-        <dependency>
-            <groupId>${project.groupId}</groupId>
-            <artifactId>livy-core_${scala.binary.version}</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-
-        <dependency>
-            <groupId>${project.groupId}</groupId>
-            <artifactId>livy-core_${scala.binary.version}</artifactId>
-            <version>${project.version}</version>
-            <type>test-jar</type>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>${project.groupId}</groupId>
-            <artifactId>livy-rsc</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-
-        <dependency>
-            <groupId>com.cloudera.livy</groupId>
-            <artifactId>livy-test-lib</artifactId>
-            <version>${project.version}</version>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>com.fasterxml.jackson.core</groupId>
-            <artifactId>jackson-core</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>com.fasterxml.jackson.core</groupId>
-            <artifactId>jackson-databind</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>com.fasterxml.jackson.module</groupId>
-            <artifactId>jackson-module-scala_${scala.binary.version}</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>io.dropwizard.metrics</groupId>
-            <artifactId>metrics-core</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>io.dropwizard.metrics</groupId>
-            <artifactId>metrics-healthchecks</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>javax.servlet</groupId>
-            <artifactId>javax.servlet-api</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.hadoop</groupId>
-            <artifactId>hadoop-auth</artifactId>
-            <scope>${hadoop.scope}</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.hadoop</groupId>
-            <artifactId>hadoop-client</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>javax.servlet</groupId>
-                    <artifactId>servlet-api</artifactId>
-                </exclusion>
-            </exclusions>
-            <scope>${hadoop.scope}</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.httpcomponents</groupId>
-            <artifactId>httpclient</artifactId>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.eclipse.jetty</groupId>
-            <artifactId>jetty-server</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.eclipse.jetty</groupId>
-            <artifactId>jetty-servlet</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.json4s</groupId>
-            <artifactId>json4s-ast_${scala.binary.version}</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.json4s</groupId>
-            <artifactId>json4s-core_${scala.binary.version}</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.json4s</groupId>
-            <artifactId>json4s-jackson_${scala.binary.version}</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.scala-lang</groupId>
-            <artifactId>scala-library</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.scalatra</groupId>
-            <artifactId>scalatra_${scala.binary.version}</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.scalatra</groupId>
-            <artifactId>scalatra-json_${scala.binary.version}</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.scalatra</groupId>
-            <artifactId>scalatra-metrics_${scala.binary.version}</artifactId>
-            <version>2.4.0.M3</version>
-            <exclusions>
-                <exclusion>
-                    <groupId>com.typesafe.akka</groupId>
-                    <artifactId>akka-actor_${scala.binary.version}</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>com.cloudera.livy</groupId>
-            <artifactId>livy-repl_${scala.binary.version}</artifactId>
-            <version>${project.version}</version>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.spark</groupId>
-            <artifactId>spark-core_${scala.binary.version}</artifactId>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.spark</groupId>
-            <artifactId>spark-repl_${scala.binary.version}</artifactId>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.spark</groupId>
-            <artifactId>spark-sql_${scala.binary.version}</artifactId>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.spark</groupId>
-            <artifactId>spark-streaming_${scala.binary.version}</artifactId>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.spark</groupId>
-            <artifactId>spark-hive_${scala.binary.version}</artifactId>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.scalatra</groupId>
-            <artifactId>scalatra-test_${scala.binary.version}</artifactId>
-            <scope>test</scope>
-        </dependency>
-
-    </dependencies>
-
-    <build>
-        <resources>
-            <resource>
-                <!-- Include the properties file to provide the build information. -->
-                <directory>${project.build.directory}/extra-resources</directory>
-                <filtering>true</filtering>
-            </resource>
-        </resources>
-
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-jar-plugin</artifactId>
-                <configuration>
-                    <archive>
-                        <manifest>
-                            <mainClass>com.cloudera.livy.server.Main</mainClass>
-                        </manifest>
-                    </archive>
-                    <outputDirectory>${project.build.directory}/jars</outputDirectory>
-                </configuration>
-            </plugin>
-
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-dependency-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <phase>package</phase>
-                        <goals>
-                            <goal>copy-dependencies</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-antrun-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <phase>generate-resources</phase>
-                        <configuration>
-                            <!-- Execute the shell script to generate the spark build information. -->
-                            <target>
-                                <exec executable="bash">
-                                    <arg value="${project.basedir}/../dev/livy-build-info.sh"/>
-                                    <arg value="${project.build.directory}/extra-resources"/>
-                                    <arg value="${project.version}"/>
-                                </exec>
-                            </target>
-                        </configuration>
-                        <goals>
-                            <goal>run</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-
-        </plugins>
-    </build>
+  </parent>
+
+  <artifactId>livy-server</artifactId>
+  <version>0.4.0-SNAPSHOT</version>
+  <packaging>jar</packaging>
+
+  <properties>
+    <skipDeploy>true</skipDeploy>
+  </properties>
+
+  <dependencies>
+
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>livy-core_${scala.binary.version}</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>livy-core_${scala.binary.version}</artifactId>
+      <version>${project.version}</version>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>livy-rsc</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>com.cloudera.livy</groupId>
+      <artifactId>livy-test-lib</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-core</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-databind</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>com.fasterxml.jackson.module</groupId>
+      <artifactId>jackson-module-scala_${scala.binary.version}</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>io.dropwizard.metrics</groupId>
+      <artifactId>metrics-core</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>io.dropwizard.metrics</groupId>
+      <artifactId>metrics-healthchecks</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>javax.servlet-api</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.hadoop</groupId>
+      <artifactId>hadoop-auth</artifactId>
+      <scope>${hadoop.scope}</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.hadoop</groupId>
+      <artifactId>hadoop-client</artifactId>
+      <exclusions>
+        <exclusion>
+          <groupId>javax.servlet</groupId>
+          <artifactId>servlet-api</artifactId>
+        </exclusion>
+      </exclusions>
+      <scope>${hadoop.scope}</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.httpcomponents</groupId>
+      <artifactId>httpclient</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-server</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-servlet</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.json4s</groupId>
+      <artifactId>json4s-ast_${scala.binary.version}</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.json4s</groupId>
+      <artifactId>json4s-core_${scala.binary.version}</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.json4s</groupId>
+      <artifactId>json4s-jackson_${scala.binary.version}</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.scala-lang</groupId>
+      <artifactId>scala-library</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.scalatra</groupId>
+      <artifactId>scalatra_${scala.binary.version}</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.scalatra</groupId>
+      <artifactId>scalatra-json_${scala.binary.version}</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.scalatra</groupId>
+      <artifactId>scalatra-metrics_${scala.binary.version}</artifactId>
+      <version>2.4.0.M3</version>
+      <exclusions>
+        <exclusion>
+          <groupId>com.typesafe.akka</groupId>
+          <artifactId>akka-actor_${scala.binary.version}</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>com.cloudera.livy</groupId>
+      <artifactId>livy-repl_${scala.binary.version}</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.spark</groupId>
+      <artifactId>spark-core_${scala.binary.version}</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.spark</groupId>
+      <artifactId>spark-repl_${scala.binary.version}</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.spark</groupId>
+      <artifactId>spark-sql_${scala.binary.version}</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.spark</groupId>
+      <artifactId>spark-streaming_${scala.binary.version}</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.spark</groupId>
+      <artifactId>spark-hive_${scala.binary.version}</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.scalatra</groupId>
+      <artifactId>scalatra-test_${scala.binary.version}</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+  </dependencies>
+
+  <build>
+    <resources>
+      <resource>
+        <!-- Include the properties file to provide the build information. -->
+        <directory>${project.build.directory}/extra-resources</directory>
+        <filtering>true</filtering>
+      </resource>
+    </resources>
+
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <manifest>
+              <mainClass>com.cloudera.livy.server.Main</mainClass>
+            </manifest>
+          </archive>
+          <outputDirectory>${project.build.directory}/jars</outputDirectory>
+        </configuration>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-dependency-plugin</artifactId>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>copy-dependencies</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-antrun-plugin</artifactId>
+        <executions>
+          <execution>
+            <phase>generate-resources</phase>
+            <configuration>
+              <!-- Execute the shell script to generate the spark build information. -->
+              <target>
+                <exec executable="bash">
+                  <arg value="${project.basedir}/../dev/livy-build-info.sh"/>
+                  <arg value="${project.build.directory}/extra-resources"/>
+                  <arg value="${project.version}"/>
+                </exec>
+              </target>
+            </configuration>
+            <goals>
+              <goal>run</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+
+    </plugins>
+  </build>
 
 </project>
 



[37/50] [abbrv] incubator-livy git commit: LIVY-340. Add YARN queue support to interactive sessions. (#314)

Posted by js...@apache.org.
LIVY-340. Add YARN queue support to interactive sessions. (#314)



Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/7212e3f3
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/7212e3f3
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/7212e3f3

Branch: refs/heads/master
Commit: 7212e3f3bbed07ab8ea372cd7a56ee1cd2b56693
Parents: 511a05f
Author: Praveen Kanamarlapudi <kp...@outlook.com>
Authored: Tue Apr 18 13:02:23 2017 -0700
Committer: Alex Man <al...@users.noreply.github.com>
Committed: Tue Apr 18 13:02:23 2017 -0700

----------------------------------------------------------------------
 .../com/cloudera/livy/server/interactive/InteractiveSession.scala | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/7212e3f3/server/src/main/scala/com/cloudera/livy/server/interactive/InteractiveSession.scala
----------------------------------------------------------------------
diff --git a/server/src/main/scala/com/cloudera/livy/server/interactive/InteractiveSession.scala b/server/src/main/scala/com/cloudera/livy/server/interactive/InteractiveSession.scala
index b53dea7..6d10c57 100644
--- a/server/src/main/scala/com/cloudera/livy/server/interactive/InteractiveSession.scala
+++ b/server/src/main/scala/com/cloudera/livy/server/interactive/InteractiveSession.scala
@@ -88,7 +88,8 @@ object InteractiveSession extends Logging {
         SparkLauncher.EXECUTOR_CORES -> request.executorCores.map(_.toString),
         SparkLauncher.EXECUTOR_MEMORY -> request.executorMemory.map(_.toString),
         "spark.executor.instances" -> request.numExecutors.map(_.toString),
-        "spark.app.name" -> request.name.map(_.toString)
+        "spark.app.name" -> request.name.map(_.toString),
+        "spark.yarn.queue" -> request.queue
       )
 
       userOpts.foreach { case (key, opt) =>


[17/50] [abbrv] incubator-livy git commit: Fix issue for some parent poms (#295)

Posted by js...@apache.org.
Fix issue for some parent poms (#295)

Change-Id: Ibf549db71b0f6dfc2004c3ff602e92860a38a093

Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/14c29e4d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/14c29e4d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/14c29e4d

Branch: refs/heads/master
Commit: 14c29e4d425f44d1f3caad1469a2ea4e136f0f44
Parents: ed1c86e
Author: Saisai Shao <sa...@gmail.com>
Authored: Mon Feb 20 16:37:26 2017 +0800
Committer: Jeff Zhang <zj...@gmail.com>
Committed: Mon Feb 20 16:37:26 2017 +0800

----------------------------------------------------------------------
 core/pom.xml                                    | 16 -------
 core/scala-2.10/pom.xml                         | 17 ++++++++
 core/scala-2.11/pom.xml                         | 17 ++++++++
 core/src/main/resources/build.marker            |  0
 .../src/main/resources/build.marker             |  0
 pom.xml                                         | 44 +++++++++++++++-----
 repl/src/main/resources/build.marker            |  0
 .../cloudera/livy/repl/ProcessInterpreter.scala |  2 +-
 .../com/cloudera/livy/repl/ReplDriver.scala     |  2 +-
 .../cloudera/livy/repl/SparkRInterpreter.scala  |  2 +-
 .../livy/repl/PythonInterpreterSpec.scala       |  2 +-
 scala-api/src/main/resources/build.marker       |  0
 scala/pom.xml                                   | 13 ------
 13 files changed, 72 insertions(+), 43 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/14c29e4d/core/pom.xml
----------------------------------------------------------------------
diff --git a/core/pom.xml b/core/pom.xml
index ae2be28..75da834 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -68,20 +68,4 @@
     </dependency>
   </dependencies>
 
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-jar-plugin</artifactId>
-        <executions>
-          <execution>
-            <goals>
-              <goal>test-jar</goal>
-            </goals>
-          </execution>
-        </executions>
-      </plugin>
-    </plugins>
-  </build>
-
 </project>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/14c29e4d/core/scala-2.10/pom.xml
----------------------------------------------------------------------
diff --git a/core/scala-2.10/pom.xml b/core/scala-2.10/pom.xml
index 27fbcba..6ac60d6 100644
--- a/core/scala-2.10/pom.xml
+++ b/core/scala-2.10/pom.xml
@@ -34,4 +34,21 @@
     <scala.version>${scala-2.10.version}</scala.version>
     <scala.binary.version>2.10</scala.binary.version>
   </properties>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <executions>
+          <execution>
+            <goals>
+              <goal>test-jar</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+
 </project>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/14c29e4d/core/scala-2.11/pom.xml
----------------------------------------------------------------------
diff --git a/core/scala-2.11/pom.xml b/core/scala-2.11/pom.xml
index afb0c77..e9e57df 100644
--- a/core/scala-2.11/pom.xml
+++ b/core/scala-2.11/pom.xml
@@ -34,4 +34,21 @@
     <scala.version>${scala-2.11.version}</scala.version>
     <scala.binary.version>2.11</scala.binary.version>
   </properties>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <executions>
+          <execution>
+            <goals>
+              <goal>test-jar</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+
 </project>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/14c29e4d/core/src/main/resources/build.marker
----------------------------------------------------------------------
diff --git a/core/src/main/resources/build.marker b/core/src/main/resources/build.marker
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/14c29e4d/integration-test/minicluster-dependencies/src/main/resources/build.marker
----------------------------------------------------------------------
diff --git a/integration-test/minicluster-dependencies/src/main/resources/build.marker b/integration-test/minicluster-dependencies/src/main/resources/build.marker
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/14c29e4d/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 8868d35..fbc4d84 100644
--- a/pom.xml
+++ b/pom.xml
@@ -180,18 +180,23 @@
     <module>assembly</module>
     <module>client-common</module>
     <module>client-http</module>
+    <module>core</module>
     <module>core/scala-2.10</module>
     <module>core/scala-2.11</module>
     <module>coverage</module>
     <module>examples</module>
     <module>python-api</module>
+    <module>repl</module>
     <module>repl/scala-2.10</module>
     <module>repl/scala-2.11</module>
     <module>rsc</module>
+    <module>scala</module>
+    <module>scala-api</module>
     <module>scala-api/scala-2.10</module>
     <module>scala-api/scala-2.11</module>
     <module>server</module>
     <module>test-lib</module>
+    <module>integration-test/minicluster-dependencies</module>
     <module>integration-test/minicluster-dependencies/scala-2.10</module>
     <module>integration-test/minicluster-dependencies/scala-2.11</module>
     <module>integration-test</module>
@@ -622,6 +627,13 @@
                 <goal>testCompile</goal>
               </goals>
             </execution>
+            <execution>
+              <id>scala-compile-first</id>
+              <phase>process-resources</phase>
+              <goals>
+                <goal>compile</goal>
+              </goals>
+            </execution>
           </executions>
           <configuration>
             <scalaVersion>${scala.version}</scalaVersion>
@@ -789,11 +801,6 @@
       </plugin>
 
       <plugin>
-        <groupId>net.alchim31.maven</groupId>
-        <artifactId>scala-maven-plugin</artifactId>
-      </plugin>
-
-      <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-antrun-plugin</artifactId>
         <executions>
@@ -933,11 +940,6 @@
       </plugin>
 
       <plugin>
-        <groupId>org.scalatest</groupId>
-        <artifactId>scalatest-maven-plugin</artifactId>
-      </plugin>
-
-      <plugin>
         <groupId>org.jacoco</groupId>
         <artifactId>jacoco-maven-plugin</artifactId>
         <version>0.7.7.201606060606</version>
@@ -1017,6 +1019,28 @@
         <spark.version>2.1.0</spark.version>
       </properties>
     </profile>
+
+    <profile>
+      <id>skip-parent-modules</id>
+      <activation>
+        <file>
+          <missing>src/main/resources/build.marker</missing>
+        </file>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.scalatest</groupId>
+            <artifactId>scalatest-maven-plugin</artifactId>
+          </plugin>
+          <plugin>
+            <groupId>net.alchim31.maven</groupId>
+            <artifactId>scala-maven-plugin</artifactId>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+
   </profiles>
 
 </project>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/14c29e4d/repl/src/main/resources/build.marker
----------------------------------------------------------------------
diff --git a/repl/src/main/resources/build.marker b/repl/src/main/resources/build.marker
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/14c29e4d/repl/src/main/scala/com/cloudera/livy/repl/ProcessInterpreter.scala
----------------------------------------------------------------------
diff --git a/repl/src/main/scala/com/cloudera/livy/repl/ProcessInterpreter.scala b/repl/src/main/scala/com/cloudera/livy/repl/ProcessInterpreter.scala
index 25a8654..c4fb8ca 100644
--- a/repl/src/main/scala/com/cloudera/livy/repl/ProcessInterpreter.scala
+++ b/repl/src/main/scala/com/cloudera/livy/repl/ProcessInterpreter.scala
@@ -18,7 +18,7 @@
 
 package com.cloudera.livy.repl
 
-import java.io.{BufferedReader, IOException, InputStreamReader, PrintWriter}
+import java.io.{BufferedReader, InputStreamReader, IOException, PrintWriter}
 import java.util.concurrent.locks.ReentrantLock
 
 import scala.concurrent.Promise

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/14c29e4d/repl/src/main/scala/com/cloudera/livy/repl/ReplDriver.scala
----------------------------------------------------------------------
diff --git a/repl/src/main/scala/com/cloudera/livy/repl/ReplDriver.scala b/repl/src/main/scala/com/cloudera/livy/repl/ReplDriver.scala
index 8c705fc..c176412 100644
--- a/repl/src/main/scala/com/cloudera/livy/repl/ReplDriver.scala
+++ b/repl/src/main/scala/com/cloudera/livy/repl/ReplDriver.scala
@@ -26,8 +26,8 @@ import org.apache.spark.SparkConf
 import org.apache.spark.api.java.JavaSparkContext
 
 import com.cloudera.livy.Logging
-import com.cloudera.livy.rsc.BaseProtocol.ReplState
 import com.cloudera.livy.rsc.{BaseProtocol, ReplJobResults, RSCConf}
+import com.cloudera.livy.rsc.BaseProtocol.ReplState
 import com.cloudera.livy.rsc.driver._
 import com.cloudera.livy.rsc.rpc.Rpc
 import com.cloudera.livy.sessions._

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/14c29e4d/repl/src/main/scala/com/cloudera/livy/repl/SparkRInterpreter.scala
----------------------------------------------------------------------
diff --git a/repl/src/main/scala/com/cloudera/livy/repl/SparkRInterpreter.scala b/repl/src/main/scala/com/cloudera/livy/repl/SparkRInterpreter.scala
index 6c42fe3..cc57d72 100644
--- a/repl/src/main/scala/com/cloudera/livy/repl/SparkRInterpreter.scala
+++ b/repl/src/main/scala/com/cloudera/livy/repl/SparkRInterpreter.scala
@@ -28,9 +28,9 @@ import scala.collection.JavaConverters._
 import scala.reflect.runtime.universe
 
 import org.apache.commons.codec.binary.Base64
+import org.apache.commons.lang.StringEscapeUtils
 import org.apache.spark.{SparkConf, SparkContext}
 import org.apache.spark.util.{ChildFirstURLClassLoader, MutableURLClassLoader, Utils}
-import org.apache.commons.lang.StringEscapeUtils
 import org.json4s._
 import org.json4s.JsonDSL._
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/14c29e4d/repl/src/test/scala/com/cloudera/livy/repl/PythonInterpreterSpec.scala
----------------------------------------------------------------------
diff --git a/repl/src/test/scala/com/cloudera/livy/repl/PythonInterpreterSpec.scala b/repl/src/test/scala/com/cloudera/livy/repl/PythonInterpreterSpec.scala
index a2733ab..00bbc68 100644
--- a/repl/src/test/scala/com/cloudera/livy/repl/PythonInterpreterSpec.scala
+++ b/repl/src/test/scala/com/cloudera/livy/repl/PythonInterpreterSpec.scala
@@ -19,7 +19,7 @@
 package com.cloudera.livy.repl
 
 import org.apache.spark.SparkConf
-import org.json4s.{DefaultFormats, JValue, JNull}
+import org.json4s.{DefaultFormats, JNull, JValue}
 import org.json4s.JsonDSL._
 import org.scalatest._
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/14c29e4d/scala-api/src/main/resources/build.marker
----------------------------------------------------------------------
diff --git a/scala-api/src/main/resources/build.marker b/scala-api/src/main/resources/build.marker
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/14c29e4d/scala/pom.xml
----------------------------------------------------------------------
diff --git a/scala/pom.xml b/scala/pom.xml
index 447c341..2d25d9d 100644
--- a/scala/pom.xml
+++ b/scala/pom.xml
@@ -100,19 +100,6 @@
           </execution>
         </executions>
       </plugin>
-      <plugin>
-        <groupId>net.alchim31.maven</groupId>
-        <artifactId>scala-maven-plugin</artifactId>
-        <executions>
-          <execution>
-            <id>scala-compile-first</id>
-            <phase>process-resources</phase>
-            <goals>
-              <goal>compile</goal>
-            </goals>
-          </execution>
-        </executions>
-      </plugin>
     </plugins>
   </build>
 


[25/50] [abbrv] incubator-livy git commit: LIVY-90. Update conf dir to use templates (#301)

Posted by js...@apache.org.
LIVY-90. Update conf dir to use templates (#301)

- Added instructions to livy-client template.
- Filled out livy-client.conf.template.
- Updated conf naming to all camelCase, switched conf files to templates and updated .gitignore.

Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/76d969e5
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/76d969e5
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/76d969e5

Branch: refs/heads/master
Commit: 76d969e58586f0fe2e707cc0bf81fdf595b01792
Parents: d74d5a9
Author: Alex Bozarth <aj...@us.ibm.com>
Authored: Fri Mar 3 16:51:58 2017 -0800
Committer: Alex Man <al...@users.noreply.github.com>
Committed: Fri Mar 3 16:51:58 2017 -0800

----------------------------------------------------------------------
 .gitignore                         |  4 ++
 conf/livy-client.conf.template     | 86 +++++++++++++++++++++++++++++
 conf/livy-env.sh                   | 33 ------------
 conf/livy-env.sh.template          | 33 ++++++++++++
 conf/livy.conf                     | 96 ---------------------------------
 conf/livy.conf.template            | 96 +++++++++++++++++++++++++++++++++
 conf/log4j.properties              | 25 ---------
 conf/log4j.properties.template     | 25 +++++++++
 conf/spark-blacklist.conf          | 19 -------
 conf/spark-blacklist.conf.template | 19 +++++++
 10 files changed, 263 insertions(+), 173 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/76d969e5/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
index 798c94f..b5ad546 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,7 +11,11 @@
 .project
 .classpath
 .scala_dependencies
+conf/*.conf
+conf/*.properties
+conf/*.sh
 lib_managed/
+logs/
 src_managed/
 target/
 reports/

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/76d969e5/conf/livy-client.conf.template
----------------------------------------------------------------------
diff --git a/conf/livy-client.conf.template b/conf/livy-client.conf.template
new file mode 100644
index 0000000..c0adb30
--- /dev/null
+++ b/conf/livy-client.conf.template
@@ -0,0 +1,86 @@
+#
+# Configurations for a Livy Client, any configurations set here will override any
+# livy or spark-default configurations.
+#
+# Before a Livy Client is able to load these configurations the folder containing
+# this file must be added to the application classpath
+#
+
+#
+# Configurations for Livy HTTPClient
+#
+
+# HTTP Request configurations
+# How long before a request times out
+# livy.client.http.connection.timeout = 10s
+# How long between data packets before a request times out
+# livy.client.http.connection.socket.timeout = 5m
+# Whether content is compressed
+# livy.client.http.content.compress.enable = true
+
+# How long before idle connections are closed
+# livy.client.http.connection.idle.timeout = 10m
+
+# Initial interval before polling for Job results
+# livy.client.http.job.initial_poll_interval = 100ms
+# Maximum interval between successive polls
+# livy.client.http.job.max_poll_interval = 5s
+
+#
+# Configurations for Livy RSCClient
+#
+
+# Configurations for registering a client with the rpc server
+# Unique client id for connections to the rpc server
+# livy.rsc.client.auth.id =
+# Secret value for authenticating client connections with server
+# livy.rsc.client.auth.secret =
+
+# Timeout when stopping a rsc client
+# livy.rsc.client.shutdown_timeout = 10s
+
+# Class of the rsc driver to use
+# livy.rsc.driver_class =
+# The kind of rsc session. Examples: pyspark or sparkr
+# livy.rsc.session.kind =
+
+# Comma-separated list of Livy RSC jars. By default Livy will upload jars from its installation
+# directory every time a session is started. By caching these files in HDFS, for example, startup
+# time of sessions on YARN can be reduced.
+# livy.rsc.jars =
+# Location of the SparkR package for running sparkr
+# livy.rsc.sparkr.package =
+# Location of the PySpark package for running pyspark
+# livy.rsc.pyspark.archives =
+
+# Address for the RSC driver to connect back with it's connection info.
+# livy.rsc.launcher.address =
+# livy.rsc.launcher.port = -1
+
+# How long will the RSC wait for a connection for a Livy server before shutting itself down.
+# livy.rsc.server.idle_timeout = 10m
+
+# The user that should be impersonated when requesting a Livy session
+# livy.rsc.proxy_user =
+
+# Host or IP adress of the rpc server
+# livy.rsc.rpc.server.address =
+# How long the rsc client will wait when attempting to connect to the Livy server
+# livy.rsc.server.connect.timeout = 90s
+
+# The logging level for the rpc channel. Possible values: TRACE, DEBUG, INFO, WARN, or ERROR
+# livy.rsc.channel.log.level =
+
+# SASL configurations for authentication
+# SASL mechanism used for authentication
+# livy.rsc.rpc.sasl.mechanisms = DIGEST-MD5
+# SASL qop used for authentication
+# livy.rsc.rpc.sasl.qop =
+
+# Time between status checks for cancelled a Job
+# livy.rsc.job_cancel.trigger_interval = 100ms
+# Time before a cancelled a Job is forced into a Cancelled state
+# livy.rsc.job_cancel.timeout = 30s
+
+# Number of statements kept in driver's memory
+# livy.rsc.retained_statements = 100
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/76d969e5/conf/livy-env.sh
----------------------------------------------------------------------
diff --git a/conf/livy-env.sh b/conf/livy-env.sh
deleted file mode 100644
index b348935..0000000
--- a/conf/livy-env.sh
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/usr/bin/env bash
-#
-# Licensed to Cloudera, Inc. under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  Cloudera, Inc. 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.
-#
-# LIVY ENVIRONMENT VARIABLES
-#
-# - JAVA_HOME       Java runtime to use. By default use "java" from PATH.
-# - HADOOP_CONF_DIR Directory containing the Hadoop / YARN configuration to use.
-# - SPARK_HOME      Spark which you would like to use in Livy.
-# - SPARK_CONF_DIR  Optional directory where the Spark configuration lives.
-#                   (Default: $SPARK_HOME/conf)
-# - LIVY_LOG_DIR    Where log files are stored. (Default: ${LIVY_HOME}/logs)
-# - LIVY_PID_DIR    Where the pid file is stored. (Default: /tmp)
-# - LIVY_SERVER_JAVA_OPTS  Java Opts for running livy server (You can set jvm related setting here,
-#                          like jvm memory/gc algorithm and etc.)
-# - LIVY_IDENT_STRING A name that identifies the Livy server instance, used to generate log file
-#                     names. (Default: name of the user starting Livy).
-# - LIVY_MAX_LOG_FILES Max number of log file to keep in the log directory. (Default: 5.)
-# - LIVY_NICENESS   Niceness of the Livy server process when running in the background. (Default: 0.)

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/76d969e5/conf/livy-env.sh.template
----------------------------------------------------------------------
diff --git a/conf/livy-env.sh.template b/conf/livy-env.sh.template
new file mode 100644
index 0000000..b348935
--- /dev/null
+++ b/conf/livy-env.sh.template
@@ -0,0 +1,33 @@
+#!/usr/bin/env bash
+#
+# Licensed to Cloudera, Inc. under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  Cloudera, Inc. 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.
+#
+# LIVY ENVIRONMENT VARIABLES
+#
+# - JAVA_HOME       Java runtime to use. By default use "java" from PATH.
+# - HADOOP_CONF_DIR Directory containing the Hadoop / YARN configuration to use.
+# - SPARK_HOME      Spark which you would like to use in Livy.
+# - SPARK_CONF_DIR  Optional directory where the Spark configuration lives.
+#                   (Default: $SPARK_HOME/conf)
+# - LIVY_LOG_DIR    Where log files are stored. (Default: ${LIVY_HOME}/logs)
+# - LIVY_PID_DIR    Where the pid file is stored. (Default: /tmp)
+# - LIVY_SERVER_JAVA_OPTS  Java Opts for running livy server (You can set jvm related setting here,
+#                          like jvm memory/gc algorithm and etc.)
+# - LIVY_IDENT_STRING A name that identifies the Livy server instance, used to generate log file
+#                     names. (Default: name of the user starting Livy).
+# - LIVY_MAX_LOG_FILES Max number of log file to keep in the log directory. (Default: 5.)
+# - LIVY_NICENESS   Niceness of the Livy server process when running in the background. (Default: 0.)

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/76d969e5/conf/livy.conf
----------------------------------------------------------------------
diff --git a/conf/livy.conf b/conf/livy.conf
deleted file mode 100644
index c23aab2..0000000
--- a/conf/livy.conf
+++ /dev/null
@@ -1,96 +0,0 @@
-# Use this keystore for the SSL certificate and key.
-# livy.keystore =
-
-# Specify the keystore password.
-# livy.keystore.password =
-
-# What host address to start the server on. By default, Livy will bind to all network interfaces.
-# livy.server.host = 0.0.0.0
-
-# What port to start the server on.
-# livy.server.port = 8998
-
-# What spark master Livy sessions should use.
-# livy.spark.master = local
-
-# What spark deploy mode Livy sessions should use.
-# livy.spark.deployMode =
-
-# Enabled to check whether timeout Livy sessions should be stopped.
-# livy.server.session.timeout-check = true
-
-# Time in milliseconds on how long Livy will wait before timing out an idle session.
-# livy.server.session.timeout = 1h
-#
-# How long a finished session state should be kept in LivyServer for query.
-# livy.server.session.state-retain.sec = 600s
-
-# If livy should impersonate the requesting users when creating a new session.
-# livy.impersonation.enabled = true
-
-# Comma-separated list of Livy RSC jars. By default Livy will upload jars from its installation
-# directory every time a session is started. By caching these files in HDFS, for example, startup
-# time of sessions on YARN can be reduced.
-# livy.rsc.jars =
-
-# Comma-separated list of Livy REPL jars. By default Livy will upload jars from its installation
-# directory every time a session is started. By caching these files in HDFS, for example, startup
-# time of sessions on YARN can be reduced. Please list all the repl dependencies including
-# livy-repl_2.10 and livy-repl_2.11 jars, Livy will automatically pick the right dependencies in
-# session creation.
-# livy.repl.jars =
-
-# Location of PySpark archives. By default Livy will upload the file from SPARK_HOME, but
-# by caching the file in HDFS, startup time of PySpark sessions on YARN can be reduced.
-# livy.pyspark.archives =
-
-# Location of the SparkR package. By default Livy will upload the file from SPARK_HOME, but
-# by caching the file in HDFS, startup time of R sessions on YARN can be reduced.
-# livy.sparkr.package =
-
-# List of local directories from where files are allowed to be added to user sessions. By
-# default it's empty, meaning users can only reference remote URIs when starting their
-# sessions.
-# livy.file.local-dir-whitelist =
-
-# Whether to enable csrf protection, by default it is false. If it is enabled, client should add
-# http-header "X-Requested-By" in request if the http method is POST/DELETE/PUT/PATCH.
-# livy.server.csrf_protection.enabled =
-
-# Whether to enable HiveContext in livy interpreter, if it is true hive-site.xml will be detected
-# on user request and then livy server classpath automatically.
-# livy.repl.enableHiveContext =
-
-# Recovery mode of Livy. Possible values:
-# off: Default. Turn off recovery. Every time Livy shuts down, it stops and forgets all sessions.
-# recovery: Livy persists session info to the state store. When Livy restarts, it recovers
-#           previous sessions from the state store.
-# Must set livy.server.recovery.state-store and livy.server.recovery.state-store.url to
-# configure the state store.
-# livy.server.recovery.mode = off
-
-# Where Livy should store state to for recovery. Possible values:
-# <empty>: Default. State store disabled.
-# filesystem: Store state on a file system.
-# zookeeper: Store state in a Zookeeper instance.
-# livy.server.recovery.state-store =
-
-# For filesystem state store, the path of the state store directory. Please don't use a filesystem
-# that doesn't support atomic rename (e.g. S3). e.g. file:///tmp/livy or hdfs:///.
-# For zookeeper, the address to the Zookeeper servers. e.g. host1:port1,host2:port2
-# livy.server.recovery.state-store.url =
-
-# If Livy can't find the yarn app within this time, consider it lost.
-# livy.server.yarn.app-lookup-timeout = 60s
-# When the cluster is busy, we may fail to launch yarn app in app-lookup-timeout, then it would
-# cause session leakage, so we need to check session leakage.
-# How long to check livy session leakage
-# livy.server.yarn.app-leakage.check_timeout = 600s
-# how often to check livy session leakage
-# livy.server.yarn.app-leakage.check_interval = 60s
-
-# How often Livy polls YARN to refresh YARN app state.
-# livy.server.yarn.poll-interval = 1s
-#
-# Days to keep Livy server request logs.
-# livy.server.request-log-retain.days = 5

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/76d969e5/conf/livy.conf.template
----------------------------------------------------------------------
diff --git a/conf/livy.conf.template b/conf/livy.conf.template
new file mode 100644
index 0000000..c23aab2
--- /dev/null
+++ b/conf/livy.conf.template
@@ -0,0 +1,96 @@
+# Use this keystore for the SSL certificate and key.
+# livy.keystore =
+
+# Specify the keystore password.
+# livy.keystore.password =
+
+# What host address to start the server on. By default, Livy will bind to all network interfaces.
+# livy.server.host = 0.0.0.0
+
+# What port to start the server on.
+# livy.server.port = 8998
+
+# What spark master Livy sessions should use.
+# livy.spark.master = local
+
+# What spark deploy mode Livy sessions should use.
+# livy.spark.deployMode =
+
+# Enabled to check whether timeout Livy sessions should be stopped.
+# livy.server.session.timeout-check = true
+
+# Time in milliseconds on how long Livy will wait before timing out an idle session.
+# livy.server.session.timeout = 1h
+#
+# How long a finished session state should be kept in LivyServer for query.
+# livy.server.session.state-retain.sec = 600s
+
+# If livy should impersonate the requesting users when creating a new session.
+# livy.impersonation.enabled = true
+
+# Comma-separated list of Livy RSC jars. By default Livy will upload jars from its installation
+# directory every time a session is started. By caching these files in HDFS, for example, startup
+# time of sessions on YARN can be reduced.
+# livy.rsc.jars =
+
+# Comma-separated list of Livy REPL jars. By default Livy will upload jars from its installation
+# directory every time a session is started. By caching these files in HDFS, for example, startup
+# time of sessions on YARN can be reduced. Please list all the repl dependencies including
+# livy-repl_2.10 and livy-repl_2.11 jars, Livy will automatically pick the right dependencies in
+# session creation.
+# livy.repl.jars =
+
+# Location of PySpark archives. By default Livy will upload the file from SPARK_HOME, but
+# by caching the file in HDFS, startup time of PySpark sessions on YARN can be reduced.
+# livy.pyspark.archives =
+
+# Location of the SparkR package. By default Livy will upload the file from SPARK_HOME, but
+# by caching the file in HDFS, startup time of R sessions on YARN can be reduced.
+# livy.sparkr.package =
+
+# List of local directories from where files are allowed to be added to user sessions. By
+# default it's empty, meaning users can only reference remote URIs when starting their
+# sessions.
+# livy.file.local-dir-whitelist =
+
+# Whether to enable csrf protection, by default it is false. If it is enabled, client should add
+# http-header "X-Requested-By" in request if the http method is POST/DELETE/PUT/PATCH.
+# livy.server.csrf_protection.enabled =
+
+# Whether to enable HiveContext in livy interpreter, if it is true hive-site.xml will be detected
+# on user request and then livy server classpath automatically.
+# livy.repl.enableHiveContext =
+
+# Recovery mode of Livy. Possible values:
+# off: Default. Turn off recovery. Every time Livy shuts down, it stops and forgets all sessions.
+# recovery: Livy persists session info to the state store. When Livy restarts, it recovers
+#           previous sessions from the state store.
+# Must set livy.server.recovery.state-store and livy.server.recovery.state-store.url to
+# configure the state store.
+# livy.server.recovery.mode = off
+
+# Where Livy should store state to for recovery. Possible values:
+# <empty>: Default. State store disabled.
+# filesystem: Store state on a file system.
+# zookeeper: Store state in a Zookeeper instance.
+# livy.server.recovery.state-store =
+
+# For filesystem state store, the path of the state store directory. Please don't use a filesystem
+# that doesn't support atomic rename (e.g. S3). e.g. file:///tmp/livy or hdfs:///.
+# For zookeeper, the address to the Zookeeper servers. e.g. host1:port1,host2:port2
+# livy.server.recovery.state-store.url =
+
+# If Livy can't find the yarn app within this time, consider it lost.
+# livy.server.yarn.app-lookup-timeout = 60s
+# When the cluster is busy, we may fail to launch yarn app in app-lookup-timeout, then it would
+# cause session leakage, so we need to check session leakage.
+# How long to check livy session leakage
+# livy.server.yarn.app-leakage.check_timeout = 600s
+# how often to check livy session leakage
+# livy.server.yarn.app-leakage.check_interval = 60s
+
+# How often Livy polls YARN to refresh YARN app state.
+# livy.server.yarn.poll-interval = 1s
+#
+# Days to keep Livy server request logs.
+# livy.server.request-log-retain.days = 5

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/76d969e5/conf/log4j.properties
----------------------------------------------------------------------
diff --git a/conf/log4j.properties b/conf/log4j.properties
deleted file mode 100644
index f855899..0000000
--- a/conf/log4j.properties
+++ /dev/null
@@ -1,25 +0,0 @@
-#
-# Licensed to Cloudera, Inc. under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  Cloudera, Inc. 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.
-#
-# The default Livy logging configuration.
-log4j.rootCategory=INFO, console
-log4j.appender.console=org.apache.log4j.ConsoleAppender
-log4j.appender.console.target=System.err
-log4j.appender.console.layout=org.apache.log4j.PatternLayout
-log4j.appender.console.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss} %p %c{1}: %m%n
-
-log4j.logger.org.eclipse.jetty=WARN

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/76d969e5/conf/log4j.properties.template
----------------------------------------------------------------------
diff --git a/conf/log4j.properties.template b/conf/log4j.properties.template
new file mode 100644
index 0000000..f855899
--- /dev/null
+++ b/conf/log4j.properties.template
@@ -0,0 +1,25 @@
+#
+# Licensed to Cloudera, Inc. under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  Cloudera, Inc. 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.
+#
+# The default Livy logging configuration.
+log4j.rootCategory=INFO, console
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+log4j.appender.console.target=System.err
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss} %p %c{1}: %m%n
+
+log4j.logger.org.eclipse.jetty=WARN

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/76d969e5/conf/spark-blacklist.conf
----------------------------------------------------------------------
diff --git a/conf/spark-blacklist.conf b/conf/spark-blacklist.conf
deleted file mode 100644
index f0919b0..0000000
--- a/conf/spark-blacklist.conf
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# Configuration override / blacklist. Defines a list of properties that users are not allowed
-# to override when starting Spark sessions.
-#
-# This file takes a list of property names (one per line). Empty lines and lines starting with "#"
-# are ignored.
-#
-
-# Disallow overriding the master and the deploy mode.
-spark.master
-spark.submit.deployMode
-
-# Disallow overriding the location of Spark cached jars.
-spark.yarn.jar
-spark.yarn.jars
-spark.yarn.archive
-
-# Don't allow users to override the RSC timeout.
-livy.rsc.server.idle_timeout

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/76d969e5/conf/spark-blacklist.conf.template
----------------------------------------------------------------------
diff --git a/conf/spark-blacklist.conf.template b/conf/spark-blacklist.conf.template
new file mode 100644
index 0000000..f0919b0
--- /dev/null
+++ b/conf/spark-blacklist.conf.template
@@ -0,0 +1,19 @@
+#
+# Configuration override / blacklist. Defines a list of properties that users are not allowed
+# to override when starting Spark sessions.
+#
+# This file takes a list of property names (one per line). Empty lines and lines starting with "#"
+# are ignored.
+#
+
+# Disallow overriding the master and the deploy mode.
+spark.master
+spark.submit.deployMode
+
+# Disallow overriding the location of Spark cached jars.
+spark.yarn.jar
+spark.yarn.jars
+spark.yarn.archive
+
+# Don't allow users to override the RSC timeout.
+livy.rsc.server.idle_timeout


[42/50] [abbrv] incubator-livy git commit: LIVY-342. Create Livy UI: Create Web UI Servlet and All Sessions Page (#319)

Posted by js...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/61b206e0/server/src/main/resources/com/cloudera/livy/server/ui/static/jquery-3.2.1.min.js
----------------------------------------------------------------------
diff --git a/server/src/main/resources/com/cloudera/livy/server/ui/static/jquery-3.2.1.min.js b/server/src/main/resources/com/cloudera/livy/server/ui/static/jquery-3.2.1.min.js
new file mode 100644
index 0000000..644d35e
--- /dev/null
+++ b/server/src/main/resources/com/cloudera/livy/server/ui/static/jquery-3.2.1.min.js
@@ -0,0 +1,4 @@
+/*! jQuery v3.2.1 | (c) JS Foundation and other contributors | jquery.org/license */
+!function(a,b){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){"use strict";var c=[],d=a.document,e=Object.getPrototypeOf,f=c.slice,g=c.concat,h=c.push,i=c.indexOf,j={},k=j.toString,l=j.hasOwnProperty,m=l.toString,n=m.call(Object),o={};function p(a,b){b=b||d;var c=b.createElement("script");c.text=a,b.head.appendChild(c).parentNode.removeChild(c)}var q="3.2.1",r=function(a,b){return new r.fn.init(a,b)},s=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,t=/^-ms-/,u=/-([a-z])/g,v=function(a,b){return b.toUpperCase()};r.fn=r.prototype={jquery:q,constructor:r,length:0,toArray:function(){return f.call(this)},get:function(a){return null==a?f.call(this):a<0?this[a+this.length]:this[a]},pushStack:function(a){var b=r.merge(this.constructor(),a);return b.prevObject=this,b},each:function(a){retu
 rn r.each(this,a)},map:function(a){return this.pushStack(r.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(f.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(a<0?b:0);return this.pushStack(c>=0&&c<b?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:h,sort:c.sort,splice:c.splice},r.extend=r.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||r.isFunction(g)||(g={}),h===i&&(g=this,h--);h<i;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(r.isPlainObject(d)||(e=Array.isArray(d)))?(e?(e=!1,f=c&&Array.isArray(c)?c:[]):f=c&&r.isPlainObject(c)?c:{},g[b]=r.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},r.extend({expando:"jQuery"+(q+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},no
 op:function(){},isFunction:function(a){return"function"===r.type(a)},isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){var b=r.type(a);return("number"===b||"string"===b)&&!isNaN(a-parseFloat(a))},isPlainObject:function(a){var b,c;return!(!a||"[object Object]"!==k.call(a))&&(!(b=e(a))||(c=l.call(b,"constructor")&&b.constructor,"function"==typeof c&&m.call(c)===n))},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?j[k.call(a)]||"object":typeof a},globalEval:function(a){p(a)},camelCase:function(a){return a.replace(t,"ms-").replace(u,v)},each:function(a,b){var c,d=0;if(w(a)){for(c=a.length;d<c;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(s,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(w(Object(a))?r.merge(c,"string"==typeof a?[a]:a):h.call(c,a)),c},inArray:funct
 ion(a,b,c){return null==b?-1:i.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;d<c;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;f<g;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,f=0,h=[];if(w(a))for(d=a.length;f<d;f++)e=b(a[f],f,c),null!=e&&h.push(e);else for(f in a)e=b(a[f],f,c),null!=e&&h.push(e);return g.apply([],h)},guid:1,proxy:function(a,b){var c,d,e;if("string"==typeof b&&(c=a[b],b=a,a=c),r.isFunction(a))return d=f.call(arguments,2),e=function(){return a.apply(b||this,d.concat(f.call(arguments)))},e.guid=a.guid=a.guid||r.guid++,e},now:Date.now,support:o}),"function"==typeof Symbol&&(r.fn[Symbol.iterator]=c[Symbol.iterator]),r.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){j["[object "+b+"]"]=b.toLowerCase()});function w(a){var b=!!a&&"length"in a&&a.length,c=r.type(a);return"function"!==c&&!r.isWindow(a)&&("array"===c||0===b||"
 number"==typeof b&&b>0&&b-1 in a)}var x=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=function(a,b){for(var c=0,d=a.length;c<d;c++)if(a[c]===b)return c;return-1},J="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",K="[\\x20\\t\\r\\n\\f]",L="(?:\\\\.|[\\w-]|[^\0-\\xa0])+",M="\\["+K+"*("+L+")(?:"+K+"*([*^$|!~]?=)"+K+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+L+"))|)"+K+"*\\]",N=":("+L+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+M+")*)|.*)\\)|)",O=new RegExp(K+"+","g"),P=new RegExp("^"+K+"+|((?:^|[^\\\\])(?:\\\\.)*)"+K+"+$","g"),Q=new RegExp("^"+K+"*,"+K+"*"),R=new RegExp("^"+K+"*([>+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(N),U=new RegExp("^
 "+L+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L+"|[*])"),ATTR:new RegExp("^"+M),PSEUDO:new RegExp("^"+N),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),aa=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:d<0?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ba=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ca=function(a,b){return b?"\0"===a?"\ufffd":a.slice(0,-1)+"\\"+a.charCodeAt(a.length-1).toString(16)+" ":"\\"+a},da=function(){m()},ea=ta(function(a){retur
 n a.disabled===!0&&("form"in a||"label"in a)},{dir:"parentNode",next:"legend"});try{G.apply(D=H.call(v.childNodes),v.childNodes),D[v.childNodes.length].nodeType}catch(fa){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s=b&&b.ownerDocument,w=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==w&&9!==w&&11!==w)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==w&&(l=Z.exec(a)))if(f=l[1]){if(9===w){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(s&&(j=s.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(l[2])return G.apply(d,b.getElementsByTagName(a)),d;if((f=l[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==w)s=b,r=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(ba,ca):b.set
 Attribute("id",k=u),o=g(a),h=o.length;while(h--)o[h]="#"+k+" "+sa(o[h]);r=o.join(","),s=$.test(a)&&qa(b.parentNode)||b}if(r)try{return G.apply(d,s.querySelectorAll(r)),d}catch(x){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(P,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("fieldset");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&a.sourceIndex-b.sourceIndex;if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}f
 unction oa(a){return function(b){return"form"in b?b.parentNode&&b.disabled===!1?"label"in b?"label"in b.parentNode?b.parentNode.disabled===a:b.disabled===a:b.isDisabled===a||b.isDisabled!==!a&&ea(b)===a:b.disabled===a:"label"in b&&b.disabled===a}}function pa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function qa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return!!b&&"HTML"!==b.nodeName},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),v!==n&&(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.append
 Child(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(n.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){return a.getAttribute("id")===b}},d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}}):(d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}},d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c,d,e,f=b.getElementById(a);if(f){if(c=f.getAttributeNode("id"),c&&c.value===a)return[f];e=b.getElementsByName(a),d=0;while(f=e[d++])if(c=f.getAttributeNode("id"),c&&c.value===a)return[f]}return[]}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElement
 sByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){if("undefined"!=typeof b.getElementsByClassName&&p)return b.getElementsByClassName(a)},r=[],q=[],(c.qsa=Y.test(n.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="<a id='"+u+"'></a><select id='"+u+"-\r\\' msallowcapture=''><option selected=''></option></select>",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){a.innerHTML="<a href='' disabled='disabled'></a><select disabled='disabled'><option/></select>";var b=n.createElement("input");b.setAttri
 bute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+K+"*[*^$|!~]?="),2!==a.querySelectorAll(":enabled").length&&q.push(":enabled",":disabled"),o.appendChild(a).disabled=!0,2!==a.querySelectorAll(":disabled").length&&q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Y.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"*"),s.call(a,"[s!='']:x"),r.push("!=",N)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Y.test(o.compareDocumentPosition),t=b||Y.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===
 b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?I(k,a)-I(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?I(k,a)-I(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?la(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(S,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>
 0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.escape=function(a){return(a+"").replace(ba,ca)},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:V,attrHandle:{},find:{},
 relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(_,aa),a[3]=(a[3]||a[4]||a[5]||"").replace(_,aa),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return V.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&T.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(_,aa).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&y(a,function(a){return b.test("string"==typ
 eof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:!b||(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(O," ")+" ").indexOf(c)>-1:"|="===b&&(e===c||e.slice(0,c.length+1)===c+"-"))}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=+
 +n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(P,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b
 ){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(_,aa),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return U.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(_,aa).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:oa(!1),disabled:oa(!0),checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:funct
 ion(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:pa(function(){return[0]}),last:pa(function(a,b){return[b-1]}),eq:pa(function(a,b,c){return[c<0?c+b:c]}),even:pa(function(a,b){for(var c=0;c<b;c+=2)a.push(c);return a}),odd:pa(function(a,b){for(var c=1;c<b;c+=2)a.push(c);return a}),lt:pa(function(a,b,c){for(var d=c<0?c+b:c;--d>=0;)a.push(d);return a}),gt:pa(function(a,b,c){for(var d=c<0?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=ma(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=na(b);function ra(){}ra.prototype=d.filters=d.pseudos,d.setFilters=new ra,g=ga.tokenize=function(a
 ,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){c&&!(e=Q.exec(h))||(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=R.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(P," ")}),h=h.slice(c.length));for(g in d.filter)!(e=V[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?ga.error(a):z(a,i).slice(0)};function sa(a){for(var b=0,c=a.length,d="";b<c;b++)d+=a[b].value;return d}function ta(a,b,c){var d=b.dir,e=b.next,f=e||d,g=c&&"parentNode"===f,h=x++;return b.first?function(b,c,e){while(b=b[d])if(1===b.nodeType||g)return a(b,c,e);return!1}:function(b,c,i){var j,k,l,m=[w,h];if(i){while(b=b[d])if((1===b.nodeType||g)&&a(b,c,i))return!0}else while(b=b[d])if(1===b.nodeType||g)if(l=b[u]||(b[u]={}),k=l[b.uniqueID]||(l[b.uniqueID]={}),e&&e===b.nodeName.toLowerCase())b=b[d]||b;else{if((j=k[f])&&j[0]===w&&j[1]===h)return m[2]=j[2];if(k[f]=m,m[2]=a(b,c,i))retur
 n!0}return!1}}function ua(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function va(a,b,c){for(var d=0,e=b.length;d<e;d++)ga(a,b[d],c);return c}function wa(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;h<i;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function xa(a,b,c,d,e,f){return d&&!d[u]&&(d=xa(d)),e&&!e[u]&&(e=xa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||va(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:wa(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=wa(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?I(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=wa(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ya(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ta(function(a){return a===b},
 h,!0),l=ta(function(a){return I(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];i<f;i++)if(c=d.relative[a[i].type])m=[ta(ua(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;e<f;e++)if(d.relative[a[e].type])break;return xa(i>1&&ua(m),i>1&&sa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(P,"$1"),c,i<e&&ya(a.slice(i,e)),e<f&&ya(a=a.slice(e)),e<f&&sa(a))}m.push(c)}return ua(m)}function za(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=E.call(i));u=wa(u)}G.apply(i,u),k&&!f&&u.length>0&&r+b.leng
 th>1&&ga.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=ya(b[c]),f[u]?d.push(f):e.push(f);f=A(a,za(e,d)),f.selector=a}return f},i=ga.select=function(a,b,c,e){var f,i,j,k,l,m="function"==typeof a&&a,n=!e&&g(a=m.selector||a);if(c=c||[],1===n.length){if(i=n[0]=n[0].slice(0),i.length>2&&"ID"===(j=i[0]).type&&9===b.nodeType&&p&&d.relative[i[1].type]){if(b=(d.find.ID(j.matches[0].replace(_,aa),b)||[])[0],!b)return c;m&&(b=b.parentNode),a=a.slice(i.shift().value.length)}f=V.needsContext.test(a)?0:i.length;while(f--){if(j=i[f],d.relative[k=j.type])break;if((l=d.find[k])&&(e=l(j.matches[0].replace(_,aa),$.test(i[0].type)&&qa(b.parentNode)||b))){if(i.splice(f,1),a=e.length&&sa(i),!a)return G.apply(c,e),c;break}}}return(m||h(a,n))(e,b,!p,c,!b||$.test(a)&&qa(b.parentNode)||b),c},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return
  1&a.compareDocumentPosition(n.createElement("fieldset"))}),ja(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){if(!c)return a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){if(!c&&"input"===a.nodeName.toLowerCase())return a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(J,function(a,b,c){var d;if(!c)return a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);r.find=x,r.expr=x.selectors,r.expr[":"]=r.expr.pseudos,r.uniqueSort=r.unique=x.uniqueSort,r.text=x.getText,r.isXMLDoc=x.isXML,r.contains=x.contains,r.escapeSelector=x.escape;var y=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&r(a).is(c))break;d.push(a)}return d},z=func
 tion(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},A=r.expr.match.needsContext;function B(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()}var C=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i,D=/^.[^:#\[\.,]*$/;function E(a,b,c){return r.isFunction(b)?r.grep(a,function(a,d){return!!b.call(a,d,a)!==c}):b.nodeType?r.grep(a,function(a){return a===b!==c}):"string"!=typeof b?r.grep(a,function(a){return i.call(b,a)>-1!==c}):D.test(b)?r.filter(b,a,c):(b=r.filter(b,a),r.grep(a,function(a){return i.call(b,a)>-1!==c&&1===a.nodeType}))}r.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?r.find.matchesSelector(d,a)?[d]:[]:r.find.matches(a,r.grep(b,function(a){return 1===a.nodeType}))},r.fn.extend({find:function(a){var b,c,d=this.length,e=this;if("string"!=typeof a)return this.pushStack(r(a).filter(function(){for(b=0;b<d;b++)if(r.contains(e[b],this))return!0}));for(c=this.pushStack([]),
 b=0;b<d;b++)r.find(a,e[b],c);return d>1?r.uniqueSort(c):c},filter:function(a){return this.pushStack(E(this,a||[],!1))},not:function(a){return this.pushStack(E(this,a||[],!0))},is:function(a){return!!E(this,"string"==typeof a&&A.test(a)?r(a):a||[],!1).length}});var F,G=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,H=r.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||F,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:G.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof r?b[0]:b,r.merge(this,r.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),C.test(e[1])&&r.isPlainObject(b))for(e in b)r.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&(this[0]=f,this.length=1),this}return a.nodeType?(this[0]=a,this.length=1,this):r.isFunction(a)?void 0!==c.ready?c.ready(a):a(r):r.makeArray(a,this)};H.prototype=r.fn,F=r(d);var I=/^(?:parents|prev(?:Until|
 All))/,J={children:!0,contents:!0,next:!0,prev:!0};r.fn.extend({has:function(a){var b=r(a,this),c=b.length;return this.filter(function(){for(var a=0;a<c;a++)if(r.contains(this,b[a]))return!0})},closest:function(a,b){var c,d=0,e=this.length,f=[],g="string"!=typeof a&&r(a);if(!A.test(a))for(;d<e;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&r.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?r.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?i.call(r(a),this[0]):i.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(r.uniqueSort(r.merge(this.get(),r(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function K(a,b){while((a=a[b])&&1!==a.nodeType);return a}r.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return y(a,"parentNode
 ")},parentsUntil:function(a,b,c){return y(a,"parentNode",c)},next:function(a){return K(a,"nextSibling")},prev:function(a){return K(a,"previousSibling")},nextAll:function(a){return y(a,"nextSibling")},prevAll:function(a){return y(a,"previousSibling")},nextUntil:function(a,b,c){return y(a,"nextSibling",c)},prevUntil:function(a,b,c){return y(a,"previousSibling",c)},siblings:function(a){return z((a.parentNode||{}).firstChild,a)},children:function(a){return z(a.firstChild)},contents:function(a){return B(a,"iframe")?a.contentDocument:(B(a,"template")&&(a=a.content||a),r.merge([],a.childNodes))}},function(a,b){r.fn[a]=function(c,d){var e=r.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=r.filter(d,e)),this.length>1&&(J[a]||r.uniqueSort(e),I.test(a)&&e.reverse()),this.pushStack(e)}});var L=/[^\x20\t\r\n\f]+/g;function M(a){var b={};return r.each(a.match(L)||[],function(a,c){b[c]=!0}),b}r.Callbacks=function(a){a="string"==typeof a?M(a):r.extend({},a);var b,c,d,e,f=
 [],g=[],h=-1,i=function(){for(e=e||a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h<f.length)f[h].apply(c[0],c[1])===!1&&a.stopOnFalse&&(h=f.length,c=!1)}a.memory||(c=!1),b=!1,e&&(f=c?[]:"")},j={add:function(){return f&&(c&&!b&&(h=f.length-1,g.push(c)),function d(b){r.each(b,function(b,c){r.isFunction(c)?a.unique&&j.has(c)||f.push(c):c&&c.length&&"string"!==r.type(c)&&d(c)})}(arguments),c&&!b&&i()),this},remove:function(){return r.each(arguments,function(a,b){var c;while((c=r.inArray(b,f,c))>-1)f.splice(c,1),c<=h&&h--}),this},has:function(a){return a?r.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||b||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j};function N(a){return a}fu
 nction O(a){throw a}function P(a,b,c,d){var e;try{a&&r.isFunction(e=a.promise)?e.call(a).done(b).fail(c):a&&r.isFunction(e=a.then)?e.call(a,b,c):b.apply(void 0,[a].slice(d))}catch(a){c.apply(void 0,[a])}}r.extend({Deferred:function(b){var c=[["notify","progress",r.Callbacks("memory"),r.Callbacks("memory"),2],["resolve","done",r.Callbacks("once memory"),r.Callbacks("once memory"),0,"resolved"],["reject","fail",r.Callbacks("once memory"),r.Callbacks("once memory"),1,"rejected"]],d="pending",e={state:function(){return d},always:function(){return f.done(arguments).fail(arguments),this},"catch":function(a){return e.then(null,a)},pipe:function(){var a=arguments;return r.Deferred(function(b){r.each(c,function(c,d){var e=r.isFunction(a[d[4]])&&a[d[4]];f[d[1]](function(){var a=e&&e.apply(this,arguments);a&&r.isFunction(a.promise)?a.promise().progress(b.notify).done(b.resolve).fail(b.reject):b[d[0]+"With"](this,e?[a]:arguments)})}),a=null}).promise()},then:function(b,d,e){var f=0;function g(b
 ,c,d,e){return function(){var h=this,i=arguments,j=function(){var a,j;if(!(b<f)){if(a=d.apply(h,i),a===c.promise())throw new TypeError("Thenable self-resolution");j=a&&("object"==typeof a||"function"==typeof a)&&a.then,r.isFunction(j)?e?j.call(a,g(f,c,N,e),g(f,c,O,e)):(f++,j.call(a,g(f,c,N,e),g(f,c,O,e),g(f,c,N,c.notifyWith))):(d!==N&&(h=void 0,i=[a]),(e||c.resolveWith)(h,i))}},k=e?j:function(){try{j()}catch(a){r.Deferred.exceptionHook&&r.Deferred.exceptionHook(a,k.stackTrace),b+1>=f&&(d!==O&&(h=void 0,i=[a]),c.rejectWith(h,i))}};b?k():(r.Deferred.getStackHook&&(k.stackTrace=r.Deferred.getStackHook()),a.setTimeout(k))}}return r.Deferred(function(a){c[0][3].add(g(0,a,r.isFunction(e)?e:N,a.notifyWith)),c[1][3].add(g(0,a,r.isFunction(b)?b:N)),c[2][3].add(g(0,a,r.isFunction(d)?d:O))}).promise()},promise:function(a){return null!=a?r.extend(a,e):e}},f={};return r.each(c,function(a,b){var g=b[2],h=b[5];e[b[1]]=g.add,h&&g.add(function(){d=h},c[3-a][2].disable,c[0][2].lock),g.add(b[3].fire),
 f[b[0]]=function(){return f[b[0]+"With"](this===f?void 0:this,arguments),this},f[b[0]+"With"]=g.fireWith}),e.promise(f),b&&b.call(f,f),f},when:function(a){var b=arguments.length,c=b,d=Array(c),e=f.call(arguments),g=r.Deferred(),h=function(a){return function(c){d[a]=this,e[a]=arguments.length>1?f.call(arguments):c,--b||g.resolveWith(d,e)}};if(b<=1&&(P(a,g.done(h(c)).resolve,g.reject,!b),"pending"===g.state()||r.isFunction(e[c]&&e[c].then)))return g.then();while(c--)P(e[c],h(c),g.reject);return g.promise()}});var Q=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;r.Deferred.exceptionHook=function(b,c){a.console&&a.console.warn&&b&&Q.test(b.name)&&a.console.warn("jQuery.Deferred exception: "+b.message,b.stack,c)},r.readyException=function(b){a.setTimeout(function(){throw b})};var R=r.Deferred();r.fn.ready=function(a){return R.then(a)["catch"](function(a){r.readyException(a)}),this},r.extend({isReady:!1,readyWait:1,ready:function(a){(a===!0?--r.readyWait:r.isReady)||(r.isReady=!
 0,a!==!0&&--r.readyWait>0||R.resolveWith(d,[r]))}}),r.ready.then=R.then;function S(){d.removeEventListener("DOMContentLoaded",S),
+a.removeEventListener("load",S),r.ready()}"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(r.ready):(d.addEventListener("DOMContentLoaded",S),a.addEventListener("load",S));var T=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===r.type(c)){e=!0;for(h in c)T(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,r.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(r(a),c)})),b))for(;h<i;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},U=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function V(){this.expando=r.expando+V.uid++}V.uid=1,V.prototype={cache:function(a){var b=a[this.expando];return b||(b={},U(a)&&(a.nodeType?a[this.expando]=b:Object.defineProperty(a,this.expando,{value:b,configurable:!0}))),b},set:function(a,b,c){var d,e=this.cache(a);if("string"==typeof b)e[r.camelCase(b)]=c;else for(d in b)e[r.camelCase(d)]=b[d];return e},get:function(a,
 b){return void 0===b?this.cache(a):a[this.expando]&&a[this.expando][r.camelCase(b)]},access:function(a,b,c){return void 0===b||b&&"string"==typeof b&&void 0===c?this.get(a,b):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d=a[this.expando];if(void 0!==d){if(void 0!==b){Array.isArray(b)?b=b.map(r.camelCase):(b=r.camelCase(b),b=b in d?[b]:b.match(L)||[]),c=b.length;while(c--)delete d[b[c]]}(void 0===b||r.isEmptyObject(d))&&(a.nodeType?a[this.expando]=void 0:delete a[this.expando])}},hasData:function(a){var b=a[this.expando];return void 0!==b&&!r.isEmptyObject(b)}};var W=new V,X=new V,Y=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Z=/[A-Z]/g;function $(a){return"true"===a||"false"!==a&&("null"===a?null:a===+a+""?+a:Y.test(a)?JSON.parse(a):a)}function _(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(Z,"-$&").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c=$(c)}catch(e){}X.set(a,b,c)}else c=void 0;return c}r.extend({hasData:function(a){return X.hasData(a)|
 |W.hasData(a)},data:function(a,b,c){return X.access(a,b,c)},removeData:function(a,b){X.remove(a,b)},_data:function(a,b,c){return W.access(a,b,c)},_removeData:function(a,b){W.remove(a,b)}}),r.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=X.get(f),1===f.nodeType&&!W.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=r.camelCase(d.slice(5)),_(f,d,e[d])));W.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){X.set(this,a)}):T(this,function(b){var c;if(f&&void 0===b){if(c=X.get(f,a),void 0!==c)return c;if(c=_(f,a),void 0!==c)return c}else this.each(function(){X.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){X.remove(this,a)})}}),r.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=W.get(a,b),c&&(!d||Array.isArray(c)?d=W.access(a,b,r.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||
 "fx";var c=r.queue(a,b),d=c.length,e=c.shift(),f=r._queueHooks(a,b),g=function(){r.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return W.get(a,c)||W.access(a,c,{empty:r.Callbacks("once memory").add(function(){W.remove(a,[b+"queue",c])})})}}),r.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?r.queue(this[0],a):void 0===b?this:this.each(function(){var c=r.queue(this,a,b);r._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&r.dequeue(this,a)})},dequeue:function(a){return this.each(function(){r.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=r.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=W.get(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h
 (),e.promise(b)}});var aa=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,ba=new RegExp("^(?:([+-])=|)("+aa+")([a-z%]*)$","i"),ca=["Top","Right","Bottom","Left"],da=function(a,b){return a=b||a,"none"===a.style.display||""===a.style.display&&r.contains(a.ownerDocument,a)&&"none"===r.css(a,"display")},ea=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};function fa(a,b,c,d){var e,f=1,g=20,h=d?function(){return d.cur()}:function(){return r.css(a,b,"")},i=h(),j=c&&c[3]||(r.cssNumber[b]?"":"px"),k=(r.cssNumber[b]||"px"!==j&&+i)&&ba.exec(r.css(a,b));if(k&&k[3]!==j){j=j||k[3],c=c||[],k=+i||1;do f=f||".5",k/=f,r.style(a,b,k+j);while(f!==(f=h()/i)&&1!==f&&--g)}return c&&(k=+k||+i||0,e=c[1]?k+(c[1]+1)*c[2]:+c[2],d&&(d.unit=j,d.start=k,d.end=e)),e}var ga={};function ha(a){var b,c=a.ownerDocument,d=a.nodeName,e=ga[d];return e?e:(b=c.body.appendChild(c.createElement(d)),e=r.css(b,"display"),b.parentNode.removeChild(b),"
 none"===e&&(e="block"),ga[d]=e,e)}function ia(a,b){for(var c,d,e=[],f=0,g=a.length;f<g;f++)d=a[f],d.style&&(c=d.style.display,b?("none"===c&&(e[f]=W.get(d,"display")||null,e[f]||(d.style.display="")),""===d.style.display&&da(d)&&(e[f]=ha(d))):"none"!==c&&(e[f]="none",W.set(d,"display",c)));for(f=0;f<g;f++)null!=e[f]&&(a[f].style.display=e[f]);return a}r.fn.extend({show:function(){return ia(this,!0)},hide:function(){return ia(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){da(this)?r(this).show():r(this).hide()})}});var ja=/^(?:checkbox|radio)$/i,ka=/<([a-z][^\/\0>\x20\t\r\n\f]+)/i,la=/^$|\/(?:java|ecma)script/i,ma={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};ma.optgroup=ma.option,ma.tbody=ma.tfoot=ma.colgroup=ma.caption=ma.thead,m
 a.th=ma.td;function na(a,b){var c;return c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[],void 0===b||b&&B(a,b)?r.merge([a],c):c}function oa(a,b){for(var c=0,d=a.length;c<d;c++)W.set(a[c],"globalEval",!b||W.get(b[c],"globalEval"))}var pa=/<|&#?\w+;/;function qa(a,b,c,d,e){for(var f,g,h,i,j,k,l=b.createDocumentFragment(),m=[],n=0,o=a.length;n<o;n++)if(f=a[n],f||0===f)if("object"===r.type(f))r.merge(m,f.nodeType?[f]:f);else if(pa.test(f)){g=g||l.appendChild(b.createElement("div")),h=(ka.exec(f)||["",""])[1].toLowerCase(),i=ma[h]||ma._default,g.innerHTML=i[1]+r.htmlPrefilter(f)+i[2],k=i[0];while(k--)g=g.lastChild;r.merge(m,g.childNodes),g=l.firstChild,g.textContent=""}else m.push(b.createTextNode(f));l.textContent="",n=0;while(f=m[n++])if(d&&r.inArray(f,d)>-1)e&&e.push(f);else if(j=r.contains(f.ownerDocument,f),g=na(l.appendChild(f),"script"),j&&oa(g),c){k=0;while(f=g[k++])la.test(f.type||""
 )&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),o.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="<textarea>x</textarea>",o.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var ra=d.documentElement,sa=/^key/,ta=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,ua=/^([^.]*)(?:\.(.+)|)/;function va(){return!0}function wa(){return!1}function xa(){try{return d.activeElement}catch(a){}}function ya(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)ya(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=wa;else if(!e)return a;return 1===f&&(g=e,e=function(a){return r().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=r.guid++)),a.each(
 function(){r.event.add(this,b,e,d,c)})}r.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=W.get(a);if(q){c.handler&&(f=c,c=f.handler,e=f.selector),e&&r.find.matchesSelector(ra,e),c.guid||(c.guid=r.guid++),(i=q.events)||(i=q.events={}),(g=q.handle)||(g=q.handle=function(b){return"undefined"!=typeof r&&r.event.triggered!==b.type?r.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(L)||[""],j=b.length;while(j--)h=ua.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n&&(l=r.event.special[n]||{},n=(e?l.delegateType:l.bindType)||n,l=r.event.special[n]||{},k=r.extend({type:n,origType:p,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&r.expr.match.needsContext.test(e),namespace:o.join(".")},f),(m=i[n])||(m=i[n]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,o,g)!==!1||a.addEventListener&&a.addEventListener(n,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),r.event.global[n]=!0)}},remove:f
 unction(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=W.hasData(a)&&W.get(a);if(q&&(i=q.events)){b=(b||"").match(L)||[""],j=b.length;while(j--)if(h=ua.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n){l=r.event.special[n]||{},n=(d?l.delegateType:l.bindType)||n,m=i[n]||[],h=h[2]&&new RegExp("(^|\\.)"+o.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&p!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,o,q.handle)!==!1||r.removeEvent(a,n,q.handle),delete i[n])}else for(n in i)r.event.remove(a,n+b[j],c,d,!0);r.isEmptyObject(i)&&W.remove(a,"handle events")}},dispatch:function(a){var b=r.event.fix(a),c,d,e,f,g,h,i=new Array(arguments.length),j=(W.get(this,"events")||{})[b.type]||[],k=r.event.special[b.type]||{};for(i[0]=b,c=1;c<arguments.length;c++)i[c]=arguments[c];if(b.delegateTarget=this,!k.preDi
 spatch||k.preDispatch.call(this,b)!==!1){h=r.event.handlers.call(this,b,j),c=0;while((f=h[c++])&&!b.isPropagationStopped()){b.currentTarget=f.elem,d=0;while((g=f.handlers[d++])&&!b.isImmediatePropagationStopped())b.rnamespace&&!b.rnamespace.test(g.namespace)||(b.handleObj=g,b.data=g.data,e=((r.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(b.result=e)===!1&&(b.preventDefault(),b.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,b),b.result}},handlers:function(a,b){var c,d,e,f,g,h=[],i=b.delegateCount,j=a.target;if(i&&j.nodeType&&!("click"===a.type&&a.button>=1))for(;j!==this;j=j.parentNode||this)if(1===j.nodeType&&("click"!==a.type||j.disabled!==!0)){for(f=[],g={},c=0;c<i;c++)d=b[c],e=d.selector+" ",void 0===g[e]&&(g[e]=d.needsContext?r(e,this).index(j)>-1:r.find(e,this,null,[j]).length),g[e]&&f.push(d);f.length&&h.push({elem:j,handlers:f})}return j=this,i<b.length&&h.push({elem:j,handlers:b.slice(i)}),h},addProp:function(a,b){Object
 .defineProperty(r.Event.prototype,a,{enumerable:!0,configurable:!0,get:r.isFunction(b)?function(){if(this.originalEvent)return b(this.originalEvent)}:function(){if(this.originalEvent)return this.originalEvent[a]},set:function(b){Object.defineProperty(this,a,{enumerable:!0,configurable:!0,writable:!0,value:b})}})},fix:function(a){return a[r.expando]?a:new r.Event(a)},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==xa()&&this.focus)return this.focus(),!1},delegateType:"focusin"},blur:{trigger:function(){if(this===xa()&&this.blur)return this.blur(),!1},delegateType:"focusout"},click:{trigger:function(){if("checkbox"===this.type&&this.click&&B(this,"input"))return this.click(),!1},_default:function(a){return B(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}}},r.removeEvent=function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c)},r.Event=function(a,b){return this instanceof r.Eve
 nt?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?va:wa,this.target=a.target&&3===a.target.nodeType?a.target.parentNode:a.target,this.currentTarget=a.currentTarget,this.relatedTarget=a.relatedTarget):this.type=a,b&&r.extend(this,b),this.timeStamp=a&&a.timeStamp||r.now(),void(this[r.expando]=!0)):new r.Event(a,b)},r.Event.prototype={constructor:r.Event,isDefaultPrevented:wa,isPropagationStopped:wa,isImmediatePropagationStopped:wa,isSimulated:!1,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=va,a&&!this.isSimulated&&a.preventDefault()},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=va,a&&!this.isSimulated&&a.stopPropagation()},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=va,a&&!this.isSimulated&&a.stopImmediatePropagation(),this.stopPropagation()}},r.each({altKey:!0,bubbles:!0,cancel
 able:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,"char":!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:function(a){var b=a.button;return null==a.which&&sa.test(a.type)?null!=a.charCode?a.charCode:a.keyCode:!a.which&&void 0!==b&&ta.test(a.type)?1&b?1:2&b?3:4&b?2:0:a.which}},r.event.addProp),r.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){r.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return e&&(e===d||r.contains(d,e))||(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),r.fn.extend({on:function(a,b,c,d){return ya(this,a,b,c,d)},one:function(a,b,c,d){return ya(this,a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a
 .handleObj)return d=a.handleObj,r(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return b!==!1&&"function"!=typeof b||(c=b,b=void 0),c===!1&&(c=wa),this.each(function(){r.event.remove(this,a,c,b)})}});var za=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,Aa=/<script|<style|<link/i,Ba=/checked\s*(?:[^=]|=\s*.checked.)/i,Ca=/^true\/(.*)/,Da=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function Ea(a,b){return B(a,"table")&&B(11!==b.nodeType?b:b.firstChild,"tr")?r(">tbody",a)[0]||a:a}function Fa(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function Ga(a){var b=Ca.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Ha(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(W.hasData(a)&&(f=W.access(a),g=W.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;c<d;c++)r.event
 .add(b,e,j[e][c])}X.hasData(a)&&(h=X.access(a),i=r.extend({},h),X.set(b,i))}}function Ia(a,b){var c=b.nodeName.toLowerCase();"input"===c&&ja.test(a.type)?b.checked=a.checked:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}function Ja(a,b,c,d){b=g.apply([],b);var e,f,h,i,j,k,l=0,m=a.length,n=m-1,q=b[0],s=r.isFunction(q);if(s||m>1&&"string"==typeof q&&!o.checkClone&&Ba.test(q))return a.each(function(e){var f=a.eq(e);s&&(b[0]=q.call(this,e,f.html())),Ja(f,b,c,d)});if(m&&(e=qa(b,a[0].ownerDocument,!1,a,d),f=e.firstChild,1===e.childNodes.length&&(e=f),f||d)){for(h=r.map(na(e,"script"),Fa),i=h.length;l<m;l++)j=e,l!==n&&(j=r.clone(j,!0,!0),i&&r.merge(h,na(j,"script"))),c.call(a[l],j,l);if(i)for(k=h[h.length-1].ownerDocument,r.map(h,Ga),l=0;l<i;l++)j=h[l],la.test(j.type||"")&&!W.access(j,"globalEval")&&r.contains(k,j)&&(j.src?r._evalUrl&&r._evalUrl(j.src):p(j.textContent.replace(Da,""),k))}return a}function Ka(a,b,c){for(var d,e=b?r.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d
 .nodeType||r.cleanData(na(d)),d.parentNode&&(c&&r.contains(d.ownerDocument,d)&&oa(na(d,"script")),d.parentNode.removeChild(d));return a}r.extend({htmlPrefilter:function(a){return a.replace(za,"<$1></$2>")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=r.contains(a.ownerDocument,a);if(!(o.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||r.isXMLDoc(a)))for(g=na(h),f=na(a),d=0,e=f.length;d<e;d++)Ia(f[d],g[d]);if(b)if(c)for(f=f||na(a),g=g||na(h),d=0,e=f.length;d<e;d++)Ha(f[d],g[d]);else Ha(a,h);return g=na(h,"script"),g.length>0&&oa(g,!i&&na(a,"script")),h},cleanData:function(a){for(var b,c,d,e=r.event.special,f=0;void 0!==(c=a[f]);f++)if(U(c)){if(b=c[W.expando]){if(b.events)for(d in b.events)e[d]?r.event.remove(c,d):r.removeEvent(c,d,b.handle);c[W.expando]=void 0}c[X.expando]&&(c[X.expando]=void 0)}}}),r.fn.extend({detach:function(a){return Ka(this,a,!0)},remove:function(a){return Ka(this,a)},text:function(a){return T(this,function(a){return void 0===a?r.text(this):this.empty()
 .each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return Ja(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ea(this,a);b.appendChild(a)}})},prepend:function(){return Ja(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ea(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ja(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ja(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(r.cleanData(na(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null!=a&&a,b=null==b?a:b,this.map(function(){return r.clone(this,a,b)})},html:function(a){return T(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0=
 ==a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!Aa.test(a)&&!ma[(ka.exec(a)||["",""])[1].toLowerCase()]){a=r.htmlPrefilter(a);try{for(;c<d;c++)b=this[c]||{},1===b.nodeType&&(r.cleanData(na(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return Ja(this,arguments,function(b){var c=this.parentNode;r.inArray(this,a)<0&&(r.cleanData(na(this)),c&&c.replaceChild(b,this))},a)}}),r.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){r.fn[a]=function(a){for(var c,d=[],e=r(a),f=e.length-1,g=0;g<=f;g++)c=g===f?this:this.clone(!0),r(e[g])[b](c),h.apply(d,c.get());return this.pushStack(d)}});var La=/^margin/,Ma=new RegExp("^("+aa+")(?!px)[a-z%]+$","i"),Na=function(b){var c=b.ownerDocument.defaultView;return c&&c.opener||(c=a),c.getComputedStyle(b)};!function(){function b(){if(i){i.style.cssText="box-sizing:border-box;position:relative;d
 isplay:block;margin:auto;border:1px;padding:1px;top:1%;width:50%",i.innerHTML="",ra.appendChild(h);var b=a.getComputedStyle(i);c="1%"!==b.top,g="2px"===b.marginLeft,e="4px"===b.width,i.style.marginRight="50%",f="4px"===b.marginRight,ra.removeChild(h),i=null}}var c,e,f,g,h=d.createElement("div"),i=d.createElement("div");i.style&&(i.style.backgroundClip="content-box",i.cloneNode(!0).style.backgroundClip="",o.clearCloneStyle="content-box"===i.style.backgroundClip,h.style.cssText="border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute",h.appendChild(i),r.extend(o,{pixelPosition:function(){return b(),c},boxSizingReliable:function(){return b(),e},pixelMarginRight:function(){return b(),f},reliableMarginLeft:function(){return b(),g}}))}();function Oa(a,b,c){var d,e,f,g,h=a.style;return c=c||Na(a),c&&(g=c.getPropertyValue(b)||c[b],""!==g||r.contains(a.ownerDocument,a)||(g=r.style(a,b)),!o.pixelMarginRight()&&Ma.test(g)&&La.test(b)&&(d=h.width,e=h.minWidth,f
 =h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0!==g?g+"":g}function Pa(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}var Qa=/^(none|table(?!-c[ea]).+)/,Ra=/^--/,Sa={position:"absolute",visibility:"hidden",display:"block"},Ta={letterSpacing:"0",fontWeight:"400"},Ua=["Webkit","Moz","ms"],Va=d.createElement("div").style;function Wa(a){if(a in Va)return a;var b=a[0].toUpperCase()+a.slice(1),c=Ua.length;while(c--)if(a=Ua[c]+b,a in Va)return a}function Xa(a){var b=r.cssProps[a];return b||(b=r.cssProps[a]=Wa(a)||a),b}function Ya(a,b,c){var d=ba.exec(b);return d?Math.max(0,d[2]-(c||0))+(d[3]||"px"):b}function Za(a,b,c,d,e){var f,g=0;for(f=c===(d?"border":"content")?4:"width"===b?1:0;f<4;f+=2)"margin"===c&&(g+=r.css(a,c+ca[f],!0,e)),d?("content"===c&&(g-=r.css(a,"padding"+ca[f],!0,e)),"margin"!==c&&(g-=r.css(a,"border"+ca[f]+"Width",!0,e))):(g+=r.css(a,"padding"+ca[f],!0,e),"padding"!==c&&(g+
 =r.css(a,"border"+ca[f]+"Width",!0,e)));return g}function $a(a,b,c){var d,e=Na(a),f=Oa(a,b,e),g="border-box"===r.css(a,"boxSizing",!1,e);return Ma.test(f)?f:(d=g&&(o.boxSizingReliable()||f===a.style[b]),"auto"===f&&(f=a["offset"+b[0].toUpperCase()+b.slice(1)]),f=parseFloat(f)||0,f+Za(a,b,c||(g?"border":"content"),d,e)+"px")}r.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Oa(a,"opacity");return""===c?"1":c}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=r.camelCase(b),i=Ra.test(b),j=a.style;return i||(b=Xa(h)),g=r.cssHooks[b]||r.cssHooks[h],void 0===c?g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:j[b]:(f=typeof c,"string"===f&&(e=ba.exec(c))&&e[1]&&(c=fa(a,b,e),f="number"),null!=c&&c===c&&("number"===f&&(c+=e&&e[3]||(r.cssNumber[
 h]?"":"px")),o.clearCloneStyle||""!==c||0!==b.indexOf("background")||(j[b]="inherit"),g&&"set"in g&&void 0===(c=g.set(a,c,d))||(i?j.setProperty(b,c):j[b]=c)),void 0)}},css:function(a,b,c,d){var e,f,g,h=r.camelCase(b),i=Ra.test(b);return i||(b=Xa(h)),g=r.cssHooks[b]||r.cssHooks[h],g&&"get"in g&&(e=g.get(a,!0,c)),void 0===e&&(e=Oa(a,b,d)),"normal"===e&&b in Ta&&(e=Ta[b]),""===c||c?(f=parseFloat(e),c===!0||isFinite(f)?f||0:e):e}}),r.each(["height","width"],function(a,b){r.cssHooks[b]={get:function(a,c,d){if(c)return!Qa.test(r.css(a,"display"))||a.getClientRects().length&&a.getBoundingClientRect().width?$a(a,b,d):ea(a,Sa,function(){return $a(a,b,d)})},set:function(a,c,d){var e,f=d&&Na(a),g=d&&Za(a,b,d,"border-box"===r.css(a,"boxSizing",!1,f),f);return g&&(e=ba.exec(c))&&"px"!==(e[3]||"px")&&(a.style[b]=c,c=r.css(a,b)),Ya(a,c,g)}}}),r.cssHooks.marginLeft=Pa(o.reliableMarginLeft,function(a,b){if(b)return(parseFloat(Oa(a,"marginLeft"))||a.getBoundingClientRect().left-ea(a,{marginLeft:0},fu
 nction(){return a.getBoundingClientRect().left}))+"px"}),r.each({margin:"",padding:"",border:"Width"},function(a,b){r.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];d<4;d++)e[a+ca[d]+b]=f[d]||f[d-2]||f[0];return e}},La.test(a)||(r.cssHooks[a+b].set=Ya)}),r.fn.extend({css:function(a,b){return T(this,function(a,b,c){var d,e,f={},g=0;if(Array.isArray(b)){for(d=Na(a),e=b.length;g<e;g++)f[b[g]]=r.css(a,b[g],!1,d);return f}return void 0!==c?r.style(a,b,c):r.css(a,b)},a,b,arguments.length>1)}});function _a(a,b,c,d,e){return new _a.prototype.init(a,b,c,d,e)}r.Tween=_a,_a.prototype={constructor:_a,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||r.easing._default,this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(r.cssNumber[c]?"":"px")},cur:function(){var a=_a.propHooks[this.prop];return a&&a.get?a.get(this):_a.propHooks._default.get(this)},run:function(a){var b,c=_a.propHooks[this.prop];return this.options.durat
 ion?this.pos=b=r.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):_a.propHooks._default.set(this),this}},_a.prototype.init.prototype=_a.prototype,_a.propHooks={_default:{get:function(a){var b;return 1!==a.elem.nodeType||null!=a.elem[a.prop]&&null==a.elem.style[a.prop]?a.elem[a.prop]:(b=r.css(a.elem,a.prop,""),b&&"auto"!==b?b:0)},set:function(a){r.fx.step[a.prop]?r.fx.step[a.prop](a):1!==a.elem.nodeType||null==a.elem.style[r.cssProps[a.prop]]&&!r.cssHooks[a.prop]?a.elem[a.prop]=a.now:r.style(a.elem,a.prop,a.now+a.unit)}}},_a.propHooks.scrollTop=_a.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},r.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},_default:"swing"},r.fx=_a.prototype.init,r.fx.step={};var ab,bb,cb=/^(?:toggle|show|hid
 e)$/,db=/queueHooks$/;function eb(){bb&&(d.hidden===!1&&a.requestAnimationFrame?a.requestAnimationFrame(eb):a.setTimeout(eb,r.fx.interval),r.fx.tick())}function fb(){return a.setTimeout(function(){ab=void 0}),ab=r.now()}function gb(a,b){var c,d=0,e={height:a};for(b=b?1:0;d<4;d+=2-b)c=ca[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function hb(a,b,c){for(var d,e=(kb.tweeners[b]||[]).concat(kb.tweeners["*"]),f=0,g=e.length;f<g;f++)if(d=e[f].call(c,b,a))return d}function ib(a,b,c){var d,e,f,g,h,i,j,k,l="width"in b||"height"in b,m=this,n={},o=a.style,p=a.nodeType&&da(a),q=W.get(a,"fxshow");c.queue||(g=r._queueHooks(a,"fx"),null==g.unqueued&&(g.unqueued=0,h=g.empty.fire,g.empty.fire=function(){g.unqueued||h()}),g.unqueued++,m.always(function(){m.always(function(){g.unqueued--,r.queue(a,"fx").length||g.empty.fire()})}));for(d in b)if(e=b[d],cb.test(e)){if(delete b[d],f=f||"toggle"===e,e===(p?"hide":"show")){if("show"!==e||!q||void 0===q[d])continue;p=!0}n[d]=q&&q[d]
 ||r.style(a,d)}if(i=!r.isEmptyObject(b),i||!r.isEmptyObject(n)){l&&1===a.nodeType&&(c.overflow=[o.overflow,o.overflowX,o.overflowY],j=q&&q.display,null==j&&(j=W.get(a,"display")),k=r.css(a,"display"),"none"===k&&(j?k=j:(ia([a],!0),j=a.style.display||j,k=r.css(a,"display"),ia([a]))),("inline"===k||"inline-block"===k&&null!=j)&&"none"===r.css(a,"float")&&(i||(m.done(function(){o.display=j}),null==j&&(k=o.display,j="none"===k?"":k)),o.display="inline-block")),c.overflow&&(o.overflow="hidden",m.always(function(){o.overflow=c.overflow[0],o.overflowX=c.overflow[1],o.overflowY=c.overflow[2]})),i=!1;for(d in n)i||(q?"hidden"in q&&(p=q.hidden):q=W.access(a,"fxshow",{display:j}),f&&(q.hidden=!p),p&&ia([a],!0),m.done(function(){p||ia([a]),W.remove(a,"fxshow");for(d in n)r.style(a,d,n[d])})),i=hb(p?q[d]:0,d,m),d in q||(q[d]=i.start,p&&(i.end=i.start,i.start=0))}}function jb(a,b){var c,d,e,f,g;for(c in a)if(d=r.camelCase(c),e=b[d],f=a[c],Array.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,dele
 te a[c]),g=r.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function kb(a,b,c){var d,e,f=0,g=kb.prefilters.length,h=r.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=ab||fb(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;g<i;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),f<1&&i?c:(i||h.notifyWith(a,[j,1,0]),h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:r.extend({},b),opts:r.extend(!0,{specialEasing:{},easing:r.easing._default},c),originalProperties:b,originalOptions:c,startTime:ab||fb(),duration:c.duration,tweens:[],createTween:function(b,c){var d=r.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;c<d;c++)j.tweens[c].run(1);return b?(h.notifyWith(a,[j,1,0]),h.resolveWith(a,[j,b])):h.rejectWith(a,[j,b]),this}}),k=j.props;for(jb(k,j.op
 ts.specialEasing);f<g;f++)if(d=kb.prefilters[f].call(j,a,k,j.opts))return r.isFunction(d.stop)&&(r._queueHooks(j.elem,j.opts.queue).stop=r.proxy(d.stop,d)),d;return r.map(k,hb,j),r.isFunction(j.opts.start)&&j.opts.start.call(a,j),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always),r.fx.timer(r.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j}r.Animation=r.extend(kb,{tweeners:{"*":[function(a,b){var c=this.createTween(a,b);return fa(c.elem,a,ba.exec(b),c),c}]},tweener:function(a,b){r.isFunction(a)?(b=a,a=["*"]):a=a.match(L);for(var c,d=0,e=a.length;d<e;d++)c=a[d],kb.tweeners[c]=kb.tweeners[c]||[],kb.tweeners[c].unshift(b)},prefilters:[ib],prefilter:function(a,b){b?kb.prefilters.unshift(a):kb.prefilters.push(a)}}),r.speed=function(a,b,c){var d=a&&"object"==typeof a?r.extend({},a):{complete:c||!c&&b||r.isFunction(a)&&a,duration:a,easing:c&&b||b&&!r.isFunction(b)&&b};return r.fx.off?d.duration=0:"number"!=typeof d.duration&&(d.duration in
  r.fx.speeds?d.duration=r.fx.speeds[d.duration]:d.duration=r.fx.speeds._default),null!=d.queue&&d.queue!==!0||(d.queue="fx"),d.old=d.complete,d.complete=function(){r.isFunction(d.old)&&d.old.call(this),d.queue&&r.dequeue(this,d.queue)},d},r.fn.extend({fadeTo:function(a,b,c,d){return this.filter(da).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=r.isEmptyObject(a),f=r.speed(b,c,d),g=function(){var b=kb(this,r.extend({},a),f);(e||W.get(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=r.timers,g=W.get(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&db.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));
 !b&&c||r.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=W.get(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=r.timers,g=d?d.length:0;for(c.finish=!0,r.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;b<g;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),r.each(["toggle","show","hide"],function(a,b){var c=r.fn[b];r.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(gb(b,!0),a,d,e)}}),r.each({slideDown:gb("show"),slideUp:gb("hide"),slideToggle:gb("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){r.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),r.timers=[],r.fx.tick=function(){var a,b=0,c=r.timers;for(ab=r.now();b<c.length;b++)a=c[b],a()||c[b]!==a||c.splice(b--,1);c.length||r.fx.stop(),ab=void 0},r.fx.timer=function(a){r.timers.push
 (a),r.fx.start()},r.fx.interval=13,r.fx.start=function(){bb||(bb=!0,eb())},r.fx.stop=function(){bb=null},r.fx.speeds={slow:600,fast:200,_default:400},r.fn.delay=function(b,c){return b=r.fx?r.fx.speeds[b]||b:b,c=c||"fx",this.queue(c,function(c,d){var e=a.setTimeout(c,b);d.stop=function(){a.clearTimeout(e)}})},function(){var a=d.createElement("input"),b=d.createElement("select"),c=b.appendChild(d.createElement("option"));a.type="checkbox",o.checkOn=""!==a.value,o.optSelected=c.selected,a=d.createElement("input"),a.value="t",a.type="radio",o.radioValue="t"===a.value}();var lb,mb=r.expr.attrHandle;r.fn.extend({attr:function(a,b){return T(this,r.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){r.removeAttr(this,a)})}}),r.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?r.prop(a,b,c):(1===f&&r.isXMLDoc(a)||(e=r.attrHooks[b.toLowerCase()]||(r.expr.match.bool.test(b)?lb:void 0)),void 0!==c?null=
 ==c?void r.removeAttr(a,b):e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+""),c):e&&"get"in e&&null!==(d=e.get(a,b))?d:(d=r.find.attr(a,b),
+null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!o.radioValue&&"radio"===b&&B(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d=0,e=b&&b.match(L);if(e&&1===a.nodeType)while(c=e[d++])a.removeAttribute(c)}}),lb={set:function(a,b,c){return b===!1?r.removeAttr(a,c):a.setAttribute(c,c),c}},r.each(r.expr.match.bool.source.match(/\w+/g),function(a,b){var c=mb[b]||r.find.attr;mb[b]=function(a,b,d){var e,f,g=b.toLowerCase();return d||(f=mb[g],mb[g]=e,e=null!=c(a,b,d)?g:null,mb[g]=f),e}});var nb=/^(?:input|select|textarea|button)$/i,ob=/^(?:a|area)$/i;r.fn.extend({prop:function(a,b){return T(this,r.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[r.propFix[a]||a]})}}),r.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&r.isXMLDoc(a)||(b=r.propFix[b]||b,e=r.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&
 &null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=r.find.attr(a,"tabindex");return b?parseInt(b,10):nb.test(a.nodeName)||ob.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),o.optSelected||(r.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}}),r.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){r.propFix[this.toLowerCase()]=this});function pb(a){var b=a.match(L)||[];return b.join(" ")}function qb(a){return a.getAttribute&&a.getAttribute("class")||""}r.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).addClass(a.call(this,b,qb(this)))});if("string"==typeof a&&a){b=a.match(L)||[];while(c=this[i++])if(e=qb(c),d=1===c.nodeType&
 &" "+pb(e)+" "){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=pb(d),e!==h&&c.setAttribute("class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).removeClass(a.call(this,b,qb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(L)||[];while(c=this[i++])if(e=qb(c),d=1===c.nodeType&&" "+pb(e)+" "){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=pb(d),e!==h&&c.setAttribute("class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):r.isFunction(a)?this.each(function(c){r(this).toggleClass(a.call(this,c,qb(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=r(this),f=a.match(L)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&"boolean"!==c||(b=qb(this),b&&W.set(this,"__className__",b),this.setAttribute&
 &this.setAttribute("class",b||a===!1?"":W.get(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+pb(qb(c))+" ").indexOf(b)>-1)return!0;return!1}});var rb=/\r/g;r.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=r.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,r(this).val()):a,null==e?e="":"number"==typeof e?e+="":Array.isArray(e)&&(e=r.map(e,function(a){return null==a?"":a+""})),b=r.valHooks[this.type]||r.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=r.valHooks[e.type]||r.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(rb,""):null==c?"":c)}}}),r.extend({valHooks:{option:{get:function(a){var b=r.find.attr(a,"value");return null!=b?b:pb(r.text(a))}},select:{get:function(a){var b,c,d,e=a.options,f=a.selectedIndex,g="sel
 ect-one"===a.type,h=g?null:[],i=g?f+1:e.length;for(d=f<0?i:g?f:0;d<i;d++)if(c=e[d],(c.selected||d===f)&&!c.disabled&&(!c.parentNode.disabled||!B(c.parentNode,"optgroup"))){if(b=r(c).val(),g)return b;h.push(b)}return h},set:function(a,b){var c,d,e=a.options,f=r.makeArray(b),g=e.length;while(g--)d=e[g],(d.selected=r.inArray(r.valHooks.option.get(d),f)>-1)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),r.each(["radio","checkbox"],function(){r.valHooks[this]={set:function(a,b){if(Array.isArray(b))return a.checked=r.inArray(r(a).val(),b)>-1}},o.checkOn||(r.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var sb=/^(?:focusinfocus|focusoutblur)$/;r.extend(r.event,{trigger:function(b,c,e,f){var g,h,i,j,k,m,n,o=[e||d],p=l.call(b,"type")?b.type:b,q=l.call(b,"namespace")?b.namespace.split("."):[];if(h=i=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!sb.test(p+r.event.triggered)&&(p.indexOf(".")>-1&&(q=p.split("."),p=q.shift(),q.sort()),k=p.indexOf(":")<0&&"on"+p,b=
 b[r.expando]?b:new r.Event(p,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=q.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:r.makeArray(c,[b]),n=r.event.special[p]||{},f||!n.trigger||n.trigger.apply(e,c)!==!1)){if(!f&&!n.noBubble&&!r.isWindow(e)){for(j=n.delegateType||p,sb.test(j+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),i=h;i===(e.ownerDocument||d)&&o.push(i.defaultView||i.parentWindow||a)}g=0;while((h=o[g++])&&!b.isPropagationStopped())b.type=g>1?j:n.bindType||p,m=(W.get(h,"events")||{})[b.type]&&W.get(h,"handle"),m&&m.apply(h,c),m=k&&h[k],m&&m.apply&&U(h)&&(b.result=m.apply(h,c),b.result===!1&&b.preventDefault());return b.type=p,f||b.isDefaultPrevented()||n._default&&n._default.apply(o.pop(),c)!==!1||!U(e)||k&&r.isFunction(e[p])&&!r.isWindow(e)&&(i=e[k],i&&(e[k]=null),r.event.triggered=p,e[p](),r.event.triggered=void 0,i&&(e[k]=i)),b.result}},simulate:function(a,b,c)
 {var d=r.extend(new r.Event,c,{type:a,isSimulated:!0});r.event.trigger(d,null,b)}}),r.fn.extend({trigger:function(a,b){return this.each(function(){r.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];if(c)return r.event.trigger(a,b,c,!0)}}),r.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(a,b){r.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),r.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),o.focusin="onfocusin"in a,o.focusin||r.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){r.event.simulate(b,a.target,r.event.fix(a))};r.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=W.access(d,b);e||d.addEventListener(a,c,!0),W.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=W.access(
 d,b)-1;e?W.access(d,b,e):(d.removeEventListener(a,c,!0),W.remove(d,b))}}});var tb=a.location,ub=r.now(),vb=/\?/;r.parseXML=function(b){var c;if(!b||"string"!=typeof b)return null;try{c=(new a.DOMParser).parseFromString(b,"text/xml")}catch(d){c=void 0}return c&&!c.getElementsByTagName("parsererror").length||r.error("Invalid XML: "+b),c};var wb=/\[\]$/,xb=/\r?\n/g,yb=/^(?:submit|button|image|reset|file)$/i,zb=/^(?:input|select|textarea|keygen)/i;function Ab(a,b,c,d){var e;if(Array.isArray(b))r.each(b,function(b,e){c||wb.test(a)?d(a,e):Ab(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d)});else if(c||"object"!==r.type(b))d(a,b);else for(e in b)Ab(a+"["+e+"]",b[e],c,d)}r.param=function(a,b){var c,d=[],e=function(a,b){var c=r.isFunction(b)?b():b;d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(null==c?"":c)};if(Array.isArray(a)||a.jquery&&!r.isPlainObject(a))r.each(a,function(){e(this.name,this.value)});else for(c in a)Ab(c,a[c],b,e);return d.join("&")},r.fn.extend({serialize:f
 unction(){return r.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=r.prop(this,"elements");return a?r.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!r(this).is(":disabled")&&zb.test(this.nodeName)&&!yb.test(a)&&(this.checked||!ja.test(a))}).map(function(a,b){var c=r(this).val();return null==c?null:Array.isArray(c)?r.map(c,function(a){return{name:b.name,value:a.replace(xb,"\r\n")}}):{name:b.name,value:c.replace(xb,"\r\n")}}).get()}});var Bb=/%20/g,Cb=/#.*$/,Db=/([?&])_=[^&]*/,Eb=/^(.*?):[ \t]*([^\r\n]*)$/gm,Fb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Gb=/^(?:GET|HEAD)$/,Hb=/^\/\//,Ib={},Jb={},Kb="*/".concat("*"),Lb=d.createElement("a");Lb.href=tb.href;function Mb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(L)||[];if(r.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Nb(a,b,c,d){var e
 ={},f=a===Jb;function g(h){var i;return e[h]=!0,r.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Ob(a,b){var c,d,e=r.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&r.extend(!0,a,d),a}function Pb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}if(f)return f!==i[0]&&i.unshift(f),c[f]}function Qb(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if
 ("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}r.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:tb.href,type:"GET",isLocal:Fb.test(tb.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Kb,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":r.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Ob(Ob(a,r.ajaxSettings),b):Ob(r.ajaxSetting
 s,a)},ajaxPrefilter:Mb(Ib),ajaxTransport:Mb(Jb),ajax:function(b,c){"object"==typeof b&&(c=b,b=void 0),c=c||{};var e,f,g,h,i,j,k,l,m,n,o=r.ajaxSetup({},c),p=o.context||o,q=o.context&&(p.nodeType||p.jquery)?r(p):r.event,s=r.Deferred(),t=r.Callbacks("once memory"),u=o.statusCode||{},v={},w={},x="canceled",y={readyState:0,getResponseHeader:function(a){var b;if(k){if(!h){h={};while(b=Eb.exec(g))h[b[1].toLowerCase()]=b[2]}b=h[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return k?g:null},setRequestHeader:function(a,b){return null==k&&(a=w[a.toLowerCase()]=w[a.toLowerCase()]||a,v[a]=b),this},overrideMimeType:function(a){return null==k&&(o.mimeType=a),this},statusCode:function(a){var b;if(a)if(k)y.always(a[y.status]);else for(b in a)u[b]=[u[b],a[b]];return this},abort:function(a){var b=a||x;return e&&e.abort(b),A(0,b),this}};if(s.promise(y),o.url=((b||o.url||tb.href)+"").replace(Hb,tb.protocol+"//"),o.type=c.method||c.type||o.method||o.type,o.dataTypes=(o.dataType
 ||"*").toLowerCase().match(L)||[""],null==o.crossDomain){j=d.createElement("a");try{j.href=o.url,j.href=j.href,o.crossDomain=Lb.protocol+"//"+Lb.host!=j.protocol+"//"+j.host}catch(z){o.crossDomain=!0}}if(o.data&&o.processData&&"string"!=typeof o.data&&(o.data=r.param(o.data,o.traditional)),Nb(Ib,o,c,y),k)return y;l=r.event&&o.global,l&&0===r.active++&&r.event.trigger("ajaxStart"),o.type=o.type.toUpperCase(),o.hasContent=!Gb.test(o.type),f=o.url.replace(Cb,""),o.hasContent?o.data&&o.processData&&0===(o.contentType||"").indexOf("application/x-www-form-urlencoded")&&(o.data=o.data.replace(Bb,"+")):(n=o.url.slice(f.length),o.data&&(f+=(vb.test(f)?"&":"?")+o.data,delete o.data),o.cache===!1&&(f=f.replace(Db,"$1"),n=(vb.test(f)?"&":"?")+"_="+ub++ +n),o.url=f+n),o.ifModified&&(r.lastModified[f]&&y.setRequestHeader("If-Modified-Since",r.lastModified[f]),r.etag[f]&&y.setRequestHeader("If-None-Match",r.etag[f])),(o.data&&o.hasContent&&o.contentType!==!1||c.contentType)&&y.setRequestHeader("Co
 ntent-Type",o.contentType),y.setRequestHeader("Accept",o.dataTypes[0]&&o.accepts[o.dataTypes[0]]?o.accepts[o.dataTypes[0]]+("*"!==o.dataTypes[0]?", "+Kb+"; q=0.01":""):o.accepts["*"]);for(m in o.headers)y.setRequestHeader(m,o.headers[m]);if(o.beforeSend&&(o.beforeSend.call(p,y,o)===!1||k))return y.abort();if(x="abort",t.add(o.complete),y.done(o.success),y.fail(o.error),e=Nb(Jb,o,c,y)){if(y.readyState=1,l&&q.trigger("ajaxSend",[y,o]),k)return y;o.async&&o.timeout>0&&(i=a.setTimeout(function(){y.abort("timeout")},o.timeout));try{k=!1,e.send(v,A)}catch(z){if(k)throw z;A(-1,z)}}else A(-1,"No Transport");function A(b,c,d,h){var j,m,n,v,w,x=c;k||(k=!0,i&&a.clearTimeout(i),e=void 0,g=h||"",y.readyState=b>0?4:0,j=b>=200&&b<300||304===b,d&&(v=Pb(o,y,d)),v=Qb(o,v,y,j),j?(o.ifModified&&(w=y.getResponseHeader("Last-Modified"),w&&(r.lastModified[f]=w),w=y.getResponseHeader("etag"),w&&(r.etag[f]=w)),204===b||"HEAD"===o.type?x="nocontent":304===b?x="notmodified":(x=v.state,m=v.data,n=v.error,j=!n)
 ):(n=x,!b&&x||(x="error",b<0&&(b=0))),y.status=b,y.statusText=(c||x)+"",j?s.resolveWith(p,[m,x,y]):s.rejectWith(p,[y,x,n]),y.statusCode(u),u=void 0,l&&q.trigger(j?"ajaxSuccess":"ajaxError",[y,o,j?m:n]),t.fireWith(p,[y,x]),l&&(q.trigger("ajaxComplete",[y,o]),--r.active||r.event.trigger("ajaxStop")))}return y},getJSON:function(a,b,c){return r.get(a,b,c,"json")},getScript:function(a,b){return r.get(a,void 0,b,"script")}}),r.each(["get","post"],function(a,b){r[b]=function(a,c,d,e){return r.isFunction(c)&&(e=e||d,d=c,c=void 0),r.ajax(r.extend({url:a,type:b,dataType:e,data:c,success:d},r.isPlainObject(a)&&a))}}),r._evalUrl=function(a){return r.ajax({url:a,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},r.fn.extend({wrapAll:function(a){var b;return this[0]&&(r.isFunction(a)&&(a=a.call(this[0])),b=r(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}
 ).append(this)),this},wrapInner:function(a){return r.isFunction(a)?this.each(function(b){r(this).wrapInner(a.call(this,b))}):this.each(function(){var b=r(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=r.isFunction(a);return this.each(function(c){r(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(a){return this.parent(a).not("body").each(function(){r(this).replaceWith(this.childNodes)}),this}}),r.expr.pseudos.hidden=function(a){return!r.expr.pseudos.visible(a)},r.expr.pseudos.visible=function(a){return!!(a.offsetWidth||a.offsetHeight||a.getClientRects().length)},r.ajaxSettings.xhr=function(){try{return new a.XMLHttpRequest}catch(b){}};var Rb={0:200,1223:204},Sb=r.ajaxSettings.xhr();o.cors=!!Sb&&"withCredentials"in Sb,o.ajax=Sb=!!Sb,r.ajaxTransport(function(b){var c,d;if(o.cors||Sb&&!b.crossDomain)return{send:function(e,f){var g,h=b.xhr();if(h.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(g in b.xhrFields)h[g]=b.xhrFields[g];b.m
 imeType&&h.overrideMimeType&&h.overrideMimeType(b.mimeType),b.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest");for(g in e)h.setRequestHeader(g,e[g]);c=function(a){return function(){c&&(c=d=h.onload=h.onerror=h.onabort=h.onreadystatechange=null,"abort"===a?h.abort():"error"===a?"number"!=typeof h.status?f(0,"error"):f(h.status,h.statusText):f(Rb[h.status]||h.status,h.statusText,"text"!==(h.responseType||"text")||"string"!=typeof h.responseText?{binary:h.response}:{text:h.responseText},h.getAllResponseHeaders()))}},h.onload=c(),d=h.onerror=c("error"),void 0!==h.onabort?h.onabort=d:h.onreadystatechange=function(){4===h.readyState&&a.setTimeout(function(){c&&d()})},c=c("abort");try{h.send(b.hasContent&&b.data||null)}catch(i){if(c)throw i}},abort:function(){c&&c()}}}),r.ajaxPrefilter(function(a){a.crossDomain&&(a.contents.script=!1)}),r.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},conte
 nts:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(a){return r.globalEval(a),a}}}),r.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),r.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(e,f){b=r("<script>").prop({charset:a.scriptCharset,src:a.url}).on("load error",c=function(a){b.remove(),c=null,a&&f("error"===a.type?404:200,a.type)}),d.head.appendChild(b[0])},abort:function(){c&&c()}}}});var Tb=[],Ub=/(=)\?(?=&|$)|\?\?/;r.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=Tb.pop()||r.expando+"_"+ub++;return this[a]=!0,a}}),r.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(Ub.test(b.url)?"url":"string"==typeof b.data&&0===(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ub.test(b.data)&&"data");if(h||"jsonp"===b.dataTypes[0])return e=b.jsonpCallback=r.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(Ub
 ,"$1"+e):b.jsonp!==!1&&(b.url+=(vb.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||r.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){void 0===f?r(a).removeProp(e):a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,Tb.push(e)),g&&r.isFunction(f)&&f(g[0]),g=f=void 0}),"script"}),o.createHTMLDocument=function(){var a=d.implementation.createHTMLDocument("").body;return a.innerHTML="<form></form><form></form>",2===a.childNodes.length}(),r.parseHTML=function(a,b,c){if("string"!=typeof a)return[];"boolean"==typeof b&&(c=b,b=!1);var e,f,g;return b||(o.createHTMLDocument?(b=d.implementation.createHTMLDocument(""),e=b.createElement("base"),e.href=d.location.href,b.head.appendChild(e)):b=d),f=C.exec(a),g=!c&&[],f?[b.createElement(f[1])]:(f=qa([a],b,g),g&&g.length&&r(g).remove(),r.merge([],f.childNodes))},r.fn.load=function(a,b,c){var d,e,f,g=this,h=a.indexOf(" ");return h>-1&&(d=pb(a.slice(h)),a=a.sl
 ice(0,h)),r.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(e="POST"),g.length>0&&r.ajax({url:a,type:e||"GET",dataType:"html",data:b}).done(function(a){f=arguments,g.html(d?r("<div>").append(r.parseHTML(a)).find(d):a)}).always(c&&function(a,b){g.each(function(){c.apply(this,f||[a.responseText,b,a])})}),this},r.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){r.fn[b]=function(a){return this.on(b,a)}}),r.expr.pseudos.animated=function(a){return r.grep(r.timers,function(b){return a===b.elem}).length},r.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=r.css(a,"position"),l=r(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=r.css(a,"top"),i=r.css(a,"left"),j=("absolute"===k||"fixed"===k)&&(f+i).indexOf("auto")>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),r.isFunction(b)&&(b=b.call(a,c,r.extend({},h))),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using
 "in b?b.using.call(a,m):l.css(m)}},r.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){r.offset.setOffset(this,a,b)});var b,c,d,e,f=this[0];if(f)return f.getClientRects().length?(d=f.getBoundingClientRect(),b=f.ownerDocument,c=b.documentElement,e=b.defaultView,{top:d.top+e.pageYOffset-c.clientTop,left:d.left+e.pageXOffset-c.clientLeft}):{top:0,left:0}},position:function(){if(this[0]){var a,b,c=this[0],d={top:0,left:0};return"fixed"===r.css(c,"position")?b=c.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),B(a[0],"html")||(d=a.offset()),d={top:d.top+r.css(a[0],"borderTopWidth",!0),left:d.left+r.css(a[0],"borderLeftWidth",!0)}),{top:b.top-d.top-r.css(c,"marginTop",!0),left:b.left-d.left-r.css(c,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent;while(a&&"static"===r.css(a,"position"))a=a.offsetParent;return a||ra})}}),r.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function
 (a,b){var c="pageYOffset"===b;r.fn[a]=function(d){return T(this,function(a,d,e){var f;return r.isWindow(a)?f=a:9===a.nodeType&&(f=a.defaultView),void 0===e?f?f[b]:a[d]:void(f?f.scrollTo(c?f.pageXOffset:e,c?e:f.pageYOffset):a[d]=e)},a,d,arguments.length)}}),r.each(["top","left"],function(a,b){r.cssHooks[b]=Pa(o.pixelPosition,function(a,c){if(c)return c=Oa(a,b),Ma.test(c)?r(a).position()[b]+"px":c})}),r.each({Height:"height",Width:"width"},function(a,b){r.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){r.fn[d]=function(e,f){var g=arguments.length&&(c||"boolean"!=typeof e),h=c||(e===!0||f===!0?"margin":"border");return T(this,function(b,c,e){var f;return r.isWindow(b)?0===d.indexOf("outer")?b["inner"+a]:b.document.documentElement["client"+a]:9===b.nodeType?(f=b.documentElement,Math.max(b.body["scroll"+a],f["scroll"+a],b.body["offset"+a],f["offset"+a],f["client"+a])):void 0===e?r.css(b,c,h):r.style(b,c,e,h)},b,g?e:void 0,g)}})}),r.fn.extend({bind:function(a,b,c){return thi
 s.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}}),r.holdReady=function(a){a?r.readyWait++:r.ready(!0)},r.isArray=Array.isArray,r.parseJSON=JSON.parse,r.nodeName=B,"function"==typeof define&&define.amd&&define("jquery",[],function(){return r});var Vb=a.jQuery,Wb=a.$;return r.noConflict=function(b){return a.$===r&&(a.$=Wb),b&&a.jQuery===r&&(a.jQuery=Vb),r},b||(a.jQuery=a.$=r),r});

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/61b206e0/server/src/main/resources/com/cloudera/livy/server/ui/static/livy-mini-logo.png
----------------------------------------------------------------------
diff --git a/server/src/main/resources/com/cloudera/livy/server/ui/static/livy-mini-logo.png b/server/src/main/resources/com/cloudera/livy/server/ui/static/livy-mini-logo.png
new file mode 100644
index 0000000..49606b4
Binary files /dev/null and b/server/src/main/resources/com/cloudera/livy/server/ui/static/livy-mini-logo.png differ

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/61b206e0/server/src/main/resources/com/cloudera/livy/server/ui/static/livy-ui.css
----------------------------------------------------------------------
diff --git a/server/src/main/resources/com/cloudera/livy/server/ui/static/livy-ui.css b/server/src/main/resources/com/cloudera/livy/server/ui/static/livy-ui.css
new file mode 100644
index 0000000..8e5d399
--- /dev/null
+++ b/server/src/main/resources/com/cloudera/livy/server/ui/static/livy-ui.css
@@ -0,0 +1,21 @@
+/*
+ * Licensed to Cloudera, Inc. under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  Cloudera, Inc. 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.
+ */
+
+body {
+  padding-top: 20px;
+}
\ No newline at end of file



[16/50] [abbrv] incubator-livy git commit: LIVY-315. Fixed SparkRInterpreter to respect config enableHiveContext. (#293)

Posted by js...@apache.org.
LIVY-315. Fixed SparkRInterpreter to respect config enableHiveContext. (#293)



Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/ed1c86e8
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/ed1c86e8
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/ed1c86e8

Branch: refs/heads/master
Commit: ed1c86e874bee2d4323d6267cdf2a8d14b7db571
Parents: f7c434c
Author: Jeff Zhang <zj...@gmail.com>
Authored: Sat Feb 18 07:50:05 2017 +0800
Committer: Alex Man <tc...@gmail.com>
Committed: Fri Feb 17 15:50:05 2017 -0800

----------------------------------------------------------------------
 .../cloudera/livy/repl/ProcessInterpreter.scala  |  1 +
 .../cloudera/livy/repl/SparkRInterpreter.scala   | 19 ++++++++++++++-----
 2 files changed, 15 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/ed1c86e8/repl/src/main/scala/com/cloudera/livy/repl/ProcessInterpreter.scala
----------------------------------------------------------------------
diff --git a/repl/src/main/scala/com/cloudera/livy/repl/ProcessInterpreter.scala b/repl/src/main/scala/com/cloudera/livy/repl/ProcessInterpreter.scala
index 78826e3..25a8654 100644
--- a/repl/src/main/scala/com/cloudera/livy/repl/ProcessInterpreter.scala
+++ b/repl/src/main/scala/com/cloudera/livy/repl/ProcessInterpreter.scala
@@ -130,6 +130,7 @@ abstract class ProcessInterpreter(process: Process)
       val exitCode = process.waitFor()
       if (exitCode != 0) {
         error(f"Process has died with $exitCode")
+        error(stderrLines.mkString("\n"))
       }
     }
   }

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/ed1c86e8/repl/src/main/scala/com/cloudera/livy/repl/SparkRInterpreter.scala
----------------------------------------------------------------------
diff --git a/repl/src/main/scala/com/cloudera/livy/repl/SparkRInterpreter.scala b/repl/src/main/scala/com/cloudera/livy/repl/SparkRInterpreter.scala
index b3d3b7e..6c42fe3 100644
--- a/repl/src/main/scala/com/cloudera/livy/repl/SparkRInterpreter.scala
+++ b/repl/src/main/scala/com/cloudera/livy/repl/SparkRInterpreter.scala
@@ -116,7 +116,8 @@ object SparkRInterpreter {
       builder.redirectErrorStream(true)
       val process = builder.start()
       new SparkRInterpreter(process, backendInstance, backendThread,
-        conf.get("spark.livy.spark_major_version", "1"))
+        conf.get("spark.livy.spark_major_version", "1"),
+        conf.getBoolean("spark.repl.enableHiveContext", false))
     } catch {
       case e: Exception =>
         if (backendThread != null) {
@@ -130,7 +131,8 @@ object SparkRInterpreter {
 class SparkRInterpreter(process: Process,
     backendInstance: Any,
     backendThread: Thread,
-    val sparkMajorVersion: String)
+    val sparkMajorVersion: String,
+    hiveEnabled: Boolean)
   extends ProcessInterpreter(process) {
   import SparkRInterpreter._
 
@@ -145,15 +147,22 @@ class SparkRInterpreter(process: Process,
     sendRequest("options(error = dump.frames)")
     if (!ClientConf.TEST_MODE) {
       sendRequest("library(SparkR)")
-
       if (sparkMajorVersion >= "2") {
-        sendRequest("spark <- SparkR::sparkR.session()")
+        if (hiveEnabled) {
+          sendRequest("spark <- SparkR::sparkR.session()")
+        } else {
+          sendRequest("spark <- SparkR::sparkR.session(enableHiveSupport=FALSE)")
+        }
         sendRequest(
           """sc <- SparkR:::callJStatic("org.apache.spark.sql.api.r.SQLUtils",
             "getJavaSparkContext", spark)""")
       } else {
         sendRequest("sc <- sparkR.init()")
-        sendRequest("sqlContext <- sparkRSQL.init(sc)")
+        if (hiveEnabled) {
+          sendRequest("sqlContext <- sparkRHive.init(sc)")
+        } else {
+          sendRequest("sqlContext <- sparkRSQL.init(sc)")
+        }
       }
     }
 


[18/50] [abbrv] incubator-livy git commit: LIVY-218. Updating link to download build 0.3.0 (#294)

Posted by js...@apache.org.
LIVY-218. Updating link to download build 0.3.0 (#294)



Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/fd20a236
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/fd20a236
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/fd20a236

Branch: refs/heads/gh-pages
Commit: fd20a236a5e2b88943a16ddf6599dbcb23180270
Parents: 0dafce4
Author: Jonathan Alter <jo...@users.noreply.github.com>
Authored: Tue Feb 21 15:47:34 2017 -0800
Committer: Alex Man <tc...@gmail.com>
Committed: Tue Feb 21 15:47:34 2017 -0800

----------------------------------------------------------------------
 quickstart.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/fd20a236/quickstart.html
----------------------------------------------------------------------
diff --git a/quickstart.html b/quickstart.html
index 53bf940..ef56b9f 100644
--- a/quickstart.html
+++ b/quickstart.html
@@ -61,7 +61,7 @@
         <div class="col-lg-12">
         
           <h2>1. Install Livy</h2>
-          <p>Download Livy packages from <a href="http://archive.cloudera.com/beta/livy/livy-server-0.2.0.zip">here</a>.</p>
+          <p>Download Livy packages from <a href="http://archive.cloudera.com/beta/livy/livy-server-0.3.0.zip">here</a>.</p>
           <h2>2. Run Livy</h2>
           <p>To run the Livy server, you will also need an Apache Spark installation. You can get Spark releases at <a href="https://spark.apache.org/downloads.html">https://spark.apache.org/downloads.html</a>. Livy requires at least Spark 1.4 and currently only supports Scala 2.10 builds of Spark. To run Livy with local sessions, first export these variables:</p>
           


[31/50] [abbrv] incubator-livy git commit: Make several modules push-able to repo (#305)

Posted by js...@apache.org.
Make several modules push-able to repo (#305)

Change-Id: I9daec6ac7fdb2c9f727cbab6db042ec144c4edb8

Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/b7cc00a9
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/b7cc00a9
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/b7cc00a9

Branch: refs/heads/master
Commit: b7cc00a947832568fed7110cb94affcdd067d375
Parents: eb7e6cc
Author: Saisai Shao <sa...@gmail.com>
Authored: Thu Mar 16 09:58:03 2017 +0800
Committer: Jeff Zhang <zj...@gmail.com>
Committed: Thu Mar 16 09:58:03 2017 +0800

----------------------------------------------------------------------
 core/pom.xml   | 4 ----
 repl/pom.xml   | 4 ----
 server/pom.xml | 4 ----
 3 files changed, 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/b7cc00a9/core/pom.xml
----------------------------------------------------------------------
diff --git a/core/pom.xml b/core/pom.xml
index 75da834..437f00f 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -31,10 +31,6 @@
   <version>0.4.0-SNAPSHOT</version>
   <packaging>pom</packaging>
 
-  <properties>
-    <skipDeploy>true</skipDeploy>
-  </properties>
-
   <dependencies>
     <dependency>
       <groupId>com.cloudera.livy</groupId>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/b7cc00a9/repl/pom.xml
----------------------------------------------------------------------
diff --git a/repl/pom.xml b/repl/pom.xml
index 12675f7..6d5f73c 100644
--- a/repl/pom.xml
+++ b/repl/pom.xml
@@ -31,10 +31,6 @@
   <version>0.4.0-SNAPSHOT</version>
   <packaging>pom</packaging>
 
-  <properties>
-    <skipDeploy>true</skipDeploy>
-  </properties>
-
   <dependencies>
 
     <dependency>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/b7cc00a9/server/pom.xml
----------------------------------------------------------------------
diff --git a/server/pom.xml b/server/pom.xml
index 7ca8c65..6846be9 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -31,10 +31,6 @@
   <version>0.4.0-SNAPSHOT</version>
   <packaging>jar</packaging>
 
-  <properties>
-    <skipDeploy>true</skipDeploy>
-  </properties>
-
   <dependencies>
 
     <dependency>


[41/50] [abbrv] incubator-livy git commit: LIVY-342. Create Livy UI: Create Web UI Servlet and All Sessions Page (#319)

Posted by js...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/61b206e0/server/src/main/resources/com/cloudera/livy/server/ui/static/sessions-table.html
----------------------------------------------------------------------
diff --git a/server/src/main/resources/com/cloudera/livy/server/ui/static/sessions-table.html b/server/src/main/resources/com/cloudera/livy/server/ui/static/sessions-table.html
new file mode 100644
index 0000000..3452b4c
--- /dev/null
+++ b/server/src/main/resources/com/cloudera/livy/server/ui/static/sessions-table.html
@@ -0,0 +1,53 @@
+<!--
+ Licensed to Cloudera, Inc. under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  Cloudera, Inc. 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.
+-->
+
+<h4 id="interactive-sessions-header" class="sessions-template">Interactive Sessions</h4>
+
+<table class="table table-striped sessions-table sessions-template">
+  <thead class="sessions-table-head">
+  <tr>
+    <th>Session Id</th>
+    <th>Application Id</th>
+    <th>
+      <span data-toggle="tooltip" title="Remote user who submitted this session">
+        Owner
+      </span>
+    </th>
+    <th>
+      <span data-toggle="tooltip" title="User to impersonate when running">
+        Proxy User
+      </span>
+    </th>
+    <th>
+      <span data-toggle="tooltip"
+            title="Session kind (spark, pyspark, pyspark3, or sparkr)">
+        Session Kind
+      </span>
+    </th>
+    <th>
+      <span data-toggle="tooltip"
+            title="Session State (not_started, starting, idle, busy,
+            shutting_down, error, dead, success)">
+        State
+      </span>
+    </th>
+  </tr>
+  </thead>
+  <tbody class="sessions-table-body">
+  </tbody>
+</table>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/61b206e0/server/src/main/scala/com/cloudera/livy/LivyConf.scala
----------------------------------------------------------------------
diff --git a/server/src/main/scala/com/cloudera/livy/LivyConf.scala b/server/src/main/scala/com/cloudera/livy/LivyConf.scala
index 8fc4777..233aa63 100644
--- a/server/src/main/scala/com/cloudera/livy/LivyConf.scala
+++ b/server/src/main/scala/com/cloudera/livy/LivyConf.scala
@@ -64,6 +64,8 @@ object LivyConf {
   val SERVER_PORT = Entry("livy.server.port", 8998)
   val CSRF_PROTECTION = LivyConf.Entry("livy.server.csrf-protection.enabled", false)
 
+  val UI_ENABLED = Entry("livy.ui.enabled", true)
+
   val IMPERSONATION_ENABLED = Entry("livy.impersonation.enabled", false)
   val SUPERUSERS = Entry("livy.superusers", null)
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/61b206e0/server/src/main/scala/com/cloudera/livy/server/LivyServer.scala
----------------------------------------------------------------------
diff --git a/server/src/main/scala/com/cloudera/livy/server/LivyServer.scala b/server/src/main/scala/com/cloudera/livy/server/LivyServer.scala
index 4bd5635..7bfe9ce 100644
--- a/server/src/main/scala/com/cloudera/livy/server/LivyServer.scala
+++ b/server/src/main/scala/com/cloudera/livy/server/LivyServer.scala
@@ -30,12 +30,14 @@ import org.apache.hadoop.security.authentication.server._
 import org.eclipse.jetty.servlet.FilterHolder
 import org.scalatra.metrics.MetricsBootstrap
 import org.scalatra.metrics.MetricsSupportExtensions._
+import org.scalatra.ScalatraServlet
 import org.scalatra.servlet.{MultipartConfig, ServletApiImplicits}
 
 import com.cloudera.livy._
 import com.cloudera.livy.server.batch.BatchSessionServlet
 import com.cloudera.livy.server.interactive.InteractiveSessionServlet
 import com.cloudera.livy.server.recovery.{SessionStore, StateStore}
+import com.cloudera.livy.server.ui.UIServlet
 import com.cloudera.livy.sessions.{BatchSessionManager, InteractiveSessionManager}
 import com.cloudera.livy.sessions.SessionManager.SESSION_RECOVERY_MODE_OFF
 import com.cloudera.livy.utils.LivySparkUtils._
@@ -142,6 +144,20 @@ class LivyServer extends Logging {
       }
     }
 
+    // Servlet for hosting static files such as html, css, and js
+    // Necessary since Jetty cannot set it's resource base inside a jar
+    val staticResourceServlet = new ScalatraServlet {
+      get("/*") {
+        getClass.getResourceAsStream("ui/static/" + params("splat"))
+      }
+    }
+
+    def uiRedirectServlet(path: String) = new ScalatraServlet {
+      get("/") {
+        redirect(path)
+      }
+    }
+
     server.context.addEventListener(
       new ServletContextListener() with MetricsBootstrap with ServletApiImplicits {
 
@@ -167,7 +183,16 @@ class LivyServer extends Logging {
             val batchServlet = new BatchSessionServlet(batchSessionManager, sessionStore, livyConf)
             mount(context, batchServlet, "/batches/*")
 
-            context.mountMetricsAdminServlet("/")
+            if (livyConf.getBoolean(UI_ENABLED)) {
+              val uiServlet = new UIServlet
+              mount(context, uiServlet, "/ui/*")
+              mount(context, staticResourceServlet, "/static/*")
+              mount(context, uiRedirectServlet("/ui/"), "/*")
+            } else {
+              mount(context, uiRedirectServlet("/metrics"), "/*")
+            }
+
+            context.mountMetricsAdminServlet("/metrics")
 
             mount(context, livyVersionServlet, "/version/*")
           } catch {

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/61b206e0/server/src/main/scala/com/cloudera/livy/server/ui/UIServlet.scala
----------------------------------------------------------------------
diff --git a/server/src/main/scala/com/cloudera/livy/server/ui/UIServlet.scala b/server/src/main/scala/com/cloudera/livy/server/ui/UIServlet.scala
new file mode 100644
index 0000000..ca2d4a1
--- /dev/null
+++ b/server/src/main/scala/com/cloudera/livy/server/ui/UIServlet.scala
@@ -0,0 +1,76 @@
+/*
+ * Licensed to Cloudera, Inc. under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  Cloudera, Inc. 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 com.cloudera.livy.server.ui
+
+import scala.xml.Node
+
+import org.scalatra.ScalatraServlet
+
+import com.cloudera.livy.LivyConf
+
+class UIServlet extends ScalatraServlet {
+  before() { contentType = "text/html" }
+
+  def getHeader(title: String): Seq[Node] =
+    <head>
+      <link rel="stylesheet" href="/static/bootstrap.min.css" type="text/css"/>
+      <link rel="stylesheet" href="/static/livy-ui.css" type="text/css"/>
+      <script src="/static/jquery-3.2.1.min.js"></script>
+      <script src="/static/bootstrap.min.js"></script>
+      <script src="/static/all-sessions.js"></script>
+      <title>{title}</title>
+    </head>
+
+  def navBar(pageName: String): Seq[Node] =
+    <nav class="navbar navbar-default">
+      <div class="container-fluid">
+        <div class="navbar-header">
+          <a class="navbar-brand" href="#">
+            <img alt="Livy" src="/static/livy-mini-logo.png"/>
+          </a>
+        </div>
+        <div class="collapse navbar-collapse">
+          <ul class="nav navbar-nav">
+            <li><a href="#">{pageName}</a></li>
+          </ul>
+        </div>
+      </div>
+    </nav>
+
+  def createPage(pageName: String, pageContents: Seq[Node]): Seq[Node] =
+    <html>
+      {getHeader("Livy - " + pageName)}
+      <body>
+        <div class="container">
+          {navBar(pageName)}
+          {pageContents}
+        </div>
+      </body>
+    </html>
+
+  get("/") {
+    val content =
+      <div id="all-sessions">
+        <div id="interactive-sessions"></div>
+        <div id="batches"></div>
+      </div>
+
+    createPage("Sessions", content)
+  }
+}


[44/50] [abbrv] incubator-livy git commit: LIVY-342. Create Livy UI: Create Web UI Servlet and All Sessions Page (#319)

Posted by js...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/61b206e0/server/src/main/resources/com/cloudera/livy/server/ui/static/bootstrap.min.css
----------------------------------------------------------------------
diff --git a/server/src/main/resources/com/cloudera/livy/server/ui/static/bootstrap.min.css b/server/src/main/resources/com/cloudera/livy/server/ui/static/bootstrap.min.css
new file mode 100755
index 0000000..72cc3ab
--- /dev/null
+++ b/server/src/main/resources/com/cloudera/livy/server/ui/static/bootstrap.min.css
@@ -0,0 +1,14 @@
+/*!
+ * Bootstrap v3.3.7 (http://getbootstrap.com)
+ * Copyright 2011-2017 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+
+/*!
+ * Generated using the Bootstrap Customizer (http://getbootstrap.com/customize/?id=794c6d582814e1084501e746ef56e328)
+ * Config saved to config.json and https://gist.github.com/794c6d582814e1084501e746ef56e328
+ *//*!
+ * Bootstrap v3.3.7 (http://getbootstrap.com)
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace, monospa
 ce;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{border:0
 ;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,*:before,*:after{background:transparent !important;color:#000 !important;-webkit-box-shadow:none !important;box-shadow:none !important;text-shadow:none !important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000 !important}.label{border:1px solid #000}.table{border-collapse:collapse !important}.table td,.table th{background-color:#fff !important}.t
 able-bordered th,.table-bordered td{border:1px solid #ddd !important}}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:hover,a:focus{color:#23527c;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive,.thumbnail>img,.thumbnail a>img,.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #
 ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role="button"]{cursor:pointer}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#777}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10p
 x}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}mark,.mark{background-color:#fcf8e3;padding:.2em}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab
 7}a.text-primary:hover,a.text-primary:focus{color:#286090}.text-success{color:#3c763d}a.text-success:hover,a.text-success:focus{color:#2b542c}.text-info{color:#31708f}a.text-info:hover,a.text-info:focus{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover,a.text-warning:focus{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover,a.text-danger:focus{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:hover,a.bg-primary:focus{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:hover,a.bg-success:focus{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover,a.bg-info:focus{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover,a.bg-warning:focus{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover,a.bg-danger:focus{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10p
 x}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.42857143}dt{font-weight:bold}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote footer:before,blockquote small:before,blockquote .
 small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0;text-align:right}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.25);box-shadow:i
 nset 0 -1px 0 rgba(0,0,0,0.25)}kbd kbd{padding:0;font-size:100%;font-weight:bold;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;word-break:break-all;word-wrap:break-word;color:#333;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4
 , .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs
 -pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-x
 s-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col
 -sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-
 left:0}}@media (min-width:992px){.col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-p
 ush-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width
 :91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:1
 6.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:
 2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*="col-"]{positi
 on:static;float:none;display:table-column}table td[class*="col-"],table th[class*="col-"]{position:static;float:none;display:table-cell}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>t
 r.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tf
 oot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}.table-responsive{overflow-x:auto;min-height:0.01%}@media screen and (max-width:767px){.table-responsive{
 width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-
 bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0;min-width:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:bold}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}input[type="range"]{display:block;width:100%}select[multiple],select[size]{height:auto}in
 put[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6)}.form-control::-moz-placehol
 der{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{border:0;background-color:transparent}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type="search"]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type="date"].form-control,input[type="time"].form-control,input[type="datetime-local"].form-control,input[type="month"].form-control{line-height:34px}input[type="date"].input-sm,input[type="time"].input-sm,input[type="datetime-local"].input-sm,input[type="month"].input-sm,.input-group-sm input[type="date"],.input-group-sm input[type="time"],.input-group-sm input[type="datetime-local"],.input-group-sm input[type="month"]{line-height:30px}input[type="date"].input-lg,input[type="t
 ime"].input-lg,input[type="datetime-local"].input-lg,input[type="month"].input-lg,.input-group-lg input[type="date"],.input-group-lg input[type="time"],.input-group-lg input[type="datetime-local"],.input-group-lg input[type="month"]{line-height:46px}}.form-group{margin-bottom:15px}.radio,.checkbox{position:relative;display:block;margin-top:10px;margin-bottom:10px}.radio label,.checkbox label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:normal;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{position:absolute;margin-left:-20px;margin-top:4px \9}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:normal;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled
 ],input[type="checkbox"][disabled],input[type="radio"].disabled,input[type="checkbox"].disabled,fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"]{cursor:not-allowed}.radio-inline.disabled,.checkbox-inline.disabled,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.radio.disabled label,.checkbox.disabled label,fieldset[disabled] .radio label,fieldset[disabled] .checkbox label{cursor:not-allowed}.form-control-static{padding-top:7px;padding-bottom:7px;margin-bottom:0;min-height:34px}.form-control-static.input-lg,.form-control-static.input-sm{padding-left:0;padding-right:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm,select[multiple].input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-heig
 ht:30px}.form-group-sm textarea.form-control,.form-group-sm select[multiple].form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}textarea.input-lg,select[multiple].input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg textarea.form-control,.form-group-lg select[multiple].form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:3
 4px;text-align:center;pointer-events:none}.input-lg+.form-control-feedback,.input-group-lg+.form-control-feedback,.form-group-lg .form-control+.form-control-feedback{width:46px;height:46px;line-height:46px}.input-sm+.form-control-feedback,.input-group-sm+.form-control-feedback,.form-group-sm .form-control+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline,.has-success.radio label,.has-success.checkbox label,.has-success.radio-inline label,.has-success.checkbox-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168}.has-succe
 ss .input-group-addon{color:#3c763d;border-color:#3c763d;background-color:#dff0d8}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline,.has-warning.radio label,.has-warning.checkbox label,.has-warning.radio-inline label,.has-warning.checkbox-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;border-color:#8a6d3b;background-color:#fcf8e3}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-
 inline,.has-error .checkbox-inline,.has-error.radio label,.has-error.checkbox label,.has-error.radio-inline label,.has-error.checkbox-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;border-color:#a94442;background-color:#f2dede}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle
 }.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn,.form-inline .input-group .form-control{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .radio label,.form-inline .checkbox label{padding-left:0}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:7px}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group
 {margin-left:-15px;margin-right:-15px}@media (min-width:768px){.form-horizontal .control-label{text-align:right;margin-bottom:0;padding-top:7px}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:active:focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn.active.focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus,
 .btn.focus{color:#333;text-decoration:none}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:focus,.btn-default.focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default:active:hover,.btn-default.active:hover,.open>.dropdown-toggle.btn-default:hover,.btn-default:active:focus,.btn-default.active:focus,.open>.dropdown-toggle.btn-default:focus,.btn-default:active.focus,.btn-default
 .active.focus,.open>.dropdown-toggle.btn-default.focus{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled.focus,.btn-default[disabled].focus,fieldset[disabled] .btn-default.focus{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary:focus,.btn-primary.focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary:active:hover,.btn-primar
 y.active:hover,.open>.dropdown-toggle.btn-primary:hover,.btn-primary:active:focus,.btn-primary.active:focus,.open>.dropdown-toggle.btn-primary:focus,.btn-primary:active.focus,.btn-primary.active.focus,.open>.dropdown-toggle.btn-primary.focus{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled.focus,.btn-primary[disabled].focus,fieldset[disabled] .btn-primary.focus{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:focus,.btn-success.focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#4
 49d44;border-color:#398439}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success:active:hover,.btn-success.active:hover,.open>.dropdown-toggle.btn-success:hover,.btn-success:active:focus,.btn-success.active:focus,.open>.dropdown-toggle.btn-success:focus,.btn-success:active.focus,.btn-success.active.focus,.open>.dropdown-toggle.btn-success.focus{color:#fff;background-color:#398439;border-color:#255625}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled.focus,.btn-success[disabled].focus,fieldset[disabled] .btn-success.focus{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#f
 ff;background-color:#5bc0de;border-color:#46b8da}.btn-info:focus,.btn-info.focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info:active:hover,.btn-info.active:hover,.open>.dropdown-toggle.btn-info:hover,.btn-info:active:focus,.btn-info.active:focus,.open>.dropdown-toggle.btn-info:focus,.btn-info:active.focus,.btn-info.active.focus,.open>.dropdown-toggle.btn-info.focus{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled.focus,.btn-info[disabled].focus,fieldset[disabled] .btn-info.focus{backgrou
 nd-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:focus,.btn-warning.focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning:active:hover,.btn-warning.active:hover,.open>.dropdown-toggle.btn-warning:hover,.btn-warning:active:focus,.btn-warning.active:focus,.open>.dropdown-toggle.btn-warning:focus,.btn-warning:active.focus,.btn-warning.active.focus,.open>.dropdown-toggle.btn-warning.focus{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-
 warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled.focus,.btn-warning[disabled].focus,fieldset[disabled] .btn-warning.focus{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:focus,.btn-danger.focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger:active:hover,.btn-danger.active:hover,.open>.dropdown-toggle.btn-danger:hover,.btn-danger:active:focus,.btn-danger.active:focus,.open>.dropdown-toggle.btn-danger:focus,.btn-danger:active.focus,.btn-danger.active.focus,.open>.dropdown-toggle.btn-danger.focus{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger:activ
 e,.btn-danger.active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled.focus,.btn-danger[disabled].focus,fieldset[disabled] .btn-danger.focus{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{color:#337ab7;font-weight:normal;border-radius:0}.btn-link,.btn-link:active,.btn-link.active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#777;text
 -decoration:none}.btn-lg,.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-sm,.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs,.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-property:height, visibility;-o-transition-property:height, visibility;transition-property:height, visibility;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-
 duration:.35s;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid \9;border-right:4px solid transparent;border-left:4px solid transparent}.dropup,.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;font-size:14px;text-align:left;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.175);box-shadow:0 6px 12px rgba(0,0,0,0.175);-webkit-background-clip:padding-box;background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px
 ;clear:both;font-weight:normal;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{text-decoration:none;color:#262626;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;outline:0;background-color:#337ab7}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#777}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{left:auto;right:0}.dropdown-menu-left{left:0;right:auto}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:9
 90}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px dashed;border-bottom:4px solid \9;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{left:auto;right:0}.navbar-right .dropdown-menu-left{left:0;right:auto}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.b
 tn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdow
 n-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child
 ){border-top-right-radius:4px;border-top-left-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-right-radius:0;border-top-left-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{float:none;display:table-cell;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}
 [data-toggle="buttons"]>.btn input[type="radio"],[data-toggle="buttons"]>.btn-group>.btn input[type="radio"],[data-toggle="buttons"]>.btn input[type="checkbox"],[data-toggle="buttons"]>.btn-group>.btn input[type="checkbox"]{position:absolute;clip:rect(0, 0, 0, 0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*="col-"]{float:none;padding-left:0;padding-right:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-gro
 up-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-chil
 d),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:normal;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type="radio"],.input-group-addon input[type="checkbox"]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:fi
 rst-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{margin-bottom:0;padding-left:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;
 padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#777;text-decoration:none;background-color:transparent;cursor:not-allowed}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a
 {text-align:center;margin-bottom:5px}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-just
 ified>li{float:none}.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px
 }}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block !important;height:auto !important;padding-bottom:0;overflow:visible !important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-left:0;padding-right:0}}.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:200px}}.container>.navbar-h
 eader,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:15px 15px;font-size:18px;line-height:20px;height:50px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}
 .navbar-toggle{position:relative;float:right;margin-right:15px;padding:9px 10px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@me
 dia (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{margin-left:-15px;margin-right:-15px;padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);margin-top:8px;margin-bottom:8px}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn,.navbar-form .input-group .form-control{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-labe
 l{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .radio label,.navbar-form .checkbox label{padding-left:0}.navbar-form .radio input[type="radio"],.navbar-form .checkbox input[type="checkbox"]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-right-radius:4px;border-top-left-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px
 }.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-left:15px;margin-right:15px}}@media (min-width:768px){.navbar-left{float:left !important}.navbar-right{float:right !important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-defau
 lt .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:#e7e7e7;color:#555}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .
 navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:hover,.navbar-default .btn-link:focus{color:#333}.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:hover,.navbar-default .btn-link[disabled]:focus,fieldset[disabled] .navbar-default .btn-link:focus{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-
 nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{background-color:#080808;color:#fff}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.
 dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:hover,.navbar-inverse .btn-link:f
 ocus{color:#fff}.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:hover,.navbar-inverse .btn-link[disabled]:focus,fieldset[disabled] .navbar-inverse .btn-link:focus{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{content:"/\00a0";padding:0 5px;color:#ccc}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;line-height:1.42857143;text-decoration:none;color:#337ab7;background-color:#fff;border:1px solid #ddd;margin-left:-1px}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-bottom-right-radius:4px;border-to
 p-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:3;color:#fff;background-color:#337ab7;border-color:#337ab7;cursor:default}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#777;background-color:#fff;border-color:#ddd;cursor:not-allowed}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-bottom-right-radius:6px;bord
 er-top-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:3px;border-top-right-radius:3px}.pager{padding-left:0;margin:20px 0;list-style:none;text-align:center}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#777;background-color:#fff;cursor:not-allowed}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;co
 lor:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:hover,a.label:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:hover,.label-default[href]:focus{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size
 :12px;font-weight:bold;color:#fff;line-height:1;vertical-align:middle;white-space:nowrap;text-align:center;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge,.btn-group-xs>.btn .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron h1,.jumbotron .h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{border-radius:6px;padding-left:15px;padding-right:15px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.j
 umbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-left:60px;padding-right:60px}.jumbotron h1,.jumbotron .h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail>img,.thumbnail a>img{margin-left:auto;margin-right:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inher
 it}.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#31708f}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{background-color:#fcf8e3;border-color:#faebcc;color:#8a6d3b}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{background-color:#f2dede;border-color:#ebccd1;color:#a94442}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{overflow:hidden;height:20px;margin-bottom:20px;background-color:#f5f5f5;b
 order-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress-bar{float:left;width:0%;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar,.progress-bar-striped{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, 
 rgba(255,255,255,0.15) 75%, transparent 75%, transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress.active .progress-bar,.progress-bar.active{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.pro
 gress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.
 15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.media{margin-top:15
 px}.media:first-child{margin-top:0}.media,.media-body{zoom:1;overflow:hidden}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-left,.media-right,.media-body{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{margin-bottom:20px;padding-left:0}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list
 -group-item-heading{color:#333}a.list-group-item:hover,button.list-group-item:hover,a.list-group-item:focus,button.list-group-item:focus{text-decoration:none;color:#555;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:hover,.list-group-item.disabled:focus{background-color:#eee;color:#777;cursor:not-allowed}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading,.list-grou
 p-item.active:focus .list-group-item-heading,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>.small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:hover .list-group-item-text,.list-group-item.active:focus .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:hover,button.list-group-item-success:hover,a.list-group-item-success:focus,button.list-group-item-success:focus{color:#3c763d;backgroun
 d-color:#d0e9c6}a.list-group-item-success.active,button.list-group-item-success.active,a.list-group-item-success.active:hover,button.list-group-item-success.active:hover,a.list-group-item-success.active:focus,button.list-group-item-success.active:focus{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:hover,button.list-group-item-info:hover,a.list-group-item-info:focus,button.list-group-item-info:focus{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,button.list-group-item-info.active,a.list-group-item-info.active:hover,button.list-group-item-info.active:hover,a.list-group-item-info.active:focus,button.list-group-item-info.active:focus{color:#fff;background-color:#31708f;border-color:#31708f}.list
 -group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:hover,button.list-group-item-warning:hover,a.list-group-item-warning:focus,button.list-group-item-warning:focus{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,button.list-group-item-warning.active,a.list-group-item-warning.active:hover,button.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus,button.list-group-item-warning.active:focus{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger
 :hover,button.list-group-item-danger:hover,a.list-group-item-danger:focus,button.list-group-item-danger:focus{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,button.list-group-item-danger.active,a.list-group-item-danger.active:hover,button.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus,button.list-group-item-danger.active:focus{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.05);box-shadow:0 1px 1px rgba(0,0,0,0.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inh
 erit}.panel-title>a,.panel-title>small,.panel-title>.small,.panel-title>small>a,.panel-title>.small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-right-radius:3px;border-top-left-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-right-radius:0;border-top-left-radius:0}.
 panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.table,.panel>.table-responsive>.table,.panel>.panel-collapse>.table{margin-bottom:0}.panel>.table caption,.panel>.table-responsive>.table caption,.panel>.panel-collapse>.table caption{padding-left:15px;padding-right:15px}.panel>.table:first-child,.panel>.table-responsive:first-child>.table:first-child{border-top-right-radius:3px;border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-chil
 d td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-
 child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child,.panel>.table-responsive:last-child>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-left-radius:3px;border-bottom-right-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot
 :last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:la
 st-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.ta

<TRUNCATED>


[12/50] [abbrv] incubator-livy git commit: LIVY-274. Add travis CI status in README (#288)

Posted by js...@apache.org.
LIVY-274. Add travis CI status in README (#288)



Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/a36e44f4
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/a36e44f4
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/a36e44f4

Branch: refs/heads/master
Commit: a36e44f405dae0409815f6872762b1a38f9bffa9
Parents: 663c613
Author: Jonathan Alter <jo...@users.noreply.github.com>
Authored: Tue Feb 14 13:58:52 2017 -0800
Committer: Alex Man <tc...@gmail.com>
Committed: Tue Feb 14 16:58:52 2017 -0500

----------------------------------------------------------------------
 README.rst | 3 +++
 1 file changed, 3 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/a36e44f4/README.rst
----------------------------------------------------------------------
diff --git a/README.rst b/README.rst
index e0b76c2..1331bf7 100644
--- a/README.rst
+++ b/README.rst
@@ -1,6 +1,9 @@
 Welcome to Livy
 ===============
 
+.. image:: https://travis-ci.org/cloudera/livy.svg?branch=master
+    :target: https://travis-ci.org/cloudera/livy
+
 Livy is an open source REST interface for interacting with `Apache Spark`_ from anywhere.
 It supports executing snippets of code or programs in a Spark context that runs locally or in `Apache Hadoop YARN`_.
 


[40/50] [abbrv] incubator-livy git commit: LIVY-355. Refactor statement progress tracker to fix binary compatible issue (#323)

Posted by js...@apache.org.
LIVY-355. Refactor statement progress tracker to fix binary compatible issue (#323)

* Refactor statement progress tracker to fix binary compatible issue

Change-Id: Ie91fd77472aeebe138bd6711a0baa82269a6b247

* refactor again to simplify the code

Change-Id: I9380bcb8dd2b594250783633a3c68e290ac7ea28

* isolate statementId to job group logic

Change-Id: If554aee2c0b3d96b54804f94cbb8df9af7843ab4


Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/0ddcaf68
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/0ddcaf68
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/0ddcaf68

Branch: refs/heads/master
Commit: 0ddcaf68d28a5120b1b74692bd92dde2301f5170
Parents: f5ef489
Author: Saisai Shao <sa...@gmail.com>
Authored: Wed May 10 04:25:57 2017 +0800
Committer: Jeff Zhang <zj...@gmail.com>
Committed: Tue May 9 13:25:57 2017 -0700

----------------------------------------------------------------------
 .../cloudera/livy/repl/SparkInterpreter.scala   |   4 +-
 .../livy/repl/SparkInterpreterSpec.scala        |   2 +-
 .../cloudera/livy/repl/SparkInterpreter.scala   |   4 +-
 .../livy/repl/SparkInterpreterSpec.scala        |   2 +-
 .../com/cloudera/livy/repl/Interpreter.scala    |  10 -
 .../cloudera/livy/repl/ProcessInterpreter.scala |   7 +-
 .../cloudera/livy/repl/PythonInterpreter.scala  |   9 +-
 .../com/cloudera/livy/repl/ReplDriver.scala     |  10 +-
 .../scala/com/cloudera/livy/repl/Session.scala  |  40 +++-
 .../cloudera/livy/repl/SparkRInterpreter.scala  |  10 +-
 .../livy/repl/StatementProgressListener.scala   | 162 -------------
 .../livy/repl/PythonInterpreterSpec.scala       |   6 +-
 .../cloudera/livy/repl/PythonSessionSpec.scala  |   6 +-
 .../livy/repl/ScalaInterpreterSpec.scala        |   2 +-
 .../livy/repl/SparkRInterpreterSpec.scala       |   3 +-
 .../cloudera/livy/repl/SparkRSessionSpec.scala  |   3 +-
 .../cloudera/livy/repl/SparkSessionSpec.scala   |  35 ++-
 .../repl/StatementProgressListenerSpec.scala    | 227 -------------------
 18 files changed, 93 insertions(+), 449 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0ddcaf68/repl/scala-2.10/src/main/scala/com/cloudera/livy/repl/SparkInterpreter.scala
----------------------------------------------------------------------
diff --git a/repl/scala-2.10/src/main/scala/com/cloudera/livy/repl/SparkInterpreter.scala b/repl/scala-2.10/src/main/scala/com/cloudera/livy/repl/SparkInterpreter.scala
index 5ef5491..d736125 100644
--- a/repl/scala-2.10/src/main/scala/com/cloudera/livy/repl/SparkInterpreter.scala
+++ b/repl/scala-2.10/src/main/scala/com/cloudera/livy/repl/SparkInterpreter.scala
@@ -33,8 +33,7 @@ import org.apache.spark.repl.SparkIMain
 /**
  * This represents a Spark interpreter. It is not thread safe.
  */
-class SparkInterpreter(conf: SparkConf,
-    override val statementProgressListener: StatementProgressListener)
+class SparkInterpreter(conf: SparkConf)
   extends AbstractSparkInterpreter with SparkContextInitializer {
 
   private var sparkIMain: SparkIMain = _
@@ -108,7 +107,6 @@ class SparkInterpreter(conf: SparkConf,
       createSparkContext(conf)
     }
 
-    sparkContext.addSparkListener(statementProgressListener)
     sparkContext
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0ddcaf68/repl/scala-2.10/src/test/scala/com/cloudera/livy/repl/SparkInterpreterSpec.scala
----------------------------------------------------------------------
diff --git a/repl/scala-2.10/src/test/scala/com/cloudera/livy/repl/SparkInterpreterSpec.scala b/repl/scala-2.10/src/test/scala/com/cloudera/livy/repl/SparkInterpreterSpec.scala
index 3df35b5..e2b783a 100644
--- a/repl/scala-2.10/src/test/scala/com/cloudera/livy/repl/SparkInterpreterSpec.scala
+++ b/repl/scala-2.10/src/test/scala/com/cloudera/livy/repl/SparkInterpreterSpec.scala
@@ -24,7 +24,7 @@ import com.cloudera.livy.LivyBaseUnitTestSuite
 
 class SparkInterpreterSpec extends FunSpec with Matchers with LivyBaseUnitTestSuite {
   describe("SparkInterpreter") {
-    val interpreter = new SparkInterpreter(null, null)
+    val interpreter = new SparkInterpreter(null)
 
     it("should parse Scala compile error.") {
       // Regression test for LIVY-260.

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0ddcaf68/repl/scala-2.11/src/main/scala/com/cloudera/livy/repl/SparkInterpreter.scala
----------------------------------------------------------------------
diff --git a/repl/scala-2.11/src/main/scala/com/cloudera/livy/repl/SparkInterpreter.scala b/repl/scala-2.11/src/main/scala/com/cloudera/livy/repl/SparkInterpreter.scala
index 6735b3a..f08a46e 100644
--- a/repl/scala-2.11/src/main/scala/com/cloudera/livy/repl/SparkInterpreter.scala
+++ b/repl/scala-2.11/src/main/scala/com/cloudera/livy/repl/SparkInterpreter.scala
@@ -33,8 +33,7 @@ import org.apache.spark.repl.SparkILoop
 /**
  * Scala 2.11 version of SparkInterpreter
  */
-class SparkInterpreter(conf: SparkConf,
-    override val statementProgressListener: StatementProgressListener)
+class SparkInterpreter(conf: SparkConf)
   extends AbstractSparkInterpreter with SparkContextInitializer {
 
   protected var sparkContext: SparkContext = _
@@ -94,7 +93,6 @@ class SparkInterpreter(conf: SparkConf,
       createSparkContext(conf)
     }
 
-    sparkContext.addSparkListener(statementProgressListener)
     sparkContext
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0ddcaf68/repl/scala-2.11/src/test/scala/com/cloudera/livy/repl/SparkInterpreterSpec.scala
----------------------------------------------------------------------
diff --git a/repl/scala-2.11/src/test/scala/com/cloudera/livy/repl/SparkInterpreterSpec.scala b/repl/scala-2.11/src/test/scala/com/cloudera/livy/repl/SparkInterpreterSpec.scala
index 56656d7..5cb88e3 100644
--- a/repl/scala-2.11/src/test/scala/com/cloudera/livy/repl/SparkInterpreterSpec.scala
+++ b/repl/scala-2.11/src/test/scala/com/cloudera/livy/repl/SparkInterpreterSpec.scala
@@ -24,7 +24,7 @@ import com.cloudera.livy.LivyBaseUnitTestSuite
 
 class SparkInterpreterSpec extends FunSpec with Matchers with LivyBaseUnitTestSuite {
   describe("SparkInterpreter") {
-    val interpreter = new SparkInterpreter(null, null)
+    val interpreter = new SparkInterpreter(null)
 
     it("should parse Scala compile error.") {
       // Regression test for LIVY-.

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0ddcaf68/repl/src/main/scala/com/cloudera/livy/repl/Interpreter.scala
----------------------------------------------------------------------
diff --git a/repl/src/main/scala/com/cloudera/livy/repl/Interpreter.scala b/repl/src/main/scala/com/cloudera/livy/repl/Interpreter.scala
index 59ad878..fa3b640 100644
--- a/repl/src/main/scala/com/cloudera/livy/repl/Interpreter.scala
+++ b/repl/src/main/scala/com/cloudera/livy/repl/Interpreter.scala
@@ -37,8 +37,6 @@ trait Interpreter {
 
   def kind: String
 
-  def statementProgressListener: StatementProgressListener
-
   /**
    * Start the Interpreter.
    *
@@ -47,14 +45,6 @@ trait Interpreter {
   def start(): SparkContext
 
   /**
-   * Execute the code and return the result.
-   */
-  def execute(statementId: Int, code: String): ExecuteResponse = {
-    statementProgressListener.setCurrentStatementId(statementId)
-    execute(code)
-  }
-
-  /**
    * Execute the code and return the result, it may
    * take some time to execute.
    */

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0ddcaf68/repl/src/main/scala/com/cloudera/livy/repl/ProcessInterpreter.scala
----------------------------------------------------------------------
diff --git a/repl/src/main/scala/com/cloudera/livy/repl/ProcessInterpreter.scala b/repl/src/main/scala/com/cloudera/livy/repl/ProcessInterpreter.scala
index 0414bbb..fe10697 100644
--- a/repl/src/main/scala/com/cloudera/livy/repl/ProcessInterpreter.scala
+++ b/repl/src/main/scala/com/cloudera/livy/repl/ProcessInterpreter.scala
@@ -41,8 +41,7 @@ private case class ShutdownRequest(promise: Promise[Unit]) extends Request
  *
  * @param process
  */
-abstract class ProcessInterpreter(process: Process,
-    override val statementProgressListener: StatementProgressListener)
+abstract class ProcessInterpreter(process: Process)
   extends Interpreter with Logging {
   protected[this] val stdin = new PrintWriter(process.getOutputStream)
   protected[this] val stdout = new BufferedReader(new InputStreamReader(process.getInputStream), 1)
@@ -53,9 +52,7 @@ abstract class ProcessInterpreter(process: Process,
     if (ClientConf.TEST_MODE) {
       null.asInstanceOf[SparkContext]
     } else {
-      val sc = SparkContext.getOrCreate()
-      sc.addSparkListener(statementProgressListener)
-      sc
+      SparkContext.getOrCreate()
     }
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0ddcaf68/repl/src/main/scala/com/cloudera/livy/repl/PythonInterpreter.scala
----------------------------------------------------------------------
diff --git a/repl/src/main/scala/com/cloudera/livy/repl/PythonInterpreter.scala b/repl/src/main/scala/com/cloudera/livy/repl/PythonInterpreter.scala
index 6e80c09..a04dfef 100644
--- a/repl/src/main/scala/com/cloudera/livy/repl/PythonInterpreter.scala
+++ b/repl/src/main/scala/com/cloudera/livy/repl/PythonInterpreter.scala
@@ -45,7 +45,7 @@ import com.cloudera.livy.sessions._
 // scalastyle:off println
 object PythonInterpreter extends Logging {
 
-  def apply(conf: SparkConf, kind: Kind, listener: StatementProgressListener): Interpreter = {
+  def apply(conf: SparkConf, kind: Kind): Interpreter = {
     val pythonExec = kind match {
         case PySpark() => sys.env.getOrElse("PYSPARK_PYTHON", "python")
         case PySpark3() => sys.env.getOrElse("PYSPARK3_PYTHON", "python3")
@@ -72,7 +72,7 @@ object PythonInterpreter extends Logging {
     env.put("LIVY_SPARK_MAJOR_VERSION", conf.get("spark.livy.spark_major_version", "1"))
     builder.redirectError(Redirect.PIPE)
     val process = builder.start()
-    new PythonInterpreter(process, gatewayServer, kind.toString, listener)
+    new PythonInterpreter(process, gatewayServer, kind.toString)
   }
 
   private def findPySparkArchives(): Seq[String] = {
@@ -190,9 +190,8 @@ object PythonInterpreter extends Logging {
 private class PythonInterpreter(
     process: Process,
     gatewayServer: GatewayServer,
-    pyKind: String,
-    listener: StatementProgressListener)
-  extends ProcessInterpreter(process, listener)
+    pyKind: String)
+  extends ProcessInterpreter(process)
   with Logging
 {
   implicit val formats = DefaultFormats

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0ddcaf68/repl/src/main/scala/com/cloudera/livy/repl/ReplDriver.scala
----------------------------------------------------------------------
diff --git a/repl/src/main/scala/com/cloudera/livy/repl/ReplDriver.scala b/repl/src/main/scala/com/cloudera/livy/repl/ReplDriver.scala
index d368c6a..695a9d0 100644
--- a/repl/src/main/scala/com/cloudera/livy/repl/ReplDriver.scala
+++ b/repl/src/main/scala/com/cloudera/livy/repl/ReplDriver.scala
@@ -44,11 +44,11 @@ class ReplDriver(conf: SparkConf, livyConf: RSCConf)
 
   override protected def initializeContext(): JavaSparkContext = {
     interpreter = kind match {
-      case PySpark() => PythonInterpreter(conf, PySpark(), new StatementProgressListener(livyConf))
+      case PySpark() => PythonInterpreter(conf, PySpark())
       case PySpark3() =>
-        PythonInterpreter(conf, PySpark3(), new StatementProgressListener(livyConf))
-      case Spark() => new SparkInterpreter(conf, new StatementProgressListener(livyConf))
-      case SparkR() => SparkRInterpreter(conf, new StatementProgressListener(livyConf))
+        PythonInterpreter(conf, PySpark3())
+      case Spark() => new SparkInterpreter(conf)
+      case SparkR() => SparkRInterpreter(conf)
     }
     session = new Session(livyConf, interpreter, { s => broadcast(new ReplState(s.toString)) })
 
@@ -94,7 +94,7 @@ class ReplDriver(conf: SparkConf, livyConf: RSCConf)
 
     // Update progress of statements when queried
     statements.foreach { s =>
-      s.updateProgress(interpreter.statementProgressListener.progressOfStatement(s.id))
+      s.updateProgress(session.progressOfStatement(s.id))
     }
 
     new ReplJobResults(statements.sortBy(_.id))

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0ddcaf68/repl/src/main/scala/com/cloudera/livy/repl/Session.scala
----------------------------------------------------------------------
diff --git a/repl/src/main/scala/com/cloudera/livy/repl/Session.scala b/repl/src/main/scala/com/cloudera/livy/repl/Session.scala
index 54056a3..31e520c 100644
--- a/repl/src/main/scala/com/cloudera/livy/repl/Session.scala
+++ b/repl/src/main/scala/com/cloudera/livy/repl/Session.scala
@@ -170,6 +170,29 @@ class Session(
     interpreter.close()
   }
 
+  /**
+   * Get the current progress of given statement id.
+   */
+  def progressOfStatement(stmtId: Int): Double = {
+    val jobGroup = statementIdToJobGroup(stmtId)
+
+    _sc.map { sc =>
+      val jobIds = sc.statusTracker.getJobIdsForGroup(jobGroup)
+      val jobs = jobIds.flatMap { id => sc.statusTracker.getJobInfo(id) }
+      val stages = jobs.flatMap { job =>
+        job.stageIds().flatMap(sc.statusTracker.getStageInfo)
+      }
+
+      val taskCount = stages.map(_.numTasks).sum
+      val completedTaskCount = stages.map(_.numCompletedTasks).sum
+      if (taskCount == 0) {
+        0.0
+      } else {
+        completedTaskCount.toDouble / taskCount
+      }
+    }.getOrElse(0.0)
+  }
+
   private def changeState(newState: SessionState): Unit = {
     synchronized {
       _state = newState
@@ -188,7 +211,7 @@ class Session(
     }
 
     val resultInJson = try {
-      interpreter.execute(executionCount, code) match {
+      interpreter.execute(code) match {
         case Interpreter.ExecuteSuccess(data) =>
           transitToIdle()
 
@@ -240,23 +263,28 @@ class Session(
   }
 
   private def setJobGroup(statementId: Int): String = {
+    val jobGroup = statementIdToJobGroup(statementId)
     val cmd = Kind(interpreter.kind) match {
       case Spark() =>
         // A dummy value to avoid automatic value binding in scala REPL.
-        s"""val _livyJobGroup$statementId = sc.setJobGroup("$statementId",""" +
-          s""""Job group for statement $statementId")"""
+        s"""val _livyJobGroup$jobGroup = sc.setJobGroup("$jobGroup",""" +
+          s""""Job group for statement $jobGroup")"""
       case PySpark() | PySpark3() =>
-        s"""sc.setJobGroup("$statementId", "Job group for statement $statementId")"""
+        s"""sc.setJobGroup("$jobGroup", "Job group for statement $jobGroup")"""
       case SparkR() =>
         interpreter.asInstanceOf[SparkRInterpreter].sparkMajorVersion match {
           case "1" =>
-            s"""setJobGroup(sc, "$statementId", "Job group for statement $statementId", """ +
+            s"""setJobGroup(sc, "$jobGroup", "Job group for statement $jobGroup", """ +
               "FALSE)"
           case "2" =>
-            s"""setJobGroup("$statementId", "Job group for statement $statementId", FALSE)"""
+            s"""setJobGroup("$jobGroup", "Job group for statement $jobGroup", FALSE)"""
         }
     }
     // Set the job group
     executeCode(statementId, cmd)
   }
+
+  private def statementIdToJobGroup(statementId: Int): String = {
+    statementId.toString
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0ddcaf68/repl/src/main/scala/com/cloudera/livy/repl/SparkRInterpreter.scala
----------------------------------------------------------------------
diff --git a/repl/src/main/scala/com/cloudera/livy/repl/SparkRInterpreter.scala b/repl/src/main/scala/com/cloudera/livy/repl/SparkRInterpreter.scala
index 7318b1e..469d0a5 100644
--- a/repl/src/main/scala/com/cloudera/livy/repl/SparkRInterpreter.scala
+++ b/repl/src/main/scala/com/cloudera/livy/repl/SparkRInterpreter.scala
@@ -68,7 +68,7 @@ object SparkRInterpreter {
     ")"
     ).r.unanchored
 
-  def apply(conf: SparkConf, listener: StatementProgressListener): SparkRInterpreter = {
+  def apply(conf: SparkConf): SparkRInterpreter = {
     val backendTimeout = sys.env.getOrElse("SPARKR_BACKEND_TIMEOUT", "120").toInt
     val mirror = universe.runtimeMirror(getClass.getClassLoader)
     val sparkRBackendClass = mirror.classLoader.loadClass("org.apache.spark.api.r.RBackend")
@@ -121,8 +121,7 @@ object SparkRInterpreter {
       val process = builder.start()
       new SparkRInterpreter(process, backendInstance, backendThread,
         conf.get("spark.livy.spark_major_version", "1"),
-        conf.getBoolean("spark.repl.enableHiveContext", false),
-        listener)
+        conf.getBoolean("spark.repl.enableHiveContext", false))
     } catch {
       case e: Exception =>
         if (backendThread != null) {
@@ -137,9 +136,8 @@ class SparkRInterpreter(process: Process,
     backendInstance: Any,
     backendThread: Thread,
     val sparkMajorVersion: String,
-    hiveEnabled: Boolean,
-    statementProgressListener: StatementProgressListener)
-  extends ProcessInterpreter(process, statementProgressListener) {
+    hiveEnabled: Boolean)
+  extends ProcessInterpreter(process) {
   import SparkRInterpreter._
 
   implicit val formats = DefaultFormats

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0ddcaf68/repl/src/main/scala/com/cloudera/livy/repl/StatementProgressListener.scala
----------------------------------------------------------------------
diff --git a/repl/src/main/scala/com/cloudera/livy/repl/StatementProgressListener.scala b/repl/src/main/scala/com/cloudera/livy/repl/StatementProgressListener.scala
deleted file mode 100644
index ae2147b..0000000
--- a/repl/src/main/scala/com/cloudera/livy/repl/StatementProgressListener.scala
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Licensed to Cloudera, Inc. under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  Cloudera, Inc. 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 com.cloudera.livy.repl
-
-import scala.collection.mutable
-
-import com.google.common.annotations.VisibleForTesting
-import org.apache.spark.Success
-import org.apache.spark.scheduler._
-
-import com.cloudera.livy.rsc.RSCConf
-
-/**
- * [[StatementProgressListener]] is an implementation of SparkListener, used to track the progress
- * of submitted statement, this class builds a mapping relation between statement, jobs, stages
- * and tasks, and uses the finished task number to calculate the statement progress.
- *
- * By default 100 latest statement progresses will be kept, users could also configure
- * livy.rsc.retained_statements to change the cached number.
- *
- * This statement progress can only reflect the statement in which has Spark jobs, if
- * the statement submitted doesn't generate any Spark job, the progress will always return 0.0
- * until completed.
- *
- * Also if the statement includes several Spark jobs, the progress will be flipped because we
- * don't know the actual number of Spark jobs/tasks generated before the statement executed.
- */
-class StatementProgressListener(conf: RSCConf) extends SparkListener {
-
-  case class TaskCount(var currFinishedTasks: Int, var totalTasks: Int)
-  case class JobState(jobId: Int, var isCompleted: Boolean)
-
-  private val retainedStatements = conf.getInt(RSCConf.Entry.RETAINED_STATEMENT_NUMBER)
-
-  /** Statement id to list of jobs map */
-  @VisibleForTesting
-  private[repl] val statementToJobs = new mutable.LinkedHashMap[Int, Seq[JobState]]()
-  @VisibleForTesting
-  private[repl] val jobIdToStatement = new mutable.HashMap[Int, Int]()
-  /** Job id to list of stage ids map */
-  @VisibleForTesting
-  private[repl] val jobIdToStages = new mutable.HashMap[Int, Seq[Int]]()
-  /** Stage id to number of finished/total tasks map */
-  @VisibleForTesting
-  private[repl] val stageIdToTaskCount = new mutable.HashMap[Int, TaskCount]()
-
-  @transient private var currentStatementId: Int = _
-
-  /**
-   * Set current statement id, onJobStart() will use current statement id to build the mapping
-   * relations.
-   */
-  def setCurrentStatementId(stmtId: Int): Unit = {
-    currentStatementId = stmtId
-  }
-
-  /**
-   * Get the current progress of given statement id.
-   */
-  def progressOfStatement(stmtId: Int): Double = synchronized {
-    var finishedTasks = 0
-    var totalTasks = 0
-
-    for {
-      job <- statementToJobs.getOrElse(stmtId, Seq.empty)
-      stageId <- jobIdToStages.getOrElse(job.jobId, Seq.empty)
-      taskCount <- stageIdToTaskCount.get(stageId)
-    } yield {
-      finishedTasks += taskCount.currFinishedTasks
-      totalTasks += taskCount.totalTasks
-    }
-
-    if (totalTasks == 0) {
-      0.0
-    } else {
-      finishedTasks.toDouble / totalTasks
-    }
-  }
-
-  /**
-   * Get the active job ids of the given statement id.
-   */
-  def activeJobsOfStatement(stmtId: Int): Seq[Int] = synchronized {
-    statementToJobs.getOrElse(stmtId, Seq.empty).filter(!_.isCompleted).map(_.jobId)
-  }
-
-  override def onJobStart(jobStart: SparkListenerJobStart): Unit = synchronized {
-    val jobs = statementToJobs.getOrElseUpdate(currentStatementId, Seq.empty) :+
-      JobState(jobStart.jobId, isCompleted = false)
-    statementToJobs.put(currentStatementId, jobs)
-    jobIdToStatement(jobStart.jobId) = currentStatementId
-
-    jobIdToStages(jobStart.jobId) = jobStart.stageInfos.map(_.stageId)
-    jobStart.stageInfos.foreach { s => stageIdToTaskCount(s.stageId) = TaskCount(0, s.numTasks) }
-  }
-
-  override def onTaskEnd(taskEnd: SparkListenerTaskEnd): Unit = synchronized {
-    taskEnd.reason match {
-      case Success =>
-        stageIdToTaskCount.get(taskEnd.stageId).foreach { t => t.currFinishedTasks += 1 }
-      case _ =>
-        // If task is failed, it will run again, so don't count it.
-    }
-  }
-
-  override def onStageSubmitted(stageSubmitted: SparkListenerStageSubmitted): Unit = synchronized {
-    // If stage is resubmitted, we should reset the task count of this stage.
-    stageIdToTaskCount.get(stageSubmitted.stageInfo.stageId).foreach { t =>
-      t.currFinishedTasks = 0
-      t.totalTasks = stageSubmitted.stageInfo.numTasks
-    }
-  }
-
-  override def onStageCompleted(stageCompleted: SparkListenerStageCompleted): Unit = synchronized {
-    stageIdToTaskCount.get(stageCompleted.stageInfo.stageId).foreach { t =>
-      t.currFinishedTasks = t.totalTasks
-    }
-  }
-
-  override def onJobEnd(jobEnd: SparkListenerJobEnd): Unit = synchronized {
-    jobIdToStatement.get(jobEnd.jobId).foreach { stmtId =>
-      statementToJobs.get(stmtId).foreach { jobs =>
-        jobs.filter(_.jobId == jobEnd.jobId).foreach(_.isCompleted = true)
-      }
-    }
-
-    // Try to clean the old data when job is finished. This will trigger data cleaning in LRU
-    // policy.
-    cleanOldMetadata()
-  }
-
-  private def cleanOldMetadata(): Unit = {
-    if (statementToJobs.size > retainedStatements) {
-      val toRemove = statementToJobs.size - retainedStatements
-      statementToJobs.take(toRemove).foreach { case (_, jobs) =>
-        jobs.foreach { job =>
-          jobIdToStatement.remove(job.jobId)
-          jobIdToStages.remove(job.jobId).foreach { stages =>
-            stages.foreach(s => stageIdToTaskCount.remove(s))
-          }
-        }
-      }
-      (0 until toRemove).foreach(_ => statementToJobs.remove(statementToJobs.head._1))
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0ddcaf68/repl/src/test/scala/com/cloudera/livy/repl/PythonInterpreterSpec.scala
----------------------------------------------------------------------
diff --git a/repl/src/test/scala/com/cloudera/livy/repl/PythonInterpreterSpec.scala b/repl/src/test/scala/com/cloudera/livy/repl/PythonInterpreterSpec.scala
index c67d580..a4a40af 100644
--- a/repl/src/test/scala/com/cloudera/livy/repl/PythonInterpreterSpec.scala
+++ b/repl/src/test/scala/com/cloudera/livy/repl/PythonInterpreterSpec.scala
@@ -245,8 +245,7 @@ class Python2InterpreterSpec extends PythonBaseInterpreterSpec {
 
   implicit val formats = DefaultFormats
 
-  override def createInterpreter(): Interpreter =
-    PythonInterpreter(new SparkConf(), PySpark(), new StatementProgressListener(new RSCConf()))
+  override def createInterpreter(): Interpreter = PythonInterpreter(new SparkConf(), PySpark())
 
   // Scalastyle is treating unicode escape as non ascii characters. Turn off the check.
   // scalastyle:off non.ascii.character.disallowed
@@ -273,8 +272,7 @@ class Python3InterpreterSpec extends PythonBaseInterpreterSpec {
     test()
   }
 
-  override def createInterpreter(): Interpreter =
-    PythonInterpreter(new SparkConf(), PySpark3(), new StatementProgressListener(new RSCConf()))
+  override def createInterpreter(): Interpreter = PythonInterpreter(new SparkConf(), PySpark3())
 
   it should "check python version is 3.x" in withInterpreter { interpreter =>
     val response = interpreter.execute("""import sys

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0ddcaf68/repl/src/test/scala/com/cloudera/livy/repl/PythonSessionSpec.scala
----------------------------------------------------------------------
diff --git a/repl/src/test/scala/com/cloudera/livy/repl/PythonSessionSpec.scala b/repl/src/test/scala/com/cloudera/livy/repl/PythonSessionSpec.scala
index 28f457f..1e5958d 100644
--- a/repl/src/test/scala/com/cloudera/livy/repl/PythonSessionSpec.scala
+++ b/repl/src/test/scala/com/cloudera/livy/repl/PythonSessionSpec.scala
@@ -174,8 +174,7 @@ abstract class PythonSessionSpec extends BaseSessionSpec {
 }
 
 class Python2SessionSpec extends PythonSessionSpec {
-  override def createInterpreter(): Interpreter =
-    PythonInterpreter(new SparkConf(), PySpark(), new StatementProgressListener(new RSCConf()))
+  override def createInterpreter(): Interpreter = PythonInterpreter(new SparkConf(), PySpark())
 }
 
 class Python3SessionSpec extends PythonSessionSpec {
@@ -185,8 +184,7 @@ class Python3SessionSpec extends PythonSessionSpec {
     test()
   }
 
-  override def createInterpreter(): Interpreter =
-    PythonInterpreter(new SparkConf(), PySpark3(), new StatementProgressListener(new RSCConf()))
+  override def createInterpreter(): Interpreter = PythonInterpreter(new SparkConf(), PySpark3())
 
   it should "check python version is 3.x" in withSession { session =>
     val statement = execute(session)(

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0ddcaf68/repl/src/test/scala/com/cloudera/livy/repl/ScalaInterpreterSpec.scala
----------------------------------------------------------------------
diff --git a/repl/src/test/scala/com/cloudera/livy/repl/ScalaInterpreterSpec.scala b/repl/src/test/scala/com/cloudera/livy/repl/ScalaInterpreterSpec.scala
index a9e1e8b..0126796 100644
--- a/repl/src/test/scala/com/cloudera/livy/repl/ScalaInterpreterSpec.scala
+++ b/repl/src/test/scala/com/cloudera/livy/repl/ScalaInterpreterSpec.scala
@@ -29,7 +29,7 @@ class ScalaInterpreterSpec extends BaseInterpreterSpec {
   implicit val formats = DefaultFormats
 
   override def createInterpreter(): Interpreter =
-    new SparkInterpreter(new SparkConf(), new StatementProgressListener(new RSCConf()))
+    new SparkInterpreter(new SparkConf())
 
   it should "execute `1 + 2` == 3" in withInterpreter { interpreter =>
     val response = interpreter.execute("1 + 2")

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0ddcaf68/repl/src/test/scala/com/cloudera/livy/repl/SparkRInterpreterSpec.scala
----------------------------------------------------------------------
diff --git a/repl/src/test/scala/com/cloudera/livy/repl/SparkRInterpreterSpec.scala b/repl/src/test/scala/com/cloudera/livy/repl/SparkRInterpreterSpec.scala
index a513867..61f1a36 100644
--- a/repl/src/test/scala/com/cloudera/livy/repl/SparkRInterpreterSpec.scala
+++ b/repl/src/test/scala/com/cloudera/livy/repl/SparkRInterpreterSpec.scala
@@ -34,8 +34,7 @@ class SparkRInterpreterSpec extends BaseInterpreterSpec {
     super.withFixture(test)
   }
 
-  override def createInterpreter(): Interpreter =
-    SparkRInterpreter(new SparkConf(), new StatementProgressListener(new RSCConf()))
+  override def createInterpreter(): Interpreter = SparkRInterpreter(new SparkConf())
 
   it should "execute `1 + 2` == 3" in withInterpreter { interpreter =>
     val response = interpreter.execute("1 + 2")

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0ddcaf68/repl/src/test/scala/com/cloudera/livy/repl/SparkRSessionSpec.scala
----------------------------------------------------------------------
diff --git a/repl/src/test/scala/com/cloudera/livy/repl/SparkRSessionSpec.scala b/repl/src/test/scala/com/cloudera/livy/repl/SparkRSessionSpec.scala
index a6091d0..c604205 100644
--- a/repl/src/test/scala/com/cloudera/livy/repl/SparkRSessionSpec.scala
+++ b/repl/src/test/scala/com/cloudera/livy/repl/SparkRSessionSpec.scala
@@ -31,8 +31,7 @@ class SparkRSessionSpec extends BaseSessionSpec {
     super.withFixture(test)
   }
 
-  override def createInterpreter(): Interpreter =
-    SparkRInterpreter(new SparkConf(), new StatementProgressListener(new RSCConf()))
+  override def createInterpreter(): Interpreter = SparkRInterpreter(new SparkConf())
 
   it should "execute `1 + 2` == 3" in withSession { session =>
     val statement = execute(session)("1 + 2")

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0ddcaf68/repl/src/test/scala/com/cloudera/livy/repl/SparkSessionSpec.scala
----------------------------------------------------------------------
diff --git a/repl/src/test/scala/com/cloudera/livy/repl/SparkSessionSpec.scala b/repl/src/test/scala/com/cloudera/livy/repl/SparkSessionSpec.scala
index a051513..52b6b42 100644
--- a/repl/src/test/scala/com/cloudera/livy/repl/SparkSessionSpec.scala
+++ b/repl/src/test/scala/com/cloudera/livy/repl/SparkSessionSpec.scala
@@ -32,8 +32,7 @@ import com.cloudera.livy.rsc.driver.StatementState
 
 class SparkSessionSpec extends BaseSessionSpec {
 
-  override def createInterpreter(): Interpreter =
-    new SparkInterpreter(new SparkConf(), new StatementProgressListener(new RSCConf()))
+  override def createInterpreter(): Interpreter = new SparkInterpreter(new SparkConf())
 
   it should "execute `1 + 2` == 3" in withSession { session =>
     val statement = execute(session)("1 + 2")
@@ -240,4 +239,36 @@ class SparkSessionSpec extends BaseSessionSpec {
         "Job 0 cancelled part of cancelled job group 0")
     }
   }
+
+  it should "correctly calculate progress" in withSession { session =>
+    val executeCode =
+      """
+        |sc.parallelize(1 to 2, 2).map(i => (i, 1)).collect()
+      """.stripMargin
+
+    val stmtId = session.execute(executeCode)
+    eventually(timeout(30 seconds), interval(100 millis)) {
+      session.progressOfStatement(stmtId) should be(1.0)
+    }
+  }
+
+  it should "not generate Spark jobs for plain Scala code" in withSession { session =>
+    val executeCode = """1 + 1"""
+
+    val stmtId = session.execute(executeCode)
+    session.progressOfStatement(stmtId) should be (0.0)
+  }
+
+  it should "handle multiple jobs in one statement" in withSession { session =>
+    val executeCode =
+      """
+        |sc.parallelize(1 to 2, 2).map(i => (i, 1)).collect()
+        |sc.parallelize(1 to 2, 2).map(i => (i, 1)).collect()
+      """.stripMargin
+
+    val stmtId = session.execute(executeCode)
+    eventually(timeout(30 seconds), interval(100 millis)) {
+      session.progressOfStatement(stmtId) should be(1.0)
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/0ddcaf68/repl/src/test/scala/com/cloudera/livy/repl/StatementProgressListenerSpec.scala
----------------------------------------------------------------------
diff --git a/repl/src/test/scala/com/cloudera/livy/repl/StatementProgressListenerSpec.scala b/repl/src/test/scala/com/cloudera/livy/repl/StatementProgressListenerSpec.scala
deleted file mode 100644
index 2acee4c..0000000
--- a/repl/src/test/scala/com/cloudera/livy/repl/StatementProgressListenerSpec.scala
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * Licensed to Cloudera, Inc. under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  Cloudera, Inc. 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 com.cloudera.livy.repl
-
-import java.util.concurrent.atomic.AtomicInteger
-
-import scala.collection.mutable.ArrayBuffer
-import scala.concurrent.duration._
-import scala.language.{postfixOps, reflectiveCalls}
-
-import org.apache.spark.SparkConf
-import org.apache.spark.scheduler._
-import org.scalatest._
-import org.scalatest.concurrent.Eventually._
-
-import com.cloudera.livy.LivyBaseUnitTestSuite
-import com.cloudera.livy.rsc.RSCConf
-
-class StatementProgressListenerSpec extends FlatSpec
-    with Matchers
-    with BeforeAndAfterAll
-    with BeforeAndAfter
-    with LivyBaseUnitTestSuite {
-  private val rscConf = new RSCConf()
-    .set(RSCConf.Entry.RETAINED_STATEMENT_NUMBER, 2)
-
-  private val testListener = new StatementProgressListener(rscConf) {
-    var onJobStartedCallback: Option[() => Unit] = None
-    var onJobEndCallback: Option[() => Unit] = None
-    var onStageEndCallback: Option[() => Unit] = None
-    var onTaskEndCallback: Option[() => Unit] = None
-
-    override  def onJobStart(jobStart: SparkListenerJobStart): Unit = {
-      super.onJobStart(jobStart)
-      onJobStartedCallback.foreach(f => f())
-    }
-
-    override def onJobEnd(jobEnd: SparkListenerJobEnd): Unit = {
-      super.onJobEnd(jobEnd)
-      onJobEndCallback.foreach(f => f())
-    }
-
-    override def onStageCompleted(stageCompleted: SparkListenerStageCompleted): Unit = {
-      super.onStageCompleted(stageCompleted)
-      onStageEndCallback.foreach(f => f())
-    }
-
-    override def onTaskEnd(taskEnd: SparkListenerTaskEnd): Unit = {
-      super.onTaskEnd(taskEnd)
-      onTaskEndCallback.foreach(f => f())
-    }
-  }
-
-  private val statementId = new AtomicInteger(0)
-
-  private def getStatementId = statementId.getAndIncrement()
-
-  private var sparkInterpreter: SparkInterpreter = _
-
-  override def beforeAll(): Unit = {
-    super.beforeAll()
-    sparkInterpreter = new SparkInterpreter(new SparkConf(), testListener)
-    sparkInterpreter.start()
-  }
-
-  override def afterAll(): Unit = {
-    sparkInterpreter.close()
-    super.afterAll()
-  }
-
-  after {
-    testListener.onJobStartedCallback = None
-    testListener.onJobEndCallback = None
-    testListener.onStageEndCallback = None
-    testListener.onTaskEndCallback = None
-  }
-
-  it should "correctly calculate progress" in {
-    val executeCode =
-      """
-        |sc.parallelize(1 to 2, 2).map(i => (i, 1)).collect()
-      """.stripMargin
-    val stmtId = getStatementId
-
-    def verifyJobs(): Unit = {
-      testListener.statementToJobs.get(stmtId) should not be (None)
-
-      // One job will be submitted
-      testListener.statementToJobs(stmtId).size should be (1)
-      val jobId = testListener.statementToJobs(stmtId).head.jobId
-      testListener.jobIdToStatement(jobId) should be (stmtId)
-
-      // 1 stage will be generated
-      testListener.jobIdToStages(jobId).size should be (1)
-      val stageIds = testListener.jobIdToStages(jobId)
-
-      // 2 tasks per stage will be generated
-      stageIds.foreach { id =>
-        testListener.stageIdToTaskCount(id).currFinishedTasks should be (0)
-        testListener.stageIdToTaskCount(id).totalTasks should be (2)
-      }
-    }
-
-    var taskEndCalls = 0
-    def verifyTasks(): Unit = {
-      taskEndCalls += 1
-      testListener.progressOfStatement(stmtId) should be (taskEndCalls.toDouble / 2)
-    }
-
-    var stageEndCalls = 0
-    def verifyStages(): Unit = {
-      stageEndCalls += 1
-      testListener.progressOfStatement(stmtId) should be (stageEndCalls.toDouble / 1)
-    }
-
-    testListener.onJobStartedCallback = Some(verifyJobs)
-    testListener.onTaskEndCallback = Some(verifyTasks)
-    testListener.onStageEndCallback = Some(verifyStages)
-    sparkInterpreter.execute(stmtId, executeCode)
-
-    eventually(timeout(30 seconds), interval(100 millis)) {
-      testListener.progressOfStatement(stmtId) should be(1.0)
-    }
-  }
-
-  it should "not generate Spark jobs for plain Scala code" in {
-    val executeCode = """1 + 1"""
-    val stmtId = getStatementId
-
-    def verifyJobs(): Unit = {
-      fail("No job will be submitted")
-    }
-
-    testListener.onJobStartedCallback = Some(verifyJobs)
-    testListener.progressOfStatement(stmtId) should be (0.0)
-    sparkInterpreter.execute(stmtId, executeCode)
-    testListener.progressOfStatement(stmtId) should be (0.0)
-  }
-
-  it should "handle multiple jobs in one statement" in {
-    val executeCode =
-      """
-        |sc.parallelize(1 to 2, 2).map(i => (i, 1)).collect()
-        |sc.parallelize(1 to 2, 2).map(i => (i, 1)).collect()
-      """.stripMargin
-    val stmtId = getStatementId
-
-    var jobs = 0
-    def verifyJobs(): Unit = {
-      jobs += 1
-
-      testListener.statementToJobs.get(stmtId) should not be (None)
-      // One job will be submitted
-      testListener.statementToJobs(stmtId).size should be (jobs)
-      val jobId = testListener.statementToJobs(stmtId)(jobs - 1).jobId
-      testListener.jobIdToStatement(jobId) should be (stmtId)
-
-      // 1 stages will be generated
-      testListener.jobIdToStages(jobId).size should be (1)
-      val stageIds = testListener.jobIdToStages(jobId)
-
-      // 2 tasks per stage will be generated
-      stageIds.foreach { id =>
-        testListener.stageIdToTaskCount(id).currFinishedTasks should be (0)
-        testListener.stageIdToTaskCount(id).totalTasks should be (2)
-      }
-    }
-
-    val taskProgress = ArrayBuffer[Double]()
-    def verifyTasks(): Unit = {
-      taskProgress += testListener.progressOfStatement(stmtId)
-    }
-
-    val stageProgress = ArrayBuffer[Double]()
-    def verifyStages(): Unit = {
-      stageProgress += testListener.progressOfStatement(stmtId)
-    }
-
-    testListener.onJobStartedCallback = Some(verifyJobs)
-    testListener.onTaskEndCallback = Some(verifyTasks)
-    testListener.onStageEndCallback = Some(verifyStages)
-    sparkInterpreter.execute(stmtId, executeCode)
-
-    taskProgress.toArray should be (Array(0.5, 1.0, 0.75, 1.0))
-    stageProgress.toArray should be (Array(1.0, 1.0))
-
-    eventually(timeout(30 seconds), interval(100 millis)) {
-      testListener.progressOfStatement(stmtId) should be(1.0)
-    }
-  }
-
-  it should "remove old statement progress" in {
-    val executeCode =
-      """
-        |sc.parallelize(1 to 2, 2).map(i => (i, 1)).collect()
-      """.stripMargin
-    val stmtId = getStatementId
-
-    def onJobEnd(): Unit = {
-      testListener.statementToJobs(stmtId).size should be (1)
-      testListener.statementToJobs(stmtId).head.isCompleted should be (true)
-
-      testListener.statementToJobs.size should be (2)
-      testListener.statementToJobs.get(0) should be (None)
-      testListener.jobIdToStatement.filter(_._2 == 0) should be (Map.empty)
-    }
-
-    testListener.onJobEndCallback = Some(onJobEnd)
-    sparkInterpreter.execute(stmtId, executeCode)
-  }
-}



[34/50] [abbrv] incubator-livy git commit: LIVY-287. Add Deprecation to Livy Configurations and update naming. (#300)

Posted by js...@apache.org.
LIVY-287. Add Deprecation to Livy Configurations and update naming. (#300)

Updates to Livy configurations

- Added config deprecation with alternatives to ClientConf, HTTPConf, RSCConf, and LivyConf.
- Added framework for deprecation without alternatives when the need arises.
- Updated naming conventions in code and templates to use - instead of _ or camelCase and deprecated previous configs.
- Updated TestClientConf and added a new test.

Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/221aa9cf
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/221aa9cf
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/221aa9cf

Branch: refs/heads/master
Commit: 221aa9cf8f33b48fd9c792f67c61b78708bfae99
Parents: 0de0e28
Author: Alex Bozarth <aj...@us.ibm.com>
Authored: Wed Apr 5 15:56:48 2017 -0700
Committer: Alex Man <al...@users.noreply.github.com>
Committed: Wed Apr 5 15:56:48 2017 -0700

----------------------------------------------------------------------
 client-common/pom.xml                           |  5 ++
 .../cloudera/livy/client/common/ClientConf.java | 61 ++++++++++++-
 .../livy/client/common/TestClientConf.java      | 75 +++++++++++++++-
 .../com/cloudera/livy/client/http/HttpConf.java | 59 ++++++++++++-
 conf/livy-client.conf.template                  | 18 ++--
 conf/livy.conf.template                         | 10 +--
 conf/spark-blacklist.conf.template              |  2 +-
 .../livy/test/framework/MiniCluster.scala       |  4 +-
 .../livy/repl/SparkContextInitializer.scala     |  4 +-
 .../java/com/cloudera/livy/rsc/RSCConf.java     | 91 ++++++++++++++++----
 .../main/scala/com/cloudera/livy/LivyConf.scala | 65 +++++++++++---
 .../com/cloudera/livy/server/LivyServer.scala   |  2 +-
 .../server/interactive/InteractiveSession.scala |  2 +-
 13 files changed, 344 insertions(+), 54 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/221aa9cf/client-common/pom.xml
----------------------------------------------------------------------
diff --git a/client-common/pom.xml b/client-common/pom.xml
index 9cc713c..e41aaae 100644
--- a/client-common/pom.xml
+++ b/client-common/pom.xml
@@ -45,5 +45,10 @@
       <artifactId>jackson-databind</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+      <scope>provided</scope>
+    </dependency>
   </dependencies>
 </project>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/221aa9cf/client-common/src/main/java/com/cloudera/livy/client/common/ClientConf.java
----------------------------------------------------------------------
diff --git a/client-common/src/main/java/com/cloudera/livy/client/common/ClientConf.java b/client-common/src/main/java/com/cloudera/livy/client/common/ClientConf.java
index 59cce37..4eb7929 100644
--- a/client-common/src/main/java/com/cloudera/livy/client/common/ClientConf.java
+++ b/client-common/src/main/java/com/cloudera/livy/client/common/ClientConf.java
@@ -28,6 +28,9 @@ import java.util.concurrent.TimeUnit;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import com.cloudera.livy.annotations.Private;
 
 /**
@@ -37,6 +40,8 @@ import com.cloudera.livy.annotations.Private;
 public abstract class ClientConf<T extends ClientConf>
   implements Iterable<Map.Entry<String, String>> {
 
+  protected Logger LOG = LoggerFactory.getLogger(getClass());
+
   public static interface ConfEntry {
 
     /** The key in the configuration file. */
@@ -71,24 +76,37 @@ public abstract class ClientConf<T extends ClientConf>
     this.config = new ConcurrentHashMap<>();
     if (config != null) {
       for (String key : config.stringPropertyNames()) {
+        logDeprecationWarning(key);
         this.config.put(key, config.getProperty(key));
       }
     }
   }
 
   public String get(String key) {
-    return config.get(key);
+    String val = config.get(key);
+    if (val != null) {
+      return val;
+    }
+    DeprecatedConf depConf = getConfigsWithAlternatives().get(key);
+    if (depConf != null) {
+      return config.get(depConf.key());
+    } else {
+      return val;
+    }
   }
 
   @SuppressWarnings("unchecked")
   public T set(String key, String value) {
+    logDeprecationWarning(key);
     config.put(key, value);
     return (T) this;
   }
 
   @SuppressWarnings("unchecked")
   public T setIfMissing(String key, String value) {
-    config.putIfAbsent(key, value);
+    if (config.putIfAbsent(key, value) == null) {
+      logDeprecationWarning(key);
+    }
     return (T) this;
   }
 
@@ -163,6 +181,7 @@ public abstract class ClientConf<T extends ClientConf>
     if (value == null) {
       config.remove(e.key());
     } else {
+      logDeprecationWarning(e.key());
       config.put(e.key(), value.toString());
     }
     return (T) this;
@@ -176,7 +195,7 @@ public abstract class ClientConf<T extends ClientConf>
   private String get(ConfEntry e, Class<?> requestedType) {
     check(getType(e.dflt()).equals(requestedType), "Invalid type conversion requested for %s.",
       e.key());
-    return config.get(e.key());
+    return this.get(e.key());
   }
 
   private boolean typesMatch(Object test, Object expected) {
@@ -193,4 +212,40 @@ public abstract class ClientConf<T extends ClientConf>
     }
   }
 
+  /** Logs a warning message if the given config key is deprecated. */
+  private void logDeprecationWarning(String key) {
+    DeprecatedConf altConfs = getConfigsWithAlternatives().get(key);
+    if (altConfs != null) {
+      LOG.warn("The configuration key " + altConfs.key() + " has been deprecated as of Livy "
+        + altConfs.version() + " and may be removed in the future. Please use the new key "
+        + key + " instead.");
+      return;
+    }
+
+    DeprecatedConf depConfs = getDeprecatedConfigs().get(key);
+    if (depConfs != null) {
+      LOG.warn("The configuration key " + depConfs.key() + " has been deprecated as of Livy "
+        + depConfs.version() + " and may be removed in the future. "
+        + depConfs.deprecationMessage());
+    }
+  }
+
+  /** Maps valid key to DeprecatedConf with the deprecated key. */
+  protected abstract Map<String, DeprecatedConf> getConfigsWithAlternatives();
+
+  /** Maps deprecated key to DeprecatedConf with the same key. */
+  protected abstract Map<String, DeprecatedConf> getDeprecatedConfigs();
+
+  public static interface DeprecatedConf {
+
+    /** The key in the configuration file. */
+    String key();
+
+    /** The Livy version in which the key was deprecated. */
+    String version();
+
+    /** Message to include in the deprecation warning for configs without alternatives */
+    String deprecationMessage();
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/221aa9cf/client-common/src/test/java/com/cloudera/livy/client/common/TestClientConf.java
----------------------------------------------------------------------
diff --git a/client-common/src/test/java/com/cloudera/livy/client/common/TestClientConf.java b/client-common/src/test/java/com/cloudera/livy/client/common/TestClientConf.java
index c8bd9c9..afb7798 100644
--- a/client-common/src/test/java/com/cloudera/livy/client/common/TestClientConf.java
+++ b/client-common/src/test/java/com/cloudera/livy/client/common/TestClientConf.java
@@ -18,6 +18,8 @@
 
 package com.cloudera.livy.client.common;
 
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.Map;
 import java.util.Properties;
 
@@ -122,6 +124,31 @@ public class TestClientConf {
     conf.getTimeAsMs(TestConf.Entry.TIME_NO_DEFAULT);
   }
 
+
+  @Test
+  public void testDeprecation() {
+    TestConf conf = new TestConf(null);
+
+    assertNull(conf.get("depKey"));
+    assertNull(conf.get("dep_alt"));
+    assertNull(conf.get("new-key"));
+    assertEquals("value", conf.get(TestConf.Entry.NEW_CONF));
+
+    TestConf depProps = new TestConf(null);
+    depProps.set("depKey", "dep-val");
+    depProps.set("dep_alt", "alt-val");
+    conf.setAll(depProps);
+    assertEquals("dep-val", conf.get("depKey"));
+    assertEquals("alt-val", conf.get("dep_alt"));
+    assertEquals("alt-val", conf.get(TestConf.Entry.NEW_CONF));
+    assertEquals("alt-val", conf.get("new-key"));
+
+    conf.set("new-key", "new-val");
+    assertEquals("new-val", conf.get(TestConf.Entry.NEW_CONF));
+    assertEquals("alt-val", conf.get("dep_alt"));
+    assertEquals("new-val", conf.get("new-key"));
+  }
+
   private static class TestConf extends ClientConf<TestConf> {
 
     static enum Entry implements ConfEntry {
@@ -131,7 +158,8 @@ public class TestClientConf {
       INT("int", 42),
       LONG("long", 84L),
       TIME("time", "168ms"),
-      TIME_NO_DEFAULT("time2", null);
+      TIME_NO_DEFAULT("time2", null),
+      NEW_CONF("new-key", "value");
 
       private final String key;
       private final Object dflt;
@@ -153,6 +181,51 @@ public class TestClientConf {
       super(p);
     }
 
+    private static final Map<String, DeprecatedConf> configsWithAlternatives
+      = Collections.unmodifiableMap(new HashMap<String, DeprecatedConf>() {{
+      put(TestConf.Entry.NEW_CONF.key, DepConf.DEP_WITH_ALT);
+    }});
+
+    private static final Map<String, DeprecatedConf> deprecatedConfigs
+      = Collections.unmodifiableMap(new HashMap<String, DeprecatedConf>() {{
+      put(DepConf.DEP_NO_ALT.key, DepConf.DEP_NO_ALT);
+    }});
+
+    protected Map<String, DeprecatedConf> getConfigsWithAlternatives() {
+      return configsWithAlternatives;
+    }
+
+    protected Map<String, DeprecatedConf> getDeprecatedConfigs() {
+      return deprecatedConfigs;
+    }
+
+    static enum DepConf implements DeprecatedConf {
+      DEP_WITH_ALT("dep_alt", "0.4"),
+      DEP_NO_ALT("depKey", "1.0");
+
+      private final String key;
+      private final String version;
+      private final String deprecationMessage;
+
+      private DepConf(String key, String version) {
+        this(key, version, "");
+      }
+
+      private DepConf(String key, String version, String deprecationMessage) {
+        this.key = key;
+        this.version = version;
+        this.deprecationMessage = deprecationMessage;
+      }
+
+      @Override
+      public String key() { return key; }
+
+      @Override
+      public String version() { return version; }
+
+      @Override
+      public String deprecationMessage() { return deprecationMessage; }
+    }
   }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/221aa9cf/client-http/src/main/java/com/cloudera/livy/client/http/HttpConf.java
----------------------------------------------------------------------
diff --git a/client-http/src/main/java/com/cloudera/livy/client/http/HttpConf.java b/client-http/src/main/java/com/cloudera/livy/client/http/HttpConf.java
index 24c191c..2ae25e5 100644
--- a/client-http/src/main/java/com/cloudera/livy/client/http/HttpConf.java
+++ b/client-http/src/main/java/com/cloudera/livy/client/http/HttpConf.java
@@ -18,19 +18,24 @@
 
 package com.cloudera.livy.client.http;
 
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.Properties;
 
 import com.cloudera.livy.client.common.ClientConf;
 
 class HttpConf extends ClientConf<HttpConf> {
 
+  private static final String HTTP_CONF_PREFIX = "livy.client.http.";
+
   static enum Entry implements ConfEntry {
     CONNECTION_TIMEOUT("connection.timeout", "10s"),
     CONNECTION_IDLE_TIMEOUT("connection.idle.timeout", "10m"),
     SOCKET_TIMEOUT("connection.socket.timeout", "5m"),
 
-    JOB_INITIAL_POLL_INTERVAL("job.initial_poll_interval", "100ms"),
-    JOB_MAX_POLL_INTERVAL("job.max_poll_interval", "5s"),
+    JOB_INITIAL_POLL_INTERVAL("job.initial-poll-interval", "100ms"),
+    JOB_MAX_POLL_INTERVAL("job.max-poll-interval", "5s"),
 
     CONTENT_COMPRESS_ENABLE("content.compress.enable", true),
 
@@ -44,7 +49,7 @@ class HttpConf extends ClientConf<HttpConf> {
     private final Object dflt;
 
     private Entry(String key, Object dflt) {
-      this.key = "livy.client.http." + key;
+      this.key = HTTP_CONF_PREFIX + key;
       this.dflt = dflt;
     }
 
@@ -80,4 +85,52 @@ class HttpConf extends ClientConf<HttpConf> {
   boolean isSpnegoEnabled() {
     return getBoolean(Entry.SPNEGO_ENABLED);
   }
+
+  private static final Map<String, DeprecatedConf> configsWithAlternatives
+    = Collections.unmodifiableMap(new HashMap<String, DeprecatedConf>() {{
+      put(HttpConf.Entry.JOB_INITIAL_POLL_INTERVAL.key, DepConf.JOB_INITIAL_POLL_INTERVAL);
+      put(HttpConf.Entry.JOB_MAX_POLL_INTERVAL.key, DepConf.JOB_MAX_POLL_INTERVAL);
+  }});
+
+  // Maps deprecated key to DeprecatedConf with the same key.
+  // There are no deprecated configs without alternatives currently.
+  private static final Map<String, DeprecatedConf> deprecatedConfigs
+    = Collections.unmodifiableMap(new HashMap<String, DeprecatedConf>());
+
+  protected Map<String, DeprecatedConf> getConfigsWithAlternatives() {
+    return configsWithAlternatives;
+  }
+
+  protected Map<String, DeprecatedConf> getDeprecatedConfigs() {
+    return deprecatedConfigs;
+  }
+
+  static enum DepConf implements DeprecatedConf {
+    JOB_INITIAL_POLL_INTERVAL("job.initial_poll_interval", "0.4"),
+    JOB_MAX_POLL_INTERVAL("job.max_poll_interval", "0.4");
+
+    private final String key;
+    private final String version;
+    private final String deprecationMessage;
+
+    private DepConf(String key, String version) {
+      this(key, version, "");
+    }
+
+    private DepConf(String key, String version, String deprecationMessage) {
+      this.key = HTTP_CONF_PREFIX + key;
+      this.version = version;
+      this.deprecationMessage = deprecationMessage;
+    }
+
+    @Override
+    public String key() { return key; }
+
+    @Override
+    public String version() { return version; }
+
+    @Override
+    public String deprecationMessage() { return deprecationMessage; }
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/221aa9cf/conf/livy-client.conf.template
----------------------------------------------------------------------
diff --git a/conf/livy-client.conf.template b/conf/livy-client.conf.template
index c0adb30..2a92b57 100644
--- a/conf/livy-client.conf.template
+++ b/conf/livy-client.conf.template
@@ -22,9 +22,9 @@
 # livy.client.http.connection.idle.timeout = 10m
 
 # Initial interval before polling for Job results
-# livy.client.http.job.initial_poll_interval = 100ms
+# livy.client.http.job.initial-poll-interval = 100ms
 # Maximum interval between successive polls
-# livy.client.http.job.max_poll_interval = 5s
+# livy.client.http.job.max-poll-interval = 5s
 
 #
 # Configurations for Livy RSCClient
@@ -37,10 +37,10 @@
 # livy.rsc.client.auth.secret =
 
 # Timeout when stopping a rsc client
-# livy.rsc.client.shutdown_timeout = 10s
+# livy.rsc.client.shutdown-timeout = 10s
 
 # Class of the rsc driver to use
-# livy.rsc.driver_class =
+# livy.rsc.driver-class =
 # The kind of rsc session. Examples: pyspark or sparkr
 # livy.rsc.session.kind =
 
@@ -58,10 +58,10 @@
 # livy.rsc.launcher.port = -1
 
 # How long will the RSC wait for a connection for a Livy server before shutting itself down.
-# livy.rsc.server.idle_timeout = 10m
+# livy.rsc.server.idle-timeout = 10m
 
 # The user that should be impersonated when requesting a Livy session
-# livy.rsc.proxy_user =
+# livy.rsc.proxy-user =
 
 # Host or IP adress of the rpc server
 # livy.rsc.rpc.server.address =
@@ -78,9 +78,9 @@
 # livy.rsc.rpc.sasl.qop =
 
 # Time between status checks for cancelled a Job
-# livy.rsc.job_cancel.trigger_interval = 100ms
+# livy.rsc.job-cancel.trigger-interval = 100ms
 # Time before a cancelled a Job is forced into a Cancelled state
-# livy.rsc.job_cancel.timeout = 30s
+# livy.rsc.job-cancel.timeout = 30s
 
 # Number of statements kept in driver's memory
-# livy.rsc.retained_statements = 100
\ No newline at end of file
+# livy.rsc.retained-statements = 100
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/221aa9cf/conf/livy.conf.template
----------------------------------------------------------------------
diff --git a/conf/livy.conf.template b/conf/livy.conf.template
index 8c5fe03..dd2f054 100644
--- a/conf/livy.conf.template
+++ b/conf/livy.conf.template
@@ -17,7 +17,7 @@
 # livy.spark.master = local
 
 # What spark deploy mode Livy sessions should use.
-# livy.spark.deployMode =
+# livy.spark.deploy-mode =
 
 # Enabled to check whether timeout Livy sessions should be stopped.
 # livy.server.session.timeout-check = true
@@ -58,11 +58,11 @@
 
 # Whether to enable csrf protection, by default it is false. If it is enabled, client should add
 # http-header "X-Requested-By" in request if the http method is POST/DELETE/PUT/PATCH.
-# livy.server.csrf_protection.enabled =
+# livy.server.csrf-protection.enabled =
 
 # Whether to enable HiveContext in livy interpreter, if it is true hive-site.xml will be detected
 # on user request and then livy server classpath automatically.
-# livy.repl.enableHiveContext =
+# livy.repl.enable-hive-context =
 
 # Recovery mode of Livy. Possible values:
 # off: Default. Turn off recovery. Every time Livy shuts down, it stops and forgets all sessions.
@@ -88,9 +88,9 @@
 # When the cluster is busy, we may fail to launch yarn app in app-lookup-timeout, then it would
 # cause session leakage, so we need to check session leakage.
 # How long to check livy session leakage
-# livy.server.yarn.app-leakage.check_timeout = 600s
+# livy.server.yarn.app-leakage.check-timeout = 600s
 # how often to check livy session leakage
-# livy.server.yarn.app-leakage.check_interval = 60s
+# livy.server.yarn.app-leakage.check-interval = 60s
 
 # How often Livy polls YARN to refresh YARN app state.
 # livy.server.yarn.poll-interval = 1s

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/221aa9cf/conf/spark-blacklist.conf.template
----------------------------------------------------------------------
diff --git a/conf/spark-blacklist.conf.template b/conf/spark-blacklist.conf.template
index f0919b0..b9f0ec2 100644
--- a/conf/spark-blacklist.conf.template
+++ b/conf/spark-blacklist.conf.template
@@ -16,4 +16,4 @@ spark.yarn.jars
 spark.yarn.archive
 
 # Don't allow users to override the RSC timeout.
-livy.rsc.server.idle_timeout
+livy.rsc.server.idle-timeout

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/221aa9cf/integration-test/src/main/scala/com/cloudera/livy/test/framework/MiniCluster.scala
----------------------------------------------------------------------
diff --git a/integration-test/src/main/scala/com/cloudera/livy/test/framework/MiniCluster.scala b/integration-test/src/main/scala/com/cloudera/livy/test/framework/MiniCluster.scala
index d520269..6aa02f1 100644
--- a/integration-test/src/main/scala/com/cloudera/livy/test/framework/MiniCluster.scala
+++ b/integration-test/src/main/scala/com/cloudera/livy/test/framework/MiniCluster.scala
@@ -176,7 +176,7 @@ object MiniLivyMain extends MiniClusterBase {
     // server. Do it atomically since it's used by MiniCluster to detect when the Livy server
     // is up and ready.
     eventually(timeout(30 seconds), interval(1 second)) {
-      val serverUrlConf = Map("livy.server.serverUrl" -> server.serverUrl())
+      val serverUrlConf = Map("livy.server.server-url" -> server.serverUrl())
       saveProperties(serverUrlConf, new File(configPath + "/serverUrl.conf"))
     }
   }
@@ -297,7 +297,7 @@ class MiniCluster(config: Map[String, String]) extends Cluster with MiniClusterU
     val localLivy = start(MiniLivyMain.getClass, confFile, extraJavaArgs = jacocoArgs)
 
     val props = loadProperties(confFile)
-    livyUrl = props("livy.server.serverUrl")
+    livyUrl = props("livy.server.server-url")
 
     // Wait until Livy server responds.
     val httpClient = new AsyncHttpClient()

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/221aa9cf/repl/src/main/scala/com/cloudera/livy/repl/SparkContextInitializer.scala
----------------------------------------------------------------------
diff --git a/repl/src/main/scala/com/cloudera/livy/repl/SparkContextInitializer.scala b/repl/src/main/scala/com/cloudera/livy/repl/SparkContextInitializer.scala
index fd082eb..533741d 100644
--- a/repl/src/main/scala/com/cloudera/livy/repl/SparkContextInitializer.scala
+++ b/repl/src/main/scala/com/cloudera/livy/repl/SparkContextInitializer.scala
@@ -46,7 +46,7 @@ trait SparkContextInitializer extends Logging {
         val loader = Option(Thread.currentThread().getContextClassLoader)
           .getOrElse(getClass.getClassLoader)
         if (loader.getResource("hive-site.xml") == null) {
-          warn("livy.repl.enableHiveContext is true but no hive-site.xml found on classpath.")
+          warn("livy.repl.enable-hive-context is true but no hive-site.xml found on classpath.")
         }
 
         sqlContext = Class.forName("org.apache.spark.sql.hive.HiveContext")
@@ -87,7 +87,7 @@ trait SparkContextInitializer extends Logging {
         val loader = Option(Thread.currentThread().getContextClassLoader)
           .getOrElse(getClass.getClassLoader)
         if (loader.getResource("hive-site.xml") == null) {
-          warn("livy.repl.enableHiveContext is true but no hive-site.xml found on classpath.")
+          warn("livy.repl.enable-hive-context is true but no hive-site.xml found on classpath.")
         }
 
         builder.getClass.getMethod("enableHiveSupport").invoke(builder)

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/221aa9cf/rsc/src/main/java/com/cloudera/livy/rsc/RSCConf.java
----------------------------------------------------------------------
diff --git a/rsc/src/main/java/com/cloudera/livy/rsc/RSCConf.java b/rsc/src/main/java/com/cloudera/livy/rsc/RSCConf.java
index 0d7b1c1..d1b8b39 100644
--- a/rsc/src/main/java/com/cloudera/livy/rsc/RSCConf.java
+++ b/rsc/src/main/java/com/cloudera/livy/rsc/RSCConf.java
@@ -21,15 +21,13 @@ import java.io.IOException;
 import java.net.Inet4Address;
 import java.net.InetAddress;
 import java.net.NetworkInterface;
+import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Properties;
 import javax.security.sasl.Sasl;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import com.cloudera.livy.client.common.ClientConf;
 
 public class RSCConf extends ClientConf<RSCConf> {
@@ -37,14 +35,14 @@ public class RSCConf extends ClientConf<RSCConf> {
   public static final String SPARK_CONF_PREFIX = "spark.";
   public static final String LIVY_SPARK_PREFIX = SPARK_CONF_PREFIX + "__livy__.";
 
-  private static final Logger LOG = LoggerFactory.getLogger(RSCConf.class);
+  private static final String RSC_CONF_PREFIX = "livy.rsc.";
 
   public static enum Entry implements ConfEntry {
     CLIENT_ID("client.auth.id", null),
     CLIENT_SECRET("client.auth.secret", null),
-    CLIENT_IN_PROCESS("client.do_not_use.run_driver_in_process", false),
-    CLIENT_SHUTDOWN_TIMEOUT("client.shutdown_timeout", "10s"),
-    DRIVER_CLASS("driver_class", null),
+    CLIENT_IN_PROCESS("client.do-not-use.run-driver-in-process", false),
+    CLIENT_SHUTDOWN_TIMEOUT("client.shutdown-timeout", "10s"),
+    DRIVER_CLASS("driver-class", null),
     SESSION_KIND("session.kind", null),
 
     LIVY_JARS("jars", null),
@@ -56,9 +54,9 @@ public class RSCConf extends ClientConf<RSCConf> {
     LAUNCHER_PORT("launcher.port", -1),
 
     // How long will the RSC wait for a connection for a Livy server before shutting itself down.
-    SERVER_IDLE_TIMEOUT("server.idle_timeout", "10m"),
+    SERVER_IDLE_TIMEOUT("server.idle-timeout", "10m"),
 
-    PROXY_USER("proxy_user", null),
+    PROXY_USER("proxy-user", null),
 
     RPC_SERVER_ADDRESS("rpc.server.address", null),
     RPC_CLIENT_HANDSHAKE_TIMEOUT("server.connect.timeout", "90s"),
@@ -71,19 +69,19 @@ public class RSCConf extends ClientConf<RSCConf> {
     SASL_MECHANISMS("rpc.sasl.mechanisms", "DIGEST-MD5"),
     SASL_QOP("rpc.sasl.qop", null),
 
-    TEST_STUCK_END_SESSION("test.do_not_use.stuck_end_session", false),
-    TEST_STUCK_START_DRIVER("test.do_not_use.stuck_start_driver", false),
+    TEST_STUCK_END_SESSION("test.do-not-use.stuck-end-session", false),
+    TEST_STUCK_START_DRIVER("test.do-not-use.stuck-start-driver", false),
 
-    JOB_CANCEL_TRIGGER_INTERVAL("job_cancel.trigger_interval", "100ms"),
-    JOB_CANCEL_TIMEOUT("job_cancel.timeout", "30s"),
+    JOB_CANCEL_TRIGGER_INTERVAL("job-cancel.trigger-interval", "100ms"),
+    JOB_CANCEL_TIMEOUT("job-cancel.timeout", "30s"),
 
-    RETAINED_STATEMENT_NUMBER("retained_statements", 100);
+    RETAINED_STATEMENT_NUMBER("retained-statements", 100);
 
     private final String key;
     private final Object dflt;
 
     private Entry(String key, Object dflt) {
-      this.key = "livy.rsc." + key;
+      this.key = RSC_CONF_PREFIX + key;
       this.dflt = dflt;
     }
 
@@ -146,4 +144,67 @@ public class RSCConf extends ClientConf<RSCConf> {
     return address.getCanonicalHostName();
   }
 
+  private static final Map<String, DeprecatedConf> configsWithAlternatives
+    = Collections.unmodifiableMap(new HashMap<String, DeprecatedConf>() {{
+      put(RSCConf.Entry.CLIENT_IN_PROCESS.key, DepConf.CLIENT_IN_PROCESS);
+      put(RSCConf.Entry.CLIENT_SHUTDOWN_TIMEOUT.key, DepConf.CLIENT_SHUTDOWN_TIMEOUT);
+      put(RSCConf.Entry.DRIVER_CLASS.key, DepConf.DRIVER_CLASS);
+      put(RSCConf.Entry.SERVER_IDLE_TIMEOUT.key, DepConf.SERVER_IDLE_TIMEOUT);
+      put(RSCConf.Entry.PROXY_USER.key, DepConf.PROXY_USER);
+      put(RSCConf.Entry.TEST_STUCK_END_SESSION.key, DepConf.TEST_STUCK_END_SESSION);
+      put(RSCConf.Entry.TEST_STUCK_START_DRIVER.key, DepConf.TEST_STUCK_START_DRIVER);
+      put(RSCConf.Entry.JOB_CANCEL_TRIGGER_INTERVAL.key, DepConf.JOB_CANCEL_TRIGGER_INTERVAL);
+      put(RSCConf.Entry.JOB_CANCEL_TIMEOUT.key, DepConf.JOB_CANCEL_TIMEOUT);
+      put(RSCConf.Entry.RETAINED_STATEMENT_NUMBER.key, DepConf.RETAINED_STATEMENT_NUMBER);
+  }});
+
+  // Maps deprecated key to DeprecatedConf with the same key.
+  // There are no deprecated configs without alternatives currently.
+  private static final Map<String, DeprecatedConf> deprecatedConfigs
+    = Collections.unmodifiableMap(new HashMap<String, DeprecatedConf>());
+
+  protected Map<String, DeprecatedConf> getConfigsWithAlternatives() {
+    return configsWithAlternatives;
+  }
+
+  protected Map<String, DeprecatedConf> getDeprecatedConfigs() {
+    return deprecatedConfigs;
+  }
+
+  static enum DepConf implements DeprecatedConf {
+    CLIENT_IN_PROCESS("client.do_not_use.run_driver_in_process", "0.4"),
+    CLIENT_SHUTDOWN_TIMEOUT("client.shutdown_timeout", "0.4"),
+    DRIVER_CLASS("driver_class", "0.4"),
+    SERVER_IDLE_TIMEOUT("server.idle_timeout", "0.4"),
+    PROXY_USER("proxy_user", "0.4"),
+    TEST_STUCK_END_SESSION("test.do_not_use.stuck_end_session", "0.4"),
+    TEST_STUCK_START_DRIVER("test.do_not_use.stuck_start_driver", "0.4"),
+    JOB_CANCEL_TRIGGER_INTERVAL("job_cancel.trigger_interval", "0.4"),
+    JOB_CANCEL_TIMEOUT("job_cancel.timeout", "0.4"),
+    RETAINED_STATEMENT_NUMBER("retained_statements", "0.4");
+
+    private final String key;
+    private final String version;
+    private final String deprecationMessage;
+
+    private DepConf(String key, String version) {
+      this(key, version, "");
+    }
+
+    private DepConf(String key, String version, String deprecationMessage) {
+      this.key = RSC_CONF_PREFIX + key;
+      this.version = version;
+      this.deprecationMessage = deprecationMessage;
+    }
+
+    @Override
+    public String key() { return key; }
+
+    @Override
+    public String version() { return version; }
+
+    @Override
+    public String deprecationMessage() { return deprecationMessage; }
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/221aa9cf/server/src/main/scala/com/cloudera/livy/LivyConf.scala
----------------------------------------------------------------------
diff --git a/server/src/main/scala/com/cloudera/livy/LivyConf.scala b/server/src/main/scala/com/cloudera/livy/LivyConf.scala
index 1db1b8f..8fc4777 100644
--- a/server/src/main/scala/com/cloudera/livy/LivyConf.scala
+++ b/server/src/main/scala/com/cloudera/livy/LivyConf.scala
@@ -20,11 +20,15 @@ package com.cloudera.livy
 
 import java.io.File
 import java.lang.{Boolean => JBoolean, Long => JLong}
+import java.util.{Map => JMap}
+
+import scala.collection.JavaConverters._
 
 import org.apache.hadoop.conf.Configuration
 
 import com.cloudera.livy.client.common.ClientConf
 import com.cloudera.livy.client.common.ClientConf.ConfEntry
+import com.cloudera.livy.client.common.ClientConf.DeprecatedConf
 
 object LivyConf {
 
@@ -40,31 +44,31 @@ object LivyConf {
 
   val SPARK_HOME = Entry("livy.server.spark-home", null)
   val LIVY_SPARK_MASTER = Entry("livy.spark.master", "local")
-  val LIVY_SPARK_DEPLOY_MODE = Entry("livy.spark.deployMode", null)
+  val LIVY_SPARK_DEPLOY_MODE = Entry("livy.spark.deploy-mode", null)
 
   // Two configurations to specify Spark and related Scala version. These are internal
   // configurations will be set by LivyServer and used in session creation. It is not required to
   // set usually unless running with unofficial Spark + Scala versions
   // (like Spark 2.0 + Scala 2.10, Spark 1.6 + Scala 2.11)
-  val LIVY_SPARK_SCALA_VERSION = Entry("livy.spark.scalaVersion", null)
+  val LIVY_SPARK_SCALA_VERSION = Entry("livy.spark.scala-version", null)
   val LIVY_SPARK_VERSION = Entry("livy.spark.version", null)
 
   val SESSION_STAGING_DIR = Entry("livy.session.staging-dir", null)
   val FILE_UPLOAD_MAX_SIZE = Entry("livy.file.upload.max.size", 100L * 1024 * 1024)
   val LOCAL_FS_WHITELIST = Entry("livy.file.local-dir-whitelist", null)
-  val ENABLE_HIVE_CONTEXT = Entry("livy.repl.enableHiveContext", false)
+  val ENABLE_HIVE_CONTEXT = Entry("livy.repl.enable-hive-context", false)
 
   val ENVIRONMENT = Entry("livy.environment", "production")
 
   val SERVER_HOST = Entry("livy.server.host", "0.0.0.0")
   val SERVER_PORT = Entry("livy.server.port", 8998)
-  val CSRF_PROTECTION = LivyConf.Entry("livy.server.csrf_protection.enabled", false)
+  val CSRF_PROTECTION = LivyConf.Entry("livy.server.csrf-protection.enabled", false)
 
   val IMPERSONATION_ENABLED = Entry("livy.impersonation.enabled", false)
   val SUPERUSERS = Entry("livy.superusers", null)
 
-  val ACCESS_CONTROL_ENABLED = Entry("livy.server.access_control.enabled", false)
-  val ACCESS_CONTROL_USERS = Entry("livy.server.access_control.users", null)
+  val ACCESS_CONTROL_ENABLED = Entry("livy.server.access-control.enabled", false)
+  val ACCESS_CONTROL_USERS = Entry("livy.server.access-control.users", null)
 
   val SSL_KEYSTORE = Entry("livy.keystore", null)
   val SSL_KEYSTORE_PASSWORD = Entry("livy.keystore.password", null)
@@ -73,7 +77,7 @@ object LivyConf {
   val AUTH_TYPE = Entry("livy.server.auth.type", null)
   val AUTH_KERBEROS_PRINCIPAL = Entry("livy.server.auth.kerberos.principal", null)
   val AUTH_KERBEROS_KEYTAB = Entry("livy.server.auth.kerberos.keytab", null)
-  val AUTH_KERBEROS_NAME_RULES = Entry("livy.server.auth.kerberos.name_rules", "DEFAULT")
+  val AUTH_KERBEROS_NAME_RULES = Entry("livy.server.auth.kerberos.name-rules", "DEFAULT")
 
   val HEARTBEAT_WATCHDOG_INTERVAL = Entry("livy.server.heartbeat-watchdog.interval", "1m")
 
@@ -82,9 +86,9 @@ object LivyConf {
   val LAUNCH_KERBEROS_KEYTAB =
     LivyConf.Entry("livy.server.launch.kerberos.keytab", null)
   val LAUNCH_KERBEROS_REFRESH_INTERVAL =
-    LivyConf.Entry("livy.server.launch.kerberos.refresh_interval", "1h")
+    LivyConf.Entry("livy.server.launch.kerberos.refresh-interval", "1h")
   val KINIT_FAIL_THRESHOLD =
-    LivyConf.Entry("livy.server.launch.kerberos.kinit_fail_threshold", 5)
+    LivyConf.Entry("livy.server.launch.kerberos.kinit-fail-threshold", 5)
 
   /**
    * Recovery mode of Livy. Possible values:
@@ -124,9 +128,9 @@ object LivyConf {
   val RSC_JARS = Entry("livy.rsc.jars", null)
 
   // How long to check livy session leakage
-  val YARN_APP_LEAKAGE_CHECK_TIMEOUT = Entry("livy.server.yarn.app-leakage.check_timeout", "600s")
+  val YARN_APP_LEAKAGE_CHECK_TIMEOUT = Entry("livy.server.yarn.app-leakage.check-timeout", "600s")
   // how often to check livy session leakage
-  val YARN_APP_LEAKAGE_CHECK_INTERVAL = Entry("livy.server.yarn.app-leakage.check_interval", "60s")
+  val YARN_APP_LEAKAGE_CHECK_INTERVAL = Entry("livy.server.yarn.app-leakage.check-interval", "60s")
 
   // Whether session timeout should be checked, by default it will be checked, which means inactive
   // session will be stopped after "livy.server.session.timeout"
@@ -166,6 +170,37 @@ object LivyConf {
     "spark.yarn.jars"
   )
 
+  case class DepConf(
+      override val key: String,
+      override val version: String,
+      override val deprecationMessage: String = "")
+    extends DeprecatedConf
+
+  private val configsWithAlternatives: Map[String, DeprecatedConf] = Map[String, DepConf](
+    LIVY_SPARK_DEPLOY_MODE.key -> DepConf("livy.spark.deployMode", "0.4"),
+    LIVY_SPARK_SCALA_VERSION.key -> DepConf("livy.spark.scalaVersion", "0.4"),
+    ENABLE_HIVE_CONTEXT.key -> DepConf("livy.repl.enableHiveContext", "0.4"),
+    CSRF_PROTECTION.key -> DepConf("livy.server.csrf_protection.enabled", "0.4"),
+    ACCESS_CONTROL_ENABLED.key -> DepConf("livy.server.access_control.enabled", "0.4"),
+    ACCESS_CONTROL_USERS.key -> DepConf("livy.server.access_control.users", "0.4"),
+    AUTH_KERBEROS_NAME_RULES.key -> DepConf("livy.server.auth.kerberos.name_rules", "0.4"),
+    LAUNCH_KERBEROS_REFRESH_INTERVAL.key ->
+      DepConf("livy.server.launch.kerberos.refresh_interval", "0.4"),
+    KINIT_FAIL_THRESHOLD.key -> DepConf("livy.server.launch.kerberos.kinit_fail_threshold", "0.4"),
+    YARN_APP_LEAKAGE_CHECK_TIMEOUT.key ->
+      DepConf("livy.server.yarn.app-leakage.check_timeout", "0.4"),
+    YARN_APP_LEAKAGE_CHECK_INTERVAL.key ->
+      DepConf("livy.server.yarn.app-leakage.check_interval", "0.4")
+  )
+
+  private val deprecatedConfigs: Map[String, DeprecatedConf] = {
+    val configs: Seq[DepConf] = Seq(
+      // There are no deprecated configs without alternatives currently.
+    )
+
+    Map(configs.map { cfg => (cfg.key -> cfg) }: _*)
+  }
+
 }
 
 /**
@@ -250,4 +285,12 @@ class LivyConf(loadDefaults: Boolean) extends ClientConf[LivyConf](null) {
     Option(get(entry)).map(_.split("[, ]+").toSeq).getOrElse(Nil)
   }
 
+  override def getConfigsWithAlternatives: JMap[String, DeprecatedConf] = {
+    configsWithAlternatives.asJava
+  }
+
+  override def getDeprecatedConfigs: JMap[String, DeprecatedConf] = {
+    deprecatedConfigs.asJava
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/221aa9cf/server/src/main/scala/com/cloudera/livy/server/LivyServer.scala
----------------------------------------------------------------------
diff --git a/server/src/main/scala/com/cloudera/livy/server/LivyServer.scala b/server/src/main/scala/com/cloudera/livy/server/LivyServer.scala
index 0499d48..4bd5635 100644
--- a/server/src/main/scala/com/cloudera/livy/server/LivyServer.scala
+++ b/server/src/main/scala/com/cloudera/livy/server/LivyServer.scala
@@ -232,7 +232,7 @@ class LivyServer extends Logging {
     })
 
     _serverUrl = Some(s"${server.protocol}://${server.host}:${server.port}")
-    sys.props("livy.server.serverUrl") = _serverUrl.get
+    sys.props("livy.server.server-url") = _serverUrl.get
   }
 
   def runKinit(keytab: String, principal: String): Boolean = {

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/221aa9cf/server/src/main/scala/com/cloudera/livy/server/interactive/InteractiveSession.scala
----------------------------------------------------------------------
diff --git a/server/src/main/scala/com/cloudera/livy/server/interactive/InteractiveSession.scala b/server/src/main/scala/com/cloudera/livy/server/interactive/InteractiveSession.scala
index 605edc6..b53dea7 100644
--- a/server/src/main/scala/com/cloudera/livy/server/interactive/InteractiveSession.scala
+++ b/server/src/main/scala/com/cloudera/livy/server/interactive/InteractiveSession.scala
@@ -100,7 +100,7 @@ object InteractiveSession extends Logging {
       info(s"Creating LivyClient for sessionId: $id")
       val builder = new LivyClientBuilder()
         .setAll(builderProperties.asJava)
-        .setConf("livy.client.sessionId", id.toString)
+        .setConf("livy.client.session-id", id.toString)
         .setConf(RSCConf.Entry.DRIVER_CLASS.key(), "com.cloudera.livy.repl.ReplDriver")
         .setConf(RSCConf.Entry.PROXY_USER.key(), proxyUser.orNull)
         .setURI(new URI("rsc:/"))


[27/50] [abbrv] incubator-livy git commit: LIVY-272. Support Statement progress for interactive session. (#260)

Posted by js...@apache.org.
LIVY-272. Support Statement progress for interactive session. (#260)



Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/70f23b90
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/70f23b90
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/70f23b90

Branch: refs/heads/master
Commit: 70f23b90f9cc7fbe98663551a4cdff86a7c069dd
Parents: 126b57e
Author: Saisai Shao <sa...@gmail.com>
Authored: Sun Mar 12 10:16:52 2017 +0800
Committer: Alex Man <al...@users.noreply.github.com>
Committed: Sat Mar 11 18:16:52 2017 -0800

----------------------------------------------------------------------
 .../cloudera/livy/repl/SparkInterpreter.scala   |   4 +-
 .../livy/repl/SparkInterpreterSpec.scala        |   2 +-
 .../cloudera/livy/repl/SparkInterpreter.scala   |   4 +-
 .../livy/repl/SparkInterpreterSpec.scala        |   2 +-
 .../livy/repl/AbstractSparkInterpreter.scala    |  11 +-
 .../com/cloudera/livy/repl/Interpreter.scala    |  16 +-
 .../cloudera/livy/repl/ProcessInterpreter.scala |  13 +-
 .../cloudera/livy/repl/PythonInterpreter.scala  |  12 +-
 .../com/cloudera/livy/repl/ReplDriver.scala     |  15 +-
 .../scala/com/cloudera/livy/repl/Session.scala  |   3 +-
 .../cloudera/livy/repl/SparkRInterpreter.scala  |  13 +-
 .../livy/repl/StatementProgressListener.scala   | 162 +++++++++++++
 .../livy/repl/PythonInterpreterSpec.scala       |   7 +-
 .../cloudera/livy/repl/PythonSessionSpec.scala  |   7 +-
 .../livy/repl/ScalaInterpreterSpec.scala        |   5 +-
 .../livy/repl/SparkRInterpreterSpec.scala       |   5 +-
 .../cloudera/livy/repl/SparkRSessionSpec.scala  |   5 +-
 .../cloudera/livy/repl/SparkSessionSpec.scala   |   6 +-
 .../repl/StatementProgressListenerSpec.scala    | 227 +++++++++++++++++++
 .../java/com/cloudera/livy/rsc/RSCConf.java     |   4 +
 .../com/cloudera/livy/rsc/driver/Statement.java |  10 +
 .../InteractiveSessionServletSpec.scala         |   1 +
 .../interactive/InteractiveSessionSpec.scala    |  16 ++
 23 files changed, 509 insertions(+), 41 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/70f23b90/repl/scala-2.10/src/main/scala/com/cloudera/livy/repl/SparkInterpreter.scala
----------------------------------------------------------------------
diff --git a/repl/scala-2.10/src/main/scala/com/cloudera/livy/repl/SparkInterpreter.scala b/repl/scala-2.10/src/main/scala/com/cloudera/livy/repl/SparkInterpreter.scala
index 3322de1..ec12929 100644
--- a/repl/scala-2.10/src/main/scala/com/cloudera/livy/repl/SparkInterpreter.scala
+++ b/repl/scala-2.10/src/main/scala/com/cloudera/livy/repl/SparkInterpreter.scala
@@ -33,7 +33,8 @@ import org.apache.spark.repl.SparkIMain
 /**
  * This represents a Spark interpreter. It is not thread safe.
  */
-class SparkInterpreter(conf: SparkConf)
+class SparkInterpreter(conf: SparkConf,
+    override val statementProgressListener: StatementProgressListener)
   extends AbstractSparkInterpreter with SparkContextInitializer {
 
   private var sparkIMain: SparkIMain = _
@@ -103,6 +104,7 @@ class SparkInterpreter(conf: SparkConf)
       createSparkContext(conf)
     }
 
+    sparkContext.addSparkListener(statementProgressListener)
     sparkContext
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/70f23b90/repl/scala-2.10/src/test/scala/com/cloudera/livy/repl/SparkInterpreterSpec.scala
----------------------------------------------------------------------
diff --git a/repl/scala-2.10/src/test/scala/com/cloudera/livy/repl/SparkInterpreterSpec.scala b/repl/scala-2.10/src/test/scala/com/cloudera/livy/repl/SparkInterpreterSpec.scala
index e2b783a..3df35b5 100644
--- a/repl/scala-2.10/src/test/scala/com/cloudera/livy/repl/SparkInterpreterSpec.scala
+++ b/repl/scala-2.10/src/test/scala/com/cloudera/livy/repl/SparkInterpreterSpec.scala
@@ -24,7 +24,7 @@ import com.cloudera.livy.LivyBaseUnitTestSuite
 
 class SparkInterpreterSpec extends FunSpec with Matchers with LivyBaseUnitTestSuite {
   describe("SparkInterpreter") {
-    val interpreter = new SparkInterpreter(null)
+    val interpreter = new SparkInterpreter(null, null)
 
     it("should parse Scala compile error.") {
       // Regression test for LIVY-260.

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/70f23b90/repl/scala-2.11/src/main/scala/com/cloudera/livy/repl/SparkInterpreter.scala
----------------------------------------------------------------------
diff --git a/repl/scala-2.11/src/main/scala/com/cloudera/livy/repl/SparkInterpreter.scala b/repl/scala-2.11/src/main/scala/com/cloudera/livy/repl/SparkInterpreter.scala
index 2bf6347..bf2f680 100644
--- a/repl/scala-2.11/src/main/scala/com/cloudera/livy/repl/SparkInterpreter.scala
+++ b/repl/scala-2.11/src/main/scala/com/cloudera/livy/repl/SparkInterpreter.scala
@@ -33,7 +33,8 @@ import org.apache.spark.repl.SparkILoop
 /**
  * Scala 2.11 version of SparkInterpreter
  */
-class SparkInterpreter(conf: SparkConf)
+class SparkInterpreter(conf: SparkConf,
+    override val statementProgressListener: StatementProgressListener)
   extends AbstractSparkInterpreter with SparkContextInitializer {
 
   protected var sparkContext: SparkContext = _
@@ -89,6 +90,7 @@ class SparkInterpreter(conf: SparkConf)
       createSparkContext(conf)
     }
 
+    sparkContext.addSparkListener(statementProgressListener)
     sparkContext
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/70f23b90/repl/scala-2.11/src/test/scala/com/cloudera/livy/repl/SparkInterpreterSpec.scala
----------------------------------------------------------------------
diff --git a/repl/scala-2.11/src/test/scala/com/cloudera/livy/repl/SparkInterpreterSpec.scala b/repl/scala-2.11/src/test/scala/com/cloudera/livy/repl/SparkInterpreterSpec.scala
index 5cb88e3..56656d7 100644
--- a/repl/scala-2.11/src/test/scala/com/cloudera/livy/repl/SparkInterpreterSpec.scala
+++ b/repl/scala-2.11/src/test/scala/com/cloudera/livy/repl/SparkInterpreterSpec.scala
@@ -24,7 +24,7 @@ import com.cloudera.livy.LivyBaseUnitTestSuite
 
 class SparkInterpreterSpec extends FunSpec with Matchers with LivyBaseUnitTestSuite {
   describe("SparkInterpreter") {
-    val interpreter = new SparkInterpreter(null)
+    val interpreter = new SparkInterpreter(null, null)
 
     it("should parse Scala compile error.") {
       // Regression test for LIVY-.

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/70f23b90/repl/src/main/scala/com/cloudera/livy/repl/AbstractSparkInterpreter.scala
----------------------------------------------------------------------
diff --git a/repl/src/main/scala/com/cloudera/livy/repl/AbstractSparkInterpreter.scala b/repl/src/main/scala/com/cloudera/livy/repl/AbstractSparkInterpreter.scala
index d30bb3b..d117da7 100644
--- a/repl/src/main/scala/com/cloudera/livy/repl/AbstractSparkInterpreter.scala
+++ b/repl/src/main/scala/com/cloudera/livy/repl/AbstractSparkInterpreter.scala
@@ -50,12 +50,13 @@ abstract class AbstractSparkInterpreter extends Interpreter with Logging {
 
   protected def valueOfTerm(name: String): Option[Any]
 
-  override def execute(code: String): Interpreter.ExecuteResponse = restoreContextClassLoader {
-    require(isStarted())
+  override protected[repl] def execute(code: String): Interpreter.ExecuteResponse =
+    restoreContextClassLoader {
+      require(isStarted())
 
-    executeLines(code.trim.split("\n").toList, Interpreter.ExecuteSuccess(JObject(
-      (TEXT_PLAIN, JString(""))
-    )))
+      executeLines(code.trim.split("\n").toList, Interpreter.ExecuteSuccess(JObject(
+        (TEXT_PLAIN, JString(""))
+      )))
   }
 
   private def executeMagic(magic: String, rest: String): Interpreter.ExecuteResponse = {

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/70f23b90/repl/src/main/scala/com/cloudera/livy/repl/Interpreter.scala
----------------------------------------------------------------------
diff --git a/repl/src/main/scala/com/cloudera/livy/repl/Interpreter.scala b/repl/src/main/scala/com/cloudera/livy/repl/Interpreter.scala
index 069953e..59ad878 100644
--- a/repl/src/main/scala/com/cloudera/livy/repl/Interpreter.scala
+++ b/repl/src/main/scala/com/cloudera/livy/repl/Interpreter.scala
@@ -37,18 +37,28 @@ trait Interpreter {
 
   def kind: String
 
+  def statementProgressListener: StatementProgressListener
+
   /**
    * Start the Interpreter.
    *
-   * @return A SparkContext, which may be null.
+   * @return A SparkContext
    */
   def start(): SparkContext
 
   /**
-   * Execute the code and return the result as a Future as it may
+   * Execute the code and return the result.
+   */
+  def execute(statementId: Int, code: String): ExecuteResponse = {
+    statementProgressListener.setCurrentStatementId(statementId)
+    execute(code)
+  }
+
+  /**
+   * Execute the code and return the result, it may
    * take some time to execute.
    */
-  def execute(code: String): ExecuteResponse
+  protected[repl] def execute(code: String): ExecuteResponse
 
   /** Shut down the interpreter. */
   def close(): Unit

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/70f23b90/repl/src/main/scala/com/cloudera/livy/repl/ProcessInterpreter.scala
----------------------------------------------------------------------
diff --git a/repl/src/main/scala/com/cloudera/livy/repl/ProcessInterpreter.scala b/repl/src/main/scala/com/cloudera/livy/repl/ProcessInterpreter.scala
index c4fb8ca..0414bbb 100644
--- a/repl/src/main/scala/com/cloudera/livy/repl/ProcessInterpreter.scala
+++ b/repl/src/main/scala/com/cloudera/livy/repl/ProcessInterpreter.scala
@@ -41,10 +41,9 @@ private case class ShutdownRequest(promise: Promise[Unit]) extends Request
  *
  * @param process
  */
-abstract class ProcessInterpreter(process: Process)
-  extends Interpreter
-  with Logging
-{
+abstract class ProcessInterpreter(process: Process,
+    override val statementProgressListener: StatementProgressListener)
+  extends Interpreter with Logging {
   protected[this] val stdin = new PrintWriter(process.getOutputStream)
   protected[this] val stdout = new BufferedReader(new InputStreamReader(process.getInputStream), 1)
 
@@ -54,11 +53,13 @@ abstract class ProcessInterpreter(process: Process)
     if (ClientConf.TEST_MODE) {
       null.asInstanceOf[SparkContext]
     } else {
-      SparkContext.getOrCreate()
+      val sc = SparkContext.getOrCreate()
+      sc.addSparkListener(statementProgressListener)
+      sc
     }
   }
 
-  override def execute(code: String): Interpreter.ExecuteResponse = {
+  override protected[repl] def execute(code: String): Interpreter.ExecuteResponse = {
     try {
       sendExecuteRequest(code)
     } catch {

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/70f23b90/repl/src/main/scala/com/cloudera/livy/repl/PythonInterpreter.scala
----------------------------------------------------------------------
diff --git a/repl/src/main/scala/com/cloudera/livy/repl/PythonInterpreter.scala b/repl/src/main/scala/com/cloudera/livy/repl/PythonInterpreter.scala
index 2195d0e..6e80c09 100644
--- a/repl/src/main/scala/com/cloudera/livy/repl/PythonInterpreter.scala
+++ b/repl/src/main/scala/com/cloudera/livy/repl/PythonInterpreter.scala
@@ -45,7 +45,7 @@ import com.cloudera.livy.sessions._
 // scalastyle:off println
 object PythonInterpreter extends Logging {
 
-  def apply(conf: SparkConf, kind: Kind): Interpreter = {
+  def apply(conf: SparkConf, kind: Kind, listener: StatementProgressListener): Interpreter = {
     val pythonExec = kind match {
         case PySpark() => sys.env.getOrElse("PYSPARK_PYTHON", "python")
         case PySpark3() => sys.env.getOrElse("PYSPARK3_PYTHON", "python3")
@@ -72,7 +72,7 @@ object PythonInterpreter extends Logging {
     env.put("LIVY_SPARK_MAJOR_VERSION", conf.get("spark.livy.spark_major_version", "1"))
     builder.redirectError(Redirect.PIPE)
     val process = builder.start()
-    new PythonInterpreter(process, gatewayServer, kind.toString)
+    new PythonInterpreter(process, gatewayServer, kind.toString, listener)
   }
 
   private def findPySparkArchives(): Seq[String] = {
@@ -187,8 +187,12 @@ object PythonInterpreter extends Logging {
   }
 }
 
-private class PythonInterpreter(process: Process, gatewayServer: GatewayServer, pyKind: String)
-  extends ProcessInterpreter(process)
+private class PythonInterpreter(
+    process: Process,
+    gatewayServer: GatewayServer,
+    pyKind: String,
+    listener: StatementProgressListener)
+  extends ProcessInterpreter(process, listener)
   with Logging
 {
   implicit val formats = DefaultFormats

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/70f23b90/repl/src/main/scala/com/cloudera/livy/repl/ReplDriver.scala
----------------------------------------------------------------------
diff --git a/repl/src/main/scala/com/cloudera/livy/repl/ReplDriver.scala b/repl/src/main/scala/com/cloudera/livy/repl/ReplDriver.scala
index c176412..d368c6a 100644
--- a/repl/src/main/scala/com/cloudera/livy/repl/ReplDriver.scala
+++ b/repl/src/main/scala/com/cloudera/livy/repl/ReplDriver.scala
@@ -44,10 +44,11 @@ class ReplDriver(conf: SparkConf, livyConf: RSCConf)
 
   override protected def initializeContext(): JavaSparkContext = {
     interpreter = kind match {
-      case PySpark() => PythonInterpreter(conf, PySpark())
-      case PySpark3() => PythonInterpreter(conf, PySpark3())
-      case Spark() => new SparkInterpreter(conf)
-      case SparkR() => SparkRInterpreter(conf)
+      case PySpark() => PythonInterpreter(conf, PySpark(), new StatementProgressListener(livyConf))
+      case PySpark3() =>
+        PythonInterpreter(conf, PySpark3(), new StatementProgressListener(livyConf))
+      case Spark() => new SparkInterpreter(conf, new StatementProgressListener(livyConf))
+      case SparkR() => SparkRInterpreter(conf, new StatementProgressListener(livyConf))
     }
     session = new Session(livyConf, interpreter, { s => broadcast(new ReplState(s.toString)) })
 
@@ -90,6 +91,12 @@ class ReplDriver(conf: SparkConf, livyConf: RSCConf)
         session.statements.filterKeys(id => id >= msg.from && id < until).values.toArray
       }
     }
+
+    // Update progress of statements when queried
+    statements.foreach { s =>
+      s.updateProgress(interpreter.statementProgressListener.progressOfStatement(s.id))
+    }
+
     new ReplJobResults(statements.sortBy(_.id))
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/70f23b90/repl/src/main/scala/com/cloudera/livy/repl/Session.scala
----------------------------------------------------------------------
diff --git a/repl/src/main/scala/com/cloudera/livy/repl/Session.scala b/repl/src/main/scala/com/cloudera/livy/repl/Session.scala
index bf1f3b4..54056a3 100644
--- a/repl/src/main/scala/com/cloudera/livy/repl/Session.scala
+++ b/repl/src/main/scala/com/cloudera/livy/repl/Session.scala
@@ -116,6 +116,7 @@ class Session(
 
       statement.compareAndTransit(StatementState.Running, StatementState.Available)
       statement.compareAndTransit(StatementState.Cancelling, StatementState.Cancelled)
+      statement.updateProgress(1.0)
     }(interpreterExecutor)
 
     statementId
@@ -187,7 +188,7 @@ class Session(
     }
 
     val resultInJson = try {
-      interpreter.execute(code) match {
+      interpreter.execute(executionCount, code) match {
         case Interpreter.ExecuteSuccess(data) =>
           transitToIdle()
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/70f23b90/repl/src/main/scala/com/cloudera/livy/repl/SparkRInterpreter.scala
----------------------------------------------------------------------
diff --git a/repl/src/main/scala/com/cloudera/livy/repl/SparkRInterpreter.scala b/repl/src/main/scala/com/cloudera/livy/repl/SparkRInterpreter.scala
index cc57d72..8e5f3c0 100644
--- a/repl/src/main/scala/com/cloudera/livy/repl/SparkRInterpreter.scala
+++ b/repl/src/main/scala/com/cloudera/livy/repl/SparkRInterpreter.scala
@@ -35,6 +35,7 @@ import org.json4s._
 import org.json4s.JsonDSL._
 
 import com.cloudera.livy.client.common.ClientConf
+import com.cloudera.livy.rsc.RSCConf
 
 // scalastyle:off println
 object SparkRInterpreter {
@@ -64,7 +65,7 @@ object SparkRInterpreter {
     ")"
     ).r.unanchored
 
-  def apply(conf: SparkConf): SparkRInterpreter = {
+  def apply(conf: SparkConf, listener: StatementProgressListener): SparkRInterpreter = {
     val backendTimeout = sys.env.getOrElse("SPARKR_BACKEND_TIMEOUT", "120").toInt
     val mirror = universe.runtimeMirror(getClass.getClassLoader)
     val sparkRBackendClass = mirror.classLoader.loadClass("org.apache.spark.api.r.RBackend")
@@ -117,7 +118,8 @@ object SparkRInterpreter {
       val process = builder.start()
       new SparkRInterpreter(process, backendInstance, backendThread,
         conf.get("spark.livy.spark_major_version", "1"),
-        conf.getBoolean("spark.repl.enableHiveContext", false))
+        conf.getBoolean("spark.repl.enableHiveContext", false),
+        listener)
     } catch {
       case e: Exception =>
         if (backendThread != null) {
@@ -132,15 +134,16 @@ class SparkRInterpreter(process: Process,
     backendInstance: Any,
     backendThread: Thread,
     val sparkMajorVersion: String,
-    hiveEnabled: Boolean)
-  extends ProcessInterpreter(process) {
+    hiveEnabled: Boolean,
+    statementProgressListener: StatementProgressListener)
+  extends ProcessInterpreter(process, statementProgressListener) {
   import SparkRInterpreter._
 
   implicit val formats = DefaultFormats
 
   private[this] var executionCount = 0
   override def kind: String = "sparkr"
-  private[this] val isStarted = new CountDownLatch(1);
+  private[this] val isStarted = new CountDownLatch(1)
 
   final override protected def waitUntilReady(): Unit = {
     // Set the option to catch and ignore errors instead of halting.

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/70f23b90/repl/src/main/scala/com/cloudera/livy/repl/StatementProgressListener.scala
----------------------------------------------------------------------
diff --git a/repl/src/main/scala/com/cloudera/livy/repl/StatementProgressListener.scala b/repl/src/main/scala/com/cloudera/livy/repl/StatementProgressListener.scala
new file mode 100644
index 0000000..ae2147b
--- /dev/null
+++ b/repl/src/main/scala/com/cloudera/livy/repl/StatementProgressListener.scala
@@ -0,0 +1,162 @@
+/*
+ * Licensed to Cloudera, Inc. under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  Cloudera, Inc. 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 com.cloudera.livy.repl
+
+import scala.collection.mutable
+
+import com.google.common.annotations.VisibleForTesting
+import org.apache.spark.Success
+import org.apache.spark.scheduler._
+
+import com.cloudera.livy.rsc.RSCConf
+
+/**
+ * [[StatementProgressListener]] is an implementation of SparkListener, used to track the progress
+ * of submitted statement, this class builds a mapping relation between statement, jobs, stages
+ * and tasks, and uses the finished task number to calculate the statement progress.
+ *
+ * By default 100 latest statement progresses will be kept, users could also configure
+ * livy.rsc.retained_statements to change the cached number.
+ *
+ * This statement progress can only reflect the statement in which has Spark jobs, if
+ * the statement submitted doesn't generate any Spark job, the progress will always return 0.0
+ * until completed.
+ *
+ * Also if the statement includes several Spark jobs, the progress will be flipped because we
+ * don't know the actual number of Spark jobs/tasks generated before the statement executed.
+ */
+class StatementProgressListener(conf: RSCConf) extends SparkListener {
+
+  case class TaskCount(var currFinishedTasks: Int, var totalTasks: Int)
+  case class JobState(jobId: Int, var isCompleted: Boolean)
+
+  private val retainedStatements = conf.getInt(RSCConf.Entry.RETAINED_STATEMENT_NUMBER)
+
+  /** Statement id to list of jobs map */
+  @VisibleForTesting
+  private[repl] val statementToJobs = new mutable.LinkedHashMap[Int, Seq[JobState]]()
+  @VisibleForTesting
+  private[repl] val jobIdToStatement = new mutable.HashMap[Int, Int]()
+  /** Job id to list of stage ids map */
+  @VisibleForTesting
+  private[repl] val jobIdToStages = new mutable.HashMap[Int, Seq[Int]]()
+  /** Stage id to number of finished/total tasks map */
+  @VisibleForTesting
+  private[repl] val stageIdToTaskCount = new mutable.HashMap[Int, TaskCount]()
+
+  @transient private var currentStatementId: Int = _
+
+  /**
+   * Set current statement id, onJobStart() will use current statement id to build the mapping
+   * relations.
+   */
+  def setCurrentStatementId(stmtId: Int): Unit = {
+    currentStatementId = stmtId
+  }
+
+  /**
+   * Get the current progress of given statement id.
+   */
+  def progressOfStatement(stmtId: Int): Double = synchronized {
+    var finishedTasks = 0
+    var totalTasks = 0
+
+    for {
+      job <- statementToJobs.getOrElse(stmtId, Seq.empty)
+      stageId <- jobIdToStages.getOrElse(job.jobId, Seq.empty)
+      taskCount <- stageIdToTaskCount.get(stageId)
+    } yield {
+      finishedTasks += taskCount.currFinishedTasks
+      totalTasks += taskCount.totalTasks
+    }
+
+    if (totalTasks == 0) {
+      0.0
+    } else {
+      finishedTasks.toDouble / totalTasks
+    }
+  }
+
+  /**
+   * Get the active job ids of the given statement id.
+   */
+  def activeJobsOfStatement(stmtId: Int): Seq[Int] = synchronized {
+    statementToJobs.getOrElse(stmtId, Seq.empty).filter(!_.isCompleted).map(_.jobId)
+  }
+
+  override def onJobStart(jobStart: SparkListenerJobStart): Unit = synchronized {
+    val jobs = statementToJobs.getOrElseUpdate(currentStatementId, Seq.empty) :+
+      JobState(jobStart.jobId, isCompleted = false)
+    statementToJobs.put(currentStatementId, jobs)
+    jobIdToStatement(jobStart.jobId) = currentStatementId
+
+    jobIdToStages(jobStart.jobId) = jobStart.stageInfos.map(_.stageId)
+    jobStart.stageInfos.foreach { s => stageIdToTaskCount(s.stageId) = TaskCount(0, s.numTasks) }
+  }
+
+  override def onTaskEnd(taskEnd: SparkListenerTaskEnd): Unit = synchronized {
+    taskEnd.reason match {
+      case Success =>
+        stageIdToTaskCount.get(taskEnd.stageId).foreach { t => t.currFinishedTasks += 1 }
+      case _ =>
+        // If task is failed, it will run again, so don't count it.
+    }
+  }
+
+  override def onStageSubmitted(stageSubmitted: SparkListenerStageSubmitted): Unit = synchronized {
+    // If stage is resubmitted, we should reset the task count of this stage.
+    stageIdToTaskCount.get(stageSubmitted.stageInfo.stageId).foreach { t =>
+      t.currFinishedTasks = 0
+      t.totalTasks = stageSubmitted.stageInfo.numTasks
+    }
+  }
+
+  override def onStageCompleted(stageCompleted: SparkListenerStageCompleted): Unit = synchronized {
+    stageIdToTaskCount.get(stageCompleted.stageInfo.stageId).foreach { t =>
+      t.currFinishedTasks = t.totalTasks
+    }
+  }
+
+  override def onJobEnd(jobEnd: SparkListenerJobEnd): Unit = synchronized {
+    jobIdToStatement.get(jobEnd.jobId).foreach { stmtId =>
+      statementToJobs.get(stmtId).foreach { jobs =>
+        jobs.filter(_.jobId == jobEnd.jobId).foreach(_.isCompleted = true)
+      }
+    }
+
+    // Try to clean the old data when job is finished. This will trigger data cleaning in LRU
+    // policy.
+    cleanOldMetadata()
+  }
+
+  private def cleanOldMetadata(): Unit = {
+    if (statementToJobs.size > retainedStatements) {
+      val toRemove = statementToJobs.size - retainedStatements
+      statementToJobs.take(toRemove).foreach { case (_, jobs) =>
+        jobs.foreach { job =>
+          jobIdToStatement.remove(job.jobId)
+          jobIdToStages.remove(job.jobId).foreach { stages =>
+            stages.foreach(s => stageIdToTaskCount.remove(s))
+          }
+        }
+      }
+      (0 until toRemove).foreach(_ => statementToJobs.remove(statementToJobs.head._1))
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/70f23b90/repl/src/test/scala/com/cloudera/livy/repl/PythonInterpreterSpec.scala
----------------------------------------------------------------------
diff --git a/repl/src/test/scala/com/cloudera/livy/repl/PythonInterpreterSpec.scala b/repl/src/test/scala/com/cloudera/livy/repl/PythonInterpreterSpec.scala
index 00bbc68..c67d580 100644
--- a/repl/src/test/scala/com/cloudera/livy/repl/PythonInterpreterSpec.scala
+++ b/repl/src/test/scala/com/cloudera/livy/repl/PythonInterpreterSpec.scala
@@ -23,6 +23,7 @@ import org.json4s.{DefaultFormats, JNull, JValue}
 import org.json4s.JsonDSL._
 import org.scalatest._
 
+import com.cloudera.livy.rsc.RSCConf
 import com.cloudera.livy.sessions._
 
 abstract class PythonBaseInterpreterSpec extends BaseInterpreterSpec {
@@ -244,7 +245,8 @@ class Python2InterpreterSpec extends PythonBaseInterpreterSpec {
 
   implicit val formats = DefaultFormats
 
-  override def createInterpreter(): Interpreter = PythonInterpreter(new SparkConf(), PySpark())
+  override def createInterpreter(): Interpreter =
+    PythonInterpreter(new SparkConf(), PySpark(), new StatementProgressListener(new RSCConf()))
 
   // Scalastyle is treating unicode escape as non ascii characters. Turn off the check.
   // scalastyle:off non.ascii.character.disallowed
@@ -271,7 +273,8 @@ class Python3InterpreterSpec extends PythonBaseInterpreterSpec {
     test()
   }
 
-  override def createInterpreter(): Interpreter = PythonInterpreter(new SparkConf(), PySpark3())
+  override def createInterpreter(): Interpreter =
+    PythonInterpreter(new SparkConf(), PySpark3(), new StatementProgressListener(new RSCConf()))
 
   it should "check python version is 3.x" in withInterpreter { interpreter =>
     val response = interpreter.execute("""import sys

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/70f23b90/repl/src/test/scala/com/cloudera/livy/repl/PythonSessionSpec.scala
----------------------------------------------------------------------
diff --git a/repl/src/test/scala/com/cloudera/livy/repl/PythonSessionSpec.scala b/repl/src/test/scala/com/cloudera/livy/repl/PythonSessionSpec.scala
index 4582acd..28f457f 100644
--- a/repl/src/test/scala/com/cloudera/livy/repl/PythonSessionSpec.scala
+++ b/repl/src/test/scala/com/cloudera/livy/repl/PythonSessionSpec.scala
@@ -23,6 +23,7 @@ import org.json4s.Extraction
 import org.json4s.jackson.JsonMethods.parse
 import org.scalatest._
 
+import com.cloudera.livy.rsc.RSCConf
 import com.cloudera.livy.sessions._
 
 abstract class PythonSessionSpec extends BaseSessionSpec {
@@ -173,7 +174,8 @@ abstract class PythonSessionSpec extends BaseSessionSpec {
 }
 
 class Python2SessionSpec extends PythonSessionSpec {
-  override def createInterpreter(): Interpreter = PythonInterpreter(new SparkConf(), PySpark())
+  override def createInterpreter(): Interpreter =
+    PythonInterpreter(new SparkConf(), PySpark(), new StatementProgressListener(new RSCConf()))
 }
 
 class Python3SessionSpec extends PythonSessionSpec {
@@ -183,7 +185,8 @@ class Python3SessionSpec extends PythonSessionSpec {
     test()
   }
 
-  override def createInterpreter(): Interpreter = PythonInterpreter(new SparkConf(), PySpark3())
+  override def createInterpreter(): Interpreter =
+    PythonInterpreter(new SparkConf(), PySpark3(), new StatementProgressListener(new RSCConf()))
 
   it should "check python version is 3.x" in withSession { session =>
     val statement = execute(session)(

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/70f23b90/repl/src/test/scala/com/cloudera/livy/repl/ScalaInterpreterSpec.scala
----------------------------------------------------------------------
diff --git a/repl/src/test/scala/com/cloudera/livy/repl/ScalaInterpreterSpec.scala b/repl/src/test/scala/com/cloudera/livy/repl/ScalaInterpreterSpec.scala
index 63076e7..a9e1e8b 100644
--- a/repl/src/test/scala/com/cloudera/livy/repl/ScalaInterpreterSpec.scala
+++ b/repl/src/test/scala/com/cloudera/livy/repl/ScalaInterpreterSpec.scala
@@ -22,11 +22,14 @@ import org.apache.spark.SparkConf
 import org.json4s.{DefaultFormats, JValue}
 import org.json4s.JsonDSL._
 
+import com.cloudera.livy.rsc.RSCConf
+
 class ScalaInterpreterSpec extends BaseInterpreterSpec {
 
   implicit val formats = DefaultFormats
 
-  override def createInterpreter(): Interpreter = new SparkInterpreter(new SparkConf())
+  override def createInterpreter(): Interpreter =
+    new SparkInterpreter(new SparkConf(), new StatementProgressListener(new RSCConf()))
 
   it should "execute `1 + 2` == 3" in withInterpreter { interpreter =>
     val response = interpreter.execute("1 + 2")

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/70f23b90/repl/src/test/scala/com/cloudera/livy/repl/SparkRInterpreterSpec.scala
----------------------------------------------------------------------
diff --git a/repl/src/test/scala/com/cloudera/livy/repl/SparkRInterpreterSpec.scala b/repl/src/test/scala/com/cloudera/livy/repl/SparkRInterpreterSpec.scala
index af03581..e9db106 100644
--- a/repl/src/test/scala/com/cloudera/livy/repl/SparkRInterpreterSpec.scala
+++ b/repl/src/test/scala/com/cloudera/livy/repl/SparkRInterpreterSpec.scala
@@ -23,6 +23,8 @@ import org.json4s.{DefaultFormats, JValue}
 import org.json4s.JsonDSL._
 import org.scalatest._
 
+import com.cloudera.livy.rsc.RSCConf
+
 class SparkRInterpreterSpec extends BaseInterpreterSpec {
 
   implicit val formats = DefaultFormats
@@ -32,7 +34,8 @@ class SparkRInterpreterSpec extends BaseInterpreterSpec {
     super.withFixture(test)
   }
 
-  override def createInterpreter(): Interpreter = SparkRInterpreter(new SparkConf())
+  override def createInterpreter(): Interpreter =
+    SparkRInterpreter(new SparkConf(), new StatementProgressListener(new RSCConf()))
 
   it should "execute `1 + 2` == 3" in withInterpreter { interpreter =>
     val response = interpreter.execute("1 + 2")

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/70f23b90/repl/src/test/scala/com/cloudera/livy/repl/SparkRSessionSpec.scala
----------------------------------------------------------------------
diff --git a/repl/src/test/scala/com/cloudera/livy/repl/SparkRSessionSpec.scala b/repl/src/test/scala/com/cloudera/livy/repl/SparkRSessionSpec.scala
index cfa2ba5..5592977 100644
--- a/repl/src/test/scala/com/cloudera/livy/repl/SparkRSessionSpec.scala
+++ b/repl/src/test/scala/com/cloudera/livy/repl/SparkRSessionSpec.scala
@@ -22,6 +22,8 @@ import org.apache.spark.SparkConf
 import org.json4s.Extraction
 import org.json4s.jackson.JsonMethods.parse
 
+import com.cloudera.livy.rsc.RSCConf
+
 class SparkRSessionSpec extends BaseSessionSpec {
 
   override protected def withFixture(test: NoArgTest) = {
@@ -29,7 +31,8 @@ class SparkRSessionSpec extends BaseSessionSpec {
     super.withFixture(test)
   }
 
-  override def createInterpreter(): Interpreter = SparkRInterpreter(new SparkConf())
+  override def createInterpreter(): Interpreter =
+    SparkRInterpreter(new SparkConf(), new StatementProgressListener(new RSCConf()))
 
   it should "execute `1 + 2` == 3" in withSession { session =>
     val statement = execute(session)("1 + 2")

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/70f23b90/repl/src/test/scala/com/cloudera/livy/repl/SparkSessionSpec.scala
----------------------------------------------------------------------
diff --git a/repl/src/test/scala/com/cloudera/livy/repl/SparkSessionSpec.scala b/repl/src/test/scala/com/cloudera/livy/repl/SparkSessionSpec.scala
index 2ef7241..a051513 100644
--- a/repl/src/test/scala/com/cloudera/livy/repl/SparkSessionSpec.scala
+++ b/repl/src/test/scala/com/cloudera/livy/repl/SparkSessionSpec.scala
@@ -23,15 +23,17 @@ import scala.language.postfixOps
 
 import org.apache.spark.SparkConf
 import org.json4s.Extraction
-import org.json4s.jackson.JsonMethods.parse
 import org.json4s.JsonAST.JValue
+import org.json4s.jackson.JsonMethods.parse
 import org.scalatest.concurrent.Eventually._
 
+import com.cloudera.livy.rsc.RSCConf
 import com.cloudera.livy.rsc.driver.StatementState
 
 class SparkSessionSpec extends BaseSessionSpec {
 
-  override def createInterpreter(): Interpreter = new SparkInterpreter(new SparkConf())
+  override def createInterpreter(): Interpreter =
+    new SparkInterpreter(new SparkConf(), new StatementProgressListener(new RSCConf()))
 
   it should "execute `1 + 2` == 3" in withSession { session =>
     val statement = execute(session)("1 + 2")

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/70f23b90/repl/src/test/scala/com/cloudera/livy/repl/StatementProgressListenerSpec.scala
----------------------------------------------------------------------
diff --git a/repl/src/test/scala/com/cloudera/livy/repl/StatementProgressListenerSpec.scala b/repl/src/test/scala/com/cloudera/livy/repl/StatementProgressListenerSpec.scala
new file mode 100644
index 0000000..2acee4c
--- /dev/null
+++ b/repl/src/test/scala/com/cloudera/livy/repl/StatementProgressListenerSpec.scala
@@ -0,0 +1,227 @@
+/*
+ * Licensed to Cloudera, Inc. under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  Cloudera, Inc. 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 com.cloudera.livy.repl
+
+import java.util.concurrent.atomic.AtomicInteger
+
+import scala.collection.mutable.ArrayBuffer
+import scala.concurrent.duration._
+import scala.language.{postfixOps, reflectiveCalls}
+
+import org.apache.spark.SparkConf
+import org.apache.spark.scheduler._
+import org.scalatest._
+import org.scalatest.concurrent.Eventually._
+
+import com.cloudera.livy.LivyBaseUnitTestSuite
+import com.cloudera.livy.rsc.RSCConf
+
+class StatementProgressListenerSpec extends FlatSpec
+    with Matchers
+    with BeforeAndAfterAll
+    with BeforeAndAfter
+    with LivyBaseUnitTestSuite {
+  private val rscConf = new RSCConf()
+    .set(RSCConf.Entry.RETAINED_STATEMENT_NUMBER, 2)
+
+  private val testListener = new StatementProgressListener(rscConf) {
+    var onJobStartedCallback: Option[() => Unit] = None
+    var onJobEndCallback: Option[() => Unit] = None
+    var onStageEndCallback: Option[() => Unit] = None
+    var onTaskEndCallback: Option[() => Unit] = None
+
+    override  def onJobStart(jobStart: SparkListenerJobStart): Unit = {
+      super.onJobStart(jobStart)
+      onJobStartedCallback.foreach(f => f())
+    }
+
+    override def onJobEnd(jobEnd: SparkListenerJobEnd): Unit = {
+      super.onJobEnd(jobEnd)
+      onJobEndCallback.foreach(f => f())
+    }
+
+    override def onStageCompleted(stageCompleted: SparkListenerStageCompleted): Unit = {
+      super.onStageCompleted(stageCompleted)
+      onStageEndCallback.foreach(f => f())
+    }
+
+    override def onTaskEnd(taskEnd: SparkListenerTaskEnd): Unit = {
+      super.onTaskEnd(taskEnd)
+      onTaskEndCallback.foreach(f => f())
+    }
+  }
+
+  private val statementId = new AtomicInteger(0)
+
+  private def getStatementId = statementId.getAndIncrement()
+
+  private var sparkInterpreter: SparkInterpreter = _
+
+  override def beforeAll(): Unit = {
+    super.beforeAll()
+    sparkInterpreter = new SparkInterpreter(new SparkConf(), testListener)
+    sparkInterpreter.start()
+  }
+
+  override def afterAll(): Unit = {
+    sparkInterpreter.close()
+    super.afterAll()
+  }
+
+  after {
+    testListener.onJobStartedCallback = None
+    testListener.onJobEndCallback = None
+    testListener.onStageEndCallback = None
+    testListener.onTaskEndCallback = None
+  }
+
+  it should "correctly calculate progress" in {
+    val executeCode =
+      """
+        |sc.parallelize(1 to 2, 2).map(i => (i, 1)).collect()
+      """.stripMargin
+    val stmtId = getStatementId
+
+    def verifyJobs(): Unit = {
+      testListener.statementToJobs.get(stmtId) should not be (None)
+
+      // One job will be submitted
+      testListener.statementToJobs(stmtId).size should be (1)
+      val jobId = testListener.statementToJobs(stmtId).head.jobId
+      testListener.jobIdToStatement(jobId) should be (stmtId)
+
+      // 1 stage will be generated
+      testListener.jobIdToStages(jobId).size should be (1)
+      val stageIds = testListener.jobIdToStages(jobId)
+
+      // 2 tasks per stage will be generated
+      stageIds.foreach { id =>
+        testListener.stageIdToTaskCount(id).currFinishedTasks should be (0)
+        testListener.stageIdToTaskCount(id).totalTasks should be (2)
+      }
+    }
+
+    var taskEndCalls = 0
+    def verifyTasks(): Unit = {
+      taskEndCalls += 1
+      testListener.progressOfStatement(stmtId) should be (taskEndCalls.toDouble / 2)
+    }
+
+    var stageEndCalls = 0
+    def verifyStages(): Unit = {
+      stageEndCalls += 1
+      testListener.progressOfStatement(stmtId) should be (stageEndCalls.toDouble / 1)
+    }
+
+    testListener.onJobStartedCallback = Some(verifyJobs)
+    testListener.onTaskEndCallback = Some(verifyTasks)
+    testListener.onStageEndCallback = Some(verifyStages)
+    sparkInterpreter.execute(stmtId, executeCode)
+
+    eventually(timeout(30 seconds), interval(100 millis)) {
+      testListener.progressOfStatement(stmtId) should be(1.0)
+    }
+  }
+
+  it should "not generate Spark jobs for plain Scala code" in {
+    val executeCode = """1 + 1"""
+    val stmtId = getStatementId
+
+    def verifyJobs(): Unit = {
+      fail("No job will be submitted")
+    }
+
+    testListener.onJobStartedCallback = Some(verifyJobs)
+    testListener.progressOfStatement(stmtId) should be (0.0)
+    sparkInterpreter.execute(stmtId, executeCode)
+    testListener.progressOfStatement(stmtId) should be (0.0)
+  }
+
+  it should "handle multiple jobs in one statement" in {
+    val executeCode =
+      """
+        |sc.parallelize(1 to 2, 2).map(i => (i, 1)).collect()
+        |sc.parallelize(1 to 2, 2).map(i => (i, 1)).collect()
+      """.stripMargin
+    val stmtId = getStatementId
+
+    var jobs = 0
+    def verifyJobs(): Unit = {
+      jobs += 1
+
+      testListener.statementToJobs.get(stmtId) should not be (None)
+      // One job will be submitted
+      testListener.statementToJobs(stmtId).size should be (jobs)
+      val jobId = testListener.statementToJobs(stmtId)(jobs - 1).jobId
+      testListener.jobIdToStatement(jobId) should be (stmtId)
+
+      // 1 stages will be generated
+      testListener.jobIdToStages(jobId).size should be (1)
+      val stageIds = testListener.jobIdToStages(jobId)
+
+      // 2 tasks per stage will be generated
+      stageIds.foreach { id =>
+        testListener.stageIdToTaskCount(id).currFinishedTasks should be (0)
+        testListener.stageIdToTaskCount(id).totalTasks should be (2)
+      }
+    }
+
+    val taskProgress = ArrayBuffer[Double]()
+    def verifyTasks(): Unit = {
+      taskProgress += testListener.progressOfStatement(stmtId)
+    }
+
+    val stageProgress = ArrayBuffer[Double]()
+    def verifyStages(): Unit = {
+      stageProgress += testListener.progressOfStatement(stmtId)
+    }
+
+    testListener.onJobStartedCallback = Some(verifyJobs)
+    testListener.onTaskEndCallback = Some(verifyTasks)
+    testListener.onStageEndCallback = Some(verifyStages)
+    sparkInterpreter.execute(stmtId, executeCode)
+
+    taskProgress.toArray should be (Array(0.5, 1.0, 0.75, 1.0))
+    stageProgress.toArray should be (Array(1.0, 1.0))
+
+    eventually(timeout(30 seconds), interval(100 millis)) {
+      testListener.progressOfStatement(stmtId) should be(1.0)
+    }
+  }
+
+  it should "remove old statement progress" in {
+    val executeCode =
+      """
+        |sc.parallelize(1 to 2, 2).map(i => (i, 1)).collect()
+      """.stripMargin
+    val stmtId = getStatementId
+
+    def onJobEnd(): Unit = {
+      testListener.statementToJobs(stmtId).size should be (1)
+      testListener.statementToJobs(stmtId).head.isCompleted should be (true)
+
+      testListener.statementToJobs.size should be (2)
+      testListener.statementToJobs.get(0) should be (None)
+      testListener.jobIdToStatement.filter(_._2 == 0) should be (Map.empty)
+    }
+
+    testListener.onJobEndCallback = Some(onJobEnd)
+    sparkInterpreter.execute(stmtId, executeCode)
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/70f23b90/rsc/src/main/java/com/cloudera/livy/rsc/RSCConf.java
----------------------------------------------------------------------
diff --git a/rsc/src/main/java/com/cloudera/livy/rsc/RSCConf.java b/rsc/src/main/java/com/cloudera/livy/rsc/RSCConf.java
index 11444e2..0d7b1c1 100644
--- a/rsc/src/main/java/com/cloudera/livy/rsc/RSCConf.java
+++ b/rsc/src/main/java/com/cloudera/livy/rsc/RSCConf.java
@@ -94,6 +94,10 @@ public class RSCConf extends ClientConf<RSCConf> {
     public Object dflt() { return dflt; }
   }
 
+  public RSCConf() {
+    this(new Properties());
+  }
+
   public RSCConf(Properties config) {
     super(config);
   }

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/70f23b90/rsc/src/main/java/com/cloudera/livy/rsc/driver/Statement.java
----------------------------------------------------------------------
diff --git a/rsc/src/main/java/com/cloudera/livy/rsc/driver/Statement.java b/rsc/src/main/java/com/cloudera/livy/rsc/driver/Statement.java
index c88514e..c1717a9 100644
--- a/rsc/src/main/java/com/cloudera/livy/rsc/driver/Statement.java
+++ b/rsc/src/main/java/com/cloudera/livy/rsc/driver/Statement.java
@@ -26,11 +26,13 @@ public class Statement {
   public final AtomicReference<StatementState> state;
   @JsonRawValue
   public volatile String output;
+  public double progress;
 
   public Statement(Integer id, StatementState state, String output) {
     this.id = id;
     this.state = new AtomicReference<>(state);
     this.output = output;
+    this.progress = 0.0;
   }
 
   public Statement() {
@@ -44,4 +46,12 @@ public class Statement {
     }
     return false;
   }
+
+  public void updateProgress(double p) {
+    if (this.state.get().isOneOf(StatementState.Cancelled, StatementState.Available)) {
+      this.progress = 1.0;
+    } else {
+      this.progress = p;
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/70f23b90/server/src/test/scala/com/cloudera/livy/server/interactive/InteractiveSessionServletSpec.scala
----------------------------------------------------------------------
diff --git a/server/src/test/scala/com/cloudera/livy/server/interactive/InteractiveSessionServletSpec.scala b/server/src/test/scala/com/cloudera/livy/server/interactive/InteractiveSessionServletSpec.scala
index 0a31194..63d605d 100644
--- a/server/src/test/scala/com/cloudera/livy/server/interactive/InteractiveSessionServletSpec.scala
+++ b/server/src/test/scala/com/cloudera/livy/server/interactive/InteractiveSessionServletSpec.scala
@@ -121,6 +121,7 @@ class InteractiveSessionServletSpec extends BaseInteractiveServletSpec {
 
     jpost[Map[String, Any]]("/0/statements", ExecuteRequest("foo")) { data =>
       data("id") should be (0)
+      data("progress") should be (0.0)
       data("output") shouldBe 1
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/70f23b90/server/src/test/scala/com/cloudera/livy/server/interactive/InteractiveSessionSpec.scala
----------------------------------------------------------------------
diff --git a/server/src/test/scala/com/cloudera/livy/server/interactive/InteractiveSessionSpec.scala b/server/src/test/scala/com/cloudera/livy/server/interactive/InteractiveSessionSpec.scala
index 146df9b..28d7157 100644
--- a/server/src/test/scala/com/cloudera/livy/server/interactive/InteractiveSessionSpec.scala
+++ b/server/src/test/scala/com/cloudera/livy/server/interactive/InteractiveSessionSpec.scala
@@ -209,6 +209,22 @@ class InteractiveSessionSpec extends FunSpec
       }
     }
 
+    withSession("should get statement progress along with statement result") { session =>
+      val code =
+        """
+          |from time import sleep
+          |sleep(3)
+        """.stripMargin
+      val statement = session.executeStatement(ExecuteRequest(code))
+      statement.progress should be (0.0)
+
+      eventually(timeout(10 seconds), interval(100 millis)) {
+        val s = session.getStatement(statement.id).get
+        s.state.get() shouldBe StatementState.Available
+        s.progress should be (1.0)
+      }
+    }
+
     withSession("should error out the session if the interpreter dies") { session =>
       session.executeStatement(ExecuteRequest("import os; os._exit(666)"))
       eventually(timeout(30 seconds), interval(100 millis)) {



[21/50] [abbrv] incubator-livy git commit: LIVY-240. Improve the session gc mechanism. (#277)

Posted by js...@apache.org.
LIVY-240. Improve the session gc mechanism. (#277)

Current session gc mechanism has some issues:
- Stopped session still needs to wait to timeout to gc-ed.
-Batch session will be gc-ed unexpectedly in run-time when timing out, which makes long running application impossible.
- Sometimes user doesn't want to stop idle sessions.

Changes of this commit:
- Never check the activity of batch session, which means batch session will only be gc-ed after stop.
- Add a configuration to turn off activity check for interactive session, which meets some usage scenarios.
- Add a configuration to control how long a finished session state will be kept in memory before cleaned out.

Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/bfdb5a19
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/bfdb5a19
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/bfdb5a19

Branch: refs/heads/master
Commit: bfdb5a1925327758b054d8f67191e2bf4bc2c2bb
Parents: 6bfe177
Author: Saisai Shao <sa...@gmail.com>
Authored: Thu Feb 23 06:05:54 2017 +0800
Committer: Alex Man <tc...@gmail.com>
Committed: Wed Feb 22 14:05:54 2017 -0800

----------------------------------------------------------------------
 conf/livy.conf                                  |  6 ++
 .../cloudera/livy/sessions/SessionState.scala   | 11 +++-
 .../main/scala/com/cloudera/livy/LivyConf.scala |  8 +++
 .../cloudera/livy/sessions/SessionManager.scala | 20 ++++++-
 .../livy/sessions/SessionManagerSpec.scala      | 58 +++++++++++++++++++-
 5 files changed, 97 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/bfdb5a19/conf/livy.conf
----------------------------------------------------------------------
diff --git a/conf/livy.conf b/conf/livy.conf
index a238f37..c23aab2 100644
--- a/conf/livy.conf
+++ b/conf/livy.conf
@@ -16,8 +16,14 @@
 # What spark deploy mode Livy sessions should use.
 # livy.spark.deployMode =
 
+# Enabled to check whether timeout Livy sessions should be stopped.
+# livy.server.session.timeout-check = true
+
 # Time in milliseconds on how long Livy will wait before timing out an idle session.
 # livy.server.session.timeout = 1h
+#
+# How long a finished session state should be kept in LivyServer for query.
+# livy.server.session.state-retain.sec = 600s
 
 # If livy should impersonate the requesting users when creating a new session.
 # livy.impersonation.enabled = true

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/bfdb5a19/core/src/main/scala/com/cloudera/livy/sessions/SessionState.scala
----------------------------------------------------------------------
diff --git a/core/src/main/scala/com/cloudera/livy/sessions/SessionState.scala b/core/src/main/scala/com/cloudera/livy/sessions/SessionState.scala
index 975d592..ac4bf9b 100644
--- a/core/src/main/scala/com/cloudera/livy/sessions/SessionState.scala
+++ b/core/src/main/scala/com/cloudera/livy/sessions/SessionState.scala
@@ -23,6 +23,11 @@ sealed trait SessionState {
   def isActive: Boolean
 }
 
+sealed trait FinishedSessionState extends SessionState {
+  /** When session is finished. */
+  def time: Long
+}
+
 object SessionState {
 
   def apply(s: String): SessionState = {
@@ -83,19 +88,19 @@ object SessionState {
     override def toString: String = "shutting_down"
   }
 
-  case class Error(time: Long = System.nanoTime()) extends SessionState {
+  case class Error(time: Long = System.nanoTime()) extends FinishedSessionState {
     override def isActive: Boolean = true
 
     override def toString: String = "error"
   }
 
-  case class Dead(time: Long = System.nanoTime()) extends SessionState {
+  case class Dead(time: Long = System.nanoTime()) extends FinishedSessionState {
     override def isActive: Boolean = false
 
     override def toString: String = "dead"
   }
 
-  case class Success(time: Long = System.nanoTime()) extends SessionState {
+  case class Success(time: Long = System.nanoTime()) extends FinishedSessionState {
     override def isActive: Boolean = false
 
     override def toString: String = "success"

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/bfdb5a19/server/src/main/scala/com/cloudera/livy/LivyConf.scala
----------------------------------------------------------------------
diff --git a/server/src/main/scala/com/cloudera/livy/LivyConf.scala b/server/src/main/scala/com/cloudera/livy/LivyConf.scala
index ab0e52b..6562b03 100644
--- a/server/src/main/scala/com/cloudera/livy/LivyConf.scala
+++ b/server/src/main/scala/com/cloudera/livy/LivyConf.scala
@@ -124,6 +124,14 @@ object LivyConf {
   // how often to check livy session leakage
   val YARN_APP_LEAKAGE_CHECK_INTERVAL = Entry("livy.server.yarn.app-leakage.check_interval", "60s")
 
+  // Whether session timeout should be checked, by default it will be checked, which means inactive
+  // session will be stopped after "livy.server.session.timeout"
+  val SESSION_TIMEOUT_CHECK = Entry("livy.server.session.timeout-check", true)
+  // How long will an inactive session be gc-ed.
+  val SESSION_TIMEOUT = Entry("livy.server.session.timeout", "1h")
+  // How long a finished session state will be kept in memory
+  val SESSION_STATE_RETAIN_TIME = Entry("livy.server.session.state-retain.sec", "600s")
+
   val SPARK_MASTER = "spark.master"
   val SPARK_DEPLOY_MODE = "spark.submit.deployMode"
   val SPARK_JARS = "spark.jars"

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/bfdb5a19/server/src/main/scala/com/cloudera/livy/sessions/SessionManager.scala
----------------------------------------------------------------------
diff --git a/server/src/main/scala/com/cloudera/livy/sessions/SessionManager.scala b/server/src/main/scala/com/cloudera/livy/sessions/SessionManager.scala
index a50bd41..e177108 100644
--- a/server/src/main/scala/com/cloudera/livy/sessions/SessionManager.scala
+++ b/server/src/main/scala/com/cloudera/livy/sessions/SessionManager.scala
@@ -36,7 +36,6 @@ import com.cloudera.livy.sessions.Session.RecoveryMetadata
 object SessionManager {
   val SESSION_RECOVERY_MODE_OFF = "off"
   val SESSION_RECOVERY_MODE_RECOVERY = "recovery"
-  val SESSION_TIMEOUT = LivyConf.Entry("livy.server.session.timeout", "1h")
 }
 
 class BatchSessionManager(
@@ -76,8 +75,11 @@ class SessionManager[S <: Session, R <: RecoveryMetadata : ClassTag](
   protected[this] final val idCounter = new AtomicInteger(0)
   protected[this] final val sessions = mutable.LinkedHashMap[Int, S]()
 
+  private[this] final val sessionTimeoutCheck = livyConf.getBoolean(LivyConf.SESSION_TIMEOUT_CHECK)
   private[this] final val sessionTimeout =
-    TimeUnit.MILLISECONDS.toNanos(livyConf.getTimeAsMs(SessionManager.SESSION_TIMEOUT))
+    TimeUnit.MILLISECONDS.toNanos(livyConf.getTimeAsMs(LivyConf.SESSION_TIMEOUT))
+  private[this] final val sessionStateRetainedInSec =
+    TimeUnit.MILLISECONDS.toNanos(livyConf.getTimeAsMs(LivyConf.SESSION_STATE_RETAIN_TIME))
 
   mockSessions.getOrElse(recover()).foreach(register)
   new GarbageCollector().start()
@@ -134,6 +136,20 @@ class SessionManager[S <: Session, R <: RecoveryMetadata : ClassTag](
     def expired(session: Session): Boolean = {
       val currentTime = System.nanoTime()
       currentTime - session.lastActivity > sessionTimeout
+      session.state match {
+        case s: FinishedSessionState =>
+          val currentTime = System.nanoTime()
+          currentTime - s.time > sessionStateRetainedInSec
+        case _ =>
+          if (!sessionTimeoutCheck) {
+            false
+          } else if (session.isInstanceOf[BatchSession]) {
+            false
+          } else {
+            val currentTime = System.nanoTime()
+            currentTime - session.lastActivity > sessionTimeout
+          }
+      }
     }
 
     Future.sequence(all().filter(expired).map(delete))

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/bfdb5a19/server/src/test/scala/com/cloudera/livy/sessions/SessionManagerSpec.scala
----------------------------------------------------------------------
diff --git a/server/src/test/scala/com/cloudera/livy/sessions/SessionManagerSpec.scala b/server/src/test/scala/com/cloudera/livy/sessions/SessionManagerSpec.scala
index 8195bf8..241ba27 100644
--- a/server/src/test/scala/com/cloudera/livy/sessions/SessionManagerSpec.scala
+++ b/server/src/test/scala/com/cloudera/livy/sessions/SessionManagerSpec.scala
@@ -30,14 +30,17 @@ import org.scalatest.mock.MockitoSugar.mock
 
 import com.cloudera.livy.{LivyBaseUnitTestSuite, LivyConf}
 import com.cloudera.livy.server.batch.{BatchRecoveryMetadata, BatchSession}
+import com.cloudera.livy.server.interactive.InteractiveSession
 import com.cloudera.livy.server.recovery.SessionStore
 import com.cloudera.livy.sessions.Session.RecoveryMetadata
 
 class SessionManagerSpec extends FunSpec with Matchers with LivyBaseUnitTestSuite {
+  implicit def executor: ExecutionContext = ExecutionContext.global
+
   describe("SessionManager") {
     it("should garbage collect old sessions") {
       val livyConf = new LivyConf()
-      livyConf.set(SessionManager.SESSION_TIMEOUT, "100ms")
+      livyConf.set(LivyConf.SESSION_TIMEOUT, "100ms")
       val manager = new SessionManager[MockSession, RecoveryMetadata](
         livyConf,
         { _ => assert(false).asInstanceOf[MockSession] },
@@ -51,6 +54,59 @@ class SessionManagerSpec extends FunSpec with Matchers with LivyBaseUnitTestSuit
         manager.get(session.id) should be(None)
       }
     }
+
+    it("batch session should not be gc-ed until application is finished") {
+      val sessionId = 24
+      val session = mock[BatchSession]
+      when(session.id).thenReturn(sessionId)
+      when(session.stop()).thenReturn(Future {})
+      when(session.lastActivity).thenReturn(System.nanoTime())
+
+      val conf = new LivyConf().set(LivyConf.SESSION_STATE_RETAIN_TIME, "1s")
+      val sm = new BatchSessionManager(conf, mock[SessionStore], Some(Seq(session)))
+      testSessionGC(session, sm)
+    }
+
+    it("interactive session should not gc-ed if session timeout check is off") {
+      val sessionId = 24
+      val session = mock[InteractiveSession]
+      when(session.id).thenReturn(sessionId)
+      when(session.stop()).thenReturn(Future {})
+      when(session.lastActivity).thenReturn(System.nanoTime())
+
+      val conf = new LivyConf().set(LivyConf.SESSION_TIMEOUT_CHECK, false)
+        .set(LivyConf.SESSION_STATE_RETAIN_TIME, "1s")
+      val sm = new InteractiveSessionManager(conf, mock[SessionStore], Some(Seq(session)))
+      testSessionGC(session, sm)
+    }
+
+    def testSessionGC(session: Session, sm: SessionManager[_, _]): Unit = {
+
+      def changeStateAndCheck(s: SessionState)(fn: SessionManager[_, _] => Unit): Unit = {
+        when(session.state).thenReturn(s)
+        Await.result(sm.collectGarbage(), Duration.Inf)
+        fn(sm)
+      }
+
+      // Batch session should not be gc-ed when alive
+      for (s <- Seq(SessionState.Running(),
+        SessionState.Idle(),
+        SessionState.Recovering(),
+        SessionState.NotStarted(),
+        SessionState.Busy(),
+        SessionState.ShuttingDown())) {
+        changeStateAndCheck(s) { sm => sm.get(session.id) should be (Some(session)) }
+      }
+
+      // Stopped session should be gc-ed after retained timeout
+      for (s <- Seq(SessionState.Error(),
+        SessionState.Success(),
+        SessionState.Dead())) {
+        eventually(timeout(30 seconds), interval(100 millis)) {
+          changeStateAndCheck(s) { sm => sm.get(session.id) should be (None) }
+        }
+      }
+    }
   }
 
   describe("BatchSessionManager") {


[23/50] [abbrv] incubator-livy git commit: LIVY-303. Add statement retention mechanism. (#279)

Posted by js...@apache.org.
LIVY-303. Add statement retention mechanism. (#279)

To avoid OOM for long running sessions, introduce statement retention mechanism to remove old statements.

Also refactor the statement state code to make it more clear.

Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/932d397b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/932d397b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/932d397b

Branch: refs/heads/master
Commit: 932d397bf6d6fe7ed9df455f8230227cb0e3761b
Parents: 2aa910c
Author: Saisai Shao <sa...@gmail.com>
Authored: Sat Feb 25 02:24:05 2017 +0800
Committer: Alex Man <al...@users.noreply.github.com>
Committed: Fri Feb 24 10:24:05 2017 -0800

----------------------------------------------------------------------
 .../scala/com/cloudera/livy/repl/Session.scala  | 91 +++++++++++---------
 .../com/cloudera/livy/repl/SessionSpec.scala    | 31 +++++++
 .../java/com/cloudera/livy/rsc/RSCConf.java     |  4 +-
 .../com/cloudera/livy/rsc/driver/Statement.java |  8 ++
 .../livy/rsc/driver/StatementState.java         | 46 ++++++++++
 5 files changed, 140 insertions(+), 40 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/932d397b/repl/src/main/scala/com/cloudera/livy/repl/Session.scala
----------------------------------------------------------------------
diff --git a/repl/src/main/scala/com/cloudera/livy/repl/Session.scala b/repl/src/main/scala/com/cloudera/livy/repl/Session.scala
index f927e73..bf1f3b4 100644
--- a/repl/src/main/scala/com/cloudera/livy/repl/Session.scala
+++ b/repl/src/main/scala/com/cloudera/livy/repl/Session.scala
@@ -18,10 +18,12 @@
 
 package com.cloudera.livy.repl
 
+import java.util.{LinkedHashMap => JLinkedHashMap}
+import java.util.Map.Entry
 import java.util.concurrent.Executors
 import java.util.concurrent.atomic.AtomicInteger
 
-import scala.collection.concurrent.TrieMap
+import scala.collection.JavaConverters._
 import scala.concurrent.{ExecutionContext, Future}
 import scala.concurrent.duration._
 
@@ -53,7 +55,7 @@ class Session(
   extends Logging {
   import Session._
 
-  private implicit val executor = ExecutionContext.fromExecutorService(
+  private val interpreterExecutor = ExecutionContext.fromExecutorService(
     Executors.newSingleThreadExecutor())
 
   private val cancelExecutor = ExecutionContext.fromExecutorService(
@@ -64,7 +66,15 @@ class Session(
   @volatile private[repl] var _sc: Option[SparkContext] = None
 
   private var _state: SessionState = SessionState.NotStarted()
-  private val _statements = TrieMap[Int, Statement]()
+
+  // Number of statements kept in driver's memory
+  private val numRetainedStatements = livyConf.getInt(RSCConf.Entry.RETAINED_STATEMENT_NUMBER)
+
+  private val _statements = new JLinkedHashMap[Int, Statement] {
+    protected override def removeEldestEntry(eldest: Entry[Int, Statement]): Boolean = {
+      size() > numRetainedStatements
+    }
+  }.asScala
 
   private val newStatementId = new AtomicInteger(0)
 
@@ -77,9 +87,9 @@ class Session(
       _sc = Option(sc)
       changeState(SessionState.Idle())
       sc
-    }
+    }(interpreterExecutor)
 
-    future.onFailure { case _ => changeState(SessionState.Error()) }
+    future.onFailure { case _ => changeState(SessionState.Error()) }(interpreterExecutor)
     future
   }
 
@@ -87,72 +97,75 @@ class Session(
 
   def state: SessionState = _state
 
-  def statements: collection.Map[Int, Statement] = _statements.readOnlySnapshot()
+  def statements: collection.Map[Int, Statement] = _statements.synchronized {
+    _statements.toMap
+  }
 
   def execute(code: String): Int = {
     val statementId = newStatementId.getAndIncrement()
-    _statements(statementId) = new Statement(statementId, StatementState.Waiting, null)
+    val statement = new Statement(statementId, StatementState.Waiting, null)
+    _statements.synchronized { _statements(statementId) = statement }
 
     Future {
       setJobGroup(statementId)
-      _statements(statementId).state.compareAndSet(StatementState.Waiting, StatementState.Running)
+      statement.compareAndTransit(StatementState.Waiting, StatementState.Running)
 
-      val executeResult = if (_statements(statementId).state.get() == StatementState.Running) {
-        executeCode(statementId, code)
-      } else {
-        null
+      if (statement.state.get() == StatementState.Running) {
+        statement.output = executeCode(statementId, code)
       }
 
-      _statements(statementId).output = executeResult
-      _statements(statementId).state.compareAndSet(StatementState.Running, StatementState.Available)
-      _statements(statementId).state.compareAndSet(
-        StatementState.Cancelling, StatementState.Cancelled)
-    }
+      statement.compareAndTransit(StatementState.Running, StatementState.Available)
+      statement.compareAndTransit(StatementState.Cancelling, StatementState.Cancelled)
+    }(interpreterExecutor)
 
     statementId
   }
 
   def cancel(statementId: Int): Unit = {
-    if (!_statements.contains(statementId)) {
+    val statementOpt = _statements.synchronized { _statements.get(statementId) }
+    if (statementOpt.isEmpty) {
       return
     }
 
-    if (_statements(statementId).state.get() == StatementState.Available ||
-      _statements(statementId).state.get() == StatementState.Cancelled ||
-      _statements(statementId).state.get() == StatementState.Cancelling) {
+    val statement = statementOpt.get
+    if (statement.state.get().isOneOf(
+      StatementState.Available, StatementState.Cancelled, StatementState.Cancelling)) {
       return
     } else {
       // statement 1 is running and statement 2 is waiting. User cancels
       // statement 2 then cancels statement 1. The 2nd cancel call will loop and block the 1st
       // cancel call since cancelExecutor is single threaded. To avoid this, set the statement
       // state to cancelled when cancelling a waiting statement.
-      _statements(statementId).state.compareAndSet(StatementState.Waiting, StatementState.Cancelled)
-      _statements(statementId).state.compareAndSet(
-        StatementState.Running, StatementState.Cancelling)
+      statement.compareAndTransit(StatementState.Waiting, StatementState.Cancelled)
+      statement.compareAndTransit(StatementState.Running, StatementState.Cancelling)
     }
 
     info(s"Cancelling statement $statementId...")
 
-      Future {
-        val deadline = livyConf.getTimeAsMs(RSCConf.Entry.JOB_CANCEL_TIMEOUT).millis.fromNow
-        while (_statements(statementId).state.get() == StatementState.Cancelling) {
-          if (deadline.isOverdue()) {
-            info(s"Failed to cancel statement $statementId.")
-            _statements(statementId).state.compareAndSet(
-              StatementState.Cancelling, StatementState.Cancelled)
-          } else {
-            _sc.foreach(_.cancelJobGroup(statementId.toString))
+    Future {
+      val deadline = livyConf.getTimeAsMs(RSCConf.Entry.JOB_CANCEL_TIMEOUT).millis.fromNow
+
+      while (statement.state.get() == StatementState.Cancelling) {
+        if (deadline.isOverdue()) {
+          info(s"Failed to cancel statement $statementId.")
+          statement.compareAndTransit(StatementState.Cancelling, StatementState.Cancelled)
+        } else {
+          _sc.foreach(_.cancelJobGroup(statementId.toString))
+          if (statement.state.get() == StatementState.Cancelling) {
+            Thread.sleep(livyConf.getTimeAsMs(RSCConf.Entry.JOB_CANCEL_TRIGGER_INTERVAL))
           }
-          Thread.sleep(livyConf.getTimeAsMs(RSCConf.Entry.JOB_CANCEL_TRIGGER_INTERVAL))
-        }
-        if (_statements(statementId).state.get() == StatementState.Cancelled) {
-          info(s"Statement $statementId cancelled.")
         }
-      }(cancelExecutor)
+      }
+
+      if (statement.state.get() == StatementState.Cancelled) {
+        info(s"Statement $statementId cancelled.")
+      }
+    }(cancelExecutor)
   }
 
   def close(): Unit = {
-    executor.shutdown()
+    interpreterExecutor.shutdown()
+    cancelExecutor.shutdown()
     interpreter.close()
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/932d397b/repl/src/test/scala/com/cloudera/livy/repl/SessionSpec.scala
----------------------------------------------------------------------
diff --git a/repl/src/test/scala/com/cloudera/livy/repl/SessionSpec.scala b/repl/src/test/scala/com/cloudera/livy/repl/SessionSpec.scala
index 6329365..203d15e 100644
--- a/repl/src/test/scala/com/cloudera/livy/repl/SessionSpec.scala
+++ b/repl/src/test/scala/com/cloudera/livy/repl/SessionSpec.scala
@@ -92,5 +92,36 @@ class SessionSpec extends FunSpec with Eventually with LivyBaseUnitTestSuite {
         actualStateTransitions.toArray shouldBe expectedStateTransitions
       }
     }
+
+    it("should remove old statements when reaching threshold") {
+      val interpreter = mock[Interpreter]
+      when(interpreter.kind).thenAnswer(new Answer[String] {
+        override def answer(invocationOnMock: InvocationOnMock): String = "spark"
+      })
+
+      rscConf.set(RSCConf.Entry.RETAINED_STATEMENT_NUMBER, 2)
+      val session = new Session(rscConf, interpreter)
+      session.start()
+
+      session.statements.size should be (0)
+      session.execute("")
+      session.statements.size should be (1)
+      session.statements.map(_._1).toSet should be (Set(0))
+      session.execute("")
+      session.statements.size should be (2)
+      session.statements.map(_._1).toSet should be (Set(0, 1))
+      session.execute("")
+      eventually {
+        session.statements.size should be (2)
+        session.statements.map(_._1).toSet should be (Set(1, 2))
+      }
+
+      // Continue submitting statements, total statements in memory should be 2.
+      session.execute("")
+      eventually {
+        session.statements.size should be (2)
+        session.statements.map(_._1).toSet should be (Set(2, 3))
+      }
+    }
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/932d397b/rsc/src/main/java/com/cloudera/livy/rsc/RSCConf.java
----------------------------------------------------------------------
diff --git a/rsc/src/main/java/com/cloudera/livy/rsc/RSCConf.java b/rsc/src/main/java/com/cloudera/livy/rsc/RSCConf.java
index 1520990..11444e2 100644
--- a/rsc/src/main/java/com/cloudera/livy/rsc/RSCConf.java
+++ b/rsc/src/main/java/com/cloudera/livy/rsc/RSCConf.java
@@ -75,7 +75,9 @@ public class RSCConf extends ClientConf<RSCConf> {
     TEST_STUCK_START_DRIVER("test.do_not_use.stuck_start_driver", false),
 
     JOB_CANCEL_TRIGGER_INTERVAL("job_cancel.trigger_interval", "100ms"),
-    JOB_CANCEL_TIMEOUT("job_cancel.timeout", "30s");
+    JOB_CANCEL_TIMEOUT("job_cancel.timeout", "30s"),
+
+    RETAINED_STATEMENT_NUMBER("retained_statements", 100);
 
     private final String key;
     private final Object dflt;

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/932d397b/rsc/src/main/java/com/cloudera/livy/rsc/driver/Statement.java
----------------------------------------------------------------------
diff --git a/rsc/src/main/java/com/cloudera/livy/rsc/driver/Statement.java b/rsc/src/main/java/com/cloudera/livy/rsc/driver/Statement.java
index 512b238..c88514e 100644
--- a/rsc/src/main/java/com/cloudera/livy/rsc/driver/Statement.java
+++ b/rsc/src/main/java/com/cloudera/livy/rsc/driver/Statement.java
@@ -36,4 +36,12 @@ public class Statement {
   public Statement() {
     this(null, null, null);
   }
+
+  public boolean compareAndTransit(final StatementState from, final StatementState to) {
+    if (state.compareAndSet(from, to)) {
+      StatementState.validate(from, to);
+      return true;
+    }
+    return false;
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/932d397b/rsc/src/main/java/com/cloudera/livy/rsc/driver/StatementState.java
----------------------------------------------------------------------
diff --git a/rsc/src/main/java/com/cloudera/livy/rsc/driver/StatementState.java b/rsc/src/main/java/com/cloudera/livy/rsc/driver/StatementState.java
index b5414ab..5e084bc 100644
--- a/rsc/src/main/java/com/cloudera/livy/rsc/driver/StatementState.java
+++ b/rsc/src/main/java/com/cloudera/livy/rsc/driver/StatementState.java
@@ -17,7 +17,12 @@
 
 package com.cloudera.livy.rsc.driver;
 
+import java.util.*;
+
 import com.fasterxml.jackson.annotation.JsonValue;
+import com.google.common.base.Preconditions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public enum StatementState {
   Waiting("waiting"),
@@ -26,6 +31,8 @@ public enum StatementState {
   Cancelling("cancelling"),
   Cancelled("cancelled");
 
+  private static final Logger LOG = LoggerFactory.getLogger(StatementState.class);
+
   private final String state;
 
   StatementState(final String text) {
@@ -37,4 +44,43 @@ public enum StatementState {
   public String toString() {
       return state;
   }
+
+  public boolean isOneOf(StatementState... states) {
+    for (StatementState s : states) {
+      if (s == this) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  private static final Map<StatementState, List<StatementState>> PREDECESSORS;
+
+  static void put(StatementState key,
+    Map<StatementState, List<StatementState>> map,
+    StatementState... values) {
+    map.put(key, Collections.unmodifiableList(Arrays.asList(values)));
+  }
+
+  static {
+    final Map<StatementState, List<StatementState>> predecessors =
+      new EnumMap<>(StatementState.class);
+    put(Waiting, predecessors);
+    put(Running, predecessors, Waiting);
+    put(Available, predecessors, Running);
+    put(Cancelling, predecessors, Running);
+    put(Cancelled, predecessors, Waiting, Cancelling);
+
+    PREDECESSORS = Collections.unmodifiableMap(predecessors);
+  }
+
+  static boolean isValid(StatementState from, StatementState to) {
+    return PREDECESSORS.get(to).contains(from);
+  }
+
+  static void validate(StatementState from, StatementState to) {
+    LOG.debug("{} -> {}", from, to);
+
+    Preconditions.checkState(isValid(from, to), "Illegal Transition: %s -> %s", from, to);
+  }
 }


[04/50] [abbrv] incubator-livy git commit: Merge pull request #237 from jerryshao/LIVY-255

Posted by js...@apache.org.
Merge pull request #237 from jerryshao/LIVY-255

LIVY-255. Update the docs for Livy build and Spark2 support

Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/dbdad9d3
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/dbdad9d3
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/dbdad9d3

Branch: refs/heads/revert-237-LIVY-255
Commit: dbdad9d37dfdf131b735df44b79a82837e53db5a
Parents: b8a0839 2e812a7
Author: Jeff Zhang <zj...@gmail.com>
Authored: Wed Nov 30 11:01:43 2016 +0800
Committer: GitHub <no...@github.com>
Committed: Wed Nov 30 11:01:43 2016 +0800

----------------------------------------------------------------------
 README.rst | 25 +++++++++++++------------
 1 file changed, 13 insertions(+), 12 deletions(-)
----------------------------------------------------------------------



[22/50] [abbrv] incubator-livy git commit: Minor. Ignore empty string in configuration join. (#299)

Posted by js...@apache.org.
Minor. Ignore empty string in configuration join. (#299)



Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/2aa910c9
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/2aa910c9
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/2aa910c9

Branch: refs/heads/master
Commit: 2aa910c9e148359b02965e5bc69341f7ac73b7b8
Parents: bfdb5a1
Author: Saisai Shao <sa...@gmail.com>
Authored: Fri Feb 24 04:18:05 2017 +0800
Committer: Alex Man <al...@users.noreply.github.com>
Committed: Thu Feb 23 12:18:05 2017 -0800

----------------------------------------------------------------------
 rsc/src/main/java/com/cloudera/livy/rsc/Utils.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/2aa910c9/rsc/src/main/java/com/cloudera/livy/rsc/Utils.java
----------------------------------------------------------------------
diff --git a/rsc/src/main/java/com/cloudera/livy/rsc/Utils.java b/rsc/src/main/java/com/cloudera/livy/rsc/Utils.java
index aa4efae..993ea1e 100644
--- a/rsc/src/main/java/com/cloudera/livy/rsc/Utils.java
+++ b/rsc/src/main/java/com/cloudera/livy/rsc/Utils.java
@@ -80,7 +80,7 @@ public class Utils {
   public static String join(Iterable<String> strs, String sep) {
     StringBuilder sb = new StringBuilder();
     for (String s : strs) {
-      if (s != null) {
+      if (s != null && !s.isEmpty()) {
         sb.append(s).append(sep);
       }
     }


[24/50] [abbrv] incubator-livy git commit: LIVY-293: Redirect spark-submit log to REST response Log field for interactive sessions. (#297)

Posted by js...@apache.org.
LIVY-293: Redirect spark-submit log to REST response Log field for interactive sessions. (#297)

Passing driverProcess to SparkApp for interactive sessions so session/log will return spark-submit log.

Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/d74d5a9c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/d74d5a9c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/d74d5a9c

Branch: refs/heads/master
Commit: d74d5a9cdaf07fa9e6f7d1fe8ebfa161572fd81a
Parents: 932d397
Author: Praveen Kanamarlapudi <kp...@outlook.com>
Authored: Mon Feb 27 14:39:16 2017 -0800
Committer: Alex Man <al...@users.noreply.github.com>
Committed: Mon Feb 27 14:39:16 2017 -0800

----------------------------------------------------------------------
 .../com/cloudera/livy/rsc/ContextLauncher.java  | 62 +-------------------
 .../cloudera/livy/rsc/DriverProcessInfo.java    | 42 +++++++++++++
 .../java/com/cloudera/livy/rsc/RSCClient.java   |  8 ++-
 .../com/cloudera/livy/rsc/RSCClientFactory.java |  7 ++-
 .../server/interactive/InteractiveSession.scala |  5 +-
 .../livy/utils/LineBufferedStream.scala         |  2 +-
 .../com/cloudera/livy/utils/SparkYarnApp.scala  |  4 +-
 .../cloudera/livy/utils/SparkYarnAppSpec.scala  |  8 ++-
 8 files changed, 70 insertions(+), 68 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/d74d5a9c/rsc/src/main/java/com/cloudera/livy/rsc/ContextLauncher.java
----------------------------------------------------------------------
diff --git a/rsc/src/main/java/com/cloudera/livy/rsc/ContextLauncher.java b/rsc/src/main/java/com/cloudera/livy/rsc/ContextLauncher.java
index eceb419..9a5e447 100644
--- a/rsc/src/main/java/com/cloudera/livy/rsc/ContextLauncher.java
+++ b/rsc/src/main/java/com/cloudera/livy/rsc/ContextLauncher.java
@@ -69,10 +69,10 @@ class ContextLauncher {
   private static final String SPARK_ARCHIVES_KEY = "spark.yarn.dist.archives";
   private static final String SPARK_HOME_ENV = "SPARK_HOME";
 
-  static Promise<ContextInfo> create(RSCClientFactory factory, RSCConf conf)
+  static DriverProcessInfo create(RSCClientFactory factory, RSCConf conf)
       throws IOException {
     ContextLauncher launcher = new ContextLauncher(factory, conf);
-    return launcher.promise;
+    return new DriverProcessInfo(launcher.promise, launcher.child.child);
   }
 
   private final Promise<ContextInfo> promise;
@@ -304,33 +304,6 @@ class ContextLauncher {
     return file;
   }
 
-  private static class Redirector implements Runnable {
-
-    private final BufferedReader in;
-
-    Redirector(InputStream in) {
-      this.in = new BufferedReader(new InputStreamReader(in));
-    }
-
-    @Override
-    public void run() {
-      try {
-        String line = null;
-        while ((line = in.readLine()) != null) {
-          LOG.info(line);
-        }
-      } catch (Exception e) {
-        LOG.warn("Error in redirector thread.", e);
-      }
-
-      try {
-        in.close();
-      } catch (IOException ioe) {
-        LOG.warn("Error closing child stream.", ioe);
-      }
-    }
-
-  }
 
   private class RegistrationHandler extends BaseProtocol
     implements RpcServer.ClientCallback {
@@ -383,8 +356,6 @@ class ContextLauncher {
     private final Promise<?> promise;
     private final Process child;
     private final Thread monitor;
-    private final Thread stdout;
-    private final Thread stderr;
     private final File confFile;
 
     public ChildProcess(RSCConf conf, Promise<?> promise, Runnable child, File confFile) {
@@ -392,8 +363,6 @@ class ContextLauncher {
       this.promise = promise;
       this.monitor = monitor(child, CHILD_IDS.incrementAndGet());
       this.child = null;
-      this.stdout = null;
-      this.stderr = null;
       this.confFile = confFile;
     }
 
@@ -402,8 +371,6 @@ class ContextLauncher {
       this.conf = conf;
       this.promise = promise;
       this.child = childProc;
-      this.stdout = redirect("stdout-redir-" + childId, child.getInputStream());
-      this.stderr = redirect("stderr-redir-" + childId, child.getErrorStream());
       this.confFile = confFile;
 
       Runnable monitorTask = new Runnable() {
@@ -450,23 +417,6 @@ class ContextLauncher {
     }
 
     public void detach() {
-      if (stdout != null) {
-        stdout.interrupt();
-        try {
-          stdout.join(conf.getTimeAsMs(CLIENT_SHUTDOWN_TIMEOUT));
-        } catch (InterruptedException ie) {
-          LOG.info("Interrupted while waiting for child stdout to finish.");
-        }
-      }
-      if (stderr != null) {
-        stderr.interrupt();
-        try {
-          stderr.join(conf.getTimeAsMs(CLIENT_SHUTDOWN_TIMEOUT));
-        } catch (InterruptedException ie) {
-          LOG.info("Interrupted while waiting for child stderr to finish.");
-        }
-      }
-
       try {
         monitor.join(conf.getTimeAsMs(CLIENT_SHUTDOWN_TIMEOUT));
       } catch (InterruptedException ie) {
@@ -474,14 +424,6 @@ class ContextLauncher {
       }
     }
 
-    private Thread redirect(String name, InputStream in) {
-      Thread thread = new Thread(new Redirector(in));
-      thread.setName(name);
-      thread.setDaemon(true);
-      thread.start();
-      return thread;
-    }
-
     private Thread monitor(final Runnable task, int childId) {
       Runnable wrappedTask = new Runnable() {
         @Override

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/d74d5a9c/rsc/src/main/java/com/cloudera/livy/rsc/DriverProcessInfo.java
----------------------------------------------------------------------
diff --git a/rsc/src/main/java/com/cloudera/livy/rsc/DriverProcessInfo.java b/rsc/src/main/java/com/cloudera/livy/rsc/DriverProcessInfo.java
new file mode 100644
index 0000000..a224fd6
--- /dev/null
+++ b/rsc/src/main/java/com/cloudera/livy/rsc/DriverProcessInfo.java
@@ -0,0 +1,42 @@
+/*
+ * 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 com.cloudera.livy.rsc;
+
+import io.netty.util.concurrent.Promise;
+
+/**
+ * Information about driver process and @{@link ContextInfo}
+ */
+public class DriverProcessInfo {
+
+  private Promise<ContextInfo> contextInfo;
+  private transient Process driverProcess;
+
+  public DriverProcessInfo(Promise<ContextInfo> contextInfo, Process driverProcess) {
+    this.contextInfo = contextInfo;
+    this.driverProcess = driverProcess;
+  }
+
+  public Promise<ContextInfo> getContextInfo() {
+    return contextInfo;
+  }
+
+  public Process getDriverProcess() {
+    return driverProcess;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/d74d5a9c/rsc/src/main/java/com/cloudera/livy/rsc/RSCClient.java
----------------------------------------------------------------------
diff --git a/rsc/src/main/java/com/cloudera/livy/rsc/RSCClient.java b/rsc/src/main/java/com/cloudera/livy/rsc/RSCClient.java
index 11f45b6..11cb0f6 100644
--- a/rsc/src/main/java/com/cloudera/livy/rsc/RSCClient.java
+++ b/rsc/src/main/java/com/cloudera/livy/rsc/RSCClient.java
@@ -60,12 +60,14 @@ public class RSCClient implements LivyClient {
   private final Promise<URI> serverUriPromise;
 
   private ContextInfo contextInfo;
+  private Process driverProcess;
   private volatile boolean isAlive;
   private volatile String replState;
 
-  RSCClient(RSCConf conf, Promise<ContextInfo> ctx) throws IOException {
+  RSCClient(RSCConf conf, Promise<ContextInfo> ctx, Process driverProcess) throws IOException {
     this.conf = conf;
     this.contextInfoPromise = ctx;
+    this.driverProcess = driverProcess;
     this.jobs = new ConcurrentHashMap<>();
     this.protocol = new ClientProtocol();
     this.driverRpc = ImmediateEventExecutor.INSTANCE.newPromise();
@@ -98,6 +100,10 @@ public class RSCClient implements LivyClient {
     return isAlive;
   }
 
+  public Process getDriverProcess() {
+    return driverProcess;
+  }
+
   private synchronized void connectToContext(final ContextInfo info) throws Exception {
     this.contextInfo = info;
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/d74d5a9c/rsc/src/main/java/com/cloudera/livy/rsc/RSCClientFactory.java
----------------------------------------------------------------------
diff --git a/rsc/src/main/java/com/cloudera/livy/rsc/RSCClientFactory.java b/rsc/src/main/java/com/cloudera/livy/rsc/RSCClientFactory.java
index d50c62e..27540bb 100644
--- a/rsc/src/main/java/com/cloudera/livy/rsc/RSCClientFactory.java
+++ b/rsc/src/main/java/com/cloudera/livy/rsc/RSCClientFactory.java
@@ -57,14 +57,17 @@ public final class RSCClientFactory implements LivyClientFactory {
     boolean needsServer = false;
     try {
       Promise<ContextInfo> info;
+      Process driverProcess = null;
       if (uri.getUserInfo() != null && uri.getHost() != null && uri.getPort() > 0) {
         info = createContextInfo(uri);
       } else {
         needsServer = true;
         ref(lconf);
-        info = ContextLauncher.create(this, lconf);
+        DriverProcessInfo processInfo = ContextLauncher.create(this, lconf);
+        info = processInfo.getContextInfo();
+        driverProcess = processInfo.getDriverProcess();
       }
-      return new RSCClient(lconf, info);
+      return new RSCClient(lconf, info, driverProcess);
     } catch (Exception e) {
       if (needsServer) {
         unref();

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/d74d5a9c/server/src/main/scala/com/cloudera/livy/server/interactive/InteractiveSession.scala
----------------------------------------------------------------------
diff --git a/server/src/main/scala/com/cloudera/livy/server/interactive/InteractiveSession.scala b/server/src/main/scala/com/cloudera/livy/server/interactive/InteractiveSession.scala
index 35fbc79..605edc6 100644
--- a/server/src/main/scala/com/cloudera/livy/server/interactive/InteractiveSession.scala
+++ b/server/src/main/scala/com/cloudera/livy/server/interactive/InteractiveSession.scala
@@ -44,6 +44,7 @@ import com.cloudera.livy.server.recovery.SessionStore
 import com.cloudera.livy.sessions._
 import com.cloudera.livy.sessions.Session._
 import com.cloudera.livy.sessions.SessionState.Dead
+import com.cloudera.livy.util.LineBufferedProcess
 import com.cloudera.livy.utils.{AppInfo, LivySparkUtils, SparkApp, SparkAppListener}
 
 @JsonIgnoreProperties(ignoreUnknown = true)
@@ -379,9 +380,11 @@ class InteractiveSession(
 
   private val app = mockApp.orElse {
     if (livyConf.isRunningOnYarn()) {
+      val driverProcess = client.flatMap { c => Option(c.getDriverProcess) }
+        .map(new LineBufferedProcess(_))
       // When Livy is running with YARN, SparkYarnApp can provide better YARN integration.
       // (e.g. Reflect YARN application state to session state).
-      Option(SparkApp.create(appTag, appId, None, livyConf, Some(this)))
+      Option(SparkApp.create(appTag, appId, driverProcess, livyConf, Some(this)))
     } else {
       // When Livy is running with other cluster manager, SparkApp doesn't provide any
       // additional benefit over controlling RSCDriver using RSCClient. Don't use it.

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/d74d5a9c/server/src/main/scala/com/cloudera/livy/utils/LineBufferedStream.scala
----------------------------------------------------------------------
diff --git a/server/src/main/scala/com/cloudera/livy/utils/LineBufferedStream.scala b/server/src/main/scala/com/cloudera/livy/utils/LineBufferedStream.scala
index d54bfb0..a8949af 100644
--- a/server/src/main/scala/com/cloudera/livy/utils/LineBufferedStream.scala
+++ b/server/src/main/scala/com/cloudera/livy/utils/LineBufferedStream.scala
@@ -39,7 +39,6 @@ class LineBufferedStream(inputStream: InputStream) extends Logging {
       for (line <- lines) {
         _lock.lock()
         try {
-          trace("stdout: ", line)
           _lines = _lines :+ line
           _condition.signalAll()
         } finally {
@@ -47,6 +46,7 @@ class LineBufferedStream(inputStream: InputStream) extends Logging {
         }
       }
 
+      _lines.map { line => info("stdout: ", line) }
       _lock.lock()
       try {
         _finished = true

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/d74d5a9c/server/src/main/scala/com/cloudera/livy/utils/SparkYarnApp.scala
----------------------------------------------------------------------
diff --git a/server/src/main/scala/com/cloudera/livy/utils/SparkYarnApp.scala b/server/src/main/scala/com/cloudera/livy/utils/SparkYarnApp.scala
index 7b5cc75..fb47e5e 100644
--- a/server/src/main/scala/com/cloudera/livy/utils/SparkYarnApp.scala
+++ b/server/src/main/scala/com/cloudera/livy/utils/SparkYarnApp.scala
@@ -128,7 +128,9 @@ class SparkYarnApp private[utils] (
   private var yarnDiagnostics: IndexedSeq[String] = IndexedSeq.empty[String]
 
   override def log(): IndexedSeq[String] =
-    process.map(_.inputLines).getOrElse(ArrayBuffer.empty[String]) ++ yarnDiagnostics
+    ("stdout: " +: process.map(_.inputLines).getOrElse(ArrayBuffer.empty[String])) ++
+    ("\nstderr: " +: process.map(_.errorLines).getOrElse(ArrayBuffer.empty[String])) ++
+    ("\nYARN Diagnostics: " +: yarnDiagnostics)
 
   override def kill(): Unit = synchronized {
     if (isRunning) {

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/d74d5a9c/server/src/test/scala/com/cloudera/livy/utils/SparkYarnAppSpec.scala
----------------------------------------------------------------------
diff --git a/server/src/test/scala/com/cloudera/livy/utils/SparkYarnAppSpec.scala b/server/src/test/scala/com/cloudera/livy/utils/SparkYarnAppSpec.scala
index 3d7c76f..1d90367 100644
--- a/server/src/test/scala/com/cloudera/livy/utils/SparkYarnAppSpec.scala
+++ b/server/src/test/scala/com/cloudera/livy/utils/SparkYarnAppSpec.scala
@@ -136,8 +136,12 @@ class SparkYarnAppSpec extends FunSpec with LivyBaseUnitTestSuite {
       Clock.withSleepMethod(mockSleep) {
         val mockYarnClient = mock[YarnClient]
         val mockSparkSubmit = mock[LineBufferedProcess]
-        val sparkSubmitLog = IndexedSeq("SPARK-SUBMIT", "LOG")
-        when(mockSparkSubmit.inputLines).thenReturn(sparkSubmitLog)
+        val sparkSubmitInfoLog = IndexedSeq("SPARK-SUBMIT", "LOG")
+        val sparkSubmitErrorLog = IndexedSeq("SPARK-SUBMIT", "error log")
+        val sparkSubmitLog = ("stdout: " +: sparkSubmitInfoLog) ++
+          ("\nstderr: " +: sparkSubmitErrorLog) :+ "\nYARN Diagnostics: "
+        when(mockSparkSubmit.inputLines).thenReturn(sparkSubmitInfoLog)
+        when(mockSparkSubmit.errorLines).thenReturn(sparkSubmitErrorLog)
         val waitForCalledLatch = new CountDownLatch(1)
         when(mockSparkSubmit.waitFor()).thenAnswer(new Answer[Int]() {
           override def answer(invocation: InvocationOnMock): Int = {


[32/50] [abbrv] incubator-livy git commit: LIVY-249. Update livy-server script to include status command and return 1 on error. (#311)

Posted by js...@apache.org.
LIVY-249. Update livy-server script to include status command and return 1 on error. (#311)

Currently if livy-server fails to start it will still return 0 (success), this has been fixed. I also added a livy-server status command that will return a status output similar to that of livy-server start when it's already running or livy-server stop when it's already stopped. Lastly I updated all output text to use livy-server instead of livy_server since that's the actual name of the script.

Tested manually.

Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/5e6f9ed3
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/5e6f9ed3
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/5e6f9ed3

Branch: refs/heads/master
Commit: 5e6f9ed3fd2667599e52e3759d869ac535114145
Parents: b7cc00a
Author: Alex Bozarth <aj...@us.ibm.com>
Authored: Fri Mar 17 00:48:34 2017 -0700
Committer: Alex Man <al...@users.noreply.github.com>
Committed: Fri Mar 17 00:48:34 2017 -0700

----------------------------------------------------------------------
 bin/livy-server | 22 ++++++++++++++++++----
 1 file changed, 18 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/5e6f9ed3/bin/livy-server
----------------------------------------------------------------------
diff --git a/bin/livy-server b/bin/livy-server
index a2636ba..71b9134 100755
--- a/bin/livy-server
+++ b/bin/livy-server
@@ -108,7 +108,7 @@ start_livy_server() {
     if [ -f "$pid" ]; then
       TARGET_ID="$(cat "$pid")"
       if [[ $(ps -p "$TARGET_ID" -o comm=) =~ "java" ]]; then
-        echo "livy_server running as process $TARGET_ID.  Stop it first."
+        echo "livy-server running as process $TARGET_ID.  Stop it first."
         exit 1
       fi
     fi
@@ -125,6 +125,7 @@ start_livy_server() {
       tail -2 "$log" | sed 's/^/  /'
       echo "full log in $log"
       rm -rf "$pid"
+      exit 1
     fi
   fi
 }
@@ -146,13 +147,26 @@ case $option in
     if [ -f $pid ]; then
       TARGET_ID="$(cat "$pid")"
       if [[ $(ps -p "$TARGET_ID" -o comm=) =~ "java" ]]; then
-        echo "stopping livy_server"
+        echo "stopping livy-server"
         kill "$TARGET_ID" && rm -f "$pid"
       else
-        echo "no livy_server to stop"
+        echo "no livy-server to stop"
       fi
     else
-      echo "no livy_server to stop"
+      echo "no livy-server to stop"
+    fi
+    ;;
+
+  (status)
+    if [ -f "$pid" ]; then
+      TARGET_ID="$(cat "$pid")"
+      if [[ $(ps -p "$TARGET_ID" -o comm=) =~ "java" ]]; then
+        echo "livy-server is running (pid: $TARGET_ID)"
+      else
+        echo "livy-server is not running"
+      fi
+    else
+      echo "livy-server is not running"
     fi
     ;;
 


[05/50] [abbrv] incubator-livy git commit: Revert "LIVY-255. Update the docs for Livy build and Spark2 support"

Posted by js...@apache.org.
Revert "LIVY-255. Update the docs for Livy build and Spark2 support"


Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/2da435ad
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/2da435ad
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/2da435ad

Branch: refs/heads/revert-237-LIVY-255
Commit: 2da435ad1d8b43b7e5b3c6eece57c096a7126a20
Parents: dbdad9d
Author: Jeff Zhang <zj...@gmail.com>
Authored: Wed Nov 30 14:25:32 2016 +0800
Committer: GitHub <no...@github.com>
Committed: Wed Nov 30 14:25:32 2016 +0800

----------------------------------------------------------------------
 README.rst | 25 ++++++++++++-------------
 1 file changed, 12 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/2da435ad/README.rst
----------------------------------------------------------------------
diff --git a/README.rst b/README.rst
index a8f58ac..b23136a 100644
--- a/README.rst
+++ b/README.rst
@@ -51,14 +51,8 @@ Required python packages for building Livy:
 
 
 To run Livy, you will also need a Spark installation. You can get Spark releases at
-https://spark.apache.org/downloads.html.
-
-Livy requires at least Spark 1.6 and supports both Scala 2.10 and 2.11 builds of Spark, Livy
-will automatically pick repl dependencies through detecting the Scala version of Spark.
-
-Livy also supports Spark 2.0+ for both interactive and batch submission, you could seamlessly
-switch to different versions of Spark through ``SPARK_HOME`` configuration, without needing to
-rebuild Livy.
+https://spark.apache.org/downloads.html. Livy requires at least Spark 1.6 and currently
+only supports Scala 2.10 builds of Spark.
 
 
 Building Livy
@@ -72,11 +66,16 @@ Livy is built using `Apache Maven`_. To check out and build Livy, run:
     cd livy
     mvn package
 
-By default Livy is built against Apache Spark 1.6.2, but the version of Spark used when running
-Livy does not need to match the version used to build Livy. Livy internally uses reflection to
-mitigate the gaps between different Spark versions, also Livy package itself does not
-contain a Spark distribution, so it will work with any supported version of Spark (Spark 1.6+)
-without needing to rebuild against specific version of Spark.
+By default Livy is built against the CDH 5.5 distribution of Spark (based off Spark 1.5.0). You can
+build Livy against a different version of Spark by setting the ``spark.version`` property:
+
+.. code:: shell
+
+    mvn -Dspark.version=1.6.1 package
+
+The version of Spark used when running Livy does not need to match the version used to build Livy.
+The Livy package itself does not contain a Spark distribution, and will work with any supported
+version of Spark.
 
 .. _Apache Maven: http://maven.apache.org
 


[08/50] [abbrv] incubator-livy git commit: Bump to 0.4.0-SNAPSHOT for master branch (#282)

Posted by js...@apache.org.
Bump to 0.4.0-SNAPSHOT for master branch (#282)

Change-Id: I32dd970bfa1150e3b47ecbfd7c1a7c348bb7e259

Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/9575d8f7
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/9575d8f7
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/9575d8f7

Branch: refs/heads/master
Commit: 9575d8f7597c55918635760da6d6916720f5dad6
Parents: 34f6c7f
Author: Saisai Shao <sa...@gmail.com>
Authored: Fri Feb 10 12:07:19 2017 +0800
Committer: Jeff Zhang <zj...@gmail.com>
Committed: Fri Feb 10 12:07:19 2017 +0800

----------------------------------------------------------------------
 api/pom.xml                                                  | 4 ++--
 assembly/pom.xml                                             | 4 ++--
 client-common/pom.xml                                        | 4 ++--
 client-http/pom.xml                                          | 4 ++--
 core/pom.xml                                                 | 4 ++--
 core/scala-2.10/pom.xml                                      | 4 ++--
 core/scala-2.11/pom.xml                                      | 4 ++--
 coverage/pom.xml                                             | 4 ++--
 examples/pom.xml                                             | 4 ++--
 integration-test/minicluster-dependencies/pom.xml            | 4 ++--
 integration-test/minicluster-dependencies/scala-2.10/pom.xml | 4 ++--
 integration-test/minicluster-dependencies/scala-2.11/pom.xml | 4 ++--
 integration-test/pom.xml                                     | 4 ++--
 pom.xml                                                      | 2 +-
 python-api/pom.xml                                           | 4 ++--
 python-api/setup.py                                          | 2 +-
 repl/pom.xml                                                 | 4 ++--
 repl/scala-2.10/pom.xml                                      | 4 ++--
 repl/scala-2.11/pom.xml                                      | 4 ++--
 rsc/pom.xml                                                  | 4 ++--
 scala-api/pom.xml                                            | 4 ++--
 scala-api/scala-2.10/pom.xml                                 | 4 ++--
 scala-api/scala-2.11/pom.xml                                 | 4 ++--
 scala/pom.xml                                                | 4 ++--
 server/pom.xml                                               | 4 ++--
 test-lib/pom.xml                                             | 4 ++--
 26 files changed, 50 insertions(+), 50 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/9575d8f7/api/pom.xml
----------------------------------------------------------------------
diff --git a/api/pom.xml b/api/pom.xml
index d196cc5..156d987 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -20,12 +20,12 @@
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-main</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.4.0-SNAPSHOT</version>
   </parent>
 
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-api</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.4.0-SNAPSHOT</version>
   <packaging>jar</packaging>
 
   <properties>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/9575d8f7/assembly/pom.xml
----------------------------------------------------------------------
diff --git a/assembly/pom.xml b/assembly/pom.xml
index e9df377..87da4e5 100644
--- a/assembly/pom.xml
+++ b/assembly/pom.xml
@@ -21,12 +21,12 @@
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-main</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.4.0-SNAPSHOT</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
 
   <artifactId>livy-assembly</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.4.0-SNAPSHOT</version>
   <packaging>pom</packaging>
 
   <properties>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/9575d8f7/client-common/pom.xml
----------------------------------------------------------------------
diff --git a/client-common/pom.xml b/client-common/pom.xml
index 810be59..9cc713c 100644
--- a/client-common/pom.xml
+++ b/client-common/pom.xml
@@ -21,12 +21,12 @@
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-main</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.4.0-SNAPSHOT</version>
   </parent>
 
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-client-common</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.4.0-SNAPSHOT</version>
   <packaging>jar</packaging>
 
   <dependencies>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/9575d8f7/client-http/pom.xml
----------------------------------------------------------------------
diff --git a/client-http/pom.xml b/client-http/pom.xml
index 4c22ddb..478e222 100644
--- a/client-http/pom.xml
+++ b/client-http/pom.xml
@@ -21,12 +21,12 @@
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-main</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.4.0-SNAPSHOT</version>
   </parent>
 
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-client-http</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.4.0-SNAPSHOT</version>
   <packaging>jar</packaging>
 
   <dependencies>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/9575d8f7/core/pom.xml
----------------------------------------------------------------------
diff --git a/core/pom.xml b/core/pom.xml
index bfac5fd..ae2be28 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -23,12 +23,12 @@
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>multi-scala-project-root</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.4.0-SNAPSHOT</version>
     <relativePath>../scala/pom.xml</relativePath>
   </parent>
 
   <artifactId>livy-core-parent</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.4.0-SNAPSHOT</version>
   <packaging>pom</packaging>
 
   <properties>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/9575d8f7/core/scala-2.10/pom.xml
----------------------------------------------------------------------
diff --git a/core/scala-2.10/pom.xml b/core/scala-2.10/pom.xml
index d757f55..27fbcba 100644
--- a/core/scala-2.10/pom.xml
+++ b/core/scala-2.10/pom.xml
@@ -20,13 +20,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-core_2.10</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.4.0-SNAPSHOT</version>
   <packaging>jar</packaging>
 
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-core-parent</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.4.0-SNAPSHOT</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/9575d8f7/core/scala-2.11/pom.xml
----------------------------------------------------------------------
diff --git a/core/scala-2.11/pom.xml b/core/scala-2.11/pom.xml
index 36c3ae2..afb0c77 100644
--- a/core/scala-2.11/pom.xml
+++ b/core/scala-2.11/pom.xml
@@ -20,13 +20,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-core_2.11</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.4.0-SNAPSHOT</version>
   <packaging>jar</packaging>
 
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-core-parent</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.4.0-SNAPSHOT</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/9575d8f7/coverage/pom.xml
----------------------------------------------------------------------
diff --git a/coverage/pom.xml b/coverage/pom.xml
index 96b5c94..d834288 100644
--- a/coverage/pom.xml
+++ b/coverage/pom.xml
@@ -24,11 +24,11 @@
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-main</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.4.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>livy-coverage-report</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.4.0-SNAPSHOT</version>
   <packaging>pom</packaging>
 
   <dependencies>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/9575d8f7/examples/pom.xml
----------------------------------------------------------------------
diff --git a/examples/pom.xml b/examples/pom.xml
index 14fbf13..fccbe40 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -24,13 +24,13 @@
     <parent>
         <groupId>com.cloudera.livy</groupId>
         <artifactId>livy-main</artifactId>
-        <version>0.3.0-SNAPSHOT</version>
+        <version>0.4.0-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
 
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-examples</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.4.0-SNAPSHOT</version>
     <packaging>jar</packaging>
 
     <properties>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/9575d8f7/integration-test/minicluster-dependencies/pom.xml
----------------------------------------------------------------------
diff --git a/integration-test/minicluster-dependencies/pom.xml b/integration-test/minicluster-dependencies/pom.xml
index 8fbf4b3..c19ff6c 100644
--- a/integration-test/minicluster-dependencies/pom.xml
+++ b/integration-test/minicluster-dependencies/pom.xml
@@ -27,10 +27,10 @@
     <groupId>com.cloudera.livy</groupId>
     <artifactId>multi-scala-project-root</artifactId>
     <relativePath>../../scala/pom.xml</relativePath>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.4.0-SNAPSHOT</version>
   </parent>
   <artifactId>minicluster-dependencies-parent</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.4.0-SNAPSHOT</version>
   <packaging>pom</packaging>
   <properties>
     <skipDeploy>true</skipDeploy>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/9575d8f7/integration-test/minicluster-dependencies/scala-2.10/pom.xml
----------------------------------------------------------------------
diff --git a/integration-test/minicluster-dependencies/scala-2.10/pom.xml b/integration-test/minicluster-dependencies/scala-2.10/pom.xml
index 3bb2259..6118301 100644
--- a/integration-test/minicluster-dependencies/scala-2.10/pom.xml
+++ b/integration-test/minicluster-dependencies/scala-2.10/pom.xml
@@ -20,13 +20,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.cloudera.livy</groupId>
   <artifactId>minicluster-dependencies_2.10</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.4.0-SNAPSHOT</version>
   <packaging>jar</packaging>
 
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>minicluster-dependencies-parent</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.4.0-SNAPSHOT</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/9575d8f7/integration-test/minicluster-dependencies/scala-2.11/pom.xml
----------------------------------------------------------------------
diff --git a/integration-test/minicluster-dependencies/scala-2.11/pom.xml b/integration-test/minicluster-dependencies/scala-2.11/pom.xml
index a3a4fef..8bdf7f4 100644
--- a/integration-test/minicluster-dependencies/scala-2.11/pom.xml
+++ b/integration-test/minicluster-dependencies/scala-2.11/pom.xml
@@ -20,13 +20,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.cloudera.livy</groupId>
   <artifactId>minicluster-dependencies_2.11</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.4.0-SNAPSHOT</version>
   <packaging>jar</packaging>
 
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>minicluster-dependencies-parent</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.4.0-SNAPSHOT</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/9575d8f7/integration-test/pom.xml
----------------------------------------------------------------------
diff --git a/integration-test/pom.xml b/integration-test/pom.xml
index 0742315..54df07f 100644
--- a/integration-test/pom.xml
+++ b/integration-test/pom.xml
@@ -24,11 +24,11 @@
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-main</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.4.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>livy-integration-test</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.4.0-SNAPSHOT</version>
   <packaging>jar</packaging>
 
   <properties>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/9575d8f7/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index c4f7329..28db23c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -23,7 +23,7 @@
 
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-main</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.4.0-SNAPSHOT</version>
   <packaging>pom</packaging>
 
   <name>livy-main</name>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/9575d8f7/python-api/pom.xml
----------------------------------------------------------------------
diff --git a/python-api/pom.xml b/python-api/pom.xml
index b40bb07..c28142a 100644
--- a/python-api/pom.xml
+++ b/python-api/pom.xml
@@ -7,13 +7,13 @@
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-main</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.4.0-SNAPSHOT</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
 
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-python-api</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.4.0-SNAPSHOT</version>
   <packaging>pom</packaging>
 
   <build>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/9575d8f7/python-api/setup.py
----------------------------------------------------------------------
diff --git a/python-api/setup.py b/python-api/setup.py
index 58ebdde..69ffbc0 100644
--- a/python-api/setup.py
+++ b/python-api/setup.py
@@ -40,7 +40,7 @@ requirements = [
 
 setup(
     name='livy-python-api',
-    version="0.3.0-SNAPSHOT",
+    version="0.4.0-SNAPSHOT",
     packages=["livy", "livy-tests"],
     package_dir={
         "": "src/main/python",

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/9575d8f7/repl/pom.xml
----------------------------------------------------------------------
diff --git a/repl/pom.xml b/repl/pom.xml
index c3f4c38..5b67824 100644
--- a/repl/pom.xml
+++ b/repl/pom.xml
@@ -24,11 +24,11 @@
         <groupId>com.cloudera.livy</groupId>
         <artifactId>multi-scala-project-root</artifactId>
         <relativePath>../scala/pom.xml</relativePath>
-        <version>0.3.0-SNAPSHOT</version>
+        <version>0.4.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>livy-repl-parent</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.4.0-SNAPSHOT</version>
     <packaging>pom</packaging>
 
     <properties>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/9575d8f7/repl/scala-2.10/pom.xml
----------------------------------------------------------------------
diff --git a/repl/scala-2.10/pom.xml b/repl/scala-2.10/pom.xml
index 887742f..3661e2b 100644
--- a/repl/scala-2.10/pom.xml
+++ b/repl/scala-2.10/pom.xml
@@ -22,13 +22,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-repl_2.10</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.4.0-SNAPSHOT</version>
   <packaging>jar</packaging>
 
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-repl-parent</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.4.0-SNAPSHOT</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/9575d8f7/repl/scala-2.11/pom.xml
----------------------------------------------------------------------
diff --git a/repl/scala-2.11/pom.xml b/repl/scala-2.11/pom.xml
index 5a2093f..d81bde2 100644
--- a/repl/scala-2.11/pom.xml
+++ b/repl/scala-2.11/pom.xml
@@ -22,13 +22,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-repl_2.11</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.4.0-SNAPSHOT</version>
   <packaging>jar</packaging>
 
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-repl-parent</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.4.0-SNAPSHOT</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/9575d8f7/rsc/pom.xml
----------------------------------------------------------------------
diff --git a/rsc/pom.xml b/rsc/pom.xml
index 3c6153a..7ff8c2a 100644
--- a/rsc/pom.xml
+++ b/rsc/pom.xml
@@ -21,12 +21,12 @@
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-main</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.4.0-SNAPSHOT</version>
   </parent>
 
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-rsc</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.4.0-SNAPSHOT</version>
   <packaging>jar</packaging>
 
   <properties>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/9575d8f7/scala-api/pom.xml
----------------------------------------------------------------------
diff --git a/scala-api/pom.xml b/scala-api/pom.xml
index b27b62d..3d67128 100644
--- a/scala-api/pom.xml
+++ b/scala-api/pom.xml
@@ -24,12 +24,12 @@
     <parent>
         <groupId>com.cloudera.livy</groupId>
         <artifactId>multi-scala-project-root</artifactId>
-        <version>0.3.0-SNAPSHOT</version>
+        <version>0.4.0-SNAPSHOT</version>
         <relativePath>../scala/pom.xml</relativePath>
     </parent>
 
     <artifactId>livy-scala-api-parent</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.4.0-SNAPSHOT</version>
     <packaging>pom</packaging>
 
     <dependencies>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/9575d8f7/scala-api/scala-2.10/pom.xml
----------------------------------------------------------------------
diff --git a/scala-api/scala-2.10/pom.xml b/scala-api/scala-2.10/pom.xml
index b7b91eb..5401405 100644
--- a/scala-api/scala-2.10/pom.xml
+++ b/scala-api/scala-2.10/pom.xml
@@ -20,13 +20,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-scala-api_2.10</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.4.0-SNAPSHOT</version>
   <packaging>jar</packaging>
 
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-scala-api-parent</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.4.0-SNAPSHOT</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/9575d8f7/scala-api/scala-2.11/pom.xml
----------------------------------------------------------------------
diff --git a/scala-api/scala-2.11/pom.xml b/scala-api/scala-2.11/pom.xml
index 9bedbc9..a79c972 100644
--- a/scala-api/scala-2.11/pom.xml
+++ b/scala-api/scala-2.11/pom.xml
@@ -20,13 +20,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-scala-api_2.11</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.4.0-SNAPSHOT</version>
   <packaging>jar</packaging>
 
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-scala-api-parent</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.4.0-SNAPSHOT</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/9575d8f7/scala/pom.xml
----------------------------------------------------------------------
diff --git a/scala/pom.xml b/scala/pom.xml
index ca71dcd..447c341 100644
--- a/scala/pom.xml
+++ b/scala/pom.xml
@@ -22,13 +22,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.cloudera.livy</groupId>
   <artifactId>multi-scala-project-root</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.4.0-SNAPSHOT</version>
   <packaging>pom</packaging>
 
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-main</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.4.0-SNAPSHOT</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/9575d8f7/server/pom.xml
----------------------------------------------------------------------
diff --git a/server/pom.xml b/server/pom.xml
index 5ef7b79..3226b6e 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -24,11 +24,11 @@
         <groupId>com.cloudera.livy</groupId>
         <artifactId>livy-main</artifactId>
         <relativePath>../pom.xml</relativePath>
-        <version>0.3.0-SNAPSHOT</version>
+        <version>0.4.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>livy-server</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.4.0-SNAPSHOT</version>
     <packaging>jar</packaging>
 
     <properties>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/9575d8f7/test-lib/pom.xml
----------------------------------------------------------------------
diff --git a/test-lib/pom.xml b/test-lib/pom.xml
index 79ec947..b9a9432 100644
--- a/test-lib/pom.xml
+++ b/test-lib/pom.xml
@@ -21,12 +21,12 @@
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-main</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.4.0-SNAPSHOT</version>
   </parent>
 
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-test-lib</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.4.0-SNAPSHOT</version>
   <packaging>jar</packaging>
 
   <properties>


[19/50] [abbrv] incubator-livy git commit: LIVY-306. Removed hard-coded minimum timeout value. (#290)

Posted by js...@apache.org.
LIVY-306. Removed hard-coded minimum timeout value. (#290)

Currently a session timeout can't be configured below 1h. This is due to a hard-coded value that was missed in the clean up of LIVY-114 and LIVY-127.

Removed the limit and the conf value (default of 1h) will be used.

Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/a72bbff6
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/a72bbff6
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/a72bbff6

Branch: refs/heads/master
Commit: a72bbff6fbf961f7413f3ca87d2a244f182f98ff
Parents: 14c29e4
Author: Alex Bozarth <aj...@us.ibm.com>
Authored: Tue Feb 21 17:29:33 2017 -0800
Committer: Alex Man <tc...@gmail.com>
Committed: Tue Feb 21 17:29:33 2017 -0800

----------------------------------------------------------------------
 server/src/main/scala/com/cloudera/livy/sessions/Session.scala     | 1 -
 .../src/main/scala/com/cloudera/livy/sessions/SessionManager.scala | 2 +-
 server/src/test/scala/com/cloudera/livy/sessions/MockSession.scala | 2 --
 3 files changed, 1 insertion(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/a72bbff6/server/src/main/scala/com/cloudera/livy/sessions/Session.scala
----------------------------------------------------------------------
diff --git a/server/src/main/scala/com/cloudera/livy/sessions/Session.scala b/server/src/main/scala/com/cloudera/livy/sessions/Session.scala
index faf3422..a0d0f8b 100644
--- a/server/src/main/scala/com/cloudera/livy/sessions/Session.scala
+++ b/server/src/main/scala/com/cloudera/livy/sessions/Session.scala
@@ -197,7 +197,6 @@ abstract class Session(val id: Int, val owner: String, val livyConf: LivyConf)
     }
   }
 
-  val timeout: Long = TimeUnit.HOURS.toNanos(1)
 
   override def toString(): String = s"${this.getClass.getSimpleName} $id"
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/a72bbff6/server/src/main/scala/com/cloudera/livy/sessions/SessionManager.scala
----------------------------------------------------------------------
diff --git a/server/src/main/scala/com/cloudera/livy/sessions/SessionManager.scala b/server/src/main/scala/com/cloudera/livy/sessions/SessionManager.scala
index 34aad1a..a50bd41 100644
--- a/server/src/main/scala/com/cloudera/livy/sessions/SessionManager.scala
+++ b/server/src/main/scala/com/cloudera/livy/sessions/SessionManager.scala
@@ -133,7 +133,7 @@ class SessionManager[S <: Session, R <: RecoveryMetadata : ClassTag](
   def collectGarbage(): Future[Iterable[Unit]] = {
     def expired(session: Session): Boolean = {
       val currentTime = System.nanoTime()
-      currentTime - session.lastActivity > math.max(sessionTimeout, session.timeout)
+      currentTime - session.lastActivity > sessionTimeout
     }
 
     Future.sequence(all().filter(expired).map(delete))

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/a72bbff6/server/src/test/scala/com/cloudera/livy/sessions/MockSession.scala
----------------------------------------------------------------------
diff --git a/server/src/test/scala/com/cloudera/livy/sessions/MockSession.scala b/server/src/test/scala/com/cloudera/livy/sessions/MockSession.scala
index dba60bf..c276a5e 100644
--- a/server/src/test/scala/com/cloudera/livy/sessions/MockSession.scala
+++ b/server/src/test/scala/com/cloudera/livy/sessions/MockSession.scala
@@ -31,7 +31,5 @@ class MockSession(id: Int, owner: String, conf: LivyConf) extends Session(id, ow
 
   override def state: SessionState = SessionState.Idle()
 
-  override val timeout: Long = 0L
-
   override def recoveryMetadata: RecoveryMetadata = RecoveryMetadata(0)
 }


[29/50] [abbrv] incubator-livy git commit: LIVY-329. Fix two SSL issues. (#308)

Posted by js...@apache.org.
LIVY-329. Fix two SSL issues. (#308)

- Livy server url is exposed as http URL even https is enabled, so we should handle this.
- Livy server SSL keystore password and key password currently set to same configurations, which should be separated.

Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/2ff8f5c6
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/2ff8f5c6
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/2ff8f5c6

Branch: refs/heads/master
Commit: 2ff8f5c69f8d7ea05f445b8240945afe910c1ab5
Parents: fbccb69
Author: Saisai Shao <sa...@gmail.com>
Authored: Tue Mar 14 03:52:02 2017 +0800
Committer: Alex Man <al...@users.noreply.github.com>
Committed: Mon Mar 13 12:52:02 2017 -0700

----------------------------------------------------------------------
 conf/livy.conf.template                                  |  3 +++
 server/src/main/scala/com/cloudera/livy/LivyConf.scala   |  4 ++++
 .../main/scala/com/cloudera/livy/server/LivyServer.scala |  2 +-
 .../main/scala/com/cloudera/livy/server/WebServer.scala  | 11 +++--------
 4 files changed, 11 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/2ff8f5c6/conf/livy.conf.template
----------------------------------------------------------------------
diff --git a/conf/livy.conf.template b/conf/livy.conf.template
index c23aab2..8c5fe03 100644
--- a/conf/livy.conf.template
+++ b/conf/livy.conf.template
@@ -3,6 +3,9 @@
 
 # Specify the keystore password.
 # livy.keystore.password =
+#
+# Specify the key password.
+# livy.key-password =
 
 # What host address to start the server on. By default, Livy will bind to all network interfaces.
 # livy.server.host = 0.0.0.0

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/2ff8f5c6/server/src/main/scala/com/cloudera/livy/LivyConf.scala
----------------------------------------------------------------------
diff --git a/server/src/main/scala/com/cloudera/livy/LivyConf.scala b/server/src/main/scala/com/cloudera/livy/LivyConf.scala
index 6562b03..1db1b8f 100644
--- a/server/src/main/scala/com/cloudera/livy/LivyConf.scala
+++ b/server/src/main/scala/com/cloudera/livy/LivyConf.scala
@@ -66,6 +66,10 @@ object LivyConf {
   val ACCESS_CONTROL_ENABLED = Entry("livy.server.access_control.enabled", false)
   val ACCESS_CONTROL_USERS = Entry("livy.server.access_control.users", null)
 
+  val SSL_KEYSTORE = Entry("livy.keystore", null)
+  val SSL_KEYSTORE_PASSWORD = Entry("livy.keystore.password", null)
+  val SSL_KEY_PASSWORD = Entry("livy.key-password", null)
+
   val AUTH_TYPE = Entry("livy.server.auth.type", null)
   val AUTH_KERBEROS_PRINCIPAL = Entry("livy.server.auth.kerberos.principal", null)
   val AUTH_KERBEROS_KEYTAB = Entry("livy.server.auth.kerberos.keytab", null)

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/2ff8f5c6/server/src/main/scala/com/cloudera/livy/server/LivyServer.scala
----------------------------------------------------------------------
diff --git a/server/src/main/scala/com/cloudera/livy/server/LivyServer.scala b/server/src/main/scala/com/cloudera/livy/server/LivyServer.scala
index a88f013..0499d48 100644
--- a/server/src/main/scala/com/cloudera/livy/server/LivyServer.scala
+++ b/server/src/main/scala/com/cloudera/livy/server/LivyServer.scala
@@ -231,7 +231,7 @@ class LivyServer extends Logging {
       }
     })
 
-    _serverUrl = Some(s"http://${server.host}:${server.port}")
+    _serverUrl = Some(s"${server.protocol}://${server.host}:${server.port}")
     sys.props("livy.server.serverUrl") = _serverUrl.get
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/2ff8f5c6/server/src/main/scala/com/cloudera/livy/server/WebServer.scala
----------------------------------------------------------------------
diff --git a/server/src/main/scala/com/cloudera/livy/server/WebServer.scala b/server/src/main/scala/com/cloudera/livy/server/WebServer.scala
index a07b05f..8f21180 100644
--- a/server/src/main/scala/com/cloudera/livy/server/WebServer.scala
+++ b/server/src/main/scala/com/cloudera/livy/server/WebServer.scala
@@ -28,18 +28,13 @@ import org.eclipse.jetty.util.ssl.SslContextFactory
 
 import com.cloudera.livy.{LivyConf, Logging}
 
-object WebServer {
-  val KeystoreKey = "livy.keystore"
-  val KeystorePasswordKey = "livy.keystore.password"
-}
-
 class WebServer(livyConf: LivyConf, var host: String, var port: Int) extends Logging {
   val server = new Server()
 
   server.setStopTimeout(1000)
   server.setStopAtShutdown(true)
 
-  val (connector, protocol) = Option(livyConf.get(WebServer.KeystoreKey)) match {
+  val (connector, protocol) = Option(livyConf.get(LivyConf.SSL_KEYSTORE)) match {
     case None =>
       (new ServerConnector(server), "http")
 
@@ -49,9 +44,9 @@ class WebServer(livyConf: LivyConf, var host: String, var port: Int) extends Log
 
       val sslContextFactory = new SslContextFactory()
       sslContextFactory.setKeyStorePath(keystore)
-      Option(livyConf.get(WebServer.KeystorePasswordKey))
+      Option(livyConf.get(LivyConf.SSL_KEYSTORE_PASSWORD))
         .foreach(sslContextFactory.setKeyStorePassword)
-      Option(livyConf.get(WebServer.KeystorePasswordKey))
+      Option(livyConf.get(LivyConf.SSL_KEY_PASSWORD))
         .foreach(sslContextFactory.setKeyManagerPassword)
 
       (new ServerConnector(server,


[43/50] [abbrv] incubator-livy git commit: LIVY-342. Create Livy UI: Create Web UI Servlet and All Sessions Page (#319)

Posted by js...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/61b206e0/server/src/main/resources/com/cloudera/livy/server/ui/static/bootstrap.min.js
----------------------------------------------------------------------
diff --git a/server/src/main/resources/com/cloudera/livy/server/ui/static/bootstrap.min.js b/server/src/main/resources/com/cloudera/livy/server/ui/static/bootstrap.min.js
new file mode 100644
index 0000000..9bcd2fc
--- /dev/null
+++ b/server/src/main/resources/com/cloudera/livy/server/ui/static/bootstrap.min.js
@@ -0,0 +1,7 @@
+/*!
+ * Bootstrap v3.3.7 (http://getbootstrap.com)
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under the MIT license
+ */
+if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>3)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){if(a(b
 .target).is(this))return b.handleObj.handler.apply(this,arguments)}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.7",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a("#"===f?[]:f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c
 ,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.7",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c).prop(c,!0)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c).prop(c,!1))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeCla
 ss("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target).closest(".btn");b.call(d,"toggle"),a(c.target).is('input[type="radio"], input[type="checkbox"]')||(c.preventDefault(),d.is("input,button")?d.trigger("focus"):d.find("input:visible,button:visible").first().trigger("focus"))}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"us
 e strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.7",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();b
 reak;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));if(!(a>this.$items.length-1||a<0))return this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),thi
 s.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){if(!this.sliding)return this.slide("next")},c.prototype.prev=function(){if(!this.sliding)return this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offs
 etWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);
 b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.7",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&
 &!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.b
 s.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expande
 d",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass("open")&&(c&&"click"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event("hide.bs.dropdown",f)),c.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",f)))))}))}funct
 ion d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.7",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=b(e),g=f.hasClass("open");if(c(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",c);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger(a.Event("shown.bs.dropdown",h))}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(".disabled, :disabled")){v
 ar e=b(d),g=e.hasClass("open");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find(".dropdown-menu"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&j<i.length-1&&j++,~j||(j=0),i.eq(j).trigger("focus")}}}};var h=a.fn.dropdown;a.fn.dropdown=d,a.fn.dropdown.Constructor=g,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=h,this},a(document).on("click.bs.dropdown.data-api",c).on("click.bs.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.bs.dropdown.data-api",f,g.prototype.toggle).on("keydown.bs.dropdown.data-api",f,g.prototype.keydown).on("keydown.bs.dropdown.data-api",".dropdown-menu",g.prototype.keydown)}(jQuery),+function(a){"use strict";function b(b,d){return this.each(function(){var e=a(this),f=e.data("bs.modal"),g=a.extend({},c.DEFAULTS,e.data(),"object"==typeof b&&b);f||e.data("bs.modal",f=new c(this,g)),"string"==typeof b?
 f[b](d):g.show&&f.show(d)})}var c=function(b,c){this.options=c,this.$body=a(document.body),this.$element=a(b),this.$dialog=this.$element.find(".modal-dialog"),this.$backdrop=null,this.isShown=null,this.originalBodyPad=null,this.scrollbarWidth=0,this.ignoreBackdropClick=!1,this.options.remote&&this.$element.find(".modal-content").load(this.options.remote,a.proxy(function(){this.$element.trigger("loaded.bs.modal")},this))};c.VERSION="3.3.7",c.TRANSITION_DURATION=300,c.BACKDROP_TRANSITION_DURATION=150,c.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},c.prototype.toggle=function(a){return this.isShown?this.hide():this.show(a)},c.prototype.show=function(b){var d=this,e=a.Event("show.bs.modal",{relatedTarget:b});this.$element.trigger(e),this.isShown||e.isDefaultPrevented()||(this.isShown=!0,this.checkScrollbar(),this.setScrollbar(),this.$body.addClass("modal-open"),this.escape(),this.resize(),this.$element.on("click.dismiss.bs.modal",'[data-dismiss="modal"]',a.proxy(this.hide,this)),this.$dial
 og.on("mousedown.dismiss.bs.modal",function(){d.$element.one("mouseup.dismiss.bs.modal",function(b){a(b.target).is(d.$element)&&(d.ignoreBackdropClick=!0)})}),this.backdrop(function(){var e=a.support.transition&&d.$element.hasClass("fade");d.$element.parent().length||d.$element.appendTo(d.$body),d.$element.show().scrollTop(0),d.adjustDialog(),e&&d.$element[0].offsetWidth,d.$element.addClass("in"),d.enforceFocus();var f=a.Event("shown.bs.modal",{relatedTarget:b});e?d.$dialog.one("bsTransitionEnd",function(){d.$element.trigger("focus").trigger(f)}).emulateTransitionEnd(c.TRANSITION_DURATION):d.$element.trigger("focus").trigger(f)}))},c.prototype.hide=function(b){b&&b.preventDefault(),b=a.Event("hide.bs.modal"),this.$element.trigger(b),this.isShown&&!b.isDefaultPrevented()&&(this.isShown=!1,this.escape(),this.resize(),a(document).off("focusin.bs.modal"),this.$element.removeClass("in").off("click.dismiss.bs.modal").off("mouseup.dismiss.bs.modal"),this.$dialog.off("mousedown.dismiss.bs.m
 odal"),a.support.transition&&this.$element.hasClass("fade")?this.$element.one("bsTransitionEnd",a.proxy(this.hideModal,this)).emulateTransitionEnd(c.TRANSITION_DURATION):this.hideModal())},c.prototype.enforceFocus=function(){a(document).off("focusin.bs.modal").on("focusin.bs.modal",a.proxy(function(a){document===a.target||this.$element[0]===a.target||this.$element.has(a.target).length||this.$element.trigger("focus")},this))},c.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on("keydown.dismiss.bs.modal",a.proxy(function(a){27==a.which&&this.hide()},this)):this.isShown||this.$element.off("keydown.dismiss.bs.modal")},c.prototype.resize=function(){this.isShown?a(window).on("resize.bs.modal",a.proxy(this.handleUpdate,this)):a(window).off("resize.bs.modal")},c.prototype.hideModal=function(){var a=this;this.$element.hide(),this.backdrop(function(){a.$body.removeClass("modal-open"),a.resetAdjustments(),a.resetScrollbar(),a.$element.trigger("hidden.bs.modal")})
 },c.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},c.prototype.backdrop=function(b){var d=this,e=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var f=a.support.transition&&e;if(this.$backdrop=a(document.createElement("div")).addClass("modal-backdrop "+e).appendTo(this.$body),this.$element.on("click.dismiss.bs.modal",a.proxy(function(a){return this.ignoreBackdropClick?void(this.ignoreBackdropClick=!1):void(a.target===a.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus():this.hide()))},this)),f&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!b)return;f?this.$backdrop.one("bsTransitionEnd",b).emulateTransitionEnd(c.BACKDROP_TRANSITION_DURATION):b()}else if(!this.isShown&&this.$backdrop){this.$backdrop.removeClass("in");var g=function(){d.removeBackdrop(),b&&b()};a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one("bsTransitionEnd",g).emulateTransiti
 onEnd(c.BACKDROP_TRANSITION_DURATION):g()}else b&&b()},c.prototype.handleUpdate=function(){this.adjustDialog()},c.prototype.adjustDialog=function(){var a=this.$element[0].scrollHeight>document.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:""})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth<a,this.scrollbarWidth=this.measureScrollbar()},c.prototype.setScrollbar=function(){var a=parseInt(this.$body.css("padding-right")||0,10);this.originalBodyPad=document.body.style.paddingRight||"",this.bodyIsOverflowing&&this.$body.css("padding-right",a+this.scrollbarWidth)},c.prototype.resetScrollbar=function(){this.$body.css("padding
 -right",this.originalBodyPad)},c.prototype.measureScrollbar=function(){var a=document.createElement("div");a.className="modal-scrollbar-measure",this.$body.append(a);var b=a.offsetWidth-a.clientWidth;return this.$body[0].removeChild(a),b};var d=a.fn.modal;a.fn.modal=b,a.fn.modal.Constructor=c,a.fn.modal.noConflict=function(){return a.fn.modal=d,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(c){var d=a(this),e=d.attr("href"),f=a(d.attr("data-target")||e&&e.replace(/.*(?=#[^\s]+$)/,"")),g=f.data("bs.modal")?"toggle":a.extend({remote:!/#/.test(e)&&e},f.data(),d.data());d.is("a")&&c.preventDefault(),f.one("show.bs.modal",function(a){a.isDefaultPrevented()||f.one("hidden.bs.modal",function(){d.is(":visible")&&d.trigger("focus")})}),b.call(f,g,this)})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tooltip"),f="object"==typeof b&&b;!e&&/destroy|hide/.test(b)||(e||d.data("bs.tooltip",e=new c(this,f)),"
 string"==typeof b&&e[b]())})}var c=function(a,b){this.type=null,this.options=null,this.enabled=null,this.timeout=null,this.hoverState=null,this.$element=null,this.inState=null,this.init("tooltip",a,b)};c.VERSION="3.3.7",c.TRANSITION_DURATION=150,c.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+
 this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){v
 ar c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);if(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),!c.isInStateTrue())return clearTimeout(c.timeout),c.hoverState="out",c.option
 s.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0
 ].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-m<o.top?"bottom":"right"==h&&k.right+l>o.width?"left":"left"==h&&k.left-l<o.left?"right":h,f.removeClass(n).addClass(h)}var p=this.getCalculatedOffset(h,k,l,m);this.applyPlacement(p,h);var q=function(){var a=e.hoverState;e.$element.trigger("shown.bs."+e.type),e.hoverState=null,"out"==a&&e.leave(e)};a.support.transition&&this.$tip.hasClass("fade")?f.one("bsTransitionEnd",q).emulateTransitionEnd(c.TRANSITION_DURATION):q()}},c.prototype.applyPlacement=function(b,c){var d=this.tip(),e=d[0].offsetWidth,f=d[0].offsetHeight,g=parseInt(d.css("margin-top"),10),h=parseInt(d.css("margin-left"),10);isNaN(g)&&(g=0),isNaN(h)&&(h=0),b.top+=g,b.left+=h,a.offset.setOffset(d[0],a.extend({using:function(a){d.css({top:Math.round(a.top),left:Math.round(a.left)})}},b),0),d.addClass("in");var i=d[0].offsetWidth,j=d[0].offsetHeight;"top"==c&&j!=f&&(b.top=b.top+f-j);var k=this.getViewport
 AdjustedDelta(c,b,i,j);k.left?b.left+=k.left:b.top+=k.top;var l=/top|bottom/.test(c),m=l?2*k.left-e+i:2*k.top-f+j,n=l?"offsetWidth":"offsetHeight";d.offset(b),this.replaceArrow(m,d[0][n],l)},c.prototype.replaceArrow=function(a,b,c){this.arrow().css(c?"left":"top",50*(1-a/b)+"%").css(c?"top":"left","")},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.options.html?"html":"text"](b),a.removeClass("fade in top bottom left right")},c.prototype.hide=function(b){function d(){"in"!=e.hoverState&&f.detach(),e.$element&&e.$element.removeAttr("aria-describedby").trigger("hidden.bs."+e.type),b&&b()}var e=this,f=a(this.$tip),g=a.Event("hide.bs."+this.type);if(this.$element.trigger(g),!g.isDefaultPrevented())return f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one("bsTransitionEnd",d).emulateTransitionEnd(c.TRANSITION_DURATION):d(),this.hoverState=null,this},c.prototype.fixTitle=function(){var a=this.$element;(a.attr("title")||"s
 tring"!=typeof a.attr("data-original-title"))&&a.attr("data-original-title",a.attr("title")||"").attr("title","")},c.prototype.hasContent=function(){return this.getTitle()},c.prototype.getPosition=function(b){b=b||this.$element;var c=b[0],d="BODY"==c.tagName,e=c.getBoundingClientRect();null==e.width&&(e=a.extend({},e,{width:e.right-e.left,height:e.bottom-e.top}));var f=window.SVGElement&&c instanceof window.SVGElement,g=d?{top:0,left:0}:f?null:b.offset(),h={scroll:d?document.documentElement.scrollTop||document.body.scrollTop:b.scrollTop()},i=d?{width:a(window).width(),height:a(window).height()}:null;return a.extend({},e,h,i,g)},c.prototype.getCalculatedOffset=function(a,b,c,d){return"bottom"==a?{top:b.top+b.height,left:b.left+b.width/2-c/2}:"top"==a?{top:b.top-d,left:b.left+b.width/2-c/2}:"left"==a?{top:b.top+b.height/2-d/2,left:b.left-c}:{top:b.top+b.height/2-d/2,left:b.left+b.width}},c.prototype.getViewportAdjustedDelta=function(a,b,c,d){var e={top:0,left:0};if(!this.$viewport)ret
 urn e;var f=this.options.viewport&&this.options.viewport.padding||0,g=this.getPosition(this.$viewport);if(/right|left/.test(a)){var h=b.top-f-g.scroll,i=b.top+f-g.scroll+d;h<g.top?e.top=g.top-h:i>g.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;j<g.left?e.left=g.left-j:k>g.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){th
 is.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null,a.$element=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;!e&&/destroy|hide/.test(b)||(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}v
 ar c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.7",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=
 function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.7",b.DEFAULTS={offset:10},b.prototype.getScrollH
 eight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b<e[0])return this.activeTarget=null,this.
 clear();for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(void 0===e[a+1]||b<e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){
+this.activeTarget=b,this.clear();var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate.bs.scrollspy")},b.prototype.clear=function(){a(this.selector).parentsUntil(this.options.target,".active").removeClass("active")};var d=a.fn.scrollspy;a.fn.scrollspy=c,a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=d,this},a(window).on("load.bs.scrollspy.data-api",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);c.call(b,b.data())})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new c(this)),"string"==typeof b&&e[b]()})}var c=function(b){this.element=a(b)};c.VERSION="3.3.7",c.TRANSITION_DURATION=150,c.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("ta
 rget");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a"),f=a.Event("hide.bs.tab",{relatedTarget:b[0]}),g=a.Event("show.bs.tab",{relatedTarget:e[0]});if(e.trigger(f),b.trigger(g),!g.isDefaultPrevented()&&!f.isDefaultPrevented()){var h=a(d);this.activate(b.closest("li"),c),this.activate(h,h.parent(),function(){e.trigger({type:"hidden.bs.tab",relatedTarget:b[0]}),b.trigger({type:"shown.bs.tab",relatedTarget:e[0]})})}}},c.prototype.activate=function(b,d,e){function f(){g.removeClass("active").find("> .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&
 &a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkP
 osition()};c.VERSION="3.3.7",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return e<c&&"top";if("bottom"==this.affixed)return null!=c?!(e+this.unpin<=f.top)&&"bottom":!(e+g<=a-d)&&"bottom";var h=null==this.affixed,i=h?e:f.top,j=h?g:b;return null!=c&&e<=c?"top":null!=d&&i+j>=a-d&&"bottom"},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"o
 bject"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery);
\ No newline at end of file


[03/50] [abbrv] incubator-livy git commit: Updating the doc

Posted by js...@apache.org.
Updating the doc

Change-Id: Ibdeb06fde53d359e77aace780a6093b2cc6a70b7


Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/2e812a79
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/2e812a79
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/2e812a79

Branch: refs/heads/revert-237-LIVY-255
Commit: 2e812a7935da6d8ac992568c6d21fefd31b443c1
Parents: 97251bd
Author: jerryshao <ss...@hortonworks.com>
Authored: Mon Nov 28 15:44:28 2016 +0800
Committer: jerryshao <ss...@hortonworks.com>
Committed: Mon Nov 28 15:44:28 2016 +0800

----------------------------------------------------------------------
 README.rst | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/2e812a79/README.rst
----------------------------------------------------------------------
diff --git a/README.rst b/README.rst
index 1d2d2e5..a8f58ac 100644
--- a/README.rst
+++ b/README.rst
@@ -74,9 +74,9 @@ Livy is built using `Apache Maven`_. To check out and build Livy, run:
 
 By default Livy is built against Apache Spark 1.6.2, but the version of Spark used when running
 Livy does not need to match the version used to build Livy. Livy internally uses reflection to
-mitigate the gaps of different Spark versions, also Livy package itself does not
+mitigate the gaps between different Spark versions, also Livy package itself does not
 contain a Spark distribution, so it will work with any supported version of Spark (Spark 1.6+)
-without to rebuild against specific version of Spark.
+without needing to rebuild against specific version of Spark.
 
 .. _Apache Maven: http://maven.apache.org
 


[11/50] [abbrv] incubator-livy git commit: LIVY-308. Avoid enabling Hive by default in Spark2. (#287)

Posted by js...@apache.org.
LIVY-308. Avoid enabling Hive by default in Spark2. (#287)

Fixed broken integration test on Spark 2.1.

Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/663c6130
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/663c6130
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/663c6130

Branch: refs/heads/master
Commit: 663c6130a5f576965b74e4448e68bc7b7668ad48
Parents: 807036a
Author: Saisai Shao <sa...@gmail.com>
Authored: Mon Feb 13 15:08:21 2017 +0800
Committer: Alex Man <tc...@gmail.com>
Committed: Mon Feb 13 02:08:21 2017 -0500

----------------------------------------------------------------------
 .travis.yml                                             |  2 ++
 pom.xml                                                 | 12 ++++++++++++
 .../cloudera/livy/repl/SparkContextInitializer.scala    |  2 +-
 3 files changed, 15 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/663c6130/.travis.yml
----------------------------------------------------------------------
diff --git a/.travis.yml b/.travis.yml
index b52b0bf..021c061 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,8 +5,10 @@ language: scala
 env:
   - MVN_FLAG='-Pspark-1.6 -DskipTests'
   - MVN_FLAG='-Pspark-2.0 -DskipTests'
+  - MVN_FLAG='-Pspark-2.1 -DskipTests'
   - MVN_FLAG='-Pspark-1.6 -DskipITs'
   - MVN_FLAG='-Pspark-2.0 -DskipITs'
+  - MVN_FLAG='-Pspark-2.1 -DskipITs'
 
 jdk:
   - oraclejdk7

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/663c6130/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 28db23c..8868d35 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1005,6 +1005,18 @@
         <spark.version>2.0.1</spark.version>
       </properties>
     </profile>
+
+    <profile>
+      <id>spark-2.1</id>
+      <activation>
+        <property>
+          <name>spark-2.1</name>
+        </property>
+      </activation>
+      <properties>
+        <spark.version>2.1.0</spark.version>
+      </properties>
+    </profile>
   </profiles>
 
 </project>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/663c6130/repl/src/main/scala/com/cloudera/livy/repl/SparkContextInitializer.scala
----------------------------------------------------------------------
diff --git a/repl/src/main/scala/com/cloudera/livy/repl/SparkContextInitializer.scala b/repl/src/main/scala/com/cloudera/livy/repl/SparkContextInitializer.scala
index 33c7f37..fd082eb 100644
--- a/repl/src/main/scala/com/cloudera/livy/repl/SparkContextInitializer.scala
+++ b/repl/src/main/scala/com/cloudera/livy/repl/SparkContextInitializer.scala
@@ -82,7 +82,7 @@ trait SparkContextInitializer extends Logging {
     builder.getClass.getMethod("config", classOf[SparkConf]).invoke(builder, conf)
 
     var spark: Object = null
-    if (conf.get("spark.sql.catalogImplementation", "hive").toLowerCase == "hive") {
+    if (conf.get("spark.sql.catalogImplementation", "in-memory").toLowerCase == "hive") {
       if (sparkClz.getMethod("hiveClassesArePresent").invoke(sparkObj).asInstanceOf[Boolean]) {
         val loader = Option(Thread.currentThread().getContextClassLoader)
           .getOrElse(getClass.getClassLoader)


[50/50] [abbrv] incubator-livy git commit: Livy:337 Binding RPCServer to user provided port and not random port (#334)

Posted by js...@apache.org.
Livy:337 Binding RPCServer to user provided port and not random port (#334)

* Code changes in RPCserver for user provided port

* Indentation Changes

* Indentation Changes

* Indentation Changes

* Indentation Changes

* Configuring Port Range

* Documentation Changed

* launcher.port.range will take care of launching RPC

* Checkstyle changes

* Checkstyle changes

* Dummy push

* Code changes

* Changed BindException Handling to SocketException Handling

* Changed Import Order

* Code changes to increase port range

* Set Port isConntect to true

* Indentation Changes & port range in livy-client.conf.template

* Indentation changes

* Changed visibilty of method private

* Indentation Changes

* Indenetation Changes

* Unit test case to test port range

* Checkstyle changes

* Unit test case for port range

* Added comment for Port Range Configuration and increase port range for unit test case


Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/9ae24d08
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/9ae24d08
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/9ae24d08

Branch: refs/heads/master
Commit: 9ae24d08738652ba5fd817780711d01b110d74a9
Parents: 02eef9a
Author: pralabhkumar <pr...@gmail.com>
Authored: Thu Jun 8 13:22:25 2017 +0530
Committer: Jeff Zhang <zj...@gmail.com>
Committed: Thu Jun 8 15:52:25 2017 +0800

----------------------------------------------------------------------
 conf/livy-client.conf.template                  |  5 +-
 .../java/com/cloudera/livy/rsc/RSCConf.java     |  4 +-
 .../com/cloudera/livy/rsc/rpc/RpcServer.java    | 86 ++++++++++++++++----
 .../java/com/cloudera/livy/rsc/rpc/TestRpc.java | 27 ++++++
 4 files changed, 104 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/9ae24d08/conf/livy-client.conf.template
----------------------------------------------------------------------
diff --git a/conf/livy-client.conf.template b/conf/livy-client.conf.template
index 2a92b57..06ad653 100644
--- a/conf/livy-client.conf.template
+++ b/conf/livy-client.conf.template
@@ -55,7 +55,8 @@
 
 # Address for the RSC driver to connect back with it's connection info.
 # livy.rsc.launcher.address =
-# livy.rsc.launcher.port = -1
+# Port Range on which RPC will launch . Port range in inclusive of start and end port .
+# livy.rsc.launcher.port.range = 10000~10110
 
 # How long will the RSC wait for a connection for a Livy server before shutting itself down.
 # livy.rsc.server.idle-timeout = 10m
@@ -83,4 +84,4 @@
 # livy.rsc.job-cancel.timeout = 30s
 
 # Number of statements kept in driver's memory
-# livy.rsc.retained-statements = 100
\ No newline at end of file
+# livy.rsc.retained-statements = 100

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/9ae24d08/rsc/src/main/java/com/cloudera/livy/rsc/RSCConf.java
----------------------------------------------------------------------
diff --git a/rsc/src/main/java/com/cloudera/livy/rsc/RSCConf.java b/rsc/src/main/java/com/cloudera/livy/rsc/RSCConf.java
index d1b8b39..afd935d 100644
--- a/rsc/src/main/java/com/cloudera/livy/rsc/RSCConf.java
+++ b/rsc/src/main/java/com/cloudera/livy/rsc/RSCConf.java
@@ -51,8 +51,10 @@ public class RSCConf extends ClientConf<RSCConf> {
 
     // Address for the RSC driver to connect back with it's connection info.
     LAUNCHER_ADDRESS("launcher.address", null),
+    LAUNCHER_PORT_RANGE("launcher.port.range", "10000~10010"),
+    // Setting up of this propety by user has no benefit. It is currently being used
+    // to pass  port information from ContextLauncher to RSCDriver
     LAUNCHER_PORT("launcher.port", -1),
-
     // How long will the RSC wait for a connection for a Livy server before shutting itself down.
     SERVER_IDLE_TIMEOUT("server.idle-timeout", "10m"),
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/9ae24d08/rsc/src/main/java/com/cloudera/livy/rsc/rpc/RpcServer.java
----------------------------------------------------------------------
diff --git a/rsc/src/main/java/com/cloudera/livy/rsc/rpc/RpcServer.java b/rsc/src/main/java/com/cloudera/livy/rsc/rpc/RpcServer.java
index 1d3e6c5..44db976 100644
--- a/rsc/src/main/java/com/cloudera/livy/rsc/rpc/RpcServer.java
+++ b/rsc/src/main/java/com/cloudera/livy/rsc/rpc/RpcServer.java
@@ -19,7 +19,10 @@ package com.cloudera.livy.rsc.rpc;
 
 import java.io.Closeable;
 import java.io.IOException;
+import java.net.BindException;
 import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.SocketException;
 import java.security.SecureRandom;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
@@ -61,18 +64,78 @@ public class RpcServer implements Closeable {
   private static final SecureRandom RND = new SecureRandom();
 
   private final String address;
-  private final Channel channel;
+  private Channel channel;
   private final EventLoopGroup group;
   private final int port;
   private final ConcurrentMap<String, ClientInfo> pendingClients;
   private final RSCConf config;
-
+  private final String portRange;
+  private static enum PortRangeSchema{START_PORT, END_PORT, MAX};
+  private final String PORT_DELIMITER = "~";
+  /**
+   * Creating RPC Server
+   * @param lconf
+   * @throws IOException
+   * @throws InterruptedException
+   */
   public RpcServer(RSCConf lconf) throws IOException, InterruptedException {
     this.config = lconf;
+    this.portRange = config.get(LAUNCHER_PORT_RANGE);
     this.group = new NioEventLoopGroup(
-        this.config.getInt(RPC_MAX_THREADS),
-        Utils.newDaemonThreadFactory("RPC-Handler-%d"));
-    this.channel = new ServerBootstrap()
+      this.config.getInt(RPC_MAX_THREADS),
+      Utils.newDaemonThreadFactory("RPC-Handler-%d"));
+    int [] portData = getPortNumberAndRange();
+    int startingPortNumber = portData[PortRangeSchema.START_PORT.ordinal()];
+    int endPort = portData[PortRangeSchema.END_PORT.ordinal()];
+    boolean isContected = false;
+    for(int tries = startingPortNumber ; tries<=endPort ; tries++){
+      try {
+        this.channel = getChannel(tries);
+        isContected = true;
+        break;
+      } catch(SocketException e){
+        LOG.debug("RPC not able to connect port " + tries + " " + e.getMessage());
+      }
+    }
+    if(!isContected) {
+      throw new IOException("Unable to connect to provided ports " + this.portRange);
+    }
+    this.port = ((InetSocketAddress) channel.localAddress()).getPort();
+    this.pendingClients = new ConcurrentHashMap<>();
+    LOG.info("Connected to the port " + this.port);
+    String address = config.get(RPC_SERVER_ADDRESS);
+    if (address == null) {
+      address = config.findLocalAddress();
+    }
+    this.address = address;
+  }
+
+  /**
+   * Get Port Numbers
+   */
+  private int[] getPortNumberAndRange() throws ArrayIndexOutOfBoundsException,
+    NumberFormatException {
+    String[] split = this.portRange.split(PORT_DELIMITER);
+    int [] portRange = new int [PortRangeSchema.MAX.ordinal()];
+    try {
+      portRange[PortRangeSchema.START_PORT.ordinal()] =
+      Integer.parseInt(split[PortRangeSchema.START_PORT.ordinal()]);
+      portRange[PortRangeSchema.END_PORT.ordinal()] =
+      Integer.parseInt(split[PortRangeSchema.END_PORT.ordinal()]);
+    } catch(ArrayIndexOutOfBoundsException e) {
+      LOG.error("Port Range format is not correct " + this.portRange);
+      throw e;
+    } catch(NumberFormatException e) {
+      LOG.error("Port are not in numeric format " + this.portRange);
+      throw e;
+    }
+    return portRange;
+  }
+  /**
+   * @throws InterruptedException
+   **/
+  private Channel getChannel(int portNumber) throws BindException, InterruptedException {
+    Channel channel = new ServerBootstrap()
       .group(group)
       .channel(NioServerSocketChannel.class)
       .childHandler(new ChannelInitializer<SocketChannel>() {
@@ -97,19 +160,11 @@ public class RpcServer implements Closeable {
       .option(ChannelOption.SO_BACKLOG, 1)
       .option(ChannelOption.SO_REUSEADDR, true)
       .childOption(ChannelOption.SO_KEEPALIVE, true)
-      .bind(0)
+      .bind(portNumber)
       .sync()
       .channel();
-    this.port = ((InetSocketAddress) channel.localAddress()).getPort();
-    this.pendingClients = new ConcurrentHashMap<>();
-
-    String address = config.get(RPC_SERVER_ADDRESS);
-    if (address == null) {
-      address = config.findLocalAddress();
-    }
-    this.address = address;
+    return channel;
   }
-
   /**
    * Tells the RPC server to expect connections from clients.
    *
@@ -310,3 +365,4 @@ public class RpcServer implements Closeable {
   }
 
 }
+

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/9ae24d08/rsc/src/test/java/com/cloudera/livy/rsc/rpc/TestRpc.java
----------------------------------------------------------------------
diff --git a/rsc/src/test/java/com/cloudera/livy/rsc/rpc/TestRpc.java b/rsc/src/test/java/com/cloudera/livy/rsc/rpc/TestRpc.java
index cf19fee..48abe94 100644
--- a/rsc/src/test/java/com/cloudera/livy/rsc/rpc/TestRpc.java
+++ b/rsc/src/test/java/com/cloudera/livy/rsc/rpc/TestRpc.java
@@ -18,6 +18,8 @@
 package com.cloudera.livy.rsc.rpc;
 
 import java.io.Closeable;
+import java.io.IOException;
+import java.net.SocketException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.concurrent.CountDownLatch;
@@ -186,6 +188,31 @@ public class TestRpc {
     assertEquals(outbound.message, reply.message);
   }
 
+  @Test
+  public void testPortRange() throws Exception {
+    String portRange = "a~b";
+    emptyConfig.set(LAUNCHER_PORT_RANGE, portRange);
+    try {
+      autoClose(new RpcServer(emptyConfig));
+    } catch (Exception ee) {
+      assertTrue(ee instanceof NumberFormatException);
+    }
+    portRange = "11000";
+    emptyConfig.set(LAUNCHER_PORT_RANGE, portRange);
+    try {
+      autoClose(new RpcServer(emptyConfig));
+    } catch (Exception ee) {
+      assertTrue(ee instanceof ArrayIndexOutOfBoundsException);
+    }
+    portRange = "11000~11110";
+    emptyConfig.set(LAUNCHER_PORT_RANGE, portRange);
+    String [] portRangeData = portRange.split("~");
+    int startPort = Integer.parseInt(portRangeData[0]);
+    int endPort = Integer.parseInt(portRangeData[1]);
+    RpcServer server = autoClose(new RpcServer(emptyConfig));
+    assertTrue(startPort <= server.getPort() && server.getPort() <= endPort);
+  }
+
   private void transfer(Rpc serverRpc, Rpc clientRpc) {
     EmbeddedChannel client = (EmbeddedChannel) clientRpc.getChannel();
     EmbeddedChannel server = (EmbeddedChannel) serverRpc.getChannel();


[48/50] [abbrv] incubator-livy git commit: LIVY-358. [Follow-up] Add unit test to verify header size configurations (#331)

Posted by js...@apache.org.
LIVY-358. [Follow-up] Add unit test to verify header size configurations (#331)

* Add unit test to verify large header size configuration

Change-Id: I6c231f9fc9773d1ea40313661b7c49ccfaa44796

* Style fix

Change-Id: I24e617f95fd3e45a674a6b5a691428f0fdabcd89

* Style fix

Change-Id: I91e71979499da8ebba41223b6fe41862de168d03

* Revert the changes

Change-Id: Id7bbd1b2378867c8534b900bc7ba9b1234a9b985

* Add configurations to livy.conf.template

Change-Id: I84d428869bc5cc22aa7f00c6c603ea4a6b052964


Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/2abb8a3d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/2abb8a3d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/2abb8a3d

Branch: refs/heads/master
Commit: 2abb8a3d2850c506ffd2b8a210813f1b8353045f
Parents: 59af39d
Author: Saisai Shao <sa...@gmail.com>
Authored: Thu May 18 11:24:38 2017 +0800
Committer: Jeff Zhang <zj...@gmail.com>
Committed: Wed May 17 23:24:38 2017 -0400

----------------------------------------------------------------------
 .../livy/client/http/LivyConnectionSpec.scala   | 53 +++++++++++++-------
 conf/livy.conf.template                         |  4 ++
 2 files changed, 38 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/2abb8a3d/client-http/src/test/scala/com/cloudera/livy/client/http/LivyConnectionSpec.scala
----------------------------------------------------------------------
diff --git a/client-http/src/test/scala/com/cloudera/livy/client/http/LivyConnectionSpec.scala b/client-http/src/test/scala/com/cloudera/livy/client/http/LivyConnectionSpec.scala
index 886d0fd..4e36106 100644
--- a/client-http/src/test/scala/com/cloudera/livy/client/http/LivyConnectionSpec.scala
+++ b/client-http/src/test/scala/com/cloudera/livy/client/http/LivyConnectionSpec.scala
@@ -18,20 +18,20 @@
 
 package com.cloudera.livy.client.http
 
+import java.io.IOException
 import java.net.URLEncoder
 import java.nio.charset.StandardCharsets.UTF_8
-import javax.servlet.http.{HttpServlet, HttpServletRequest, HttpServletResponse}
 
 import org.apache.http.client.utils.URIBuilder
 import org.eclipse.jetty.security._
 import org.eclipse.jetty.security.authentication.BasicAuthenticator
-import org.eclipse.jetty.server.Server
-import org.eclipse.jetty.servlet.{ServletContextHandler, ServletHolder}
 import org.eclipse.jetty.util.security._
 import org.scalatest.{BeforeAndAfterAll, FunSpecLike}
 import org.scalatest.Matchers._
+import org.scalatra.servlet.ScalatraListener
 
-import com.cloudera.livy.LivyBaseUnitTestSuite
+import com.cloudera.livy.{LivyBaseUnitTestSuite, LivyConf}
+import com.cloudera.livy.server.WebServer
 
 class LivyConnectionSpec extends FunSpecLike with BeforeAndAfterAll with LivyBaseUnitTestSuite {
   describe("LivyConnection") {
@@ -60,31 +60,29 @@ class LivyConnectionSpec extends FunSpecLike with BeforeAndAfterAll with LivyBas
       csh
     }
 
-    def staticServlet(): HttpServlet = new HttpServlet {
-      override def doGet(req: HttpServletRequest, resp: HttpServletResponse): Unit = {
-        resp.getWriter.print("true")
-      }
-    }
-
-    def test(password: String): Unit = {
+    def test(password: String, livyConf: LivyConf = new LivyConf()): Unit = {
       val username = "user name"
 
-      val server = new Server(0)
-      val context = new ServletContextHandler(ServletContextHandler.SESSIONS)
-      context.setSecurityHandler(basicAuth(username, password, "realm"))
-      context.setContextPath("/")
-      context.addServlet(new ServletHolder(staticServlet()), "/")
-      server.setHandler(context)
+      val server = new WebServer(livyConf, "0.0.0.0", 0)
+      server.context.setSecurityHandler(basicAuth(username, password, "realm"))
+      server.context.setResourceBase("src/main/com/cloudera/livy/server")
+      server.context.setInitParameter(ScalatraListener.LifeCycleKey,
+        classOf[HttpClientTestBootstrap].getCanonicalName)
+      server.context.addEventListener(new ScalatraListener)
       server.start()
 
       val utf8Name = UTF_8.name()
-      val uri = new URIBuilder(server.getURI())
+      val uri = new URIBuilder()
+        .setScheme(server.protocol)
+        .setHost(server.host)
+        .setPort(server.port)
         .setUserInfo(URLEncoder.encode(username, utf8Name), URLEncoder.encode(password, utf8Name))
         .build()
       info(uri.toString)
       val conn = new LivyConnection(uri, new HttpConf(null))
       try {
-        conn.get(classOf[Boolean], "/") shouldBe true
+        conn.get(classOf[Object], "/") should not be (null)
+
       } finally {
         conn.close()
       }
@@ -100,5 +98,22 @@ class LivyConnectionSpec extends FunSpecLike with BeforeAndAfterAll with LivyBas
     it("should support HTTP auth with empty password") {
       test("")
     }
+
+    it("should be failed with large header size") {
+      val livyConf = new LivyConf()
+        .set(LivyConf.REQUEST_HEADER_SIZE, 1024)
+        .set(LivyConf.RESPONSE_HEADER_SIZE, 1024)
+      val pwd = "test-password" * 100
+      val exception = intercept[IOException](test(pwd, livyConf))
+      exception.getMessage.contains("Request Entity Too Large") should be(true)
+    }
+
+    it("should be succeeded with configured header size") {
+      val livyConf = new LivyConf()
+        .set(LivyConf.REQUEST_HEADER_SIZE, 2048)
+        .set(LivyConf.RESPONSE_HEADER_SIZE, 2048)
+      val pwd = "test-password" * 100
+      test(pwd, livyConf)
+    }
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/2abb8a3d/conf/livy.conf.template
----------------------------------------------------------------------
diff --git a/conf/livy.conf.template b/conf/livy.conf.template
index 8bef995..d57717a 100644
--- a/conf/livy.conf.template
+++ b/conf/livy.conf.template
@@ -19,6 +19,10 @@
 # What spark deploy mode Livy sessions should use.
 # livy.spark.deploy-mode =
 
+# Configure Livy server http request and response header size.
+# livy.server.request-header.size = 131072
+# livy.server.response-header.size = 131072
+
 # Enabled to check whether timeout Livy sessions should be stopped.
 # livy.server.session.timeout-check = true
 


[36/50] [abbrv] incubator-livy git commit: Minor. Changed git clone command in README to use http instead of ssh. (#315)

Posted by js...@apache.org.
Minor. Changed git clone command in README to use http instead of ssh. (#315)



Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/511a05f2
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/511a05f2
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/511a05f2

Branch: refs/heads/master
Commit: 511a05f2282cd85a457017cc5a739672aaed5238
Parents: 07f6072
Author: Alex Man <al...@users.noreply.github.com>
Authored: Tue Apr 18 12:59:57 2017 -0700
Committer: GitHub <no...@github.com>
Committed: Tue Apr 18 12:59:57 2017 -0700

----------------------------------------------------------------------
 README.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/511a05f2/README.rst
----------------------------------------------------------------------
diff --git a/README.rst b/README.rst
index b72dd0f..5e1fa13 100644
--- a/README.rst
+++ b/README.rst
@@ -72,7 +72,7 @@ Livy is built using `Apache Maven`_. To check out and build Livy, run:
 
 .. code:: shell
 
-    git clone git@github.com:cloudera/livy.git
+    git clone https://github.com/cloudera/livy.git
     cd livy
     mvn package
 


[38/50] [abbrv] incubator-livy git commit: Remove guava api in Livy (#321)

Posted by js...@apache.org.
Remove guava api in Livy (#321)

Change-Id: Ia8b635dbb9e8ef8e55bbe566967c5abaa5e07020

Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/e8c3e067
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/e8c3e067
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/e8c3e067

Branch: refs/heads/master
Commit: e8c3e067782c98f9ceeb1b62e18ff676c3921fab
Parents: 7212e3f
Author: Saisai Shao <sa...@gmail.com>
Authored: Fri Apr 28 11:48:31 2017 +0800
Committer: Jeff Zhang <zj...@gmail.com>
Committed: Fri Apr 28 11:48:31 2017 +0800

----------------------------------------------------------------------
 .../main/java/com/cloudera/livy/rsc/driver/StatementState.java | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e8c3e067/rsc/src/main/java/com/cloudera/livy/rsc/driver/StatementState.java
----------------------------------------------------------------------
diff --git a/rsc/src/main/java/com/cloudera/livy/rsc/driver/StatementState.java b/rsc/src/main/java/com/cloudera/livy/rsc/driver/StatementState.java
index 5e084bc..61a86d0 100644
--- a/rsc/src/main/java/com/cloudera/livy/rsc/driver/StatementState.java
+++ b/rsc/src/main/java/com/cloudera/livy/rsc/driver/StatementState.java
@@ -20,7 +20,6 @@ package com.cloudera.livy.rsc.driver;
 import java.util.*;
 
 import com.fasterxml.jackson.annotation.JsonValue;
-import com.google.common.base.Preconditions;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -80,7 +79,8 @@ public enum StatementState {
 
   static void validate(StatementState from, StatementState to) {
     LOG.debug("{} -> {}", from, to);
-
-    Preconditions.checkState(isValid(from, to), "Illegal Transition: %s -> %s", from, to);
+    if (!isValid(from, to)) {
+      throw new IllegalStateException("Illegal Transition: " + from + " -> " + to);
+    }
   }
 }


[49/50] [abbrv] incubator-livy git commit: Make sure to install setuptools less then version 36.0.0 to avoid module six not found issue (#341)

Posted by js...@apache.org.
Make sure to install setuptools less then version 36.0.0 to avoid module six not found issue (#341)

Change-Id: I7ba64be56354be5a03e6f6b349990af6b662e457

Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/02eef9a5
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/02eef9a5
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/02eef9a5

Branch: refs/heads/master
Commit: 02eef9a5b22d42cf5837f1a0b4805775116e4885
Parents: 2abb8a3
Author: Saisai Shao <sa...@gmail.com>
Authored: Fri Jun 2 10:14:05 2017 +0800
Committer: Jeff Zhang <zj...@gmail.com>
Committed: Fri Jun 2 10:14:05 2017 +0800

----------------------------------------------------------------------
 .travis.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/02eef9a5/.travis.yml
----------------------------------------------------------------------
diff --git a/.travis.yml b/.travis.yml
index 021c061..e985c31 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -30,8 +30,8 @@ before_install:
   - sudo apt-get -y install python3-pip python-dev
   - sudo apt-get -y install libkrb5-dev
   - sudo apt-get -y remove python-setuptools
-  - pip install --user --upgrade pip setuptools
-  - pip3 install --user --upgrade pip setuptools
+  - pip install --user --upgrade pip "setuptools < 36"
+  - pip3 install --user --upgrade pip "setuptools < 36"
   - pip install --user codecov cloudpickle
   - pip3 install --user cloudpickle
 


[02/50] [abbrv] incubator-livy git commit: Update the docs related Livy build and Spark 2 support

Posted by js...@apache.org.
Update the docs related Livy build and Spark 2 support

Change-Id: Id59c628e73da46a124f718b192fc92336ac8eace


Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/97251bdc
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/97251bdc
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/97251bdc

Branch: refs/heads/revert-237-LIVY-255
Commit: 97251bdcfa9543997d85a06149820a7c794fa8d2
Parents: b8a0839
Author: jerryshao <ss...@hortonworks.com>
Authored: Mon Nov 28 15:41:58 2016 +0800
Committer: jerryshao <ss...@hortonworks.com>
Committed: Mon Nov 28 15:41:58 2016 +0800

----------------------------------------------------------------------
 README.rst | 25 +++++++++++++------------
 1 file changed, 13 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/97251bdc/README.rst
----------------------------------------------------------------------
diff --git a/README.rst b/README.rst
index b23136a..1d2d2e5 100644
--- a/README.rst
+++ b/README.rst
@@ -51,8 +51,14 @@ Required python packages for building Livy:
 
 
 To run Livy, you will also need a Spark installation. You can get Spark releases at
-https://spark.apache.org/downloads.html. Livy requires at least Spark 1.6 and currently
-only supports Scala 2.10 builds of Spark.
+https://spark.apache.org/downloads.html.
+
+Livy requires at least Spark 1.6 and supports both Scala 2.10 and 2.11 builds of Spark, Livy
+will automatically pick repl dependencies through detecting the Scala version of Spark.
+
+Livy also supports Spark 2.0+ for both interactive and batch submission, you could seamlessly
+switch to different versions of Spark through ``SPARK_HOME`` configuration, without needing to
+rebuild Livy.
 
 
 Building Livy
@@ -66,16 +72,11 @@ Livy is built using `Apache Maven`_. To check out and build Livy, run:
     cd livy
     mvn package
 
-By default Livy is built against the CDH 5.5 distribution of Spark (based off Spark 1.5.0). You can
-build Livy against a different version of Spark by setting the ``spark.version`` property:
-
-.. code:: shell
-
-    mvn -Dspark.version=1.6.1 package
-
-The version of Spark used when running Livy does not need to match the version used to build Livy.
-The Livy package itself does not contain a Spark distribution, and will work with any supported
-version of Spark.
+By default Livy is built against Apache Spark 1.6.2, but the version of Spark used when running
+Livy does not need to match the version used to build Livy. Livy internally uses reflection to
+mitigate the gaps of different Spark versions, also Livy package itself does not
+contain a Spark distribution, so it will work with any supported version of Spark (Spark 1.6+)
+without to rebuild against specific version of Spark.
 
 .. _Apache Maven: http://maven.apache.org
 


[06/50] [abbrv] incubator-livy git commit: Updated Livy version to 0.3.0.

Posted by js...@apache.org.
Updated Livy version to 0.3.0.


Project: http://git-wip-us.apache.org/repos/asf/incubator-livy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-livy/commit/e36b6f57
Tree: http://git-wip-us.apache.org/repos/asf/incubator-livy/tree/e36b6f57
Diff: http://git-wip-us.apache.org/repos/asf/incubator-livy/diff/e36b6f57

Branch: refs/heads/branch-0.3
Commit: e36b6f57cad6f52eb56f431517a35bc063ed3c5d
Parents: 69462b9
Author: Alex Man <tc...@gmail.com>
Authored: Tue Jan 24 16:37:08 2017 -0800
Committer: Alex Man <tc...@gmail.com>
Committed: Tue Jan 24 17:15:20 2017 -0800

----------------------------------------------------------------------
 api/pom.xml                                                  | 4 ++--
 assembly/pom.xml                                             | 4 ++--
 client-common/pom.xml                                        | 4 ++--
 client-http/pom.xml                                          | 4 ++--
 core/pom.xml                                                 | 4 ++--
 core/scala-2.10/pom.xml                                      | 4 ++--
 core/scala-2.11/pom.xml                                      | 4 ++--
 coverage/pom.xml                                             | 4 ++--
 examples/pom.xml                                             | 4 ++--
 integration-test/minicluster-dependencies/pom.xml            | 4 ++--
 integration-test/minicluster-dependencies/scala-2.10/pom.xml | 4 ++--
 integration-test/minicluster-dependencies/scala-2.11/pom.xml | 4 ++--
 integration-test/pom.xml                                     | 4 ++--
 pom.xml                                                      | 2 +-
 python-api/pom.xml                                           | 4 ++--
 python-api/setup.py                                          | 2 +-
 repl/pom.xml                                                 | 4 ++--
 repl/scala-2.10/pom.xml                                      | 4 ++--
 repl/scala-2.11/pom.xml                                      | 4 ++--
 rsc/pom.xml                                                  | 4 ++--
 scala-api/pom.xml                                            | 4 ++--
 scala-api/scala-2.10/pom.xml                                 | 4 ++--
 scala-api/scala-2.11/pom.xml                                 | 4 ++--
 scala/pom.xml                                                | 4 ++--
 server/pom.xml                                               | 4 ++--
 test-lib/pom.xml                                             | 4 ++--
 26 files changed, 50 insertions(+), 50 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e36b6f57/api/pom.xml
----------------------------------------------------------------------
diff --git a/api/pom.xml b/api/pom.xml
index d196cc5..8873c61 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -20,12 +20,12 @@
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-main</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.3.0</version>
   </parent>
 
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-api</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.3.0</version>
   <packaging>jar</packaging>
 
   <properties>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e36b6f57/assembly/pom.xml
----------------------------------------------------------------------
diff --git a/assembly/pom.xml b/assembly/pom.xml
index e9df377..fe1515a 100644
--- a/assembly/pom.xml
+++ b/assembly/pom.xml
@@ -21,12 +21,12 @@
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-main</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.3.0</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
 
   <artifactId>livy-assembly</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.3.0</version>
   <packaging>pom</packaging>
 
   <properties>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e36b6f57/client-common/pom.xml
----------------------------------------------------------------------
diff --git a/client-common/pom.xml b/client-common/pom.xml
index 810be59..c3202fb 100644
--- a/client-common/pom.xml
+++ b/client-common/pom.xml
@@ -21,12 +21,12 @@
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-main</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.3.0</version>
   </parent>
 
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-client-common</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.3.0</version>
   <packaging>jar</packaging>
 
   <dependencies>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e36b6f57/client-http/pom.xml
----------------------------------------------------------------------
diff --git a/client-http/pom.xml b/client-http/pom.xml
index 4c22ddb..dd295c1 100644
--- a/client-http/pom.xml
+++ b/client-http/pom.xml
@@ -21,12 +21,12 @@
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-main</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.3.0</version>
   </parent>
 
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-client-http</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.3.0</version>
   <packaging>jar</packaging>
 
   <dependencies>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e36b6f57/core/pom.xml
----------------------------------------------------------------------
diff --git a/core/pom.xml b/core/pom.xml
index bfac5fd..e17d871 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -23,12 +23,12 @@
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>multi-scala-project-root</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.3.0</version>
     <relativePath>../scala/pom.xml</relativePath>
   </parent>
 
   <artifactId>livy-core-parent</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.3.0</version>
   <packaging>pom</packaging>
 
   <properties>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e36b6f57/core/scala-2.10/pom.xml
----------------------------------------------------------------------
diff --git a/core/scala-2.10/pom.xml b/core/scala-2.10/pom.xml
index d757f55..3708d88 100644
--- a/core/scala-2.10/pom.xml
+++ b/core/scala-2.10/pom.xml
@@ -20,13 +20,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-core_2.10</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.3.0</version>
   <packaging>jar</packaging>
 
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-core-parent</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.3.0</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e36b6f57/core/scala-2.11/pom.xml
----------------------------------------------------------------------
diff --git a/core/scala-2.11/pom.xml b/core/scala-2.11/pom.xml
index 36c3ae2..a47f9b4 100644
--- a/core/scala-2.11/pom.xml
+++ b/core/scala-2.11/pom.xml
@@ -20,13 +20,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-core_2.11</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.3.0</version>
   <packaging>jar</packaging>
 
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-core-parent</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.3.0</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e36b6f57/coverage/pom.xml
----------------------------------------------------------------------
diff --git a/coverage/pom.xml b/coverage/pom.xml
index 96b5c94..f8123f8 100644
--- a/coverage/pom.xml
+++ b/coverage/pom.xml
@@ -24,11 +24,11 @@
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-main</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.3.0</version>
   </parent>
 
   <artifactId>livy-coverage-report</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.3.0</version>
   <packaging>pom</packaging>
 
   <dependencies>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e36b6f57/examples/pom.xml
----------------------------------------------------------------------
diff --git a/examples/pom.xml b/examples/pom.xml
index 14fbf13..a3470dc 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -24,13 +24,13 @@
     <parent>
         <groupId>com.cloudera.livy</groupId>
         <artifactId>livy-main</artifactId>
-        <version>0.3.0-SNAPSHOT</version>
+        <version>0.3.0</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
 
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-examples</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.3.0</version>
     <packaging>jar</packaging>
 
     <properties>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e36b6f57/integration-test/minicluster-dependencies/pom.xml
----------------------------------------------------------------------
diff --git a/integration-test/minicluster-dependencies/pom.xml b/integration-test/minicluster-dependencies/pom.xml
index 8fbf4b3..ad3fdf1 100644
--- a/integration-test/minicluster-dependencies/pom.xml
+++ b/integration-test/minicluster-dependencies/pom.xml
@@ -27,10 +27,10 @@
     <groupId>com.cloudera.livy</groupId>
     <artifactId>multi-scala-project-root</artifactId>
     <relativePath>../../scala/pom.xml</relativePath>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.3.0</version>
   </parent>
   <artifactId>minicluster-dependencies-parent</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.3.0</version>
   <packaging>pom</packaging>
   <properties>
     <skipDeploy>true</skipDeploy>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e36b6f57/integration-test/minicluster-dependencies/scala-2.10/pom.xml
----------------------------------------------------------------------
diff --git a/integration-test/minicluster-dependencies/scala-2.10/pom.xml b/integration-test/minicluster-dependencies/scala-2.10/pom.xml
index 3bb2259..ec5828a 100644
--- a/integration-test/minicluster-dependencies/scala-2.10/pom.xml
+++ b/integration-test/minicluster-dependencies/scala-2.10/pom.xml
@@ -20,13 +20,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.cloudera.livy</groupId>
   <artifactId>minicluster-dependencies_2.10</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.3.0</version>
   <packaging>jar</packaging>
 
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>minicluster-dependencies-parent</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.3.0</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e36b6f57/integration-test/minicluster-dependencies/scala-2.11/pom.xml
----------------------------------------------------------------------
diff --git a/integration-test/minicluster-dependencies/scala-2.11/pom.xml b/integration-test/minicluster-dependencies/scala-2.11/pom.xml
index a3a4fef..42e4028 100644
--- a/integration-test/minicluster-dependencies/scala-2.11/pom.xml
+++ b/integration-test/minicluster-dependencies/scala-2.11/pom.xml
@@ -20,13 +20,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.cloudera.livy</groupId>
   <artifactId>minicluster-dependencies_2.11</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.3.0</version>
   <packaging>jar</packaging>
 
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>minicluster-dependencies-parent</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.3.0</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e36b6f57/integration-test/pom.xml
----------------------------------------------------------------------
diff --git a/integration-test/pom.xml b/integration-test/pom.xml
index 0742315..ea15a6a 100644
--- a/integration-test/pom.xml
+++ b/integration-test/pom.xml
@@ -24,11 +24,11 @@
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-main</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.3.0</version>
   </parent>
 
   <artifactId>livy-integration-test</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.3.0</version>
   <packaging>jar</packaging>
 
   <properties>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e36b6f57/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index c4f7329..630c1c5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -23,7 +23,7 @@
 
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-main</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.3.0</version>
   <packaging>pom</packaging>
 
   <name>livy-main</name>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e36b6f57/python-api/pom.xml
----------------------------------------------------------------------
diff --git a/python-api/pom.xml b/python-api/pom.xml
index b40bb07..95d492e 100644
--- a/python-api/pom.xml
+++ b/python-api/pom.xml
@@ -7,13 +7,13 @@
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-main</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.3.0</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
 
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-python-api</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.3.0</version>
   <packaging>pom</packaging>
 
   <build>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e36b6f57/python-api/setup.py
----------------------------------------------------------------------
diff --git a/python-api/setup.py b/python-api/setup.py
index 58ebdde..f7c5c20 100644
--- a/python-api/setup.py
+++ b/python-api/setup.py
@@ -40,7 +40,7 @@ requirements = [
 
 setup(
     name='livy-python-api',
-    version="0.3.0-SNAPSHOT",
+    version="0.3.0",
     packages=["livy", "livy-tests"],
     package_dir={
         "": "src/main/python",

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e36b6f57/repl/pom.xml
----------------------------------------------------------------------
diff --git a/repl/pom.xml b/repl/pom.xml
index c3f4c38..6470267 100644
--- a/repl/pom.xml
+++ b/repl/pom.xml
@@ -24,11 +24,11 @@
         <groupId>com.cloudera.livy</groupId>
         <artifactId>multi-scala-project-root</artifactId>
         <relativePath>../scala/pom.xml</relativePath>
-        <version>0.3.0-SNAPSHOT</version>
+        <version>0.3.0</version>
     </parent>
 
     <artifactId>livy-repl-parent</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.3.0</version>
     <packaging>pom</packaging>
 
     <properties>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e36b6f57/repl/scala-2.10/pom.xml
----------------------------------------------------------------------
diff --git a/repl/scala-2.10/pom.xml b/repl/scala-2.10/pom.xml
index 887742f..dfdadb9 100644
--- a/repl/scala-2.10/pom.xml
+++ b/repl/scala-2.10/pom.xml
@@ -22,13 +22,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-repl_2.10</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.3.0</version>
   <packaging>jar</packaging>
 
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-repl-parent</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.3.0</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e36b6f57/repl/scala-2.11/pom.xml
----------------------------------------------------------------------
diff --git a/repl/scala-2.11/pom.xml b/repl/scala-2.11/pom.xml
index 5a2093f..d67da5f 100644
--- a/repl/scala-2.11/pom.xml
+++ b/repl/scala-2.11/pom.xml
@@ -22,13 +22,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-repl_2.11</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.3.0</version>
   <packaging>jar</packaging>
 
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-repl-parent</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.3.0</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e36b6f57/rsc/pom.xml
----------------------------------------------------------------------
diff --git a/rsc/pom.xml b/rsc/pom.xml
index 3c6153a..35576a0 100644
--- a/rsc/pom.xml
+++ b/rsc/pom.xml
@@ -21,12 +21,12 @@
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-main</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.3.0</version>
   </parent>
 
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-rsc</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.3.0</version>
   <packaging>jar</packaging>
 
   <properties>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e36b6f57/scala-api/pom.xml
----------------------------------------------------------------------
diff --git a/scala-api/pom.xml b/scala-api/pom.xml
index b27b62d..f902e5d 100644
--- a/scala-api/pom.xml
+++ b/scala-api/pom.xml
@@ -24,12 +24,12 @@
     <parent>
         <groupId>com.cloudera.livy</groupId>
         <artifactId>multi-scala-project-root</artifactId>
-        <version>0.3.0-SNAPSHOT</version>
+        <version>0.3.0</version>
         <relativePath>../scala/pom.xml</relativePath>
     </parent>
 
     <artifactId>livy-scala-api-parent</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.3.0</version>
     <packaging>pom</packaging>
 
     <dependencies>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e36b6f57/scala-api/scala-2.10/pom.xml
----------------------------------------------------------------------
diff --git a/scala-api/scala-2.10/pom.xml b/scala-api/scala-2.10/pom.xml
index b7b91eb..692bc64 100644
--- a/scala-api/scala-2.10/pom.xml
+++ b/scala-api/scala-2.10/pom.xml
@@ -20,13 +20,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-scala-api_2.10</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.3.0</version>
   <packaging>jar</packaging>
 
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-scala-api-parent</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.3.0</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e36b6f57/scala-api/scala-2.11/pom.xml
----------------------------------------------------------------------
diff --git a/scala-api/scala-2.11/pom.xml b/scala-api/scala-2.11/pom.xml
index 9bedbc9..e3a366b 100644
--- a/scala-api/scala-2.11/pom.xml
+++ b/scala-api/scala-2.11/pom.xml
@@ -20,13 +20,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-scala-api_2.11</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.3.0</version>
   <packaging>jar</packaging>
 
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-scala-api-parent</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.3.0</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e36b6f57/scala/pom.xml
----------------------------------------------------------------------
diff --git a/scala/pom.xml b/scala/pom.xml
index ca71dcd..54e9f51 100644
--- a/scala/pom.xml
+++ b/scala/pom.xml
@@ -22,13 +22,13 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.cloudera.livy</groupId>
   <artifactId>multi-scala-project-root</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.3.0</version>
   <packaging>pom</packaging>
 
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-main</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.3.0</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
 

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e36b6f57/server/pom.xml
----------------------------------------------------------------------
diff --git a/server/pom.xml b/server/pom.xml
index 5ef7b79..e31c5ff 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -24,11 +24,11 @@
         <groupId>com.cloudera.livy</groupId>
         <artifactId>livy-main</artifactId>
         <relativePath>../pom.xml</relativePath>
-        <version>0.3.0-SNAPSHOT</version>
+        <version>0.3.0</version>
     </parent>
 
     <artifactId>livy-server</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.3.0</version>
     <packaging>jar</packaging>
 
     <properties>

http://git-wip-us.apache.org/repos/asf/incubator-livy/blob/e36b6f57/test-lib/pom.xml
----------------------------------------------------------------------
diff --git a/test-lib/pom.xml b/test-lib/pom.xml
index 79ec947..b509b63 100644
--- a/test-lib/pom.xml
+++ b/test-lib/pom.xml
@@ -21,12 +21,12 @@
   <parent>
     <groupId>com.cloudera.livy</groupId>
     <artifactId>livy-main</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.3.0</version>
   </parent>
 
   <groupId>com.cloudera.livy</groupId>
   <artifactId>livy-test-lib</artifactId>
-  <version>0.3.0-SNAPSHOT</version>
+  <version>0.3.0</version>
   <packaging>jar</packaging>
 
   <properties>