php_gearman_task.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. /*
  2. * Gearman PHP Extension
  3. *
  4. * Copyright (C) 2008 James M. Luedke <contact@jamesluedke.com>,
  5. * Eric Day <eday@oddments.org>
  6. * All rights reserved.
  7. *
  8. * Use and distribution licensed under the PHP license. See
  9. * the LICENSE file in this directory for full text.
  10. */
  11. #include "php_gearman_task.h"
  12. inline gearman_task_obj *gearman_task_fetch_object(zend_object *obj) {
  13. return (gearman_task_obj *)((char*)(obj) - XtOffsetOf(gearman_task_obj, std));
  14. }
  15. inline zend_object *gearman_task_obj_new(zend_class_entry *ce) {
  16. gearman_task_obj *intern = ecalloc(1,
  17. sizeof(gearman_task_obj) +
  18. zend_object_properties_size(ce));
  19. zend_object_std_init(&(intern->std), ce);
  20. object_properties_init(&intern->std, ce);
  21. intern->task_id = 0;
  22. intern->std.handlers = &gearman_task_obj_handlers;
  23. return &intern->std;
  24. }
  25. /* this function will be used to call our user defined task callbacks */
  26. gearman_return_t _php_task_cb_fn(gearman_task_obj *task, gearman_client_obj *client, zval zcall) {
  27. gearman_return_t ret;
  28. zval ztask, argv[2], retval;
  29. uint32_t param_count;
  30. ZVAL_OBJ(&ztask, &task->std);
  31. ZVAL_COPY_VALUE(&argv[0], &ztask);
  32. if (Z_ISUNDEF(task->zdata)) {
  33. param_count = 1;
  34. } else {
  35. ZVAL_COPY_VALUE(&argv[1], &task->zdata);
  36. param_count = 2;
  37. }
  38. if (call_user_function(EG(function_table), NULL, &zcall, &retval, param_count, argv) != SUCCESS) {
  39. php_error_docref(NULL,
  40. E_WARNING,
  41. "Could not call the function %s",
  42. ( Z_ISUNDEF(zcall) || Z_TYPE(zcall) != IS_STRING) ? "[undefined]" : Z_STRVAL(zcall)
  43. );
  44. ret = 0;
  45. } else {
  46. if (Z_ISUNDEF(retval)) {
  47. ret = 0;
  48. } else {
  49. if (Z_TYPE(retval) != IS_LONG) {
  50. convert_to_long(&retval);
  51. }
  52. ret = Z_LVAL(retval);
  53. }
  54. }
  55. return ret;
  56. }
  57. void _php_task_free(gearman_task_st *task, void *context) {
  58. gearman_task_obj *task_obj= (gearman_task_obj *) context;
  59. gearman_client_obj *cli_obj = Z_GEARMAN_CLIENT_P(&task_obj->zclient);
  60. task_obj->flags &= ~GEARMAN_TASK_OBJ_CREATED;
  61. zend_hash_index_del(Z_ARRVAL(cli_obj->task_list), task_obj->task_id);
  62. }
  63. /* TODO: clean this up a bit, Macro? */
  64. gearman_return_t _php_task_workload_fn(gearman_task_st *task) {
  65. gearman_task_obj *task_obj = (gearman_task_obj *) gearman_task_context(task);
  66. gearman_client_obj *client_obj = Z_GEARMAN_CLIENT_P(&task_obj->zclient);
  67. return _php_task_cb_fn(task_obj, client_obj, client_obj->zworkload_fn);
  68. }
  69. gearman_return_t _php_task_created_fn(gearman_task_st *task) {
  70. gearman_task_obj *task_obj = (gearman_task_obj *) gearman_task_context(task);
  71. gearman_client_obj *client_obj = Z_GEARMAN_CLIENT_P(&task_obj->zclient);
  72. return _php_task_cb_fn(task_obj, client_obj, client_obj->zcreated_fn);
  73. }
  74. gearman_return_t _php_task_data_fn(gearman_task_st *task) {
  75. gearman_task_obj *task_obj = (gearman_task_obj *) gearman_task_context(task);
  76. gearman_client_obj *client_obj = Z_GEARMAN_CLIENT_P(&task_obj->zclient);
  77. return _php_task_cb_fn(task_obj, client_obj, client_obj->zdata_fn);
  78. }
  79. gearman_return_t _php_task_warning_fn(gearman_task_st *task) {
  80. gearman_task_obj *task_obj = (gearman_task_obj *) gearman_task_context(task);
  81. gearman_client_obj *client_obj = Z_GEARMAN_CLIENT_P(&task_obj->zclient);
  82. return _php_task_cb_fn(task_obj, client_obj, client_obj->zwarning_fn);
  83. }
  84. gearman_return_t _php_task_status_fn(gearman_task_st *task) {
  85. gearman_task_obj *task_obj = (gearman_task_obj *) gearman_task_context(task);
  86. gearman_client_obj *client_obj = Z_GEARMAN_CLIENT_P(&task_obj->zclient);
  87. return _php_task_cb_fn(task_obj, client_obj, client_obj->zstatus_fn);
  88. }
  89. gearman_return_t _php_task_complete_fn(gearman_task_st *task) {
  90. gearman_task_obj *task_obj = (gearman_task_obj *) gearman_task_context(task);
  91. gearman_client_obj *client_obj = Z_GEARMAN_CLIENT_P(&task_obj->zclient);
  92. return _php_task_cb_fn(task_obj, client_obj, client_obj->zcomplete_fn);
  93. }
  94. gearman_return_t _php_task_exception_fn(gearman_task_st *task) {
  95. gearman_task_obj *task_obj = (gearman_task_obj *) gearman_task_context(task);
  96. gearman_client_obj *client_obj = Z_GEARMAN_CLIENT_P(&task_obj->zclient);
  97. return _php_task_cb_fn(task_obj, client_obj, client_obj->zexception_fn);
  98. }
  99. gearman_return_t _php_task_fail_fn(gearman_task_st *task) {
  100. gearman_task_obj *task_obj = (gearman_task_obj *) gearman_task_context(task);
  101. gearman_client_obj *client_obj = Z_GEARMAN_CLIENT_P(&task_obj->zclient);
  102. return _php_task_cb_fn(task_obj, client_obj, client_obj->zfail_fn);
  103. }
  104. /* {{{ proto object GearmanTask::__construct()
  105. Returns a task object */
  106. PHP_METHOD(GearmanTask, __construct) {
  107. }
  108. void gearman_task_free_obj(zend_object *object) {
  109. gearman_task_obj *intern = gearman_task_fetch_object(object);
  110. if (!intern) {
  111. return;
  112. }
  113. zval_dtor(&intern->zworkload);
  114. zval_dtor(&intern->zdata);
  115. zval_dtor(&intern->zclient);
  116. zend_object_std_dtor(&intern->std);
  117. }
  118. /* {{{ proto int gearman_task_return_code()
  119. get last gearman_return_t */
  120. PHP_FUNCTION(gearman_task_return_code) {
  121. zval *zobj;
  122. gearman_task_obj *obj;
  123. if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &zobj, gearman_task_ce) == FAILURE) {
  124. RETURN_NULL();
  125. }
  126. obj = Z_GEARMAN_TASK_P(zobj);
  127. RETURN_LONG(obj->ret);
  128. }
  129. /* }}} */
  130. /* {{{ proto false|string gearman_task_function_name(object task)
  131. Returns function name associated with a task. */
  132. PHP_FUNCTION(gearman_task_function_name) {
  133. zval *zobj;
  134. gearman_task_obj *obj;
  135. if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &zobj, gearman_task_ce) == FAILURE) {
  136. RETURN_NULL();
  137. }
  138. obj = Z_GEARMAN_TASK_P(zobj);
  139. if (obj->flags & GEARMAN_TASK_OBJ_CREATED) {
  140. RETURN_STRING((char *)gearman_task_function_name(obj->task));
  141. }
  142. RETURN_FALSE;
  143. }
  144. /* }}} */
  145. /* {{{ proto false|string gearman_task_unique(object task)
  146. Returns unique identifier for a task. */
  147. PHP_FUNCTION(gearman_task_unique) {
  148. zval *zobj;
  149. gearman_task_obj *obj;
  150. if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &zobj, gearman_task_ce) == FAILURE) {
  151. RETURN_NULL();
  152. }
  153. obj = Z_GEARMAN_TASK_P(zobj);
  154. if (obj->flags & GEARMAN_TASK_OBJ_CREATED) {
  155. RETURN_STRING((char *)gearman_task_unique(obj->task));
  156. }
  157. RETURN_FALSE;
  158. }
  159. /* }}} */
  160. /* {{{ proto false|string gearman_task_job_handle(object task)
  161. Returns job handle for a task. */
  162. PHP_FUNCTION(gearman_task_job_handle) {
  163. zval *zobj;
  164. gearman_task_obj *obj;
  165. if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &zobj, gearman_task_ce) == FAILURE) {
  166. RETURN_NULL();
  167. }
  168. obj = Z_GEARMAN_TASK_P(zobj);
  169. if (obj->flags & GEARMAN_TASK_OBJ_CREATED) {
  170. RETURN_STRING((char *)gearman_task_job_handle(obj->task));
  171. }
  172. RETURN_FALSE;
  173. }
  174. /* }}} */
  175. /* {{{ proto bool gearman_task_is_known(object task)
  176. Get status on whether a task is known or not */
  177. PHP_FUNCTION(gearman_task_is_known) {
  178. zval *zobj;
  179. gearman_task_obj *obj;
  180. if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &zobj, gearman_task_ce) == FAILURE) {
  181. RETURN_NULL();
  182. }
  183. obj = Z_GEARMAN_TASK_P(zobj);
  184. if (obj->flags & GEARMAN_TASK_OBJ_CREATED) {
  185. RETURN_BOOL(gearman_task_is_known(obj->task));
  186. }
  187. RETURN_FALSE;
  188. }
  189. /* }}} */
  190. /* {{{ proto bool gearman_task_is_running(object task)
  191. Get status on whether a task is running or not */
  192. PHP_FUNCTION(gearman_task_is_running) {
  193. zval *zobj;
  194. gearman_task_obj *obj;
  195. if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &zobj, gearman_task_ce) == FAILURE) {
  196. RETURN_NULL();
  197. }
  198. obj = Z_GEARMAN_TASK_P(zobj);
  199. if (obj->flags & GEARMAN_TASK_OBJ_CREATED) {
  200. RETURN_BOOL(gearman_task_is_running(obj->task));
  201. }
  202. RETURN_FALSE;
  203. }
  204. /* }}} */
  205. /* {{{ proto false|int gearman_task_numerator(object task)
  206. Returns the numerator of percentage complete for a task. */
  207. PHP_FUNCTION(gearman_task_numerator) {
  208. zval *zobj;
  209. gearman_task_obj *obj;
  210. if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &zobj, gearman_task_ce) == FAILURE) {
  211. RETURN_NULL();
  212. }
  213. obj = Z_GEARMAN_TASK_P(zobj);
  214. if (obj->flags & GEARMAN_TASK_OBJ_CREATED) {
  215. RETURN_LONG(gearman_task_numerator(obj->task));
  216. }
  217. RETURN_FALSE;
  218. }
  219. /* }}} */
  220. /* {{{ proto false|int gearman_task_denominator(object task)
  221. Returns the denominator of percentage complete for a task. */
  222. PHP_FUNCTION(gearman_task_denominator) {
  223. zval *zobj;
  224. gearman_task_obj *obj;
  225. if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &zobj, gearman_task_ce) == FAILURE) {
  226. RETURN_NULL();
  227. }
  228. obj = Z_GEARMAN_TASK_P(zobj);
  229. if (obj->flags & GEARMAN_TASK_OBJ_CREATED) {
  230. RETURN_LONG(gearman_task_denominator(obj->task));
  231. }
  232. RETURN_FALSE;
  233. }
  234. /* }}} */
  235. /* {{{ proto false|string gearman_task_data(object task)
  236. Get data being returned for a task. */
  237. PHP_FUNCTION(gearman_task_data) {
  238. zval *zobj;
  239. gearman_task_obj *obj;
  240. const uint8_t *data;
  241. size_t data_len;
  242. if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &zobj, gearman_task_ce) == FAILURE) {
  243. RETURN_NULL();
  244. }
  245. obj = Z_GEARMAN_TASK_P(zobj);
  246. if (obj->flags & GEARMAN_TASK_OBJ_CREATED &&
  247. !gearman_client_has_option(&Z_GEARMAN_CLIENT_P(&obj->zclient)->client, GEARMAN_CLIENT_UNBUFFERED_RESULT)) {
  248. data = gearman_task_data(obj->task);
  249. data_len = gearman_task_data_size(obj->task);
  250. RETURN_STRINGL((char *)data, (long) data_len);
  251. }
  252. RETURN_FALSE;
  253. }
  254. /* }}} */
  255. /* {{{ proto false|int gearman_task_data_size(object task)
  256. Get data size being returned for a task. */
  257. PHP_FUNCTION(gearman_task_data_size) {
  258. zval *zobj;
  259. gearman_task_obj *obj;
  260. if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &zobj, gearman_task_ce) == FAILURE) {
  261. RETURN_FALSE;
  262. }
  263. obj = Z_GEARMAN_TASK_P(zobj);
  264. if (obj->flags & GEARMAN_TASK_OBJ_CREATED) {
  265. RETURN_LONG(gearman_task_data_size(obj->task));
  266. }
  267. RETURN_FALSE;
  268. }
  269. /* }}} */
  270. /* {{{ proto false|int gearman_task_send_workload(object task, string data)
  271. NOT-TESTED Send packet data for a task. */
  272. PHP_FUNCTION(gearman_task_send_workload) {
  273. zval *zobj;
  274. gearman_task_obj *obj;
  275. char *data;
  276. size_t data_len;
  277. if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &zobj, gearman_task_ce,
  278. &data, &data_len) == FAILURE) {
  279. RETURN_FALSE;
  280. }
  281. obj = Z_GEARMAN_TASK_P(zobj);
  282. if (!(obj->flags & GEARMAN_TASK_OBJ_CREATED)) {
  283. RETURN_FALSE;
  284. }
  285. /* XXX verify that i am doing this correctly */
  286. data_len = gearman_task_send_workload(obj->task, data, data_len, &obj->ret);
  287. if (obj->ret != GEARMAN_SUCCESS)
  288. {
  289. php_error_docref(NULL, E_WARNING, "%s",
  290. gearman_client_error(&Z_GEARMAN_CLIENT_P(&obj->zclient)->client));
  291. RETURN_FALSE;
  292. }
  293. RETURN_LONG(data_len);
  294. }
  295. /* }}} */
  296. /* {{{ proto false|array gearman_task_recv_data(object task, long buffer_size)
  297. NOT-TESTED Read work or result data into a buffer for a task. */
  298. PHP_FUNCTION(gearman_task_recv_data) {
  299. zval *zobj;
  300. gearman_task_obj *obj;
  301. char *data_buffer;
  302. zend_long data_buffer_size;
  303. size_t data_len;
  304. if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &zobj, gearman_task_ce,
  305. &data_buffer_size) == FAILURE) {
  306. RETURN_NULL();
  307. }
  308. obj = Z_GEARMAN_TASK_P(zobj);
  309. if (!(obj->flags & GEARMAN_TASK_OBJ_CREATED)) {
  310. RETURN_FALSE;
  311. }
  312. data_buffer= (char *) emalloc(data_buffer_size);
  313. data_len= gearman_task_recv_data(obj->task, data_buffer, data_buffer_size,
  314. &obj->ret);
  315. if (obj->ret != GEARMAN_SUCCESS &&
  316. !gearman_client_has_option(&Z_GEARMAN_CLIENT_P(&obj->zclient)->client, GEARMAN_CLIENT_UNBUFFERED_RESULT)) {
  317. php_error_docref(NULL, E_WARNING, "%s",
  318. gearman_client_error(&Z_GEARMAN_CLIENT_P(&obj->zclient)->client));
  319. RETURN_FALSE;
  320. }
  321. array_init(return_value);
  322. add_next_index_long(return_value, (long)data_len);
  323. add_next_index_stringl(return_value, (char *)data_buffer,
  324. (long)data_len);
  325. }
  326. /* }}} */