1 /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
2 *
3 * Gearmand client and server library.
4 *
5 * Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
6 * Copyright (C) 2008 Brian Aker, Eric Day
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are
11 * met:
12 *
13 * * Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * * Redistributions in binary form must reproduce the above
17 * copyright notice, this list of conditions and the following disclaimer
18 * in the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * * The names of its contributors may not be used to endorse or
22 * promote products derived from this software without specific prior
23 * written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 */
38
39 /**
40 * @file
41 * @brief Server worker definitions
42 */
43
44 #include "gear_config.h"
45 #include "libgearman-server/common.h"
46
47 #include <memory>
48
gearman_server_worker_create(gearman_server_con_st * con,gearman_server_function_st * function)49 static gearman_server_worker_st* gearman_server_worker_create(gearman_server_con_st *con, gearman_server_function_st *function)
50 {
51 gearman_server_worker_st *worker;
52
53 if (Server->free_worker_count > 0)
54 {
55 worker= Server->free_worker_list;
56 GEARMAN_LIST_DEL(Server->free_worker, worker, con_);
57 }
58 else
59 {
60 worker= new (std::nothrow) gearman_server_worker_st;
61 if (worker == NULL)
62 {
63 gearmand_merror("new", gearman_server_worker_st, 1);
64 return NULL;
65 }
66 }
67
68 worker->job_count= 0;
69 worker->timeout= -1;
70 worker->con= con;
71 GEARMAN_LIST_ADD(con->worker, worker, con_);
72 worker->function= function;
73
74 /* Add worker to the function list, which is a double-linked circular list. */
75 if (function->worker_list == NULL)
76 {
77 function->worker_list= worker;
78 worker->function_next= worker;
79 worker->function_prev= worker;
80 }
81 else
82 {
83 worker->function_next= function->worker_list;
84 worker->function_prev= function->worker_list->function_prev;
85 worker->function_next->function_prev= worker;
86 worker->function_prev->function_next= worker;
87 }
88 function->worker_count++;
89
90 worker->job_list= NULL;
91
92 return worker;
93 }
94
95 /*
96 * Public definitions
97 */
98
99 gearman_server_worker_st *
gearman_server_worker_add(gearman_server_con_st * con,const char * function_name,size_t function_name_size,long timeout)100 gearman_server_worker_add(gearman_server_con_st *con, const char *function_name,
101 size_t function_name_size, long timeout)
102 {
103 gearman_server_function_st *function= gearman_server_function_get(Server, function_name,
104 function_name_size);
105 if (function == NULL)
106 {
107 return NULL;
108 }
109
110 gearman_server_worker_st* worker= gearman_server_worker_create(con, function);
111 if (worker == NULL)
112 {
113 return NULL;
114 }
115
116 worker->timeout= timeout;
117
118 return worker;
119 }
120
gearman_server_worker_free(gearman_server_worker_st * worker)121 void gearman_server_worker_free(gearman_server_worker_st *worker)
122 {
123 /* If the worker was in the middle of a job, requeue it. */
124 while (worker->job_list != NULL)
125 {
126 gearmand_error_t ret= gearman_server_job_queue(worker->job_list);
127 if (ret != GEARMAN_SUCCESS)
128 {
129 gearmand_gerror_warn("gearman_server_job_queue", ret);
130 }
131 }
132
133 GEARMAN_LIST_DEL(worker->con->worker, worker, con_);
134
135 if (worker == worker->function_next)
136 {
137 worker->function->worker_list= NULL;
138 }
139 else
140 {
141 worker->function_next->function_prev= worker->function_prev;
142 worker->function_prev->function_next= worker->function_next;
143
144 if (worker == worker->function->worker_list)
145 {
146 worker->function->worker_list= worker->function_next;
147 }
148 }
149 worker->function->worker_count--;
150
151 if (Server->free_worker_count < GEARMAN_MAX_FREE_SERVER_WORKER)
152 {
153 GEARMAN_LIST_ADD(Server->free_worker, worker, con_);
154 }
155 else
156 {
157 gearmand_debug("delete");
158 delete worker;
159 }
160 }
161