1 /*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
2  *
3  *  Gearmand client and server library.
4  *
5  *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
6  *  All rights reserved.
7  *
8  *  Redistribution and use in source and binary forms, with or without
9  *  modification, are permitted provided that the following conditions are
10  *  met:
11  *
12  *      * Redistributions of source code must retain the above copyright
13  *  notice, this list of conditions and the following disclaimer.
14  *
15  *      * Redistributions in binary form must reproduce the above
16  *  copyright notice, this list of conditions and the following disclaimer
17  *  in the documentation and/or other materials provided with the
18  *  distribution.
19  *
20  *      * The names of its contributors may not be used to endorse or
21  *  promote products derived from this software without specific prior
22  *  written permission.
23  *
24  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  *
36  */
37 
38 #include "gear_config.h"
39 #include <libgearman/common.h>
40 #include <libgearman/add.hpp>
41 #include <libgearman/universal.hpp>
42 #include <libgearman/do.hpp>
43 
44 #include "libgearman/assert.hpp"
45 
46 #include <cerrno>
47 #include <cstring>
48 
client_do(gearman_client_st * client,gearman_command_t command,const char * function_name,const char * unique,const void * workload_str,size_t workload_size,size_t * result_size,gearman_return_t * ret_ptr)49 void *client_do(gearman_client_st *client, gearman_command_t command,
50                 const char *function_name,
51                 const char *unique,
52                 const void *workload_str, size_t workload_size,
53                 size_t *result_size, gearman_return_t *ret_ptr)
54 {
55   gearman_task_st do_task;
56   gearman_string_t function= { gearman_string_param_cstr(function_name) };
57   gearman_unique_t local_unique= gearman_unique_make(unique, unique ? strlen(unique) : 0);
58   gearman_string_t workload= { static_cast<const char*>(workload_str), workload_size };
59 
60   // Set to zero in case of error
61   size_t unused_result_size;
62   if (result_size == NULL)
63   {
64     result_size= &unused_result_size;
65   }
66   *result_size= 0;
67 
68   gearman_return_t unused;
69   if (ret_ptr == NULL)
70   {
71     ret_ptr= &unused;
72   }
73 
74   if (client == NULL)
75   {
76     *ret_ptr= GEARMAN_INVALID_ARGUMENT;
77     return NULL;
78   }
79 
80   gearman_task_st *do_task_ptr= add_task(*client, &do_task, NULL, command,
81                                          function,
82                                          local_unique,
83                                          workload,
84                                          time_t(0),
85                                          gearman_actions_do_default());
86   if (do_task_ptr == NULL)
87   {
88     *ret_ptr= gearman_universal_error_code(client->universal);
89     return NULL;
90   }
91 
92   gearman_return_t ret= gearman_client_run_block_tasks(client, do_task_ptr);
93 
94   const void *returnable= NULL;
95 
96   // gearman_client_run_block_tasks failed
97   if (gearman_failed(ret))
98   {
99     gearman_error(client->universal, ret, "occured during gearman_client_run_tasks()");
100 
101     *ret_ptr= ret;
102     *result_size= 0;
103   }
104   else // Now we check the task itself
105   {
106     assert(ret == GEARMAN_SUCCESS); // Programmer mistake
107     if (gearman_success(do_task_ptr->result_rc))
108     {
109       *ret_ptr= do_task_ptr->result_rc;
110       if (gearman_task_result(do_task_ptr))
111       {
112         gearman_string_t result= gearman_result_take_string(do_task_ptr->result_ptr);
113         *result_size= gearman_size(result);
114         returnable= gearman_c_str(result);
115       }
116       else // NULL SUCCESSFUL job
117       { }
118     }
119     else // gearman_client_run_block_tasks() was successful, but the task was not
120     {
121       gearman_error(client->universal, do_task_ptr->result_rc, "occured during gearman_client_run_tasks()");
122 
123       *ret_ptr= do_task_ptr->result_rc;
124       *result_size= 0;
125     }
126   }
127 
128   assert(client->task_list);
129   gearman_task_free(&do_task);
130   client->new_tasks= 0;
131   client->running_tasks= 0;
132 
133   return const_cast<void *>(returnable);
134 }
135 
client_do_background(gearman_client_st * client,gearman_command_t command,gearman_string_t & function,gearman_unique_t & unique,gearman_string_t & workload,gearman_job_handle_t job_handle)136 gearman_return_t client_do_background(gearman_client_st *client,
137                                       gearman_command_t command,
138                                       gearman_string_t &function,
139                                       gearman_unique_t &unique,
140                                       gearman_string_t &workload,
141                                       gearman_job_handle_t job_handle)
142 {
143   if (client == NULL)
144   {
145     return GEARMAN_INVALID_ARGUMENT;
146   }
147 
148   gearman_task_st do_task;
149   gearman_task_st *do_task_ptr= add_task(*client, &do_task,
150                                          client,
151                                          command,
152                                          function,
153                                          unique,
154                                          workload,
155                                          time_t(0),
156                                          gearman_actions_do_default());
157   if (do_task_ptr == NULL)
158   {
159     return gearman_universal_error_code(client->universal);
160   }
161 
162   gearman_task_clear_fn(do_task_ptr);
163 
164   gearman_return_t ret= gearman_client_run_block_tasks(client, do_task_ptr);
165   assert(ret != GEARMAN_IO_WAIT);
166   if (ret != GEARMAN_IO_WAIT)
167   {
168     if (job_handle)
169     {
170       strncpy(job_handle, do_task.job_handle, GEARMAN_JOB_HANDLE_SIZE);
171     }
172     client->new_tasks= 0;
173     client->running_tasks= 0;
174   }
175   gearman_task_free(&do_task);
176 
177   return ret;
178 }
179