From c3185a49b61f1a50d92656af569a009650e1ed3b Mon Sep 17 00:00:00 2001 From: Prateek Kumar Date: Thu, 23 Oct 2025 17:37:58 -0700 Subject: [PATCH 01/27] PHP: Add logging Signed-off-by: Prateek Kumar --- .gitignore | 5 ++ command_response.c | 8 +-- tests/ValkeyGlideTest.php | 107 +++++++++++++++++++++++++++++++++++++ valkey_glide.c | 3 ++ valkey_glide_cluster.c | 4 ++ valkey_glide_core_common.c | 5 ++ 6 files changed, 129 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 9b166864..87ec3961 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,11 @@ Cargo.lock *.pdb dump.rdb .env + +# Log files +logs/ +*.log +*.log.* python/.env* benchmarks/results diff --git a/command_response.c b/command_response.c index 42c0e0c8..7eea552a 100644 --- a/command_response.c +++ b/command_response.c @@ -18,6 +18,7 @@ #include "ext/standard/php_var.h" #include "include/glide/command_request.pb-c.h" #include "include/glide/response.pb-c.h" +#include "logger.h" #include "include/glide_bindings.h" #include "valkey_glide_commands_common.h" @@ -313,12 +314,12 @@ CommandResult* execute_command_with_route(const void* glide_client, /* Validate result before returning */ if (!result) { - printf("Error: Command execution returned NULL result\n"); + VALKEY_LOG_ERROR("command_response", "Command execution returned NULL result"); } else if (result->command_error) { - printf("Error: Command execution failed: %s\n", + VALKEY_LOG_ERROR("command_response", result->command_error->command_error_message ? result->command_error->command_error_message - : "Unknown error"); + : "Unknown command error"); } return result; @@ -359,6 +360,7 @@ int handle_string_response(CommandResult* result, char** output, size_t* output_ /* Check if there was an error */ if (result->command_error) { + VALKEY_LOG_ERROR("command_response", "Command execution failed with error"); return -1; } diff --git a/tests/ValkeyGlideTest.php b/tests/ValkeyGlideTest.php index 3f7de8c3..a68ad87a 100644 --- a/tests/ValkeyGlideTest.php +++ b/tests/ValkeyGlideTest.php @@ -7571,4 +7571,111 @@ public function testFunction() $this->assertEquals([['library_name' => 'mylib', 'engine' => 'LUA', 'functions' => [['name' => 'myfunc', 'description' => false,'flags' => []]]]], $this->valkey_glide->function('list')); $this->assertTrue($this->valkey_glide->function('delete', 'mylib')); } + + public function testGetCommandWithLogging() + { + // Create unique log file for this test + $logFile = '/tmp/valkey_get_test_' . uniqid() . '.log'; + + // Initialize logger with debug level for detailed test logging + $this->assertTrue(valkey_glide_logger_set_config("debug", $logFile)); + $this->assertTrue(valkey_glide_logger_is_initialized()); + + valkey_glide_logger_info("get-test", "=== Starting GET command test ==="); + + // Test setup + $testKey = 'test-key-' . uniqid(); + $testValue = 'test-value-' . uniqid(); + + valkey_glide_logger_debug("get-test", "Test key: $testKey"); + valkey_glide_logger_debug("get-test", "Test value: $testValue"); + + // Set the key + valkey_glide_logger_info("get-test", "Setting key via SET command"); + $setResult = $this->valkey_glide->set($testKey, $testValue); + valkey_glide_logger_debug("get-test", "SET result: " . ($setResult ? 'true' : 'false')); + $this->assertTrue($setResult); + + // Get the key + valkey_glide_logger_info("get-test", "Retrieving key via GET command"); + $getValue = $this->valkey_glide->get($testKey); + valkey_glide_logger_debug("get-test", "GET result: " . ($getValue ?: 'null')); + + // Verify result + $this->assertEquals($testValue, $getValue); + valkey_glide_logger_info("get-test", "✓ GET command test passed - values match"); + + // Test non-existent key + valkey_glide_logger_info("get-test", "Testing non-existent key"); + $nonExistentKey = 'non-existent-key-' . uniqid(); + valkey_glide_logger_debug("get-test", "Non-existent key: $nonExistentKey"); + + $nonExistentResult = $this->valkey_glide->get($nonExistentKey); + valkey_glide_logger_debug("get-test", "Non-existent key result: " . ($nonExistentResult === false ? 'false' : $nonExistentResult)); + + $this->assertFalse($nonExistentResult); + valkey_glide_logger_info("get-test", "✓ Non-existent key test passed"); + + // Test with various data types + $testCases = [ + 'string' => 'hello world', + 'number' => '12345', + 'special' => 'émojis: 🚀 unicode: ñáéíóú' + ]; + + foreach ($testCases as $type => $value) { + valkey_glide_logger_info("get-test", "Testing $type data type"); + $key = "test-$type-" . uniqid(); + + valkey_glide_logger_debug("get-test", "Setting $key = $value"); + $this->assertTrue($this->valkey_glide->set($key, $value)); + + $result = $this->valkey_glide->get($key); + valkey_glide_logger_debug("get-test", "Retrieved $key = $result"); + + $this->assertEquals($value, $result); + valkey_glide_logger_info("get-test", "✓ $type test passed"); + + // Clean up + $this->valkey_glide->del($key); + } + + // Clean up main test key + valkey_glide_logger_info("get-test", "Cleaning up test key"); + $delResult = $this->valkey_glide->del($testKey); + valkey_glide_logger_debug("get-test", "DEL result: $delResult"); + + valkey_glide_logger_info("get-test", "=== GET command test completed successfully ==="); + valkey_glide_logger_info("get-test", "Log file location: $logFile"); + + // Verify logging actually worked + sleep(1); // Wait for logs to be written + + // Check logger is initialized + $this->assertTrue(valkey_glide_logger_is_initialized(), "Logger should be initialized"); + $this->assertEquals(3, valkey_glide_logger_get_level(), "Debug level should be 3"); + + // Verify log file creation + $actualLogFiles = glob($logFile . '*'); + $this->assertTrue(count($actualLogFiles) > 0, "Log file should be created"); + + // Verify log content + $actualLogFile = $actualLogFiles[0]; + $this->assertTrue(file_exists($actualLogFile), "Log file should exist"); + + $logContent = file_get_contents($actualLogFile); + $this->assertTrue(!empty($logContent), "Log file should not be empty"); + + // Verify specific log messages exist + $this->assertStringContains("=== Starting GET command test ===", $logContent, "Should contain test start message"); + $this->assertStringContains("Setting key via SET command", $logContent, "Should contain SET operation log"); + $this->assertStringContains("Retrieving key via GET command", $logContent, "Should contain GET operation log"); + $this->assertStringContains("✓ GET command test passed - values match", $logContent, "Should contain success message"); + $this->assertStringContains("get-test", $logContent, "Should contain test identifier"); + + // Output log file location for verification + echo "\n=== LOG FILE LOCATION ===\n"; + echo "Log file: $actualLogFile\n"; + echo "========================\n"; + } } diff --git a/valkey_glide.c b/valkey_glide.c index 7e3a3a4e..2338838a 100644 --- a/valkey_glide.c +++ b/valkey_glide.c @@ -199,6 +199,7 @@ void valkey_glide_build_client_config_base(valkey_glide_php_common_constructor_p /* Invalid address format */ const char* error_message = "Invalid address format. Expected array with 'host' and 'port' keys."; + VALKEY_LOG_ERROR("php_construct", error_message); zend_throw_exception(valkey_glide_exception_ce, error_message, 0); valkey_glide_cleanup_client_config(config); return; @@ -470,6 +471,7 @@ PHP_METHOD(ValkeyGlide, __construct) { if (!common_params.database_id_is_null) { if (common_params.database_id < 0) { const char* error_message = "Database ID must be non-negative."; + VALKEY_LOG_ERROR("php_construct", error_message); zend_throw_exception(valkey_glide_exception_ce, error_message, 0); return; } @@ -479,6 +481,7 @@ PHP_METHOD(ValkeyGlide, __construct) { if (!common_params.addresses || zend_hash_num_elements(Z_ARRVAL_P(common_params.addresses)) == 0) { const char* error_message = "Addresses array cannot be empty"; + VALKEY_LOG_ERROR("php_construct", error_message); zend_throw_exception(valkey_glide_exception_ce, error_message, 0); return; } diff --git a/valkey_glide_cluster.c b/valkey_glide_cluster.c index e0063c0c..89f2abe0 100644 --- a/valkey_glide_cluster.c +++ b/valkey_glide_cluster.c @@ -12,6 +12,7 @@ #include "common.h" #include "ext/standard/info.h" +#include "logger.h" #include "valkey_glide_commands_common.h" #include "valkey_glide_geo_common.h" #include "valkey_glide_hash_common.h" /* Include hash command framework */ @@ -60,6 +61,7 @@ PHP_METHOD(ValkeyGlideCluster, __construct) { /* Validate database_id range early */ if (!common_params.database_id_is_null && common_params.database_id < 0) { const char* error_message = "Database ID must be non-negative."; + VALKEY_LOG_ERROR("cluster_construct", error_message); zend_throw_exception(get_valkey_glide_exception_ce(), error_message, 0); return; } @@ -80,9 +82,11 @@ PHP_METHOD(ValkeyGlideCluster, __construct) { const ConnectionResponse* conn_resp = create_glide_cluster_client(&client_config); if (conn_resp->connection_error_message) { + VALKEY_LOG_ERROR("cluster_construct", conn_resp->connection_error_message); zend_throw_exception( get_valkey_glide_exception_ce(), conn_resp->connection_error_message, 0); } else { + VALKEY_LOG_INFO("cluster_construct", "ValkeyGlide cluster client created successfully"); valkey_glide->glide_client = conn_resp->conn_ptr; } diff --git a/valkey_glide_core_common.c b/valkey_glide_core_common.c index b9b6c98a..42c5473e 100644 --- a/valkey_glide_core_common.c +++ b/valkey_glide_core_common.c @@ -20,6 +20,7 @@ #include #include +#include "logger.h" #include "valkey_glide_z_common.h" /* ==================================================================== @@ -36,6 +37,7 @@ int execute_core_command(valkey_glide_object* valkey_glide, z_result_processor_t processor, zval* return_value) { if (!valkey_glide || !args || !args->glide_client || !processor) { + VALKEY_LOG_ERROR("execute_core_command", "Invalid parameters provided"); efree(result_ptr); return 0; } @@ -55,6 +57,7 @@ int execute_core_command(valkey_glide_object* valkey_glide, prepare_core_args(args, &cmd_args, &cmd_args_len, &allocated_strings, &allocated_count); if (arg_count < 0) { + VALKEY_LOG_ERROR("execute_core_command", "Failed to prepare command arguments"); efree(result_ptr); return 0; } @@ -103,12 +106,14 @@ int execute_core_command(valkey_glide_object* valkey_glide, /* Non-routed commands use standard processor */ res = processor(result->response, result_ptr, return_value); } else { + VALKEY_LOG_ERROR("execute_core_command", "Command execution returned no response"); ZVAL_FALSE(return_value); } /* Free the result - handle_string_response doesn't free it */ free_command_result(result); } else { + VALKEY_LOG_ERROR("execute_core_command", "Command execution failed - NULL result"); ZVAL_FALSE(return_value); } From e2d48bca9a33f058c9398c650e47dfd86986645e Mon Sep 17 00:00:00 2001 From: Prateek Kumar Date: Sun, 26 Oct 2025 23:25:13 -0700 Subject: [PATCH 02/27] PHP: Fix formatting issue Signed-off-by: Prateek Kumar --- command_response.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/command_response.c b/command_response.c index 9b50f093..e32f6a82 100644 --- a/command_response.c +++ b/command_response.c @@ -18,8 +18,8 @@ #include "ext/standard/php_var.h" #include "include/glide/command_request.pb-c.h" #include "include/glide/response.pb-c.h" -#include "logger.h" #include "include/glide_bindings.h" +#include "logger.h" #include "valkey_glide_commands_common.h" #define DEBUG_COMMAND_RESPONSE_TO_ZVAL 0 @@ -316,10 +316,10 @@ CommandResult* execute_command_with_route(const void* glide_client, if (!result) { VALKEY_LOG_ERROR("command_response", "Command execution returned NULL result"); } else if (result->command_error) { - VALKEY_LOG_ERROR("command_response", - result->command_error->command_error_message - ? result->command_error->command_error_message - : "Unknown command error"); + VALKEY_LOG_ERROR("command_response", + result->command_error->command_error_message + ? result->command_error->command_error_message + : "Unknown command error"); } return result; From 3821a7cc4d2c9dd67ddc3af631e11007357c2acb Mon Sep 17 00:00:00 2001 From: Prateek Kumar Date: Sun, 26 Oct 2025 23:38:39 -0700 Subject: [PATCH 03/27] PHP: Add error logs Signed-off-by: Prateek Kumar --- src/client_constructor_mock.c | 5 +++++ valkey_glide_commands.c | 2 ++ 2 files changed, 7 insertions(+) diff --git a/src/client_constructor_mock.c b/src/client_constructor_mock.c index f8fac3a0..f1abbfaa 100644 --- a/src/client_constructor_mock.c +++ b/src/client_constructor_mock.c @@ -15,6 +15,7 @@ #include "common.h" #include "ext/standard/info.h" +#include "logger.h" #include "php.h" #include "zend_exceptions.h" @@ -42,6 +43,7 @@ static zval* build_php_connection_request(uint8_t* valkey_glide_base_client_configuration_t* base_config) { if (!request_bytes) { const char* error_message = "Protobuf memory allocation error."; + VALKEY_LOG_ERROR("mock_construct", error_message); zend_throw_exception(get_valkey_glide_exception_ce(), error_message, 0); valkey_glide_cleanup_client_config(base_config); return NULL; @@ -100,6 +102,7 @@ PHP_METHOD(ClientConstructorMock, simulate_standalone_constructor) { if (!common_params.addresses || zend_hash_num_elements(Z_ARRVAL_P(common_params.addresses)) == 0) { const char* error_message = "Addresses array cannot be empty"; + VALKEY_LOG_ERROR("mock_construct", error_message); zend_throw_exception(get_valkey_glide_exception_ce(), error_message, 0); return; } @@ -107,6 +110,7 @@ PHP_METHOD(ClientConstructorMock, simulate_standalone_constructor) { /* Validate database_id range before setting */ if (!common_params.database_id_is_null && common_params.database_id < 0) { const char* error_message = "Database ID must be non-negative."; + VALKEY_LOG_ERROR("mock_construct", error_message); zend_throw_exception(get_valkey_glide_exception_ce(), error_message, 0); return; } @@ -154,6 +158,7 @@ PHP_METHOD(ClientConstructorMock, simulate_cluster_constructor) { /* Validate database_id range before setting */ if (!common_params.database_id_is_null && common_params.database_id < 0) { const char* error_message = "Database ID must be non-negative."; + VALKEY_LOG_ERROR("mock_construct", error_message); zend_throw_exception(get_valkey_glide_exception_ce(), error_message, 0); return; } diff --git a/valkey_glide_commands.c b/valkey_glide_commands.c index cc8c2528..e682999b 100644 --- a/valkey_glide_commands.c +++ b/valkey_glide_commands.c @@ -19,6 +19,7 @@ #include "command_response.h" #include "include/glide_bindings.h" +#include "logger.h" #include "php.h" #include "valkey_glide_commands_common.h" #include "valkey_glide_core_common.h" @@ -610,6 +611,7 @@ int execute_copy_command(zval* object, int argc, zval* return_value, zend_class_ if (Z_TYPE_P(val) == IS_LONG) { zend_long db_id = Z_LVAL_P(val); if (db_id < 0) { + VALKEY_LOG_ERROR("command_validation", "Database ID must be non-negative"); zend_throw_exception( get_valkey_glide_exception_ce(), "Database ID must be non-negative", 0); return 0; From fd7f1759220e0228d70e70d55ad3d2ea95ea761a Mon Sep 17 00:00:00 2001 From: Prateek Kumar Date: Mon, 27 Oct 2025 00:10:10 -0700 Subject: [PATCH 04/27] PHP: Remove printf statements Signed-off-by: Prateek Kumar --- command_response.c | 78 +++++++++++++++++------------------- valkey_glide_commands.c | 2 +- valkey_glide_core_commands.c | 4 +- valkey_glide_core_common.c | 70 +++++++++++++++++++++++++++----- valkey_glide_s_common.c | 3 +- valkey_glide_x_common.c | 2 +- 6 files changed, 102 insertions(+), 57 deletions(-) diff --git a/command_response.c b/command_response.c index e32f6a82..a177e368 100644 --- a/command_response.c +++ b/command_response.c @@ -163,7 +163,7 @@ uint8_t* create_route_bytes_from_route(cluster_route_t* route, size_t* route_byt case ROUTE_TYPE_KEY: /* Validate key data */ if (!route->data.key_route.key || route->data.key_route.key_len == 0) { - printf("Error: Invalid key data for route\n"); + VALKEY_LOG_ERROR("route_processing", "Invalid key data for route"); *route_bytes_len = 0; return NULL; } @@ -198,7 +198,7 @@ uint8_t* create_route_bytes_from_route(cluster_route_t* route, size_t* route_byt default: /* Unknown route type */ - printf("Error: Unknown route type: %d\n", route->type); + VALKEY_LOG_ERROR("route_processing", "Unknown route type: %d", route->type); *route_bytes_len = 0; return NULL; } @@ -206,14 +206,14 @@ uint8_t* create_route_bytes_from_route(cluster_route_t* route, size_t* route_byt /* Get serialized size and allocate buffer */ *route_bytes_len = command_request__routes__get_packed_size(&routes); if (*route_bytes_len == 0) { - printf("Error: Failed to get packed size for route\n"); + VALKEY_LOG_ERROR("route_processing", "Failed to get packed size for route"); return NULL; } route_bytes = (uint8_t*) emalloc(*route_bytes_len); if (!route_bytes) { - printf("Error: Failed to allocate memory for route bytes\n"); + VALKEY_LOG_ERROR("memory_allocation", "Failed to allocate memory for route bytes"); *route_bytes_len = 0; return NULL; } @@ -221,8 +221,10 @@ uint8_t* create_route_bytes_from_route(cluster_route_t* route, size_t* route_byt /* Serialize the routes */ size_t packed_size = command_request__routes__pack(&routes, route_bytes); if (packed_size != *route_bytes_len) { - printf( - "Error: Packed size mismatch: expected %zu, got %zu\n", *route_bytes_len, packed_size); + VALKEY_LOG_ERROR("route_processing", + "Packed size mismatch: expected %zu, got %zu", + *route_bytes_len, + packed_size); efree(route_bytes); *route_bytes_len = 0; return NULL; @@ -241,7 +243,7 @@ CommandResult* execute_command_with_route(const void* glide_client, zval* arg_route) { /* Validate route parameter */ if (!arg_route) { - printf("Error: arg_route is NULL\n"); + VALKEY_LOG_ERROR("route_processing", "arg_route is NULL"); return NULL; } @@ -250,7 +252,7 @@ CommandResult* execute_command_with_route(const void* glide_client, memset(&route, 0, sizeof(cluster_route_t)); if (!parse_cluster_route(arg_route, &route)) { /* Failed to parse the route */ - printf("Error: Failed to parse cluster route\n"); + VALKEY_LOG_ERROR("route_processing", "Failed to parse cluster route"); return NULL; } @@ -258,7 +260,7 @@ CommandResult* execute_command_with_route(const void* glide_client, size_t route_bytes_len = 0; uint8_t* route_bytes = create_route_bytes_from_route(&route, &route_bytes_len); if (!route_bytes) { - printf("Error: Failed to create route bytes\n"); + VALKEY_LOG_ERROR("route_processing", "Failed to create route bytes"); /* Free dynamically allocated key if needed before returning */ if (route.type == ROUTE_TYPE_KEY && route.data.key_route.key_allocated) { efree(route.data.key_route.key); @@ -268,24 +270,28 @@ CommandResult* execute_command_with_route(const void* glide_client, /* Validate all parameters before FFI call */ if (!glide_client) { - printf("ERROR: glide_client is NULL\n"); + VALKEY_LOG_ERROR("parameter_validation", "glide_client is NULL"); return NULL; } if (arg_count > 0) { if (!args) { - printf("ERROR: args is NULL but arg_count is %lu\n", arg_count); + VALKEY_LOG_ERROR( + "parameter_validation", "args is NULL but arg_count is %lu", arg_count); return NULL; } if (!args_len) { - printf("ERROR: args_len is NULL but arg_count is %lu\n", arg_count); + VALKEY_LOG_ERROR( + "parameter_validation", "args_len is NULL but arg_count is %lu", arg_count); return NULL; } } if (route_bytes_len > 0) { if (!route_bytes) { - printf("ERROR: route_bytes is NULL but route_bytes_len is %zu\n", route_bytes_len); + VALKEY_LOG_ERROR("parameter_validation", + "route_bytes is NULL but route_bytes_len is %zu", + route_bytes_len); return NULL; } } @@ -434,7 +440,7 @@ int command_response_to_zval(CommandResponse* response, switch (response->response_type) { case Null: #if DEBUG_COMMAND_RESPONSE_TO_ZVAL - printf("%s:%d - CommandResponse is NULL\n", __FILE__, __LINE__); + VALKEY_LOG_DEBUG("response_processing", "CommandResponse is NULL"); #endif if (use_false_if_null) { // printf("%s:%d - CommandResponse is converted to false\n", __FILE__, __LINE__); @@ -446,52 +452,43 @@ int command_response_to_zval(CommandResponse* response, return 0; case Int: #if DEBUG_COMMAND_RESPONSE_TO_ZVAL - - printf( - "%s:%d - CommandResponse is Int: %ld\n", __FILE__, __LINE__, response->int_value); + VALKEY_LOG_DEBUG( + "response_processing", "CommandResponse is Int: %ld", response->int_value); #endif ZVAL_LONG(output, response->int_value); return 1; case Float: #if DEBUG_COMMAND_RESPONSE_TO_ZVAL - printf("%s:%d - CommandResponse is Float: %f\n", - __FILE__, - __LINE__, - response->float_value); + VALKEY_LOG_DEBUG( + "response_processing", "CommandResponse is Float: %f", response->float_value); #endif ZVAL_DOUBLE(output, response->float_value); #if DEBUG_COMMAND_RESPONSE_TO_ZVAL - - printf("%s:%d - Converted CommandResponse to double: %f\n", - __FILE__, - __LINE__, - Z_DVAL_P(output)); + VALKEY_LOG_DEBUG( + "response_processing", "Converted CommandResponse to double: %f", Z_DVAL_P(output)); #endif return 1; case Bool: #if DEBUG_COMMAND_RESPONSE_TO_ZVAL - - printf( - "%s:%d - CommandResponse is Bool: %d\n", __FILE__, __LINE__, response->bool_value); + VALKEY_LOG_DEBUG( + "response_processing", "CommandResponse is Bool: %d", response->bool_value); #endif ZVAL_BOOL(output, response->bool_value); return 1; case String: #if DEBUG_COMMAND_RESPONSE_TO_ZVAL - - printf("%s:%d - CommandResponse is String with length: %ld\n", - __FILE__, - __LINE__, - response->string_value_len); + VALKEY_LOG_DEBUG("response_processing", + "CommandResponse is String with length: %ld", + response->string_value_len); #endif ZVAL_STRINGL(output, response->string_value, response->string_value_len); return 1; case Array: #if DEBUG_COMMAND_RESPONSE_TO_ZVAL - - printf( - "%s:%d - CommandResponse is Array with length: %ld, use_associative_array = %d\n ", + VALKEY_LOG_DEBUG( + "response_processing", + "CommandResponse is Array with length: %ld, use_associative_array = %d", __FILE__, __LINE__, response->array_value_len, @@ -522,10 +519,9 @@ int command_response_to_zval(CommandResponse* response, } } else if (use_associative_array == COMMAND_RESPONSE_ARRAY_ASSOCIATIVE) { #if DEBUG_COMMAND_RESPONSE_TO_ZVAL - printf("%s:%d - response->array_value[0]->command_response_type = %d\n ", - __FILE__, - __LINE__, - response->array_value[0].response_type); + VALKEY_LOG_DEBUG("response_processing", + "response->array_value[0]->command_response_type = %d", + response->array_value[0].response_type); #endif array_init(output); for (int64_t i = 0; i < response->array_value_len; ++i) { diff --git a/valkey_glide_commands.c b/valkey_glide_commands.c index e682999b..ab963182 100644 --- a/valkey_glide_commands.c +++ b/valkey_glide_commands.c @@ -833,7 +833,7 @@ int execute_select_command(zval* object, int argc, zval* return_value, zend_clas /* SELECT cannot be used in batch mode */ if (valkey_glide->is_in_batch_mode) { - php_printf("Error: SELECT command cannot be used in batch mode\n"); + VALKEY_LOG_ERROR("batch_validation", "SELECT command cannot be used in batch mode"); return 0; } diff --git a/valkey_glide_core_commands.c b/valkey_glide_core_commands.c index cfb374cc..f1305482 100644 --- a/valkey_glide_core_commands.c +++ b/valkey_glide_core_commands.c @@ -215,7 +215,7 @@ static const ConnectionResponse* create_base_glide_client( /* Check if there was an error */ if (conn_resp->connection_error_message) { - printf("Error creating client: %s\n", conn_resp->connection_error_message); + VALKEY_LOG_ERROR("client_creation", conn_resp->connection_error_message); } return conn_resp; @@ -1955,7 +1955,7 @@ static int process_lcs_result(CommandResponse* response, void* output, zval* ret default: - printf("default response\n"); + VALKEY_LOG_WARN("command_response", "Unexpected default response type"); /* Unsupported response type */ ZVAL_FALSE(return_value); ret_val = 0; diff --git a/valkey_glide_core_common.c b/valkey_glide_core_common.c index 0accaaee..8a769e58 100644 --- a/valkey_glide_core_common.c +++ b/valkey_glide_core_common.c @@ -37,11 +37,25 @@ int execute_core_command(valkey_glide_object* valkey_glide, z_result_processor_t processor, zval* return_value) { if (!valkey_glide || !args || !args->glide_client || !processor) { - VALKEY_LOG_ERROR("execute_core_command", "Invalid parameters provided"); + if (!valkey_glide) { + VALKEY_LOG_ERROR("parameter_validation", "ValkeyGlide object is NULL"); + } else if (!args) { + VALKEY_LOG_ERROR("parameter_validation", "Command arguments are NULL"); + } else if (!args->glide_client) { + VALKEY_LOG_ERROR("parameter_validation", "Client connection handle is NULL"); + } else if (!processor) { + VALKEY_LOG_ERROR("parameter_validation", "Result processor is NULL"); + } efree(result_ptr); return 0; } + /* Log command execution entry */ + VALKEY_LOG_DEBUG("command_execution", "Entering command execution"); + VALKEY_LOG_DEBUG("command_execution", "Command type: %d", args->cmd_type); + VALKEY_LOG_DEBUG( + "command_execution", "Batch mode: %s", valkey_glide->is_in_batch_mode ? "yes" : "no"); + uintptr_t* cmd_args = NULL; unsigned long* cmd_args_len = NULL; char** allocated_strings = NULL; @@ -53,6 +67,7 @@ int execute_core_command(valkey_glide_object* valkey_glide, debug_print_core_args(args); /* Prepare command arguments based on command type */ + VALKEY_LOG_DEBUG("command_execution", "Preparing command arguments"); arg_count = prepare_core_args(args, &cmd_args, &cmd_args_len, &allocated_strings, &allocated_count); @@ -62,10 +77,12 @@ int execute_core_command(valkey_glide_object* valkey_glide, return 0; } + VALKEY_LOG_DEBUG("command_execution", "Argument count: %d", arg_count); + /* Check for batch mode */ if (valkey_glide->is_in_batch_mode) { /* Create batch-compatible processor wrapper */ - + VALKEY_LOG_DEBUG("command_execution", "Entering batch mode execution"); res = buffer_command_for_batch(valkey_glide, args->cmd_type, @@ -78,14 +95,21 @@ int execute_core_command(valkey_glide_object* valkey_glide, free_core_args(cmd_args, cmd_args_len, allocated_strings, allocated_count); if (res == 0) { + VALKEY_LOG_WARN("batch_execution", + "Failed to buffer command for batch - command type: %d", + args->cmd_type); efree(result_ptr); + } else { + VALKEY_LOG_DEBUG("batch_execution", "Command successfully buffered for batch"); } return res; } /* Execute the command - use routing if cluster mode and route provided */ + VALKEY_LOG_DEBUG("command_execution", "Executing command via FFI"); if (args->has_route && args->route_param) { /* Cluster mode with routing */ + VALKEY_LOG_DEBUG("command_execution", "Using cluster routing"); result = execute_command_with_route(args->glide_client, args->cmd_type, arg_count, @@ -101,6 +125,7 @@ int execute_core_command(valkey_glide_object* valkey_glide, debug_print_command_result(result); /* Process result using appropriate handler */ + VALKEY_LOG_DEBUG("command_execution", "Processing command result"); if (result) { if (result->response) { /* Non-routed commands use standard processor */ @@ -1133,9 +1158,20 @@ int process_core_type_result(CommandResponse* response, void* output, zval* retu * Allocate command argument arrays */ int allocate_core_arg_arrays(int count, uintptr_t** args_out, unsigned long** args_len_out) { - *args_out = (uintptr_t*) emalloc(count * sizeof(uintptr_t)); - *args_len_out = (unsigned long*) emalloc(count * sizeof(unsigned long)); + *args_out = (uintptr_t*) emalloc(count * sizeof(uintptr_t)); + if (!*args_out) { + VALKEY_LOG_ERROR("memory_allocation", + "Failed to allocate memory for command arguments array"); + return 0; + } + *args_len_out = (unsigned long*) emalloc(count * sizeof(unsigned long)); + if (!*args_len_out) { + VALKEY_LOG_ERROR("memory_allocation", + "Failed to allocate memory for command arguments length array"); + efree(*args_out); + return 0; + } return 1; } @@ -1145,7 +1181,11 @@ int allocate_core_arg_arrays(int count, uintptr_t** args_out, unsigned long** ar * Create string tracker for memory management */ char** create_string_tracker(int max_strings) { - return (char**) ecalloc(max_strings, sizeof(char*)); + char** tracker = (char**) ecalloc(max_strings, sizeof(char*)); + if (!tracker) { + VALKEY_LOG_ERROR("memory_allocation", "Failed to allocate memory for string tracker"); + } + return tracker; } /** @@ -1492,17 +1532,25 @@ int process_core_string_result(CommandResponse* response, void* output, zval* re if (response->response_type == String) { if (response->string_value_len == 0) { result = emalloc(1); - if (result) { - (result)[0] = '\0'; + if (!result) { + VALKEY_LOG_ERROR("memory_allocation", + "Failed to allocate memory for empty string result"); + ZVAL_NULL(return_value); + return 0; } + result[0] = '\0'; result_len = 0; } else { result = emalloc(response->string_value_len + 1); - if (result) { - memcpy(result, response->string_value, response->string_value_len); - (result)[response->string_value_len] = '\0'; + if (!result) { + VALKEY_LOG_ERROR("memory_allocation", + "Failed to allocate memory for string result"); + ZVAL_NULL(return_value); + return 0; } - result_len = response->string_value_len; + memcpy(result, response->string_value, response->string_value_len); + result[response->string_value_len] = '\0'; + result_len = response->string_value_len; } if (result) { ZVAL_STRINGL(return_value, result, result_len); diff --git a/valkey_glide_s_common.c b/valkey_glide_s_common.c index 5da0734f..403d4686 100644 --- a/valkey_glide_s_common.c +++ b/valkey_glide_s_common.c @@ -576,7 +576,8 @@ int process_s_scan_result_async(CommandResponse* response, void* output, zval* r efree(args->cursor); efree(args); } else { - printf("No response received in process_s_scan_result_async\n"); + VALKEY_LOG_ERROR("scan_processing", + "No response received in process_s_scan_result_async"); args->cursor = "0"; } diff --git a/valkey_glide_x_common.c b/valkey_glide_x_common.c index f1031f09..792a37b1 100644 --- a/valkey_glide_x_common.c +++ b/valkey_glide_x_common.c @@ -420,7 +420,7 @@ int execute_x_generic_command(valkey_glide_object* valkey_glide, args, &cmd_args, &args_len, &allocated_strings, &allocated_count); break; default: - printf("Unknown command type: %d\n", cmd_type); + VALKEY_LOG_ERROR("command_processing", "Unknown command type: %d", cmd_type); return 0; } From e8bd63b3323d96a75f751f067ec6317cea55cfba Mon Sep 17 00:00:00 2001 From: Prateek Kumar Date: Mon, 27 Oct 2025 00:23:17 -0700 Subject: [PATCH 05/27] PHP: Remove printf statements Signed-off-by: Prateek Kumar --- command_response.c | 7 +++++-- valkey_glide_core_common.c | 31 ++++++++++++++++++++++++------- valkey_glide_x_common.c | 7 +++++-- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/command_response.c b/command_response.c index a177e368..868057fa 100644 --- a/command_response.c +++ b/command_response.c @@ -196,11 +196,14 @@ uint8_t* create_route_bytes_from_route(cluster_route_t* route, size_t* route_byt routes.simple_routes = simple_route; break; - default: + default: { /* Unknown route type */ - VALKEY_LOG_ERROR("route_processing", "Unknown route type: %d", route->type); + char error_msg[64]; + snprintf(error_msg, sizeof(error_msg), "Unknown route type: %d", route->type); + VALKEY_LOG_ERROR("route_processing", error_msg); *route_bytes_len = 0; return NULL; + } } /* Get serialized size and allocate buffer */ diff --git a/valkey_glide_core_common.c b/valkey_glide_core_common.c index 8a769e58..d998410c 100644 --- a/valkey_glide_core_common.c +++ b/valkey_glide_core_common.c @@ -52,9 +52,19 @@ int execute_core_command(valkey_glide_object* valkey_glide, /* Log command execution entry */ VALKEY_LOG_DEBUG("command_execution", "Entering command execution"); - VALKEY_LOG_DEBUG("command_execution", "Command type: %d", args->cmd_type); - VALKEY_LOG_DEBUG( - "command_execution", "Batch mode: %s", valkey_glide->is_in_batch_mode ? "yes" : "no"); + { + char cmd_type_msg[64]; + snprintf(cmd_type_msg, sizeof(cmd_type_msg), "Command type: %d", args->cmd_type); + VALKEY_LOG_DEBUG("command_execution", cmd_type_msg); + } + { + char batch_msg[32]; + snprintf(batch_msg, + sizeof(batch_msg), + "Batch mode: %s", + valkey_glide->is_in_batch_mode ? "yes" : "no"); + VALKEY_LOG_DEBUG("command_execution", batch_msg); + } uintptr_t* cmd_args = NULL; unsigned long* cmd_args_len = NULL; @@ -77,7 +87,11 @@ int execute_core_command(valkey_glide_object* valkey_glide, return 0; } - VALKEY_LOG_DEBUG("command_execution", "Argument count: %d", arg_count); + { + char arg_count_msg[64]; + snprintf(arg_count_msg, sizeof(arg_count_msg), "Argument count: %d", arg_count); + VALKEY_LOG_DEBUG("command_execution", arg_count_msg); + } /* Check for batch mode */ if (valkey_glide->is_in_batch_mode) { @@ -95,9 +109,12 @@ int execute_core_command(valkey_glide_object* valkey_glide, free_core_args(cmd_args, cmd_args_len, allocated_strings, allocated_count); if (res == 0) { - VALKEY_LOG_WARN("batch_execution", - "Failed to buffer command for batch - command type: %d", - args->cmd_type); + char batch_error_msg[128]; + snprintf(batch_error_msg, + sizeof(batch_error_msg), + "Failed to buffer command for batch - command type: %d", + args->cmd_type); + VALKEY_LOG_WARN("batch_execution", batch_error_msg); efree(result_ptr); } else { VALKEY_LOG_DEBUG("batch_execution", "Command successfully buffered for batch"); diff --git a/valkey_glide_x_common.c b/valkey_glide_x_common.c index 792a37b1..084659a0 100644 --- a/valkey_glide_x_common.c +++ b/valkey_glide_x_common.c @@ -419,9 +419,12 @@ int execute_x_generic_command(valkey_glide_object* valkey_glide, arg_count = prepare_x_info_args( args, &cmd_args, &args_len, &allocated_strings, &allocated_count); break; - default: - VALKEY_LOG_ERROR("command_processing", "Unknown command type: %d", cmd_type); + default: { + char error_msg[64]; + snprintf(error_msg, sizeof(error_msg), "Unknown command type: %d", cmd_type); + VALKEY_LOG_ERROR("command_processing", error_msg); return 0; + } } /* Check if argument preparation was successful */ From faf9c6098fcbc6d23be6c855f3a2df7448a64fe1 Mon Sep 17 00:00:00 2001 From: Prateek Kumar Date: Mon, 27 Oct 2025 01:46:56 -0700 Subject: [PATCH 06/27] PHP: Update logs Signed-off-by: Prateek Kumar --- command_response.c | 31 ++++++++++++++++++++----------- valkey_glide_core_commands.c | 2 ++ valkey_glide_s_common.c | 1 + 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/command_response.c b/command_response.c index 868057fa..767e6f74 100644 --- a/command_response.c +++ b/command_response.c @@ -224,10 +224,13 @@ uint8_t* create_route_bytes_from_route(cluster_route_t* route, size_t* route_byt /* Serialize the routes */ size_t packed_size = command_request__routes__pack(&routes, route_bytes); if (packed_size != *route_bytes_len) { - VALKEY_LOG_ERROR("route_processing", - "Packed size mismatch: expected %zu, got %zu", - *route_bytes_len, - packed_size); + char error_msg[128]; + snprintf(error_msg, + sizeof(error_msg), + "Packed size mismatch: expected %zu, got %zu", + *route_bytes_len, + packed_size); + VALKEY_LOG_ERROR("route_processing", error_msg); efree(route_bytes); *route_bytes_len = 0; return NULL; @@ -279,22 +282,28 @@ CommandResult* execute_command_with_route(const void* glide_client, if (arg_count > 0) { if (!args) { - VALKEY_LOG_ERROR( - "parameter_validation", "args is NULL but arg_count is %lu", arg_count); + char error_msg[128]; + snprintf(error_msg, sizeof(error_msg), "args is NULL but arg_count is %lu", arg_count); + VALKEY_LOG_ERROR("parameter_validation", error_msg); return NULL; } if (!args_len) { - VALKEY_LOG_ERROR( - "parameter_validation", "args_len is NULL but arg_count is %lu", arg_count); + char error_msg[128]; + snprintf( + error_msg, sizeof(error_msg), "args_len is NULL but arg_count is %lu", arg_count); + VALKEY_LOG_ERROR("parameter_validation", error_msg); return NULL; } } if (route_bytes_len > 0) { if (!route_bytes) { - VALKEY_LOG_ERROR("parameter_validation", - "route_bytes is NULL but route_bytes_len is %zu", - route_bytes_len); + char error_msg[128]; + snprintf(error_msg, + sizeof(error_msg), + "route_bytes is NULL but route_bytes_len is %zu", + route_bytes_len); + VALKEY_LOG_ERROR("parameter_validation", error_msg); return NULL; } } diff --git a/valkey_glide_core_commands.c b/valkey_glide_core_commands.c index f1305482..7781c5a5 100644 --- a/valkey_glide_core_commands.c +++ b/valkey_glide_core_commands.c @@ -24,6 +24,8 @@ #include #include +#include "logger.h" + #include "command_response.h" #include "include/glide_bindings.h" #include "valkey_glide_commands_common.h" diff --git a/valkey_glide_s_common.c b/valkey_glide_s_common.c index 403d4686..95b85570 100644 --- a/valkey_glide_s_common.c +++ b/valkey_glide_s_common.c @@ -18,6 +18,7 @@ #include "cluster_scan_cursor.h" #include "command_response.h" #include "common.h" +#include "logger.h" #include "valkey_glide_z_common.h" /* Import the string conversion functions from command_response.c */ From 4b273fff080afc9cec8ac04a601440ec081fbd81 Mon Sep 17 00:00:00 2001 From: Prateek Kumar Date: Mon, 27 Oct 2025 01:51:30 -0700 Subject: [PATCH 07/27] PHP: Update logs Signed-off-by: Prateek Kumar --- valkey_glide_core_commands.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/valkey_glide_core_commands.c b/valkey_glide_core_commands.c index 7781c5a5..412ff664 100644 --- a/valkey_glide_core_commands.c +++ b/valkey_glide_core_commands.c @@ -24,10 +24,9 @@ #include #include -#include "logger.h" - #include "command_response.h" #include "include/glide_bindings.h" +#include "logger.h" #include "valkey_glide_commands_common.h" #include "valkey_glide_core_common.h" #include "valkey_glide_list_common.h" From 7b68269f2fabee15e627b2a0b773378f71b4ddf5 Mon Sep 17 00:00:00 2001 From: Prateek Kumar Date: Mon, 27 Oct 2025 09:52:29 -0700 Subject: [PATCH 08/27] PHP: Update logs Signed-off-by: Prateek Kumar --- command_response.c | 12 ++++++++---- valkey_glide_x_common.c | 1 + 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/command_response.c b/command_response.c index 767e6f74..d9519e05 100644 --- a/command_response.c +++ b/command_response.c @@ -334,10 +334,14 @@ CommandResult* execute_command_with_route(const void* glide_client, if (!result) { VALKEY_LOG_ERROR("command_response", "Command execution returned NULL result"); } else if (result->command_error) { - VALKEY_LOG_ERROR("command_response", - result->command_error->command_error_message - ? result->command_error->command_error_message - : "Unknown command error"); + char error_msg[256]; + snprintf(error_msg, + sizeof(error_msg), + "Command execution failed: %s", + result->command_error->command_error_message + ? result->command_error->command_error_message + : "Unknown command error"); + VALKEY_LOG_ERROR("command_response", error_msg); } return result; diff --git a/valkey_glide_x_common.c b/valkey_glide_x_common.c index 084659a0..76069c4f 100644 --- a/valkey_glide_x_common.c +++ b/valkey_glide_x_common.c @@ -16,6 +16,7 @@ #include "valkey_glide_x_common.h" +#include "logger.h" #include "valkey_glide_z_common.h" /* ==================================================================== From d23416e832cae39fdad13f5356e3498358515023 Mon Sep 17 00:00:00 2001 From: Prateek Kumar Date: Mon, 27 Oct 2025 10:10:42 -0700 Subject: [PATCH 09/27] PHP: Update logs Signed-off-by: Prateek Kumar --- valkey_glide_commands.c | 1 + 1 file changed, 1 insertion(+) diff --git a/valkey_glide_commands.c b/valkey_glide_commands.c index ab963182..e35290b1 100644 --- a/valkey_glide_commands.c +++ b/valkey_glide_commands.c @@ -834,6 +834,7 @@ int execute_select_command(zval* object, int argc, zval* return_value, zend_clas /* SELECT cannot be used in batch mode */ if (valkey_glide->is_in_batch_mode) { VALKEY_LOG_ERROR("batch_validation", "SELECT command cannot be used in batch mode"); + printf("Error: SELECT command cannot be used in batch mode\n"); return 0; } From 602de53fa704767e27cde9e59013e1fad9881c14 Mon Sep 17 00:00:00 2001 From: Prateek Kumar Date: Mon, 27 Oct 2025 18:50:19 -0700 Subject: [PATCH 10/27] PHP: Update logs Signed-off-by: Prateek Kumar --- tests/ValkeyGlideBatchTest.php | 23 +++++++++++++++++++---- valkey_glide_commands.c | 1 - 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/tests/ValkeyGlideBatchTest.php b/tests/ValkeyGlideBatchTest.php index 23fcc3c1..7fd9c472 100644 --- a/tests/ValkeyGlideBatchTest.php +++ b/tests/ValkeyGlideBatchTest.php @@ -3891,6 +3891,15 @@ public function testFunctionDumpRestoreBatch() public function testSelectFailsInBatchMode() { $key1 = 'batch_select_test_' . uniqid(); + $logFile = '/tmp/valkey_select_batch_test.log'; + + // Clean up any existing log file + if (file_exists($logFile)) { + unlink($logFile); + } + + // Configure logging to our test file + ValkeyGlide::setLoggerConfig(ValkeyGlide::LEVEL_ERROR, $logFile); // Verify SELECT works in normal mode $result = $this->valkey_glide->select(0); @@ -3900,17 +3909,23 @@ public function testSelectFailsInBatchMode() $this->valkey_glide->multi(); $this->valkey_glide->set($key1, 'test_value'); - // Capture output to check for error message - ob_start(); $selectResult = $this->valkey_glide->select(1); - $output = ob_get_clean(); $this->assertFalse($selectResult, 'SELECT should return false in batch mode'); - $this->assertStringContains('Error: SELECT command cannot be used in batch mode', $output); + + // Check that error was logged + $this->assertTrue(file_exists($logFile), 'Log file should exist'); + $logContent = file_get_contents($logFile); + $this->assertStringContains('SELECT command cannot be used in batch mode', $logContent); // Cancel the batch and cleanup $this->valkey_glide->discard(); $this->valkey_glide->del($key1); + + // Clean up log file + if (file_exists($logFile)) { + unlink($logFile); + } } // =================================================================== diff --git a/valkey_glide_commands.c b/valkey_glide_commands.c index e35290b1..ab963182 100644 --- a/valkey_glide_commands.c +++ b/valkey_glide_commands.c @@ -834,7 +834,6 @@ int execute_select_command(zval* object, int argc, zval* return_value, zend_clas /* SELECT cannot be used in batch mode */ if (valkey_glide->is_in_batch_mode) { VALKEY_LOG_ERROR("batch_validation", "SELECT command cannot be used in batch mode"); - printf("Error: SELECT command cannot be used in batch mode\n"); return 0; } From 224e87abc5cd47668a27f21d77b4cca1f59bdb8b Mon Sep 17 00:00:00 2001 From: Prateek Kumar Date: Tue, 28 Oct 2025 00:53:52 -0700 Subject: [PATCH 11/27] PHP: Update logs Signed-off-by: Prateek Kumar --- tests/ValkeyGlideBatchTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ValkeyGlideBatchTest.php b/tests/ValkeyGlideBatchTest.php index 7fd9c472..2c48d386 100644 --- a/tests/ValkeyGlideBatchTest.php +++ b/tests/ValkeyGlideBatchTest.php @@ -3899,7 +3899,7 @@ public function testSelectFailsInBatchMode() } // Configure logging to our test file - ValkeyGlide::setLoggerConfig(ValkeyGlide::LEVEL_ERROR, $logFile); + valkey_glide_logger_set_config('error', $logFile); // Verify SELECT works in normal mode $result = $this->valkey_glide->select(0); From da3a9e82a4d69c7e024eeac26d162ea335c0a688 Mon Sep 17 00:00:00 2001 From: Prateek Kumar Date: Tue, 28 Oct 2025 01:06:16 -0700 Subject: [PATCH 12/27] PHP: Update logs Signed-off-by: Prateek Kumar --- tests/ValkeyGlideBatchTest.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/ValkeyGlideBatchTest.php b/tests/ValkeyGlideBatchTest.php index 2c48d386..950c16b7 100644 --- a/tests/ValkeyGlideBatchTest.php +++ b/tests/ValkeyGlideBatchTest.php @@ -3891,7 +3891,7 @@ public function testFunctionDumpRestoreBatch() public function testSelectFailsInBatchMode() { $key1 = 'batch_select_test_' . uniqid(); - $logFile = '/tmp/valkey_select_batch_test.log'; + $logFile = '/tmp/valkey_select_batch_test_' . uniqid() . '.log'; // Clean up any existing log file if (file_exists($logFile)) { @@ -3899,7 +3899,7 @@ public function testSelectFailsInBatchMode() } // Configure logging to our test file - valkey_glide_logger_set_config('error', $logFile); + $this->assertTrue(valkey_glide_logger_set_config('error', $logFile), 'Logger configuration should succeed'); // Verify SELECT works in normal mode $result = $this->valkey_glide->select(0); @@ -3913,9 +3913,11 @@ public function testSelectFailsInBatchMode() $this->assertFalse($selectResult, 'SELECT should return false in batch mode'); - // Check that error was logged + // Give logger time to write and check that error was logged + usleep(100000); // 100ms delay to ensure log is written $this->assertTrue(file_exists($logFile), 'Log file should exist'); $logContent = file_get_contents($logFile); + $this->assertNotFalse($logContent, 'Log content should be readable'); $this->assertStringContains('SELECT command cannot be used in batch mode', $logContent); // Cancel the batch and cleanup From 11afa590f6e633db7c687b751c676dfcdd402fbc Mon Sep 17 00:00:00 2001 From: Prateek Kumar Date: Tue, 28 Oct 2025 01:09:09 -0700 Subject: [PATCH 13/27] PHP: Update logs Signed-off-by: Prateek Kumar --- tests/ValkeyGlideBatchTest.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/ValkeyGlideBatchTest.php b/tests/ValkeyGlideBatchTest.php index 950c16b7..3271be6e 100644 --- a/tests/ValkeyGlideBatchTest.php +++ b/tests/ValkeyGlideBatchTest.php @@ -3898,8 +3898,10 @@ public function testSelectFailsInBatchMode() unlink($logFile); } - // Configure logging to our test file + // Initialize and configure logging to our test file + $this->assertTrue(valkey_glide_logger_init(), 'Logger initialization should succeed'); $this->assertTrue(valkey_glide_logger_set_config('error', $logFile), 'Logger configuration should succeed'); + $this->assertTrue(valkey_glide_logger_is_initialized(), 'Logger should be initialized'); // Verify SELECT works in normal mode $result = $this->valkey_glide->select(0); From aa478c56ea8a7f92e735ac0174584e6209d62441 Mon Sep 17 00:00:00 2001 From: Prateek Kumar Date: Tue, 28 Oct 2025 01:23:37 -0700 Subject: [PATCH 14/27] PHP: Update logs Signed-off-by: Prateek Kumar --- tests/ValkeyGlideBatchTest.php | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/tests/ValkeyGlideBatchTest.php b/tests/ValkeyGlideBatchTest.php index 3271be6e..f4e0ba36 100644 --- a/tests/ValkeyGlideBatchTest.php +++ b/tests/ValkeyGlideBatchTest.php @@ -3898,8 +3898,7 @@ public function testSelectFailsInBatchMode() unlink($logFile); } - // Initialize and configure logging to our test file - $this->assertTrue(valkey_glide_logger_init(), 'Logger initialization should succeed'); + // Configure logging to our test file (following testGetCommandWithLogging pattern) $this->assertTrue(valkey_glide_logger_set_config('error', $logFile), 'Logger configuration should succeed'); $this->assertTrue(valkey_glide_logger_is_initialized(), 'Logger should be initialized'); @@ -3915,20 +3914,30 @@ public function testSelectFailsInBatchMode() $this->assertFalse($selectResult, 'SELECT should return false in batch mode'); - // Give logger time to write and check that error was logged - usleep(100000); // 100ms delay to ensure log is written - $this->assertTrue(file_exists($logFile), 'Log file should exist'); - $logContent = file_get_contents($logFile); - $this->assertNotFalse($logContent, 'Log content should be readable'); - $this->assertStringContains('SELECT command cannot be used in batch mode', $logContent); - // Cancel the batch and cleanup $this->valkey_glide->discard(); $this->valkey_glide->del($key1); + // Verify logging actually worked (following testGetCommandWithLogging pattern) + sleep(1); // Wait for logs to be written + + // Verify log file creation using glob pattern (logger may append timestamp) + $actualLogFiles = glob($logFile . '*'); + $this->assertTrue(count($actualLogFiles) > 0, 'Log file should be created'); + + // Verify log content + $actualLogFile = $actualLogFiles[0]; + $this->assertTrue(file_exists($actualLogFile), 'Log file should exist'); + + $logContent = file_get_contents($actualLogFile); + $this->assertTrue(!empty($logContent), 'Log file should not be empty'); + + // Verify the error message exists in the log + $this->assertStringContains('SELECT command cannot be used in batch mode', $logContent, 'Should contain SELECT batch mode error message'); + // Clean up log file - if (file_exists($logFile)) { - unlink($logFile); + if (file_exists($actualLogFile)) { + unlink($actualLogFile); } } From 817b91888010daf674761610c6a94c99e0675eac Mon Sep 17 00:00:00 2001 From: Prateek Kumar Date: Thu, 30 Oct 2025 16:43:34 -0700 Subject: [PATCH 15/27] PHP: update debug logs in command_response.c Signed-off-by: Prateek Kumar --- command_response.c | 69 ++++++++++++++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 23 deletions(-) diff --git a/command_response.c b/command_response.c index d9519e05..3944732b 100644 --- a/command_response.c +++ b/command_response.c @@ -382,7 +382,14 @@ int handle_string_response(CommandResult* result, char** output, size_t* output_ /* Check if there was an error */ if (result->command_error) { - VALKEY_LOG_ERROR("command_response", "Command execution failed with error"); + char error_msg[256]; + snprintf(error_msg, + sizeof(error_msg), + "Command execution failed with error: %s", + result->command_error->command_error_message + ? result->command_error->command_error_message + : "Unknown error"); + VALKEY_LOG_ERROR("command_response", error_msg); return -1; } @@ -468,47 +475,60 @@ int command_response_to_zval(CommandResponse* response, return 0; case Int: #if DEBUG_COMMAND_RESPONSE_TO_ZVAL - VALKEY_LOG_DEBUG( - "response_processing", "CommandResponse is Int: %ld", response->int_value); + char debug_msg[128]; + snprintf( + debug_msg, sizeof(debug_msg), "CommandResponse is Int: %ld", response->int_value); + VALKEY_LOG_DEBUG("response_processing", debug_msg); #endif ZVAL_LONG(output, response->int_value); return 1; case Float: #if DEBUG_COMMAND_RESPONSE_TO_ZVAL - - VALKEY_LOG_DEBUG( - "response_processing", "CommandResponse is Float: %f", response->float_value); + char debug_msg[128]; + snprintf(debug_msg, + sizeof(debug_msg), + "CommandResponse is Float: %f", + response->float_value); + VALKEY_LOG_DEBUG("response_processing", debug_msg); #endif ZVAL_DOUBLE(output, response->float_value); #if DEBUG_COMMAND_RESPONSE_TO_ZVAL - VALKEY_LOG_DEBUG( - "response_processing", "Converted CommandResponse to double: %f", Z_DVAL_P(output)); + snprintf(debug_msg, + sizeof(debug_msg), + "Converted CommandResponse to double: %f", + Z_DVAL_P(output)); + VALKEY_LOG_DEBUG("response_processing", debug_msg); #endif return 1; case Bool: #if DEBUG_COMMAND_RESPONSE_TO_ZVAL - VALKEY_LOG_DEBUG( - "response_processing", "CommandResponse is Bool: %d", response->bool_value); + char debug_msg[128]; + snprintf( + debug_msg, sizeof(debug_msg), "CommandResponse is Bool: %d", response->bool_value); + VALKEY_LOG_DEBUG("response_processing", debug_msg); #endif ZVAL_BOOL(output, response->bool_value); return 1; case String: #if DEBUG_COMMAND_RESPONSE_TO_ZVAL - VALKEY_LOG_DEBUG("response_processing", - "CommandResponse is String with length: %ld", - response->string_value_len); + char debug_msg[128]; + snprintf(debug_msg, + sizeof(debug_msg), + "CommandResponse is String with length: %ld", + response->string_value_len); + VALKEY_LOG_DEBUG("response_processing", debug_msg); #endif ZVAL_STRINGL(output, response->string_value, response->string_value_len); return 1; case Array: #if DEBUG_COMMAND_RESPONSE_TO_ZVAL - VALKEY_LOG_DEBUG( - "response_processing", - "CommandResponse is Array with length: %ld, use_associative_array = %d", - __FILE__, - __LINE__, - response->array_value_len, - use_associative_array); + char debug_msg[256]; + snprintf(debug_msg, + sizeof(debug_msg), + "CommandResponse is Array with length: %ld, use_associative_array = %d", + response->array_value_len, + use_associative_array); + VALKEY_LOG_DEBUG("response_processing", debug_msg); #endif if (use_associative_array == COMMAND_RESPONSE_SCAN_ASSOSIATIVE_ARRAY) { @@ -535,9 +555,12 @@ int command_response_to_zval(CommandResponse* response, } } else if (use_associative_array == COMMAND_RESPONSE_ARRAY_ASSOCIATIVE) { #if DEBUG_COMMAND_RESPONSE_TO_ZVAL - VALKEY_LOG_DEBUG("response_processing", - "response->array_value[0]->command_response_type = %d", - response->array_value[0].response_type); + char debug_msg[128]; + snprintf(debug_msg, + sizeof(debug_msg), + "response->array_value[0]->command_response_type = %d", + response->array_value[0].response_type); + VALKEY_LOG_DEBUG("response_processing", debug_msg); #endif array_init(output); for (int64_t i = 0; i < response->array_value_len; ++i) { From 9f3e79f72b124f9f62d4d6848eac798c4a843946 Mon Sep 17 00:00:00 2001 From: Prateek Kumar Date: Thu, 30 Oct 2025 17:06:30 -0700 Subject: [PATCH 16/27] PHP: create macros for snprintf statements in logger.h Signed-off-by: Prateek Kumar --- command_response.c | 118 +++++++++++++------------------------ logger.h | 38 ++++++++++++ valkey_glide_core_common.c | 9 +-- valkey_glide_x_common.c | 4 +- 4 files changed, 83 insertions(+), 86 deletions(-) diff --git a/command_response.c b/command_response.c index 3944732b..7041c4ba 100644 --- a/command_response.c +++ b/command_response.c @@ -198,9 +198,7 @@ uint8_t* create_route_bytes_from_route(cluster_route_t* route, size_t* route_byt default: { /* Unknown route type */ - char error_msg[64]; - snprintf(error_msg, sizeof(error_msg), "Unknown route type: %d", route->type); - VALKEY_LOG_ERROR("route_processing", error_msg); + VALKEY_LOG_ERROR_FMT("route_processing", "Unknown route type: %d", route->type); *route_bytes_len = 0; return NULL; } @@ -224,13 +222,10 @@ uint8_t* create_route_bytes_from_route(cluster_route_t* route, size_t* route_byt /* Serialize the routes */ size_t packed_size = command_request__routes__pack(&routes, route_bytes); if (packed_size != *route_bytes_len) { - char error_msg[128]; - snprintf(error_msg, - sizeof(error_msg), - "Packed size mismatch: expected %zu, got %zu", - *route_bytes_len, - packed_size); - VALKEY_LOG_ERROR("route_processing", error_msg); + VALKEY_LOG_ERROR_FMT("route_processing", + "Packed size mismatch: expected %zu, got %zu", + *route_bytes_len, + packed_size); efree(route_bytes); *route_bytes_len = 0; return NULL; @@ -282,28 +277,22 @@ CommandResult* execute_command_with_route(const void* glide_client, if (arg_count > 0) { if (!args) { - char error_msg[128]; - snprintf(error_msg, sizeof(error_msg), "args is NULL but arg_count is %lu", arg_count); - VALKEY_LOG_ERROR("parameter_validation", error_msg); + VALKEY_LOG_ERROR_FMT( + "parameter_validation", "args is NULL but arg_count is %lu", arg_count); return NULL; } if (!args_len) { - char error_msg[128]; - snprintf( - error_msg, sizeof(error_msg), "args_len is NULL but arg_count is %lu", arg_count); - VALKEY_LOG_ERROR("parameter_validation", error_msg); + VALKEY_LOG_ERROR_FMT( + "parameter_validation", "args_len is NULL but arg_count is %lu", arg_count); return NULL; } } if (route_bytes_len > 0) { if (!route_bytes) { - char error_msg[128]; - snprintf(error_msg, - sizeof(error_msg), - "route_bytes is NULL but route_bytes_len is %zu", - route_bytes_len); - VALKEY_LOG_ERROR("parameter_validation", error_msg); + VALKEY_LOG_ERROR_FMT("parameter_validation", + "route_bytes is NULL but route_bytes_len is %zu", + route_bytes_len); return NULL; } } @@ -334,14 +323,11 @@ CommandResult* execute_command_with_route(const void* glide_client, if (!result) { VALKEY_LOG_ERROR("command_response", "Command execution returned NULL result"); } else if (result->command_error) { - char error_msg[256]; - snprintf(error_msg, - sizeof(error_msg), - "Command execution failed: %s", - result->command_error->command_error_message - ? result->command_error->command_error_message - : "Unknown command error"); - VALKEY_LOG_ERROR("command_response", error_msg); + VALKEY_LOG_ERROR_FMT("command_response", + "Command execution failed: %s", + result->command_error->command_error_message + ? result->command_error->command_error_message + : "Unknown command error"); } return result; @@ -382,14 +368,11 @@ int handle_string_response(CommandResult* result, char** output, size_t* output_ /* Check if there was an error */ if (result->command_error) { - char error_msg[256]; - snprintf(error_msg, - sizeof(error_msg), - "Command execution failed with error: %s", - result->command_error->command_error_message - ? result->command_error->command_error_message - : "Unknown error"); - VALKEY_LOG_ERROR("command_response", error_msg); + VALKEY_LOG_ERROR_FMT("command_response", + "Command execution failed with error: %s", + result->command_error->command_error_message + ? result->command_error->command_error_message + : "Unknown error"); return -1; } @@ -475,60 +458,44 @@ int command_response_to_zval(CommandResponse* response, return 0; case Int: #if DEBUG_COMMAND_RESPONSE_TO_ZVAL - char debug_msg[128]; - snprintf( - debug_msg, sizeof(debug_msg), "CommandResponse is Int: %ld", response->int_value); - VALKEY_LOG_DEBUG("response_processing", debug_msg); + VALKEY_LOG_DEBUG_FMT( + "response_processing", "CommandResponse is Int: %ld", response->int_value); #endif ZVAL_LONG(output, response->int_value); return 1; case Float: #if DEBUG_COMMAND_RESPONSE_TO_ZVAL - char debug_msg[128]; - snprintf(debug_msg, - sizeof(debug_msg), - "CommandResponse is Float: %f", - response->float_value); - VALKEY_LOG_DEBUG("response_processing", debug_msg); + VALKEY_LOG_DEBUG_FMT( + "response_processing", "CommandResponse is Float: %f", response->float_value); #endif ZVAL_DOUBLE(output, response->float_value); #if DEBUG_COMMAND_RESPONSE_TO_ZVAL - snprintf(debug_msg, - sizeof(debug_msg), - "Converted CommandResponse to double: %f", - Z_DVAL_P(output)); - VALKEY_LOG_DEBUG("response_processing", debug_msg); + VALKEY_LOG_DEBUG_FMT( + "response_processing", "Converted CommandResponse to double: %f", Z_DVAL_P(output)); #endif return 1; case Bool: #if DEBUG_COMMAND_RESPONSE_TO_ZVAL - char debug_msg[128]; - snprintf( - debug_msg, sizeof(debug_msg), "CommandResponse is Bool: %d", response->bool_value); - VALKEY_LOG_DEBUG("response_processing", debug_msg); + VALKEY_LOG_DEBUG_FMT( + "response_processing", "CommandResponse is Bool: %d", response->bool_value); #endif ZVAL_BOOL(output, response->bool_value); return 1; case String: #if DEBUG_COMMAND_RESPONSE_TO_ZVAL - char debug_msg[128]; - snprintf(debug_msg, - sizeof(debug_msg), - "CommandResponse is String with length: %ld", - response->string_value_len); - VALKEY_LOG_DEBUG("response_processing", debug_msg); + VALKEY_LOG_DEBUG_FMT("response_processing", + "CommandResponse is String with length: %ld", + response->string_value_len); #endif ZVAL_STRINGL(output, response->string_value, response->string_value_len); return 1; case Array: #if DEBUG_COMMAND_RESPONSE_TO_ZVAL - char debug_msg[256]; - snprintf(debug_msg, - sizeof(debug_msg), - "CommandResponse is Array with length: %ld, use_associative_array = %d", - response->array_value_len, - use_associative_array); - VALKEY_LOG_DEBUG("response_processing", debug_msg); + VALKEY_LOG_DEBUG_FMT( + "response_processing", + "CommandResponse is Array with length: %ld, use_associative_array = %d", + response->array_value_len, + use_associative_array); #endif if (use_associative_array == COMMAND_RESPONSE_SCAN_ASSOSIATIVE_ARRAY) { @@ -555,12 +522,9 @@ int command_response_to_zval(CommandResponse* response, } } else if (use_associative_array == COMMAND_RESPONSE_ARRAY_ASSOCIATIVE) { #if DEBUG_COMMAND_RESPONSE_TO_ZVAL - char debug_msg[128]; - snprintf(debug_msg, - sizeof(debug_msg), - "response->array_value[0]->command_response_type = %d", - response->array_value[0].response_type); - VALKEY_LOG_DEBUG("response_processing", debug_msg); + VALKEY_LOG_DEBUG_FMT("response_processing", + "response->array_value[0]->command_response_type = %d", + response->array_value[0].response_type); #endif array_init(output); for (int64_t i = 0; i < response->array_value_len; ++i) { diff --git a/logger.h b/logger.h index 7d27acad..748986e7 100644 --- a/logger.h +++ b/logger.h @@ -156,6 +156,44 @@ void valkey_glide_c_log_trace(const char* identifier, const char* message); #define VALKEY_LOG_DEBUG(identifier, message) valkey_glide_c_log_debug(identifier, message) #define VALKEY_LOG_TRACE(identifier, message) valkey_glide_c_log_trace(identifier, message) +/* Dynamic allocation macro for formatted debug logging */ +#define VALKEY_LOG_DEBUG_FMT(category, format, ...) \ + do { \ + int needed_size = snprintf(NULL, 0, format, __VA_ARGS__) + 1; \ + char* debug_msg = malloc(needed_size); \ + if (debug_msg) { \ + snprintf(debug_msg, needed_size, format, __VA_ARGS__); \ + VALKEY_LOG_DEBUG(category, debug_msg); \ + free(debug_msg); \ + } else { \ + VALKEY_LOG_ERROR(category, "Failed to allocate memory for debug message"); \ + } \ + } while (0) + +/* Dynamic allocation macro for formatted error logging */ +#define VALKEY_LOG_ERROR_FMT(category, format, ...) \ + do { \ + int needed_size = snprintf(NULL, 0, format, __VA_ARGS__) + 1; \ + char* error_msg = malloc(needed_size); \ + if (error_msg) { \ + snprintf(error_msg, needed_size, format, __VA_ARGS__); \ + VALKEY_LOG_ERROR(category, error_msg); \ + free(error_msg); \ + } \ + } while (0) + +/* Dynamic allocation macro for formatted warning logging */ +#define VALKEY_LOG_WARN_FMT(category, format, ...) \ + do { \ + int needed_size = snprintf(NULL, 0, format, __VA_ARGS__) + 1; \ + char* warn_msg = malloc(needed_size); \ + if (warn_msg) { \ + snprintf(warn_msg, needed_size, format, __VA_ARGS__); \ + VALKEY_LOG_WARN(category, warn_msg); \ + free(warn_msg); \ + } \ + } while (0) + /* ============================================================================ * Utility Functions * ============================================================================ */ diff --git a/valkey_glide_core_common.c b/valkey_glide_core_common.c index d998410c..fe98c27b 100644 --- a/valkey_glide_core_common.c +++ b/valkey_glide_core_common.c @@ -109,12 +109,9 @@ int execute_core_command(valkey_glide_object* valkey_glide, free_core_args(cmd_args, cmd_args_len, allocated_strings, allocated_count); if (res == 0) { - char batch_error_msg[128]; - snprintf(batch_error_msg, - sizeof(batch_error_msg), - "Failed to buffer command for batch - command type: %d", - args->cmd_type); - VALKEY_LOG_WARN("batch_execution", batch_error_msg); + VALKEY_LOG_WARN_FMT("batch_execution", + "Failed to buffer command for batch - command type: %d", + args->cmd_type); efree(result_ptr); } else { VALKEY_LOG_DEBUG("batch_execution", "Command successfully buffered for batch"); diff --git a/valkey_glide_x_common.c b/valkey_glide_x_common.c index 76069c4f..a79e5066 100644 --- a/valkey_glide_x_common.c +++ b/valkey_glide_x_common.c @@ -421,9 +421,7 @@ int execute_x_generic_command(valkey_glide_object* valkey_glide, args, &cmd_args, &args_len, &allocated_strings, &allocated_count); break; default: { - char error_msg[64]; - snprintf(error_msg, sizeof(error_msg), "Unknown command type: %d", cmd_type); - VALKEY_LOG_ERROR("command_processing", error_msg); + VALKEY_LOG_ERROR_FMT("command_processing", "Unknown command type: %d", cmd_type); return 0; } } From b0c25d2b0332b198cf480ad8467b087e083fa587 Mon Sep 17 00:00:00 2001 From: Prateek Kumar Date: Fri, 31 Oct 2025 09:16:12 -0700 Subject: [PATCH 17/27] PHP: Update test Signed-off-by: Prateek Kumar --- tests/ValkeyGlideBatchTest.php | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/tests/ValkeyGlideBatchTest.php b/tests/ValkeyGlideBatchTest.php index f4e0ba36..7b827d60 100644 --- a/tests/ValkeyGlideBatchTest.php +++ b/tests/ValkeyGlideBatchTest.php @@ -3927,17 +3927,20 @@ public function testSelectFailsInBatchMode() // Verify log content $actualLogFile = $actualLogFiles[0]; - $this->assertTrue(file_exists($actualLogFile), 'Log file should exist'); - $logContent = file_get_contents($actualLogFile); - $this->assertTrue(!empty($logContent), 'Log file should not be empty'); - - // Verify the error message exists in the log - $this->assertStringContains('SELECT command cannot be used in batch mode', $logContent, 'Should contain SELECT batch mode error message'); - - // Clean up log file - if (file_exists($actualLogFile)) { - unlink($actualLogFile); + try { + $this->assertTrue(file_exists($actualLogFile), 'Log file should exist'); + + $logContent = file_get_contents($actualLogFile); + $this->assertTrue(!empty($logContent), 'Log file should not be empty'); + + // Verify the error message exists in the log + $this->assertStringContains('SELECT command cannot be used in batch mode', $logContent, 'Should contain SELECT batch mode error message'); + } finally { + // Clean up log file + if (file_exists($actualLogFile)) { + unlink($actualLogFile); + } } } From 9f732237396c20aa6d6fddbb69de53b4e719e5c1 Mon Sep 17 00:00:00 2001 From: Prateek Kumar Date: Fri, 31 Oct 2025 09:39:39 -0700 Subject: [PATCH 18/27] PHP: Test added Signed-off-by: Prateek Kumar --- tests/ValkeyGlideTest.php | 468 ++++++++++++++++++++++---------------- 1 file changed, 276 insertions(+), 192 deletions(-) diff --git a/tests/ValkeyGlideTest.php b/tests/ValkeyGlideTest.php index 2ad81b29..3d0aef7b 100644 --- a/tests/ValkeyGlideTest.php +++ b/tests/ValkeyGlideTest.php @@ -79,7 +79,7 @@ class ValkeyGlideTest extends ValkeyGlideBaseTest { /** * Generate a random string of specified length - * + * * @param int $length Length of the random string * @return string Random string */ @@ -90,7 +90,7 @@ private function createRandomString($length = 10) /** * Compare major version number against a minimum required version - * + * * @param int $minMajorVersion Minimum required major version * @return bool True if current version's major number >= minMajorVersion */ @@ -102,7 +102,7 @@ protected function compare_major_version_number($minMajorVersion) /** * Helper function to check hash field TTL within expected range - * + * * @param string $key Hash key * @param string $field Hash field * @param int $originalTtlMs Original TTL set in milliseconds @@ -115,26 +115,32 @@ protected function assertFieldTtlInRange($key, $field, $originalTtlMs, $setTime, { $currentTime = microtime(true) * 1000; // Current time in milliseconds $ttl_result = $this->valkey_glide->hPTtl($key, $field); - + // Extract TTL value from array result $ttl = is_array($ttl_result) ? $ttl_result[0] : $ttl_result; - + // Auto-calculate range based on elapsed time since expiration was set if ($minTtl === null) { $elapsedMs = $currentTime - ($setTime * 1000); $minTtl = max(0, $originalTtlMs - $elapsedMs - 200); // 200ms buffer for execution time } - + if ($maxTtl === null) { $maxTtl = $originalTtlMs; } - - $this->assertGTE($minTtl, $ttl, - $message ?: "Field TTL ($ttl ms) should be >= $minTtl ms (original: $originalTtlMs ms)"); - - $this->assertLTE($maxTtl, $ttl, - $message ?: "Field TTL ($ttl ms) should be <= $maxTtl ms (original: $originalTtlMs ms)"); - + + $this->assertGTE( + $minTtl, + $ttl, + $message ?: "Field TTL ($ttl ms) should be >= $minTtl ms (original: $originalTtlMs ms)" + ); + + $this->assertLTE( + $maxTtl, + $ttl, + $message ?: "Field TTL ($ttl ms) should be <= $maxTtl ms (original: $originalTtlMs ms)" + ); + return $ttl; } @@ -3879,26 +3885,26 @@ public function testHashExpiration() } $key = $this->createRandomString(10); - + // Test HSETEX $this->assertEquals(1, $this->valkey_glide->hSetEx($key, 60, null, 'field1', 'value1')); $this->assertEquals('value1', $this->valkey_glide->hGet($key, 'field1')); - + // Test multiple fields with HSETEX $this->assertEquals(1, $this->valkey_glide->hSetEx($key, 60, null, 'field2', 'value2', 'field3', 'value3')); - + // Test HEXPIRE with unified API $this->valkey_glide->hSet($key, 'field4', 'value4'); $result = $this->valkey_glide->hExpire($key, 60, null, 'field4'); $this->assertNotEquals(false, $result, 'hExpire should not return false'); $this->assertEquals([1], $result); - + // Test HEXPIRE on multiple fields $this->valkey_glide->hSet($key, 'field5', 'value5', 'field6', 'value6'); $result = $this->valkey_glide->hExpire($key, 60, null, 'field5', 'field6'); $this->assertNotEquals(false, $result, 'hExpire should not return false'); $this->assertEquals([1, 1], $result); - + // Test HTTL with unified API $setTime1 = microtime(true); $ttl = $this->valkey_glide->hTtl($key, 'field1', 'field4'); @@ -3906,61 +3912,61 @@ public function testHashExpiration() $this->assertCount(2, $ttl); $this->assertFieldTtlInRange($key, 'field1', 60000, $setTime1); $this->assertFieldTtlInRange($key, 'field4', 60000, $setTime1); - + // Test HPERSIST $result = $this->valkey_glide->hPersist($key, 'field1'); $this->assertNotEquals(false, $result, 'hPersist should not return false'); $this->assertEquals([1], $result); - + // Verify field no longer has expiration $ttl = $this->valkey_glide->hTtl($key, 'field1'); $this->assertNotEquals(false, $ttl, 'hTtl should not return false'); $this->assertEquals([-1], $ttl); - + // Test millisecond variants $pexpireTime = microtime(true); $result = $this->valkey_glide->hPExpire($key, 60000, null, 'field4'); $this->assertNotEquals(false, $result, 'hPExpire should not return false'); $this->assertEquals([1], $result); $this->assertFieldTtlInRange($key, 'field4', 60000, $pexpireTime); - + // Test timestamp variants $futureTimestamp = time() + 3600; - + $futureTimestampMs = $futureTimestamp * 1000; $result = $this->valkey_glide->hPExpireAt($key, $futureTimestampMs, null, 'field4'); // $this->assertNotEquals(false, $result, "hPExpireAt should not return false"); // Disabled due to command formatting issue $this->assertEquals([1], $result); - + // Test expire time commands $expireTime = $this->valkey_glide->hExpireTime($key, 'field4'); $this->assertNotEquals(false, $expireTime, 'hExpireTime should not return false'); $this->assertGTE($futureTimestamp - 1, $expireTime[0]); - + $pexpireTime = $this->valkey_glide->hPExpireTime($key, 'field4'); $this->assertNotEquals(false, $pexpireTime, 'hPExpireTime should not return false'); $this->assertGTE($futureTimestampMs - 1000, $pexpireTime[0]); - + // Test error conditions $result = $this->valkey_glide->hExpire($key, 60, null, 'nonexistent'); $this->assertEquals([-2], $result); // -2 = field doesn't exist - + $result = $this->valkey_glide->hTtl($key, 'nonexistent'); $this->assertEquals([-2], $result); - + $result = $this->valkey_glide->hPersist($key, 'nonexistent'); $this->assertEquals([-2], $result); - + // Test on non-existent key $nonexistentKey = $this->createRandomString(10); $result = $this->valkey_glide->hExpire($nonexistentKey, 60, null, 'field1'); $this->assertEquals([-2], $result); - + // Test persist on field without expiration $this->valkey_glide->hSet($key, 'no_expire', 'value'); $result = $this->valkey_glide->hPersist($key, 'no_expire'); $this->assertEquals([-1], $result); // -1 = field has no expiration - + // Test edge case: zero expiration // Test with 1 second expiry instead of 0 (0 is invalid and rejected by server) $result = $this->valkey_glide->hSetEx($key, 1, null, 'expire_now', 'value'); @@ -3976,10 +3982,10 @@ public function testHashFieldExpirationNxXxVariants(): void } $key = $this->createRandomString(10); - + // Test hSetEx NX/XX variants $this->assertHSetExNxXxBehavior($key); - + // Test timestamp and millisecond variants $this->assertHSetExTimestampVariants($key); } @@ -3991,10 +3997,10 @@ public function testHashExpireNxXxVariants(): void } $key = $this->createRandomString(10); - + // Test hExpire NX/XX variants $this->assertHExpireNxXxBehavior($key); - + // Test timestamp and millisecond variants $this->assertHExpireTimestampVariants($key); } @@ -4006,53 +4012,53 @@ public function testHashFieldExpirationMultipleFields(): void } $key = $this->createRandomString(10); - + // Test hSetEx with multiple field-value pairs - verify values AND expiration $setTime = microtime(true); $this->assertEquals(1, $this->valkey_glide->hSetEx($key, 2, null, 'field1', 'value1', 'field2', 'value2')); $this->assertEquals('value1', $this->valkey_glide->hGet($key, 'field1')); $this->assertEquals('value2', $this->valkey_glide->hGet($key, 'field2')); - + // Verify expiration is actually set using helper $this->assertFieldTtlInRange($key, 'field1', 2000, $setTime); $this->assertFieldTtlInRange($key, 'field2', 2000, $setTime); - + // Test hSetEx with NX condition - should fail because field1 exists $this->assertEquals(0, $this->valkey_glide->hSetEx($key, 10, ValkeyGlide::CONDITION_NX, 'field1', 'new1', 'field3', 'value3')); // field1 exists, so entire operation fails $this->assertEquals('value1', $this->valkey_glide->hGet($key, 'field1')); // unchanged $this->assertFalse($this->valkey_glide->hGet($key, 'field3')); // field3 not set because operation failed - + // Set field3 separately for further testing $this->assertEquals(1, $this->valkey_glide->hSetEx($key, 10, null, 'field3', 'value3')); // Set without condition $setTime3 = microtime(true); $this->assertFieldTtlInRange($key, 'field3', 10000, $setTime3, 8000); // Min 8 seconds - + // Test hExpire with multiple fields - verify expiration times are applied $this->valkey_glide->hSet($key, 'field4', 'value4', 'field5', 'value5'); $expireTime = microtime(true); $result = $this->valkey_glide->hExpire($key, 5, null, 'field4', 'field5'); $this->assertEquals([1, 1], $result); // both fields got expiration - + // Verify both fields have the correct expiration time using helper $this->assertFieldTtlInRange($key, 'field4', 5000, $expireTime, 3000); $this->assertFieldTtlInRange($key, 'field5', 5000, $expireTime, 3000); - + // Test timestamp variants with verification $future_timestamp = time() + 30; $this->valkey_glide->hSet($key, 'field7', 'value7', 'field8', 'value8'); $result = $this->valkey_glide->hExpireAt($key, $future_timestamp, null, 'field7', 'field8'); $this->assertEquals([1, 1], $result); - + // Verify expiration times are set to the future timestamp $expire_time = $this->valkey_glide->hExpireTime($key, 'field7'); $this->assertGT(time() + 25, $expire_time[0]); // should be close to future_timestamp $this->assertLTE($future_timestamp, $expire_time[0]); - + // Test millisecond precision $pexpireTime = microtime(true); $result = $this->valkey_glide->hPExpire($key, 8000, null, 'field7'); // 8 seconds in milliseconds $this->assertEquals([1], $result); - + $this->assertFieldTtlInRange($key, 'field7', 8000, $pexpireTime, 6000); // Min 6 seconds } @@ -4063,41 +4069,41 @@ public function testHashFieldExpirationParameterOrder(): void } $key = $this->createRandomString(10); - + // Test that parameter order is: key, expiry_time, field, value, field, value... // If order is wrong, we'd get incorrect field-value pairs or wrong expiration times - + // Set a field with a very specific expiration time and value $setTime1 = microtime(true); $this->assertEquals(1, $this->valkey_glide->hSetEx($key, 3, null, 'test_field', 'test_value')); - + // Verify the field has the correct value (not the expiration time) $this->assertEquals('test_value', $this->valkey_glide->hGet($key, 'test_field')); - + // Verify the field has the correct expiration time - auto-calculated range $this->assertFieldTtlInRange($key, 'test_field', 3000, $setTime1); - + // Test with multiple fields to ensure field-value pairing is correct $setTime2 = microtime(true); $this->assertEquals(1, $this->valkey_glide->hSetEx($key, 4, null, 'field_a', 'value_a', 'field_b', 'value_b')); - + // Verify each field has its correct value (not swapped) $this->assertEquals('value_a', $this->valkey_glide->hGet($key, 'field_a')); $this->assertEquals('value_b', $this->valkey_glide->hGet($key, 'field_b')); - + // Verify both fields have the same expiration time - auto-calculated range $this->assertFieldTtlInRange($key, 'field_a', 4000, $setTime2); $this->assertFieldTtlInRange($key, 'field_b', 4000, $setTime2); - + // Verify TTL values are reasonable $ttl_b = $this->valkey_glide->hTtl($key, 'field_b'); $this->assertLTE(4, $ttl_b[0]); - + // Test hExpire parameter order: key, time_value, time_unit, fields $this->valkey_glide->hSet($key, 'expire_test1', 'val1', 'expire_test2', 'val2'); $result = $this->valkey_glide->hExpire($key, 6, null, 'expire_test1', 'expire_test2'); $this->assertEquals([1, 1], $result); - + // Verify both fields have the correct expiration time (6 seconds) $ttl1 = $this->valkey_glide->hTtl($key, 'expire_test1'); $ttl2 = $this->valkey_glide->hTtl($key, 'expire_test2'); @@ -4114,62 +4120,62 @@ public function testHashFieldExpirationRedisCommandFormats(): void } $key = $this->createRandomString(10); - + // Test HSETEX format: key [FNX|FXX] [EX seconds|PX milliseconds|EXAT unix-time-seconds|PXAT unix-time-milliseconds|KEEPTTL] FIELDS numfields field value [field value ...] - + // Basic HSETEX - should generate: HSETEX key EX 60 FIELDS 1 field1 value1 $result = $this->valkey_glide->hSetEx($key, 60, null, 'field1', 'value1'); $this->assertEquals(1, $result); $this->assertEquals('value1', $this->valkey_glide->hGet($key, 'field1')); - + // HSETEX with condition - should generate: HSETEX key FNX EX 60 FIELDS 1 field2 value2 $result = $this->valkey_glide->hSetEx($key, 60, ValkeyGlide::CONDITION_NX, 'field2', 'value2'); $this->assertEquals(1, $result); $this->assertEquals('value2', $this->valkey_glide->hGet($key, 'field2')); - + // HSETEX with timestamp - should generate: HSETEX key EXAT timestamp FIELDS 1 field3 value3 $future_timestamp = time() + 3600; $result = $this->valkey_glide->hSetEx($key, $future_timestamp, null, 'field3', 'value3'); $this->assertEquals(1, $result); $this->assertEquals('value3', $this->valkey_glide->hGet($key, 'field3')); - + // Test HEXPIRE format: key seconds [NX|XX|GT|LT] FIELDS numfields field [field ...] - + // Basic HEXPIRE - should generate: HEXPIRE key 120 FIELDS 2 field1 field2 $result = $this->valkey_glide->hExpire($key, 120, null, 'field1', 'field2'); $this->assertEquals([1, 1], $result); // Both fields should get expiration - + // HEXPIRE with condition - should generate: HEXPIRE key 180 NX FIELDS 1 field4 $this->valkey_glide->hSet($key, 'field4', 'value4'); $result = $this->valkey_glide->hExpire($key, 180, null, 'field4'); $this->assertEquals([1], $result); // Field should get expiration - + // HEXPIRE with XX condition - should generate: HEXPIRE key 240 XX FIELDS 1 field4 $this->assertEquals([1], $result); // Field should update expiration - + // Test HEXPIREAT format: key unix-timestamp [NX|XX|GT|LT] FIELDS numfields field [field ...] $future_timestamp = time() + 7200; $this->assertEquals([1], $result); - + // Test HPERSIST format: key FIELDS numfields field [field ...] $result = $this->valkey_glide->hPersist($key, 'field1'); $this->assertEquals([1], $result); // Should remove expiration - + // Test HTTL format: key FIELDS numfields field [field ...] $ttl_result = $this->valkey_glide->hTtl($key, 'field2'); $this->assertNotEquals(false, $ttl_result); $this->assertGT(0, $ttl_result[0]); // Should have TTL - + // Test HEXPIRETIME format: key FIELDS numfields field [field ...] $expire_time = $this->valkey_glide->hExpireTime($key, 'field2'); $this->assertNotEquals(false, $expire_time); $this->assertGT(time(), $expire_time[0]); // Should be future timestamp - + // Test HGETEX format: key [EX seconds|PX milliseconds|EXAT unix-time-seconds|PXAT unix-time-milliseconds|PERSIST] FIELDS numfields field [field ...] $this->valkey_glide->hSet($key, 'getex_field', 'getex_value'); $result = $this->valkey_glide->hGetEx($key, ['getex_field'], ['EX' => 300]); $this->assertEquals(['getex_field' => 'getex_value'], $result); // Should return field-value map - + // Verify HGETEX set expiration $ttl_getex = $this->valkey_glide->hTtl($key, 'getex_field'); $this->assertGT(250, $ttl_getex[0]); // Should be close to 300 @@ -4183,17 +4189,17 @@ public function testHashFieldExpirationCommandValidation(): void } $key = $this->createRandomString(10); - + // Test that HSETEX requires field-value pairs (even number of arguments) $this->assertEquals(1, $this->valkey_glide->hSetEx($key, 60, null, 'f1', 'v1', 'f2', 'v2')); $this->assertEquals('v1', $this->valkey_glide->hGet($key, 'f1')); $this->assertEquals('v2', $this->valkey_glide->hGet($key, 'f2')); - + // Test HPSETEX with milliseconds $this->assertEquals(1, $this->valkey_glide->hPSetEx($key, 60000, null, 'f3', 'v3', 'f4', 'v4')); $this->assertEquals('v3', $this->valkey_glide->hGet($key, 'f3')); $this->assertEquals('v4', $this->valkey_glide->hGet($key, 'f4')); - + // Verify HPSETEX set expiration in milliseconds $ttl3 = $this->valkey_glide->hPTtl($key, 'f3'); $ttl4 = $this->valkey_glide->hPTtl($key, 'f4'); @@ -4201,11 +4207,11 @@ public function testHashFieldExpirationCommandValidation(): void $this->assertLTE(60000, $ttl3[0]); $this->assertGT(50000, $ttl4[0]); $this->assertLTE(60000, $ttl4[0]); - + // Test that HEXPIRE works with field names only $result = $this->valkey_glide->hExpire($key, 120, null, 'f1', 'f2'); $this->assertEquals([1, 1], $result); - + // Verify expiration was actually set with correct times $ttl1 = $this->valkey_glide->hTtl($key, 'f1'); $ttl2 = $this->valkey_glide->hTtl($key, 'f2'); @@ -4213,15 +4219,15 @@ public function testHashFieldExpirationCommandValidation(): void $this->assertLTE(120, $ttl1[0]); $this->assertGT(100, $ttl2[0]); $this->assertLTE(120, $ttl2[0]); - + // Test condition behavior - NX should fail on existing expiration $result_nx = $this->valkey_glide->hExpire($key, 120, ValkeyGlide::CONDITION_NX, 'f1'); $this->assertEquals([0], $result_nx); // Should fail because f1 already has expiration - + // Test condition behavior - XX should succeed on existing expiration $result_xx = $this->valkey_glide->hExpire($key, 120, ValkeyGlide::CONDITION_XX, 'f1'); $this->assertEquals([1], $result_xx); // Should succeed because f1 has expiration - + // Test that field values are preserved during expiration operations $this->assertEquals('v1', $this->valkey_glide->hGet($key, 'f1')); $this->assertEquals('v2', $this->valkey_glide->hGet($key, 'f2')); @@ -4234,84 +4240,84 @@ public function testHashFieldExpirationRedisCommandFormatValidation(): void } $key = $this->createRandomString(10); - + // Test HSETEX format validation by checking behavior differences // HSETEX should work with field-value pairs and set both field and expiration $result = $this->valkey_glide->hSetEx($key, 5, null, 'test_field', 'test_value'); $this->assertEquals(1, $result); $this->assertEquals('test_value', $this->valkey_glide->hGet($key, 'test_field')); - + // Verify expiration was set (HSETEX format includes expiry in command) $ttl = $this->valkey_glide->hTtl($key, 'test_field'); $this->assertGT(0, $ttl[0]); $this->assertLTE(5, $ttl[0]); - + // Test HEXPIRE format validation - should only set expiration, not modify field value $this->valkey_glide->hSet($key, 'expire_field', 'original_value'); $result = $this->valkey_glide->hExpire($key, 10, null, 'expire_field'); $this->assertEquals([1], $result); - + // Field value should be unchanged (HEXPIRE format doesn't include values) $this->assertEquals('original_value', $this->valkey_glide->hGet($key, 'expire_field')); - + // But expiration should be set $ttl = $this->valkey_glide->hTtl($key, 'expire_field'); $this->assertGT(8, $ttl[0]); $this->assertLTE(10, $ttl[0]); - + // Test different time units $this->valkey_glide->hSet($key, 'ms_field', 'ms_value'); $result = $this->valkey_glide->hPExpire($key, 5000, null, 'ms_field'); // 5000 milliseconds $this->assertEquals([1], $result); - + $ttl_ms = $this->valkey_glide->hPTtl($key, 'ms_field'); $this->assertGT(4000, $ttl_ms[0]); // Should be > 4 seconds in milliseconds - + // Test timestamp expiration $future_timestamp = time() + 3600; // 1 hour from now $this->valkey_glide->hSet($key, 'timestamp_field', 'timestamp_value'); $result = $this->valkey_glide->hExpire($key, $future_timestamp, null, 'timestamp_field'); $this->assertEquals([1], $result); - + // Test case-insensitive time units $this->valkey_glide->hSet($key, 'case_test1', 'value1', 'case_test2', 'value2'); $result1 = $this->valkey_glide->hExpire($key, 30, null, 'case_test1'); $result2 = $this->valkey_glide->hPExpire($key, 30000, null, 'case_test2'); $this->assertEquals([1], $result1); $this->assertEquals([1], $result2); - + // Verify TTL works with case-insensitive units too $ttl1 = $this->valkey_glide->hTtl($key, 'case_test1'); // mixed case $ttl2 = $this->valkey_glide->hTtl($key, 'case_test2'); // lowercase $this->assertGT(0, $ttl1[0]); $this->assertGT(0, $ttl2[0]); - + // Test field-only command format validation (HTTL, HPERSIST) $ttl_result = $this->valkey_glide->hTtl($key, 'expire_field'); $this->assertIsArray($ttl_result); $this->assertGT(0, $ttl_result[0]); - + // HPERSIST should remove expiration $persist_result = $this->valkey_glide->hPersist($key, 'expire_field'); $this->assertEquals([1], $persist_result); - + // Field should no longer have expiration $ttl_after_persist = $this->valkey_glide->hTtl($key, 'expire_field'); $this->assertEquals([-1], $ttl_after_persist); // -1 means no expiration - + // But field value should still be intact $this->assertEquals('original_value', $this->valkey_glide->hGet($key, 'expire_field')); - + // Test HGETEX format validation - should get field values AND set expiration $this->valkey_glide->hSet($key, 'getex_test', 'getex_original'); $result = $this->valkey_glide->hGetEx($key, ['getex_test'], ['EX' => 15]); $this->assertEquals(['getex_test' => 'getex_original'], $result); // Should return field-value map - + // HGETEX should have set expiration $ttl_getex = $this->valkey_glide->hTtl($key, 'getex_test'); $this->assertGT(10, $ttl_getex[0]); $this->assertLTE(15, $ttl_getex[0]); - + // Field value should be unchanged $this->assertEquals('getex_original', $this->valkey_glide->hGet($key, 'getex_test')); } @@ -4323,45 +4329,45 @@ public function testHashFieldExpirationConditionFormatValidation(): void } $key = $this->createRandomString(10); - + // Test that HSETEX conditions (FNX/FXX) work correctly // FNX should only set if field doesn't exist $result = $this->valkey_glide->hSetEx($key, 60, ValkeyGlide::CONDITION_NX, 'fnx_field', 'value1'); $this->assertEquals(1, $result); // Should succeed - field doesn't exist $this->assertEquals('value1', $this->valkey_glide->hGet($key, 'fnx_field')); - + // Second FNX should fail - field now exists $result = $this->valkey_glide->hSetEx($key, 60, ValkeyGlide::CONDITION_NX, 'fnx_field', 'value2'); $this->assertEquals(0, $result); // Should fail - field exists $this->assertEquals('value1', $this->valkey_glide->hGet($key, 'fnx_field')); // Unchanged - + // FXX should only set if field exists $result = $this->valkey_glide->hSetEx($key, 60, ValkeyGlide::CONDITION_XX, 'nonexistent', 'value'); $this->assertEquals(0, $result); // Should fail - field doesn't exist - + $result = $this->valkey_glide->hSetEx($key, 60, ValkeyGlide::CONDITION_XX, 'fnx_field', 'updated_value'); $this->assertEquals(1, $result); // Should succeed - field exists $this->assertEquals('updated_value', $this->valkey_glide->hGet($key, 'fnx_field')); - + // Test that HEXPIRE conditions (NX/XX) work correctly $this->valkey_glide->hSet($key, 'nx_field', 'test_value'); - + // NX should only set expiration if field has no expiration $result_nx = $this->valkey_glide->hExpire($key, 60, ValkeyGlide::CONDITION_NX, 'nx_field'); $this->assertEquals([1], $result_nx); // Should succeed - no expiration - + // Second NX should fail - field now has expiration $result_nx2 = $this->valkey_glide->hExpire($key, 60, ValkeyGlide::CONDITION_NX, 'nx_field'); $this->assertEquals([0], $result_nx2); // Should fail - has expiration - + // XX should only set expiration if field has expiration $this->valkey_glide->hSet($key, 'xx_field', 'test_value2'); $result_xx_fail = $this->valkey_glide->hExpire($key, 60, ValkeyGlide::CONDITION_XX, 'xx_field'); $this->assertEquals([0], $result_xx_fail); // Should fail - no expiration - + $result_xx_success = $this->valkey_glide->hExpire($key, 60, ValkeyGlide::CONDITION_XX, 'nx_field'); $this->assertEquals([1], $result_xx_success); // Should succeed - has expiration - + // Verify field values weren't corrupted by condition logic $this->assertEquals('test_value', $this->valkey_glide->hGet($key, 'nx_field')); $this->assertEquals('test_value2', $this->valkey_glide->hGet($key, 'xx_field')); @@ -4374,42 +4380,42 @@ public function testHashFieldExpirationFormatRegressionTests(): void } $key = $this->createRandomString(10); - + // These tests would have failed with the original incorrect format implementation - + // Test 1: HEXPIRE with multiple fields should work (would fail if using HSETEX format) $this->valkey_glide->hSet($key, 'field1', 'value1', 'field2', 'value2', 'field3', 'value3'); $result = $this->valkey_glide->hExpire($key, 30, null, 'field1', 'field2', 'field3'); $this->assertEquals([1, 1, 1], $result); // All fields should get expiration - + // Verify all fields have expiration but values are unchanged $this->assertEquals('value1', $this->valkey_glide->hGet($key, 'field1')); $this->assertEquals('value2', $this->valkey_glide->hGet($key, 'field2')); $this->assertEquals('value3', $this->valkey_glide->hGet($key, 'field3')); - + $ttl1 = $this->valkey_glide->hTtl($key, 'field1'); $ttl2 = $this->valkey_glide->hTtl($key, 'field2'); $ttl3 = $this->valkey_glide->hTtl($key, 'field3'); $this->assertGT(25, $ttl1[0]); $this->assertGT(25, $ttl2[0]); $this->assertGT(25, $ttl3[0]); - + // Test 2: HTTL with multiple fields should work (would fail if using HSETEX format) $ttl_results = $this->valkey_glide->hTtl($key, 'field1', 'field2', 'field3'); $this->assertCount(3, $ttl_results); $this->assertGT(0, $ttl_results[0]); $this->assertGT(0, $ttl_results[1]); $this->assertGT(0, $ttl_results[2]); - + // Test 3: HPERSIST with multiple fields should work $persist_results = $this->valkey_glide->hPersist($key, 'field1', 'field2'); $this->assertEquals([1, 1], $persist_results); - + // Verify persistence worked $ttl_after_persist = $this->valkey_glide->hTtl($key, 'field1', 'field2', 'field3'); $this->assertEquals([-1, -1], array_slice($ttl_after_persist, 0, 2)); // First two should have no expiration $this->assertGT(0, $ttl_after_persist[2]); // Third should still have expiration - + // Test 4: HSETEX with odd number of arguments should fail gracefully // (This would expose format issues if field-value pairing is wrong) try { @@ -4420,32 +4426,32 @@ public function testHashFieldExpirationFormatRegressionTests(): void } catch (Exception $e) { $this->fail('HSETEX with proper field-value pairs should not fail: ' . $e->getMessage()); } - + // Test 5: Verify expiration units are handled correctly // HSETEX should handle different time units, HEXPIRE should use raw seconds $future_timestamp = time() + 3600; - + // HSETEX with timestamp should work $result = $this->valkey_glide->hSetEx($key, $future_timestamp, null, 'timestamp_field', 'timestamp_value'); $this->assertEquals(1, $result); $this->assertEquals('timestamp_value', $this->valkey_glide->hGet($key, 'timestamp_field')); - + // HEXPIREAT with timestamp should work $this->valkey_glide->hSet($key, 'expire_at_field', 'expire_at_value'); $result = $this->valkey_glide->hExpireAt($key, $future_timestamp, null, 'expire_at_field'); $this->assertEquals([1], $result); $this->assertEquals('expire_at_value', $this->valkey_glide->hGet($key, 'expire_at_field')); - + // Both should have similar expiration times $expire_time1 = $this->valkey_glide->hExpireTime($key, 'timestamp_field'); $expire_time2 = $this->valkey_glide->hExpireTime($key, 'expire_at_field'); $this->assertLT(abs($expire_time1[0] - $expire_time2[0]), 5); // Should be within 5 seconds - + // Test 6: HGETEX format validation - should work with multiple fields and return values $this->valkey_glide->hSet($key, 'getex1', 'value1', 'getex2', 'value2', 'getex3', 'value3'); $result = $this->valkey_glide->hGetEx($key, ['getex1', 'getex2'], ['EX' => 45]); $this->assertEquals(['getex1' => 'value1', 'getex2' => 'value2'], $result); - + // Verify HGETEX set expiration on requested fields only $ttl_getex1 = $this->valkey_glide->hTtl($key, 'getex1'); $ttl_getex2 = $this->valkey_glide->hTtl($key, 'getex2'); @@ -4453,12 +4459,12 @@ public function testHashFieldExpirationFormatRegressionTests(): void $this->assertGT(40, $ttl_getex1[0]); // Should have expiration $this->assertGT(40, $ttl_getex2[0]); // Should have expiration $this->assertEquals([-1], $ttl_getex3); // Should NOT have expiration - + // Test HGETEX with PERSIST option $this->valkey_glide->hExpire($key, 60, null, 'getex1'); // Set expiration first $result = $this->valkey_glide->hGetEx($key, ['getex1'], ['PERSIST' => true]); // Remove expiration $this->assertEquals(['getex1' => 'value1'], $result); - + $ttl_after_persist = $this->valkey_glide->hTtl($key, 'getex1'); $this->assertEquals([-1], $ttl_after_persist); // Should have no expiration } @@ -4470,33 +4476,33 @@ public function testHashFieldExpirationModeParameters(): void } $key = $this->createRandomString(10); - + // Test hExpire with mode parameter $this->valkey_glide->hSet($key, 'field1', 'value1'); - + // NX should succeed - no expiration set $result = $this->valkey_glide->hExpire($key, 60, 'NX', 'field1'); $this->assertEquals([1], $result); - + // NX should fail - expiration already set $result = $this->valkey_glide->hExpire($key, 60, 'NX', 'field1'); $this->assertEquals([0], $result); - + // XX should succeed - expiration exists $result = $this->valkey_glide->hExpire($key, 120, 'XX', 'field1'); $this->assertEquals([1], $result); - + // Test hPExpire with mode parameter $this->valkey_glide->hSet($key, 'field2', 'value2'); $result = $this->valkey_glide->hPExpire($key, 60000, 'NX', 'field2'); $this->assertEquals([1], $result); - + // Test hExpireAt with mode parameter $this->valkey_glide->hSet($key, 'field3', 'value3'); $future_timestamp = time() + 3600; $result = $this->valkey_glide->hExpireAt($key, $future_timestamp, 'NX', 'field3'); $this->assertEquals([1], $result); - + // Test hPExpireAt with mode parameter $this->valkey_glide->hSet($key, 'field4', 'value4'); $future_timestamp_ms = (time() + 3600) * 1000; @@ -4508,14 +4514,14 @@ private function assertHSetExNxXxBehavior(string $key): void { // Set up fields with expiration $this->valkey_glide->hSetEx($key, 60, null, 'field1', 'value1', 'field2', 'value2', 'field3', 'value3'); - + // Test variadic syntax: hTtl($key, 'field1', 'field2', 'field3') $ttl_variadic = $this->valkey_glide->hTtl($key, 'field1', 'field2', 'field3'); $this->assertCount(3, $ttl_variadic); $this->assertGT(50, $ttl_variadic[0]); $this->assertGT(50, $ttl_variadic[1]); $this->assertGT(50, $ttl_variadic[2]); - + // Test single field $ttl_single = $this->valkey_glide->hTtl($key, 'field1'); $this->assertCount(1, $ttl_single); @@ -4529,77 +4535,77 @@ public function testHashFieldExpirationAllVariantsFormatValidation(): void } $key = $this->createRandomString(10); - + // Test all HSETEX variants (HSETEX format with field-value pairs) - + // HPSETEX - milliseconds $result = $this->valkey_glide->hPSetEx($key, 5000, null, 'psetex_field', 'psetex_value'); $this->assertEquals(1, $result); $this->assertEquals('psetex_value', $this->valkey_glide->hGet($key, 'psetex_field')); $pttl = $this->valkey_glide->hPTtl($key, 'psetex_field'); $this->assertGT(4000, $pttl[0]); - + // HSETEXAT - timestamp $future_timestamp = time() + 1800; $result = $this->valkey_glide->hSetEx($key, $future_timestamp, null, 'setat_field', 'setat_value'); $this->assertEquals(1, $result); $this->assertEquals('setat_value', $this->valkey_glide->hGet($key, 'setat_field')); - + // HPSETEXAT - timestamp in milliseconds $future_timestamp_ms = (time() + 1800) * 1000; $result = $this->valkey_glide->hPSetEx($key, $future_timestamp_ms, null, 'psetat_field', 'psetat_value'); $this->assertEquals(1, $result); $this->assertEquals('psetat_value', $this->valkey_glide->hGet($key, 'psetat_field')); - + // HSETEX condition variants $result = $this->valkey_glide->hSetEx($key, 60, ValkeyGlide::CONDITION_NX, 'new_field', 'new_value'); $this->assertEquals(1, $result); // Should succeed - field doesn't exist - + $result = $this->valkey_glide->hSetEx($key, 60, ValkeyGlide::CONDITION_XX, 'new_field', 'updated_value'); $this->assertEquals(1, $result); // Should succeed - field exists $this->assertEquals('updated_value', $this->valkey_glide->hGet($key, 'new_field')); - + // HPSETEX condition variants $result = $this->valkey_glide->hPSetEx($key, 60000, ValkeyGlide::CONDITION_NX, 'pnx_field', 'pnx_value'); $this->assertEquals(1, $result); // Should succeed - field doesn't exist - + $result = $this->valkey_glide->hPSetEx($key, 60000, ValkeyGlide::CONDITION_XX, 'pnx_field', 'pxx_value'); $this->assertEquals(1, $result); // Should succeed - field exists $this->assertEquals('pxx_value', $this->valkey_glide->hGet($key, 'pnx_field')); - + // Test all HEXPIRE variants (HEXPIRE format with fields only) - + // HPEXPIRE - milliseconds $this->valkey_glide->hSet($key, 'pexpire_field', 'pexpire_value'); $result = $this->valkey_glide->hPExpire($key, 8000, null, 'pexpire_field'); $this->assertEquals([1], $result); $this->assertEquals('pexpire_value', $this->valkey_glide->hGet($key, 'pexpire_field')); // Value unchanged - + // HPEXPIREAT - timestamp in milliseconds $this->valkey_glide->hSet($key, 'pexpireat_field', 'pexpireat_value'); $result = $this->valkey_glide->hPExpireAt($key, $future_timestamp_ms, null, 'pexpireat_field'); $this->assertEquals([1], $result); $this->assertEquals('pexpireat_value', $this->valkey_glide->hGet($key, 'pexpireat_field')); // Value unchanged - + // HEXPIRE condition variants $this->valkey_glide->hSet($key, 'expire_cond_field', 'expire_cond_value'); $this->assertEquals([1], $result); // Should succeed - no expiration - + $this->assertEquals([1], $result); // Should succeed - has expiration $this->assertEquals('expire_cond_value', $this->valkey_glide->hGet($key, 'expire_cond_field')); // Value unchanged - + // Test field-only commands (no expiry parameters) - + // HPTTL - milliseconds TTL $pttl_result = $this->valkey_glide->hPTtl($key, 'pnx_field'); $this->assertNotEquals(false, $pttl_result); $this->assertGT(0, $pttl_result[0]); // Should have TTL in milliseconds - + // HPEXPIRETIME - milliseconds timestamp $pexpire_time = $this->valkey_glide->hPExpireTime($key, 'pexpireat_field'); $this->assertNotEquals(false, $pexpire_time); $this->assertGT(time() * 1000, $pexpire_time[0]); // Should be future timestamp in ms - + // Verify all field values are preserved $this->assertEquals('psetex_value', $this->valkey_glide->hGet($key, 'psetex_field')); $this->assertEquals('setat_value', $this->valkey_glide->hGet($key, 'setat_field')); @@ -4613,15 +4619,15 @@ private function assertHSetExTimestampVariants(string $key): void { $future_timestamp = time() + 3600; $future_timestamp_ms = $future_timestamp * 1000; - + // Test timestamp variants - set the values first $this->assertEquals(1, $this->valkey_glide->hSetEx($key, $future_timestamp, null, 'field2', 'updated_value2')); $this->assertEquals('updated_value2', $this->valkey_glide->hGet($key, 'field2')); - + // Test millisecond variants $this->assertEquals(1, $this->valkey_glide->hPSetEx($key, $future_timestamp_ms, null, 'field3', 'updated_value3')); $this->assertEquals('updated_value3', $this->valkey_glide->hGet($key, 'field3')); - + // Test millisecond timestamp variants $this->assertEquals(1, $this->valkey_glide->hPSetEx($key, $future_timestamp_ms, null, 'field4', 'updated_value4')); $this->assertEquals('updated_value4', $this->valkey_glide->hGet($key, 'field4')); @@ -4631,19 +4637,19 @@ private function assertHExpireNxXxBehavior(string $key): void { // Set up fields without expiration $this->valkey_glide->hSet($key, 'field1', 'value1', 'field2', 'value2'); - + // Test hExpireNx - only if field has no expiration $result = $this->valkey_glide->hExpire($key, 60, null, 'field1'); $this->assertEquals([1], $result); // 1 = expiration set - + // Should succeed - hExpire can update existing expiration $result = $this->valkey_glide->hExpire($key, 60, null, 'field1'); $this->assertEquals([1], $result); // 1 = expiration updated - + // Test hExpire on same field again $result = $this->valkey_glide->hExpire($key, 60, null, 'field1'); $this->assertEquals([1], $result); // 1 = expiration updated again - + $result = $this->valkey_glide->hExpire($key, 60, null, 'field1'); $this->assertEquals([1], $result); // 1 = expiration updated } @@ -4652,30 +4658,30 @@ private function assertHExpireTimestampVariants(string $key): void { $future_timestamp = time() + 3600; $future_timestamp_ms = $future_timestamp * 1000; - + // Test timestamp variants $this->valkey_glide->hSet($key, 'field3', 'value3'); $result = $this->valkey_glide->hExpireAt($key, $future_timestamp, null, 'field3'); $this->assertEquals([1], $result); - + $result = $this->valkey_glide->hExpireAt($key, $future_timestamp, null, 'field3'); $this->assertEquals([1], $result); // can update existing expiration - + $result = $this->valkey_glide->hExpireAt($key, $future_timestamp, null, 'field3'); $this->assertEquals([1], $result); // updated expiration again - + // Test millisecond variants $this->valkey_glide->hSet($key, 'field4', 'value4', 'field5', 'value5'); - + $result = $this->valkey_glide->hPExpireAt($key, $future_timestamp_ms, null, 'field4'); $this->assertEquals([1], $result); - + $result = $this->valkey_glide->hPExpireAt($key, $future_timestamp_ms, null, 'field4'); $this->assertEquals([1], $result); - + $result = $this->valkey_glide->hPExpireAt($key, $future_timestamp_ms, null, 'field5'); $this->assertEquals([1], $result); - + $result = $this->valkey_glide->hPExpireAt($key, $future_timestamp_ms, null, 'field4'); $this->assertEquals([1], $result); } @@ -7580,30 +7586,30 @@ public function testCopyWithDatabase() $this->valkey_glide->select(0); $this->valkey_glide->set('{key}src', 'test_value'); - + // Test with string key - may fail if multi-database not supported $result1 = $this->valkey_glide->copy('{key}src', '{key}dst', ['DB' => 1]); $this->assertIsBool($result1); - + if ($result1) { // Verify key exists in database 1 $this->valkey_glide->select(1); $this->assertKeyEquals('test_value', '{key}dst'); $this->valkey_glide->select(0); } - + // Test with constant $this->valkey_glide->set('{key}src2', 'constant_test'); $result2 = $this->valkey_glide->copy('{key}src2', '{key}dst2', [ValkeyGlide::COPY_DB => 1]); $this->assertIsBool($result2); - + if ($result2) { // Verify with constant $this->valkey_glide->select(1); $this->assertKeyEquals('constant_test', '{key}dst2'); $this->valkey_glide->select(0); } - + // Test combined options if ($result1) { $result3 = $this->valkey_glide->copy('{key}src', '{key}dst', [ @@ -7612,7 +7618,7 @@ public function testCopyWithDatabase() ]); $this->assertIsBool($result3); } - + // Clean up $this->valkey_glide->del('{key}src', '{key}src2'); $this->valkey_glide->select(1); @@ -7643,106 +7649,184 @@ public function testGetCommandWithLogging() { // Create unique log file for this test $logFile = '/tmp/valkey_get_test_' . uniqid() . '.log'; - + // Initialize logger with debug level for detailed test logging $this->assertTrue(valkey_glide_logger_set_config("debug", $logFile)); $this->assertTrue(valkey_glide_logger_is_initialized()); - + valkey_glide_logger_info("get-test", "=== Starting GET command test ==="); - + // Test setup $testKey = 'test-key-' . uniqid(); $testValue = 'test-value-' . uniqid(); - + valkey_glide_logger_debug("get-test", "Test key: $testKey"); valkey_glide_logger_debug("get-test", "Test value: $testValue"); - + // Set the key valkey_glide_logger_info("get-test", "Setting key via SET command"); $setResult = $this->valkey_glide->set($testKey, $testValue); valkey_glide_logger_debug("get-test", "SET result: " . ($setResult ? 'true' : 'false')); $this->assertTrue($setResult); - + // Get the key valkey_glide_logger_info("get-test", "Retrieving key via GET command"); $getValue = $this->valkey_glide->get($testKey); valkey_glide_logger_debug("get-test", "GET result: " . ($getValue ?: 'null')); - + // Verify result $this->assertEquals($testValue, $getValue); valkey_glide_logger_info("get-test", "✓ GET command test passed - values match"); - + // Test non-existent key valkey_glide_logger_info("get-test", "Testing non-existent key"); $nonExistentKey = 'non-existent-key-' . uniqid(); valkey_glide_logger_debug("get-test", "Non-existent key: $nonExistentKey"); - + $nonExistentResult = $this->valkey_glide->get($nonExistentKey); valkey_glide_logger_debug("get-test", "Non-existent key result: " . ($nonExistentResult === false ? 'false' : $nonExistentResult)); - + $this->assertFalse($nonExistentResult); valkey_glide_logger_info("get-test", "✓ Non-existent key test passed"); - + // Test with various data types $testCases = [ 'string' => 'hello world', 'number' => '12345', 'special' => 'émojis: 🚀 unicode: ñáéíóú' ]; - + foreach ($testCases as $type => $value) { valkey_glide_logger_info("get-test", "Testing $type data type"); $key = "test-$type-" . uniqid(); - + valkey_glide_logger_debug("get-test", "Setting $key = $value"); $this->assertTrue($this->valkey_glide->set($key, $value)); - + $result = $this->valkey_glide->get($key); valkey_glide_logger_debug("get-test", "Retrieved $key = $result"); - + $this->assertEquals($value, $result); valkey_glide_logger_info("get-test", "✓ $type test passed"); - + // Clean up $this->valkey_glide->del($key); } - + // Clean up main test key valkey_glide_logger_info("get-test", "Cleaning up test key"); $delResult = $this->valkey_glide->del($testKey); valkey_glide_logger_debug("get-test", "DEL result: $delResult"); - + valkey_glide_logger_info("get-test", "=== GET command test completed successfully ==="); valkey_glide_logger_info("get-test", "Log file location: $logFile"); - + // Verify logging actually worked sleep(1); // Wait for logs to be written - + // Check logger is initialized $this->assertTrue(valkey_glide_logger_is_initialized(), "Logger should be initialized"); $this->assertEquals(3, valkey_glide_logger_get_level(), "Debug level should be 3"); - + // Verify log file creation $actualLogFiles = glob($logFile . '*'); $this->assertTrue(count($actualLogFiles) > 0, "Log file should be created"); - + // Verify log content $actualLogFile = $actualLogFiles[0]; $this->assertTrue(file_exists($actualLogFile), "Log file should exist"); - + $logContent = file_get_contents($actualLogFile); $this->assertTrue(!empty($logContent), "Log file should not be empty"); - + // Verify specific log messages exist $this->assertStringContains("=== Starting GET command test ===", $logContent, "Should contain test start message"); $this->assertStringContains("Setting key via SET command", $logContent, "Should contain SET operation log"); $this->assertStringContains("Retrieving key via GET command", $logContent, "Should contain GET operation log"); $this->assertStringContains("✓ GET command test passed - values match", $logContent, "Should contain success message"); $this->assertStringContains("get-test", $logContent, "Should contain test identifier"); - + // Output log file location for verification echo "\n=== LOG FILE LOCATION ===\n"; echo "Log file: $actualLogFile\n"; echo "========================\n"; } + + public function testGetCommandWithConsoleLogging() + { + // Initialize logger with null filename to test console output + $this->assertTrue(valkey_glide_logger_set_config("debug", null)); + $this->assertTrue(valkey_glide_logger_is_initialized()); + + // Capture output using ob_start + ob_start(); + + try { + // Test setup + $testKey = 'console-test-key-' . uniqid(); + $testValue = 'console-test-value-' . uniqid(); + + valkey_glide_logger_info("console-test", "=== Starting console logging test ==="); + valkey_glide_logger_debug("console-test", "Test key: $testKey"); + + // Set and get the key + $setResult = $this->valkey_glide->set($testKey, $testValue); + valkey_glide_logger_info("console-test", "SET operation completed"); + $this->assertTrue($setResult); + + $getValue = $this->valkey_glide->get($testKey); + valkey_glide_logger_info("console-test", "GET operation completed"); + $this->assertEquals($testValue, $getValue); + + valkey_glide_logger_info("console-test", "=== Console logging test completed ==="); + + // Clean up + $this->valkey_glide->del($testKey); + } finally { + // Capture any output that went to stdout/stderr + $output = ob_get_contents(); + ob_end_clean(); + } + + // Check if any output was captured + if (!empty($output)) { + echo "\n=== CONSOLE OUTPUT CAPTURED ===\n"; + echo $output; + echo "===============================\n"; + $this->assertStringContains("console-test", $output, "Should contain console logging output"); + } else { + echo "\n=== NO STDOUT CAPTURED VIA ob_start() - CHECKING STDOUT REDIRECTION ===\n"; + + // Since ob_start() doesn't capture C-level stdout, we need to test stdout redirection + // Create a temporary script to capture stdout + $tempScript = tempnam(sys_get_temp_dir(), 'stdout_test_'); + $stdoutFile = tempnam(sys_get_temp_dir(), 'stdout_output_'); + + file_put_contents($tempScript, ''); + + // Execute script and redirect stdout to file + exec("php $tempScript 1>$stdoutFile 2>/dev/null"); + + $stdoutContent = file_get_contents($stdoutFile); + + if (!empty($stdoutContent)) { + echo "STDOUT content captured:\n"; + echo $stdoutContent . "\n"; + $this->assertStringContains("stdout-test", $stdoutContent, "Should contain stdout logging output"); + echo "✓ Logger with null filename writes to stdout (bypasses ob_start)\n"; + } else { + echo "No stdout output captured\n"; + } + + // Cleanup + unlink($tempScript); + unlink($stdoutFile); + echo "=======================================================\n"; + } + } } From f3b7151bfe594f93450429df9a6fc00c6f4be26a Mon Sep 17 00:00:00 2001 From: Prateek Kumar Date: Fri, 31 Oct 2025 10:23:09 -0700 Subject: [PATCH 19/27] PHP: Update logs Signed-off-by: Prateek Kumar --- valkey_glide_core_common.c | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/valkey_glide_core_common.c b/valkey_glide_core_common.c index fe98c27b..c2b29862 100644 --- a/valkey_glide_core_common.c +++ b/valkey_glide_core_common.c @@ -52,19 +52,9 @@ int execute_core_command(valkey_glide_object* valkey_glide, /* Log command execution entry */ VALKEY_LOG_DEBUG("command_execution", "Entering command execution"); - { - char cmd_type_msg[64]; - snprintf(cmd_type_msg, sizeof(cmd_type_msg), "Command type: %d", args->cmd_type); - VALKEY_LOG_DEBUG("command_execution", cmd_type_msg); - } - { - char batch_msg[32]; - snprintf(batch_msg, - sizeof(batch_msg), - "Batch mode: %s", - valkey_glide->is_in_batch_mode ? "yes" : "no"); - VALKEY_LOG_DEBUG("command_execution", batch_msg); - } + VALKEY_LOG_DEBUG_FMT("command_execution", "Command type: %d", args->cmd_type); + VALKEY_LOG_DEBUG_FMT( + "command_execution", "Batch mode: %s", valkey_glide->is_in_batch_mode ? "yes" : "no"); uintptr_t* cmd_args = NULL; unsigned long* cmd_args_len = NULL; @@ -87,11 +77,7 @@ int execute_core_command(valkey_glide_object* valkey_glide, return 0; } - { - char arg_count_msg[64]; - snprintf(arg_count_msg, sizeof(arg_count_msg), "Argument count: %d", arg_count); - VALKEY_LOG_DEBUG("command_execution", arg_count_msg); - } + VALKEY_LOG_DEBUG_FMT("command_execution", "Argument count: %d", arg_count); /* Check for batch mode */ if (valkey_glide->is_in_batch_mode) { From 16eb389439cdbcb6d6105366b2f2fe757d01ce5f Mon Sep 17 00:00:00 2001 From: Prateek Kumar Date: Fri, 31 Oct 2025 10:31:00 -0700 Subject: [PATCH 20/27] PHP: Update debug log in valkey_glide_core_common.c Signed-off-by: Prateek Kumar --- valkey_glide_core_common.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/valkey_glide_core_common.c b/valkey_glide_core_common.c index c2b29862..60f8e9cd 100644 --- a/valkey_glide_core_common.c +++ b/valkey_glide_core_common.c @@ -51,10 +51,10 @@ int execute_core_command(valkey_glide_object* valkey_glide, } /* Log command execution entry */ - VALKEY_LOG_DEBUG("command_execution", "Entering command execution"); - VALKEY_LOG_DEBUG_FMT("command_execution", "Command type: %d", args->cmd_type); - VALKEY_LOG_DEBUG_FMT( - "command_execution", "Batch mode: %s", valkey_glide->is_in_batch_mode ? "yes" : "no"); + VALKEY_LOG_DEBUG_FMT("command_execution", + "Entering command execution - Command type: %d, Batch mode: %s", + args->cmd_type, + valkey_glide->is_in_batch_mode ? "yes" : "no"); uintptr_t* cmd_args = NULL; unsigned long* cmd_args_len = NULL; From 80a7101a383e5d52470af199de74345cc0fa22ac Mon Sep 17 00:00:00 2001 From: Prateek Kumar Date: Fri, 31 Oct 2025 10:37:49 -0700 Subject: [PATCH 21/27] PHP: update DEBUG_VALKEY_GLIDE_PHP in valkey_glide_core_common.c by removing printf statements Signed-off-by: Prateek Kumar --- valkey_glide_core_common.c | 44 +++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/valkey_glide_core_common.c b/valkey_glide_core_common.c index 60f8e9cd..ffbd0dd5 100644 --- a/valkey_glide_core_common.c +++ b/valkey_glide_core_common.c @@ -1687,40 +1687,40 @@ int execute_multi_key_command(valkey_glide_object* valkey_glide, #ifdef DEBUG_VALKEY_GLIDE_PHP void debug_print_core_args(core_command_args_t* args) { if (!args) { - printf("DEBUG: core_args is NULL\n"); + VALKEY_LOG_ERROR("debug_core_args", "core_args is NULL"); return; } - printf("DEBUG: Core Command Args:\n"); - printf(" cmd_type: %d\n", args->cmd_type); - printf(" key: %.*s (len: %zu)\n", + VALKEY_LOG_DEBUG("debug_core_args", "Core Command Args:"); + VALKEY_LOG_DEBUG_FMT("debug_core_args", " cmd_type: %d", args->cmd_type); + VALKEY_LOG_DEBUG_FMT("debug_core_args", " key: %.*s (len: %zu)", (int) args->key_len, args->key ? args->key : "NULL", args->key_len); - printf(" arg_count: %d\n", args->arg_count); + VALKEY_LOG_DEBUG_FMT("debug_core_args", " arg_count: %d", args->arg_count); for (int i = 0; i < args->arg_count; i++) { - printf(" arg[%d]: type=%d\n", i, args->args[i].type); + VALKEY_LOG_DEBUG_FMT("debug_core_args", " arg[%d]: type=%d", i, args->args[i].type); switch (args->args[i].type) { case CORE_ARG_TYPE_STRING: - printf(" string: %.*s (len: %zu)\n", + VALKEY_LOG_DEBUG_FMT("debug_core_args", " string: %.*s (len: %zu)", (int) args->args[i].data.string_arg.len, args->args[i].data.string_arg.value, args->args[i].data.string_arg.len); break; case CORE_ARG_TYPE_LONG: - printf(" long: %ld\n", args->args[i].data.long_arg.value); + VALKEY_LOG_DEBUG_FMT("debug_core_args", " long: %ld", args->args[i].data.long_arg.value); break; case CORE_ARG_TYPE_DOUBLE: - printf(" double: %f\n", args->args[i].data.double_arg.value); + VALKEY_LOG_DEBUG_FMT("debug_core_args", " double: %f", args->args[i].data.double_arg.value); break; default: - printf(" (other type)\n"); + VALKEY_LOG_DEBUG("debug_core_args", " (other type)"); break; } } - printf(" options: has_expire=%d, nx=%d, xx=%d\n", + VALKEY_LOG_DEBUG_FMT("debug_core_args", " options: has_expire=%d, nx=%d, xx=%d", args->options.has_expire, args->options.nx, args->options.xx); @@ -1728,43 +1728,43 @@ void debug_print_core_args(core_command_args_t* args) { void debug_print_command_result(CommandResult* result) { if (!result) { - printf("DEBUG: CommandResult is NULL\n"); + VALKEY_LOG_ERROR("debug_command_result", "CommandResult is NULL"); return; } - printf("DEBUG: CommandResult:\n"); - printf(" command_error: %s\n", result->command_error ? "YES" : "NO"); + VALKEY_LOG_DEBUG("debug_command_result", "CommandResult:"); + VALKEY_LOG_DEBUG_FMT("debug_command_result", " command_error: %s", result->command_error ? "YES" : "NO"); if (result->command_error) { - printf(" error_message: %s\n", + VALKEY_LOG_ERROR_FMT("debug_command_result", " error_message: %s", result->command_error->command_error_message ? result->command_error->command_error_message : "NULL"); } if (result->response) { - printf(" response_type: %d\n", result->response->response_type); + VALKEY_LOG_DEBUG_FMT("debug_command_result", " response_type: %d", result->response->response_type); switch (result->response->response_type) { case Int: - printf(" int_value: %ld\n", result->response->int_value); + VALKEY_LOG_DEBUG_FMT("debug_command_result", " int_value: %ld", result->response->int_value); break; case String: - printf(" string_value: %.*s (len: %ld)\n", + VALKEY_LOG_DEBUG_FMT("debug_command_result", " string_value: %.*s (len: %ld)", (int) result->response->string_value_len, result->response->string_value, result->response->string_value_len); break; case Bool: - printf(" bool_value: %s\n", result->response->bool_value ? "true" : "false"); + VALKEY_LOG_DEBUG_FMT("debug_command_result", " bool_value: %s", result->response->bool_value ? "true" : "false"); break; case Float: - printf(" float_value: %f\n", result->response->float_value); + VALKEY_LOG_DEBUG_FMT("debug_command_result", " float_value: %f", result->response->float_value); break; default: - printf(" (other response type)\n"); + VALKEY_LOG_DEBUG("debug_command_result", " (other response type)"); break; } } else { - printf(" response: NULL\n"); + VALKEY_LOG_DEBUG("debug_command_result", " response: NULL"); } } #endif From 8bf0fa17b69074a655c67a72ccd75361d6c7db75 Mon Sep 17 00:00:00 2001 From: Prateek Kumar Date: Fri, 31 Oct 2025 10:44:03 -0700 Subject: [PATCH 22/27] PHP: format file valkey_glide_core_common.c Signed-off-by: Prateek Kumar --- valkey_glide_core_common.c | 67 +++++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 27 deletions(-) diff --git a/valkey_glide_core_common.c b/valkey_glide_core_common.c index ffbd0dd5..3b8bc211 100644 --- a/valkey_glide_core_common.c +++ b/valkey_glide_core_common.c @@ -1693,26 +1693,30 @@ void debug_print_core_args(core_command_args_t* args) { VALKEY_LOG_DEBUG("debug_core_args", "Core Command Args:"); VALKEY_LOG_DEBUG_FMT("debug_core_args", " cmd_type: %d", args->cmd_type); - VALKEY_LOG_DEBUG_FMT("debug_core_args", " key: %.*s (len: %zu)", - (int) args->key_len, - args->key ? args->key : "NULL", - args->key_len); + VALKEY_LOG_DEBUG_FMT("debug_core_args", + " key: %.*s (len: %zu)", + (int) args->key_len, + args->key ? args->key : "NULL", + args->key_len); VALKEY_LOG_DEBUG_FMT("debug_core_args", " arg_count: %d", args->arg_count); for (int i = 0; i < args->arg_count; i++) { VALKEY_LOG_DEBUG_FMT("debug_core_args", " arg[%d]: type=%d", i, args->args[i].type); switch (args->args[i].type) { case CORE_ARG_TYPE_STRING: - VALKEY_LOG_DEBUG_FMT("debug_core_args", " string: %.*s (len: %zu)", - (int) args->args[i].data.string_arg.len, - args->args[i].data.string_arg.value, - args->args[i].data.string_arg.len); + VALKEY_LOG_DEBUG_FMT("debug_core_args", + " string: %.*s (len: %zu)", + (int) args->args[i].data.string_arg.len, + args->args[i].data.string_arg.value, + args->args[i].data.string_arg.len); break; case CORE_ARG_TYPE_LONG: - VALKEY_LOG_DEBUG_FMT("debug_core_args", " long: %ld", args->args[i].data.long_arg.value); + VALKEY_LOG_DEBUG_FMT( + "debug_core_args", " long: %ld", args->args[i].data.long_arg.value); break; case CORE_ARG_TYPE_DOUBLE: - VALKEY_LOG_DEBUG_FMT("debug_core_args", " double: %f", args->args[i].data.double_arg.value); + VALKEY_LOG_DEBUG_FMT( + "debug_core_args", " double: %f", args->args[i].data.double_arg.value); break; default: VALKEY_LOG_DEBUG("debug_core_args", " (other type)"); @@ -1720,10 +1724,11 @@ void debug_print_core_args(core_command_args_t* args) { } } - VALKEY_LOG_DEBUG_FMT("debug_core_args", " options: has_expire=%d, nx=%d, xx=%d", - args->options.has_expire, - args->options.nx, - args->options.xx); + VALKEY_LOG_DEBUG_FMT("debug_core_args", + " options: has_expire=%d, nx=%d, xx=%d", + args->options.has_expire, + args->options.nx, + args->options.xx); } void debug_print_command_result(CommandResult* result) { @@ -1733,31 +1738,39 @@ void debug_print_command_result(CommandResult* result) { } VALKEY_LOG_DEBUG("debug_command_result", "CommandResult:"); - VALKEY_LOG_DEBUG_FMT("debug_command_result", " command_error: %s", result->command_error ? "YES" : "NO"); + VALKEY_LOG_DEBUG_FMT( + "debug_command_result", " command_error: %s", result->command_error ? "YES" : "NO"); if (result->command_error) { - VALKEY_LOG_ERROR_FMT("debug_command_result", " error_message: %s", - result->command_error->command_error_message - ? result->command_error->command_error_message - : "NULL"); + VALKEY_LOG_ERROR_FMT("debug_command_result", + " error_message: %s", + result->command_error->command_error_message + ? result->command_error->command_error_message + : "NULL"); } if (result->response) { - VALKEY_LOG_DEBUG_FMT("debug_command_result", " response_type: %d", result->response->response_type); + VALKEY_LOG_DEBUG_FMT( + "debug_command_result", " response_type: %d", result->response->response_type); switch (result->response->response_type) { case Int: - VALKEY_LOG_DEBUG_FMT("debug_command_result", " int_value: %ld", result->response->int_value); + VALKEY_LOG_DEBUG_FMT( + "debug_command_result", " int_value: %ld", result->response->int_value); break; case String: - VALKEY_LOG_DEBUG_FMT("debug_command_result", " string_value: %.*s (len: %ld)", - (int) result->response->string_value_len, - result->response->string_value, - result->response->string_value_len); + VALKEY_LOG_DEBUG_FMT("debug_command_result", + " string_value: %.*s (len: %ld)", + (int) result->response->string_value_len, + result->response->string_value, + result->response->string_value_len); break; case Bool: - VALKEY_LOG_DEBUG_FMT("debug_command_result", " bool_value: %s", result->response->bool_value ? "true" : "false"); + VALKEY_LOG_DEBUG_FMT("debug_command_result", + " bool_value: %s", + result->response->bool_value ? "true" : "false"); break; case Float: - VALKEY_LOG_DEBUG_FMT("debug_command_result", " float_value: %f", result->response->float_value); + VALKEY_LOG_DEBUG_FMT( + "debug_command_result", " float_value: %f", result->response->float_value); break; default: VALKEY_LOG_DEBUG("debug_command_result", " (other response type)"); From 34dd2828f6b2536a9ca7633ce5f191f5e3f89ec5 Mon Sep 17 00:00:00 2001 From: Prateek Kumar Date: Fri, 31 Oct 2025 11:05:55 -0700 Subject: [PATCH 23/27] PHP: Updated log level check in logger.h macros Signed-off-by: Prateek Kumar --- logger.h | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/logger.h b/logger.h index 748986e7..79a05cfe 100644 --- a/logger.h +++ b/logger.h @@ -159,6 +159,7 @@ void valkey_glide_c_log_trace(const char* identifier, const char* message); /* Dynamic allocation macro for formatted debug logging */ #define VALKEY_LOG_DEBUG_FMT(category, format, ...) \ do { \ + if (valkey_glide_logger_get_level() == VALKEY_LOG_LEVEL_OFF || VALKEY_LOG_LEVEL_DEBUG > valkey_glide_logger_get_level()) break; \ int needed_size = snprintf(NULL, 0, format, __VA_ARGS__) + 1; \ char* debug_msg = malloc(needed_size); \ if (debug_msg) { \ @@ -173,25 +174,27 @@ void valkey_glide_c_log_trace(const char* identifier, const char* message); /* Dynamic allocation macro for formatted error logging */ #define VALKEY_LOG_ERROR_FMT(category, format, ...) \ do { \ - int needed_size = snprintf(NULL, 0, format, __VA_ARGS__) + 1; \ - char* error_msg = malloc(needed_size); \ - if (error_msg) { \ - snprintf(error_msg, needed_size, format, __VA_ARGS__); \ - VALKEY_LOG_ERROR(category, error_msg); \ - free(error_msg); \ - } \ + if (valkey_glide_logger_get_level() == VALKEY_LOG_LEVEL_OFF || VALKEY_LOG_LEVEL_ERROR > valkey_glide_logger_get_level()) break; \ + int needed_size = snprintf(NULL, 0, format, __VA_ARGS__) + 1; \ + char* error_msg = malloc(needed_size); \ + if (error_msg) { \ + snprintf(error_msg, needed_size, format, __VA_ARGS__); \ + VALKEY_LOG_ERROR(category, error_msg); \ + free(error_msg); \ + } \ } while (0) /* Dynamic allocation macro for formatted warning logging */ #define VALKEY_LOG_WARN_FMT(category, format, ...) \ do { \ - int needed_size = snprintf(NULL, 0, format, __VA_ARGS__) + 1; \ - char* warn_msg = malloc(needed_size); \ - if (warn_msg) { \ - snprintf(warn_msg, needed_size, format, __VA_ARGS__); \ - VALKEY_LOG_WARN(category, warn_msg); \ - free(warn_msg); \ - } \ + if (valkey_glide_logger_get_level() == VALKEY_LOG_LEVEL_OFF || VALKEY_LOG_LEVEL_WARN > valkey_glide_logger_get_level()) break; \ + int needed_size = snprintf(NULL, 0, format, __VA_ARGS__) + 1; \ + char* warn_msg = malloc(needed_size); \ + if (warn_msg) { \ + snprintf(warn_msg, needed_size, format, __VA_ARGS__); \ + VALKEY_LOG_WARN(category, warn_msg); \ + free(warn_msg); \ + } \ } while (0) /* ============================================================================ From 7ff5baf7748944a2fd1e750299fc02b2e2fe6a22 Mon Sep 17 00:00:00 2001 From: Prateek Kumar Date: Fri, 31 Oct 2025 11:07:24 -0700 Subject: [PATCH 24/27] PHP: Format file logger.h Signed-off-by: Prateek Kumar --- logger.h | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/logger.h b/logger.h index 79a05cfe..cc6a36c1 100644 --- a/logger.h +++ b/logger.h @@ -159,7 +159,9 @@ void valkey_glide_c_log_trace(const char* identifier, const char* message); /* Dynamic allocation macro for formatted debug logging */ #define VALKEY_LOG_DEBUG_FMT(category, format, ...) \ do { \ - if (valkey_glide_logger_get_level() == VALKEY_LOG_LEVEL_OFF || VALKEY_LOG_LEVEL_DEBUG > valkey_glide_logger_get_level()) break; \ + if (valkey_glide_logger_get_level() == VALKEY_LOG_LEVEL_OFF || \ + VALKEY_LOG_LEVEL_DEBUG > valkey_glide_logger_get_level()) \ + break; \ int needed_size = snprintf(NULL, 0, format, __VA_ARGS__) + 1; \ char* debug_msg = malloc(needed_size); \ if (debug_msg) { \ @@ -174,27 +176,31 @@ void valkey_glide_c_log_trace(const char* identifier, const char* message); /* Dynamic allocation macro for formatted error logging */ #define VALKEY_LOG_ERROR_FMT(category, format, ...) \ do { \ - if (valkey_glide_logger_get_level() == VALKEY_LOG_LEVEL_OFF || VALKEY_LOG_LEVEL_ERROR > valkey_glide_logger_get_level()) break; \ - int needed_size = snprintf(NULL, 0, format, __VA_ARGS__) + 1; \ - char* error_msg = malloc(needed_size); \ - if (error_msg) { \ - snprintf(error_msg, needed_size, format, __VA_ARGS__); \ - VALKEY_LOG_ERROR(category, error_msg); \ - free(error_msg); \ - } \ + if (valkey_glide_logger_get_level() == VALKEY_LOG_LEVEL_OFF || \ + VALKEY_LOG_LEVEL_ERROR > valkey_glide_logger_get_level()) \ + break; \ + int needed_size = snprintf(NULL, 0, format, __VA_ARGS__) + 1; \ + char* error_msg = malloc(needed_size); \ + if (error_msg) { \ + snprintf(error_msg, needed_size, format, __VA_ARGS__); \ + VALKEY_LOG_ERROR(category, error_msg); \ + free(error_msg); \ + } \ } while (0) /* Dynamic allocation macro for formatted warning logging */ #define VALKEY_LOG_WARN_FMT(category, format, ...) \ do { \ - if (valkey_glide_logger_get_level() == VALKEY_LOG_LEVEL_OFF || VALKEY_LOG_LEVEL_WARN > valkey_glide_logger_get_level()) break; \ - int needed_size = snprintf(NULL, 0, format, __VA_ARGS__) + 1; \ - char* warn_msg = malloc(needed_size); \ - if (warn_msg) { \ - snprintf(warn_msg, needed_size, format, __VA_ARGS__); \ - VALKEY_LOG_WARN(category, warn_msg); \ - free(warn_msg); \ - } \ + if (valkey_glide_logger_get_level() == VALKEY_LOG_LEVEL_OFF || \ + VALKEY_LOG_LEVEL_WARN > valkey_glide_logger_get_level()) \ + break; \ + int needed_size = snprintf(NULL, 0, format, __VA_ARGS__) + 1; \ + char* warn_msg = malloc(needed_size); \ + if (warn_msg) { \ + snprintf(warn_msg, needed_size, format, __VA_ARGS__); \ + VALKEY_LOG_WARN(category, warn_msg); \ + free(warn_msg); \ + } \ } while (0) /* ============================================================================ From 7674b8f4962ee539f04dee51a2b7f84e14b2858b Mon Sep 17 00:00:00 2001 From: Prateek Kumar Date: Fri, 31 Oct 2025 11:28:16 -0700 Subject: [PATCH 25/27] PHP: Update macros in logger.h Signed-off-by: Prateek Kumar --- logger.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/logger.h b/logger.h index cc6a36c1..840e9a00 100644 --- a/logger.h +++ b/logger.h @@ -163,11 +163,11 @@ void valkey_glide_c_log_trace(const char* identifier, const char* message); VALKEY_LOG_LEVEL_DEBUG > valkey_glide_logger_get_level()) \ break; \ int needed_size = snprintf(NULL, 0, format, __VA_ARGS__) + 1; \ - char* debug_msg = malloc(needed_size); \ + char* debug_msg = emalloc(needed_size); \ if (debug_msg) { \ snprintf(debug_msg, needed_size, format, __VA_ARGS__); \ VALKEY_LOG_DEBUG(category, debug_msg); \ - free(debug_msg); \ + efree(debug_msg); \ } else { \ VALKEY_LOG_ERROR(category, "Failed to allocate memory for debug message"); \ } \ @@ -180,11 +180,11 @@ void valkey_glide_c_log_trace(const char* identifier, const char* message); VALKEY_LOG_LEVEL_ERROR > valkey_glide_logger_get_level()) \ break; \ int needed_size = snprintf(NULL, 0, format, __VA_ARGS__) + 1; \ - char* error_msg = malloc(needed_size); \ + char* error_msg = emalloc(needed_size); \ if (error_msg) { \ snprintf(error_msg, needed_size, format, __VA_ARGS__); \ VALKEY_LOG_ERROR(category, error_msg); \ - free(error_msg); \ + efree(error_msg); \ } \ } while (0) @@ -195,11 +195,11 @@ void valkey_glide_c_log_trace(const char* identifier, const char* message); VALKEY_LOG_LEVEL_WARN > valkey_glide_logger_get_level()) \ break; \ int needed_size = snprintf(NULL, 0, format, __VA_ARGS__) + 1; \ - char* warn_msg = malloc(needed_size); \ + char* warn_msg = emalloc(needed_size); \ if (warn_msg) { \ snprintf(warn_msg, needed_size, format, __VA_ARGS__); \ VALKEY_LOG_WARN(category, warn_msg); \ - free(warn_msg); \ + efree(warn_msg); \ } \ } while (0) From 25e3286485568b36dd83de815b4d52283f000ae9 Mon Sep 17 00:00:00 2001 From: Prateek Kumar Date: Fri, 31 Oct 2025 11:32:16 -0700 Subject: [PATCH 26/27] PHP: Macros in logger.h updated with error logs Signed-off-by: Prateek Kumar --- logger.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/logger.h b/logger.h index 840e9a00..6569754a 100644 --- a/logger.h +++ b/logger.h @@ -185,6 +185,8 @@ void valkey_glide_c_log_trace(const char* identifier, const char* message); snprintf(error_msg, needed_size, format, __VA_ARGS__); \ VALKEY_LOG_ERROR(category, error_msg); \ efree(error_msg); \ + } else { \ + VALKEY_LOG_ERROR(category, "Failed to allocate memory for error message"); \ } \ } while (0) @@ -200,6 +202,8 @@ void valkey_glide_c_log_trace(const char* identifier, const char* message); snprintf(warn_msg, needed_size, format, __VA_ARGS__); \ VALKEY_LOG_WARN(category, warn_msg); \ efree(warn_msg); \ + } else { \ + VALKEY_LOG_ERROR(category, "Failed to allocate memory for warning message"); \ } \ } while (0) From a8f89f08f4cdaf548d7bc75b13c834d99feb57dc Mon Sep 17 00:00:00 2001 From: Prateek Kumar Date: Fri, 31 Oct 2025 11:51:18 -0700 Subject: [PATCH 27/27] PHP: Common macro added in logger.h Signed-off-by: Prateek Kumar --- logger.h | 83 ++++++++++++++++++++++++++------------------------------ 1 file changed, 38 insertions(+), 45 deletions(-) diff --git a/logger.h b/logger.h index 6569754a..130333dd 100644 --- a/logger.h +++ b/logger.h @@ -156,56 +156,49 @@ void valkey_glide_c_log_trace(const char* identifier, const char* message); #define VALKEY_LOG_DEBUG(identifier, message) valkey_glide_c_log_debug(identifier, message) #define VALKEY_LOG_TRACE(identifier, message) valkey_glide_c_log_trace(identifier, message) -/* Dynamic allocation macro for formatted debug logging */ -#define VALKEY_LOG_DEBUG_FMT(category, format, ...) \ - do { \ - if (valkey_glide_logger_get_level() == VALKEY_LOG_LEVEL_OFF || \ - VALKEY_LOG_LEVEL_DEBUG > valkey_glide_logger_get_level()) \ - break; \ - int needed_size = snprintf(NULL, 0, format, __VA_ARGS__) + 1; \ - char* debug_msg = emalloc(needed_size); \ - if (debug_msg) { \ - snprintf(debug_msg, needed_size, format, __VA_ARGS__); \ - VALKEY_LOG_DEBUG(category, debug_msg); \ - efree(debug_msg); \ - } else { \ - VALKEY_LOG_ERROR(category, "Failed to allocate memory for debug message"); \ - } \ +/* Base macro for formatted logging with dynamic allocation */ +#define VALKEY_LOG_FMT_BASE(level_constant, level_function, level_name, category, format, ...) \ + do { \ + if (valkey_glide_logger_get_level() == VALKEY_LOG_LEVEL_OFF || \ + level_constant > valkey_glide_logger_get_level()) \ + break; \ + int needed_size = snprintf(NULL, 0, format, __VA_ARGS__) + 1; \ + char* log_msg = emalloc(needed_size); \ + if (log_msg) { \ + snprintf(log_msg, needed_size, format, __VA_ARGS__); \ + level_function(category, log_msg); \ + efree(log_msg); \ + } else { \ + VALKEY_LOG_ERROR(category, "Failed to allocate memory for " level_name " message"); \ + } \ } while (0) +/* Dynamic allocation macro for formatted debug logging */ +#define VALKEY_LOG_DEBUG_FMT(category, format, ...) \ + VALKEY_LOG_FMT_BASE(VALKEY_LOG_LEVEL_DEBUG, \ + VALKEY_LOG_DEBUG, \ + VALKEY_LOG_LEVEL_DEBUG_STR, \ + category, \ + format, \ + __VA_ARGS__) + /* Dynamic allocation macro for formatted error logging */ -#define VALKEY_LOG_ERROR_FMT(category, format, ...) \ - do { \ - if (valkey_glide_logger_get_level() == VALKEY_LOG_LEVEL_OFF || \ - VALKEY_LOG_LEVEL_ERROR > valkey_glide_logger_get_level()) \ - break; \ - int needed_size = snprintf(NULL, 0, format, __VA_ARGS__) + 1; \ - char* error_msg = emalloc(needed_size); \ - if (error_msg) { \ - snprintf(error_msg, needed_size, format, __VA_ARGS__); \ - VALKEY_LOG_ERROR(category, error_msg); \ - efree(error_msg); \ - } else { \ - VALKEY_LOG_ERROR(category, "Failed to allocate memory for error message"); \ - } \ - } while (0) +#define VALKEY_LOG_ERROR_FMT(category, format, ...) \ + VALKEY_LOG_FMT_BASE(VALKEY_LOG_LEVEL_ERROR, \ + VALKEY_LOG_ERROR, \ + VALKEY_LOG_LEVEL_ERROR_STR, \ + category, \ + format, \ + __VA_ARGS__) /* Dynamic allocation macro for formatted warning logging */ -#define VALKEY_LOG_WARN_FMT(category, format, ...) \ - do { \ - if (valkey_glide_logger_get_level() == VALKEY_LOG_LEVEL_OFF || \ - VALKEY_LOG_LEVEL_WARN > valkey_glide_logger_get_level()) \ - break; \ - int needed_size = snprintf(NULL, 0, format, __VA_ARGS__) + 1; \ - char* warn_msg = emalloc(needed_size); \ - if (warn_msg) { \ - snprintf(warn_msg, needed_size, format, __VA_ARGS__); \ - VALKEY_LOG_WARN(category, warn_msg); \ - efree(warn_msg); \ - } else { \ - VALKEY_LOG_ERROR(category, "Failed to allocate memory for warning message"); \ - } \ - } while (0) +#define VALKEY_LOG_WARN_FMT(category, format, ...) \ + VALKEY_LOG_FMT_BASE(VALKEY_LOG_LEVEL_WARN, \ + VALKEY_LOG_WARN, \ + VALKEY_LOG_LEVEL_WARN_STR, \ + category, \ + format, \ + __VA_ARGS__) /* ============================================================================ * Utility Functions