Adding Missing filters to CLIENT LIST and Dedup Parsing (#1401)
Adds filter options to CLIENT LIST: * USER <username> Return clients authenticated by <username>. * ADDR <ip:port> Return clients connected from the specified address. * LADDR <ip:port> Return clients connected to the specified local address. * SKIPME (YES|NO) Exclude the current client from the list (default: no). * MAXAGE <maxage> Only list connections older than the specified age. Modifies the ID filter to CLIENT KILL to allow multiple IDs * ID <client-id> [<client-id>...] Kill connections by client ids. This makes CLIENT LIST and CLIENT KILL accept the same options. For backward compatibility, the default value for SKIPME is NO for CLIENT LIST and YES for CLIENT KILL. The MAXAGE comes from CLIENT KILL, where it *keeps* clients with the given max age and kills the older ones. This logic becomes weird for CLIENT LIST, but is kept for similary with CLIENT KILL, for the use case of first testing manually using CLIENT LIST, and then running CLIENT KILL with the same filters. The `ID client-id [client-id ...]` no longer needs to be the last filter. The parsing logic determines if an argument is an ID or not based on whether it can be parsed as an integer or not. Partly addresses: #668 --------- Signed-off-by: Sarthak Aggarwal <sarthagg@amazon.com>
This commit is contained in:
parent
c5a1585547
commit
6a8f068e36
@ -1289,6 +1289,7 @@ commandHistory CLIENT_KILL_History[] = {
|
||||
{"6.2.0","`LADDR` option."},
|
||||
{"8.0.0","`MAXAGE` option."},
|
||||
{"8.0.0","Replaced `master` `TYPE` with `primary`. `master` still supported for backward compatibility."},
|
||||
{"8.1.0","`ID` option accepts multiple IDs."},
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -1320,7 +1321,7 @@ struct COMMAND_ARG CLIENT_KILL_filter_new_format_skipme_Subargs[] = {
|
||||
|
||||
/* CLIENT KILL filter new_format argument table */
|
||||
struct COMMAND_ARG CLIENT_KILL_filter_new_format_Subargs[] = {
|
||||
{MAKE_ARG("client-id",ARG_TYPE_INTEGER,-1,"ID",NULL,"2.8.12",CMD_ARG_OPTIONAL,0,NULL)},
|
||||
{MAKE_ARG("client-id",ARG_TYPE_INTEGER,-1,"ID",NULL,"2.8.12",CMD_ARG_OPTIONAL|CMD_ARG_MULTIPLE,0,NULL)},
|
||||
{MAKE_ARG("client-type",ARG_TYPE_ONEOF,-1,"TYPE",NULL,"2.8.12",CMD_ARG_OPTIONAL,6,NULL),.subargs=CLIENT_KILL_filter_new_format_client_type_Subargs},
|
||||
{MAKE_ARG("username",ARG_TYPE_STRING,-1,"USER",NULL,NULL,CMD_ARG_OPTIONAL,0,NULL)},
|
||||
{MAKE_ARG("addr",ARG_TYPE_STRING,-1,"ADDR",NULL,NULL,CMD_ARG_OPTIONAL,0,NULL),.display_text="ip:port"},
|
||||
@ -1352,6 +1353,7 @@ commandHistory CLIENT_LIST_History[] = {
|
||||
{"7.0.0","Added `resp`, `multi-mem`, `rbs` and `rbp` fields."},
|
||||
{"7.0.3","Added `ssub` field."},
|
||||
{"8.0.0","Replaced `master` `TYPE` with `primary`. `master` still supported for backward compatibility."},
|
||||
{"8.1.0","Added filters USER, ADDR, LADDR, SKIPME, and MAXAGE"},
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -1375,10 +1377,21 @@ struct COMMAND_ARG CLIENT_LIST_client_type_Subargs[] = {
|
||||
{MAKE_ARG("pubsub",ARG_TYPE_PURE_TOKEN,-1,"PUBSUB",NULL,NULL,CMD_ARG_NONE,0,NULL)},
|
||||
};
|
||||
|
||||
/* CLIENT LIST skipme argument table */
|
||||
struct COMMAND_ARG CLIENT_LIST_skipme_Subargs[] = {
|
||||
{MAKE_ARG("yes",ARG_TYPE_PURE_TOKEN,-1,"YES",NULL,NULL,CMD_ARG_NONE,0,NULL)},
|
||||
{MAKE_ARG("no",ARG_TYPE_PURE_TOKEN,-1,"NO",NULL,NULL,CMD_ARG_NONE,0,NULL)},
|
||||
};
|
||||
|
||||
/* CLIENT LIST argument table */
|
||||
struct COMMAND_ARG CLIENT_LIST_Args[] = {
|
||||
{MAKE_ARG("client-type",ARG_TYPE_ONEOF,-1,"TYPE",NULL,"5.0.0",CMD_ARG_OPTIONAL,4,NULL),.subargs=CLIENT_LIST_client_type_Subargs},
|
||||
{MAKE_ARG("client-id",ARG_TYPE_INTEGER,-1,"ID",NULL,"6.2.0",CMD_ARG_OPTIONAL|CMD_ARG_MULTIPLE,0,NULL)},
|
||||
{MAKE_ARG("username",ARG_TYPE_STRING,-1,"USER",NULL,"8.1.0",CMD_ARG_OPTIONAL,0,NULL)},
|
||||
{MAKE_ARG("addr",ARG_TYPE_STRING,-1,"ADDR",NULL,"8.1.0",CMD_ARG_OPTIONAL,0,NULL),.display_text="ip:port"},
|
||||
{MAKE_ARG("laddr",ARG_TYPE_STRING,-1,"LADDR",NULL,"8.1.0",CMD_ARG_OPTIONAL,0,NULL),.display_text="ip:port"},
|
||||
{MAKE_ARG("skipme",ARG_TYPE_ONEOF,-1,"SKIPME",NULL,"8.1.0",CMD_ARG_OPTIONAL,2,NULL),.subargs=CLIENT_LIST_skipme_Subargs},
|
||||
{MAKE_ARG("maxage",ARG_TYPE_INTEGER,-1,"MAXAGE",NULL,"8.1.0",CMD_ARG_OPTIONAL,0,NULL)},
|
||||
};
|
||||
|
||||
/********** CLIENT NO_EVICT ********************/
|
||||
@ -1652,26 +1665,26 @@ struct COMMAND_ARG CLIENT_UNBLOCK_Args[] = {
|
||||
|
||||
/* CLIENT command table */
|
||||
struct COMMAND_STRUCT CLIENT_Subcommands[] = {
|
||||
{MAKE_CMD("caching","Instructs the server whether to track the keys in the next request.","O(1)","6.0.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_CACHING_History,0,CLIENT_CACHING_Tips,0,clientCommand,3,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,CLIENT_CACHING_Keyspecs,0,NULL,1),.args=CLIENT_CACHING_Args},
|
||||
{MAKE_CMD("capa","A client claims its capability.","O(1)","8.0.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_CAPA_History,0,CLIENT_CAPA_Tips,0,clientCommand,-3,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE,ACL_CATEGORY_CONNECTION,CLIENT_CAPA_Keyspecs,0,NULL,1),.args=CLIENT_CAPA_Args},
|
||||
{MAKE_CMD("getname","Returns the name of the connection.","O(1)","2.6.9",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_GETNAME_History,0,CLIENT_GETNAME_Tips,0,clientCommand,2,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,CLIENT_GETNAME_Keyspecs,0,NULL,0)},
|
||||
{MAKE_CMD("getredir","Returns the client ID to which the connection's tracking notifications are redirected.","O(1)","6.0.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_GETREDIR_History,0,CLIENT_GETREDIR_Tips,0,clientCommand,2,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,CLIENT_GETREDIR_Keyspecs,0,NULL,0)},
|
||||
{MAKE_CMD("help","Returns helpful text about the different subcommands.","O(1)","5.0.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_HELP_History,0,CLIENT_HELP_Tips,0,clientCommand,2,CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,CLIENT_HELP_Keyspecs,0,NULL,0)},
|
||||
{MAKE_CMD("id","Returns the unique client ID of the connection.","O(1)","5.0.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_ID_History,0,CLIENT_ID_Tips,0,clientCommand,2,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,CLIENT_ID_Keyspecs,0,NULL,0)},
|
||||
{MAKE_CMD("import-source","Mark this client as an import source when server is in import mode.","O(1)","8.1.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_IMPORT_SOURCE_History,0,CLIENT_IMPORT_SOURCE_Tips,0,clientCommand,3,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE,ACL_CATEGORY_CONNECTION,CLIENT_IMPORT_SOURCE_Keyspecs,0,NULL,1),.args=CLIENT_IMPORT_SOURCE_Args},
|
||||
{MAKE_CMD("info","Returns information about the connection.","O(1)","6.2.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_INFO_History,0,CLIENT_INFO_Tips,1,clientCommand,2,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,CLIENT_INFO_Keyspecs,0,NULL,0)},
|
||||
{MAKE_CMD("kill","Terminates open connections.","O(N) where N is the number of client connections","2.4.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_KILL_History,7,CLIENT_KILL_Tips,0,clientCommand,-3,CMD_ADMIN|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,CLIENT_KILL_Keyspecs,0,NULL,1),.args=CLIENT_KILL_Args},
|
||||
{MAKE_CMD("list","Lists open connections.","O(N) where N is the number of client connections","2.4.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_LIST_History,7,CLIENT_LIST_Tips,1,clientCommand,-2,CMD_ADMIN|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,CLIENT_LIST_Keyspecs,0,NULL,2),.args=CLIENT_LIST_Args},
|
||||
{MAKE_CMD("no-evict","Sets the client eviction mode of the connection.","O(1)","7.0.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_NO_EVICT_History,0,CLIENT_NO_EVICT_Tips,0,clientCommand,3,CMD_ADMIN|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,CLIENT_NO_EVICT_Keyspecs,0,NULL,1),.args=CLIENT_NO_EVICT_Args},
|
||||
{MAKE_CMD("no-touch","Controls whether commands sent by the client affect the LRU/LFU of accessed keys.","O(1)","7.2.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_NO_TOUCH_History,0,CLIENT_NO_TOUCH_Tips,0,clientCommand,3,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE,ACL_CATEGORY_CONNECTION,CLIENT_NO_TOUCH_Keyspecs,0,NULL,1),.args=CLIENT_NO_TOUCH_Args},
|
||||
{MAKE_CMD("pause","Suspends commands processing.","O(1)","3.0.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_PAUSE_History,1,CLIENT_PAUSE_Tips,0,clientCommand,-3,CMD_ADMIN|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,CLIENT_PAUSE_Keyspecs,0,NULL,2),.args=CLIENT_PAUSE_Args},
|
||||
{MAKE_CMD("reply","Instructs the server whether to reply to commands.","O(1)","3.2.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_REPLY_History,0,CLIENT_REPLY_Tips,0,clientCommand,3,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,CLIENT_REPLY_Keyspecs,0,NULL,1),.args=CLIENT_REPLY_Args},
|
||||
{MAKE_CMD("caching","Instructs the server whether to track the keys in the next request.","O(1)","6.0.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_CACHING_History,0,CLIENT_CACHING_Tips,0,clientCachingCommand,3,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,CLIENT_CACHING_Keyspecs,0,NULL,1),.args=CLIENT_CACHING_Args},
|
||||
{MAKE_CMD("capa","A client claims its capability.","O(1)","8.0.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_CAPA_History,0,CLIENT_CAPA_Tips,0,clientCapaCommand,-3,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE,ACL_CATEGORY_CONNECTION,CLIENT_CAPA_Keyspecs,0,NULL,1),.args=CLIENT_CAPA_Args},
|
||||
{MAKE_CMD("getname","Returns the name of the connection.","O(1)","2.6.9",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_GETNAME_History,0,CLIENT_GETNAME_Tips,0,clientGetNameCommand,2,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,CLIENT_GETNAME_Keyspecs,0,NULL,0)},
|
||||
{MAKE_CMD("getredir","Returns the client ID to which the connection's tracking notifications are redirected.","O(1)","6.0.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_GETREDIR_History,0,CLIENT_GETREDIR_Tips,0,clientGetredirCommand,2,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,CLIENT_GETREDIR_Keyspecs,0,NULL,0)},
|
||||
{MAKE_CMD("help","Returns helpful text about the different subcommands.","O(1)","5.0.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_HELP_History,0,CLIENT_HELP_Tips,0,clientHelpCommand,2,CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,CLIENT_HELP_Keyspecs,0,NULL,0)},
|
||||
{MAKE_CMD("id","Returns the unique client ID of the connection.","O(1)","5.0.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_ID_History,0,CLIENT_ID_Tips,0,clientIDCommand,2,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,CLIENT_ID_Keyspecs,0,NULL,0)},
|
||||
{MAKE_CMD("import-source","Mark this client as an import source when server is in import mode.","O(1)","8.1.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_IMPORT_SOURCE_History,0,CLIENT_IMPORT_SOURCE_Tips,0,clientImportSourceCommand,3,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE,ACL_CATEGORY_CONNECTION,CLIENT_IMPORT_SOURCE_Keyspecs,0,NULL,1),.args=CLIENT_IMPORT_SOURCE_Args},
|
||||
{MAKE_CMD("info","Returns information about the connection.","O(1)","6.2.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_INFO_History,0,CLIENT_INFO_Tips,1,clientInfoCommand,2,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,CLIENT_INFO_Keyspecs,0,NULL,0)},
|
||||
{MAKE_CMD("kill","Terminates open connections.","O(N) where N is the number of client connections","2.4.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_KILL_History,8,CLIENT_KILL_Tips,0,clientKillCommand,-3,CMD_ADMIN|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,CLIENT_KILL_Keyspecs,0,NULL,1),.args=CLIENT_KILL_Args},
|
||||
{MAKE_CMD("list","Lists open connections.","O(N) where N is the number of client connections","2.4.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_LIST_History,8,CLIENT_LIST_Tips,1,clientListCommand,-2,CMD_ADMIN|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,CLIENT_LIST_Keyspecs,0,NULL,7),.args=CLIENT_LIST_Args},
|
||||
{MAKE_CMD("no-evict","Sets the client eviction mode of the connection.","O(1)","7.0.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_NO_EVICT_History,0,CLIENT_NO_EVICT_Tips,0,clientNoEvictCommand,3,CMD_ADMIN|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,CLIENT_NO_EVICT_Keyspecs,0,NULL,1),.args=CLIENT_NO_EVICT_Args},
|
||||
{MAKE_CMD("no-touch","Controls whether commands sent by the client affect the LRU/LFU of accessed keys.","O(1)","7.2.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_NO_TOUCH_History,0,CLIENT_NO_TOUCH_Tips,0,clientNoTouchCommand,3,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE,ACL_CATEGORY_CONNECTION,CLIENT_NO_TOUCH_Keyspecs,0,NULL,1),.args=CLIENT_NO_TOUCH_Args},
|
||||
{MAKE_CMD("pause","Suspends commands processing.","O(1)","3.0.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_PAUSE_History,1,CLIENT_PAUSE_Tips,0,clientPauseCommand,-3,CMD_ADMIN|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,CLIENT_PAUSE_Keyspecs,0,NULL,2),.args=CLIENT_PAUSE_Args},
|
||||
{MAKE_CMD("reply","Instructs the server whether to reply to commands.","O(1)","3.2.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_REPLY_History,0,CLIENT_REPLY_Tips,0,clientReplyCommand,3,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,CLIENT_REPLY_Keyspecs,0,NULL,1),.args=CLIENT_REPLY_Args},
|
||||
{MAKE_CMD("setinfo","Sets information specific to the client or connection.","O(1)","7.2.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_SETINFO_History,0,CLIENT_SETINFO_Tips,2,clientSetinfoCommand,4,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,CLIENT_SETINFO_Keyspecs,0,NULL,1),.args=CLIENT_SETINFO_Args},
|
||||
{MAKE_CMD("setname","Sets the connection name.","O(1)","2.6.9",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_SETNAME_History,0,CLIENT_SETNAME_Tips,2,clientCommand,3,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,CLIENT_SETNAME_Keyspecs,0,NULL,1),.args=CLIENT_SETNAME_Args},
|
||||
{MAKE_CMD("tracking","Controls server-assisted client-side caching for the connection.","O(1). Some options may introduce additional complexity.","6.0.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_TRACKING_History,0,CLIENT_TRACKING_Tips,0,clientCommand,-3,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,CLIENT_TRACKING_Keyspecs,0,NULL,7),.args=CLIENT_TRACKING_Args},
|
||||
{MAKE_CMD("trackinginfo","Returns information about server-assisted client-side caching for the connection.","O(1)","6.2.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_TRACKINGINFO_History,0,CLIENT_TRACKINGINFO_Tips,0,clientCommand,2,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,CLIENT_TRACKINGINFO_Keyspecs,0,NULL,0)},
|
||||
{MAKE_CMD("unblock","Unblocks a client blocked by a blocking command from a different connection.","O(log N) where N is the number of client connections","5.0.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_UNBLOCK_History,0,CLIENT_UNBLOCK_Tips,0,clientCommand,-3,CMD_ADMIN|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,CLIENT_UNBLOCK_Keyspecs,0,NULL,2),.args=CLIENT_UNBLOCK_Args},
|
||||
{MAKE_CMD("unpause","Resumes processing commands from paused clients.","O(N) Where N is the number of paused clients","6.2.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_UNPAUSE_History,0,CLIENT_UNPAUSE_Tips,0,clientCommand,2,CMD_ADMIN|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,CLIENT_UNPAUSE_Keyspecs,0,NULL,0)},
|
||||
{MAKE_CMD("setname","Sets the connection name.","O(1)","2.6.9",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_SETNAME_History,0,CLIENT_SETNAME_Tips,2,clientSetNameCommand,3,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,CLIENT_SETNAME_Keyspecs,0,NULL,1),.args=CLIENT_SETNAME_Args},
|
||||
{MAKE_CMD("tracking","Controls server-assisted client-side caching for the connection.","O(1). Some options may introduce additional complexity.","6.0.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_TRACKING_History,0,CLIENT_TRACKING_Tips,0,clientTrackingCommand,-3,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,CLIENT_TRACKING_Keyspecs,0,NULL,7),.args=CLIENT_TRACKING_Args},
|
||||
{MAKE_CMD("trackinginfo","Returns information about server-assisted client-side caching for the connection.","O(1)","6.2.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_TRACKINGINFO_History,0,CLIENT_TRACKINGINFO_Tips,0,clientTrackingInfoCommand,2,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,CLIENT_TRACKINGINFO_Keyspecs,0,NULL,0)},
|
||||
{MAKE_CMD("unblock","Unblocks a client blocked by a blocking command from a different connection.","O(log N) where N is the number of client connections","5.0.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_UNBLOCK_History,0,CLIENT_UNBLOCK_Tips,0,clientUnblockCommand,-3,CMD_ADMIN|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,CLIENT_UNBLOCK_Keyspecs,0,NULL,2),.args=CLIENT_UNBLOCK_Args},
|
||||
{MAKE_CMD("unpause","Resumes processing commands from paused clients.","O(N) Where N is the number of paused clients","6.2.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_UNPAUSE_History,0,CLIENT_UNPAUSE_Tips,0,clientUnpauseCommand,2,CMD_ADMIN|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,CLIENT_UNPAUSE_Keyspecs,0,NULL,0)},
|
||||
{0}
|
||||
};
|
||||
|
||||
@ -10910,7 +10923,7 @@ struct COMMAND_STRUCT serverCommandTable[] = {
|
||||
{MAKE_CMD("readwrite","Enables read-write queries for a connection to a Valkey replica node.","O(1)","3.0.0",CMD_DOC_NONE,NULL,NULL,"cluster",COMMAND_GROUP_CLUSTER,READWRITE_History,0,READWRITE_Tips,0,readwriteCommand,1,CMD_FAST|CMD_LOADING|CMD_STALE,ACL_CATEGORY_CONNECTION,READWRITE_Keyspecs,0,NULL,0)},
|
||||
/* connection */
|
||||
{MAKE_CMD("auth","Authenticates the connection.","O(N) where N is the number of passwords defined for the user","1.0.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,AUTH_History,1,AUTH_Tips,0,authCommand,-2,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_FAST|CMD_NO_AUTH|CMD_SENTINEL|CMD_ALLOW_BUSY,ACL_CATEGORY_CONNECTION,AUTH_Keyspecs,0,NULL,2),.args=AUTH_Args},
|
||||
{MAKE_CMD("client","A container for client connection commands.","Depends on subcommand.","2.4.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_History,0,CLIENT_Tips,0,NULL,-2,CMD_SENTINEL,0,CLIENT_Keyspecs,0,NULL,0),.subcommands=CLIENT_Subcommands},
|
||||
{MAKE_CMD("client","A container for client connection commands.","Depends on subcommand.","2.4.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,CLIENT_History,0,CLIENT_Tips,0,clientCommand,-2,CMD_SENTINEL,0,CLIENT_Keyspecs,0,NULL,0),.subcommands=CLIENT_Subcommands},
|
||||
{MAKE_CMD("echo","Returns the given string.","O(1)","1.0.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,ECHO_History,0,ECHO_Tips,0,echoCommand,2,CMD_LOADING|CMD_STALE|CMD_FAST,ACL_CATEGORY_CONNECTION,ECHO_Keyspecs,0,NULL,1),.args=ECHO_Args},
|
||||
{MAKE_CMD("hello","Handshakes with the server.","O(1)","6.0.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,HELLO_History,2,HELLO_Tips,0,helloCommand,-1,CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_FAST|CMD_NO_AUTH|CMD_SENTINEL|CMD_ALLOW_BUSY,ACL_CATEGORY_CONNECTION,HELLO_Keyspecs,0,NULL,1),.args=HELLO_Args},
|
||||
{MAKE_CMD("ping","Returns the server's liveliness response.","O(1)","1.0.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,PING_History,0,PING_Tips,2,pingCommand,-1,CMD_FAST|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,PING_Keyspecs,0,NULL,1),.args=PING_Args},
|
||||
|
@ -6,7 +6,7 @@
|
||||
"since": "6.0.0",
|
||||
"arity": 3,
|
||||
"container": "CLIENT",
|
||||
"function": "clientCommand",
|
||||
"function": "clientCachingCommand",
|
||||
"command_flags": [
|
||||
"NOSCRIPT",
|
||||
"LOADING",
|
||||
|
@ -6,7 +6,7 @@
|
||||
"since": "8.0.0",
|
||||
"arity": -3,
|
||||
"container": "CLIENT",
|
||||
"function": "clientCommand",
|
||||
"function": "clientCapaCommand",
|
||||
"command_flags": [
|
||||
"NOSCRIPT",
|
||||
"LOADING",
|
||||
|
@ -6,7 +6,7 @@
|
||||
"since": "2.6.9",
|
||||
"arity": 2,
|
||||
"container": "CLIENT",
|
||||
"function": "clientCommand",
|
||||
"function": "clientGetNameCommand",
|
||||
"command_flags": [
|
||||
"NOSCRIPT",
|
||||
"LOADING",
|
||||
|
@ -6,7 +6,7 @@
|
||||
"since": "6.0.0",
|
||||
"arity": 2,
|
||||
"container": "CLIENT",
|
||||
"function": "clientCommand",
|
||||
"function": "clientGetredirCommand",
|
||||
"command_flags": [
|
||||
"NOSCRIPT",
|
||||
"LOADING",
|
||||
|
@ -6,7 +6,7 @@
|
||||
"since": "5.0.0",
|
||||
"arity": 2,
|
||||
"container": "CLIENT",
|
||||
"function": "clientCommand",
|
||||
"function": "clientHelpCommand",
|
||||
"command_flags": [
|
||||
"LOADING",
|
||||
"STALE",
|
||||
|
@ -6,7 +6,7 @@
|
||||
"since": "5.0.0",
|
||||
"arity": 2,
|
||||
"container": "CLIENT",
|
||||
"function": "clientCommand",
|
||||
"function": "clientIDCommand",
|
||||
"command_flags": [
|
||||
"NOSCRIPT",
|
||||
"LOADING",
|
||||
|
@ -6,7 +6,7 @@
|
||||
"since": "8.1.0",
|
||||
"arity": 3,
|
||||
"container": "CLIENT",
|
||||
"function": "clientCommand",
|
||||
"function": "clientImportSourceCommand",
|
||||
"command_flags": [
|
||||
"NOSCRIPT",
|
||||
"LOADING",
|
||||
|
@ -6,7 +6,7 @@
|
||||
"since": "6.2.0",
|
||||
"arity": 2,
|
||||
"container": "CLIENT",
|
||||
"function": "clientCommand",
|
||||
"function": "clientInfoCommand",
|
||||
"command_flags": [
|
||||
"NOSCRIPT",
|
||||
"LOADING",
|
||||
|
@ -6,7 +6,7 @@
|
||||
"since": "2.4.0",
|
||||
"arity": -3,
|
||||
"container": "CLIENT",
|
||||
"function": "clientCommand",
|
||||
"function": "clientKillCommand",
|
||||
"history": [
|
||||
[
|
||||
"2.8.12",
|
||||
@ -35,6 +35,10 @@
|
||||
[
|
||||
"8.0.0",
|
||||
"Replaced `master` `TYPE` with `primary`. `master` still supported for backward compatibility."
|
||||
],
|
||||
[
|
||||
"8.1.0",
|
||||
"`ID` option accepts multiple IDs."
|
||||
]
|
||||
],
|
||||
"command_flags": [
|
||||
@ -68,6 +72,7 @@
|
||||
"name": "client-id",
|
||||
"type": "integer",
|
||||
"optional": true,
|
||||
"multiple": true,
|
||||
"since": "2.8.12"
|
||||
},
|
||||
{
|
||||
|
@ -6,7 +6,7 @@
|
||||
"since": "2.4.0",
|
||||
"arity": -2,
|
||||
"container": "CLIENT",
|
||||
"function": "clientCommand",
|
||||
"function": "clientListCommand",
|
||||
"history": [
|
||||
[
|
||||
"2.8.12",
|
||||
@ -35,6 +35,10 @@
|
||||
[
|
||||
"8.0.0",
|
||||
"Replaced `master` `TYPE` with `primary`. `master` still supported for backward compatibility."
|
||||
],
|
||||
[
|
||||
"8.1.0",
|
||||
"Added filters USER, ADDR, LADDR, SKIPME, and MAXAGE"
|
||||
]
|
||||
],
|
||||
"command_flags": [
|
||||
@ -91,6 +95,55 @@
|
||||
"optional": true,
|
||||
"multiple": true,
|
||||
"since": "6.2.0"
|
||||
},
|
||||
{
|
||||
"token": "USER",
|
||||
"name": "username",
|
||||
"type": "string",
|
||||
"optional": true,
|
||||
"since": "8.1.0"
|
||||
},
|
||||
{
|
||||
"token": "ADDR",
|
||||
"name": "addr",
|
||||
"display": "ip:port",
|
||||
"type": "string",
|
||||
"optional": true,
|
||||
"since": "8.1.0"
|
||||
},
|
||||
{
|
||||
"token": "LADDR",
|
||||
"name": "laddr",
|
||||
"display": "ip:port",
|
||||
"type": "string",
|
||||
"optional": true,
|
||||
"since": "8.1.0"
|
||||
},
|
||||
{
|
||||
"token": "SKIPME",
|
||||
"name": "skipme",
|
||||
"type": "oneof",
|
||||
"optional": true,
|
||||
"since": "8.1.0",
|
||||
"arguments": [
|
||||
{
|
||||
"name": "yes",
|
||||
"type": "pure-token",
|
||||
"token": "YES"
|
||||
},
|
||||
{
|
||||
"name": "no",
|
||||
"type": "pure-token",
|
||||
"token": "NO"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"token": "MAXAGE",
|
||||
"name": "maxage",
|
||||
"type": "integer",
|
||||
"optional": true,
|
||||
"since": "8.1.0"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
"since": "7.0.0",
|
||||
"arity": 3,
|
||||
"container": "CLIENT",
|
||||
"function": "clientCommand",
|
||||
"function": "clientNoEvictCommand",
|
||||
"command_flags": [
|
||||
"ADMIN",
|
||||
"NOSCRIPT",
|
||||
|
@ -6,7 +6,7 @@
|
||||
"since": "7.2.0",
|
||||
"arity": 3,
|
||||
"container": "CLIENT",
|
||||
"function": "clientCommand",
|
||||
"function": "clientNoTouchCommand",
|
||||
"command_flags": [
|
||||
"NOSCRIPT",
|
||||
"LOADING",
|
||||
|
@ -6,7 +6,7 @@
|
||||
"since": "3.0.0",
|
||||
"arity": -3,
|
||||
"container": "CLIENT",
|
||||
"function": "clientCommand",
|
||||
"function": "clientPauseCommand",
|
||||
"history": [
|
||||
[
|
||||
"6.2.0",
|
||||
|
@ -6,7 +6,7 @@
|
||||
"since": "3.2.0",
|
||||
"arity": 3,
|
||||
"container": "CLIENT",
|
||||
"function": "clientCommand",
|
||||
"function": "clientReplyCommand",
|
||||
"command_flags": [
|
||||
"NOSCRIPT",
|
||||
"LOADING",
|
||||
|
@ -6,7 +6,7 @@
|
||||
"since": "2.6.9",
|
||||
"arity": 3,
|
||||
"container": "CLIENT",
|
||||
"function": "clientCommand",
|
||||
"function": "clientSetNameCommand",
|
||||
"command_flags": [
|
||||
"NOSCRIPT",
|
||||
"LOADING",
|
||||
|
@ -6,7 +6,7 @@
|
||||
"since": "6.0.0",
|
||||
"arity": -3,
|
||||
"container": "CLIENT",
|
||||
"function": "clientCommand",
|
||||
"function": "clientTrackingCommand",
|
||||
"command_flags": [
|
||||
"NOSCRIPT",
|
||||
"LOADING",
|
||||
|
@ -6,7 +6,7 @@
|
||||
"since": "6.2.0",
|
||||
"arity": 2,
|
||||
"container": "CLIENT",
|
||||
"function": "clientCommand",
|
||||
"function": "clientTrackingInfoCommand",
|
||||
"command_flags": [
|
||||
"NOSCRIPT",
|
||||
"LOADING",
|
||||
|
@ -6,7 +6,7 @@
|
||||
"since": "5.0.0",
|
||||
"arity": -3,
|
||||
"container": "CLIENT",
|
||||
"function": "clientCommand",
|
||||
"function": "clientUnblockCommand",
|
||||
"command_flags": [
|
||||
"ADMIN",
|
||||
"NOSCRIPT",
|
||||
|
@ -6,7 +6,7 @@
|
||||
"since": "6.2.0",
|
||||
"arity": 2,
|
||||
"container": "CLIENT",
|
||||
"function": "clientCommand",
|
||||
"function": "clientUnpauseCommand",
|
||||
"command_flags": [
|
||||
"ADMIN",
|
||||
"NOSCRIPT",
|
||||
|
@ -4,6 +4,7 @@
|
||||
"complexity": "Depends on subcommand.",
|
||||
"group": "connection",
|
||||
"since": "2.4.0",
|
||||
"function": "clientCommand",
|
||||
"arity": -2,
|
||||
"command_flags": [
|
||||
"SENTINEL"
|
||||
|
1161
src/networking.c
1161
src/networking.c
File diff suppressed because it is too large
Load Diff
19
src/server.h
19
src/server.h
@ -3782,6 +3782,25 @@ void dumpCommand(client *c);
|
||||
void objectCommand(client *c);
|
||||
void memoryCommand(client *c);
|
||||
void clientCommand(client *c);
|
||||
void clientHelpCommand(client *c);
|
||||
void clientIDCommand(client *c);
|
||||
void clientInfoCommand(client *c);
|
||||
void clientListCommand(client *c);
|
||||
void clientReplyCommand(client *c);
|
||||
void clientNoEvictCommand(client *c);
|
||||
void clientKillCommand(client *c);
|
||||
void clientUnblockCommand(client *c);
|
||||
void clientSetNameCommand(client *c);
|
||||
void clientGetNameCommand(client *c);
|
||||
void clientUnpauseCommand(client *c);
|
||||
void clientPauseCommand(client *c);
|
||||
void clientTrackingCommand(client *c);
|
||||
void clientCachingCommand(client *c);
|
||||
void clientGetredirCommand(client *c);
|
||||
void clientTrackingInfoCommand(client *c);
|
||||
void clientNoTouchCommand(client *c);
|
||||
void clientCapaCommand(client *c);
|
||||
void clientImportSourceCommand(client *c);
|
||||
void helloCommand(client *c);
|
||||
void clientSetinfoCommand(client *c);
|
||||
void evalCommand(client *c);
|
||||
|
@ -19,6 +19,126 @@ start_server {tags {"introspection"}} {
|
||||
r client info
|
||||
} {id=* addr=*:* laddr=*:* fd=* name=* age=* idle=* flags=N db=* sub=0 psub=0 ssub=0 multi=-1 watch=0 qbuf=0 qbuf-free=* argv-mem=* multi-mem=0 rbs=* rbp=* obl=0 oll=0 omem=0 tot-mem=* events=r cmd=client|info user=* redir=-1 resp=* lib-name=* lib-ver=* tot-net-in=* tot-net-out=* tot-cmds=*}
|
||||
|
||||
test {CLIENT LIST with ADDR filter} {
|
||||
set client_info [r client info]
|
||||
regexp {addr=([^ ]+)} $client_info match myaddr
|
||||
set cl [split [r client list addr $myaddr] "\r\n"]
|
||||
regexp {addr=([^ ]+) .* cmd=([^ ]+)} [lindex $cl 0] _ actual_addr actual_cmd
|
||||
assert_equal $myaddr $actual_addr
|
||||
assert_equal "client|list" $actual_cmd
|
||||
}
|
||||
|
||||
test {CLIENT LIST with LADDR filter} {
|
||||
set client_info [r client info]
|
||||
regexp {laddr=([^ ]+)} $client_info match myladdr
|
||||
set cl [split [r client list laddr $myladdr] "\r\n"]
|
||||
|
||||
regexp {laddr=([^ ]+)} [lindex $cl 0] _ actual_laddr
|
||||
|
||||
assert_equal $myladdr $actual_laddr
|
||||
}
|
||||
|
||||
test {CLIENT LIST with MAXAGE filter} {
|
||||
set cl [split [r client list maxage 1000000] "\r\n"]
|
||||
|
||||
foreach line $cl {
|
||||
regexp {age=([0-9]+)} $line _ age
|
||||
assert {[expr {$age <= 1000000}]}
|
||||
}
|
||||
}
|
||||
|
||||
test {CLIENT LIST with TYPE filter} {
|
||||
set cl [split [r client list type normal] "\r\n"]
|
||||
|
||||
foreach line $cl {
|
||||
regexp {flags=([^ ]+)} $line _ flags
|
||||
assert [regexp {.*N.*} $flags]
|
||||
}
|
||||
}
|
||||
|
||||
test {CLIENT LIST with USER filter} {
|
||||
set client_info [r client info]
|
||||
regexp {user=([^ ]+)} $client_info match myuser
|
||||
set cl [split [r client list user $myuser] "\r\n"]
|
||||
|
||||
foreach line $cl {
|
||||
regexp {user=([^ ]+)} $line _ actual_user
|
||||
assert_equal $myuser $actual_user
|
||||
}
|
||||
}
|
||||
|
||||
test {CLIENT LIST with SKIPME filter} {
|
||||
set cl [split [r client list skipme no] "\r\n"]
|
||||
|
||||
set found_self 0
|
||||
foreach line $cl {
|
||||
regexp {id=([0-9]+)} $line _ client_id
|
||||
if {[expr {$client_id == [r client id]}]} {
|
||||
set found_self 1
|
||||
}
|
||||
}
|
||||
|
||||
assert_equal $found_self 1
|
||||
}
|
||||
|
||||
test {CLIENT LIST with multiple IDs and TYPE filter} {
|
||||
# Create multiple clients
|
||||
set c1 [valkey_client]
|
||||
set c2 [valkey_client]
|
||||
set c3 [valkey_client]
|
||||
|
||||
# Fetch their IDs
|
||||
set id1 [$c1 client id]
|
||||
set id2 [$c2 client id]
|
||||
set id3 [$c3 client id]
|
||||
|
||||
# Filter by multiple IDs and TYPE
|
||||
set cl [split [r client list id $id1 $id2 type normal] "\r\n"]
|
||||
|
||||
# Assert only c1 and c2 are present and match TYPE=N (NORMAL)
|
||||
foreach line $cl {
|
||||
regexp {id=([0-9]+).*flags=([^ ]+)} $line _ client_id flags
|
||||
assert {[lsearch -exact "$id1 $id2" $client_id] != -1}
|
||||
assert {[string match *N* $flags]}
|
||||
}
|
||||
|
||||
# Close clients
|
||||
$c1 close
|
||||
$c2 close
|
||||
$c3 close
|
||||
}
|
||||
|
||||
test {CLIENT LIST with filters matching no clients} {
|
||||
# Create multiple clients
|
||||
set c1 [valkey_client]
|
||||
set c2 [valkey_client]
|
||||
|
||||
# Use a filter that doesn't match any client (e.g., invalid user)
|
||||
assert_error "ERR No such user 'invalid_user'" {r client list user invalid_user}
|
||||
|
||||
# Close clients
|
||||
$c1 close
|
||||
$c2 close
|
||||
}
|
||||
|
||||
test {CLIENT LIST with illegal arguments} {
|
||||
assert_error "ERR syntax error" {r client list id 10 wrong_arg}
|
||||
|
||||
assert_error "ERR syntax error" {r client list id str}
|
||||
assert_error "ERR *greater than 0*" {r client list id -1}
|
||||
assert_error "ERR *greater than 0*" {r client list id 0}
|
||||
|
||||
assert_error "ERR Unknown client type*" {r client list type wrong_type}
|
||||
|
||||
assert_error "ERR No such user*" {r client list user wrong_user}
|
||||
|
||||
assert_error "ERR syntax error*" {r client list skipme yes_or_no}
|
||||
|
||||
assert_error "ERR *not an integer or out of range*" {r client list maxage str}
|
||||
assert_error "ERR *not an integer or out of range*" {r client list maxage 9999999999999999999}
|
||||
assert_error "ERR *greater than 0*" {r client list maxage -1}
|
||||
}
|
||||
|
||||
proc get_field_in_client_info {info field} {
|
||||
set info [string trim $info]
|
||||
foreach item [split $info " "] {
|
||||
@ -108,7 +228,7 @@ start_server {tags {"introspection"}} {
|
||||
assert_error "ERR wrong number of arguments for 'client|kill' command" {r client kill}
|
||||
assert_error "ERR syntax error*" {r client kill id 10 wrong_arg}
|
||||
|
||||
assert_error "ERR *greater than 0*" {r client kill id str}
|
||||
assert_error "ERR syntax error*" {r client kill id str}
|
||||
assert_error "ERR *greater than 0*" {r client kill id -1}
|
||||
assert_error "ERR *greater than 0*" {r client kill id 0}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user