From: Zeev Suraski Date: Thu, 23 Nov 2000 18:43:18 +0000 (+0000) Subject: Very initial work on chunked output buffering. It's really unoptimized at X-Git-Tag: php-4.0.4RC3~71 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=888f376e4cc2c87b0e0c4214e3a5af52f4160b28;p=php Very initial work on chunked output buffering. It's really unoptimized at this time, and it can crash under some circumstances, but that's the concept... --- diff --git a/ext/standard/output.c b/ext/standard/output.c index a64f81502f..88f74b57f0 100644 --- a/ext/standard/output.c +++ b/ext/standard/output.c @@ -30,7 +30,7 @@ static int php_ub_body_write(const char *str, uint str_length); static int php_ub_body_write_no_header(const char *str, uint str_length); static int php_b_body_write(const char *str, uint str_length); -static void php_ob_init(uint initial_size, uint block_size, zval *output_handler); +static void php_ob_init(uint initial_size, uint block_size, zval *output_handler, int chunk_size); static void php_ob_append(const char *text, uint text_length); #if 0 static void php_ob_prepend(const char *text, uint text_length); @@ -88,14 +88,14 @@ PHPAPI int php_header_write(const char *str, uint str_length) } /* Start output buffering */ -PHPAPI int php_start_ob_buffer(zval *output_handler) +PHPAPI int php_start_ob_buffer(zval *output_handler, int chunk_size) { OLS_FETCH(); if (OG(lock)) { return FAILURE; } - php_ob_init(40*1024, 10*1024, output_handler); + php_ob_init(40*1024, 10*1024, output_handler, chunk_size); OG(php_body_write) = php_b_body_write; return SUCCESS; } @@ -228,7 +228,7 @@ static inline void php_ob_allocate(void) } -static void php_ob_init(uint initial_size, uint block_size, zval *output_handler) +static void php_ob_init(uint initial_size, uint block_size, zval *output_handler, int chunk_size) { OLS_FETCH(); @@ -244,6 +244,7 @@ static void php_ob_init(uint initial_size, uint block_size, zval *output_handler OG(active_ob_buffer).buffer = (char *) emalloc(initial_size+1); OG(active_ob_buffer).text_length = 0; OG(active_ob_buffer).output_handler = output_handler; + OG(active_ob_buffer).chunk_size = chunk_size; } @@ -251,11 +252,27 @@ static void php_ob_append(const char *text, uint text_length) { char *target; int original_ob_text_length; + int new_size; OLS_FETCH(); original_ob_text_length=OG(active_ob_buffer).text_length; - OG(active_ob_buffer).text_length += text_length; + new_size = OG(active_ob_buffer).text_length + text_length; + + if (OG(active_ob_buffer).chunk_size + && new_size > OG(active_ob_buffer).chunk_size) { + zval *output_handler = OG(active_ob_buffer).output_handler; + int chunk_size = OG(active_ob_buffer).chunk_size; + + if (output_handler) { + output_handler->refcount++; + } + php_end_ob_buffer(1); + php_start_ob_buffer(output_handler, chunk_size); + php_ob_append(text, text_length); + return; + } + OG(active_ob_buffer).text_length = new_size; php_ob_allocate(); target = OG(active_ob_buffer).buffer+original_ob_text_length; memcpy(target, text, text_length); @@ -396,6 +413,7 @@ static int php_ub_body_write(const char *str, uint str_length) PHP_FUNCTION(ob_start) { zval *output_handler; + int chunk_size=0; switch (ZEND_NUM_ARGS()) { case 0: @@ -412,11 +430,24 @@ PHP_FUNCTION(ob_start) output_handler->refcount++; } break; + case 2: { + zval **output_handler_p, **chunk_size_p; + + if (zend_get_parameters_ex(2, &output_handler_p, &chunk_size_p)==FAILURE) { + RETURN_FALSE; + } + SEPARATE_ZVAL(output_handler_p); + output_handler = *output_handler_p; + output_handler->refcount++; + convert_to_long_ex(chunk_size_p); + chunk_size = Z_LVAL_PP(chunk_size_p); + } + break; default: ZEND_WRONG_PARAM_COUNT(); break; } - if (php_start_ob_buffer(output_handler)==FAILURE) { + if (php_start_ob_buffer(output_handler, chunk_size)==FAILURE) { php_error(E_WARNING, "Cannot use output buffering in output buffering display handlers"); RETURN_FALSE; } diff --git a/ext/standard/php_output.h b/ext/standard/php_output.h index 7d22698796..7a2154f54c 100644 --- a/ext/standard/php_output.h +++ b/ext/standard/php_output.h @@ -26,7 +26,7 @@ PHPAPI void php_output_startup(void); PHPAPI int php_body_write(const char *str, uint str_length); PHPAPI int php_header_write(const char *str, uint str_length); -PHPAPI int php_start_ob_buffer(zval *output_handler); +PHPAPI int php_start_ob_buffer(zval *output_handler, int chunk_size); PHPAPI void php_end_ob_buffer(int send_buffer); PHPAPI void php_end_ob_buffers(int send_buffer); PHPAPI int php_ob_get_buffer(pval *p); @@ -51,6 +51,7 @@ typedef struct _php_ob_buffer { uint text_length; int block_size; zval *output_handler; + int chunk_size; } php_ob_buffer; typedef struct _php_output_globals { diff --git a/main/main.c b/main/main.c index e9ec859198..4d92d309d2 100644 --- a/main/main.c +++ b/main/main.c @@ -632,9 +632,9 @@ int php_request_startup(CLS_D ELS_DC PLS_DC SLS_DC) Z_STRLEN_P(output_handler) = strlen(PG(output_handler)); /* this can be optimized */ Z_STRVAL_P(output_handler) = estrndup(PG(output_handler), Z_STRLEN_P(output_handler)); Z_TYPE_P(output_handler) = IS_STRING; - php_start_ob_buffer(output_handler); + php_start_ob_buffer(output_handler, 0); } else if (PG(output_buffering)) { - php_start_ob_buffer(NULL); + php_start_ob_buffer(NULL, 0); } else if (PG(implicit_flush)) { php_start_implicit_flush(); } diff --git a/main/output.c b/main/output.c index a64f81502f..88f74b57f0 100644 --- a/main/output.c +++ b/main/output.c @@ -30,7 +30,7 @@ static int php_ub_body_write(const char *str, uint str_length); static int php_ub_body_write_no_header(const char *str, uint str_length); static int php_b_body_write(const char *str, uint str_length); -static void php_ob_init(uint initial_size, uint block_size, zval *output_handler); +static void php_ob_init(uint initial_size, uint block_size, zval *output_handler, int chunk_size); static void php_ob_append(const char *text, uint text_length); #if 0 static void php_ob_prepend(const char *text, uint text_length); @@ -88,14 +88,14 @@ PHPAPI int php_header_write(const char *str, uint str_length) } /* Start output buffering */ -PHPAPI int php_start_ob_buffer(zval *output_handler) +PHPAPI int php_start_ob_buffer(zval *output_handler, int chunk_size) { OLS_FETCH(); if (OG(lock)) { return FAILURE; } - php_ob_init(40*1024, 10*1024, output_handler); + php_ob_init(40*1024, 10*1024, output_handler, chunk_size); OG(php_body_write) = php_b_body_write; return SUCCESS; } @@ -228,7 +228,7 @@ static inline void php_ob_allocate(void) } -static void php_ob_init(uint initial_size, uint block_size, zval *output_handler) +static void php_ob_init(uint initial_size, uint block_size, zval *output_handler, int chunk_size) { OLS_FETCH(); @@ -244,6 +244,7 @@ static void php_ob_init(uint initial_size, uint block_size, zval *output_handler OG(active_ob_buffer).buffer = (char *) emalloc(initial_size+1); OG(active_ob_buffer).text_length = 0; OG(active_ob_buffer).output_handler = output_handler; + OG(active_ob_buffer).chunk_size = chunk_size; } @@ -251,11 +252,27 @@ static void php_ob_append(const char *text, uint text_length) { char *target; int original_ob_text_length; + int new_size; OLS_FETCH(); original_ob_text_length=OG(active_ob_buffer).text_length; - OG(active_ob_buffer).text_length += text_length; + new_size = OG(active_ob_buffer).text_length + text_length; + + if (OG(active_ob_buffer).chunk_size + && new_size > OG(active_ob_buffer).chunk_size) { + zval *output_handler = OG(active_ob_buffer).output_handler; + int chunk_size = OG(active_ob_buffer).chunk_size; + + if (output_handler) { + output_handler->refcount++; + } + php_end_ob_buffer(1); + php_start_ob_buffer(output_handler, chunk_size); + php_ob_append(text, text_length); + return; + } + OG(active_ob_buffer).text_length = new_size; php_ob_allocate(); target = OG(active_ob_buffer).buffer+original_ob_text_length; memcpy(target, text, text_length); @@ -396,6 +413,7 @@ static int php_ub_body_write(const char *str, uint str_length) PHP_FUNCTION(ob_start) { zval *output_handler; + int chunk_size=0; switch (ZEND_NUM_ARGS()) { case 0: @@ -412,11 +430,24 @@ PHP_FUNCTION(ob_start) output_handler->refcount++; } break; + case 2: { + zval **output_handler_p, **chunk_size_p; + + if (zend_get_parameters_ex(2, &output_handler_p, &chunk_size_p)==FAILURE) { + RETURN_FALSE; + } + SEPARATE_ZVAL(output_handler_p); + output_handler = *output_handler_p; + output_handler->refcount++; + convert_to_long_ex(chunk_size_p); + chunk_size = Z_LVAL_PP(chunk_size_p); + } + break; default: ZEND_WRONG_PARAM_COUNT(); break; } - if (php_start_ob_buffer(output_handler)==FAILURE) { + if (php_start_ob_buffer(output_handler, chunk_size)==FAILURE) { php_error(E_WARNING, "Cannot use output buffering in output buffering display handlers"); RETURN_FALSE; } diff --git a/main/php_output.h b/main/php_output.h index 7d22698796..7a2154f54c 100644 --- a/main/php_output.h +++ b/main/php_output.h @@ -26,7 +26,7 @@ PHPAPI void php_output_startup(void); PHPAPI int php_body_write(const char *str, uint str_length); PHPAPI int php_header_write(const char *str, uint str_length); -PHPAPI int php_start_ob_buffer(zval *output_handler); +PHPAPI int php_start_ob_buffer(zval *output_handler, int chunk_size); PHPAPI void php_end_ob_buffer(int send_buffer); PHPAPI void php_end_ob_buffers(int send_buffer); PHPAPI int php_ob_get_buffer(pval *p); @@ -51,6 +51,7 @@ typedef struct _php_ob_buffer { uint text_length; int block_size; zval *output_handler; + int chunk_size; } php_ob_buffer; typedef struct _php_output_globals {