-
Notifications
You must be signed in to change notification settings - Fork 2
/
Chmpx.c
428 lines (388 loc) · 14.4 KB
/
Chmpx.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
/*
* CHMPX PHP Extension library
*
* Copyright 2015 Yahoo Japan corporation.
*
* CHMPX is inprocess data exchange by MQ with consistent hashing.
* CHMPX is made for the purpose of the construction of
* original messaging system and the offer of the client
* library.
* CHMPX transfers messages between the client and the server/
* slave. CHMPX based servers are dispersed by consistent
* hashing and are automatically layouted. As a result, it
* provides a high performance, a high scalability.
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*
* AUTHOR: [email protected]
* CREATE: Mon Mar 16 2015
* REVISION:
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
// cppcheck-suppress missingInclude
#include "php.h"
// cppcheck-suppress missingInclude
#include "ext/standard/info.h"
#include "php_chmpxpx.h"
PHP_METHOD(Chmpx, __construct)
{
// chmpx_handle property
// Firstly, create a chmpx_handle
chmpx_h* chmpx_handle_ptr = emalloc(sizeof(long));
if (chmpx_handle_ptr == NULL) {
php_error(E_ERROR, "malloc error");
return;
}
*chmpx_handle_ptr = CHM_INVALID_CHMPXHANDLE;
// Secondarily, create a zend_resource with the chmpx handle
zend_resource* my_chmpx_handle_ptr = zend_register_resource(chmpx_handle_ptr, chmpx_handle_resource_number);
// Thirdly, create a zval with the zend_resource
zval zval_new_chmpx_handle;
ZVAL_RES(&zval_new_chmpx_handle, my_chmpx_handle_ptr);
// Finally, set the zend_resource with this object
chmpxpx_update_property_resource(Z_OBJCE_P(ZEND_THIS), ZEND_THIS, "chmpx_handle", strlen("chmpx_handle"), &zval_new_chmpx_handle);
// is_server_mode property
// Firstly, create a is_server_mode
long* is_server_mode_ptr = emalloc(sizeof(long));
if (is_server_mode_ptr == NULL) {
php_error(E_ERROR, "malloc error");
return;
}
*is_server_mode_ptr = 1;
// Secondarily, create a zend_resource with the chmpx handle
zend_resource* my_res_is_server_mode = zend_register_resource(is_server_mode_ptr, is_server_mode_resource_number);
// Thirdly, create a zval with the zend_resource
zval zval_new_is_server_mode;
ZVAL_RES(&zval_new_is_server_mode, my_res_is_server_mode);
// Finally, set the zend_resource with this object
chmpxpx_update_property_resource(Z_OBJCE_P(ZEND_THIS), ZEND_THIS, "is_server_mode", strlen("is_server_mode"), &zval_new_is_server_mode);
}
static void chmpx_class_dtor_opt(INTERNAL_FUNCTION_PARAMETERS, int opt)
{
// declare_variables
zend_bool is_destruct = true;
// hack: override the is_on_server by using the opt parameter
switch (opt) {
case 0:
is_destruct = false;
break;
case 1:
break;
default:
RETURN_FALSE;
}
// assign_after_declare
// chmpx_handle resource
zval* zval_chmpx_handle_ptr = chmpxpx_read_property_resource(Z_OBJCE_P(ZEND_THIS), ZEND_THIS, "chmpx_handle");
if(zval_chmpx_handle_ptr) {
chmpx_h* chmpx_handle_ptr;
chmpx_handle_ptr = (chmpx_h *)zend_fetch_resource(Z_RES_P(zval_chmpx_handle_ptr), "chmpx_handle", chmpx_handle_resource_number);
if(CHM_INVALID_CHMPXHANDLE != *chmpx_handle_ptr){
// destroy handle
chmpx_destroy(*chmpx_handle_ptr);
}
zval_dtor(zval_chmpx_handle_ptr);
}
// is_server_mode resource
zval* zval_is_server_mode = chmpxpx_read_property_resource(Z_OBJCE_P(ZEND_THIS), ZEND_THIS, "is_server_mode");
if(zval_is_server_mode) {
zval_dtor(zval_is_server_mode);
}
// update_props
// NOTICE: set invalid handle to avoid SIGSEGV if not is_destruct
if (!is_destruct) {
// Firstly, create a chmpx_handle
chmpx_h* chmpx_handle_ptr = emalloc(sizeof(long));
if (chmpx_handle_ptr == NULL) {
php_error(E_ERROR, "malloc error");
RETURN_FALSE;
}
// cppcheck-suppress unmatchedSuppression
// cppcheck-suppress nullPointerRedundantCheck
*chmpx_handle_ptr = CHM_INVALID_CHMPXHANDLE;
// Secondarily, create a zend_resource with the chmpx handle
zend_resource* my_chmpx_handle_ptr = zend_register_resource(chmpx_handle_ptr, chmpx_handle_resource_number);
// Thirdly, create a zval with the zend_resource
zval zval_new_chmpx_handle;
ZVAL_RES(&zval_new_chmpx_handle, my_chmpx_handle_ptr);
// Finally, set the zend_resource with this object
chmpxpx_update_property_resource(Z_OBJCE_P(ZEND_THIS), ZEND_THIS, "chmpx_handle", strlen("chmpx_handle"), &zval_new_chmpx_handle);
}
// return_result after call_some_functions
// NOTICE: destruct shoud return nothing
if (!is_destruct) {
RETURN_TRUE;
}
}
PHP_METHOD(Chmpx, __destruct)
{
chmpx_class_dtor_opt(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
}
PHP_METHOD(Chmpx, destroy)
{
chmpx_class_dtor_opt(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
}
static void chmpx_class_create_instance_opt(INTERNAL_FUNCTION_PARAMETERS, int opt)
{
// declare_variables
char* filepath = NULL;
size_t filepath_len = 0;
zend_bool is_on_server = true;
zend_bool is_auto_rejoin = false;
// assign_after_declare
ZEND_PARSE_PARAMETERS_START(1, 3)
Z_PARAM_STRING(filepath, filepath_len)
Z_PARAM_OPTIONAL
Z_PARAM_BOOL(is_on_server)
Z_PARAM_BOOL(is_auto_rejoin)
ZEND_PARSE_PARAMETERS_END();
// hack: override the is_on_server by using the opt parameter
switch (opt) {
case 0:
case 1:
is_on_server = true;
break;
case 2:
is_on_server = false;
break;
default:
RETURN_FALSE;
}
// validate_after_assign
if(!filepath || 0 == filepath_len){
php_error(E_ERROR, "CHMPX configuration file path is empty.");
RETURN_FALSE;
}
// get_props and get_resources
// chmpx_handle
zval* zval_chmpx_handle_ptr = chmpxpx_read_property_resource(Z_OBJCE_P(ZEND_THIS), ZEND_THIS, "chmpx_handle");
if(zval_chmpx_handle_ptr) {
chmpx_h* chmpx_handle_ptr = (chmpx_h *)zend_fetch_resource(Z_RES_P(zval_chmpx_handle_ptr), "chmpx_handle", chmpx_handle_resource_number);
if(CHM_INVALID_CHMPXHANDLE != *chmpx_handle_ptr){
// destroy handle
chmpx_destroy(*chmpx_handle_ptr);
}
zval_dtor(zval_chmpx_handle_ptr);
}
// is_server_mode
zval* zval_is_server_mode = chmpxpx_read_property_resource(Z_OBJCE_P(ZEND_THIS), ZEND_THIS, "is_server_mode");
if(zval_is_server_mode) {
zval_dtor(zval_is_server_mode);
}
// call_some_functions after get_resources
// Firstly, create a chmpx_handle
chmpx_h* new_chmpx_handle_ptr = emalloc(sizeof(long));
if (new_chmpx_handle_ptr == NULL) {
php_error(E_ERROR, "malloc error");
RETURN_FALSE;
}
// cppcheck-suppress unmatchedSuppression
// cppcheck-suppress nullPointerRedundantCheck
*new_chmpx_handle_ptr = chmpx_create(filepath, 0 != is_on_server ? true : false, 0 != is_auto_rejoin ? true : false);
// Secondarily, create a zend_resource with the chmpx handle
zend_resource* res_new_chmpx_handle = zend_register_resource(new_chmpx_handle_ptr, chmpx_handle_resource_number);
// Thirdly, create a zval with the zend_resource
zval zval_res_new_chmpx_handle;
ZVAL_RES(&zval_res_new_chmpx_handle, res_new_chmpx_handle);
// Finally, set the zend_resource with this object
chmpxpx_update_property_resource(Z_OBJCE_P(ZEND_THIS), ZEND_THIS, "chmpx_handle", strlen("chmpx_handle"), &zval_res_new_chmpx_handle);
// update a property after init props after getting props
// Firstly, create a is_server_mode
bool* new_is_server_mode_ptr = emalloc(sizeof(bool));
if (new_is_server_mode_ptr == NULL) {
php_error(E_ERROR, "malloc error");
RETURN_FALSE;
}
// cppcheck-suppress unmatchedSuppression
// cppcheck-suppress nullPointerRedundantCheck
*new_is_server_mode_ptr = is_on_server;
// Secondarily, create a zend_resource with the is_server_mode
zend_resource* res_new_is_server_mode = zend_register_resource(new_is_server_mode_ptr, is_server_mode_resource_number);
// Thirdly create a zval with the zend_resource
zval zval_res_new_is_server_mode;
ZVAL_RES(&zval_res_new_is_server_mode, res_new_is_server_mode);
// Finally, set the zend_resource with this object
chmpxpx_update_property_resource(Z_OBJCE_P(ZEND_THIS), ZEND_THIS, "is_server_mode", strlen("is_server_mode"), &zval_res_new_is_server_mode);
// return_result after call_some_functions
RETURN_TRUE;
}
PHP_METHOD(Chmpx, create)
{
chmpx_class_create_instance_opt(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
}
PHP_METHOD(Chmpx, createServer)
{
chmpx_class_create_instance_opt(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
}
PHP_METHOD(Chmpx, createSlave)
{
chmpx_class_create_instance_opt(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2);
}
PHP_METHOD(Chmpx, isRunning)
{
// get_props
zval* zval_chmpx_handle_ptr = chmpxpx_read_property_resource(Z_OBJCE_P(ZEND_THIS), ZEND_THIS, "chmpx_handle");
if(!zval_chmpx_handle_ptr) {
php_error(E_NOTICE, "zval_chmpx_handle_ptr shoule be a valid pointer but NULL");
}
// get_resources after get_props
chmpx_h* chmpx_handle_ptr = (chmpx_h *)zend_fetch_resource(Z_RES_P(zval_chmpx_handle_ptr), "chmpx_handle", chmpx_handle_resource_number);
if(CHM_INVALID_CHMPXHANDLE == *chmpx_handle_ptr){
php_error(E_NOTICE, "chmpx_handle is CHM_INVALID_CHMPXHANDLE");
RETURN_FALSE;
}
// call_some_functions after get_resources
bool bResult = is_chmpx_proc_exists(*chmpx_handle_ptr);
// return_result after call_some_functions
if (bResult) {
RETURN_TRUE;
}
php_error(E_NOTICE, "is_chmpx_proc_exists false");
RETURN_FALSE;
}
static void chmpx_class_get_instance_opt(INTERNAL_FUNCTION_PARAMETERS, int opt)
{
// declare_variables
zend_bool is_on_server = true;
zend_bool no_giveup_rejoin = false;
// assign_after_declare
ZEND_PARSE_PARAMETERS_START(0, 1)
Z_PARAM_OPTIONAL
Z_PARAM_BOOL(no_giveup_rejoin)
ZEND_PARSE_PARAMETERS_END();
// hack: override the is_on_server by using the opt parameter
switch (opt) {
case 1:
is_on_server = true;
break;
case 2:
is_on_server = false;
break;
default:
RETURN_FALSE;
}
// validate_after_assign
// get_props
// chmpx_handle property
zval* zval_chmpx_handle_ptr = chmpxpx_read_property_resource(Z_OBJCE_P(ZEND_THIS), ZEND_THIS, "chmpx_handle");
if(!zval_chmpx_handle_ptr) {
php_error(E_NOTICE, "chmpx_handle property is invalid");
RETURN_FALSE;
}
// getting the is_server_mode property
zval* zval_is_server_mode = chmpxpx_read_property_resource(Z_OBJCE_P(ZEND_THIS), ZEND_THIS, "is_server_mode");
if(!zval_is_server_mode) {
php_error(E_NOTICE, "is_server_mode porperty is invalid");
RETURN_FALSE;
}
// get_resources after get_props
// chmpx_handle property
chmpx_h* chmpx_handle_ptr = (chmpx_h *)zend_fetch_resource(Z_RES_P(zval_chmpx_handle_ptr), "chmpx_handle", chmpx_handle_resource_number);
if(CHM_INVALID_CHMPXHANDLE == *chmpx_handle_ptr){
// no created handle
RETURN_FALSE;
}
// is_server_mode
bool* is_server_mode_ptr = (bool *)zend_fetch_resource(Z_RES_P(zval_is_server_mode), "is_server_mode", is_server_mode_resource_number);
if( !is_on_server && *is_server_mode_ptr ){
// mode is server
php_error(E_NOTICE, "is_server_mode should be slave but server");
RETURN_FALSE;
}
// call_some_functions after get_resources
// NOTICE: this case does not call ChmpxSlave::__construct().
if (!is_on_server) {
// set msgid handle for ChmpxSlave instance
msgid_t* res_msgid_handle_ptr = emalloc(sizeof(long));
// cppcheck-suppress unmatchedSuppression
// cppcheck-suppress nullPointerRedundantCheck
if (res_msgid_handle_ptr == NULL) {
php_error(E_ERROR, "malloc error");
RETURN_FALSE;
}
// cppcheck-suppress unmatchedSuppression
// cppcheck-suppress nullPointerRedundantCheck
*res_msgid_handle_ptr = chmpx_open(*chmpx_handle_ptr, 0 != no_giveup_rejoin ? true : false);
// cppcheck-suppress unmatchedSuppression
// cppcheck-suppress nullPointerRedundantCheck
if(CHM_INVALID_MSGID == *res_msgid_handle_ptr){
php_error(E_NOTICE, "failed to open msgid on slave CHMPX.");
RETURN_FALSE;
}
// cppcheck-suppress unmatchedSuppression
// cppcheck-suppress nullPointerRedundantCheck
zval zval_msgid_handle;
zend_resource* my_res_msgid_handle = zend_register_resource(res_msgid_handle_ptr, msgid_handle_resource_number);
ZVAL_RES(&zval_msgid_handle, my_res_msgid_handle);
// NOTICE: set invalid handle to avoid SIGSEGV
zval zval_dup_chmpx_handle;
chmpx_h* res_dup_chmpx_handle_ptr = emalloc(sizeof(long));
// cppcheck-suppress unmatchedSuppression
// cppcheck-suppress nullPointerRedundantCheck
if (res_dup_chmpx_handle_ptr == NULL) {
php_error(E_ERROR, "malloc error");
RETURN_FALSE;
}
// cppcheck-suppress unmatchedSuppression
// cppcheck-suppress nullPointerRedundantCheck
*res_dup_chmpx_handle_ptr = *chmpx_handle_ptr;
zend_resource* my_res_dup_chmpx_handle = zend_register_resource(res_dup_chmpx_handle_ptr, chmpx_handle_resource_number);
ZVAL_RES(&zval_dup_chmpx_handle, my_res_dup_chmpx_handle);
// return a new object(ChmpxSlave class)
object_init_ex(return_value, chmpx_slave_class_entry);
add_property_zval(return_value, "chmpx_handle", &zval_dup_chmpx_handle);
add_property_zval(return_value, "msgid_handle", &zval_msgid_handle);
} else {
// set pkt handle for ChmpxServer instance
chmpx_pkt_h* res_pkt_handle_ptr = emalloc(sizeof(long));
// cppcheck-suppress unmatchedSuppression
// cppcheck-suppress nullPointerRedundantCheck
if (res_pkt_handle_ptr == NULL) {
php_error(E_ERROR, "malloc error");
RETURN_FALSE;
}
// cppcheck-suppress unmatchedSuppression
// cppcheck-suppress nullPointerRedundantCheck
*res_pkt_handle_ptr = 0L;
zval zval_pkt_handle;
zend_resource* my_res_pkt_handle = zend_register_resource(res_pkt_handle_ptr, chmpx_pkt_handle_resource_number);
ZVAL_RES(&zval_pkt_handle, my_res_pkt_handle);
// NOTICE: set invalid handle to avoid SIGSEGV
zval zval_dup_chmpx_handle;
chmpx_h* res_dup_chmpx_handle_ptr = emalloc(sizeof(long));
// cppcheck-suppress unmatchedSuppression
// cppcheck-suppress nullPointerRedundantCheck
if (res_dup_chmpx_handle_ptr == NULL) {
php_error(E_ERROR, "malloc error");
RETURN_FALSE;
}
// cppcheck-suppress unmatchedSuppression
// cppcheck-suppress nullPointerRedundantCheck
*res_dup_chmpx_handle_ptr = *chmpx_handle_ptr;
zend_resource* my_res_dup_chmpx_handle = zend_register_resource(res_dup_chmpx_handle_ptr, chmpx_handle_resource_number);
ZVAL_RES(&zval_dup_chmpx_handle, my_res_dup_chmpx_handle);
// return a new object(ChmpxServer class)
object_init_ex(return_value, chmpx_server_class_entry);
add_property_zval(return_value, "chmpx_handle", &zval_dup_chmpx_handle);
add_property_zval(return_value, "chmpx_pkt_handle", &zval_pkt_handle);
}
}
PHP_METHOD(Chmpx, getChmpxSlave)
{
chmpx_class_get_instance_opt(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2);
}
PHP_METHOD(Chmpx, getChmpxServer)
{
chmpx_class_get_instance_opt(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noexpandtab sw=4 ts=4 fdm=marker
* vim<600: noexpandtab sw=4 ts=4
*/