diff --git a/apc_sma.c b/apc_sma.c index b0bbbc86..a4534012 100644 --- a/apc_sma.c +++ b/apc_sma.c @@ -631,11 +631,29 @@ PHP_APCU_API zend_bool apc_sma_get_avail_size(apc_sma_t* sma, size_t size) { int32_t i; for (i = 0; i < sma->num; i++) { - sma_header_t* header = SMA_HDR(sma, i); - if (header->avail > size) { - return 1; + sma_header_t *shmaddr = SMA_HDR(sma, i); + + /* If total size of available memory is too small, we can skip the contiguous-block check */ + if (shmaddr->avail < size) { + continue; + } + + SMA_LOCK(sma, i); + block_t *cur = BLOCKAT(ALIGNWORD(sizeof(sma_header_t))); + + /* Look for a contiguous block of memory */ + while (cur->fnext) { + cur = BLOCKAT(cur->fnext); + + if (cur->size >= size) { + SMA_UNLOCK(sma, i); + return 1; + } } + + SMA_UNLOCK(sma, i); } + return 0; } diff --git a/apc_sma.h b/apc_sma.h index b4891f5e..6e4998e1 100644 --- a/apc_sma.h +++ b/apc_sma.h @@ -138,7 +138,7 @@ PHP_APCU_API void apc_sma_free_info(apc_sma_t* sma, apc_sma_info_t* info); PHP_APCU_API size_t apc_sma_get_avail_mem(apc_sma_t* sma); /* -* apc_sma_api_get_avail_size will return true if at least size bytes are available to the sma +* apc_sma_api_get_avail_size will return true if at least size contiguous bytes are available to the sma */ PHP_APCU_API zend_bool apc_sma_get_avail_size(apc_sma_t* sma, size_t size); diff --git a/tests/apc_020.phpt b/tests/apc_020.phpt index ea388d31..7c74ee3d 100644 --- a/tests/apc_020.phpt +++ b/tests/apc_020.phpt @@ -17,7 +17,7 @@ apc.shm_size=1M apcu_store("no_ttl_unaccessed", 12); apcu_store("no_ttl_accessed", 24); apcu_store("ttl", 42, 3); -apcu_store("dummy", "xxx"); +apcu_store("dummy", str_repeat('x', 1000)); apcu_inc_request_time(1); apcu_fetch("no_ttl_accessed");