The jenkins gearman plugin
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MyGearmanWorkerImpl.java 24KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660
  1. /*
  2. *
  3. * Copyright 2013 OpenStack Foundation
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. /*
  19. * This is adapted from gearman-java with the following license
  20. *
  21. * Copyright (C) 2013 by Eric Lambert <eric.d.lambert@gmail.com>
  22. * Use and distribution licensed under the BSD license. See
  23. * the COPYING file in the parent directory for full text.
  24. */
  25. package hudson.plugins.gearman;
  26. import java.io.IOException;
  27. import java.nio.channels.SelectionKey;
  28. import java.nio.channels.Selector;
  29. import java.util.ArrayList;
  30. import java.util.HashMap;
  31. import java.util.HashSet;
  32. import java.util.Iterator;
  33. import java.util.LinkedList;
  34. import java.util.List;
  35. import java.util.Map;
  36. import java.util.Queue;
  37. import java.util.Set;
  38. import java.util.concurrent.ConcurrentLinkedQueue;
  39. import java.util.concurrent.ExecutorService;
  40. import org.gearman.common.Constants;
  41. import org.gearman.common.GearmanException;
  42. import org.gearman.common.GearmanJobServerConnection;
  43. import org.gearman.common.GearmanJobServerIpConnectionFactory;
  44. import org.gearman.common.GearmanJobServerSession;
  45. import org.gearman.common.GearmanNIOJobServerConnectionFactory;
  46. import org.gearman.common.GearmanPacket;
  47. import org.gearman.common.GearmanPacket.DataComponentName;
  48. import org.gearman.common.GearmanPacketImpl;
  49. import org.gearman.common.GearmanPacketMagic;
  50. import org.gearman.common.GearmanPacketType;
  51. import org.gearman.common.GearmanServerResponseHandler;
  52. import org.gearman.common.GearmanSessionEvent;
  53. import org.gearman.common.GearmanSessionEventHandler;
  54. import org.gearman.common.GearmanTask;
  55. import org.gearman.worker.DefaultGearmanFunctionFactory;
  56. import org.gearman.worker.GearmanFunction;
  57. import org.gearman.worker.GearmanFunctionFactory;
  58. import org.gearman.worker.GearmanWorker;
  59. import org.gearman.util.ByteUtils;
  60. import org.slf4j.LoggerFactory;
  61. public class MyGearmanWorkerImpl implements GearmanSessionEventHandler {
  62. static public enum State {
  63. IDLE, RUNNING, SHUTTINGDOWN
  64. }
  65. private static final String DESCRIPION_PREFIX = "GearmanWorker";
  66. private ConcurrentLinkedQueue<GearmanSessionEvent> eventList = null;
  67. private Selector ioAvailable = null;
  68. private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(
  69. Constants.GEARMAN_WORKER_LOGGER_NAME);
  70. private String id;
  71. private Map<String, FunctionDefinition> functionMap;
  72. private State state;
  73. private ExecutorService executorService;
  74. private GearmanJobServerSession session = null;
  75. private final GearmanJobServerIpConnectionFactory connFactory = new GearmanNIOJobServerConnectionFactory();
  76. private volatile boolean jobUniqueIdRequired = false;
  77. private FunctionRegistry functionRegistry;
  78. private AvailabilityMonitor availability;
  79. class GrabJobEventHandler implements GearmanServerResponseHandler {
  80. private final GearmanJobServerSession session;
  81. private boolean isDone = false;
  82. GrabJobEventHandler(GearmanJobServerSession session) {
  83. super();
  84. this.session = session;
  85. }
  86. public void handleEvent(GearmanPacket event) throws GearmanException {
  87. handleSessionEvent(new GearmanSessionEvent(event, session));
  88. isDone = true;
  89. }
  90. public boolean isDone() {
  91. return isDone;
  92. }
  93. }
  94. static class FunctionDefinition {
  95. private final long timeout;
  96. private final GearmanFunctionFactory factory;
  97. FunctionDefinition(long timeout, GearmanFunctionFactory factory) {
  98. this.timeout = timeout;
  99. this.factory = factory;
  100. }
  101. long getTimeout() {
  102. return timeout;
  103. }
  104. GearmanFunctionFactory getFactory() {
  105. return factory;
  106. }
  107. }
  108. class FunctionRegistry {
  109. private Set<GearmanFunctionFactory> functions;
  110. private boolean updated = false;
  111. FunctionRegistry() {
  112. functions = new HashSet<GearmanFunctionFactory>();
  113. }
  114. public synchronized Set<GearmanFunctionFactory> getFunctions(){
  115. if (updated) {
  116. updated = false;
  117. return functions;
  118. } else {
  119. return null;
  120. }
  121. }
  122. public synchronized void setFunctions(Set<GearmanFunctionFactory> functions){
  123. this.functions = functions;
  124. this.updated = true;
  125. }
  126. public synchronized void setUpdated(boolean updated) {
  127. this.updated = updated;
  128. }
  129. }
  130. public void reconnect() {
  131. LOG.info("---- Worker " + this + " starting reconnect for " + session.toString());
  132. // In case we held the availability lock earlier, release it.
  133. availability.unlock(this);
  134. try {
  135. session.initSession(ioAvailable, this);
  136. if (id != null) {
  137. sendToAll(new GearmanPacketImpl(GearmanPacketMagic.REQ,
  138. GearmanPacketType.SET_CLIENT_ID,
  139. ByteUtils.toUTF8Bytes(id)));
  140. }
  141. // Reset events so that we don't process events from the old
  142. // connection.
  143. eventList = new ConcurrentLinkedQueue<GearmanSessionEvent>();
  144. // this will cause a grab-job event
  145. functionRegistry.setUpdated(true);
  146. // Make sure we reset the function list
  147. functionMap.clear();
  148. } catch (IOException e) {
  149. try {
  150. Thread.sleep(2000);
  151. } catch (InterruptedException e1) {
  152. LOG.warn("---- Worker " + this + " interrupted while reconnecting", e);
  153. return;
  154. }
  155. }
  156. LOG.info("---- Worker " + this + " ending reconnect for " + session.toString());
  157. }
  158. public MyGearmanWorkerImpl(AvailabilityMonitor availability) {
  159. this (null, availability);
  160. }
  161. public MyGearmanWorkerImpl(ExecutorService executorService,
  162. AvailabilityMonitor availability) {
  163. this.availability = availability;
  164. eventList = new ConcurrentLinkedQueue<GearmanSessionEvent>();
  165. id = DESCRIPION_PREFIX + ":" + Thread.currentThread().getId();
  166. functionMap = new HashMap<String, FunctionDefinition>();
  167. state = State.IDLE;
  168. this.executorService = executorService;
  169. functionRegistry = new FunctionRegistry();
  170. try {
  171. ioAvailable = Selector.open();
  172. } catch (IOException ioe) {
  173. LOG.warn("---- Worker " + this + " failed to open IO selector", ioe);
  174. }
  175. }
  176. @Override
  177. public String toString() {
  178. return id;
  179. }
  180. public void setFunctions(Set<GearmanFunctionFactory> functions) {
  181. LOG.info("---- Worker " + this + " registering " + functions.size() + " functions");
  182. functionRegistry.setFunctions(functions);
  183. ioAvailable.wakeup();
  184. }
  185. /**
  186. * This is a small lie -- it only returns the functions it has been
  187. * instructed to register, not the ones it has actually gotton around
  188. * to registering. This is mostly here for tests.
  189. **/
  190. public Set getRegisteredFunctions() {
  191. Set<String> ret = new HashSet<String>();
  192. Set<GearmanFunctionFactory> functions = functionRegistry.getFunctions();
  193. if (functions == null) {
  194. return ret;
  195. }
  196. for (GearmanFunctionFactory factory: functions) {
  197. ret.add(factory.getFunctionName());
  198. }
  199. return ret;
  200. }
  201. private void registerFunctions() throws IOException {
  202. Set<GearmanFunctionFactory> functions = functionRegistry.getFunctions();
  203. if (functions == null) {
  204. return;
  205. }
  206. HashMap<String, FunctionDefinition> newFunctionMap = new HashMap<String, FunctionDefinition>();
  207. // If we have no previous data then reset abilities to be sure the
  208. // gearman server has no stale data that we don't know about.
  209. // Or if we have no functions anymore just reset everything, we don't
  210. // need a CANT_DO per lost function.
  211. if (functions.isEmpty() || functionMap.isEmpty()) {
  212. sendToAll(new GearmanPacketImpl(GearmanPacketMagic.REQ,
  213. GearmanPacketType.RESET_ABILITIES, new byte[0]));
  214. session.driveSessionIO();
  215. LOG.debug("---- Worker " + this + " reset functions");
  216. if (!isRunning()) {
  217. // Ensure we start from scratch on reconnection.
  218. functionMap.clear();
  219. return;
  220. }
  221. }
  222. // Now only update if we have data to update.
  223. if (!functions.isEmpty()) {
  224. for (GearmanFunctionFactory factory: functions) {
  225. FunctionDefinition def = new FunctionDefinition(0, factory);
  226. newFunctionMap.put(factory.getFunctionName(), def);
  227. if (!functionMap.containsKey(factory.getFunctionName())) {
  228. sendToAll(generateCanDoPacket(def));
  229. session.driveSessionIO();
  230. if (!isRunning()) {
  231. // Ensure we start from scratch on reconnection.
  232. functionMap.clear();
  233. return;
  234. }
  235. LOG.debug("---- Worker " + this + " registered function " +
  236. factory.getFunctionName());
  237. }
  238. functionMap.remove(factory.getFunctionName());
  239. }
  240. for (FunctionDefinition def: functionMap.values()) {
  241. sendToAll(generateCantDoPacket(def));
  242. session.driveSessionIO();
  243. if (!isRunning()) {
  244. // Ensure we start from scratch on reconnection.
  245. functionMap.clear();
  246. return;
  247. }
  248. LOG.debug("---- Worker " + this + " unregistered function " +
  249. def.getFactory().getFunctionName());
  250. }
  251. }
  252. functionMap = newFunctionMap;
  253. GearmanSessionEvent nextEvent = eventList.peek();
  254. if (nextEvent == null ||
  255. nextEvent.getPacket().getPacketType() != GearmanPacketType.NOOP) {
  256. // Simulate a NOOP packet which will kick off a GRAB_JOB cycle
  257. // if we're sleeping. If we get a real NOOP in the mean time,
  258. // it should be fine because GearmanJobServerSession ignores a
  259. // NOOP if PRE_SLEEP is not on the stack.
  260. GearmanPacket p = new GearmanPacketImpl(GearmanPacketMagic.RES,
  261. GearmanPacketType.NOOP, new byte[0]);
  262. GearmanSessionEvent event = new GearmanSessionEvent(p, session);
  263. session.handleSessionEvent(event);
  264. }
  265. }
  266. public void enqueueNoopEvent() {
  267. // Simulate a NOOP packet which will kick off a GRAB_JOB cycle.
  268. // This unconditionally enqueues the NOOP which will send a GRAB_JOB
  269. // and should only be used when you know you need to send a GRAB_JOB.
  270. // Cases like worker start, post function run, post failure.
  271. GearmanPacket p = new GearmanPacketImpl(GearmanPacketMagic.RES,
  272. GearmanPacketType.NOOP, new byte[0]);
  273. GearmanSessionEvent event = new GearmanSessionEvent(p, session);
  274. enqueueEvent(event);
  275. }
  276. public void work() {
  277. GearmanSessionEvent event = null;
  278. GearmanFunction function = null;
  279. LOG.info("---- Worker " + this + " starting work");
  280. if (!state.equals(State.IDLE)) {
  281. throw new IllegalStateException("Can not call work while worker " +
  282. "is running or shutting down");
  283. }
  284. state = State.RUNNING;
  285. // When we first start working we will already be initialized so must
  286. // enqueue a Noop event to trigger GRAB_JOB here.
  287. enqueueNoopEvent();
  288. while (isRunning()) {
  289. LOG.debug("---- Worker " + this + " top of run loop");
  290. if (!session.isInitialized()) {
  291. LOG.debug("---- Worker " + this + " run loop reconnect");
  292. reconnect();
  293. enqueueNoopEvent();
  294. // Restart loop to check we connected.
  295. continue;
  296. }
  297. try {
  298. LOG.debug("---- Worker " + this + " run loop register functions");
  299. registerFunctions();
  300. } catch (IOException io) {
  301. LOG.warn("---- Worker " + this + " receieved IOException while" +
  302. " registering functions", io);
  303. session.closeSession();
  304. continue;
  305. }
  306. if (!isRunning() || !session.isInitialized()) continue;
  307. event = eventList.poll();
  308. function = processSessionEvent(event);
  309. if (!isRunning() || !session.isInitialized()) continue;
  310. // For the time being we will execute the jobs synchronously
  311. // in the future, I expect to change this.
  312. if (function != null) {
  313. LOG.info("---- Worker " + this + " executing function");
  314. submitFunction(function);
  315. // Send another grab_job on the next loop
  316. enqueueNoopEvent();
  317. // Skip IO as submitFunction drives the IO for function
  318. // running.
  319. continue;
  320. }
  321. if (!isRunning() || !session.isInitialized()) continue;
  322. // Run IO, select waiting for ability to read and/or write
  323. // then read and/or write.
  324. int interestOps = SelectionKey.OP_READ;
  325. if (session.sessionHasDataToWrite()) {
  326. interestOps |= SelectionKey.OP_WRITE;
  327. }
  328. session.getSelectionKey().interestOps(interestOps);
  329. try {
  330. ioAvailable.select();
  331. } catch (IOException io) {
  332. LOG.warn("---- Worker " + this + " receieved IOException while" +
  333. " selecting for IO", io);
  334. session.closeSession();
  335. continue;
  336. }
  337. if (ioAvailable.selectedKeys().contains(session.getSelectionKey())) {
  338. LOG.debug("---- Worker " + this + " received input in run loop");
  339. if (!session.isInitialized()) {
  340. LOG.debug("---- Worker " + this + " session is no longer initialized");
  341. continue;
  342. }
  343. try {
  344. session.driveSessionIO();
  345. } catch (IOException io) {
  346. LOG.warn("---- Worker " + this + " received IOException while driving" +
  347. " IO on session " + session, io);
  348. session.closeSession();
  349. continue;
  350. }
  351. }
  352. LOG.debug("---- Worker " + this + " run loop finished driving session io");
  353. }
  354. shutDownWorker(true);
  355. }
  356. private void sendGrabJob(GearmanJobServerSession s) throws InterruptedException {
  357. // If we can get the lock, this will prevent other workers and
  358. // Jenkins itself from scheduling builds on this node. If we
  359. // can not get the lock, this will wait for it.
  360. availability.lock(this);
  361. GearmanTask grabJobTask = new GearmanTask(
  362. new GrabJobEventHandler(s),
  363. new GearmanPacketImpl(GearmanPacketMagic.REQ,
  364. getGrabJobPacketType(), new byte[0]));
  365. s.submitTask(grabJobTask);
  366. }
  367. public void handleSessionEvent(GearmanSessionEvent event)
  368. throws IllegalArgumentException, IllegalStateException {
  369. enqueueEvent(event);
  370. }
  371. public void enqueueEvent(GearmanSessionEvent event) {
  372. // Enqueue in a thread safe manner. Events will
  373. // be pulled off and processed serially in this workers
  374. // main thread.
  375. eventList.add(event);
  376. }
  377. private GearmanFunction processSessionEvent(GearmanSessionEvent event)
  378. throws IllegalArgumentException, IllegalStateException {
  379. if (event != null) {
  380. GearmanPacket p = event.getPacket();
  381. GearmanJobServerSession s = event.getSession();
  382. GearmanPacketType t = p.getPacketType();
  383. LOG.debug("---- Worker " + this + " handling session event" +
  384. " ( Session = " + s + " Event = " + t + " )");
  385. switch (t) {
  386. case JOB_ASSIGN:
  387. //TODO Figure out what the right behavior is if JobUUIDRequired was false when we submitted but is now true
  388. LOG.info("---- Worker " + this + " received job assignment");
  389. return addNewJob(event);
  390. case JOB_ASSIGN_UNIQ:
  391. //TODO Figure out what the right behavior is if JobUUIDRequired was true when we submitted but is now false
  392. LOG.info("---- Worker " + this + " received unique job assignment");
  393. return addNewJob(event);
  394. case NOOP:
  395. LOG.debug("---- Worker " + this + " sending grab job after wakeup");
  396. try {
  397. sendGrabJob(s);
  398. } catch (InterruptedException e) {
  399. LOG.warn("---- Worker " + this + " interrupted while waiting for okay to send " +
  400. "grab job", e);
  401. }
  402. break;
  403. case NO_JOB:
  404. // We didn't get a job, so allow other workers or
  405. // Jenkins to schedule on this node.
  406. availability.unlock(this);
  407. LOG.debug("---- Worker " + this + " sending pre sleep after no_job");
  408. GearmanTask preSleepTask = new GearmanTask(new GrabJobEventHandler(s),
  409. new GearmanPacketImpl(GearmanPacketMagic.REQ,
  410. GearmanPacketType.PRE_SLEEP, new byte[0]));
  411. s.submitTask(preSleepTask);
  412. break;
  413. case ECHO_RES:
  414. break;
  415. case OPTION_RES:
  416. break;
  417. case ERROR:
  418. s.closeSession();
  419. break;
  420. default:
  421. LOG.warn("---- Worker " + this + " received unknown packet type " + t +
  422. " from session " + s + "; closing connection");
  423. s.closeSession();
  424. }
  425. }
  426. return null;
  427. }
  428. public boolean addServer(String host, int port) {
  429. return addServer(connFactory.createConnection(host, port));
  430. }
  431. public boolean addServer(GearmanJobServerConnection conn)
  432. throws IllegalArgumentException, IllegalStateException {
  433. if (conn == null) {
  434. throw new IllegalArgumentException("Connection can not be null");
  435. }
  436. if (session != null) {
  437. return true;
  438. }
  439. session = new GearmanJobServerSession(conn);
  440. reconnect();
  441. LOG.debug("---- Worker " + this + " added server " + conn);
  442. return true;
  443. }
  444. public void setWorkerID(String id) throws IllegalArgumentException {
  445. if (id == null) {
  446. throw new IllegalArgumentException("Worker ID may not be null");
  447. }
  448. this.id = id;
  449. if (session.isInitialized()) {
  450. sendToAll(new GearmanPacketImpl(GearmanPacketMagic.REQ,
  451. GearmanPacketType.SET_CLIENT_ID,
  452. ByteUtils.toUTF8Bytes(id)));
  453. }
  454. }
  455. public String getWorkerID() {
  456. return id;
  457. }
  458. public void stop() {
  459. state = State.SHUTTINGDOWN;
  460. }
  461. public List<Exception> shutdown() {
  462. return shutDownWorker(false);
  463. }
  464. public boolean isRunning() {
  465. return state.equals(State.RUNNING);
  466. }
  467. public void setJobUniqueIdRequired(boolean requiresJobUUID) {
  468. jobUniqueIdRequired = requiresJobUUID;
  469. }
  470. public boolean isJobUniqueIdRequired() {
  471. return jobUniqueIdRequired;
  472. }
  473. private GearmanPacket generateCanDoPacket(FunctionDefinition def) {
  474. GearmanPacketType pt = GearmanPacketType.CAN_DO;
  475. byte[] data = ByteUtils.toUTF8Bytes(def.getFactory().getFunctionName());
  476. return new GearmanPacketImpl(GearmanPacketMagic.REQ, pt, data);
  477. }
  478. private GearmanPacket generateCantDoPacket(FunctionDefinition def) {
  479. GearmanPacketType pt = GearmanPacketType.CANT_DO;
  480. byte[] data = ByteUtils.toUTF8Bytes(def.getFactory().getFunctionName());
  481. return new GearmanPacketImpl(GearmanPacketMagic.REQ, pt, data);
  482. }
  483. private void sendToAll(GearmanPacket p) {
  484. sendToAll(null, p);
  485. }
  486. private void sendToAll(GearmanServerResponseHandler handler, GearmanPacket p) {
  487. GearmanTask gsr = new GearmanTask(handler, p);
  488. session.submitTask(gsr);
  489. }
  490. /*
  491. * For the time being this will always return an empty list of
  492. * exceptions because closeSession does not throw an exception
  493. */
  494. private List<Exception> shutDownWorker(boolean completeTasks) {
  495. LOG.info("---- Worker " + this + " commencing shutdown");
  496. ArrayList<Exception> exceptions = new ArrayList<Exception>();
  497. // This gives any jobs in flight a chance to complete
  498. if (executorService != null) {
  499. if (completeTasks) {
  500. executorService.shutdown();
  501. } else {
  502. executorService.shutdownNow();
  503. }
  504. }
  505. session.closeSession();
  506. try {
  507. ioAvailable.close();
  508. } catch (IOException ioe) {
  509. LOG.warn("---- Worker " + this + " encountered IOException while closing selector: ", ioe);
  510. }
  511. state = State.IDLE;
  512. LOG.info("---- Worker " + this + " completed shutdown");
  513. return exceptions;
  514. }
  515. private GearmanFunction addNewJob(GearmanSessionEvent event) {
  516. byte[] handle, data, functionNameBytes, unique;
  517. GearmanPacket p = event.getPacket();
  518. String functionName;
  519. handle = p.getDataComponentValue(
  520. GearmanPacket.DataComponentName.JOB_HANDLE);
  521. functionNameBytes = p.getDataComponentValue(
  522. GearmanPacket.DataComponentName.FUNCTION_NAME);
  523. data = p.getDataComponentValue(
  524. GearmanPacket.DataComponentName.DATA);
  525. unique = p.getDataComponentValue(DataComponentName.UNIQUE_ID);
  526. functionName = ByteUtils.fromUTF8Bytes(functionNameBytes);
  527. FunctionDefinition def = functionMap.get(functionName);
  528. if (def == null) {
  529. GearmanTask gsr = new GearmanTask(
  530. new GearmanPacketImpl(GearmanPacketMagic.REQ,
  531. GearmanPacketType.WORK_FAIL, handle));
  532. session.submitTask(gsr);
  533. availability.unlock(this);
  534. enqueueNoopEvent();
  535. } else {
  536. GearmanFunction function = def.getFactory().getFunction();
  537. function.setData(data);
  538. function.setJobHandle(handle);
  539. function.registerEventListener(session);
  540. if (unique != null && unique.length > 0) {
  541. function.setUniqueId(unique);
  542. }
  543. return function;
  544. }
  545. return null;
  546. }
  547. private void submitFunction(GearmanFunction fun) {
  548. try {
  549. if (executorService == null) {
  550. fun.call();
  551. } else {
  552. executorService.submit(fun);
  553. }
  554. // We should have submitted either a WORK_EXCEPTION, COMPLETE,
  555. // or FAIL; make sure it gets sent.
  556. session.driveSessionIO();
  557. } catch (IOException io) {
  558. LOG.warn("---- Worker " + this + " receieved IOException while" +
  559. " running function",io);
  560. session.closeSession();
  561. } catch (Exception e) {
  562. LOG.warn("---- Worker " + this + " exception while executing function " + fun.getName(), e);
  563. }
  564. // Unlock the monitor for this worker
  565. availability.unlock(this);
  566. }
  567. private GearmanPacketType getGrabJobPacketType() {
  568. if (jobUniqueIdRequired) {
  569. return GearmanPacketType.GRAB_JOB_UNIQ;
  570. }
  571. return GearmanPacketType.GRAB_JOB;
  572. }
  573. }