Skip to content
Snippets Groups Projects
Commit e47253e0 authored by Charles Reiss's avatar Charles Reiss
Browse files

Reset ClassLoader in MesosSchedulerBackend, too. (per review comments).

Also set ClassLoader for all mesos callbacks, not just statusUpdate,
registered.
parent 8c1d1c98
No related branches found
No related tags found
No related merge requests found
...@@ -118,20 +118,28 @@ private[spark] class MesosSchedulerBackend( ...@@ -118,20 +118,28 @@ private[spark] class MesosSchedulerBackend(
return execArgs return execArgs
} }
private def setClassLoader() { private def setClassLoader(): ClassLoader = {
// Since native code starts the thread our callbacks run in, it may not correctly val oldClassLoader = Thread.currentThread.getContextClassLoader
// inherit and custom class loaders. Therefore, set the class loader manually.
Thread.currentThread.setContextClassLoader(classLoader) Thread.currentThread.setContextClassLoader(classLoader)
return oldClassLoader
}
private def restoreClassLoader(oldClassLoader: ClassLoader) {
Thread.currentThread.setContextClassLoader(oldClassLoader)
} }
override def offerRescinded(d: SchedulerDriver, o: OfferID) {} override def offerRescinded(d: SchedulerDriver, o: OfferID) {}
override def registered(d: SchedulerDriver, frameworkId: FrameworkID, masterInfo: MasterInfo) { override def registered(d: SchedulerDriver, frameworkId: FrameworkID, masterInfo: MasterInfo) {
setClassLoader() val oldClassLoader = setClassLoader()
logInfo("Registered as framework ID " + frameworkId.getValue) try {
registeredLock.synchronized { logInfo("Registered as framework ID " + frameworkId.getValue)
isRegistered = true registeredLock.synchronized {
registeredLock.notifyAll() isRegistered = true
registeredLock.notifyAll()
}
} finally {
restoreClassLoader(oldClassLoader)
} }
} }
...@@ -153,50 +161,54 @@ private[spark] class MesosSchedulerBackend( ...@@ -153,50 +161,54 @@ private[spark] class MesosSchedulerBackend(
* tasks are balanced across the cluster. * tasks are balanced across the cluster.
*/ */
override def resourceOffers(d: SchedulerDriver, offers: JList[Offer]) { override def resourceOffers(d: SchedulerDriver, offers: JList[Offer]) {
setClassLoader() val oldClassLoader = setClassLoader()
synchronized { try {
// Build a big list of the offerable workers, and remember their indices so that we can synchronized {
// figure out which Offer to reply to for each worker // Build a big list of the offerable workers, and remember their indices so that we can
val offerableIndices = new ArrayBuffer[Int] // figure out which Offer to reply to for each worker
val offerableWorkers = new ArrayBuffer[WorkerOffer] val offerableIndices = new ArrayBuffer[Int]
val offerableWorkers = new ArrayBuffer[WorkerOffer]
def enoughMemory(o: Offer) = {
val mem = getResource(o.getResourcesList, "mem") def enoughMemory(o: Offer) = {
val slaveId = o.getSlaveId.getValue val mem = getResource(o.getResourcesList, "mem")
mem >= executorMemory || slaveIdsWithExecutors.contains(slaveId) val slaveId = o.getSlaveId.getValue
} mem >= executorMemory || slaveIdsWithExecutors.contains(slaveId)
}
for ((offer, index) <- offers.zipWithIndex if enoughMemory(offer)) { for ((offer, index) <- offers.zipWithIndex if enoughMemory(offer)) {
offerableIndices += index offerableIndices += index
offerableWorkers += new WorkerOffer( offerableWorkers += new WorkerOffer(
offer.getSlaveId.getValue, offer.getSlaveId.getValue,
offer.getHostname, offer.getHostname,
getResource(offer.getResourcesList, "cpus").toInt) getResource(offer.getResourcesList, "cpus").toInt)
} }
// Call into the ClusterScheduler // Call into the ClusterScheduler
val taskLists = scheduler.resourceOffers(offerableWorkers) val taskLists = scheduler.resourceOffers(offerableWorkers)
// Build a list of Mesos tasks for each slave // Build a list of Mesos tasks for each slave
val mesosTasks = offers.map(o => Collections.emptyList[MesosTaskInfo]()) val mesosTasks = offers.map(o => Collections.emptyList[MesosTaskInfo]())
for ((taskList, index) <- taskLists.zipWithIndex) { for ((taskList, index) <- taskLists.zipWithIndex) {
if (!taskList.isEmpty) { if (!taskList.isEmpty) {
val offerNum = offerableIndices(index) val offerNum = offerableIndices(index)
val slaveId = offers(offerNum).getSlaveId.getValue val slaveId = offers(offerNum).getSlaveId.getValue
slaveIdsWithExecutors += slaveId slaveIdsWithExecutors += slaveId
mesosTasks(offerNum) = new JArrayList[MesosTaskInfo](taskList.size) mesosTasks(offerNum) = new JArrayList[MesosTaskInfo](taskList.size)
for (taskDesc <- taskList) { for (taskDesc <- taskList) {
taskIdToSlaveId(taskDesc.taskId) = slaveId taskIdToSlaveId(taskDesc.taskId) = slaveId
mesosTasks(offerNum).add(createMesosTask(taskDesc, slaveId)) mesosTasks(offerNum).add(createMesosTask(taskDesc, slaveId))
}
} }
} }
}
// Reply to the offers // Reply to the offers
val filters = Filters.newBuilder().setRefuseSeconds(1).build() // TODO: lower timeout? val filters = Filters.newBuilder().setRefuseSeconds(1).build() // TODO: lower timeout?
for (i <- 0 until offers.size) { for (i <- 0 until offers.size) {
d.launchTasks(offers(i).getId, mesosTasks(i), filters) d.launchTasks(offers(i).getId, mesosTasks(i), filters)
}
} }
} finally {
restoreClassLoader(oldClassLoader)
} }
} }
...@@ -236,24 +248,33 @@ private[spark] class MesosSchedulerBackend( ...@@ -236,24 +248,33 @@ private[spark] class MesosSchedulerBackend(
} }
override def statusUpdate(d: SchedulerDriver, status: TaskStatus) { override def statusUpdate(d: SchedulerDriver, status: TaskStatus) {
setClassLoader() val oldClassLoader = setClassLoader()
val tid = status.getTaskId.getValue.toLong try {
val state = TaskState.fromMesos(status.getState) val tid = status.getTaskId.getValue.toLong
synchronized { val state = TaskState.fromMesos(status.getState)
if (status.getState == MesosTaskState.TASK_LOST && taskIdToSlaveId.contains(tid)) { synchronized {
// We lost the executor on this slave, so remember that it's gone if (status.getState == MesosTaskState.TASK_LOST && taskIdToSlaveId.contains(tid)) {
slaveIdsWithExecutors -= taskIdToSlaveId(tid) // We lost the executor on this slave, so remember that it's gone
} slaveIdsWithExecutors -= taskIdToSlaveId(tid)
if (isFinished(status.getState)) { }
taskIdToSlaveId.remove(tid) if (isFinished(status.getState)) {
taskIdToSlaveId.remove(tid)
}
} }
scheduler.statusUpdate(tid, state, status.getData.asReadOnlyByteBuffer)
} finally {
restoreClassLoader(oldClassLoader)
} }
scheduler.statusUpdate(tid, state, status.getData.asReadOnlyByteBuffer)
} }
override def error(d: SchedulerDriver, message: String) { override def error(d: SchedulerDriver, message: String) {
logError("Mesos error: " + message) val oldClassLoader = setClassLoader()
scheduler.error(message) try {
logError("Mesos error: " + message)
scheduler.error(message)
} finally {
restoreClassLoader(oldClassLoader)
}
} }
override def stop() { override def stop() {
...@@ -269,11 +290,16 @@ private[spark] class MesosSchedulerBackend( ...@@ -269,11 +290,16 @@ private[spark] class MesosSchedulerBackend(
override def frameworkMessage(d: SchedulerDriver, e: ExecutorID, s: SlaveID, b: Array[Byte]) {} override def frameworkMessage(d: SchedulerDriver, e: ExecutorID, s: SlaveID, b: Array[Byte]) {}
private def recordSlaveLost(d: SchedulerDriver, slaveId: SlaveID, reason: ExecutorLossReason) { private def recordSlaveLost(d: SchedulerDriver, slaveId: SlaveID, reason: ExecutorLossReason) {
logInfo("Mesos slave lost: " + slaveId.getValue) val oldClassLoader = setClassLoader()
synchronized { try {
slaveIdsWithExecutors -= slaveId.getValue logInfo("Mesos slave lost: " + slaveId.getValue)
synchronized {
slaveIdsWithExecutors -= slaveId.getValue
}
scheduler.executorLost(slaveId.getValue, reason)
} finally {
restoreClassLoader(oldClassLoader)
} }
scheduler.executorLost(slaveId.getValue, reason)
} }
override def slaveLost(d: SchedulerDriver, slaveId: SlaveID) { override def slaveLost(d: SchedulerDriver, slaveId: SlaveID) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment