Skip to content

Commit 1d5408b

Browse files
committed
Starting initial work on server implementation
1 parent eaa92d4 commit 1d5408b

File tree

4 files changed

+299
-2
lines changed

4 files changed

+299
-2
lines changed

config.m4

+3-1
Original file line numberDiff line numberDiff line change
@@ -339,11 +339,13 @@ if test "$PHP_MEMCACHED" != "no"; then
339339

340340
PHP_SUBST(MEMCACHED_SHARED_LIBADD)
341341

342-
PHP_MEMCACHED_FILES="php_memcached.c php_libmemcached_compat.c fastlz/fastlz.c g_fmt.c"
342+
PHP_MEMCACHED_FILES="php_memcached.c php_libmemcached_compat.c php_memcached_server.c fastlz/fastlz.c g_fmt.c"
343343

344344
if test "$PHP_MEMCACHED_SESSION" != "no"; then
345345
PHP_MEMCACHED_FILES="${PHP_MEMCACHED_FILES} php_memcached_session.c"
346346
fi
347+
348+
PHP_ADD_LIBRARY_WITH_PATH(memcachedprotocol, $PHP_LIBMEMCACHED_DIR/$PHP_LIBDIR, MEMCACHED_SHARED_LIBADD)
347349

348350
PHP_NEW_EXTENSION(memcached, $PHP_MEMCACHED_FILES, $ext_shared,,$SESSION_INCLUDES $IGBINARY_INCLUDES)
349351
PHP_ADD_BUILD_DIR($ext_builddir/fastlz, 1)

php_memcached.c

+42-1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@
5151
# include "php_memcached_session.h"
5252
#endif
5353

54+
#include "php_memcached_server.h"
55+
5456
#include "fastlz/fastlz.h"
5557
#include <zlib.h>
5658

@@ -220,6 +222,7 @@ enum {
220222
};
221223

222224
static zend_class_entry *memcached_ce = NULL;
225+
static zend_class_entry *memcached_server_ce = NULL;
223226
static zend_class_entry *memcached_exception_ce = NULL;
224227

225228
static zend_object_handlers memcached_object_handlers;
@@ -3373,9 +3376,32 @@ static int php_memc_do_result_callback(zval *zmemc_obj, zend_fcall_info *fci,
33733376

33743377
return rc;
33753378
}
3376-
33773379
/* }}} */
33783380

3381+
static
3382+
PHP_METHOD(MemcachedServer, run)
3383+
{
3384+
php_memc_proto_handler_t *h = php_memc_proto_handler_new ();
3385+
my_run (h);
3386+
}
3387+
3388+
static
3389+
PHP_METHOD(MemcachedServer, on)
3390+
{
3391+
char *event_name;
3392+
int event_name_len;
3393+
zend_fcall_info fci;
3394+
zend_fcall_info_cache fci_cache;
3395+
3396+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sf", &event_name, &event_name_len, &fci, &fci_cache) == FAILURE) {
3397+
return;
3398+
}
3399+
3400+
3401+
3402+
}
3403+
3404+
33793405
/* {{{ methods arginfo */
33803406
ZEND_BEGIN_ARG_INFO_EX(arginfo___construct, 0, 0, 0)
33813407
ZEND_ARG_INFO(0, persistent_id)
@@ -3744,6 +3770,17 @@ static zend_function_entry memcached_class_methods[] = {
37443770
#undef MEMC_ME
37453771
/* }}} */
37463772

3773+
/* {{{ */
3774+
#define MEMC_SE_ME(name, args) PHP_ME(MemcachedServer, name, args, ZEND_ACC_PUBLIC)
3775+
static
3776+
zend_function_entry memcached_server_class_methods[] = {
3777+
MEMC_SE_ME(run, NULL)
3778+
MEMC_SE_ME(on, NULL)
3779+
}
3780+
#undef MEMC_SE_ME
3781+
/* }}} */
3782+
3783+
37473784
/* {{{ memcached_module_entry
37483785
*/
37493786

@@ -3974,6 +4011,10 @@ PHP_MINIT_FUNCTION(memcached)
39744011
memcached_ce = zend_register_internal_class(&ce TSRMLS_CC);
39754012
memcached_ce->create_object = php_memc_new;
39764013

4014+
INIT_CLASS_ENTRY(ce, "MemcachedServer", memcached_server_class_methods);
4015+
memcached_server_ce = zend_register_internal_class(&ce TSRMLS_CC);
4016+
memcached_server_ce->create_object = php_memc_server_new;
4017+
39774018
INIT_CLASS_ENTRY(ce, "MemcachedException", NULL);
39784019
memcached_exception_ce = zend_register_internal_class_ex(&ce, php_memc_get_exception_base(0 TSRMLS_CC), NULL TSRMLS_CC);
39794020
/* TODO

php_memcached_server.c

+220
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
/*
2+
+----------------------------------------------------------------------+
3+
| Copyright (c) 2009-2013 The PHP Group |
4+
+----------------------------------------------------------------------+
5+
| This source file is subject to version 3.01 of the PHP license, |
6+
| that is bundled with this package in the file LICENSE, and is |
7+
| available through the world-wide-web at the following url: |
8+
| http://www.php.net/license/3_01.txt. |
9+
| If you did not receive a copy of the PHP license and are unable to |
10+
| obtain it through the world-wide-web, please send a note to |
11+
| [email protected] so we can mail you a copy immediately. |
12+
+----------------------------------------------------------------------+
13+
| Authors: Mikko Koppanen <[email protected]> |
14+
+----------------------------------------------------------------------+
15+
*/
16+
17+
#ifdef HAVE_CONFIG_H
18+
#include "config.h"
19+
#endif
20+
21+
#include <php.h>
22+
#include "php_libmemcached_compat.h"
23+
#include <libmemcachedprotocol-0.0/handler.h>
24+
25+
#include "php_memcached.h"
26+
#include "php_memcached_server.h"
27+
28+
#include <event2/listener.h>
29+
30+
#undef NDEBUG
31+
#undef _NDEBUG
32+
#include <assert.h>
33+
34+
35+
struct _php_memc_proto_handler_t {
36+
memcached_binary_protocol_callback_st callbacks;
37+
struct memcached_protocol_st *protocol_handle;
38+
struct event_base *event_base;
39+
};
40+
41+
// memcached protocol callbacks
42+
static
43+
protocol_binary_response_status s_add_handler(const void *cookie, const void *key, uint16_t keylen, const void *data,
44+
uint32_t datalen, uint32_t flags, uint32_t exptime, uint64_t *cas)
45+
{
46+
protocol_binary_response_status retval = PROTOCOL_BINARY_RESPONSE_SUCCESS;
47+
48+
fprintf (stderr, "adding key\n");
49+
50+
return retval;
51+
}
52+
53+
// libevent callbacks
54+
typedef struct _php_memc_client_t {
55+
struct memcached_protocol_client_st *protocol_client;
56+
struct event_base *event_base;
57+
} php_memc_client_t;
58+
59+
static
60+
void s_handle_memcached_event (evutil_socket_t fd, short what, void *arg)
61+
{
62+
int rc;
63+
short flags = 0;
64+
php_memc_client_t *client = (php_memc_client_t *)arg;
65+
memcached_protocol_event_t events = memcached_protocol_client_work (client->protocol_client);
66+
67+
if (events & MEMCACHED_PROTOCOL_ERROR_EVENT) {
68+
php_error_docref (NULL TSRMLS_CC, E_WARNING, "Client error during communication");
69+
70+
memcached_protocol_client_destroy (client->protocol_client);
71+
efree (client);
72+
evutil_closesocket (fd);
73+
return;
74+
}
75+
76+
if (events & MEMCACHED_PROTOCOL_WRITE_EVENT) {
77+
flags = EV_WRITE;
78+
}
79+
80+
if (events & MEMCACHED_PROTOCOL_READ_EVENT) {
81+
flags |= EV_READ;
82+
}
83+
84+
rc = event_base_once (client->event_base, fd, flags, s_handle_memcached_event, client, NULL);
85+
if (rc != 0) {
86+
php_error_docref (NULL TSRMLS_CC, E_WARNING, "Failed to schedule events");
87+
}
88+
}
89+
90+
static
91+
void s_accept_cb (evutil_socket_t fd, short what, void *arg)
92+
{
93+
int rc;
94+
php_memc_client_t *client;
95+
struct sockaddr_storage addr;
96+
socklen_t addr_len;
97+
evutil_socket_t sock;
98+
99+
php_memc_proto_handler_t *handler = (php_memc_proto_handler_t *) arg;
100+
101+
/* Accept the connection */
102+
addr_len = sizeof (addr);
103+
sock = accept (fd, (struct sockaddr *) &addr, &addr_len);
104+
105+
if (sock == -1) {
106+
php_error_docref (NULL TSRMLS_CC, E_WARNING, "Failed to accept the client: %s", strerror (errno));
107+
return;
108+
}
109+
110+
client = ecalloc (1, sizeof (php_memc_client_t));
111+
client->protocol_client = memcached_protocol_create_client (handler->protocol_handle, sock);
112+
client->event_base = handler->event_base;
113+
114+
if (!client->protocol_client) {
115+
php_error_docref (NULL TSRMLS_CC, E_WARNING, "Failed to allocate protocol client");
116+
efree (client);
117+
evutil_closesocket (sock);
118+
return;
119+
}
120+
121+
// TODO: this should timeout
122+
rc = event_base_once (handler->event_base, sock, EV_READ, s_handle_memcached_event, client, NULL);
123+
124+
if (rc != 0) {
125+
php_error_docref (NULL TSRMLS_CC, E_WARNING, "Failed to add event for client");
126+
memcached_protocol_client_destroy (client->protocol_client);
127+
efree (client);
128+
evutil_closesocket (sock);
129+
return;
130+
}
131+
}
132+
133+
php_memc_proto_handler_t *php_memc_proto_handler_new ()
134+
{
135+
php_memc_proto_handler_t *handler = ecalloc (1, sizeof (php_memc_proto_handler_t));
136+
137+
handler->protocol_handle = memcached_protocol_create_instance ();
138+
assert (handler->protocol_handle);
139+
140+
memset (&handler->callbacks, 0, sizeof (memcached_binary_protocol_callback_st));
141+
142+
handler->callbacks.interface_version = MEMCACHED_PROTOCOL_HANDLER_V1;
143+
handler->callbacks.interface.v1.add = s_add_handler;
144+
/*handler->callbacks.interface.v1.append = s_append_handler;
145+
handler->callbacks.interface.v1.decrement = s_decrement_handler;
146+
handler->callbacks.interface.v1.delete_object = s_delete_handler;
147+
handler->callbacks.interface.v1.flush_object = s_flush_handler;
148+
handler->callbacks.interface.v1.get = s_get_handler;
149+
handler->callbacks.interface.v1.increment = s_increment_handler;
150+
handler->callbacks.interface.v1.noop = s_noop_handler;
151+
handler->callbacks.interface.v1.prepend = s_prepend_handler;
152+
handler->callbacks.interface.v1.quit = s_quit_handler;
153+
handler->callbacks.interface.v1.replace = s_replace_handler;
154+
handler->callbacks.interface.v1.set = s_set_handler;
155+
handler->callbacks.interface.v1.stat = s_stat_handler;
156+
handler->callbacks.interface.v1.version = s_version_handler;
157+
*/
158+
159+
memcached_binary_protocol_set_callbacks(handler->protocol_handle, &handler->callbacks);
160+
return handler;
161+
}
162+
163+
static
164+
evutil_socket_t s_create_listening_socket (const char *spec)
165+
{
166+
evutil_socket_t sock;
167+
struct sockaddr_storage addr;
168+
int addr_len;
169+
170+
int rc;
171+
172+
addr_len = sizeof (struct sockaddr);
173+
rc = evutil_parse_sockaddr_port (spec, (struct sockaddr *) &addr, &addr_len);
174+
assert (rc == 0);
175+
176+
sock = socket (AF_INET, SOCK_STREAM, 0);
177+
assert (sock >= 0);
178+
179+
rc = bind (sock, (struct sockaddr *) &addr, addr_len);
180+
assert (sock >= 0);
181+
182+
rc = listen (sock, 1024);
183+
assert (rc >= 0);
184+
185+
rc = evutil_make_socket_nonblocking (sock);
186+
assert (rc == 0);
187+
188+
rc = evutil_make_listen_socket_reuseable (sock);
189+
assert (rc == 0);
190+
191+
rc = evutil_make_socket_closeonexec (sock);
192+
assert (rc == 0);
193+
194+
return sock;
195+
}
196+
197+
void my_run (php_memc_proto_handler_t *handler)
198+
{
199+
struct event *accept_event;
200+
evutil_socket_t sock = s_create_listening_socket ("127.0.0.1:3434");
201+
202+
handler->event_base = event_base_new();
203+
204+
accept_event = event_new (handler->event_base, sock, EV_READ | EV_PERSIST, s_accept_cb, handler);
205+
event_add (accept_event, NULL);
206+
207+
int f = event_base_dispatch (handler->event_base);
208+
fprintf (stderr, "Re: %d\n", f);
209+
}
210+
211+
void php_memc_proto_handler_destroy (php_memc_proto_handler_t **ptr)
212+
{
213+
php_memc_proto_handler_t *handler = *ptr;
214+
215+
if (handler->protocol_handle)
216+
memcached_protocol_destroy_instance (handler->protocol_handle);
217+
218+
efree (handler);
219+
*ptr = NULL;
220+
}

php_memcached_server.h

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
+----------------------------------------------------------------------+
3+
| Copyright (c) 2009-2013 The PHP Group |
4+
+----------------------------------------------------------------------+
5+
| This source file is subject to version 3.01 of the PHP license, |
6+
| that is bundled with this package in the file LICENSE, and is |
7+
| available through the world-wide-web at the following url: |
8+
| http://www.php.net/license/3_01.txt. |
9+
| If you did not receive a copy of the PHP license and are unable to |
10+
| obtain it through the world-wide-web, please send a note to |
11+
| [email protected] so we can mail you a copy immediately. |
12+
+----------------------------------------------------------------------+
13+
| Authors: Mikko Koppanen <[email protected]> |
14+
+----------------------------------------------------------------------+
15+
*/
16+
17+
#ifndef _PHP_MEMCACHED_SERVER_H_
18+
# define _PHP_MEMCACHED_SERVER_H_
19+
20+
/*
21+
Opaque structure
22+
*/
23+
typedef struct _php_memc_proto_handler_t php_memc_proto_handler_t;
24+
25+
/*
26+
Functions
27+
*/
28+
php_memc_proto_handler_t *php_memc_proto_handler_new ();
29+
30+
void php_memc_proto_handler_destroy (php_memc_proto_handler_t **ptr);
31+
32+
void my_run (php_memc_proto_handler_t *h);
33+
34+
#endif

0 commit comments

Comments
 (0)