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 
41 #include <libgearman/unique.hpp>
42 #include <libgearman/result.hpp>
43 
44 #include "libgearman/assert.hpp"
45 #include "libgearman/vector.h"
46 
47 #include <memory>
48 
49 struct gearman_result_st;
50 
_client_pause_data(gearman_task_st * task)51 static gearman_return_t _client_pause_data(gearman_task_st *task)
52 {
53   if (task->options.is_paused)
54   {
55     task->options.is_paused= false;
56     return GEARMAN_SUCCESS;
57   }
58 
59   if (gearman_task_data_size(task))
60   {
61     if (gearman_task_result(task))
62     {
63       gearman_task_result(task)->clear();
64     }
65     else
66     {
67       task->result_ptr= new (std::nothrow) gearman_result_st(gearman_task_data_size(task));
68       if (task->result_ptr == NULL)
69       {
70         return GEARMAN_MEMORY_ALLOCATION_FAILURE;
71       }
72     }
73     assert_msg(task->result_ptr, "programmer error, result_ptr has not been allocated for task");
74 
75     gearman_string_append(gearman_task_mutable_result(task)->mutable_string(), static_cast<const char*>(gearman_task_data(task)), gearman_task_data_size(task));
76   }
77 
78   if (task->recv->command == GEARMAN_COMMAND_WORK_DATA)
79   { }
80   else if (task->recv->command == GEARMAN_COMMAND_WORK_WARNING)
81   { }
82   else if (task->recv->command == GEARMAN_COMMAND_WORK_EXCEPTION)
83   { }
84   else // GEARMAN_COMMAND_WORK_COMPLETE
85   {
86     return GEARMAN_SUCCESS;
87   }
88 
89   task->options.is_paused= true;
90 
91   return GEARMAN_PAUSE;
92 }
93 
_client_pause_complete(gearman_task_st * task)94 static gearman_return_t _client_pause_complete(gearman_task_st *task)
95 {
96   return _client_pause_data(task);
97 }
98 
99 
_client_pause_status(gearman_task_st * task)100 static gearman_return_t _client_pause_status(gearman_task_st *task)
101 {
102   assert_msg(task->recv->command == GEARMAN_COMMAND_WORK_STATUS or
103              task->recv->command == GEARMAN_COMMAND_STATUS_RES_UNIQUE or
104              task->recv->command == GEARMAN_COMMAND_STATUS_RES, "status has been called out of order for task, or was registered to run on non-status callback, see gearman_actions_t(3)");
105   if (task->options.is_paused)
106   {
107     task->options.is_paused= false;
108     return GEARMAN_SUCCESS;
109   }
110   task->options.is_paused= true;
111 
112   return GEARMAN_PAUSE;
113 }
114 
_client_pause_fail(gearman_task_st * task)115 static gearman_return_t _client_pause_fail(gearman_task_st *task)
116 {
117   assert_msg(task->recv->command == GEARMAN_COMMAND_WORK_FAIL,
118              "fail callback has been called out of order for task, or was registered to run on non-fail callback, see gearman_actions_t(3)");
119   if (task->options.is_paused)
120   {
121     task->options.is_paused= false;
122     return GEARMAN_SUCCESS;
123   }
124   task->options.is_paused= true;
125 
126   return GEARMAN_PAUSE;
127 }
128 
_client_do_data(gearman_task_st * task)129 static gearman_return_t _client_do_data(gearman_task_st *task)
130 {
131   if (gearman_task_data_size(task))
132   {
133     if (gearman_task_result(task) == NULL)
134     {
135       task->result_ptr= new (std::nothrow) gearman_result_st(gearman_task_data_size(task));
136       if (task->result_ptr == NULL)
137       {
138         return GEARMAN_MEMORY_ALLOCATION_FAILURE;
139       }
140     }
141 
142     assert(gearman_task_mutable_result(task));
143     gearman_task_mutable_result(task)->mutable_string()->append(static_cast<const char*>(gearman_task_data(task)), gearman_task_data_size(task));
144   }
145 
146   return GEARMAN_SUCCESS;
147 }
148 
_client_do_complete(gearman_task_st * task)149 static gearman_return_t _client_do_complete(gearman_task_st *task)
150 {
151   if (gearman_task_data_size(task))
152   {
153     if (gearman_task_result(task) == NULL)
154     {
155       task->result_ptr= new (std::nothrow) gearman_result_st(gearman_task_data_size(task));
156       if (task->result_ptr == NULL)
157       {
158         return GEARMAN_MEMORY_ALLOCATION_FAILURE;
159       }
160     }
161 
162     gearman_string_append(gearman_task_mutable_result(task)->mutable_string(), static_cast<const char*>(gearman_task_data(task)), gearman_task_data_size(task));
163   }
164 
165   task->result_rc= GEARMAN_SUCCESS;
166 
167   return GEARMAN_SUCCESS;
168 }
169 
gearman_actions_default(void)170 const gearman_actions_t &gearman_actions_default(void)
171 {
172   static gearman_actions_t default_actions= { 0, 0, 0, 0, 0, 0, 0, 0 };
173 
174   return default_actions;
175 }
176 
177 
gearman_actions_do_default(void)178 const gearman_actions_t &gearman_actions_do_default(void)
179 {
180   static gearman_actions_t default_actions= { 0, 0, _client_do_data, 0, 0, _client_do_complete, 0, 0 };
181 
182   return default_actions;
183 }
184 
gearman_actions_execute_defaults(void)185 const gearman_actions_t &gearman_actions_execute_defaults(void)
186 {
187   static gearman_actions_t default_actions= { 0, 0, _client_do_data, 0, 0, _client_do_complete, 0, 0 };
188 
189   return default_actions;
190 }
191 
gearman_actions_pause(void)192 const gearman_actions_t &gearman_actions_pause(void)
193 {
194   static gearman_actions_t default_actions= { 0, 0,
195     _client_pause_data,  // gearman_data_fn
196     _client_pause_data,  // gearman_warning_fn
197     _client_pause_status,  // gearman_universal_status_fn
198     _client_pause_complete, // gearman_complete_fn
199     _client_pause_data, // gearman_exception_fn
200     _client_pause_fail }; // gearman_fail_fn
201 
202   return default_actions;
203 }
204