{"action":"created","comment":{"url":"https://api.github.com/repos/apache/spark/pulls/comments/51650895","id":51650895,"diff_hunk":"@@ -245,99 +239,182 @@ private[spark] class CoarseMesosSchedulerBackend(\n    */\n   override def resourceOffers(d: SchedulerDriver, offers: JList[Offer]) {\n     stateLock.synchronized {\n-      val filters = Filters.newBuilder().setRefuseSeconds(5).build()\n-      for (offer <- offers.asScala) {\n+      logDebug(s\"Received ${offers.size} resource offers.\")\n+\n+      val (matchedOffers, unmatchedOffers) = offers.asScala.partition { offer =>\n         val offerAttributes = toAttributeMap(offer.getAttributesList)\n-        val meetsConstraints = matchesAttributeRequirements(slaveOfferConstraints, offerAttributes)\n+        matchesAttributeRequirements(slaveOfferConstraints, offerAttributes)\n+      }\n+\n+      declineUnmatchedOffers(d, unmatchedOffers)\n+      handleMatchedOffers(d, matchedOffers)\n+    }\n+  }\n+\n+  private def declineUnmatchedOffers(d: SchedulerDriver, offers: Buffer[Offer]) {\n+    for (offer <- offers) {\n+      val id = offer.getId.getValue\n+      val offerAttributes = toAttributeMap(offer.getAttributesList)\n+      val mem = getResource(offer.getResourcesList, \"mem\")\n+      val cpus = getResource(offer.getResourcesList, \"cpus\")\n+      val filters = Filters.newBuilder()\n+        .setRefuseSeconds(rejectOfferDurationForUnmetConstraints).build()\n+\n+      logDebug(s\"Declining offer: $id with attributes: $offerAttributes mem: $mem cpu: $cpus\"\n+        + s\" for $rejectOfferDurationForUnmetConstraints seconds\")\n+\n+      d.declineOffer(offer.getId, filters)\n+    }\n+  }\n+\n+  private def handleMatchedOffers(d: SchedulerDriver, offers: Buffer[Offer]) {\n+    val tasks = getTasks(offers)\n+    for (offer <- offers) {\n+      val offerAttributes = toAttributeMap(offer.getAttributesList)\n+      val offerMem = getResource(offer.getResourcesList, \"mem\")\n+      val offerCpus = getResource(offer.getResourcesList, \"cpus\")\n+      val id = offer.getId.getValue\n+\n+      if (tasks.contains(offer.getId)) { // accept\n+        val filters = Filters.newBuilder().setRefuseSeconds(5).build()\n+        val offerTasks = tasks(offer.getId)\n+\n+        logDebug(s\"Accepting offer: $id with attributes: $offerAttributes \" +\n+          s\"mem: $offerMem cpu: $offerCpus.  Launching ${offerTasks.size} Mesos tasks.\")\n+\n+        for (task <- offerTasks) {\n+          val taskId = task.getTaskId\n+          val mem = getResource(task.getResourcesList, \"mem\")\n+          val cpus = getResource(task.getResourcesList, \"cpus\")\n+\n+          logDebug(s\"Launching Mesos task: ${taskId.getValue} with mem: $mem cpu: $cpus.\")\n+        }\n+\n+        d.launchTasks(\n+          Collections.singleton(offer.getId),\n+          offerTasks.asJava,\n+          filters)\n+      } else { // decline\n+        logDebug(s\"Declining offer: $id with attributes: $offerAttributes \" +\n+          s\"mem: $offerMem cpu: $offerCpus\")\n+\n+        d.declineOffer(offer.getId)\n+      }\n+    }\n+  }\n+\n+  private def getTasks(offers: Buffer[Offer]): mutable.Map[OfferID, List[MesosTaskInfo]] = {\n+    // offerID -> tasks\n+    val tasks = new HashMap[OfferID, List[MesosTaskInfo]].withDefaultValue(Nil)\n+\n+    // offerID -> resources\n+    val remainingResources = HashMap[String, JList[Resource]](offers.map(offer =>\n+      (offer.getId.getValue, offer.getResourcesList)): _*)\n+\n+    var launchTasks = true\n+\n+    // TODO(mgummelt): combine offers for a single slave\n+    // round-robin create executors on the available offers\n+    while (launchTasks) {\n+      launchTasks = false\n+\n+      for (offer <- offers) {\n         val slaveId = offer.getSlaveId.getValue\n-        val mem = getResource(offer.getResourcesList, \"mem\")\n-        val cpus = getResource(offer.getResourcesList, \"cpus\").toInt\n-        val id = offer.getId.getValue\n-        if (meetsConstraints) {\n-          if (taskIdToSlaveId.size < executorLimit &&\n-              totalCoresAcquired < maxCores &&\n-              mem >= calculateTotalMemory(sc) &&\n-              cpus >= 1 &&\n-              failuresBySlaveId.getOrElse(slaveId, 0) < MAX_SLAVE_FAILURES &&\n-              !slaveIdsWithExecutors.contains(slaveId)) {\n-            // Launch an executor on the slave\n-            val cpusToUse = math.min(cpus, maxCores - totalCoresAcquired)\n-            totalCoresAcquired += cpusToUse\n-            val taskId = newMesosTaskId()\n-            taskIdToSlaveId.put(taskId, slaveId)\n-            slaveIdsWithExecutors += slaveId\n-            coresByTaskId(taskId) = cpusToUse\n-            // Gather cpu resources from the available resources and use them in the task.\n-            val (remainingResources, cpuResourcesToUse) =\n-              partitionResources(offer.getResourcesList, \"cpus\", cpusToUse)\n-            val (_, memResourcesToUse) =\n-              partitionResources(remainingResources.asJava, \"mem\", calculateTotalMemory(sc))\n-            val taskBuilder = MesosTaskInfo.newBuilder()\n-              .setTaskId(TaskID.newBuilder().setValue(taskId.toString).build())\n-              .setSlaveId(offer.getSlaveId)\n-              .setCommand(createCommand(offer, cpusToUse + extraCoresPerSlave, taskId))\n-              .setName(\"Task \" + taskId)\n-              .addAllResources(cpuResourcesToUse.asJava)\n-              .addAllResources(memResourcesToUse.asJava)\n-\n-            sc.conf.getOption(\"spark.mesos.executor.docker.image\").foreach { image =>\n-              MesosSchedulerBackendUtil\n-                .setupContainerBuilderDockerInfo(image, sc.conf, taskBuilder.getContainerBuilder())\n-            }\n-\n-            // Accept the offer and launch the task\n-            logDebug(s\"Accepting offer: $id with attributes: $offerAttributes mem: $mem cpu: $cpus\")\n-            slaveIdToHost(offer.getSlaveId.getValue) = offer.getHostname\n-            d.launchTasks(\n-              Collections.singleton(offer.getId),\n-              Collections.singleton(taskBuilder.build()), filters)\n-          } else {\n-            // Decline the offer\n-            logDebug(s\"Declining offer: $id with attributes: $offerAttributes mem: $mem cpu: $cpus\")\n-            d.declineOffer(offer.getId)\n+        val offerId = offer.getId.getValue\n+        val resources = remainingResources(offerId)\n+\n+        if (canLaunchTask(slaveId, resources)) {\n+          // Create a task\n+          launchTasks = true\n+          val taskId = newMesosTaskId()\n+          val offerCPUs = getResource(resources, \"cpus\").toInt\n+\n+          val taskCPUs = calculateTotalCPUs(offerCPUs)\n+          val taskMemory = calculateTotalMemory(sc)\n+\n+          slaves.getOrElseUpdate(slaveId, new Slave(offer.getHostname)).taskIDs.add(taskId)\n+\n+          val (afterCPUResources, cpuResourcesToUse) =\n+            partitionResources(resources, \"cpus\", taskCPUs)\n+          val (resourcesLeft, memResourcesToUse) =\n+            partitionResources(afterCPUResources.asJava, \"mem\", taskMemory)\n+\n+          val taskBuilder = MesosTaskInfo.newBuilder()\n+            .setTaskId(TaskID.newBuilder().setValue(taskId.toString).build())\n+            .setSlaveId(offer.getSlaveId)\n+            .setCommand(createCommand(offer, taskCPUs + extraCoresPerExecutor, taskId))\n+            .setName(\"Task \" + taskId)\n+            .addAllResources(cpuResourcesToUse.asJava)\n+            .addAllResources(memResourcesToUse.asJava)\n+\n+          sc.conf.getOption(\"spark.mesos.executor.docker.image\").foreach { image =>\n+            MesosSchedulerBackendUtil\n+              .setupContainerBuilderDockerInfo(image, sc.conf, taskBuilder.getContainerBuilder)\n           }\n-        } else {\n-          // This offer does not meet constraints. We don't need to see it again.\n-          // Decline the offer for a long period of time.\n-          logDebug(s\"Declining offer: $id with attributes: $offerAttributes mem: $mem cpu: $cpus\"\n-              + s\" for $rejectOfferDurationForUnmetConstraints seconds\")\n-          d.declineOffer(offer.getId, Filters.newBuilder()\n-            .setRefuseSeconds(rejectOfferDurationForUnmetConstraints).build())\n+\n+          tasks(offer.getId) ::= taskBuilder.build()\n+          remainingResources(offerId) = resourcesLeft.asJava\n+          totalCoresAcquired += taskCPUs\n+          coresByTaskId(taskId) = taskCPUs\n         }\n       }\n     }\n+    tasks\n   }\n \n+  private def canLaunchTask(slaveId: String, resources: JList[Resource]): Boolean = {\n+    val offerMem = getResource(resources, \"mem\")\n+    val offerCPUs = getResource(resources, \"cpus\").toInt\n+    val cpus = calculateTotalCPUs(offerCPUs)\n+    val mem = calculateTotalMemory(sc)\n+\n+    cpus > 0 &&\n+      cpus <= offerCPUs &&\n+      cpus + totalCoresAcquired <= maxCores &&\n+      mem <= offerMem &&\n+      slaves.values.map(_.taskIDs.size).sum < executorLimit &&\n+      slaves.get(slaveId).map(_.taskFailures).getOrElse(0) < MAX_SLAVE_FAILURES\n+  }\n+\n+  private def calculateTotalCPUs(offerCPUs: Int): Int = {","path":"core/src/main/scala/org/apache/spark/scheduler/cluster/mesos/CoarseMesosSchedulerBackend.scala","position":325,"original_position":325,"commit_id":"318486ef4302f997f18904437dda1a550e423bb6","original_commit_id":"318486ef4302f997f18904437dda1a550e423bb6","user":{"login":"mgummelt","id":153734,"avatar_url":"https://avatars.githubusercontent.com/u/153734?v=3","gravatar_id":"","url":"https://api.github.com/users/mgummelt","html_url":"https://github.com/mgummelt","followers_url":"https://api.github.com/users/mgummelt/followers","following_url":"https://api.github.com/users/mgummelt/following{/other_user}","gists_url":"https://api.github.com/users/mgummelt/gists{/gist_id}","starred_url":"https://api.github.com/users/mgummelt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mgummelt/subscriptions","organizations_url":"https://api.github.com/users/mgummelt/orgs","repos_url":"https://api.github.com/users/mgummelt/repos","events_url":"https://api.github.com/users/mgummelt/events{/privacy}","received_events_url":"https://api.github.com/users/mgummelt/received_events","type":"User","site_admin":false},"body":"I agree that this is a bad name, but I'm trying to be consistent with the existing `calculateTotalMemory`.  I could change both if you'd like, but I think consistency is most important.","created_at":"2016-02-02T22:58:04Z","updated_at":"2016-02-02T22:58:04Z","html_url":"https://github.com/apache/spark/pull/10993#discussion_r51650895","pull_request_url":"https://api.github.com/repos/apache/spark/pulls/10993","_links":{"self":{"href":"https://api.github.com/repos/apache/spark/pulls/comments/51650895"},"html":{"href":"https://github.com/apache/spark/pull/10993#discussion_r51650895"},"pull_request":{"href":"https://api.github.com/repos/apache/spark/pulls/10993"}}},"pull_request":{"url":"https://api.github.com/repos/apache/spark/pulls/10993","id":57719878,"html_url":"https://github.com/apache/spark/pull/10993","diff_url":"https://github.com/apache/spark/pull/10993.diff","patch_url":"https://github.com/apache/spark/pull/10993.patch","issue_url":"https://api.github.com/repos/apache/spark/issues/10993","number":10993,"state":"open","locked":false,"title":"[SPARK-5095] [Mesos] Support launching multiple mesos executors in coarse grained mesos mode.","user":{"login":"mgummelt","id":153734,"avatar_url":"https://avatars.githubusercontent.com/u/153734?v=3","gravatar_id":"","url":"https://api.github.com/users/mgummelt","html_url":"https://github.com/mgummelt","followers_url":"https://api.github.com/users/mgummelt/followers","following_url":"https://api.github.com/users/mgummelt/following{/other_user}","gists_url":"https://api.github.com/users/mgummelt/gists{/gist_id}","starred_url":"https://api.github.com/users/mgummelt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mgummelt/subscriptions","organizations_url":"https://api.github.com/users/mgummelt/orgs","repos_url":"https://api.github.com/users/mgummelt/repos","events_url":"https://api.github.com/users/mgummelt/events{/privacy}","received_events_url":"https://api.github.com/users/mgummelt/received_events","type":"User","site_admin":false},"body":"This is the next iteration of @tnachen's previous PR: https://github.com/apache/spark/pull/4027\r\n\r\nIn that PR, we resolved with @andrewor14 and @pwendell to implement the Mesos scheduler's support of `spark.executor.cores` to be consistent with YARN and Standalone.  This PR implements that resolution.\r\n\r\nThis PR implements two high-level features.  These two features are co-dependent, so they're implemented both here:\r\n- Mesos support for spark.executor.cores\r\n- Multiple executors per slave\r\n\r\nWe at Mesosphere have been working with Typesafe on a Spark/Mesos integration test suite: https://github.com/typesafehub/mesos-spark-integration-tests, which passes for this PR.\r\n\r\nThe contribution is my original work and I license the work to the project under the project's open source license. \r\n","created_at":"2016-01-30T00:00:02Z","updated_at":"2016-02-02T22:58:04Z","closed_at":null,"merged_at":null,"merge_commit_sha":"b1ed5b6d7eb94d12b6f90d3239b6737dd1332f67","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/apache/spark/pulls/10993/commits","review_comments_url":"https://api.github.com/repos/apache/spark/pulls/10993/comments","review_comment_url":"https://api.github.com/repos/apache/spark/pulls/comments{/number}","comments_url":"https://api.github.com/repos/apache/spark/issues/10993/comments","statuses_url":"https://api.github.com/repos/apache/spark/statuses/318486ef4302f997f18904437dda1a550e423bb6","head":{"label":"mesosphere:executor_sizing","ref":"executor_sizing","sha":"318486ef4302f997f18904437dda1a550e423bb6","user":{"login":"mesosphere","id":3458585,"avatar_url":"https://avatars.githubusercontent.com/u/3458585?v=3","gravatar_id":"","url":"https://api.github.com/users/mesosphere","html_url":"https://github.com/mesosphere","followers_url":"https://api.github.com/users/mesosphere/followers","following_url":"https://api.github.com/users/mesosphere/following{/other_user}","gists_url":"https://api.github.com/users/mesosphere/gists{/gist_id}","starred_url":"https://api.github.com/users/mesosphere/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mesosphere/subscriptions","organizations_url":"https://api.github.com/users/mesosphere/orgs","repos_url":"https://api.github.com/users/mesosphere/repos","events_url":"https://api.github.com/users/mesosphere/events{/privacy}","received_events_url":"https://api.github.com/users/mesosphere/received_events","type":"Organization","site_admin":false},"repo":{"id":34087729,"name":"spark","full_name":"mesosphere/spark","owner":{"login":"mesosphere","id":3458585,"avatar_url":"https://avatars.githubusercontent.com/u/3458585?v=3","gravatar_id":"","url":"https://api.github.com/users/mesosphere","html_url":"https://github.com/mesosphere","followers_url":"https://api.github.com/users/mesosphere/followers","following_url":"https://api.github.com/users/mesosphere/following{/other_user}","gists_url":"https://api.github.com/users/mesosphere/gists{/gist_id}","starred_url":"https://api.github.com/users/mesosphere/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mesosphere/subscriptions","organizations_url":"https://api.github.com/users/mesosphere/orgs","repos_url":"https://api.github.com/users/mesosphere/repos","events_url":"https://api.github.com/users/mesosphere/events{/privacy}","received_events_url":"https://api.github.com/users/mesosphere/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mesosphere/spark","description":"Mirror of Apache Spark","fork":true,"url":"https://api.github.com/repos/mesosphere/spark","forks_url":"https://api.github.com/repos/mesosphere/spark/forks","keys_url":"https://api.github.com/repos/mesosphere/spark/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mesosphere/spark/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mesosphere/spark/teams","hooks_url":"https://api.github.com/repos/mesosphere/spark/hooks","issue_events_url":"https://api.github.com/repos/mesosphere/spark/issues/events{/number}","events_url":"https://api.github.com/repos/mesosphere/spark/events","assignees_url":"https://api.github.com/repos/mesosphere/spark/assignees{/user}","branches_url":"https://api.github.com/repos/mesosphere/spark/branches{/branch}","tags_url":"https://api.github.com/repos/mesosphere/spark/tags","blobs_url":"https://api.github.com/repos/mesosphere/spark/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mesosphere/spark/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mesosphere/spark/git/refs{/sha}","trees_url":"https://api.github.com/repos/mesosphere/spark/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mesosphere/spark/statuses/{sha}","languages_url":"https://api.github.com/repos/mesosphere/spark/languages","stargazers_url":"https://api.github.com/repos/mesosphere/spark/stargazers","contributors_url":"https://api.github.com/repos/mesosphere/spark/contributors","subscribers_url":"https://api.github.com/repos/mesosphere/spark/subscribers","subscription_url":"https://api.github.com/repos/mesosphere/spark/subscription","commits_url":"https://api.github.com/repos/mesosphere/spark/commits{/sha}","git_commits_url":"https://api.github.com/repos/mesosphere/spark/git/commits{/sha}","comments_url":"https://api.github.com/repos/mesosphere/spark/comments{/number}","issue_comment_url":"https://api.github.com/repos/mesosphere/spark/issues/comments{/number}","contents_url":"https://api.github.com/repos/mesosphere/spark/contents/{+path}","compare_url":"https://api.github.com/repos/mesosphere/spark/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mesosphere/spark/merges","archive_url":"https://api.github.com/repos/mesosphere/spark/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mesosphere/spark/downloads","issues_url":"https://api.github.com/repos/mesosphere/spark/issues{/number}","pulls_url":"https://api.github.com/repos/mesosphere/spark/pulls{/number}","milestones_url":"https://api.github.com/repos/mesosphere/spark/milestones{/number}","notifications_url":"https://api.github.com/repos/mesosphere/spark/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mesosphere/spark/labels{/name}","releases_url":"https://api.github.com/repos/mesosphere/spark/releases{/id}","deployments_url":"https://api.github.com/repos/mesosphere/spark/deployments","created_at":"2015-04-17T00:19:40Z","updated_at":"2016-01-25T13:12:56Z","pushed_at":"2016-02-02T14:45:37Z","git_url":"git://github.com/mesosphere/spark.git","ssh_url":"git@github.com:mesosphere/spark.git","clone_url":"https://github.com/mesosphere/spark.git","svn_url":"https://github.com/mesosphere/spark","homepage":null,"size":141215,"stargazers_count":1,"watchers_count":1,"language":"Scala","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":2,"mirror_url":null,"open_issues_count":2,"forks":2,"open_issues":2,"watchers":1,"default_branch":"master"}},"base":{"label":"apache:master","ref":"master","sha":"be7a2fc0716b7d25327b6f8f683390fc62532e3b","user":{"login":"apache","id":47359,"avatar_url":"https://avatars.githubusercontent.com/u/47359?v=3","gravatar_id":"","url":"https://api.github.com/users/apache","html_url":"https://github.com/apache","followers_url":"https://api.github.com/users/apache/followers","following_url":"https://api.github.com/users/apache/following{/other_user}","gists_url":"https://api.github.com/users/apache/gists{/gist_id}","starred_url":"https://api.github.com/users/apache/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apache/subscriptions","organizations_url":"https://api.github.com/users/apache/orgs","repos_url":"https://api.github.com/users/apache/repos","events_url":"https://api.github.com/users/apache/events{/privacy}","received_events_url":"https://api.github.com/users/apache/received_events","type":"Organization","site_admin":false},"repo":{"id":17165658,"name":"spark","full_name":"apache/spark","owner":{"login":"apache","id":47359,"avatar_url":"https://avatars.githubusercontent.com/u/47359?v=3","gravatar_id":"","url":"https://api.github.com/users/apache","html_url":"https://github.com/apache","followers_url":"https://api.github.com/users/apache/followers","following_url":"https://api.github.com/users/apache/following{/other_user}","gists_url":"https://api.github.com/users/apache/gists{/gist_id}","starred_url":"https://api.github.com/users/apache/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apache/subscriptions","organizations_url":"https://api.github.com/users/apache/orgs","repos_url":"https://api.github.com/users/apache/repos","events_url":"https://api.github.com/users/apache/events{/privacy}","received_events_url":"https://api.github.com/users/apache/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/apache/spark","description":"Mirror of Apache Spark","fork":false,"url":"https://api.github.com/repos/apache/spark","forks_url":"https://api.github.com/repos/apache/spark/forks","keys_url":"https://api.github.com/repos/apache/spark/keys{/key_id}","collaborators_url":"https://api.github.com/repos/apache/spark/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/apache/spark/teams","hooks_url":"https://api.github.com/repos/apache/spark/hooks","issue_events_url":"https://api.github.com/repos/apache/spark/issues/events{/number}","events_url":"https://api.github.com/repos/apache/spark/events","assignees_url":"https://api.github.com/repos/apache/spark/assignees{/user}","branches_url":"https://api.github.com/repos/apache/spark/branches{/branch}","tags_url":"https://api.github.com/repos/apache/spark/tags","blobs_url":"https://api.github.com/repos/apache/spark/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/apache/spark/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/apache/spark/git/refs{/sha}","trees_url":"https://api.github.com/repos/apache/spark/git/trees{/sha}","statuses_url":"https://api.github.com/repos/apache/spark/statuses/{sha}","languages_url":"https://api.github.com/repos/apache/spark/languages","stargazers_url":"https://api.github.com/repos/apache/spark/stargazers","contributors_url":"https://api.github.com/repos/apache/spark/contributors","subscribers_url":"https://api.github.com/repos/apache/spark/subscribers","subscription_url":"https://api.github.com/repos/apache/spark/subscription","commits_url":"https://api.github.com/repos/apache/spark/commits{/sha}","git_commits_url":"https://api.github.com/repos/apache/spark/git/commits{/sha}","comments_url":"https://api.github.com/repos/apache/spark/comments{/number}","issue_comment_url":"https://api.github.com/repos/apache/spark/issues/comments{/number}","contents_url":"https://api.github.com/repos/apache/spark/contents/{+path}","compare_url":"https://api.github.com/repos/apache/spark/compare/{base}...{head}","merges_url":"https://api.github.com/repos/apache/spark/merges","archive_url":"https://api.github.com/repos/apache/spark/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/apache/spark/downloads","issues_url":"https://api.github.com/repos/apache/spark/issues{/number}","pulls_url":"https://api.github.com/repos/apache/spark/pulls{/number}","milestones_url":"https://api.github.com/repos/apache/spark/milestones{/number}","notifications_url":"https://api.github.com/repos/apache/spark/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/apache/spark/labels{/name}","releases_url":"https://api.github.com/repos/apache/spark/releases{/id}","deployments_url":"https://api.github.com/repos/apache/spark/deployments","created_at":"2014-02-25T08:00:08Z","updated_at":"2016-02-02T22:50:20Z","pushed_at":"2016-02-02T22:45:37Z","git_url":"git://github.com/apache/spark.git","ssh_url":"git@github.com:apache/spark.git","clone_url":"https://github.com/apache/spark.git","svn_url":"https://github.com/apache/spark","homepage":null,"size":408212,"stargazers_count":7314,"watchers_count":7314,"language":"Scala","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":6658,"mirror_url":"git://git.apache.org/spark.git","open_issues_count":358,"forks":6658,"open_issues":358,"watchers":7314,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/apache/spark/pulls/10993"},"html":{"href":"https://github.com/apache/spark/pull/10993"},"issue":{"href":"https://api.github.com/repos/apache/spark/issues/10993"},"comments":{"href":"https://api.github.com/repos/apache/spark/issues/10993/comments"},"review_comments":{"href":"https://api.github.com/repos/apache/spark/pulls/10993/comments"},"review_comment":{"href":"https://api.github.com/repos/apache/spark/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/apache/spark/pulls/10993/commits"},"statuses":{"href":"https://api.github.com/repos/apache/spark/statuses/318486ef4302f997f18904437dda1a550e423bb6"}}}}