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