1 Star 1 Fork 0

蒋建勇 / phpredis

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
redis.c 108.72 KB
一键复制 编辑 原始数据 按行查看 历史
michael-grunder 提交于 2017-08-21 11:06 . arginfo for updated exists
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562
/* -*- Mode: C; tab-width: 4 -*- */
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2009 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Original author: Alfonso Jimenez <yo@alfonsojimenez.com> |
| Maintainer: Nicolas Favre-Felix <n.favre-felix@owlient.eu> |
| Maintainer: Nasreddine Bouafif <n.bouafif@owlient.eu> |
| Maintainer: Michael Grunder <michael.grunder@gmail.com> |
+----------------------------------------------------------------------+
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "common.h"
#include "ext/standard/info.h"
#include "php_redis.h"
#include "redis_commands.h"
#include "redis_array.h"
#include "redis_cluster.h"
#include <zend_exceptions.h>
#ifdef PHP_SESSION
#include "ext/session/php_session.h"
#endif
#include "library.h"
#ifdef PHP_SESSION
extern ps_module ps_mod_redis;
extern ps_module ps_mod_redis_cluster;
#endif
extern zend_class_entry *redis_array_ce;
extern zend_class_entry *redis_cluster_ce;
extern zend_class_entry *redis_cluster_exception_ce;
zend_class_entry *redis_ce;
zend_class_entry *redis_exception_ce;
extern zend_function_entry redis_array_functions[];
extern zend_function_entry redis_cluster_functions[];
PHP_INI_BEGIN()
/* redis arrays */
PHP_INI_ENTRY("redis.arrays.autorehash", "", PHP_INI_ALL, NULL)
PHP_INI_ENTRY("redis.arrays.connecttimeout", "", PHP_INI_ALL, NULL)
PHP_INI_ENTRY("redis.arrays.distributor", "", PHP_INI_ALL, NULL)
PHP_INI_ENTRY("redis.arrays.functions", "", PHP_INI_ALL, NULL)
PHP_INI_ENTRY("redis.arrays.hosts", "", PHP_INI_ALL, NULL)
PHP_INI_ENTRY("redis.arrays.index", "", PHP_INI_ALL, NULL)
PHP_INI_ENTRY("redis.arrays.lazyconnect", "", PHP_INI_ALL, NULL)
PHP_INI_ENTRY("redis.arrays.names", "", PHP_INI_ALL, NULL)
PHP_INI_ENTRY("redis.arrays.pconnect", "", PHP_INI_ALL, NULL)
PHP_INI_ENTRY("redis.arrays.previous", "", PHP_INI_ALL, NULL)
PHP_INI_ENTRY("redis.arrays.readtimeout", "", PHP_INI_ALL, NULL)
PHP_INI_ENTRY("redis.arrays.retryinterval", "", PHP_INI_ALL, NULL)
/* redis cluster */
PHP_INI_ENTRY("redis.clusters.persistent", "", PHP_INI_ALL, NULL)
PHP_INI_ENTRY("redis.clusters.read_timeout", "", PHP_INI_ALL, NULL)
PHP_INI_ENTRY("redis.clusters.seeds", "", PHP_INI_ALL, NULL)
PHP_INI_ENTRY("redis.clusters.timeout", "", PHP_INI_ALL, NULL)
PHP_INI_END()
/** {{{ Argument info for commands in redis 1.0 */
ZEND_BEGIN_ARG_INFO_EX(arginfo_connect, 0, 0, 2)
ZEND_ARG_INFO(0, host)
ZEND_ARG_INFO(0, port)
ZEND_ARG_INFO(0, timeout)
ZEND_ARG_INFO(0, retry_interval)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_info, 0, 0, 0)
ZEND_ARG_INFO(0, option)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_client, 0, 0, 1)
ZEND_ARG_INFO(0, cmd)
#if PHP_VERSION_ID >= 50600
ZEND_ARG_VARIADIC_INFO(0, args)
#else
ZEND_ARG_INFO(0, ...)
#endif
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_config, 0, 0, 2)
ZEND_ARG_INFO(0, cmd)
ZEND_ARG_INFO(0, key)
ZEND_ARG_INFO(0, value)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_pubsub, 0, 0, 1)
ZEND_ARG_INFO(0, cmd)
#if PHP_VERSION_ID >= 50600
ZEND_ARG_VARIADIC_INFO(0, args)
#else
ZEND_ARG_INFO(0, ...)
#endif
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_slowlog, 0, 0, 1)
ZEND_ARG_INFO(0, arg)
ZEND_ARG_INFO(0, option)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_pconnect, 0, 0, 2)
ZEND_ARG_INFO(0, host)
ZEND_ARG_INFO(0, port)
ZEND_ARG_INFO(0, timeout)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_mget, 0, 0, 1)
ZEND_ARG_ARRAY_INFO(0, keys, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_exists, 0, 0, 1)
ZEND_ARG_INFO(0, key)
#if PHP_VERSION_ID >= 50600
ZEND_ARG_VARIADIC_INFO(0, other_keys)
#else
ZEND_ARG_INFO(0, ...)
#endif
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_del, 0, 0, 1)
ZEND_ARG_INFO(0, key)
#if PHP_VERSION_ID >= 50600
ZEND_ARG_VARIADIC_INFO(0, other_keys)
#else
ZEND_ARG_INFO(0, ...)
#endif
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_keys, 0, 0, 1)
ZEND_ARG_INFO(0, pattern)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_generic_sort, 0, 0, 1)
ZEND_ARG_INFO(0, key)
ZEND_ARG_INFO(0, pattern)
ZEND_ARG_INFO(0, get)
ZEND_ARG_INFO(0, start)
ZEND_ARG_INFO(0, end)
ZEND_ARG_INFO(0, getList)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_lrem, 0, 0, 3)
ZEND_ARG_INFO(0, key)
ZEND_ARG_INFO(0, value)
ZEND_ARG_INFO(0, count)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_auth, 0, 0, 1)
ZEND_ARG_INFO(0, password)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_select, 0, 0, 1)
ZEND_ARG_INFO(0, dbindex)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_move, 0, 0, 2)
ZEND_ARG_INFO(0, key)
ZEND_ARG_INFO(0, dbindex)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_slaveof, 0, 0, 0)
ZEND_ARG_INFO(0, host)
ZEND_ARG_INFO(0, port)
ZEND_END_ARG_INFO()
/* }}} */
ZEND_BEGIN_ARG_INFO_EX(arginfo_migrate, 0, 0, 5)
ZEND_ARG_INFO(0, host)
ZEND_ARG_INFO(0, port)
ZEND_ARG_INFO(0, key)
ZEND_ARG_INFO(0, db)
ZEND_ARG_INFO(0, timeout)
ZEND_ARG_INFO(0, copy)
ZEND_ARG_INFO(0, replace)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_wait, 0, 0, 2)
ZEND_ARG_INFO(0, numslaves)
ZEND_ARG_INFO(0, timeout)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_script, 0, 0, 1)
ZEND_ARG_INFO(0, cmd)
#if PHP_VERSION_ID >= 50600
ZEND_ARG_VARIADIC_INFO(0, args)
#else
ZEND_ARG_INFO(0, ...)
#endif
ZEND_END_ARG_INFO()
/**
* Argument info for the SCAN proper
*/
ZEND_BEGIN_ARG_INFO_EX(arginfo_scan, 0, 0, 1)
ZEND_ARG_INFO(1, i_iterator)
ZEND_ARG_INFO(0, str_pattern)
ZEND_ARG_INFO(0, i_count)
ZEND_END_ARG_INFO()
/**
* Argument info for key scanning
*/
ZEND_BEGIN_ARG_INFO_EX(arginfo_kscan, 0, 0, 2)
ZEND_ARG_INFO(0, str_key)
ZEND_ARG_INFO(1, i_iterator)
ZEND_ARG_INFO(0, str_pattern)
ZEND_ARG_INFO(0, i_count)
ZEND_END_ARG_INFO()
#ifdef ZTS
ZEND_DECLARE_MODULE_GLOBALS(redis)
#endif
static zend_function_entry redis_functions[] = {
PHP_ME(Redis, __construct, arginfo_void, ZEND_ACC_CTOR | ZEND_ACC_PUBLIC)
PHP_ME(Redis, __destruct, arginfo_void, ZEND_ACC_DTOR | ZEND_ACC_PUBLIC)
PHP_ME(Redis, _prefix, arginfo_key, ZEND_ACC_PUBLIC)
PHP_ME(Redis, _serialize, arginfo_value, ZEND_ACC_PUBLIC)
PHP_ME(Redis, _unserialize, arginfo_value, ZEND_ACC_PUBLIC)
PHP_ME(Redis, append, arginfo_key_value, ZEND_ACC_PUBLIC)
PHP_ME(Redis, auth, arginfo_auth, ZEND_ACC_PUBLIC)
PHP_ME(Redis, bgSave, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(Redis, bgrewriteaof, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(Redis, bitcount, arginfo_key, ZEND_ACC_PUBLIC)
PHP_ME(Redis, bitop, arginfo_bitop, ZEND_ACC_PUBLIC)
PHP_ME(Redis, bitpos, arginfo_bitpos, ZEND_ACC_PUBLIC)
PHP_ME(Redis, blPop, arginfo_blrpop, ZEND_ACC_PUBLIC)
PHP_ME(Redis, brPop, arginfo_blrpop, ZEND_ACC_PUBLIC)
PHP_ME(Redis, brpoplpush, arginfo_brpoplpush, ZEND_ACC_PUBLIC)
PHP_ME(Redis, clearLastError, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(Redis, client, arginfo_client, ZEND_ACC_PUBLIC)
PHP_ME(Redis, close, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(Redis, command, arginfo_command, ZEND_ACC_PUBLIC)
PHP_ME(Redis, config, arginfo_config, ZEND_ACC_PUBLIC)
PHP_ME(Redis, connect, arginfo_connect, ZEND_ACC_PUBLIC)
PHP_ME(Redis, dbSize, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(Redis, debug, arginfo_key, ZEND_ACC_PUBLIC)
PHP_ME(Redis, decr, arginfo_key, ZEND_ACC_PUBLIC)
PHP_ME(Redis, decrBy, arginfo_key_value, ZEND_ACC_PUBLIC)
PHP_ME(Redis, delete, arginfo_del, ZEND_ACC_PUBLIC)
PHP_ME(Redis, discard, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(Redis, dump, arginfo_key, ZEND_ACC_PUBLIC)
PHP_ME(Redis, echo, arginfo_echo, ZEND_ACC_PUBLIC)
PHP_ME(Redis, eval, arginfo_eval, ZEND_ACC_PUBLIC)
PHP_ME(Redis, evalsha, arginfo_evalsha, ZEND_ACC_PUBLIC)
PHP_ME(Redis, exec, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(Redis, exists, arginfo_exists, ZEND_ACC_PUBLIC)
PHP_ME(Redis, expireAt, arginfo_key_timestamp, ZEND_ACC_PUBLIC)
PHP_ME(Redis, flushAll, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(Redis, flushDB, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(Redis, geoadd, arginfo_geoadd, ZEND_ACC_PUBLIC)
PHP_ME(Redis, geodist, arginfo_geodist, ZEND_ACC_PUBLIC)
PHP_ME(Redis, geohash, arginfo_key_members, ZEND_ACC_PUBLIC)
PHP_ME(Redis, geopos, arginfo_key_members, ZEND_ACC_PUBLIC)
PHP_ME(Redis, georadius, arginfo_georadius, ZEND_ACC_PUBLIC)
PHP_ME(Redis, georadiusbymember, arginfo_georadiusbymember, ZEND_ACC_PUBLIC)
PHP_ME(Redis, get, arginfo_key, ZEND_ACC_PUBLIC)
PHP_ME(Redis, getAuth, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(Redis, getBit, arginfo_key_offset, ZEND_ACC_PUBLIC)
PHP_ME(Redis, getDBNum, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(Redis, getHost, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(Redis, getKeys, arginfo_keys, ZEND_ACC_PUBLIC)
PHP_ME(Redis, getLastError, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(Redis, getMode, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(Redis, getMultiple, arginfo_mget, ZEND_ACC_PUBLIC)
PHP_ME(Redis, getOption, arginfo_getoption, ZEND_ACC_PUBLIC)
PHP_ME(Redis, getPersistentID, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(Redis, getPort, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(Redis, getRange, arginfo_key_start_end, ZEND_ACC_PUBLIC)
PHP_ME(Redis, getReadTimeout, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(Redis, getSet, arginfo_key_value, ZEND_ACC_PUBLIC)
PHP_ME(Redis, getTimeout, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(Redis, hDel, arginfo_key_members, ZEND_ACC_PUBLIC)
PHP_ME(Redis, hExists, arginfo_key_member, ZEND_ACC_PUBLIC)
PHP_ME(Redis, hGet, arginfo_key_member, ZEND_ACC_PUBLIC)
PHP_ME(Redis, hGetAll, arginfo_key, ZEND_ACC_PUBLIC)
PHP_ME(Redis, hIncrBy, arginfo_key_member_value, ZEND_ACC_PUBLIC)
PHP_ME(Redis, hIncrByFloat, arginfo_key_member_value, ZEND_ACC_PUBLIC)
PHP_ME(Redis, hKeys, arginfo_key, ZEND_ACC_PUBLIC)
PHP_ME(Redis, hLen, arginfo_key, ZEND_ACC_PUBLIC)
PHP_ME(Redis, hMget, arginfo_hmget, ZEND_ACC_PUBLIC)
PHP_ME(Redis, hMset, arginfo_hmset, ZEND_ACC_PUBLIC)
PHP_ME(Redis, hSet, arginfo_key_member_value, ZEND_ACC_PUBLIC)
PHP_ME(Redis, hSetNx, arginfo_key_member_value, ZEND_ACC_PUBLIC)
PHP_ME(Redis, hStrLen, arginfo_key_member, ZEND_ACC_PUBLIC)
PHP_ME(Redis, hVals, arginfo_key, ZEND_ACC_PUBLIC)
PHP_ME(Redis, hscan, arginfo_kscan, ZEND_ACC_PUBLIC)
PHP_ME(Redis, incr, arginfo_key, ZEND_ACC_PUBLIC)
PHP_ME(Redis, incrBy, arginfo_key_value, ZEND_ACC_PUBLIC)
PHP_ME(Redis, incrByFloat, arginfo_key_value, ZEND_ACC_PUBLIC)
PHP_ME(Redis, info, arginfo_info, ZEND_ACC_PUBLIC)
PHP_ME(Redis, isConnected, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(Redis, lGet, arginfo_lindex, ZEND_ACC_PUBLIC)
PHP_ME(Redis, lGetRange, arginfo_key_start_end, ZEND_ACC_PUBLIC)
PHP_ME(Redis, lInsert, arginfo_linsert, ZEND_ACC_PUBLIC)
PHP_ME(Redis, lPop, arginfo_key, ZEND_ACC_PUBLIC)
PHP_ME(Redis, lPush, arginfo_key_value, ZEND_ACC_PUBLIC)
PHP_ME(Redis, lPushx, arginfo_key_value, ZEND_ACC_PUBLIC)
PHP_ME(Redis, lRemove, arginfo_lrem, ZEND_ACC_PUBLIC)
PHP_ME(Redis, lSet, arginfo_lset, ZEND_ACC_PUBLIC)
PHP_ME(Redis, lSize, arginfo_key, ZEND_ACC_PUBLIC)
PHP_ME(Redis, lastSave, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(Redis, listTrim, arginfo_ltrim, ZEND_ACC_PUBLIC)
PHP_ME(Redis, migrate, arginfo_migrate, ZEND_ACC_PUBLIC)
PHP_ME(Redis, move, arginfo_move, ZEND_ACC_PUBLIC)
PHP_ME(Redis, mset, arginfo_pairs, ZEND_ACC_PUBLIC)
PHP_ME(Redis, msetnx, arginfo_pairs, ZEND_ACC_PUBLIC)
PHP_ME(Redis, multi, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(Redis, object, arginfo_object, ZEND_ACC_PUBLIC)
PHP_ME(Redis, pconnect, arginfo_pconnect, ZEND_ACC_PUBLIC)
PHP_ME(Redis, persist, arginfo_key, ZEND_ACC_PUBLIC)
PHP_ME(Redis, pexpire, arginfo_key_timestamp, ZEND_ACC_PUBLIC)
PHP_ME(Redis, pexpireAt, arginfo_key_timestamp, ZEND_ACC_PUBLIC)
PHP_ME(Redis, pfadd, arginfo_pfadd, ZEND_ACC_PUBLIC)
PHP_ME(Redis, pfcount, arginfo_key, ZEND_ACC_PUBLIC)
PHP_ME(Redis, pfmerge, arginfo_pfmerge, ZEND_ACC_PUBLIC)
PHP_ME(Redis, ping, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(Redis, pipeline, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(Redis, psetex, arginfo_key_expire_value, ZEND_ACC_PUBLIC)
PHP_ME(Redis, psubscribe, arginfo_psubscribe, ZEND_ACC_PUBLIC)
PHP_ME(Redis, pttl, arginfo_key, ZEND_ACC_PUBLIC)
PHP_ME(Redis, publish, arginfo_publish, ZEND_ACC_PUBLIC)
PHP_ME(Redis, pubsub, arginfo_pubsub, ZEND_ACC_PUBLIC)
PHP_ME(Redis, punsubscribe, arginfo_punsubscribe, ZEND_ACC_PUBLIC)
PHP_ME(Redis, rPop, arginfo_key, ZEND_ACC_PUBLIC)
PHP_ME(Redis, rPush, arginfo_key_value, ZEND_ACC_PUBLIC)
PHP_ME(Redis, rPushx, arginfo_key_value, ZEND_ACC_PUBLIC)
PHP_ME(Redis, randomKey, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(Redis, rawcommand, arginfo_rawcommand, ZEND_ACC_PUBLIC)
PHP_ME(Redis, renameKey, arginfo_key_newkey, ZEND_ACC_PUBLIC)
PHP_ME(Redis, renameNx, arginfo_key_newkey, ZEND_ACC_PUBLIC)
PHP_ME(Redis, restore, arginfo_restore, ZEND_ACC_PUBLIC)
PHP_ME(Redis, role, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(Redis, rpoplpush, arginfo_rpoplpush, ZEND_ACC_PUBLIC)
PHP_ME(Redis, sAdd, arginfo_key_value, ZEND_ACC_PUBLIC)
PHP_ME(Redis, sAddArray, arginfo_sadd_array, ZEND_ACC_PUBLIC)
PHP_ME(Redis, sContains, arginfo_key_value, ZEND_ACC_PUBLIC)
PHP_ME(Redis, sDiff, arginfo_nkeys, ZEND_ACC_PUBLIC)
PHP_ME(Redis, sDiffStore, arginfo_dst_nkeys, ZEND_ACC_PUBLIC)
PHP_ME(Redis, sInter, arginfo_nkeys, ZEND_ACC_PUBLIC)
PHP_ME(Redis, sInterStore, arginfo_dst_nkeys, ZEND_ACC_PUBLIC)
PHP_ME(Redis, sMembers, arginfo_key, ZEND_ACC_PUBLIC)
PHP_ME(Redis, sMove, arginfo_smove, ZEND_ACC_PUBLIC)
PHP_ME(Redis, sPop, arginfo_key, ZEND_ACC_PUBLIC)
PHP_ME(Redis, sRandMember, arginfo_srand_member, ZEND_ACC_PUBLIC)
PHP_ME(Redis, sRemove, arginfo_key_value, ZEND_ACC_PUBLIC)
PHP_ME(Redis, sSize, arginfo_key, ZEND_ACC_PUBLIC)
PHP_ME(Redis, sUnion, arginfo_nkeys, ZEND_ACC_PUBLIC)
PHP_ME(Redis, sUnionStore, arginfo_dst_nkeys, ZEND_ACC_PUBLIC)
PHP_ME(Redis, save, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(Redis, scan, arginfo_scan, ZEND_ACC_PUBLIC)
PHP_ME(Redis, script, arginfo_script, ZEND_ACC_PUBLIC)
PHP_ME(Redis, select, arginfo_select, ZEND_ACC_PUBLIC)
PHP_ME(Redis, set, arginfo_set, ZEND_ACC_PUBLIC)
PHP_ME(Redis, setBit, arginfo_key_offset_value, ZEND_ACC_PUBLIC)
PHP_ME(Redis, setOption, arginfo_setoption, ZEND_ACC_PUBLIC)
PHP_ME(Redis, setRange, arginfo_key_offset_value, ZEND_ACC_PUBLIC)
PHP_ME(Redis, setTimeout, arginfo_expire, ZEND_ACC_PUBLIC)
PHP_ME(Redis, setex, arginfo_key_expire_value, ZEND_ACC_PUBLIC)
PHP_ME(Redis, setnx, arginfo_key_value, ZEND_ACC_PUBLIC)
PHP_ME(Redis, slaveof, arginfo_slaveof, ZEND_ACC_PUBLIC)
PHP_ME(Redis, slowlog, arginfo_slowlog, ZEND_ACC_PUBLIC)
PHP_ME(Redis, sort, arginfo_sort, ZEND_ACC_PUBLIC)
PHP_ME(Redis, sortAsc, arginfo_generic_sort, ZEND_ACC_PUBLIC)
PHP_ME(Redis, sortAscAlpha, arginfo_generic_sort, ZEND_ACC_PUBLIC)
PHP_ME(Redis, sortDesc, arginfo_generic_sort, ZEND_ACC_PUBLIC)
PHP_ME(Redis, sortDescAlpha, arginfo_generic_sort, ZEND_ACC_PUBLIC)
PHP_ME(Redis, sscan, arginfo_kscan, ZEND_ACC_PUBLIC)
PHP_ME(Redis, strlen, arginfo_key, ZEND_ACC_PUBLIC)
PHP_ME(Redis, subscribe, arginfo_subscribe, ZEND_ACC_PUBLIC)
PHP_ME(Redis, swapdb, arginfo_swapdb, ZEND_ACC_PUBLIC)
PHP_ME(Redis, time, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(Redis, ttl, arginfo_key, ZEND_ACC_PUBLIC)
PHP_ME(Redis, type, arginfo_key, ZEND_ACC_PUBLIC)
PHP_ME(Redis, unlink, arginfo_nkeys, ZEND_ACC_PUBLIC)
PHP_ME(Redis, unsubscribe, arginfo_unsubscribe, ZEND_ACC_PUBLIC)
PHP_ME(Redis, unwatch, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(Redis, wait, arginfo_wait, ZEND_ACC_PUBLIC)
PHP_ME(Redis, watch, arginfo_watch, ZEND_ACC_PUBLIC)
PHP_ME(Redis, zAdd, arginfo_zadd, ZEND_ACC_PUBLIC)
PHP_ME(Redis, zCard, arginfo_key, ZEND_ACC_PUBLIC)
PHP_ME(Redis, zCount, arginfo_key_min_max, ZEND_ACC_PUBLIC)
PHP_ME(Redis, zDelete, arginfo_key_members, ZEND_ACC_PUBLIC)
PHP_ME(Redis, zDeleteRangeByRank, arginfo_key_start_end, ZEND_ACC_PUBLIC)
PHP_ME(Redis, zDeleteRangeByScore, arginfo_key_min_max, ZEND_ACC_PUBLIC)
PHP_ME(Redis, zIncrBy, arginfo_zincrby, ZEND_ACC_PUBLIC)
PHP_ME(Redis, zInter, arginfo_zstore, ZEND_ACC_PUBLIC)
PHP_ME(Redis, zLexCount, arginfo_key_min_max, ZEND_ACC_PUBLIC)
PHP_ME(Redis, zRange, arginfo_zrange, ZEND_ACC_PUBLIC)
PHP_ME(Redis, zRangeByLex, arginfo_zrangebylex, ZEND_ACC_PUBLIC)
PHP_ME(Redis, zRangeByScore, arginfo_zrangebyscore, ZEND_ACC_PUBLIC)
PHP_ME(Redis, zRank, arginfo_key_member, ZEND_ACC_PUBLIC)
PHP_ME(Redis, zRemRangeByLex, arginfo_key_min_max, ZEND_ACC_PUBLIC)
PHP_ME(Redis, zRevRange, arginfo_zrange, ZEND_ACC_PUBLIC)
PHP_ME(Redis, zRevRangeByLex, arginfo_zrangebylex, ZEND_ACC_PUBLIC)
PHP_ME(Redis, zRevRangeByScore, arginfo_zrangebyscore, ZEND_ACC_PUBLIC)
PHP_ME(Redis, zRevRank, arginfo_key_member, ZEND_ACC_PUBLIC)
PHP_ME(Redis, zScore, arginfo_key_member, ZEND_ACC_PUBLIC)
PHP_ME(Redis, zUnion, arginfo_zstore, ZEND_ACC_PUBLIC)
PHP_ME(Redis, zscan, arginfo_kscan, ZEND_ACC_PUBLIC)
PHP_MALIAS(Redis, del, delete, arginfo_del, ZEND_ACC_PUBLIC)
PHP_MALIAS(Redis, evaluate, eval, arginfo_eval, ZEND_ACC_PUBLIC)
PHP_MALIAS(Redis, evaluateSha, evalsha, arginfo_evalsha, ZEND_ACC_PUBLIC)
PHP_MALIAS(Redis, expire, setTimeout, arginfo_expire, ZEND_ACC_PUBLIC)
PHP_MALIAS(Redis, keys, getKeys, arginfo_keys, ZEND_ACC_PUBLIC)
PHP_MALIAS(Redis, lLen, lSize, arginfo_key, ZEND_ACC_PUBLIC)
PHP_MALIAS(Redis, lindex, lGet, arginfo_lindex, ZEND_ACC_PUBLIC)
PHP_MALIAS(Redis, lrange, lGetRange, arginfo_key_start_end, ZEND_ACC_PUBLIC)
PHP_MALIAS(Redis, lrem, lRemove, arginfo_lrem, ZEND_ACC_PUBLIC)
PHP_MALIAS(Redis, ltrim, listTrim, arginfo_ltrim, ZEND_ACC_PUBLIC)
PHP_MALIAS(Redis, mget, getMultiple, arginfo_mget, ZEND_ACC_PUBLIC)
PHP_MALIAS(Redis, open, connect, arginfo_connect, ZEND_ACC_PUBLIC)
PHP_MALIAS(Redis, popen, pconnect, arginfo_pconnect, ZEND_ACC_PUBLIC)
PHP_MALIAS(Redis, rename, renameKey, arginfo_key_newkey, ZEND_ACC_PUBLIC)
PHP_MALIAS(Redis, sGetMembers, sMembers, arginfo_key, ZEND_ACC_PUBLIC)
PHP_MALIAS(Redis, scard, sSize, arginfo_key, ZEND_ACC_PUBLIC)
PHP_MALIAS(Redis, sendEcho, echo, arginfo_echo, ZEND_ACC_PUBLIC)
PHP_MALIAS(Redis, sismember, sContains, arginfo_key_value, ZEND_ACC_PUBLIC)
PHP_MALIAS(Redis, srem, sRemove, arginfo_key_value, ZEND_ACC_PUBLIC)
PHP_MALIAS(Redis, substr, getRange, arginfo_key_start_end, ZEND_ACC_PUBLIC)
PHP_MALIAS(Redis, zRem, zDelete, arginfo_key_members, ZEND_ACC_PUBLIC)
PHP_MALIAS(Redis, zRemRangeByRank, zDeleteRangeByRank, arginfo_key_min_max, ZEND_ACC_PUBLIC)
PHP_MALIAS(Redis, zRemRangeByScore, zDeleteRangeByScore, arginfo_key_min_max, ZEND_ACC_PUBLIC)
PHP_MALIAS(Redis, zRemove, zDelete, arginfo_key_members, ZEND_ACC_PUBLIC)
PHP_MALIAS(Redis, zRemoveRangeByScore, zDeleteRangeByScore, arginfo_key_min_max, ZEND_ACC_PUBLIC)
PHP_MALIAS(Redis, zReverseRange, zRevRange, arginfo_zrange, ZEND_ACC_PUBLIC)
PHP_MALIAS(Redis, zSize, zCard, arginfo_key, ZEND_ACC_PUBLIC)
PHP_MALIAS(Redis, zinterstore, zInter, arginfo_zstore, ZEND_ACC_PUBLIC)
PHP_MALIAS(Redis, zunionstore, zUnion, arginfo_zstore, ZEND_ACC_PUBLIC)
PHP_FE_END
};
static const zend_module_dep redis_deps[] = {
#ifdef HAVE_REDIS_IGBINARY
ZEND_MOD_REQUIRED("igbinary")
#endif
ZEND_MOD_END
};
zend_module_entry redis_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER_EX,
NULL,
redis_deps,
#endif
"redis",
NULL,
PHP_MINIT(redis),
PHP_MSHUTDOWN(redis),
NULL,
NULL,
PHP_MINFO(redis),
#if ZEND_MODULE_API_NO >= 20010901
PHP_REDIS_VERSION,
#endif
STANDARD_MODULE_PROPERTIES
};
#ifdef COMPILE_DL_REDIS
ZEND_GET_MODULE(redis)
#endif
/* Send a static DISCARD in case we're in MULTI mode. */
static int
redis_send_discard(RedisSock *redis_sock TSRMLS_DC)
{
int result = FAILURE;
char *cmd, *resp;
int resp_len, cmd_len;
/* format our discard command */
cmd_len = REDIS_SPPRINTF(&cmd, "DISCARD", "");
/* send our DISCARD command */
if (redis_sock_write(redis_sock, cmd, cmd_len TSRMLS_CC) >= 0 &&
(resp = redis_sock_read(redis_sock,&resp_len TSRMLS_CC)) != NULL)
{
/* success if we get OK */
result = (resp_len == 3 && strncmp(resp,"+OK", 3) == 0) ? SUCCESS:FAILURE;
/* free our response */
efree(resp);
}
/* free our command */
efree(cmd);
/* return success/failure */
return result;
}
static void
free_reply_callbacks(RedisSock *redis_sock)
{
fold_item *fi;
for (fi = redis_sock->head; fi; ) {
fold_item *fi_next = fi->next;
free(fi);
fi = fi_next;
}
redis_sock->head = NULL;
redis_sock->current = NULL;
}
#if (PHP_MAJOR_VERSION < 7)
void
free_redis_object(void *object TSRMLS_DC)
{
redis_object *redis = (redis_object *)object;
zend_object_std_dtor(&redis->std TSRMLS_CC);
if (redis->sock) {
redis_sock_disconnect(redis->sock TSRMLS_CC);
redis_free_socket(redis->sock);
}
efree(redis);
}
zend_object_value
create_redis_object(zend_class_entry *ce TSRMLS_DC)
{
zend_object_value retval;
redis_object *redis = ecalloc(1, sizeof(redis_object));
memset(redis, 0, sizeof(redis_object));
zend_object_std_init(&redis->std, ce TSRMLS_CC);
#if PHP_VERSION_ID < 50399
zval *tmp;
zend_hash_copy(redis->std.properties, &ce->default_properties,
(copy_ctor_func_t)zval_add_ref, (void *)&tmp, sizeof(zval *));
#else
object_properties_init(&redis->std, ce);
#endif
retval.handle = zend_objects_store_put(redis,
(zend_objects_store_dtor_t)zend_objects_destroy_object,
(zend_objects_free_object_storage_t)free_redis_object,
NULL TSRMLS_CC);
retval.handlers = zend_get_std_object_handlers();
return retval;
}
#else
zend_object_handlers redis_object_handlers;
void
free_redis_object(zend_object *object)
{
redis_object *redis = (redis_object *)((char *)(object) - XtOffsetOf(redis_object, std));
zend_object_std_dtor(&redis->std TSRMLS_CC);
if (redis->sock) {
redis_sock_disconnect(redis->sock TSRMLS_CC);
redis_free_socket(redis->sock);
}
}
zend_object *
create_redis_object(zend_class_entry *ce TSRMLS_DC)
{
redis_object *redis = ecalloc(1, sizeof(redis_object) + zend_object_properties_size(ce));
redis->sock = NULL;
zend_object_std_init(&redis->std, ce TSRMLS_CC);
object_properties_init(&redis->std, ce);
memcpy(&redis_object_handlers, zend_get_std_object_handlers(), sizeof(redis_object_handlers));
redis_object_handlers.offset = XtOffsetOf(redis_object, std);
redis_object_handlers.free_obj = free_redis_object;
redis->std.handlers = &redis_object_handlers;
return &redis->std;
}
#endif
static zend_always_inline RedisSock *
redis_sock_get_instance(zval *id TSRMLS_DC, int no_throw)
{
redis_object *redis;
if (Z_TYPE_P(id) == IS_OBJECT) {
redis = PHPREDIS_GET_OBJECT(redis_object, id);
if (redis->sock) {
return redis->sock;
}
}
// Throw an exception unless we've been requested not to
if (!no_throw) {
zend_throw_exception(redis_exception_ce, "Redis server went away", 0 TSRMLS_CC);
}
return NULL;
}
/**
* redis_sock_get
*/
PHP_REDIS_API RedisSock *
redis_sock_get(zval *id TSRMLS_DC, int no_throw)
{
RedisSock *redis_sock;
if ((redis_sock = redis_sock_get_instance(id TSRMLS_CC, no_throw)) == NULL) {
return NULL;
}
if (redis_sock->lazy_connect) {
redis_sock->lazy_connect = 0;
if (redis_sock_server_open(redis_sock TSRMLS_CC) < 0) {
return NULL;
}
}
return redis_sock;
}
/**
* redis_sock_get_direct
* Returns our attached RedisSock pointer if we're connected
*/
PHP_REDIS_API RedisSock *redis_sock_get_connected(INTERNAL_FUNCTION_PARAMETERS) {
zval *object;
RedisSock *redis_sock;
// If we can't grab our object, or get a socket, or we're not connected,
// return NULL
if((zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
&object, redis_ce) == FAILURE) ||
(redis_sock = redis_sock_get(object TSRMLS_CC, 1)) == NULL ||
redis_sock->status != REDIS_SOCK_STATUS_CONNECTED)
{
return NULL;
}
/* Return our socket */
return redis_sock;
}
/* Redis and RedisCluster objects share serialization/prefixing settings so
* this is a generic function to add class constants to either */
static void add_class_constants(zend_class_entry *ce, int is_cluster TSRMLS_DC) {
zend_declare_class_constant_long(ce, ZEND_STRL("REDIS_NOT_FOUND"), REDIS_NOT_FOUND TSRMLS_CC);
zend_declare_class_constant_long(ce, ZEND_STRL("REDIS_STRING"), REDIS_STRING TSRMLS_CC);
zend_declare_class_constant_long(ce, ZEND_STRL("REDIS_SET"), REDIS_SET TSRMLS_CC);
zend_declare_class_constant_long(ce, ZEND_STRL("REDIS_LIST"), REDIS_LIST TSRMLS_CC);
zend_declare_class_constant_long(ce, ZEND_STRL("REDIS_ZSET"), REDIS_ZSET TSRMLS_CC);
zend_declare_class_constant_long(ce, ZEND_STRL("REDIS_HASH"), REDIS_HASH TSRMLS_CC);
/* Cluster doesn't support pipelining at this time */
if(!is_cluster) {
zend_declare_class_constant_long(ce, ZEND_STRL("PIPELINE"), PIPELINE TSRMLS_CC);
}
/* Add common mode constants */
zend_declare_class_constant_long(ce, ZEND_STRL("ATOMIC"), ATOMIC TSRMLS_CC);
zend_declare_class_constant_long(ce, ZEND_STRL("MULTI"), MULTI TSRMLS_CC);
/* options */
zend_declare_class_constant_long(ce, ZEND_STRL("OPT_SERIALIZER"), REDIS_OPT_SERIALIZER TSRMLS_CC);
zend_declare_class_constant_long(ce, ZEND_STRL("OPT_PREFIX"), REDIS_OPT_PREFIX TSRMLS_CC);
zend_declare_class_constant_long(ce, ZEND_STRL("OPT_READ_TIMEOUT"), REDIS_OPT_READ_TIMEOUT TSRMLS_CC);
zend_declare_class_constant_long(ce, ZEND_STRL("OPT_TCP_KEEPALIVE"), REDIS_OPT_TCP_KEEPALIVE TSRMLS_CC);
zend_declare_class_constant_long(ce, ZEND_STRL("OPT_COMPRESSION"), REDIS_OPT_COMPRESSION TSRMLS_CC);
/* serializer */
zend_declare_class_constant_long(ce, ZEND_STRL("SERIALIZER_NONE"), REDIS_SERIALIZER_NONE TSRMLS_CC);
zend_declare_class_constant_long(ce, ZEND_STRL("SERIALIZER_PHP"), REDIS_SERIALIZER_PHP TSRMLS_CC);
#ifdef HAVE_REDIS_IGBINARY
zend_declare_class_constant_long(ce, ZEND_STRL("SERIALIZER_IGBINARY"), REDIS_SERIALIZER_IGBINARY TSRMLS_CC);
#endif
/* compression */
zend_declare_class_constant_long(ce, ZEND_STRL("COMPRESSION_NONE"), REDIS_COMPRESSION_NONE TSRMLS_CC);
#ifdef HAVE_REDIS_LZF
zend_declare_class_constant_long(ce, ZEND_STRL("COMPRESSION_LZF"), REDIS_COMPRESSION_LZF TSRMLS_CC);
#endif
/* scan options*/
zend_declare_class_constant_long(ce, ZEND_STRL("OPT_SCAN"), REDIS_OPT_SCAN TSRMLS_CC);
zend_declare_class_constant_long(ce, ZEND_STRL("SCAN_RETRY"), REDIS_SCAN_RETRY TSRMLS_CC);
zend_declare_class_constant_long(ce, ZEND_STRL("SCAN_NORETRY"), REDIS_SCAN_NORETRY TSRMLS_CC);
/* Cluster option to allow for slave failover */
if (is_cluster) {
zend_declare_class_constant_long(ce, ZEND_STRL("OPT_SLAVE_FAILOVER"), REDIS_OPT_FAILOVER TSRMLS_CC);
zend_declare_class_constant_long(ce, ZEND_STRL("FAILOVER_NONE"), REDIS_FAILOVER_NONE TSRMLS_CC);
zend_declare_class_constant_long(ce, ZEND_STRL("FAILOVER_ERROR"), REDIS_FAILOVER_ERROR TSRMLS_CC);
zend_declare_class_constant_long(ce, ZEND_STRL("FAILOVER_DISTRIBUTE"), REDIS_FAILOVER_DISTRIBUTE TSRMLS_CC);
zend_declare_class_constant_long(ce, ZEND_STRL("FAILOVER_DISTRIBUTE_SLAVES"), REDIS_FAILOVER_DISTRIBUTE_SLAVES TSRMLS_CC);
}
zend_declare_class_constant_stringl(ce, "AFTER", 5, "after", 5 TSRMLS_CC);
zend_declare_class_constant_stringl(ce, "BEFORE", 6, "before", 6 TSRMLS_CC);
}
/**
* PHP_MINIT_FUNCTION
*/
PHP_MINIT_FUNCTION(redis)
{
struct timeval tv;
zend_class_entry redis_class_entry;
zend_class_entry redis_array_class_entry;
zend_class_entry redis_cluster_class_entry;
zend_class_entry redis_exception_class_entry;
zend_class_entry redis_cluster_exception_class_entry;
zend_class_entry *exception_ce = NULL;
/* Seed random generator (for RedisCluster failover) */
gettimeofday(&tv, NULL);
srand(tv.tv_usec * tv.tv_sec);
REGISTER_INI_ENTRIES();
/* Redis class */
INIT_CLASS_ENTRY(redis_class_entry, "Redis", redis_functions);
redis_ce = zend_register_internal_class(&redis_class_entry TSRMLS_CC);
redis_ce->create_object = create_redis_object;
/* RedisArray class */
INIT_CLASS_ENTRY(redis_array_class_entry, "RedisArray", redis_array_functions);
redis_array_ce = zend_register_internal_class(&redis_array_class_entry TSRMLS_CC);
redis_array_ce->create_object = create_redis_array_object;
/* RedisCluster class */
INIT_CLASS_ENTRY(redis_cluster_class_entry, "RedisCluster", redis_cluster_functions);
redis_cluster_ce = zend_register_internal_class(&redis_cluster_class_entry TSRMLS_CC);
redis_cluster_ce->create_object = create_cluster_context;
/* Base Exception class */
#if HAVE_SPL
exception_ce = zend_hash_str_find_ptr(CG(class_table), "RuntimeException", sizeof("RuntimeException") - 1);
#endif
if (exception_ce == NULL) {
#if (PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION < 2)
exception_ce = zend_exception_get_default();
#else
exception_ce = zend_exception_get_default(TSRMLS_C);
#endif
}
/* RedisException class */
INIT_CLASS_ENTRY(redis_exception_class_entry, "RedisException", NULL);
redis_exception_ce = zend_register_internal_class_ex(
&redis_exception_class_entry,
#if (PHP_MAJOR_VERSION < 7)
exception_ce, NULL TSRMLS_CC
#else
exception_ce
#endif
);
/* RedisClusterException class */
INIT_CLASS_ENTRY(redis_cluster_exception_class_entry,
"RedisClusterException", NULL);
redis_cluster_exception_ce = zend_register_internal_class_ex(
&redis_cluster_exception_class_entry,
#if (PHP_MAJOR_VERSION < 7)
exception_ce, NULL TSRMLS_CC
#else
exception_ce
#endif
);
/* Add shared class constants to Redis and RedisCluster objects */
add_class_constants(redis_ce, 0 TSRMLS_CC);
add_class_constants(redis_cluster_ce, 1 TSRMLS_CC);
#ifdef PHP_SESSION
php_session_register_module(&ps_mod_redis);
php_session_register_module(&ps_mod_redis_cluster);
#endif
return SUCCESS;
}
/**
* PHP_MSHUTDOWN_FUNCTION
*/
PHP_MSHUTDOWN_FUNCTION(redis)
{
return SUCCESS;
}
/**
* PHP_MINFO_FUNCTION
*/
PHP_MINFO_FUNCTION(redis)
{
php_info_print_table_start();
php_info_print_table_header(2, "Redis Support", "enabled");
php_info_print_table_row(2, "Redis Version", PHP_REDIS_VERSION);
#ifdef HAVE_REDIS_IGBINARY
php_info_print_table_row(2, "Available serializers", "php, igbinary");
#else
php_info_print_table_row(2, "Available serializers", "php");
#endif
#ifdef HAVE_REDIS_LZF
php_info_print_table_row(2, "Available compression", "lzf");
#endif
php_info_print_table_end();
}
/* {{{ proto Redis Redis::__construct()
Public constructor */
PHP_METHOD(Redis, __construct)
{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
RETURN_FALSE;
}
}
/* }}} */
/* {{{ proto Redis Redis::__destruct()
Public Destructor
*/
PHP_METHOD(Redis,__destruct) {
if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
RETURN_FALSE;
}
// Grab our socket
RedisSock *redis_sock;
if ((redis_sock = redis_sock_get_instance(getThis() TSRMLS_CC, 1)) == NULL) {
RETURN_FALSE;
}
// If we think we're in MULTI mode, send a discard
if (IS_MULTI(redis_sock)) {
if (!IS_PIPELINE(redis_sock) && redis_sock->stream) {
// Discard any multi commands, and free any callbacks that have been
// queued
redis_send_discard(redis_sock TSRMLS_CC);
}
free_reply_callbacks(redis_sock);
}
}
/* {{{ proto boolean Redis::connect(string host, int port [, double timeout [, long retry_interval]])
*/
PHP_METHOD(Redis, connect)
{
if (redis_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0) == FAILURE) {
RETURN_FALSE;
} else {
RETURN_TRUE;
}
}
/* }}} */
/* {{{ proto boolean Redis::pconnect(string host, int port [, double timeout])
*/
PHP_METHOD(Redis, pconnect)
{
if (redis_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1) == FAILURE) {
RETURN_FALSE;
} else {
RETURN_TRUE;
}
}
/* }}} */
PHP_REDIS_API int
redis_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
{
zval *object;
char *host = NULL, *persistent_id = "";
zend_long port = -1, retry_interval = 0;
strlen_t host_len, persistent_id_len;
double timeout = 0.0, read_timeout = 0.0;
redis_object *redis;
#ifdef ZTS
/* not sure how in threaded mode this works so disabled persistence at
* first */
persistent = 0;
#endif
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
"Os|ldsld", &object, redis_ce, &host,
&host_len, &port, &timeout, &persistent_id,
&persistent_id_len, &retry_interval,
&read_timeout) == FAILURE)
{
return FAILURE;
} else if (!persistent) {
persistent_id = NULL;
}
if (timeout < 0L || timeout > INT_MAX) {
zend_throw_exception(redis_exception_ce,
"Invalid connect timeout", 0 TSRMLS_CC);
return FAILURE;
}
if (read_timeout < 0L || read_timeout > INT_MAX) {
zend_throw_exception(redis_exception_ce,
"Invalid read timeout", 0 TSRMLS_CC);
return FAILURE;
}
if (retry_interval < 0L || retry_interval > INT_MAX) {
zend_throw_exception(redis_exception_ce, "Invalid retry interval",
0 TSRMLS_CC);
return FAILURE;
}
/* If it's not a unix socket, set to default */
if(port == -1 && host_len && host[0] != '/') {
port = 6379;
}
redis = PHPREDIS_GET_OBJECT(redis_object, object);
/* if there is a redis sock already we have to remove it */
if (redis->sock) {
redis_sock_disconnect(redis->sock TSRMLS_CC);
redis_free_socket(redis->sock);
}
redis->sock = redis_sock_create(host, host_len, port, timeout, read_timeout, persistent,
persistent_id, retry_interval, 0);
if (redis_sock_server_open(redis->sock TSRMLS_CC) < 0) {
if (redis->sock->err) {
zend_throw_exception(redis_exception_ce, ZSTR_VAL(redis->sock->err), 0 TSRMLS_CC);
}
redis_free_socket(redis->sock);
redis->sock = NULL;
return FAILURE;
}
return SUCCESS;
}
/* {{{ proto long Redis::bitop(string op, string key, ...) */
PHP_METHOD(Redis, bitop)
{
REDIS_PROCESS_CMD(bitop, redis_long_response);
}
/* }}} */
/* {{{ proto long Redis::bitcount(string key, [int start], [int end])
*/
PHP_METHOD(Redis, bitcount)
{
REDIS_PROCESS_CMD(bitcount, redis_long_response);
}
/* }}} */
/* {{{ proto integer Redis::bitpos(string key, int bit, [int start, int end]) */
PHP_METHOD(Redis, bitpos)
{
REDIS_PROCESS_CMD(bitpos, redis_long_response);
}
/* }}} */
/* {{{ proto boolean Redis::close()
*/
PHP_METHOD(Redis, close)
{
RedisSock *redis_sock = redis_sock_get_connected(INTERNAL_FUNCTION_PARAM_PASSTHRU);
if (redis_sock && redis_sock_disconnect(redis_sock TSRMLS_CC)) {
RETURN_TRUE;
}
RETURN_FALSE;
}
/* }}} */
/* {{{ proto boolean Redis::set(string key, mixed val, long timeout,
* [array opt) */
PHP_METHOD(Redis, set) {
REDIS_PROCESS_CMD(set, redis_boolean_response);
}
/* {{{ proto boolean Redis::setex(string key, long expire, string value)
*/
PHP_METHOD(Redis, setex)
{
REDIS_PROCESS_KW_CMD("SETEX", redis_key_long_val_cmd, redis_boolean_response);
}
/* {{{ proto boolean Redis::psetex(string key, long expire, string value)
*/
PHP_METHOD(Redis, psetex)
{
REDIS_PROCESS_KW_CMD("PSETEX", redis_key_long_val_cmd, redis_boolean_response);
}
/* {{{ proto boolean Redis::setnx(string key, string value)
*/
PHP_METHOD(Redis, setnx)
{
REDIS_PROCESS_KW_CMD("SETNX", redis_kv_cmd, redis_1_response);
}
/* }}} */
/* {{{ proto string Redis::getSet(string key, string value)
*/
PHP_METHOD(Redis, getSet)
{
REDIS_PROCESS_KW_CMD("GETSET", redis_kv_cmd, redis_string_response);
}
/* }}} */
/* {{{ proto string Redis::randomKey()
*/
PHP_METHOD(Redis, randomKey)
{
REDIS_PROCESS_KW_CMD("RANDOMKEY", redis_empty_cmd, redis_ping_response);
}
/* }}} */
/* {{{ proto string Redis::echo(string msg)
*/
PHP_METHOD(Redis, echo)
{
REDIS_PROCESS_KW_CMD("ECHO", redis_str_cmd, redis_string_response);
}
/* }}} */
/* {{{ proto string Redis::renameKey(string key_src, string key_dst)
*/
PHP_METHOD(Redis, renameKey)
{
REDIS_PROCESS_KW_CMD("RENAME", redis_key_key_cmd, redis_boolean_response);
}
/* }}} */
/* {{{ proto string Redis::renameNx(string key_src, string key_dst)
*/
PHP_METHOD(Redis, renameNx)
{
REDIS_PROCESS_KW_CMD("RENAMENX", redis_key_key_cmd, redis_1_response);
}
/* }}} */
/* }}} */
/* {{{ proto string Redis::get(string key)
*/
PHP_METHOD(Redis, get)
{
REDIS_PROCESS_KW_CMD("GET", redis_key_cmd, redis_string_response);
}
/* }}} */
/* {{{ proto string Redis::ping()
*/
PHP_METHOD(Redis, ping)
{
REDIS_PROCESS_KW_CMD("PING", redis_empty_cmd, redis_ping_response);
}
/* }}} */
/* {{{ proto boolean Redis::incr(string key [,int value])
*/
PHP_METHOD(Redis, incr){
REDIS_PROCESS_CMD(incr, redis_long_response);
}
/* }}} */
/* {{{ proto boolean Redis::incrBy(string key ,int value)
*/
PHP_METHOD(Redis, incrBy){
REDIS_PROCESS_KW_CMD("INCRBY", redis_key_long_cmd, redis_long_response);
}
/* }}} */
/* {{{ proto float Redis::incrByFloat(string key, float value)
*/
PHP_METHOD(Redis, incrByFloat) {
REDIS_PROCESS_KW_CMD("INCRBYFLOAT", redis_key_dbl_cmd,
redis_bulk_double_response);
}
/* }}} */
/* {{{ proto boolean Redis::decr(string key) */
PHP_METHOD(Redis, decr)
{
REDIS_PROCESS_CMD(decr, redis_long_response);
}
/* }}} */
/* {{{ proto boolean Redis::decrBy(string key ,int value)
*/
PHP_METHOD(Redis, decrBy){
REDIS_PROCESS_KW_CMD("DECRBY", redis_key_long_cmd, redis_long_response);
}
/* }}} */
/* {{{ proto array Redis::getMultiple(array keys)
*/
PHP_METHOD(Redis, getMultiple)
{
zval *object, *z_args, *z_ele;
HashTable *hash;
RedisSock *redis_sock;
smart_string cmd = {0};
int arg_count;
/* Make sure we have proper arguments */
if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oa",
&object, redis_ce, &z_args) == FAILURE) {
RETURN_FALSE;
}
/* We'll need the socket */
if ((redis_sock = redis_sock_get(object TSRMLS_CC, 0)) == NULL) {
RETURN_FALSE;
}
/* Grab our array */
hash = Z_ARRVAL_P(z_args);
/* We don't need to do anything if there aren't any keys */
if((arg_count = zend_hash_num_elements(hash)) == 0) {
RETURN_FALSE;
}
/* Build our command header */
redis_cmd_init_sstr(&cmd, arg_count, "MGET", 4);
/* Iterate through and grab our keys */
ZEND_HASH_FOREACH_VAL(hash, z_ele) {
zend_string *zstr = zval_get_string(z_ele);
redis_cmd_append_sstr_key(&cmd, ZSTR_VAL(zstr), ZSTR_LEN(zstr), redis_sock, NULL);
zend_string_release(zstr);
} ZEND_HASH_FOREACH_END();
/* Kick off our command */
REDIS_PROCESS_REQUEST(redis_sock, cmd.c, cmd.len);
if (IS_ATOMIC(redis_sock)) {
if(redis_sock_read_multibulk_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU,
redis_sock, NULL, NULL) < 0) {
RETURN_FALSE;
}
}
REDIS_PROCESS_RESPONSE(redis_sock_read_multibulk_reply);
}
/* {{{ proto boolean Redis::exists(string key)
*/
PHP_METHOD(Redis, exists)
{
REDIS_PROCESS_KW_CMD("EXISTS", redis_key_cmd, redis_1_response);
}
/* }}} */
/* {{{ proto boolean Redis::delete(string key)
*/
PHP_METHOD(Redis, delete)
{
REDIS_PROCESS_CMD(del, redis_long_response);
}
/* }}} */
/* {{{ proto long Redis::unlink(string $key1, string $key2 [, string $key3...]) }}}
* {{{ proto long Redis::unlink(array $keys) */
PHP_METHOD(Redis, unlink)
{
REDIS_PROCESS_CMD(unlink, redis_long_response);
}
PHP_REDIS_API void redis_set_watch(RedisSock *redis_sock)
{
redis_sock->watching = 1;
}
PHP_REDIS_API void redis_watch_response(INTERNAL_FUNCTION_PARAMETERS,
RedisSock *redis_sock, zval *z_tab, void *ctx)
{
redis_boolean_response_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock,
z_tab, ctx, redis_set_watch);
}
/* {{{ proto boolean Redis::watch(string key1, string key2...)
*/
PHP_METHOD(Redis, watch)
{
REDIS_PROCESS_CMD(watch, redis_watch_response);
}
/* }}} */
PHP_REDIS_API void redis_clear_watch(RedisSock *redis_sock)
{
redis_sock->watching = 0;
}
PHP_REDIS_API void redis_unwatch_response(INTERNAL_FUNCTION_PARAMETERS,
RedisSock *redis_sock, zval *z_tab,
void *ctx)
{
redis_boolean_response_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock,
z_tab, ctx, redis_clear_watch);
}
/* {{{ proto boolean Redis::unwatch()
*/
PHP_METHOD(Redis, unwatch)
{
REDIS_PROCESS_KW_CMD("UNWATCH", redis_empty_cmd, redis_unwatch_response);
}
/* }}} */
/* {{{ proto array Redis::getKeys(string pattern)
*/
PHP_METHOD(Redis, getKeys)
{
REDIS_PROCESS_KW_CMD("KEYS", redis_key_cmd, redis_mbulk_reply_raw);
}
/* }}} */
/* {{{ proto int Redis::type(string key)
*/
PHP_METHOD(Redis, type)
{
REDIS_PROCESS_KW_CMD("TYPE", redis_key_cmd, redis_type_response);
}
/* }}} */
/* {{{ proto long Redis::append(string key, string val) */
PHP_METHOD(Redis, append)
{
REDIS_PROCESS_KW_CMD("APPEND", redis_kv_cmd, redis_long_response);
}
/* }}} */
/* {{{ proto string Redis::GetRange(string key, long start, long end) */
PHP_METHOD(Redis, getRange)
{
REDIS_PROCESS_KW_CMD("GETRANGE", redis_key_long_long_cmd,
redis_string_response);
}
/* }}} */
/* {{{ proto string Redis::setRange(string key, long start, string value) */
PHP_METHOD(Redis, setRange)
{
REDIS_PROCESS_KW_CMD("SETRANGE", redis_key_long_str_cmd,
redis_long_response);
}
/* }}} */
/* {{{ proto long Redis::getbit(string key, long idx) */
PHP_METHOD(Redis, getBit)
{
REDIS_PROCESS_KW_CMD("GETBIT", redis_key_long_cmd, redis_long_response);
}
/* }}} */
/* {{{ proto long Redis::setbit(string key, long idx, bool|int value) */
PHP_METHOD(Redis, setBit)
{
REDIS_PROCESS_CMD(setbit, redis_long_response);
}
/* }}} */
/* {{{ proto long Redis::strlen(string key) */
PHP_METHOD(Redis, strlen)
{
REDIS_PROCESS_KW_CMD("STRLEN", redis_key_cmd, redis_long_response);
}
/* }}} */
/* {{{ proto boolean Redis::lPush(string key , string value)
*/
PHP_METHOD(Redis, lPush)
{
REDIS_PROCESS_KW_CMD("LPUSH", redis_key_varval_cmd, redis_long_response);
}
/* }}} */
/* {{{ proto boolean Redis::rPush(string key , string value)
*/
PHP_METHOD(Redis, rPush)
{
REDIS_PROCESS_KW_CMD("RPUSH", redis_key_varval_cmd, redis_long_response);
}
/* }}} */
PHP_METHOD(Redis, lInsert)
{
REDIS_PROCESS_CMD(linsert, redis_long_response);
}
/* {{{ proto long Redis::lPushx(string key, mixed value) */
PHP_METHOD(Redis, lPushx)
{
REDIS_PROCESS_KW_CMD("LPUSHX", redis_kv_cmd, redis_long_response);
}
/* }}} */
/* {{{ proto long Redis::rPushx(string key, mixed value) */
PHP_METHOD(Redis, rPushx)
{
REDIS_PROCESS_KW_CMD("RPUSHX", redis_kv_cmd, redis_long_response);
}
/* }}} */
/* {{{ proto string Redis::lPOP(string key) */
PHP_METHOD(Redis, lPop)
{
REDIS_PROCESS_KW_CMD("LPOP", redis_key_cmd, redis_string_response);
}
/* }}} */
/* {{{ proto string Redis::rPOP(string key) */
PHP_METHOD(Redis, rPop)
{
REDIS_PROCESS_KW_CMD("RPOP", redis_key_cmd, redis_string_response);
}
/* }}} */
/* {{{ proto string Redis::blPop(string key1, string key2, ..., int timeout) */
PHP_METHOD(Redis, blPop)
{
REDIS_PROCESS_CMD(blpop, redis_sock_read_multibulk_reply);
}
/* }}} */
/* {{{ proto string Redis::brPop(string key1, string key2, ..., int timeout) */
PHP_METHOD(Redis, brPop)
{
REDIS_PROCESS_CMD(brpop, redis_sock_read_multibulk_reply);
}
/* }}} */
/* {{{ proto int Redis::lSize(string key) */
PHP_METHOD(Redis, lSize)
{
REDIS_PROCESS_KW_CMD("LLEN", redis_key_cmd, redis_long_response);
}
/* }}} */
/* {{{ proto boolean Redis::lRemove(string list, string value, int count = 0) */
PHP_METHOD(Redis, lRemove)
{
REDIS_PROCESS_CMD(lrem, redis_long_response);
}
/* }}} */
/* {{{ proto boolean Redis::listTrim(string key , int start , int end) */
PHP_METHOD(Redis, listTrim)
{
REDIS_PROCESS_KW_CMD("LTRIM", redis_key_long_long_cmd,
redis_boolean_response);
}
/* }}} */
/* {{{ proto string Redis::lGet(string key , int index) */
PHP_METHOD(Redis, lGet)
{
REDIS_PROCESS_KW_CMD("LINDEX", redis_key_long_cmd, redis_string_response);
}
/* }}} */
/* {{{ proto array Redis::lGetRange(string key, int start , int end) */
PHP_METHOD(Redis, lGetRange)
{
REDIS_PROCESS_KW_CMD("LRANGE", redis_key_long_long_cmd,
redis_sock_read_multibulk_reply);
}
/* }}} */
/* {{{ proto long Redis::sAdd(string key , mixed value) */
PHP_METHOD(Redis, sAdd)
{
REDIS_PROCESS_KW_CMD("SADD", redis_key_varval_cmd, redis_long_response);
}
/* }}} */
/* {{{ proto boolean Redis::sAddArray(string key, array $values) */
PHP_METHOD(Redis, sAddArray) {
REDIS_PROCESS_KW_CMD("SADD", redis_key_arr_cmd, redis_long_response);
} /* }}} */
/* {{{ proto int Redis::sSize(string key) */
PHP_METHOD(Redis, sSize)
{
REDIS_PROCESS_KW_CMD("SCARD", redis_key_cmd, redis_long_response);
}
/* }}} */
/* {{{ proto boolean Redis::sRemove(string set, string value) */
PHP_METHOD(Redis, sRemove)
{
REDIS_PROCESS_KW_CMD("SREM", redis_key_varval_cmd, redis_long_response);
}
/* }}} */
/* {{{ proto boolean Redis::sMove(string src, string dst, mixed value) */
PHP_METHOD(Redis, sMove)
{
REDIS_PROCESS_CMD(smove, redis_1_response);
}
/* }}} */
/* {{{ proto string Redis::sPop(string key) */
PHP_METHOD(Redis, sPop)
{
if (ZEND_NUM_ARGS() == 1) {
REDIS_PROCESS_KW_CMD("SPOP", redis_key_cmd, redis_string_response);
} else if (ZEND_NUM_ARGS() == 2) {
REDIS_PROCESS_KW_CMD("SPOP", redis_key_long_cmd, redis_sock_read_multibulk_reply);
} else {
ZEND_WRONG_PARAM_COUNT();
}
}
/* }}} */
/* {{{ proto string Redis::sRandMember(string key [int count]) */
PHP_METHOD(Redis, sRandMember)
{
char *cmd;
int cmd_len;
short have_count;
RedisSock *redis_sock;
// Grab our socket, validate call
if ((redis_sock = redis_sock_get(getThis() TSRMLS_CC, 0)) == NULL ||
redis_srandmember_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock,
&cmd, &cmd_len, NULL, NULL, &have_count) == FAILURE)
{
RETURN_FALSE;
}
REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len);
if(have_count) {
if (IS_ATOMIC(redis_sock)) {
if(redis_sock_read_multibulk_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU,
redis_sock, NULL, NULL) < 0)
{
RETURN_FALSE;
}
}
REDIS_PROCESS_RESPONSE(redis_sock_read_multibulk_reply);
} else {
if (IS_ATOMIC(redis_sock)) {
redis_string_response(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock,
NULL, NULL);
}
REDIS_PROCESS_RESPONSE(redis_string_response);
}
}
/* }}} */
/* {{{ proto boolean Redis::sContains(string set, string value) */
PHP_METHOD(Redis, sContains)
{
REDIS_PROCESS_KW_CMD("SISMEMBER", redis_kv_cmd, redis_1_response);
}
/* }}} */
/* {{{ proto array Redis::sMembers(string set) */
PHP_METHOD(Redis, sMembers)
{
REDIS_PROCESS_KW_CMD("SMEMBERS", redis_key_cmd,
redis_sock_read_multibulk_reply);
}
/* }}} */
/* {{{ proto array Redis::sInter(string key0, ... string keyN) */
PHP_METHOD(Redis, sInter) {
REDIS_PROCESS_CMD(sinter, redis_sock_read_multibulk_reply);
}
/* }}} */
/* {{{ proto array Redis::sInterStore(string dst, string key0,...string keyN) */
PHP_METHOD(Redis, sInterStore) {
REDIS_PROCESS_CMD(sinterstore, redis_long_response);
}
/* }}} */
/* {{{ proto array Redis::sUnion(string key0, ... string keyN) */
PHP_METHOD(Redis, sUnion) {
REDIS_PROCESS_CMD(sunion, redis_sock_read_multibulk_reply);
}
/* }}} */
/* {{{ proto array Redis::sUnionStore(string dst, string key0, ... keyN) */
PHP_METHOD(Redis, sUnionStore) {
REDIS_PROCESS_CMD(sunionstore, redis_long_response);
}
/* }}} */
/* {{{ proto array Redis::sDiff(string key0, ... string keyN) */
PHP_METHOD(Redis, sDiff) {
REDIS_PROCESS_CMD(sdiff, redis_sock_read_multibulk_reply);
}
/* }}} */
/* {{{ proto array Redis::sDiffStore(string dst, string key0, ... keyN) */
PHP_METHOD(Redis, sDiffStore) {
REDIS_PROCESS_CMD(sdiffstore, redis_long_response);
}
/* }}} */
/* {{{ proto array Redis::sort(string key, array options) */
PHP_METHOD(Redis, sort) {
char *cmd;
int cmd_len, have_store;
RedisSock *redis_sock;
// Grab socket, handle command construction
if ((redis_sock = redis_sock_get(getThis() TSRMLS_CC, 0)) == NULL ||
redis_sort_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, &have_store,
&cmd, &cmd_len, NULL, NULL) == FAILURE)
{
RETURN_FALSE;
}
REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len);
if (IS_ATOMIC(redis_sock)) {
if (redis_read_variant_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU,
redis_sock, NULL, NULL) < 0)
{
RETURN_FALSE;
}
}
REDIS_PROCESS_RESPONSE(redis_read_variant_reply);
}
static void
generic_sort_cmd(INTERNAL_FUNCTION_PARAMETERS, int desc, int alpha)
{
zval *object, *zele, *zget = NULL;
RedisSock *redis_sock;
zend_string *zpattern;
char *key = NULL, *pattern = NULL, *store = NULL;
strlen_t keylen, patternlen, storelen;
zend_long offset = -1, count = -1;
int argc = 1; /* SORT key is the simplest SORT command */
smart_string cmd = {0};
/* Parse myriad of sort arguments */
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
"Os|s!z!lls", &object, redis_ce, &key,
&keylen, &pattern, &patternlen, &zget,
&offset, &count, &store, &storelen)
== FAILURE)
{
RETURN_FALSE;
}
/* Ensure we're sorting something, and we can get context */
if (keylen == 0 || !(redis_sock = redis_sock_get(object TSRMLS_CC, 0)))
RETURN_FALSE;
/* Start calculating argc depending on input arguments */
if (pattern && patternlen) argc += 2; /* BY pattern */
if (offset >= 0 && count >= 0) argc += 3; /* LIMIT offset count */
if (alpha) argc += 1; /* ALPHA */
if (store) argc += 2; /* STORE destination */
if (desc) argc += 1; /* DESC (ASC is the default) */
/* GET is special. It can be 0 .. N arguments depending what we have */
if (zget) {
if (Z_TYPE_P(zget) == IS_ARRAY)
argc += zend_hash_num_elements(Z_ARRVAL_P(zget));
else if (Z_STRLEN_P(zget) > 0) {
argc += 2; /* GET pattern */
}
}
/* Start constructing final command and append key */
redis_cmd_init_sstr(&cmd, argc, "SORT", 4);
redis_cmd_append_sstr_key(&cmd, key, keylen, redis_sock, NULL);
/* BY pattern */
if (pattern && patternlen) {
redis_cmd_append_sstr(&cmd, "BY", sizeof("BY") - 1);
redis_cmd_append_sstr(&cmd, pattern, patternlen);
}
/* LIMIT offset count */
if (offset >= 0 && count >= 0) {
redis_cmd_append_sstr(&cmd, "LIMIT", sizeof("LIMIT") - 1);
redis_cmd_append_sstr_long(&cmd, offset);
redis_cmd_append_sstr_long(&cmd, count);
}
/* Handle any number of GET pattern arguments we've been passed */
if (zget != NULL) {
if (Z_TYPE_P(zget) == IS_ARRAY) {
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(zget), zele) {
zpattern = zval_get_string(zele);
redis_cmd_append_sstr(&cmd, "GET", sizeof("GET") - 1);
redis_cmd_append_sstr(&cmd, ZSTR_VAL(zpattern), ZSTR_LEN(zpattern));
zend_string_release(zpattern);
} ZEND_HASH_FOREACH_END();
} else {
zpattern = zval_get_string(zget);
redis_cmd_append_sstr(&cmd, "GET", sizeof("GET") - 1);
redis_cmd_append_sstr(&cmd, ZSTR_VAL(zpattern), ZSTR_LEN(zpattern));
zend_string_release(zpattern);
}
}
/* Append optional DESC and ALPHA modifiers */
if (desc) redis_cmd_append_sstr(&cmd, "DESC", sizeof("DESC") - 1);
if (alpha) redis_cmd_append_sstr(&cmd, "ALPHA", sizeof("ALPHA") - 1);
/* Finally append STORE if we've got it */
if (store && storelen) {
redis_cmd_append_sstr(&cmd, "STORE", sizeof("STORE") - 1);
redis_cmd_append_sstr_key(&cmd, store, storelen, redis_sock, NULL);
}
REDIS_PROCESS_REQUEST(redis_sock, cmd.c, cmd.len);
if (IS_ATOMIC(redis_sock)) {
if (redis_read_variant_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU,
redis_sock, NULL, NULL) < 0)
{
RETURN_FALSE;
}
}
REDIS_PROCESS_RESPONSE(redis_read_variant_reply);
}
/* {{{ proto array Redis::sortAsc(string key, string pattern, string get,
* int start, int end, bool getList]) */
PHP_METHOD(Redis, sortAsc)
{
generic_sort_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0);
}
/* }}} */
/* {{{ proto array Redis::sortAscAlpha(string key, string pattern, string get,
* int start, int end, bool getList]) */
PHP_METHOD(Redis, sortAscAlpha)
{
generic_sort_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 1);
}
/* }}} */
/* {{{ proto array Redis::sortDesc(string key, string pattern, string get,
* int start, int end, bool getList]) */
PHP_METHOD(Redis, sortDesc)
{
generic_sort_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 0);
}
/* }}} */
/* {{{ proto array Redis::sortDescAlpha(string key, string pattern, string get,
* int start, int end, bool getList]) */
PHP_METHOD(Redis, sortDescAlpha)
{
generic_sort_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 1);
}
/* }}} */
/* {{{ proto array Redis::setTimeout(string key, int timeout) */
PHP_METHOD(Redis, setTimeout) {
REDIS_PROCESS_KW_CMD("EXPIRE", redis_key_long_cmd, redis_1_response);
}
/* }}} */
/* {{{ proto bool Redis::pexpire(string key, long ms) */
PHP_METHOD(Redis, pexpire) {
REDIS_PROCESS_KW_CMD("PEXPIRE", redis_key_long_cmd, redis_1_response);
}
/* }}} */
/* {{{ proto array Redis::expireAt(string key, int timestamp) */
PHP_METHOD(Redis, expireAt) {
REDIS_PROCESS_KW_CMD("EXPIREAT", redis_key_long_cmd, redis_1_response);
}
/* }}} */
/* {{{ proto array Redis::pexpireAt(string key, int timestamp) */
PHP_METHOD(Redis, pexpireAt) {
REDIS_PROCESS_KW_CMD("PEXPIREAT", redis_key_long_cmd, redis_1_response);
}
/* }}} */
/* {{{ proto array Redis::lSet(string key, int index, string value) */
PHP_METHOD(Redis, lSet) {
REDIS_PROCESS_KW_CMD("LSET", redis_key_long_val_cmd,
redis_boolean_response);
}
/* }}} */
/* {{{ proto string Redis::save() */
PHP_METHOD(Redis, save)
{
REDIS_PROCESS_KW_CMD("SAVE", redis_empty_cmd, redis_boolean_response);
}
/* }}} */
/* {{{ proto string Redis::bgSave() */
PHP_METHOD(Redis, bgSave)
{
REDIS_PROCESS_KW_CMD("BGSAVE", redis_empty_cmd, redis_boolean_response);
}
/* }}} */
/* {{{ proto integer Redis::lastSave() */
PHP_METHOD(Redis, lastSave)
{
REDIS_PROCESS_KW_CMD("LASTSAVE", redis_empty_cmd, redis_long_response);
}
/* }}} */
/* {{{ proto bool Redis::flushDB() */
PHP_METHOD(Redis, flushDB)
{
REDIS_PROCESS_KW_CMD("FLUSHDB", redis_empty_cmd, redis_boolean_response);
}
/* }}} */
/* {{{ proto bool Redis::flushAll() */
PHP_METHOD(Redis, flushAll)
{
REDIS_PROCESS_KW_CMD("FLUSHALL", redis_empty_cmd, redis_boolean_response);
}
/* }}} */
/* {{{ proto int Redis::dbSize() */
PHP_METHOD(Redis, dbSize)
{
REDIS_PROCESS_KW_CMD("DBSIZE", redis_empty_cmd, redis_long_response);
}
/* }}} */
/* {{{ proto bool Redis::auth(string passwd) */
PHP_METHOD(Redis, auth) {
REDIS_PROCESS_CMD(auth, redis_boolean_response);
}
/* }}} */
/* {{{ proto long Redis::persist(string key) */
PHP_METHOD(Redis, persist) {
REDIS_PROCESS_KW_CMD("PERSIST", redis_key_cmd, redis_1_response);
}
/* }}} */
/* {{{ proto long Redis::ttl(string key) */
PHP_METHOD(Redis, ttl) {
REDIS_PROCESS_KW_CMD("TTL", redis_key_cmd, redis_long_response);
}
/* }}} */
/* {{{ proto long Redis::pttl(string key) */
PHP_METHOD(Redis, pttl) {
REDIS_PROCESS_KW_CMD("PTTL", redis_key_cmd, redis_long_response);
}
/* }}} */
/* {{{ proto array Redis::info() */
PHP_METHOD(Redis, info) {
zval *object;
RedisSock *redis_sock;
char *cmd, *opt = NULL;
strlen_t opt_len;
int cmd_len;
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
"O|s", &object, redis_ce, &opt, &opt_len)
== FAILURE)
{
RETURN_FALSE;
}
if ((redis_sock = redis_sock_get(object TSRMLS_CC, 0)) == NULL) {
RETURN_FALSE;
}
/* Build a standalone INFO command or one with an option */
if (opt != NULL) {
cmd_len = REDIS_SPPRINTF(&cmd, "INFO", "s", opt, opt_len);
} else {
cmd_len = REDIS_SPPRINTF(&cmd, "INFO", "");
}
REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len);
if (IS_ATOMIC(redis_sock)) {
redis_info_response(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, NULL,
NULL);
}
REDIS_PROCESS_RESPONSE(redis_info_response);
}
/* }}} */
/* {{{ proto bool Redis::select(long dbNumber) */
PHP_METHOD(Redis, select) {
zval *object;
RedisSock *redis_sock;
char *cmd;
int cmd_len;
zend_long dbNumber;
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol",
&object, redis_ce, &dbNumber) == FAILURE) {
RETURN_FALSE;
}
if (dbNumber < 0 || (redis_sock = redis_sock_get(object TSRMLS_CC, 0)) == NULL) {
RETURN_FALSE;
}
redis_sock->dbNumber = dbNumber;
cmd_len = REDIS_SPPRINTF(&cmd, "SELECT", "d", dbNumber);
REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len);
if (IS_ATOMIC(redis_sock)) {
redis_boolean_response(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock,
NULL, NULL);
}
REDIS_PROCESS_RESPONSE(redis_boolean_response);
}
/* }}} */
/* {{{ proto bool Redis::swapdb(long srcdb, long dstdb) */
PHP_METHOD(Redis, swapdb) {
REDIS_PROCESS_KW_CMD("SWAPDB", redis_long_long_cmd, redis_boolean_response);
}
/* {{{ proto bool Redis::move(string key, long dbindex) */
PHP_METHOD(Redis, move) {
REDIS_PROCESS_KW_CMD("MOVE", redis_key_long_cmd, redis_1_response);
}
/* }}} */
static
void generic_mset(INTERNAL_FUNCTION_PARAMETERS, char *kw, ResultCallback fun)
{
RedisSock *redis_sock;
smart_string cmd = {0};
zval *object, *z_array;
HashTable *htargs;
zend_string *zkey;
zval *zmem;
char buf[64];
size_t keylen;
ulong idx;
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oa",
&object, redis_ce, &z_array) == FAILURE)
{
RETURN_FALSE;
}
/* Make sure we can get our socket, and we were not passed an empty array */
if ((redis_sock = redis_sock_get(object TSRMLS_CC, 0)) == NULL ||
zend_hash_num_elements(Z_ARRVAL_P(z_array)) == 0)
{
RETURN_FALSE;
}
/* Initialize our command */
htargs = Z_ARRVAL_P(z_array);
redis_cmd_init_sstr(&cmd, zend_hash_num_elements(htargs) * 2, kw, strlen(kw));
ZEND_HASH_FOREACH_KEY_VAL(htargs, idx, zkey, zmem) {
/* Handle string or numeric keys */
if (zkey) {
redis_cmd_append_sstr_key(&cmd, ZSTR_VAL(zkey), ZSTR_LEN(zkey), redis_sock, NULL);
} else {
keylen = snprintf(buf, sizeof(buf), "%ld", (long)idx);
redis_cmd_append_sstr_key(&cmd, buf, (strlen_t)keylen, redis_sock, NULL);
}
/* Append our value */
redis_cmd_append_sstr_zval(&cmd, zmem, redis_sock TSRMLS_CC);
} ZEND_HASH_FOREACH_END();
REDIS_PROCESS_REQUEST(redis_sock, cmd.c, cmd.len);
if (IS_ATOMIC(redis_sock)) {
fun(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, NULL, NULL);
}
REDIS_PROCESS_RESPONSE(fun);
}
/* {{{ proto bool Redis::mset(array (key => value, ...)) */
PHP_METHOD(Redis, mset) {
generic_mset(INTERNAL_FUNCTION_PARAM_PASSTHRU, "MSET", redis_boolean_response);
}
/* }}} */
/* {{{ proto bool Redis::msetnx(array (key => value, ...)) */
PHP_METHOD(Redis, msetnx) {
generic_mset(INTERNAL_FUNCTION_PARAM_PASSTHRU, "MSETNX", redis_1_response);
}
/* }}} */
/* {{{ proto string Redis::rpoplpush(string srckey, string dstkey) */
PHP_METHOD(Redis, rpoplpush)
{
REDIS_PROCESS_KW_CMD("RPOPLPUSH", redis_key_key_cmd, redis_string_response);
}
/* }}} */
/* {{{ proto string Redis::brpoplpush(string src, string dst, int timeout) */
PHP_METHOD(Redis, brpoplpush) {
REDIS_PROCESS_CMD(brpoplpush, redis_string_response);
}
/* }}} */
/* {{{ proto long Redis::zAdd(string key, int score, string value) */
PHP_METHOD(Redis, zAdd) {
REDIS_PROCESS_CMD(zadd, redis_long_response);
}
/* }}} */
/* Handle ZRANGE and ZREVRANGE as they're the same except for keyword */
static void generic_zrange_cmd(INTERNAL_FUNCTION_PARAMETERS, char *kw,
zrange_cb fun)
{
char *cmd;
int cmd_len;
RedisSock *redis_sock;
int withscores = 0;
if ((redis_sock = redis_sock_get(getThis() TSRMLS_CC, 0)) == NULL) {
RETURN_FALSE;
}
if(fun(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, kw, &cmd,
&cmd_len, &withscores, NULL, NULL) == FAILURE)
{
RETURN_FALSE;
}
REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len);
if(withscores) {
if (IS_ATOMIC(redis_sock)) {
redis_mbulk_reply_zipped_keys_dbl(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, NULL, NULL);
}
REDIS_PROCESS_RESPONSE(redis_mbulk_reply_zipped_keys_dbl);
} else {
if (IS_ATOMIC(redis_sock)) {
if(redis_sock_read_multibulk_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU,
redis_sock, NULL, NULL) < 0)
{
RETURN_FALSE;
}
}
REDIS_PROCESS_RESPONSE(redis_sock_read_multibulk_reply);
}
}
/* {{{ proto array Redis::zRange(string key,int start,int end,bool scores = 0) */
PHP_METHOD(Redis, zRange)
{
generic_zrange_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, "ZRANGE",
redis_zrange_cmd);
}
/* {{{ proto array Redis::zRevRange(string k, long s, long e, bool scores = 0) */
PHP_METHOD(Redis, zRevRange) {
generic_zrange_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, "ZREVRANGE",
redis_zrange_cmd);
}
/* }}} */
/* {{{ proto array Redis::zRangeByScore(string k,string s,string e,array opt) */
PHP_METHOD(Redis, zRangeByScore) {
generic_zrange_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, "ZRANGEBYSCORE",
redis_zrangebyscore_cmd);
}
/* }}} */
/* {{{ proto array Redis::zRevRangeByScore(string key, string start, string end,
* array options) */
PHP_METHOD(Redis, zRevRangeByScore) {
generic_zrange_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, "ZREVRANGEBYSCORE",
redis_zrangebyscore_cmd);
}
/* }}} */
/* {{{ proto array Redis::zRangeByLex(string key, string min, string max, [
* offset, limit]) */
PHP_METHOD(Redis, zRangeByLex) {
REDIS_PROCESS_KW_CMD("ZRANGEBYLEX", redis_zrangebylex_cmd,
redis_sock_read_multibulk_reply);
}
/* }}} */
PHP_METHOD(Redis, zRevRangeByLex) {
REDIS_PROCESS_KW_CMD("ZREVRANGEBYLEX", redis_zrangebylex_cmd,
redis_sock_read_multibulk_reply);
}
/* }}} */
/* {{{ proto long Redis::zLexCount(string key, string min, string max) */
PHP_METHOD(Redis, zLexCount) {
REDIS_PROCESS_KW_CMD("ZLEXCOUNT", redis_gen_zlex_cmd, redis_long_response);
}
/* }}} */
/* {{{ proto long Redis::zRemRangeByLex(string key, string min, string max) */
PHP_METHOD(Redis, zRemRangeByLex) {
REDIS_PROCESS_KW_CMD("ZREMRANGEBYLEX", redis_gen_zlex_cmd,
redis_long_response);
}
/* }}} */
/* {{{ proto long Redis::zDelete(string key, string member) */
PHP_METHOD(Redis, zDelete)
{
REDIS_PROCESS_KW_CMD("ZREM", redis_key_varval_cmd, redis_long_response);
}
/* }}} */
/* {{{ proto long Redis::zDeleteRangeByScore(string k, string s, string e) */
PHP_METHOD(Redis, zDeleteRangeByScore)
{
REDIS_PROCESS_KW_CMD("ZREMRANGEBYSCORE", redis_key_str_str_cmd,
redis_long_response);
}
/* }}} */
/* {{{ proto long Redis::zDeleteRangeByRank(string key, long start, long end) */
PHP_METHOD(Redis, zDeleteRangeByRank)
{
REDIS_PROCESS_KW_CMD("ZREMRANGEBYRANK", redis_key_long_long_cmd,
redis_long_response);
}
/* }}} */
/* {{{ proto array Redis::zCount(string key, string start , string end) */
PHP_METHOD(Redis, zCount)
{
REDIS_PROCESS_KW_CMD("ZCOUNT", redis_key_str_str_cmd, redis_long_response);
}
/* }}} */
/* {{{ proto long Redis::zCard(string key) */
PHP_METHOD(Redis, zCard)
{
REDIS_PROCESS_KW_CMD("ZCARD", redis_key_cmd, redis_long_response);
}
/* }}} */
/* {{{ proto double Redis::zScore(string key, mixed member) */
PHP_METHOD(Redis, zScore)
{
REDIS_PROCESS_KW_CMD("ZSCORE", redis_kv_cmd,
redis_bulk_double_response);
}
/* }}} */
/* {{{ proto long Redis::zRank(string key, string member) */
PHP_METHOD(Redis, zRank) {
REDIS_PROCESS_KW_CMD("ZRANK", redis_kv_cmd, redis_long_response);
}
/* }}} */
/* {{{ proto long Redis::zRevRank(string key, string member) */
PHP_METHOD(Redis, zRevRank) {
REDIS_PROCESS_KW_CMD("ZREVRANK", redis_kv_cmd, redis_long_response);
}
/* }}} */
/* {{{ proto double Redis::zIncrBy(string key, double value, mixed member) */
PHP_METHOD(Redis, zIncrBy)
{
REDIS_PROCESS_CMD(zincrby, redis_bulk_double_response);
}
/* }}} */
/* zInter */
PHP_METHOD(Redis, zInter) {
REDIS_PROCESS_KW_CMD("ZINTERSTORE", redis_zinter_cmd, redis_long_response);
}
/* zUnion */
PHP_METHOD(Redis, zUnion) {
REDIS_PROCESS_KW_CMD("ZUNIONSTORE", redis_zinter_cmd, redis_long_response);
}
/* hashes */
/* {{{ proto long Redis::hset(string key, string mem, string val) */
PHP_METHOD(Redis, hSet)
{
REDIS_PROCESS_CMD(hset, redis_long_response);
}
/* }}} */
/* {{{ proto bool Redis::hSetNx(string key, string mem, string val) */
PHP_METHOD(Redis, hSetNx)
{
REDIS_PROCESS_CMD(hsetnx, redis_1_response);
}
/* }}} */
/* {{{ proto string Redis::hget(string key, string mem) */
PHP_METHOD(Redis, hGet)
{
REDIS_PROCESS_KW_CMD("HGET", redis_key_str_cmd, redis_string_response);
}
/* }}} */
/* {{{ proto long Redis::hLen(string key) */
PHP_METHOD(Redis, hLen)
{
REDIS_PROCESS_KW_CMD("HLEN", redis_key_cmd, redis_long_response);
}
/* }}} */
/* {{{ proto long Redis::hDel(string key, string mem1, ... memN) */
PHP_METHOD(Redis, hDel)
{
REDIS_PROCESS_CMD(hdel, redis_long_response);
}
/* }}} */
/* {{{ proto bool Redis::hExists(string key, string mem) */
PHP_METHOD(Redis, hExists)
{
REDIS_PROCESS_KW_CMD("HEXISTS", redis_key_str_cmd, redis_1_response);
}
/* {{{ proto array Redis::hkeys(string key) */
PHP_METHOD(Redis, hKeys)
{
REDIS_PROCESS_KW_CMD("HKEYS", redis_key_cmd, redis_mbulk_reply_raw);
}
/* }}} */
/* {{{ proto array Redis::hvals(string key) */
PHP_METHOD(Redis, hVals)
{
REDIS_PROCESS_KW_CMD("HVALS", redis_key_cmd,
redis_sock_read_multibulk_reply);
}
/* {{{ proto array Redis::hgetall(string key) */
PHP_METHOD(Redis, hGetAll) {
REDIS_PROCESS_KW_CMD("HGETALL", redis_key_cmd, redis_mbulk_reply_zipped_vals);
}
/* }}} */
/* {{{ proto double Redis::hIncrByFloat(string k, string me, double v) */
PHP_METHOD(Redis, hIncrByFloat)
{
REDIS_PROCESS_CMD(hincrbyfloat, redis_bulk_double_response);
}
/* }}} */
/* {{{ proto long Redis::hincrby(string key, string mem, long byval) */
PHP_METHOD(Redis, hIncrBy)
{
REDIS_PROCESS_CMD(hincrby, redis_long_response);
}
/* }}} */
/* {{{ array Redis::hMget(string hash, array keys) */
PHP_METHOD(Redis, hMget) {
REDIS_PROCESS_CMD(hmget, redis_mbulk_reply_assoc);
}
/* }}} */
/* {{{ proto bool Redis::hmset(string key, array keyvals) */
PHP_METHOD(Redis, hMset)
{
REDIS_PROCESS_CMD(hmset, redis_boolean_response);
}
/* }}} */
/* {{{ proto long Redis::hstrlen(string key, string field) */
PHP_METHOD(Redis, hStrLen) {
REDIS_PROCESS_CMD(hstrlen, redis_long_response);
}
/* }}} */
/* flag : get, set {ATOMIC, MULTI, PIPELINE} */
PHP_METHOD(Redis, multi)
{
RedisSock *redis_sock;
char *resp, *cmd;
int resp_len, cmd_len;
zval *object;
zend_long multi_value = MULTI;
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
"O|l", &object, redis_ce, &multi_value)
== FAILURE)
{
RETURN_FALSE;
}
/* if the flag is activated, send the command, the reply will be "QUEUED"
* or -ERR */
if ((redis_sock = redis_sock_get(object TSRMLS_CC, 0)) == NULL) {
RETURN_FALSE;
}
if (multi_value == PIPELINE) {
/* Cannot enter pipeline mode in a MULTI block */
if (IS_MULTI(redis_sock)) {
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Can't activate pipeline in multi mode!");
RETURN_FALSE;
}
/* Enable PIPELINE if we're not already in one */
if (IS_ATOMIC(redis_sock)) {
free_reply_callbacks(redis_sock);
REDIS_ENABLE_MODE(redis_sock, PIPELINE);
}
} else if (multi_value == MULTI) {
/* Don't want to do anything if we're alredy in MULTI mode */
if (!IS_MULTI(redis_sock)) {
cmd_len = REDIS_SPPRINTF(&cmd, "MULTI", "");
if (IS_PIPELINE(redis_sock)) {
PIPELINE_ENQUEUE_COMMAND(cmd, cmd_len);
efree(cmd);
REDIS_SAVE_CALLBACK(NULL, NULL);
REDIS_ENABLE_MODE(redis_sock, MULTI);
} else {
SOCKET_WRITE_COMMAND(redis_sock, cmd, cmd_len)
efree(cmd);
if ((resp = redis_sock_read(redis_sock, &resp_len TSRMLS_CC)) == NULL) {
RETURN_FALSE;
} else if (strncmp(resp, "+OK", 3) != 0) {
efree(resp);
RETURN_FALSE;
}
efree(resp);
REDIS_ENABLE_MODE(redis_sock, MULTI);
}
}
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown mode sent to Redis::multi");
RETURN_FALSE;
}
RETURN_ZVAL(getThis(), 1, 0);
}
/* discard */
PHP_METHOD(Redis, discard)
{
RedisSock *redis_sock;
zval *object;
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
&object, redis_ce) == FAILURE) {
RETURN_FALSE;
}
if ((redis_sock = redis_sock_get(object TSRMLS_CC, 0)) == NULL) {
RETURN_FALSE;
}
redis_sock->mode = ATOMIC;
free_reply_callbacks(redis_sock);
RETURN_BOOL(redis_send_discard(redis_sock TSRMLS_CC) == SUCCESS);
}
/* redis_sock_read_multibulk_multi_reply */
PHP_REDIS_API int redis_sock_read_multibulk_multi_reply(INTERNAL_FUNCTION_PARAMETERS,
RedisSock *redis_sock)
{
char inbuf[4096];
int numElems;
size_t len;
if (redis_sock_gets(redis_sock, inbuf, sizeof(inbuf) - 1, &len TSRMLS_CC) < 0) {
return - 1;
}
/* number of responses */
numElems = atoi(inbuf+1);
if(numElems < 0) {
return -1;
}
array_init(return_value);
redis_sock_read_multibulk_multi_reply_loop(INTERNAL_FUNCTION_PARAM_PASSTHRU,
redis_sock, return_value, numElems);
return 0;
}
/* exec */
PHP_METHOD(Redis, exec)
{
RedisSock *redis_sock;
char *cmd;
int cmd_len, ret;
zval *object;
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
"O", &object, redis_ce) == FAILURE ||
(redis_sock = redis_sock_get(object TSRMLS_CC, 0)) == NULL
) {
RETURN_FALSE;
}
if (IS_MULTI(redis_sock)) {
cmd_len = REDIS_SPPRINTF(&cmd, "EXEC", "");
if (IS_PIPELINE(redis_sock)) {
PIPELINE_ENQUEUE_COMMAND(cmd, cmd_len);
efree(cmd);
REDIS_SAVE_CALLBACK(NULL, NULL);
REDIS_DISABLE_MODE(redis_sock, MULTI);
RETURN_ZVAL(getThis(), 1, 0);
}
SOCKET_WRITE_COMMAND(redis_sock, cmd, cmd_len)
efree(cmd);
ret = redis_sock_read_multibulk_multi_reply(
INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock);
free_reply_callbacks(redis_sock);
REDIS_DISABLE_MODE(redis_sock, MULTI);
redis_sock->watching = 0;
if (ret < 0) {
zval_dtor(return_value);
RETURN_FALSE;
}
}
if (IS_PIPELINE(redis_sock)) {
if (redis_sock->pipeline_cmd == NULL) {
/* Empty array when no command was run. */
array_init(return_value);
} else {
if (redis_sock_write(redis_sock, redis_sock->pipeline_cmd,
redis_sock->pipeline_len TSRMLS_CC) < 0) {
ZVAL_FALSE(return_value);
} else {
array_init(return_value);
redis_sock_read_multibulk_multi_reply_loop(
INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, return_value, 0);
}
efree(redis_sock->pipeline_cmd);
redis_sock->pipeline_cmd = NULL;
redis_sock->pipeline_len = 0;
}
free_reply_callbacks(redis_sock);
REDIS_DISABLE_MODE(redis_sock, PIPELINE);
}
}
PHP_REDIS_API int
redis_response_enqueued(RedisSock *redis_sock TSRMLS_DC)
{
char *resp;
int resp_len, ret = FAILURE;
if ((resp = redis_sock_read(redis_sock, &resp_len TSRMLS_CC)) != NULL) {
if (strncmp(resp, "+QUEUED", 7) == 0) {
ret = SUCCESS;
}
efree(resp);
}
return ret;
}
PHP_REDIS_API int
redis_sock_read_multibulk_multi_reply_loop(INTERNAL_FUNCTION_PARAMETERS,
RedisSock *redis_sock, zval *z_tab,
int numElems)
{
fold_item *fi;
for (fi = redis_sock->head; fi; /* void */) {
if (fi->fun) {
fi->fun(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab,
fi->ctx TSRMLS_CC);
fi = fi->next;
continue;
}
size_t len;
char inbuf[255];
if (redis_sock_gets(redis_sock, inbuf, sizeof(inbuf) - 1, &len TSRMLS_CC) < 0) {
} else if (strncmp(inbuf, "+OK", 3) != 0) {
}
while ((fi = fi->next) && fi->fun) {
if (redis_response_enqueued(redis_sock TSRMLS_CC) == SUCCESS) {
} else {
}
}
if (redis_sock_gets(redis_sock, inbuf, sizeof(inbuf) - 1, &len TSRMLS_CC) < 0) {
}
#if (PHP_MAJOR_VERSION < 7)
zval *z_ret;
MAKE_STD_ZVAL(z_ret);
#else
zval zv, *z_ret = &zv;
#endif
array_init(z_ret);
add_next_index_zval(z_tab, z_ret);
int num = atol(inbuf + 1);
if (num > 0 && redis_read_multibulk_recursive(redis_sock, num, z_ret TSRMLS_CC) < 0) {
}
if (fi) fi = fi->next;
}
redis_sock->current = fi;
return 0;
}
PHP_METHOD(Redis, pipeline)
{
RedisSock *redis_sock;
zval *object;
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
"O", &object, redis_ce) == FAILURE ||
(redis_sock = redis_sock_get(object TSRMLS_CC, 0)) == NULL
) {
RETURN_FALSE;
}
/* User cannot enter MULTI mode if already in a pipeline */
if (IS_MULTI(redis_sock)) {
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Can't activate pipeline in multi mode!");
RETURN_FALSE;
}
/* Enable pipeline mode unless we're already in that mode in which case this
* is just a NO OP */
if (IS_ATOMIC(redis_sock)) {
/* NB : we keep the function fold, to detect the last function.
* We need the response format of the n - 1 command. So, we can delete
* when n > 2, the { 1 .. n - 2} commands */
free_reply_callbacks(redis_sock);
REDIS_ENABLE_MODE(redis_sock, PIPELINE);
}
RETURN_ZVAL(getThis(), 1, 0);
}
/* {{{ proto long Redis::publish(string channel, string msg) */
PHP_METHOD(Redis, publish)
{
REDIS_PROCESS_KW_CMD("PUBLISH", redis_key_str_cmd, redis_long_response);
}
/* }}} */
/* {{{ proto void Redis::psubscribe(Array(pattern1, pattern2, ... patternN)) */
PHP_METHOD(Redis, psubscribe)
{
REDIS_PROCESS_KW_CMD("PSUBSCRIBE", redis_subscribe_cmd,
redis_subscribe_response);
}
/* {{{ proto void Redis::subscribe(Array(channel1, channel2, ... channelN)) */
PHP_METHOD(Redis, subscribe) {
REDIS_PROCESS_KW_CMD("SUBSCRIBE", redis_subscribe_cmd,
redis_subscribe_response);
}
/**
* [p]unsubscribe channel_0 channel_1 ... channel_n
* [p]unsubscribe(array(channel_0, channel_1, ..., channel_n))
* response format :
* array(
* channel_0 => TRUE|FALSE,
* channel_1 => TRUE|FALSE,
* ...
* channel_n => TRUE|FALSE
* );
**/
PHP_REDIS_API void generic_unsubscribe_cmd(INTERNAL_FUNCTION_PARAMETERS,
char *unsub_cmd)
{
zval *object, *array, *data;
HashTable *arr_hash;
RedisSock *redis_sock;
char *cmd = "", *old_cmd = NULL;
int cmd_len, array_count;
int i;
zval z_tab, *z_channel;
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oa",
&object, redis_ce, &array) == FAILURE) {
RETURN_FALSE;
}
if ((redis_sock = redis_sock_get(object TSRMLS_CC, 0)) == NULL) {
RETURN_FALSE;
}
arr_hash = Z_ARRVAL_P(array);
array_count = zend_hash_num_elements(arr_hash);
if (array_count == 0) {
RETURN_FALSE;
}
ZEND_HASH_FOREACH_VAL(arr_hash, data) {
ZVAL_DEREF(data);
if (Z_TYPE_P(data) == IS_STRING) {
char *old_cmd = NULL;
if(*cmd) {
old_cmd = cmd;
}
spprintf(&cmd, 0, "%s %s", cmd, Z_STRVAL_P(data));
if(old_cmd) {
efree(old_cmd);
}
}
} ZEND_HASH_FOREACH_END();
old_cmd = cmd;
cmd_len = spprintf(&cmd, 0, "%s %s\r\n", unsub_cmd, cmd);
efree(old_cmd);
SOCKET_WRITE_COMMAND(redis_sock, cmd, cmd_len)
efree(cmd);
array_init(return_value);
for (i = 1; i <= array_count; i++) {
redis_sock_read_multibulk_reply_zval(
INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, &z_tab);
if (Z_TYPE(z_tab) == IS_ARRAY) {
if ((z_channel = zend_hash_index_find(Z_ARRVAL(z_tab), 1)) == NULL) {
RETURN_FALSE;
}
add_assoc_bool(return_value, Z_STRVAL_P(z_channel), 1);
} else {
//error
zval_dtor(&z_tab);
RETURN_FALSE;
}
zval_dtor(&z_tab);
}
}
PHP_METHOD(Redis, unsubscribe)
{
REDIS_PROCESS_KW_CMD("UNSUBSCRIBE", redis_unsubscribe_cmd,
redis_unsubscribe_response);
}
PHP_METHOD(Redis, punsubscribe)
{
REDIS_PROCESS_KW_CMD("PUNSUBSCRIBE", redis_unsubscribe_cmd,
redis_unsubscribe_response);
}
/* {{{ proto string Redis::bgrewriteaof() */
PHP_METHOD(Redis, bgrewriteaof)
{
REDIS_PROCESS_KW_CMD("BGREWRITEAOF", redis_empty_cmd,
redis_boolean_response);
}
/* }}} */
/* {{{ proto string Redis::slaveof([host, port]) */
PHP_METHOD(Redis, slaveof)
{
zval *object;
RedisSock *redis_sock;
char *cmd = "", *host = NULL;
strlen_t host_len;
zend_long port = 6379;
int cmd_len;
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
"O|sl", &object, redis_ce, &host,
&host_len, &port) == FAILURE)
{
RETURN_FALSE;
}
if (port < 0 || (redis_sock = redis_sock_get(object TSRMLS_CC, 0)) == NULL) {
RETURN_FALSE;
}
if (host && host_len) {
cmd_len = REDIS_SPPRINTF(&cmd, "SLAVEOF", "sd", host, host_len, (int)port);
} else {
cmd_len = REDIS_SPPRINTF(&cmd, "SLAVEOF", "ss", "NO", 2, "ONE", 3);
}
REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len);
if (IS_ATOMIC(redis_sock)) {
redis_boolean_response(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock,
NULL, NULL);
}
REDIS_PROCESS_RESPONSE(redis_boolean_response);
}
/* }}} */
/* {{{ proto string Redis::object(key) */
PHP_METHOD(Redis, object)
{
RedisSock *redis_sock;
char *cmd; int cmd_len;
REDIS_REPLY_TYPE rtype;
if ((redis_sock = redis_sock_get(getThis() TSRMLS_CC, 0)) == NULL) {
RETURN_FALSE;
}
if(redis_object_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, &rtype,
&cmd, &cmd_len, NULL, NULL)==FAILURE)
{
RETURN_FALSE;
}
REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len);
if(rtype == TYPE_INT) {
if (IS_ATOMIC(redis_sock)) {
redis_long_response(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock,
NULL, NULL);
}
REDIS_PROCESS_RESPONSE(redis_long_response);
} else {
if (IS_ATOMIC(redis_sock)) {
redis_string_response(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock,
NULL, NULL);
}
REDIS_PROCESS_RESPONSE(redis_string_response);
}
}
/* }}} */
/* {{{ proto string Redis::getOption($option) */
PHP_METHOD(Redis, getOption)
{
RedisSock *redis_sock;
if ((redis_sock = redis_sock_get_instance(getThis() TSRMLS_CC, 0)) == NULL) {
RETURN_FALSE;
}
redis_getoption_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, NULL);
}
/* }}} */
/* {{{ proto string Redis::setOption(string $option, mixed $value) */
PHP_METHOD(Redis, setOption)
{
RedisSock *redis_sock;
if ((redis_sock = redis_sock_get_instance(getThis() TSRMLS_CC, 0)) == NULL) {
RETURN_FALSE;
}
redis_setoption_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, NULL);
}
/* }}} */
/* {{{ proto boolean Redis::config(string op, string key [, mixed value]) */
PHP_METHOD(Redis, config)
{
zval *object;
RedisSock *redis_sock;
char *key = NULL, *val = NULL, *cmd, *op = NULL;
strlen_t key_len, val_len, op_len;
enum {CFG_GET, CFG_SET} mode;
int cmd_len;
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
"Oss|s", &object, redis_ce, &op, &op_len,
&key, &key_len, &val, &val_len) == FAILURE)
{
RETURN_FALSE;
}
/* op must be GET or SET */
if(strncasecmp(op, "GET", 3) == 0) {
mode = CFG_GET;
} else if(strncasecmp(op, "SET", 3) == 0) {
mode = CFG_SET;
} else {
RETURN_FALSE;
}
if ((redis_sock = redis_sock_get(object TSRMLS_CC, 0)) == NULL) {
RETURN_FALSE;
}
if (mode == CFG_GET && val == NULL) {
cmd_len = REDIS_SPPRINTF(&cmd, "CONFIG", "ss", op, op_len, key, key_len);
REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len)
if (IS_ATOMIC(redis_sock)) {
redis_mbulk_reply_zipped_raw(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, NULL, NULL);
}
REDIS_PROCESS_RESPONSE(redis_mbulk_reply_zipped_raw);
} else if(mode == CFG_SET && val != NULL) {
cmd_len = REDIS_SPPRINTF(&cmd, "CONFIG", "sss", op, op_len, key, key_len, val, val_len);
REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len)
if (IS_ATOMIC(redis_sock)) {
redis_boolean_response(
INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, NULL, NULL);
}
REDIS_PROCESS_RESPONSE(redis_boolean_response);
} else {
RETURN_FALSE;
}
}
/* }}} */
/* {{{ proto boolean Redis::slowlog(string arg, [int option]) */
PHP_METHOD(Redis, slowlog) {
zval *object;
RedisSock *redis_sock;
char *arg, *cmd;
int cmd_len;
strlen_t arg_len;
zend_long option = 0;
enum {SLOWLOG_GET, SLOWLOG_LEN, SLOWLOG_RESET} mode;
// Make sure we can get parameters
if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
"Os|l", &object, redis_ce, &arg, &arg_len,
&option) == FAILURE)
{
RETURN_FALSE;
}
/* Figure out what kind of slowlog command we're executing */
if(!strncasecmp(arg, "GET", 3)) {
mode = SLOWLOG_GET;
} else if(!strncasecmp(arg, "LEN", 3)) {
mode = SLOWLOG_LEN;
} else if(!strncasecmp(arg, "RESET", 5)) {
mode = SLOWLOG_RESET;
} else {
/* This command is not valid */
RETURN_FALSE;
}
/* Make sure we can grab our redis socket */
if ((redis_sock = redis_sock_get(object TSRMLS_CC, 0)) == NULL) {
RETURN_FALSE;
}
// Create our command. For everything except SLOWLOG GET (with an arg) it's
// just two parts
if (mode == SLOWLOG_GET && ZEND_NUM_ARGS() == 2) {
cmd_len = REDIS_SPPRINTF(&cmd, "SLOWLOG", "sl", arg, arg_len, option);
} else {
cmd_len = REDIS_SPPRINTF(&cmd, "SLOWLOG", "s", arg, arg_len);
}
/* Kick off our command */
REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len);
if (IS_ATOMIC(redis_sock)) {
if(redis_read_variant_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU,
redis_sock, NULL, NULL) < 0)
{
RETURN_FALSE;
}
}
REDIS_PROCESS_RESPONSE(redis_read_variant_reply);
}
/* {{{ proto Redis::wait(int num_slaves, int ms) }}} */
PHP_METHOD(Redis, wait) {
zval *object;
RedisSock *redis_sock;
zend_long num_slaves, timeout;
char *cmd;
int cmd_len;
/* Make sure arguments are valid */
if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oll",
&object, redis_ce, &num_slaves, &timeout)
==FAILURE)
{
RETURN_FALSE;
}
/* Don't even send this to Redis if our args are negative */
if(num_slaves < 0 || timeout < 0) {
RETURN_FALSE;
}
/* Grab our socket */
if ((redis_sock = redis_sock_get(object TSRMLS_CC, 0)) == NULL) {
RETURN_FALSE;
}
// Construct the command
cmd_len = REDIS_SPPRINTF(&cmd, "WAIT", "ll", num_slaves, timeout);
/* Kick it off */
REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len);
if (IS_ATOMIC(redis_sock)) {
redis_long_response(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, NULL,
NULL);
}
REDIS_PROCESS_RESPONSE(redis_long_response);
}
/* Construct a PUBSUB command */
PHP_REDIS_API int
redis_build_pubsub_cmd(RedisSock *redis_sock, char **ret, PUBSUB_TYPE type,
zval *arg TSRMLS_DC)
{
HashTable *ht_chan;
zval *z_ele;
smart_string cmd = {0};
if (type == PUBSUB_CHANNELS) {
if (arg) {
/* With a pattern */
return REDIS_SPPRINTF(ret, "PUBSUB", "sk", "CHANNELS", sizeof("CHANNELS") - 1,
Z_STRVAL_P(arg), Z_STRLEN_P(arg));
} else {
/* No pattern */
return REDIS_SPPRINTF(ret, "PUBSUB", "s", "CHANNELS", sizeof("CHANNELS") - 1);
}
} else if (type == PUBSUB_NUMSUB) {
ht_chan = Z_ARRVAL_P(arg);
// Add PUBSUB and NUMSUB bits
redis_cmd_init_sstr(&cmd, zend_hash_num_elements(ht_chan)+1, "PUBSUB", sizeof("PUBSUB")-1);
redis_cmd_append_sstr(&cmd, "NUMSUB", sizeof("NUMSUB")-1);
/* Iterate our elements */
ZEND_HASH_FOREACH_VAL(ht_chan, z_ele) {
zend_string *zstr = zval_get_string(z_ele);
redis_cmd_append_sstr_key(&cmd, ZSTR_VAL(zstr), ZSTR_LEN(zstr), redis_sock, NULL);
zend_string_release(zstr);
} ZEND_HASH_FOREACH_END();
/* Set return */
*ret = cmd.c;
return cmd.len;
} else if (type == PUBSUB_NUMPAT) {
return REDIS_SPPRINTF(ret, "PUBSUB", "s", "NUMPAT", sizeof("NUMPAT") - 1);
}
/* Shouldn't ever happen */
return -1;
}
/*
* {{{ proto Redis::pubsub("channels", pattern);
* proto Redis::pubsub("numsub", Array channels);
* proto Redis::pubsub("numpat"); }}}
*/
PHP_METHOD(Redis, pubsub) {
zval *object;
RedisSock *redis_sock;
char *keyword, *cmd;
int cmd_len;
strlen_t kw_len;
PUBSUB_TYPE type;
zval *arg = NULL;
// Parse arguments
if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
"Os|z", &object, redis_ce, &keyword,
&kw_len, &arg)==FAILURE)
{
RETURN_FALSE;
}
/* Validate our sub command keyword, and that we've got proper arguments */
if(!strncasecmp(keyword, "channels", sizeof("channels"))) {
/* One (optional) string argument */
if(arg && Z_TYPE_P(arg) != IS_STRING) {
RETURN_FALSE;
}
type = PUBSUB_CHANNELS;
} else if(!strncasecmp(keyword, "numsub", sizeof("numsub"))) {
/* One array argument */
if(ZEND_NUM_ARGS() < 2 || Z_TYPE_P(arg) != IS_ARRAY ||
zend_hash_num_elements(Z_ARRVAL_P(arg)) == 0)
{
RETURN_FALSE;
}
type = PUBSUB_NUMSUB;
} else if(!strncasecmp(keyword, "numpat", sizeof("numpat"))) {
type = PUBSUB_NUMPAT;
} else {
/* Invalid keyword */
RETURN_FALSE;
}
/* Grab our socket context object */
if ((redis_sock = redis_sock_get(object TSRMLS_CC, 0)) == NULL) {
RETURN_FALSE;
}
/* Construct our "PUBSUB" command */
cmd_len = redis_build_pubsub_cmd(redis_sock, &cmd, type, arg TSRMLS_CC);
REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len);
if(type == PUBSUB_NUMSUB) {
if (IS_ATOMIC(redis_sock)) {
if(redis_mbulk_reply_zipped_keys_int(INTERNAL_FUNCTION_PARAM_PASSTHRU,
redis_sock, NULL, NULL) < 0)
{
RETURN_FALSE;
}
}
REDIS_PROCESS_RESPONSE(redis_mbulk_reply_zipped_keys_int);
} else {
if (IS_ATOMIC(redis_sock)) {
if(redis_read_variant_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU,
redis_sock, NULL, NULL) < 0)
{
RETURN_FALSE;
}
}
REDIS_PROCESS_RESPONSE(redis_read_variant_reply);
}
}
/* {{{ proto variant Redis::eval(string script, [array keys, long num_keys]) */
PHP_METHOD(Redis, eval)
{
REDIS_PROCESS_KW_CMD("EVAL", redis_eval_cmd, redis_read_variant_reply);
}
/* {{{ proto variant Redis::evalsha(string sha1, [array keys, long num_keys]) */
PHP_METHOD(Redis, evalsha) {
REDIS_PROCESS_KW_CMD("EVALSHA", redis_eval_cmd, redis_read_variant_reply);
}
/* {{{ proto status Redis::script('flush')
* {{{ proto status Redis::script('kill')
* {{{ proto string Redis::script('load', lua_script)
* {{{ proto int Reids::script('exists', script_sha1 [, script_sha2, ...])
*/
PHP_METHOD(Redis, script) {
zval *z_args;
RedisSock *redis_sock;
smart_string cmd = {0};
int argc = ZEND_NUM_ARGS();
/* Attempt to grab our socket */
if (argc < 1 || (redis_sock = redis_sock_get(getThis() TSRMLS_CC, 0)) == NULL) {
RETURN_FALSE;
}
/* Allocate an array big enough to store our arguments */
z_args = ecalloc(argc, sizeof(zval));
/* Make sure we can grab our arguments, we have a string directive */
if (zend_get_parameters_array(ht, argc, z_args) == FAILURE ||
redis_build_script_cmd(&cmd, argc, z_args) == NULL
) {
efree(z_args);
RETURN_FALSE;
}
/* Free our alocated arguments */
efree(z_args);
// Kick off our request
REDIS_PROCESS_REQUEST(redis_sock, cmd.c, cmd.len);
if (IS_ATOMIC(redis_sock)) {
if(redis_read_variant_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU,
redis_sock, NULL, NULL) < 0)
{
RETURN_FALSE;
}
}
REDIS_PROCESS_RESPONSE(redis_read_variant_reply);
}
/* {{{ proto DUMP key */
PHP_METHOD(Redis, dump) {
REDIS_PROCESS_KW_CMD("DUMP", redis_key_cmd, redis_string_response);
}
/* }}} */
/* {{{ proto Redis::restore(ttl, key, value) */
PHP_METHOD(Redis, restore) {
REDIS_PROCESS_KW_CMD("RESTORE", redis_key_long_val_cmd,
redis_boolean_response);
}
/* }}} */
/* {{{ proto Redis::debug(string key) */
PHP_METHOD(Redis, debug) {
REDIS_PROCESS_KW_CMD("DEBUG", redis_key_cmd, redis_string_response);
}
/* }}} */
/* {{{ proto Redis::migrate(host port key dest-db timeout [bool copy,
* bool replace]) */
PHP_METHOD(Redis, migrate) {
REDIS_PROCESS_CMD(migrate, redis_boolean_response);
}
/* {{{ proto Redis::_prefix(key) */
PHP_METHOD(Redis, _prefix) {
RedisSock *redis_sock;
if ((redis_sock = redis_sock_get_instance(getThis() TSRMLS_CC, 0)) == NULL) {
RETURN_FALSE;
}
redis_prefix_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock);
}
/* {{{ proto Redis::_serialize(value) */
PHP_METHOD(Redis, _serialize) {
RedisSock *redis_sock;
// Grab socket
if ((redis_sock = redis_sock_get_instance(getThis() TSRMLS_CC, 0)) == NULL) {
RETURN_FALSE;
}
redis_serialize_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock);
}
/* {{{ proto Redis::_unserialize(value) */
PHP_METHOD(Redis, _unserialize) {
RedisSock *redis_sock;
// Grab socket
if ((redis_sock = redis_sock_get_instance(getThis() TSRMLS_CC, 0)) == NULL) {
RETURN_FALSE;
}
redis_unserialize_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock,
redis_exception_ce);
}
/* {{{ proto Redis::getLastError() */
PHP_METHOD(Redis, getLastError) {
zval *object;
RedisSock *redis_sock;
// Grab our object
if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
&object, redis_ce) == FAILURE)
{
RETURN_FALSE;
}
// Grab socket
if ((redis_sock = redis_sock_get_instance(object TSRMLS_CC, 0)) == NULL) {
RETURN_FALSE;
}
/* Return our last error or NULL if we don't have one */
if (redis_sock->err) {
RETURN_STRINGL(ZSTR_VAL(redis_sock->err), ZSTR_LEN(redis_sock->err));
}
RETURN_NULL();
}
/* {{{ proto Redis::clearLastError() */
PHP_METHOD(Redis, clearLastError) {
zval *object;
RedisSock *redis_sock;
// Grab our object
if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
&object, redis_ce) == FAILURE)
{
RETURN_FALSE;
}
// Grab socket
if ((redis_sock = redis_sock_get_instance(object TSRMLS_CC, 0)) == NULL) {
RETURN_FALSE;
}
// Clear error message
if (redis_sock->err) {
zend_string_release(redis_sock->err);
redis_sock->err = NULL;
}
RETURN_TRUE;
}
/*
* {{{ proto long Redis::getMode()
*/
PHP_METHOD(Redis, getMode) {
zval *object;
RedisSock *redis_sock;
/* Grab our object */
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &object, redis_ce) == FAILURE) {
RETURN_FALSE;
}
/* Grab socket */
if ((redis_sock = redis_sock_get_instance(object TSRMLS_CC, 0)) == NULL) {
RETURN_FALSE;
}
if (IS_PIPELINE(redis_sock)) {
RETVAL_LONG(PIPELINE);
} else if (IS_MULTI(redis_sock)) {
RETVAL_LONG(MULTI);
} else {
RETVAL_LONG(ATOMIC);
}
}
/* {{{ proto Redis::time() */
PHP_METHOD(Redis, time) {
REDIS_PROCESS_KW_CMD("TIME", redis_empty_cmd, redis_mbulk_reply_raw);
}
/* {{{ proto array Redis::role() */
PHP_METHOD(Redis, role) {
REDIS_PROCESS_KW_CMD("ROLE", redis_empty_cmd, redis_read_variant_reply);
}
/*
* Introspection stuff
*/
/* {{{ proto Redis::IsConnected */
PHP_METHOD(Redis, isConnected) {
RedisSock *redis_sock;
if((redis_sock = redis_sock_get_connected(INTERNAL_FUNCTION_PARAM_PASSTHRU))) {
RETURN_TRUE;
} else {
RETURN_FALSE;
}
}
/* {{{ proto Redis::getHost() */
PHP_METHOD(Redis, getHost) {
RedisSock *redis_sock;
if((redis_sock = redis_sock_get_connected(INTERNAL_FUNCTION_PARAM_PASSTHRU))) {
RETURN_STRINGL(ZSTR_VAL(redis_sock->host), ZSTR_LEN(redis_sock->host));
} else {
RETURN_FALSE;
}
}
/* {{{ proto Redis::getPort() */
PHP_METHOD(Redis, getPort) {
RedisSock *redis_sock;
if((redis_sock = redis_sock_get_connected(INTERNAL_FUNCTION_PARAM_PASSTHRU))) {
/* Return our port */
RETURN_LONG(redis_sock->port);
} else {
RETURN_FALSE;
}
}
/* {{{ proto Redis::getDBNum */
PHP_METHOD(Redis, getDBNum) {
RedisSock *redis_sock;
if((redis_sock = redis_sock_get_connected(INTERNAL_FUNCTION_PARAM_PASSTHRU))) {
/* Return our db number */
RETURN_LONG(redis_sock->dbNumber);
} else {
RETURN_FALSE;
}
}
/* {{{ proto Redis::getTimeout */
PHP_METHOD(Redis, getTimeout) {
RedisSock *redis_sock;
if((redis_sock = redis_sock_get_connected(INTERNAL_FUNCTION_PARAM_PASSTHRU))) {
RETURN_DOUBLE(redis_sock->timeout);
} else {
RETURN_FALSE;
}
}
/* {{{ proto Redis::getReadTimeout */
PHP_METHOD(Redis, getReadTimeout) {
RedisSock *redis_sock;
if((redis_sock = redis_sock_get_connected(INTERNAL_FUNCTION_PARAM_PASSTHRU))) {
RETURN_DOUBLE(redis_sock->read_timeout);
} else {
RETURN_FALSE;
}
}
/* {{{ proto Redis::getPersistentID */
PHP_METHOD(Redis, getPersistentID) {
RedisSock *redis_sock;
if ((redis_sock = redis_sock_get_connected(INTERNAL_FUNCTION_PARAM_PASSTHRU)) == NULL) {
RETURN_FALSE;
} else if (redis_sock->persistent_id == NULL) {
RETURN_NULL();
}
RETURN_STRINGL(ZSTR_VAL(redis_sock->persistent_id), ZSTR_LEN(redis_sock->persistent_id));
}
/* {{{ proto Redis::getAuth */
PHP_METHOD(Redis, getAuth) {
RedisSock *redis_sock;
if ((redis_sock = redis_sock_get_connected(INTERNAL_FUNCTION_PARAM_PASSTHRU)) == NULL) {
RETURN_FALSE;
} else if (redis_sock->auth == NULL) {
RETURN_NULL();
}
RETURN_STRINGL(ZSTR_VAL(redis_sock->auth), ZSTR_LEN(redis_sock->auth));
}
/*
* $redis->client('list');
* $redis->client('kill', <ip:port>);
* $redis->client('setname', <name>);
* $redis->client('getname');
*/
PHP_METHOD(Redis, client) {
zval *object;
RedisSock *redis_sock;
char *cmd, *opt = NULL, *arg = NULL;
strlen_t opt_len, arg_len;
int cmd_len;
// Parse our method parameters
if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
"Os|s", &object, redis_ce, &opt, &opt_len,
&arg, &arg_len) == FAILURE)
{
RETURN_FALSE;
}
/* Grab our socket */
if ((redis_sock = redis_sock_get(object TSRMLS_CC, 0)) == NULL) {
RETURN_FALSE;
}
/* Build our CLIENT command */
if (ZEND_NUM_ARGS() == 2) {
cmd_len = REDIS_SPPRINTF(&cmd, "CLIENT", "ss", opt, opt_len, arg, arg_len);
} else {
cmd_len = REDIS_SPPRINTF(&cmd, "CLIENT", "s", opt, opt_len);
}
/* Execute our queue command */
REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len);
/* We handle CLIENT LIST with a custom response function */
if(!strncasecmp(opt, "list", 4)) {
if (IS_ATOMIC(redis_sock)) {
redis_client_list_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU,redis_sock,
NULL);
}
REDIS_PROCESS_RESPONSE(redis_client_list_reply);
} else {
if (IS_ATOMIC(redis_sock)) {
redis_read_variant_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU,
redis_sock,NULL,NULL);
}
REDIS_PROCESS_RESPONSE(redis_read_variant_reply);
}
}
/* {{{ proto mixed Redis::rawcommand(string $command, [ $arg1 ... $argN]) */
PHP_METHOD(Redis, rawcommand) {
int argc = ZEND_NUM_ARGS(), cmd_len;
char *cmd = NULL;
RedisSock *redis_sock;
zval *z_args;
/* Sanity check on arguments */
if (argc < 1) {
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Must pass at least one command keyword");
RETURN_FALSE;
}
z_args = emalloc(argc * sizeof(zval));
if (zend_get_parameters_array(ht, argc, z_args) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Internal PHP error parsing arguments");
efree(z_args);
RETURN_FALSE;
} else if (redis_build_raw_cmd(z_args, argc, &cmd, &cmd_len TSRMLS_CC) < 0 ||
(redis_sock = redis_sock_get(getThis() TSRMLS_CC, 0)) == NULL
) {
if (cmd) efree(cmd);
efree(z_args);
RETURN_FALSE;
}
/* Clean up command array */
efree(z_args);
/* Execute our command */
REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len);
if (IS_ATOMIC(redis_sock)) {
redis_read_variant_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU,redis_sock,NULL,NULL);
}
REDIS_PROCESS_RESPONSE(redis_read_variant_reply);
}
/* }}} */
/* {{{ proto array Redis::command()
* proto array Redis::command('info', string cmd)
* proto array Redis::command('getkeys', array cmd_args) */
PHP_METHOD(Redis, command) {
REDIS_PROCESS_CMD(command, redis_read_variant_reply);
}
/* }}} */
/* Helper to format any combination of SCAN arguments */
PHP_REDIS_API int
redis_build_scan_cmd(char **cmd, REDIS_SCAN_TYPE type, char *key, int key_len,
int iter, char *pattern, int pattern_len, int count)
{
smart_string cmdstr = {0};
char *keyword;
int argc;
/* Count our arguments +1 for key if it's got one, and + 2 for pattern */
/* or count given that they each carry keywords with them. */
argc = 1 + (key_len > 0) + (pattern_len > 0 ? 2 : 0) + (count > 0 ? 2 : 0);
/* Turn our type into a keyword */
switch(type) {
case TYPE_SCAN:
keyword = "SCAN";
break;
case TYPE_SSCAN:
keyword = "SSCAN";
break;
case TYPE_HSCAN:
keyword = "HSCAN";
break;
case TYPE_ZSCAN:
default:
keyword = "ZSCAN";
break;
}
/* Start the command */
redis_cmd_init_sstr(&cmdstr, argc, keyword, strlen(keyword));
if (key_len) redis_cmd_append_sstr(&cmdstr, key, key_len);
redis_cmd_append_sstr_int(&cmdstr, iter);
/* Append COUNT if we've got it */
if(count) {
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "COUNT");
redis_cmd_append_sstr_int(&cmdstr, count);
}
/* Append MATCH if we've got it */
if(pattern_len) {
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "MATCH");
redis_cmd_append_sstr(&cmdstr, pattern, pattern_len);
}
/* Return our command length */
*cmd = cmdstr.c;
return cmdstr.len;
}
/* {{{ proto redis::scan(&$iterator, [pattern, [count]]) */
PHP_REDIS_API void
generic_scan_cmd(INTERNAL_FUNCTION_PARAMETERS, REDIS_SCAN_TYPE type) {
zval *object, *z_iter;
RedisSock *redis_sock;
HashTable *hash;
char *pattern = NULL, *cmd, *key = NULL;
int cmd_len, num_elements, key_free = 0;
strlen_t key_len = 0, pattern_len = 0;
zend_long count = 0, iter;
/* Different prototype depending on if this is a key based scan */
if(type != TYPE_SCAN) {
// Requires a key
if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
"Osz/|s!l", &object, redis_ce, &key,
&key_len, &z_iter, &pattern,
&pattern_len, &count)==FAILURE)
{
RETURN_FALSE;
}
} else {
// Doesn't require a key
if(zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
"Oz/|s!l", &object, redis_ce, &z_iter,
&pattern, &pattern_len, &count)
== FAILURE)
{
RETURN_FALSE;
}
}
/* Grab our socket */
if ((redis_sock = redis_sock_get(object TSRMLS_CC, 0)) == NULL) {
RETURN_FALSE;
}
/* Calling this in a pipeline makes no sense */
if (!IS_ATOMIC(redis_sock)) {
php_error_docref(NULL TSRMLS_CC, E_ERROR,
"Can't call SCAN commands in multi or pipeline mode!");
RETURN_FALSE;
}
// The iterator should be passed in as NULL for the first iteration, but we
// can treat any NON LONG value as NULL for these purposes as we've
// seperated the variable anyway.
if(Z_TYPE_P(z_iter) != IS_LONG || Z_LVAL_P(z_iter) < 0) {
/* Convert to long */
convert_to_long(z_iter);
iter = 0;
} else if(Z_LVAL_P(z_iter) != 0) {
/* Update our iterator value for the next passthru */
iter = Z_LVAL_P(z_iter);
} else {
/* We're done, back to iterator zero */
RETURN_FALSE;
}
/* Prefix our key if we've got one and we have a prefix set */
if(key_len) {
key_free = redis_key_prefix(redis_sock, &key, &key_len);
}
/**
* Redis can return to us empty keys, especially in the case where there
* are a large number of keys to scan, and we're matching against a
* pattern. phpredis can be set up to abstract this from the user, by
* setting OPT_SCAN to REDIS_SCAN_RETRY. Otherwise we will return empty
* keys and the user will need to make subsequent calls with an updated
* iterator.
*/
do {
/* Free our previous reply if we're back in the loop. We know we are
* if our return_value is an array */
if (Z_TYPE_P(return_value) == IS_ARRAY) {
zval_dtor(return_value);
ZVAL_NULL(return_value);
}
// Format our SCAN command
cmd_len = redis_build_scan_cmd(&cmd, type, key, key_len, (int)iter,
pattern, pattern_len, count);
/* Execute our command getting our new iterator value */
REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len);
if(redis_sock_read_scan_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU,
redis_sock,type,&iter) < 0)
{
if(key_free) efree(key);
RETURN_FALSE;
}
/* Get the number of elements */
hash = Z_ARRVAL_P(return_value);
num_elements = zend_hash_num_elements(hash);
} while(redis_sock->scan == REDIS_SCAN_RETRY && iter != 0 &&
num_elements == 0);
/* Free our key if it was prefixed */
if(key_free) efree(key);
/* Update our iterator reference */
Z_LVAL_P(z_iter) = iter;
}
PHP_METHOD(Redis, scan) {
generic_scan_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, TYPE_SCAN);
}
PHP_METHOD(Redis, hscan) {
generic_scan_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, TYPE_HSCAN);
}
PHP_METHOD(Redis, sscan) {
generic_scan_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, TYPE_SSCAN);
}
PHP_METHOD(Redis, zscan) {
generic_scan_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, TYPE_ZSCAN);
}
/*
* HyperLogLog based commands
*/
/* {{{ proto Redis::pfAdd(string key, array elements) }}} */
PHP_METHOD(Redis, pfadd) {
REDIS_PROCESS_CMD(pfadd, redis_long_response);
}
/* {{{ proto Redis::pfCount(string key) }}}*/
PHP_METHOD(Redis, pfcount) {
REDIS_PROCESS_CMD(pfcount, redis_long_response);
}
/* {{{ proto Redis::pfMerge(string dstkey, array keys) }}}*/
PHP_METHOD(Redis, pfmerge) {
REDIS_PROCESS_CMD(pfmerge, redis_boolean_response);
}
/*
* Geo commands
*/
PHP_METHOD(Redis, geoadd) {
REDIS_PROCESS_KW_CMD("GEOADD", redis_key_varval_cmd, redis_long_response);
}
PHP_METHOD(Redis, geohash) {
REDIS_PROCESS_KW_CMD("GEOHASH", redis_key_varval_cmd, redis_mbulk_reply_raw);
}
PHP_METHOD(Redis, geopos) {
REDIS_PROCESS_KW_CMD("GEOPOS", redis_key_varval_cmd, redis_read_variant_reply);
}
PHP_METHOD(Redis, geodist) {
REDIS_PROCESS_CMD(geodist, redis_bulk_double_response);
}
PHP_METHOD(Redis, georadius) {
REDIS_PROCESS_CMD(georadius, redis_read_variant_reply);
}
PHP_METHOD(Redis, georadiusbymember) {
REDIS_PROCESS_CMD(georadiusbymember, redis_read_variant_reply);
}
/* vim: set tabstop=4 softtabstop=4 expandtab shiftwidth=4: */
1
https://gitee.com/tools/phpredis.git
git@gitee.com:tools/phpredis.git
tools
phpredis
phpredis
master

搜索帮助