2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010 Hyves (http://www.hyves.nl) |
6 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
7 | Copyright (c) 1997-2010 The PHP Group |
8 +----------------------------------------------------------------------+
9 | This source file is subject to version 3.01 of the PHP license, |
10 | that is bundled with this package in the file LICENSE, and is |
11 | available through the world-wide-web at the following url: |
12 | http://www.php.net/license/3_01.txt |
13 | If you did not receive a copy of the PHP license and are unable to |
14 | obtain it through the world-wide-web, please send a note to |
15 | license@php.net so we can mail you a copy immediately. |
16 +----------------------------------------------------------------------+
19 #include "hphp/runtime/base/array-init.h"
20 #include "hphp/runtime/ext/extension.h"
21 #include "hphp/runtime/vm/native-data.h"
22 #include "hphp/runtime/ext/memcached/libmemcached_portability.h"
23 #include "hphp/runtime/base/builtin-functions.h"
24 #include "hphp/runtime/ext/json/ext_json.h"
31 #include "hphp/system/systemlib.h"
34 ///////////////////////////////////////////////////////////////////////////////
36 // Payload value flags
37 #define MEMC_VAL_TYPE_MASK 0xf
39 #define MEMC_VAL_IS_STRING 0
40 #define MEMC_VAL_IS_LONG 1
41 #define MEMC_VAL_IS_DOUBLE 2
42 #define MEMC_VAL_IS_BOOL 3
43 #define MEMC_VAL_IS_SERIALIZED 4
44 #define MEMC_VAL_IS_IGBINARY 5
45 #define MEMC_VAL_IS_JSON 6
47 #define MEMC_VAL_COMPRESSED (1<<4)
48 #define MEMC_VAL_COMPRESSION_ZLIB (1<<5)
49 #define MEMC_VAL_COMPRESSION_FASTLZ (1<<6)
51 #define MEMC_COMPRESS_THRESHOLD 100
53 #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x00052000
54 # define MEMCACHED_SERVER_TEMPORARILY_DISABLED (1024 << 2)
57 #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000002
58 # define HAVE_MEMCACHED_TOUCH 1
62 const int64_t q_Memcached$$OPT_COMPRESSION
= -1001;
63 const int64_t q_Memcached$$OPT_PREFIX_KEY
= -1002;
64 const int64_t q_Memcached$$OPT_SERIALIZER
= -1003;
67 const int64_t q_Memcached$$RES_PAYLOAD_FAILURE
= -1001;
70 const int64_t q_Memcached$$SERIALIZER_PHP
= 1;
71 const int64_t q_Memcached$$SERIALIZER_IGBINARY
= 2;
72 const int64_t q_Memcached$$SERIALIZER_JSON
= 3;
75 const int64_t q_Memcached$$GET_PRESERVE_ORDER
= 1;
84 struct MEMCACHEDGlobals final
{
85 std::string sess_prefix
;
87 static __thread MEMCACHEDGlobals
* s_memcached_globals
;
88 #define MEMCACHEDG(name) s_memcached_globals->name
91 struct MemcachedResultWrapper
{
92 memcached_result_st value
;
93 explicit MemcachedResultWrapper(memcached_st
*memcached
) {
94 memcached_result_create(memcached
, &value
);
96 ~MemcachedResultWrapper() {
97 memcached_result_free(&value
);
103 * Since libmemcachd is in C, we cannot use lambda functions as lambda functions
104 * are special typed and normally passed by templated types.
106 static memcached_return_t
memcached_dump_callback(const memcached_st
*,
108 size_t len
, void* context
) {
109 ((Array
*)context
)->append(Variant
{makeStaticString(key
, len
)});
110 return MEMCACHED_SUCCESS
;
113 const StaticString
s_MemcachedData("MemcachedData");
115 struct MemcachedData
{
119 serializer(q_Memcached$$SERIALIZER_PHP
),
120 rescode(MEMCACHED_SUCCESS
) {
121 memcached_create(&memcached
);
124 memcached_free(&memcached
);
127 memcached_st memcached
;
137 typedef std::shared_ptr
<Impl
> ImplPtr
;
140 bool handleError(memcached_return status
) {
142 case MEMCACHED_SUCCESS
:
143 case MEMCACHED_STORED
:
144 case MEMCACHED_DELETED
:
148 case MEMCACHED_BUFFERED
:
149 m_impl
->rescode
= status
;
152 m_impl
->rescode
= status
;
156 void toPayload(const Variant
& value
, std::vector
<char> &payload
,
159 if (value
.isString() || value
.isNumeric()) {
160 encoded
= value
.toString();
161 if (value
.isString()) flags
= MEMC_VAL_IS_STRING
;
162 else if (value
.isInteger()) flags
= MEMC_VAL_IS_LONG
;
163 else if (value
.isDouble()) flags
= MEMC_VAL_IS_DOUBLE
;
164 else if (value
.isBoolean()) flags
= MEMC_VAL_IS_BOOL
;
167 switch (m_impl
->serializer
) {
168 case q_Memcached$$SERIALIZER_JSON
:
169 encoded
= Variant::attach(HHVM_FN(json_encode
)(value
)).toString();
170 flags
= MEMC_VAL_IS_JSON
;
173 encoded
= f_serialize(value
);
174 flags
= MEMC_VAL_IS_SERIALIZED
;
179 if (m_impl
->compression
&& encoded
.length() >= MEMC_COMPRESS_THRESHOLD
) {
180 unsigned long payloadCompLength
= compressBound(encoded
.length());
181 payload
.resize(payloadCompLength
);
182 if (compress((Bytef
*)payload
.data(), &payloadCompLength
,
183 (const Bytef
*)encoded
.data(), encoded
.length()) == Z_OK
) {
184 payload
.resize(payloadCompLength
);
185 flags
|= MEMC_VAL_COMPRESSED
;
188 raise_warning("could not compress value");
192 payload
.insert(payload
.end(),
193 encoded
.data(), encoded
.data() + encoded
.length());
195 bool toObject(Variant
& value
, const memcached_result_st
&result
) {
196 const char *payload
= memcached_result_value(&result
);
197 size_t payloadLength
= memcached_result_length(&result
);
198 uint32_t flags
= memcached_result_flags(&result
);
200 String decompPayload
;
201 if (flags
& MEMC_VAL_COMPRESSED
) {
203 std::vector
<char> buffer
;
204 unsigned long bufferSize
;
209 if ((flags
& MEMC_VAL_COMPRESSION_FASTLZ
||
210 flags
& MEMC_VAL_COMPRESSION_ZLIB
)
211 && payloadLength
> sizeof(uint32_t)) {
212 memcpy(&maxLength
, payload
, sizeof(uint32_t));
213 if (maxLength
< std::numeric_limits
<uint32_t>::max()) {
214 buffer
.resize(maxLength
+ 1);
215 payloadLength
-= sizeof(uint32_t);
216 payload
+= sizeof(uint32_t);
217 bufferSize
= maxLength
;
219 if (flags
& MEMC_VAL_COMPRESSION_FASTLZ
) {
220 bufferSize
= fastlz_decompress(payload
, payloadLength
,
221 buffer
.data(), maxLength
);
222 done
= (bufferSize
> 0);
223 } else if (flags
& MEMC_VAL_COMPRESSION_ZLIB
) {
224 status
= uncompress((Bytef
*)buffer
.data(), &bufferSize
,
225 (const Bytef
*)payload
, (uLong
)payloadLength
);
226 done
= (status
== Z_OK
);
233 for (int factor
= 1; factor
<= 16; ++factor
) {
235 std::numeric_limits
<unsigned long>::max() / (1 << factor
)) {
238 bufferSize
= payloadLength
* (1 << factor
) + 1;
239 buffer
.resize(bufferSize
);
240 status
= uncompress((Bytef
*)buffer
.data(), &bufferSize
,
241 (const Bytef
*)payload
, (uLong
)payloadLength
);
242 if (status
== Z_OK
) {
245 } else if (status
!= Z_BUF_ERROR
) {
251 raise_warning("could not uncompress value");
255 String::attach(StringData::Make(buffer
.data(), bufferSize
, CopyString
));
258 String::attach(StringData::Make(payload
, payloadLength
, CopyString
));
261 switch (flags
& MEMC_VAL_TYPE_MASK
) {
262 case MEMC_VAL_IS_STRING
:
263 value
= decompPayload
;
265 case MEMC_VAL_IS_LONG
:
266 value
= decompPayload
.toInt64();
268 case MEMC_VAL_IS_DOUBLE
:
269 value
= decompPayload
.toDouble();
271 case MEMC_VAL_IS_BOOL
:
272 value
= decompPayload
.toBoolean();
274 case MEMC_VAL_IS_JSON
:
275 value
= Variant::attach(HHVM_FN(json_decode
)(decompPayload
));
277 case MEMC_VAL_IS_SERIALIZED
:
278 value
= unserialize_from_string(decompPayload
);
280 case MEMC_VAL_IS_IGBINARY
:
281 raise_warning("could not unserialize value, no igbinary support");
284 raise_warning("unknown payload type");
289 memcached_return
doCacheCallback(const Variant
& callback
, ObjectData
* this_
,
290 const String
& key
, Variant
& value
) {
291 Array
params(PackedArrayInit(3).append(Variant(this_
))
293 .appendRef(value
).toArray());
294 if (!vm_call_user_func(callback
, params
).toBoolean()) {
295 return MEMCACHED_NOTFOUND
;
298 std::vector
<char> payload
; uint32_t flags
;
299 toPayload(value
, payload
, flags
);
300 return memcached_set(&m_impl
->memcached
, key
.c_str(), key
.length(),
301 payload
.data(), payload
.size(), 0, flags
);
303 bool getMultiImpl(const String
& server_key
, const Array
& keys
, bool enableCas
,
304 Array
*returnValue
) {
305 std::vector
<const char*> keysCopy
;
306 keysCopy
.reserve(keys
.size());
307 std::vector
<size_t> keysLengthCopy
;
308 keysLengthCopy
.reserve(keys
.size());
309 for (ArrayIter
iter(keys
); iter
; ++iter
) {
310 Variant vKey
= iter
.second();
311 if (!vKey
.isString()) continue;
312 StringData
*key
= vKey
.getStringData();
313 if (key
->empty()) continue;
314 keysCopy
.push_back(key
->data());
315 keysLengthCopy
.push_back(key
->size());
316 if (returnValue
) returnValue
->set(String(key
), init_null(), true);
318 if (keysCopy
.size() == 0) {
319 m_impl
->rescode
= MEMCACHED_BAD_KEY_PROVIDED
;
323 memcached_behavior_set(&m_impl
->memcached
, MEMCACHED_BEHAVIOR_SUPPORT_CAS
,
325 const char *myServerKey
= server_key
.empty() ? nullptr : server_key
.c_str();
326 size_t myServerKeyLen
= server_key
.length();
327 return handleError(memcached_mget_by_key(&m_impl
->memcached
,
328 myServerKey
, myServerKeyLen
, keysCopy
.data(), keysLengthCopy
.data(),
331 bool fetchImpl(memcached_result_st
&result
, Array
&item
) {
332 memcached_return status
;
333 if (!memcached_fetch_result(&m_impl
->memcached
, &result
, &status
)) {
339 if (!toObject(value
, result
)) {
340 m_impl
->rescode
= q_Memcached$$RES_PAYLOAD_FAILURE
;
344 const char *key
= memcached_result_key_value(&result
);
345 size_t keyLength
= memcached_result_key_length(&result
);
346 String
sKey(key
, keyLength
, CopyString
);
347 double cas
= (double) memcached_result_cas(&result
);
349 item
= make_map_array(s_key
, sKey
, s_value
, value
, s_cas
, cas
);
352 typedef memcached_return_t (*SetOperation
)(memcached_st
*,
353 const char *, size_t, const char *, size_t, const char *, size_t,
356 bool setOperationImpl(SetOperation op
, const String
& server_key
,
357 const String
& key
, const Variant
& value
,
359 m_impl
->rescode
= MEMCACHED_SUCCESS
;
361 m_impl
->rescode
= MEMCACHED_BAD_KEY_PROVIDED
;
365 std::vector
<char> payload
; uint32_t flags
;
366 toPayload(value
, payload
, flags
);
368 const String
& myServerKey
= server_key
.empty() ? key
: server_key
;
369 return handleError(op(&m_impl
->memcached
, myServerKey
.c_str(),
370 myServerKey
.length(), key
.c_str(), key
.length(),
371 payload
.data(), payload
.size(), expiration
, flags
));
374 Variant
incDecOp(bool isInc
,
375 const StringData
* server_key
, const StringData
* key
,
376 int64_t offset
, const Variant
& initial_value
, int64_t expiry
) {
377 m_impl
->rescode
= MEMCACHED_SUCCESS
;
378 if (key
->empty() || strchr(key
->data(), ' ')) {
379 m_impl
->rescode
= MEMCACHED_BAD_KEY_PROVIDED
;
383 raise_warning("offset has to be >= 0");
387 // Dispatch to the correct memcached_* function depending on initial_value,
388 // server_key, and isInc.
390 memcached_return_t status
;
392 bool use_initial
= initial_value
.isInteger();
393 auto mc
= &m_impl
->memcached
;
395 if (!isBinaryProtocol()) {
396 raise_warning("Initial value is only supported with binary protocol");
402 status
= memcached_increment_with_initial_by_key(
404 server_key
->data(), server_key
->size(), key
->data(), key
->size(),
405 offset
, initial_value
.asInt64Val(), expiry
, &value
);
407 status
= memcached_decrement_with_initial_by_key(
409 server_key
->data(), server_key
->size(), key
->data(), key
->size(),
410 offset
, initial_value
.asInt64Val(), expiry
, &value
);
414 status
= memcached_increment_with_initial(
415 mc
, key
->data(), key
->size(),
416 offset
, initial_value
.asInt64Val(), expiry
, &value
);
418 status
= memcached_decrement_with_initial(
419 mc
, key
->data(), key
->size(),
420 offset
, initial_value
.asInt64Val(), expiry
, &value
);
426 status
= memcached_increment_by_key(
428 server_key
->data(), server_key
->size(), key
->data(), key
->size(),
431 status
= memcached_decrement_by_key(
433 server_key
->data(), server_key
->size(), key
->data(), key
->size(),
438 status
= memcached_increment(
439 mc
, key
->data(), key
->size(), offset
, &value
);
441 status
= memcached_decrement(
442 mc
, key
->data(), key
->size(), offset
, &value
);
447 if (!handleError(status
)) return false;
448 return (int64_t)value
;
451 bool isBinaryProtocol() {
452 return memcached_behavior_get(&m_impl
->memcached
,
453 MEMCACHED_BEHAVIOR_BINARY_PROTOCOL
);
456 typedef std::map
<std::string
, ImplPtr
> ImplMap
;
457 static DECLARE_THREAD_LOCAL(ImplMap
, s_persistentMap
);
460 void HHVM_METHOD(Memcached
, __construct
,
461 const Variant
& persistent_id
/*= null*/) {
462 auto data
= Native::data
<MemcachedData
>(this_
);
463 if (persistent_id
.isNull()) {
464 data
->m_impl
.reset(new MemcachedData::Impl
);
465 data
->m_impl
->is_persistent
= false;
466 data
->m_impl
->is_pristine
= true;
468 bool is_pristine
= false;
469 MemcachedData::ImplPtr
&impl
= (*data
->s_persistentMap
)[
470 persistent_id
.toString().toCppString()
473 impl
.reset(new MemcachedData::Impl
);
477 data
->m_impl
->is_persistent
= true;
478 data
->m_impl
->is_pristine
= is_pristine
;
482 bool HHVM_METHOD(Memcached
, quit
) {
483 auto data
= Native::data
<MemcachedData
>(this_
);
484 memcached_quit(&data
->m_impl
->memcached
);
488 Variant
HHVM_METHOD(Memcached
, getallkeys
) {
489 auto data
= Native::data
<MemcachedData
>(this_
);
490 memcached_dump_fn callbacks
[] = {
491 &memcached_dump_callback
,
495 memcached_return status
= memcached_dump(&data
->m_impl
->memcached
, callbacks
,
498 sizeof(memcached_dump_fn
));
499 if (!data
->handleError(status
)) {
506 Variant
HHVM_METHOD(Memcached
, getbykey
, const String
& server_key
,
508 const Variant
& cache_cb
/*= null*/,
509 VRefParam cas_token
/*= null*/) {
510 auto data
= Native::data
<MemcachedData
>(this_
);
511 data
->m_impl
->rescode
= MEMCACHED_SUCCESS
;
513 data
->m_impl
->rescode
= MEMCACHED_BAD_KEY_PROVIDED
;
517 memcached_behavior_set(&data
->m_impl
->memcached
,
518 MEMCACHED_BEHAVIOR_SUPPORT_CAS
,
519 cas_token
.isReferenced() ? 1 : 0);
520 const char *myServerKey
= server_key
.empty() ? nullptr : server_key
.c_str();
521 size_t myServerKeyLen
= server_key
.length();
522 const char *myKey
= key
.c_str();
523 size_t myKeyLen
= key
.length();
524 memcached_return status
= memcached_mget_by_key(&data
->m_impl
->memcached
,
525 myServerKey
, myServerKeyLen
, &myKey
, &myKeyLen
, 1);
526 if (!data
->handleError(status
)) return false;
529 MemcachedResultWrapper
result(&data
->m_impl
->memcached
);
530 if (!memcached_fetch_result(&data
->m_impl
->memcached
,
531 &result
.value
, &status
)) {
532 if (status
== MEMCACHED_END
) status
= MEMCACHED_NOTFOUND
;
533 if (status
== MEMCACHED_NOTFOUND
&& !cache_cb
.isNull()) {
534 status
= data
->doCacheCallback(cache_cb
, this_
, key
, returnValue
);
535 if (!data
->handleError(status
)) return false;
536 cas_token
.assignIfRef(0.0);
539 data
->handleError(status
);
543 if (!data
->toObject(returnValue
, result
.value
)) {
544 data
->m_impl
->rescode
= q_Memcached$$RES_PAYLOAD_FAILURE
;
547 cas_token
.assignIfRef((double) memcached_result_cas(&result
.value
));
551 Variant
HHVM_METHOD(Memcached
, getmultibykey
, const String
& server_key
,
553 VRefParam cas_tokens
/*= uninit_variant*/,
555 auto data
= Native::data
<MemcachedData
>(this_
);
556 data
->m_impl
->rescode
= MEMCACHED_SUCCESS
;
558 bool preserveOrder
= flags
& q_Memcached$$GET_PRESERVE_ORDER
;
559 Array returnValue
= Array::Create();
560 if (!data
->getMultiImpl(server_key
, keys
, cas_tokens
.isReferenced(),
561 preserveOrder
? &returnValue
: nullptr)) {
565 Array cas_tokens_arr
;
566 SCOPE_EXIT
{ cas_tokens
.assignIfRef(cas_tokens_arr
); };
568 MemcachedResultWrapper
result(&data
->m_impl
->memcached
);
569 memcached_return status
;
570 while (memcached_fetch_result(&data
->m_impl
->memcached
, &result
.value
,
572 if (status
!= MEMCACHED_SUCCESS
) {
573 status
= MEMCACHED_SOME_ERRORS
;
574 data
->handleError(status
);
578 if (!data
->toObject(value
, result
.value
)) {
579 data
->m_impl
->rescode
= q_Memcached$$RES_PAYLOAD_FAILURE
;
582 const char *key
= memcached_result_key_value(&result
.value
);
583 size_t keyLength
= memcached_result_key_length(&result
.value
);
584 String
sKey(key
, keyLength
, CopyString
);
585 returnValue
.set(sKey
, value
, true);
586 if (cas_tokens
.isReferenced()) {
587 double cas
= (double) memcached_result_cas(&result
.value
);
588 cas_tokens_arr
.set(sKey
, cas
, true);
594 bool HHVM_METHOD(Memcached
, getdelayedbykey
, const String
& server_key
,
595 const Array
& keys
, bool with_cas
/*= false*/,
596 const Variant
& value_cb
/*= uninit_variant*/) {
597 auto data
= Native::data
<MemcachedData
>(this_
);
598 data
->m_impl
->rescode
= MEMCACHED_SUCCESS
;
600 if (!data
->getMultiImpl(server_key
, keys
, with_cas
, nullptr)) return false;
601 if (value_cb
.isNull()) return true;
603 MemcachedResultWrapper
result(&data
->m_impl
->memcached
); Array item
;
604 while (data
->fetchImpl(result
.value
, item
)) {
605 vm_call_user_func(value_cb
, make_packed_array(Variant(this_
), item
));
608 if (data
->m_impl
->rescode
!= MEMCACHED_END
) return false;
609 data
->m_impl
->rescode
= MEMCACHED_SUCCESS
;
613 Variant
HHVM_METHOD(Memcached
, fetch
) {
614 auto data
= Native::data
<MemcachedData
>(this_
);
615 data
->m_impl
->rescode
= MEMCACHED_SUCCESS
;
617 MemcachedResultWrapper
result(&data
->m_impl
->memcached
); Array item
;
618 if (!data
->fetchImpl(result
.value
, item
)) return false;
623 Variant
HHVM_METHOD(Memcached
, fetchall
) {
624 auto data
= Native::data
<MemcachedData
>(this_
);
625 data
->m_impl
->rescode
= MEMCACHED_SUCCESS
;
628 MemcachedResultWrapper
result(&data
->m_impl
->memcached
); Array item
;
629 while (data
->fetchImpl(result
.value
, item
)) {
630 returnValue
.append(item
);
633 if (data
->m_impl
->rescode
!= MEMCACHED_END
) return false;
637 bool HHVM_METHOD(Memcached
, setbykey
, const String
& server_key
,
638 const String
& key
, const Variant
& value
,
639 int expiration
/*= 0*/) {
640 auto data
= Native::data
<MemcachedData
>(this_
);
641 return data
->setOperationImpl(memcached_set_by_key
, server_key
, key
, value
,
645 bool HHVM_METHOD(Memcached
, addbykey
, const String
& server_key
,
646 const String
& key
, const Variant
& value
,
647 int expiration
/*= 0*/) {
648 auto data
= Native::data
<MemcachedData
>(this_
);
649 return data
->setOperationImpl(memcached_add_by_key
, server_key
, key
, value
,
653 bool HHVM_METHOD(Memcached
, appendbykey
, const String
& server_key
,
655 const String
& value
) {
656 auto data
= Native::data
<MemcachedData
>(this_
);
657 if (data
->m_impl
->compression
) {
658 raise_warning("cannot append/prepend with compression turned on");
661 return data
->setOperationImpl(memcached_append_by_key
, server_key
, key
,
665 bool HHVM_METHOD(Memcached
, prependbykey
, const String
& server_key
,
667 const String
& value
) {
668 auto data
= Native::data
<MemcachedData
>(this_
);
669 if (data
->m_impl
->compression
) {
670 raise_warning("cannot append/prepend with compression turned on");
673 return data
->setOperationImpl(memcached_prepend_by_key
, server_key
, key
,
677 bool HHVM_METHOD(Memcached
, replacebykey
, const String
& server_key
,
679 const Variant
& value
,
680 int expiration
/*= 0*/) {
681 auto data
= Native::data
<MemcachedData
>(this_
);
682 return data
->setOperationImpl(memcached_replace_by_key
, server_key
, key
,
686 bool HHVM_METHOD(Memcached
, casbykey
, double cas_token
,
687 const String
& server_key
,
689 const Variant
& value
,
690 int expiration
/*= 0*/) {
691 auto data
= Native::data
<MemcachedData
>(this_
);
692 data
->m_impl
->rescode
= MEMCACHED_SUCCESS
;
694 data
->m_impl
->rescode
= MEMCACHED_BAD_KEY_PROVIDED
;
698 std::vector
<char> payload
; uint32_t flags
;
699 data
->toPayload(value
, payload
, flags
);
701 const String
& myServerKey
= server_key
.empty() ? key
: server_key
;
702 return data
->handleError(memcached_cas_by_key(&data
->m_impl
->memcached
,
703 myServerKey
.c_str(), myServerKey
.length(), key
.c_str(), key
.length(),
704 payload
.data(), payload
.size(), expiration
, flags
, (uint64_t)cas_token
));
707 bool HHVM_METHOD(Memcached
, deletebykey
, const String
& server_key
,
710 auto data
= Native::data
<MemcachedData
>(this_
);
711 data
->m_impl
->rescode
= MEMCACHED_SUCCESS
;
713 data
->m_impl
->rescode
= MEMCACHED_BAD_KEY_PROVIDED
;
717 const String
& myServerKey
= server_key
.empty() ? key
: server_key
;
718 return data
->handleError(memcached_delete_by_key(&data
->m_impl
->memcached
,
719 myServerKey
.c_str(), myServerKey
.length(),
720 key
.c_str(), key
.length(), time
));
723 Variant
HHVM_METHOD(Memcached
, deletemultibykey
, const String
& server_key
,
725 int64_t time
/*= 0*/) {
726 auto data
= Native::data
<MemcachedData
>(this_
);
727 data
->m_impl
->rescode
= MEMCACHED_SUCCESS
;
729 memcached_return status_memcached
;
731 Array returnValue
= Array::Create();
732 for (ArrayIter
iter(keys
); iter
; ++iter
) {
733 Variant vKey
= iter
.second();
734 if (!vKey
.isString()) continue;
735 const String
& key
= vKey
.toString();
736 if (key
.empty()) continue;
737 const String
& myServerKey
= server_key
.empty() ? key
: server_key
;
738 status_memcached
= memcached_delete_by_key(&data
->m_impl
->memcached
,
739 myServerKey
.c_str(), myServerKey
.length(),
740 key
.c_str(), key
.length(), time
);
742 status
= data
->handleError(status_memcached
);
744 returnValue
.set(key
, status_memcached
, true);
746 returnValue
.set(key
, status
, true);
752 Variant
HHVM_METHOD(Memcached
, increment
,
754 int64_t offset
/* = 1 */,
755 const Variant
& initial_value
/* = false */,
756 int64_t expiry
/* = 0 */) {
757 return Native::data
<MemcachedData
>(this_
)->incDecOp(
758 true, nullptr, key
.get(), offset
, initial_value
, expiry
);
761 Variant
HHVM_METHOD(Memcached
, incrementbykey
,
762 const String
& server_key
,
764 int64_t offset
/* = 1 */,
765 const Variant
& initial_value
/* = false */,
766 int64_t expiry
/* = 0 */) {
767 return Native::data
<MemcachedData
>(this_
)->incDecOp(
768 true, server_key
.get(), key
.get(), offset
, initial_value
, expiry
);
771 Variant
HHVM_METHOD(Memcached
, decrement
,
773 int64_t offset
/* = 1 */,
774 const Variant
& initial_value
/* = false */,
775 int64_t expiry
/* = 0 */) {
776 return Native::data
<MemcachedData
>(this_
)->incDecOp(
777 false, nullptr, key
.get(), offset
, initial_value
, expiry
);
780 Variant
HHVM_METHOD(Memcached
, decrementbykey
,
781 const String
& server_key
,
783 int64_t offset
/* = 1 */,
784 const Variant
& initial_value
/* = false */,
785 int64_t expiry
/* = 0 */) {
786 return Native::data
<MemcachedData
>(this_
)->incDecOp(
787 false, server_key
.get(), key
.get(), offset
, initial_value
, expiry
);
790 bool HHVM_METHOD(Memcached
, addserver
, const String
& host
, int port
,
791 int weight
/*= 0*/) {
792 auto data
= Native::data
<MemcachedData
>(this_
);
793 data
->m_impl
->rescode
= MEMCACHED_SUCCESS
;
794 if (!host
.empty() && host
[0] == '/') {
795 return data
->handleError(memcached_server_add_unix_socket_with_weight(
796 &data
->m_impl
->memcached
, host
.c_str(), weight
));
798 return data
->handleError(memcached_server_add_with_weight(
799 &data
->m_impl
->memcached
, host
.c_str(), port
, weight
806 const StaticString
s_host("host"), s_port("port");
807 #ifdef LMCD_SERVER_QUERY_INCLUDES_WEIGHT
808 const StaticString
s_weight("weight");
811 memcached_return_t
doServerListCallback(const memcached_st
*ptr
,
812 LMCD_SERVER_CALLBACK_INSTANCE_TYPE server
, void *context
) {
813 Array
*returnValue
= (Array
*) context
;
814 const char* hostname
= LMCD_SERVER_HOSTNAME(server
);
815 in_port_t port
= LMCD_SERVER_PORT(server
);
816 #ifdef LMCD_SERVER_QUERY_INCLUDES_WEIGHT
817 returnValue
->append(make_map_array(s_host
, String(hostname
, CopyString
),
818 s_port
, (int32_t)port
,
819 s_weight
, (int32_t)server
->weight
));
821 returnValue
->append(make_map_array(s_host
, String(hostname
, CopyString
),
822 s_port
, (int32_t)port
));
824 return MEMCACHED_SUCCESS
;
828 Array
HHVM_METHOD(Memcached
, getserverlist
) {
829 auto data
= Native::data
<MemcachedData
>(this_
);
830 Array returnValue
= Array::Create();
831 memcached_server_function callbacks
[] = { doServerListCallback
};
832 memcached_server_cursor(&data
->m_impl
->memcached
, callbacks
, &returnValue
, 1);
836 bool HHVM_METHOD(Memcached
, resetserverlist
) {
837 auto data
= Native::data
<MemcachedData
>(this_
);
838 memcached_servers_reset(&data
->m_impl
->memcached
);
842 Variant
HHVM_METHOD(Memcached
, getserverbykey
, const String
& server_key
) {
843 auto data
= Native::data
<MemcachedData
>(this_
);
844 data
->m_impl
->rescode
= MEMCACHED_SUCCESS
;
845 if (server_key
.empty()) {
846 data
->m_impl
->rescode
= MEMCACHED_BAD_KEY_PROVIDED
;
850 memcached_return_t error
;
851 LMCD_SERVER_BY_KEY_INSTANCE_TYPE server
= memcached_server_by_key(
852 &data
->m_impl
->memcached
, server_key
.c_str(), server_key
.size(), &error
);
854 data
->handleError(error
);
858 const char* hostname
= LMCD_SERVER_HOSTNAME(server
);
859 in_port_t port
= LMCD_SERVER_PORT(server
);
860 #ifdef LMCD_SERVER_QUERY_INCLUDES_WEIGHT
861 Array returnValue
= make_map_array(s_host
, String(hostname
, CopyString
),
862 s_port
, (int32_t)port
,
863 s_weight
, (int32_t)server
->weight
);
865 Array returnValue
= make_map_array(s_host
, String(hostname
, CopyString
),
866 s_port
, (int32_t)port
);
872 struct StatsContext
{
873 memcached_stat_st
*stats
;
880 s_threads("threads"),
882 s_pointer_size("pointer_size"),
883 s_rusage_user_seconds("rusage_user_seconds"),
884 s_rusage_user_microseconds("rusage_user_microseconds"),
885 s_rusage_system_seconds("rusage_system_seconds"),
886 s_rusage_system_microseconds("rusage_system_microseconds"),
887 s_curr_items("curr_items"),
888 s_total_items("total_items"),
889 s_limit_maxbytes("limit_maxbytes"),
890 s_curr_connections("curr_connections"),
891 s_total_connections("total_connections"),
892 s_connection_structures("connection_structures"),
894 s_cmd_get("cmd_get"),
895 s_cmd_set("cmd_set"),
896 s_get_hits("get_hits"),
897 s_get_misses("get_misses"),
898 s_evictions("evictions"),
899 s_bytes_read("bytes_read"),
900 s_bytes_written("bytes_written"),
901 s_version("version");
903 memcached_return_t
doStatsCallback(const memcached_st
*ptr
,
904 LMCD_SERVER_CALLBACK_INSTANCE_TYPE server
, void *inContext
) {
905 StatsContext
*context
= (StatsContext
*) inContext
;
906 char key
[NI_MAXHOST
+ 6];
907 const char* hostname
= LMCD_SERVER_HOSTNAME(server
);
908 in_port_t port
= LMCD_SERVER_PORT(server
);
909 snprintf(key
, sizeof(key
), "%s:%d", hostname
, port
);
910 memcached_stat_st
*stats
= context
->stats
;
911 ssize_t i
= context
->returnValue
.size();
913 context
->returnValue
.set(String(key
, CopyString
),
915 s_pid
, (int64_t)stats
[i
].pid
,
916 s_uptime
, (int64_t)stats
[i
].uptime
,
917 s_threads
, (int64_t)stats
[i
].threads
,
918 s_time
, (int64_t)stats
[i
].time
,
919 s_pointer_size
, (int64_t)stats
[i
].pointer_size
,
920 s_rusage_user_seconds
, (int64_t)stats
[i
].rusage_user_seconds
,
921 s_rusage_user_microseconds
, (int64_t)stats
[i
]
922 .rusage_user_microseconds
,
923 s_rusage_system_seconds
, (int64_t)stats
[i
].rusage_system_seconds
,
924 s_rusage_system_microseconds
, (int64_t)stats
[i
]
925 .rusage_system_microseconds
,
926 s_curr_items
, (int64_t)stats
[i
].curr_items
,
927 s_total_items
, (int64_t)stats
[i
].total_items
,
928 s_limit_maxbytes
, (int64_t)stats
[i
].limit_maxbytes
,
929 s_curr_connections
, (int64_t)stats
[i
].curr_connections
,
930 s_total_connections
, (int64_t)stats
[i
].total_connections
,
931 s_connection_structures
, (int64_t)stats
[i
].connection_structures
,
932 s_bytes
, (int64_t)stats
[i
].bytes
,
933 s_cmd_get
, (int64_t)stats
[i
].cmd_get
,
934 s_cmd_set
, (int64_t)stats
[i
].cmd_set
,
935 s_get_hits
, (int64_t)stats
[i
].get_hits
,
936 s_get_misses
, (int64_t)stats
[i
].get_misses
,
937 s_evictions
, (int64_t)stats
[i
].evictions
,
938 s_bytes_read
, (int64_t)stats
[i
].bytes_read
,
939 s_bytes_written
, (int64_t)stats
[i
].bytes_written
,
940 s_version
, String(stats
[i
].version
, CopyString
)
944 return MEMCACHED_SUCCESS
;
948 Variant
HHVM_METHOD(Memcached
, getstats
) {
949 auto data
= Native::data
<MemcachedData
>(this_
);
950 memcached_return_t error
;
951 memcached_stat_st
*stats
= memcached_stat(&data
->m_impl
->memcached
,
954 data
->handleError(error
);
958 memcached_server_function callbacks
[] = { doStatsCallback
};
959 StatsContext context
; context
.stats
= stats
;
960 memcached_server_cursor(&data
->m_impl
->memcached
, callbacks
, &context
, 1);
962 memcached_stat_free(&data
->m_impl
->memcached
, stats
);
963 return context
.returnValue
;
967 memcached_return_t
doVersionCallback(const memcached_st
*ptr
,
968 LMCD_SERVER_CALLBACK_INSTANCE_TYPE server
, void *context
) {
969 Array
*returnValue
= (Array
*) context
;
970 char key
[NI_MAXHOST
+ 6], version
[16];
972 const char* hostname
= LMCD_SERVER_HOSTNAME(server
);
973 in_port_t port
= LMCD_SERVER_PORT(server
);
974 uint8_t majorVersion
= LMCD_SERVER_MAJOR_VERSION(server
);
975 uint8_t minorVersion
= LMCD_SERVER_MINOR_VERSION(server
);
976 uint8_t microVersion
= LMCD_SERVER_MICRO_VERSION(server
);
978 // libmemcached starting with 0.46 use UINT8_MAX as the default version, not 0
979 #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX <= 0x00045000
980 if (majorVersion
== 0 && minorVersion
== 0 && microVersion
== 0) {
981 majorVersion
= UINT8_MAX
;
982 minorVersion
= UINT8_MAX
;
983 microVersion
= UINT8_MAX
;
987 snprintf(key
, sizeof(key
), "%s:%d", hostname
, port
);
988 snprintf(version
, sizeof(version
), "%" PRIu8
".%" PRIu8
".%" PRIu8
,
989 majorVersion
, minorVersion
, microVersion
);
990 returnValue
->set(String(key
, CopyString
), String(version
, CopyString
));
991 return MEMCACHED_SUCCESS
;
995 Variant
HHVM_METHOD(Memcached
, getversion
) {
996 auto data
= Native::data
<MemcachedData
>(this_
);
997 memcached_version(&data
->m_impl
->memcached
);
999 Array returnValue
= Array::Create();
1000 memcached_server_function callbacks
[] = { doVersionCallback
};
1001 memcached_server_cursor(&data
->m_impl
->memcached
, callbacks
, &returnValue
, 1);
1005 bool HHVM_METHOD(Memcached
, flush
, int delay
/*= 0*/) {
1006 auto data
= Native::data
<MemcachedData
>(this_
);
1007 return data
->handleError(memcached_flush(&data
->m_impl
->memcached
, delay
));
1010 Variant
HHVM_METHOD(Memcached
, getoption
, int option
) {
1011 auto data
= Native::data
<MemcachedData
>(this_
);
1013 case q_Memcached$$OPT_COMPRESSION
:
1014 return data
->m_impl
->compression
;
1016 case q_Memcached$$OPT_PREFIX_KEY
:
1018 memcached_return retval
;
1019 char *result
= (char*) memcached_callback_get(&data
->m_impl
->memcached
,
1020 MEMCACHED_CALLBACK_PREFIX_KEY
, &retval
);
1021 if (retval
== MEMCACHED_SUCCESS
&& result
) {
1022 return String(result
, CopyString
);
1024 else return empty_string_variant();
1027 case q_Memcached$$OPT_SERIALIZER
:
1028 return data
->m_impl
->serializer
;
1030 case MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE
:
1031 case MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE
:
1032 if (memcached_server_count(&data
->m_impl
->memcached
) == 0) {
1033 raise_warning("no servers defined");
1039 // Assume that it's a libmemcached behavior option
1040 return (int64_t) memcached_behavior_get(&data
->m_impl
->memcached
,
1041 (memcached_behavior_t
)option
);
1045 bool HHVM_METHOD(Memcached
, setoption
, int option
, const Variant
& value
) {
1046 auto data
= Native::data
<MemcachedData
>(this_
);
1048 case q_Memcached$$OPT_COMPRESSION
:
1049 data
->m_impl
->compression
= value
.toBoolean();
1052 case q_Memcached$$OPT_PREFIX_KEY
:
1054 String sValue
= value
.toString();
1055 char *key
= const_cast<char*>(sValue
.empty() ? nullptr : sValue
.c_str());
1056 if (memcached_callback_set(&data
->m_impl
->memcached
,
1057 MEMCACHED_CALLBACK_PREFIX_KEY
, key
) == MEMCACHED_BAD_KEY_PROVIDED
) {
1058 raise_warning("bad key provided");
1064 case MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED
:
1066 uint64_t lValue
= value
.toInt64();
1067 if (memcached_behavior_set(&data
->m_impl
->memcached
,
1068 MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED
, lValue
) == MEMCACHED_FAILURE
) {
1069 raise_warning("error setting memcached option");
1073 /* This is necessary because libmemcached doesn't reset hash/distribution
1074 * options on false case, like it does for MEMCACHED_BEHAVIOR_KETAMA
1075 * (non-weighted) case. We have to clean up ourselves.
1078 memcached_behavior_set_key_hash(&data
->m_impl
->memcached
,
1079 MEMCACHED_HASH_DEFAULT
);
1080 memcached_behavior_set_distribution_hash(&data
->m_impl
->memcached
,
1081 MEMCACHED_HASH_DEFAULT
);
1082 memcached_behavior_set_distribution(&data
->m_impl
->memcached
,
1083 MEMCACHED_DISTRIBUTION_MODULA
);
1088 case q_Memcached$$OPT_SERIALIZER
:
1090 int iValue
= value
.toInt32(10);
1092 case q_Memcached$$SERIALIZER_PHP
:
1093 case q_Memcached$$SERIALIZER_JSON
:
1094 data
->m_impl
->serializer
= iValue
;
1097 data
->m_impl
->serializer
= q_Memcached$$SERIALIZER_PHP
;
1098 raise_warning("invalid serializer provided");
1106 if ((option
< 0) || (option
>= MEMCACHED_BEHAVIOR_MAX
)) {
1107 raise_warning("error setting memcached option");
1111 // Assume that it's a libmemcached behavior option
1112 uint64_t lValue
= value
.toInt64();
1113 if (memcached_behavior_set(&data
->m_impl
->memcached
,
1114 (memcached_behavior_t
)option
, lValue
) == MEMCACHED_FAILURE
) {
1115 raise_warning("error setting memcached option");
1124 int64_t HHVM_METHOD(Memcached
, getresultcode
) {
1125 auto data
= Native::data
<MemcachedData
>(this_
);
1126 return data
->m_impl
->rescode
;
1129 String
HHVM_METHOD(Memcached
, getresultmessage
) {
1130 auto data
= Native::data
<MemcachedData
>(this_
);
1131 if (data
->m_impl
->rescode
== q_Memcached$$RES_PAYLOAD_FAILURE
) {
1132 return "PAYLOAD FAILURE";
1134 return memcached_strerror(&data
->m_impl
->memcached
,
1135 (memcached_return_t
)data
->m_impl
->rescode
);
1139 bool HHVM_METHOD(Memcached
, ispersistent
) {
1140 auto data
= Native::data
<MemcachedData
>(this_
);
1141 return data
->m_impl
->is_persistent
;
1144 bool HHVM_METHOD(Memcached
, ispristine
) {
1145 auto data
= Native::data
<MemcachedData
>(this_
);
1146 return data
->m_impl
->is_pristine
;
1149 bool HHVM_METHOD(Memcached
, touchbykey
,
1150 ATTRIBUTE_UNUSED
const String
& server_key
,
1151 ATTRIBUTE_UNUSED
const String
& key
,
1152 ATTRIBUTE_UNUSED
int expiration
/*= 0*/) {
1154 #ifndef HAVE_MEMCACHED_TOUCH
1155 throw_not_supported(__func__
, "Not Implemented in libmemcached versions below"
1159 auto data
= Native::data
<MemcachedData
>(this_
);
1160 data
->m_impl
->rescode
= MEMCACHED_SUCCESS
;
1162 data
->m_impl
->rescode
= MEMCACHED_BAD_KEY_PROVIDED
;
1166 #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000016
1167 if (memcached_behavior_get(&data
->m_impl
->memcached
,
1168 MEMCACHED_BEHAVIOR_BINARY_PROTOCOL
)) {
1169 raise_warning("using touch command with binary protocol is not "
1170 "recommended with libmemcached versions below 1.0.16");
1174 memcached_return_t status
;
1175 const String
& myServerKey
= server_key
.empty() ? key
: server_key
;
1176 status
= memcached_touch_by_key(&data
->m_impl
->memcached
,
1177 myServerKey
.c_str(), myServerKey
.length(),
1178 key
.c_str(), key
.length(), expiration
);
1180 if (!data
->handleError(status
)) return false;
1181 data
->m_impl
->rescode
= MEMCACHED_SUCCESS
;
1186 ///////////////////////////////////////////////////////////////////////////////
1188 IMPLEMENT_THREAD_LOCAL(MemcachedData::ImplMap
, MemcachedData::s_persistentMap
);
1190 const StaticString
s_Memcached("Memcached");
1192 struct MemcachedExtension final
: Extension
{
1193 MemcachedExtension() : Extension("memcached", "2.2.0b1") {}
1194 void threadInit() override
{
1195 if (s_memcached_globals
) {
1198 s_memcached_globals
= new MEMCACHEDGlobals
;
1199 IniSetting::Bind(this, IniSetting::PHP_INI_ALL
,
1200 "memcached.sess_prefix", &MEMCACHEDG(sess_prefix
));
1203 void threadShutdown() override
{
1204 delete s_memcached_globals
;
1205 s_memcached_globals
= nullptr;
1208 void moduleInit() override
{
1209 HHVM_ME(Memcached
, __construct
);
1210 HHVM_ME(Memcached
, quit
);
1211 HHVM_ME(Memcached
, getallkeys
);
1212 HHVM_ME(Memcached
, getbykey
);
1213 HHVM_ME(Memcached
, getmultibykey
);
1214 HHVM_ME(Memcached
, getdelayedbykey
);
1215 HHVM_ME(Memcached
, fetch
);
1216 HHVM_ME(Memcached
, fetchall
);
1217 HHVM_ME(Memcached
, setbykey
);
1218 HHVM_ME(Memcached
, addbykey
);
1219 HHVM_ME(Memcached
, appendbykey
);
1220 HHVM_ME(Memcached
, prependbykey
);
1221 HHVM_ME(Memcached
, replacebykey
);
1222 HHVM_ME(Memcached
, casbykey
);
1223 HHVM_ME(Memcached
, deletebykey
);
1224 HHVM_ME(Memcached
, deletemultibykey
);
1225 HHVM_ME(Memcached
, increment
);
1226 HHVM_ME(Memcached
, incrementbykey
);
1227 HHVM_ME(Memcached
, decrement
);
1228 HHVM_ME(Memcached
, decrementbykey
);
1229 HHVM_ME(Memcached
, addserver
);
1230 HHVM_ME(Memcached
, getserverlist
);
1231 HHVM_ME(Memcached
, resetserverlist
);
1232 HHVM_ME(Memcached
, getserverbykey
);
1233 HHVM_ME(Memcached
, getstats
);
1234 HHVM_ME(Memcached
, getversion
);
1235 HHVM_ME(Memcached
, flush
);
1236 HHVM_ME(Memcached
, getoption
);
1237 HHVM_ME(Memcached
, setoption
);
1238 HHVM_ME(Memcached
, getresultcode
);
1239 HHVM_ME(Memcached
, getresultmessage
);
1240 HHVM_ME(Memcached
, ispersistent
);
1241 HHVM_ME(Memcached
, ispristine
);
1242 HHVM_ME(Memcached
, touchbykey
);
1244 Native::registerNativeDataInfo
<MemcachedData
>(s_MemcachedData
.get());
1246 HHVM_RCC_BOOL(Memcached
, HAVE_IGBINARY
, false);
1247 HHVM_RCC_BOOL(Memcached
, HAVE_JSON
, true);
1249 HHVM_RCC_INT(Memcached
, DISTRIBUTION_CONSISTENT
,
1250 MEMCACHED_DISTRIBUTION_CONSISTENT
);
1251 HHVM_RCC_INT(Memcached
, DISTRIBUTION_CONSISTENT_KETAMA
,
1252 MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA
);
1253 #ifdef MEMCACHED_DISTRIBUTION_CONSISTENT_WEIGHTED
1254 HHVM_RCC_INT(Memcached
, DISTRIBUTION_CONSISTENT_WEIGHTED
,
1255 MEMCACHED_DISTRIBUTION_CONSISTENT_WEIGHTED
);
1257 HHVM_RCC_INT(Memcached
, DISTRIBUTION_MODULA
, MEMCACHED_DISTRIBUTION_MODULA
);
1258 HHVM_RCC_INT(Memcached
, GET_PRESERVE_ORDER
,
1259 q_Memcached$$GET_PRESERVE_ORDER
);
1260 HHVM_RCC_INT(Memcached
, HASH_CRC
, MEMCACHED_HASH_CRC
);
1261 HHVM_RCC_INT(Memcached
, HASH_DEFAULT
, MEMCACHED_HASH_DEFAULT
);
1262 HHVM_RCC_INT(Memcached
, HASH_FNV1_32
, MEMCACHED_HASH_FNV1_32
);
1263 HHVM_RCC_INT(Memcached
, HASH_FNV1_64
, MEMCACHED_HASH_FNV1_64
);
1264 HHVM_RCC_INT(Memcached
, HASH_FNV1A_32
, MEMCACHED_HASH_FNV1A_32
);
1265 HHVM_RCC_INT(Memcached
, HASH_FNV1A_64
, MEMCACHED_HASH_FNV1A_64
);
1266 HHVM_RCC_INT(Memcached
, HASH_HSIEH
, MEMCACHED_HASH_HSIEH
);
1267 HHVM_RCC_INT(Memcached
, HASH_MD5
, MEMCACHED_HASH_MD5
);
1268 HHVM_RCC_INT(Memcached
, HASH_MURMUR
, MEMCACHED_HASH_MURMUR
);
1269 HHVM_RCC_INT(Memcached
, OPT_BINARY_PROTOCOL
,
1270 MEMCACHED_BEHAVIOR_BINARY_PROTOCOL
);
1271 HHVM_RCC_INT(Memcached
, OPT_BUFFER_WRITES
,
1272 MEMCACHED_BEHAVIOR_BUFFER_REQUESTS
);
1273 HHVM_RCC_INT(Memcached
, OPT_CACHE_LOOKUPS
,
1274 MEMCACHED_BEHAVIOR_CACHE_LOOKUPS
);
1275 HHVM_RCC_INT(Memcached
, OPT_COMPRESSION
, q_Memcached$$OPT_COMPRESSION
);
1276 HHVM_RCC_INT(Memcached
, OPT_CONNECT_TIMEOUT
,
1277 MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT
);
1278 HHVM_RCC_INT(Memcached
, OPT_DISTRIBUTION
, MEMCACHED_BEHAVIOR_DISTRIBUTION
);
1279 HHVM_RCC_INT(Memcached
, OPT_HASH
, MEMCACHED_BEHAVIOR_HASH
);
1280 HHVM_RCC_INT(Memcached
, OPT_LIBKETAMA_COMPATIBLE
,
1281 MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED
);
1282 HHVM_RCC_INT(Memcached
, OPT_LIBKETAMA_HASH
, MEMCACHED_BEHAVIOR_KETAMA_HASH
);
1283 HHVM_RCC_INT(Memcached
, OPT_NO_BLOCK
, MEMCACHED_BEHAVIOR_NO_BLOCK
);
1284 HHVM_RCC_INT(Memcached
, OPT_POLL_TIMEOUT
, MEMCACHED_BEHAVIOR_POLL_TIMEOUT
);
1285 HHVM_RCC_INT(Memcached
, OPT_PREFIX_KEY
, q_Memcached$$OPT_PREFIX_KEY
);
1286 HHVM_RCC_INT(Memcached
, OPT_HASH_WITH_PREFIX_KEY
,
1287 MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY
);
1288 HHVM_RCC_INT(Memcached
, OPT_RECV_TIMEOUT
, MEMCACHED_BEHAVIOR_RCV_TIMEOUT
);
1289 HHVM_RCC_INT(Memcached
, OPT_RETRY_TIMEOUT
,
1290 MEMCACHED_BEHAVIOR_RETRY_TIMEOUT
);
1291 HHVM_RCC_INT(Memcached
, OPT_SEND_TIMEOUT
, MEMCACHED_BEHAVIOR_SND_TIMEOUT
);
1292 HHVM_RCC_INT(Memcached
, OPT_SERIALIZER
, q_Memcached$$OPT_SERIALIZER
);
1293 HHVM_RCC_INT(Memcached
, OPT_SERVER_FAILURE_LIMIT
,
1294 MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT
);
1295 HHVM_RCC_INT(Memcached
, OPT_SOCKET_RECV_SIZE
,
1296 MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE
);
1297 HHVM_RCC_INT(Memcached
, OPT_SOCKET_SEND_SIZE
,
1298 MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE
);
1299 HHVM_RCC_INT(Memcached
, OPT_TCP_NODELAY
, MEMCACHED_BEHAVIOR_TCP_NODELAY
);
1300 HHVM_RCC_INT(Memcached
, RES_BAD_KEY_PROVIDED
, MEMCACHED_BAD_KEY_PROVIDED
);
1301 HHVM_RCC_INT(Memcached
, RES_BUFFERED
, MEMCACHED_BUFFERED
);
1302 HHVM_RCC_INT(Memcached
, RES_CLIENT_ERROR
, MEMCACHED_CLIENT_ERROR
);
1303 HHVM_RCC_INT(Memcached
, RES_CONNECTION_SOCKET_CREATE_FAILURE
,
1304 MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE
);
1305 HHVM_RCC_INT(Memcached
, RES_DATA_EXISTS
, MEMCACHED_DATA_EXISTS
);
1306 HHVM_RCC_INT(Memcached
, RES_END
, MEMCACHED_END
);
1307 HHVM_RCC_INT(Memcached
, RES_ERRNO
, MEMCACHED_ERRNO
);
1308 HHVM_RCC_INT(Memcached
, RES_FAILURE
, MEMCACHED_FAILURE
);
1309 HHVM_RCC_INT(Memcached
, RES_HOST_LOOKUP_FAILURE
,
1310 MEMCACHED_HOST_LOOKUP_FAILURE
);
1311 HHVM_RCC_INT(Memcached
, RES_INVALID_HOST_PROTOCOL
,
1312 MEMCACHED_INVALID_HOST_PROTOCOL
);
1313 HHVM_RCC_INT(Memcached
, RES_NO_SERVERS
, MEMCACHED_NO_SERVERS
);
1314 HHVM_RCC_INT(Memcached
, RES_NOT_SUPPORTED
, MEMCACHED_NOT_SUPPORTED
);
1315 HHVM_RCC_INT(Memcached
, RES_NOTFOUND
, MEMCACHED_NOTFOUND
);
1316 HHVM_RCC_INT(Memcached
, RES_NOTSTORED
, MEMCACHED_NOTSTORED
);
1317 HHVM_RCC_INT(Memcached
, RES_PARTIAL_READ
, MEMCACHED_PARTIAL_READ
);
1318 HHVM_RCC_INT(Memcached
, RES_PAYLOAD_FAILURE
,
1319 q_Memcached$$RES_PAYLOAD_FAILURE
);
1320 HHVM_RCC_INT(Memcached
, RES_PROTOCOL_ERROR
, MEMCACHED_PROTOCOL_ERROR
);
1321 HHVM_RCC_INT(Memcached
, RES_SERVER_ERROR
, MEMCACHED_SERVER_ERROR
);
1322 HHVM_RCC_INT(Memcached
, RES_SOME_ERRORS
, MEMCACHED_SOME_ERRORS
);
1323 HHVM_RCC_INT(Memcached
, RES_SUCCESS
, MEMCACHED_SUCCESS
);
1324 HHVM_RCC_INT(Memcached
, RES_TIMEOUT
, MEMCACHED_TIMEOUT
);
1325 HHVM_RCC_INT(Memcached
, RES_UNKNOWN_READ_FAILURE
,
1326 MEMCACHED_UNKNOWN_READ_FAILURE
);
1327 HHVM_RCC_INT(Memcached
, RES_WRITE_FAILURE
, MEMCACHED_WRITE_FAILURE
);
1328 HHVM_RCC_INT(Memcached
, SERIALIZER_IGBINARY
,
1329 q_Memcached$$SERIALIZER_IGBINARY
);
1330 HHVM_RCC_INT(Memcached
, SERIALIZER_JSON
, q_Memcached$$SERIALIZER_JSON
);
1331 HHVM_RCC_INT(Memcached
, SERIALIZER_PHP
, q_Memcached$$SERIALIZER_PHP
);
1332 HHVM_RCC_INT(Memcached
, OPT_VERIFY_KEY
, MEMCACHED_BEHAVIOR_VERIFY_KEY
);
1333 HHVM_RCC_INT(Memcached
, OPT_SORT_HOSTS
, MEMCACHED_BEHAVIOR_SORT_HOSTS
);
1334 HHVM_RCC_INT(Memcached
, RES_SERVER_MARKED_DEAD
,
1335 MEMCACHED_SERVER_MARKED_DEAD
);
1336 #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00049000
1337 HHVM_RCC_INT(Memcached
, OPT_REMOVE_FAILED_SERVERS
,
1338 MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS
);
1340 #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000003
1341 HHVM_RCC_INT(Memcached
, OPT_DEAD_TIMEOUT
, MEMCACHED_BEHAVIOR_DEAD_TIMEOUT
);
1343 HHVM_RCC_INT(Memcached
, RES_SERVER_TEMPORARILY_DISABLED
,
1344 MEMCACHED_SERVER_TEMPORARILY_DISABLED
);
1345 HHVM_RCC_INT(Memcached
, LIBMEMCACHED_VERSION_HEX
, LIBMEMCACHED_VERSION_HEX
);
1346 HHVM_RCC_BOOL(Memcached
, GET_ERROR_RETURN_VALUE
, false);
1351 } s_memcached_extension
;