Index: /trunk/ChangeLog
===================================================================
--- /trunk/ChangeLog	(revision 1063)
+++ /trunk/ChangeLog	(revision 1064)
@@ -3,4 +3,5 @@
 ========
  * chg: proto array xcache_clear_cache(int type, [ int id = -1 ]). -1 means all cache splits
+ * new: proto array xcache_enable_cache(int type, [ int id = -1, [ bool enable = true ] ])
 
 Ini Settings Changes
Index: /trunk/NEWS
===================================================================
--- /trunk/NEWS	(revision 1063)
+++ /trunk/NEWS	(revision 1064)
@@ -4,4 +4,5 @@
  * adds warning for misconfiguration
  * auto disable caching on crash
+ * updated api
  * uses extension to load XCache. load via zend_extension is unsupported
  * updated XCache admin page
Index: /trunk/htdocs/cacher/cacher-zh-simplified.lang.php
===================================================================
--- /trunk/htdocs/cacher/cacher-zh-simplified.lang.php	(revision 1063)
+++ /trunk/htdocs/cacher/cacher-zh-simplified.lang.php	(revision 1064)
@@ -18,6 +18,12 @@
 		'Normal'
 		=> '正常',
-		'Compiling(%s)'
-		=> '编译中(%s)',
+		'Compiling'
+		=> '编译中',
+		'Disabled'
+		=> '禁用',
+		'Disable'
+		=> '禁用',
+		'Enable'
+		=> '启用',
 		'Modify'
 		=> '修改',
Index: /trunk/htdocs/cacher/cacher-zh-traditional.lang.php
===================================================================
--- /trunk/htdocs/cacher/cacher-zh-traditional.lang.php	(revision 1063)
+++ /trunk/htdocs/cacher/cacher-zh-traditional.lang.php	(revision 1064)
@@ -18,6 +18,12 @@
 		'Normal'
 		=> '正常',
-		'Compiling(%s)'
-		=> '編譯中(%s)',
+		'Compiling'
+		=> '編譯中',
+		'Disabled'
+		=> '禁用',
+		'Disable'
+		=> '禁用',
+		'Enable'
+		=> '啟用',
 		'Modify'
 		=> '修改',
Index: /trunk/htdocs/cacher/cacher.php
===================================================================
--- /trunk/htdocs/cacher/cacher.php	(revision 1063)
+++ /trunk/htdocs/cacher/cacher.php	(revision 1064)
@@ -158,6 +158,6 @@
 $_GET['type'] = $type = (int) $_GET['type'];
 
-// {{{ process clear
-function processClear()
+// {{{ process clear, enable, disable
+function processAction()
 {
 	$type = isset($_POST['type']) ? $_POST['type'] : null;
@@ -168,17 +168,15 @@
 		$cacheid = (int) (isset($_POST['cacheid']) ? $_POST['cacheid'] : 0);
 		if (isset($_POST['clearcache'])) {
-			$count = xcache_count($type);
-			if ($cacheid >= 0) {
-				for ($cacheid = 0; $cacheid < $count; $cacheid ++) {
-					xcache_clear_cache($type, $cacheid);
-				}
-			}
-			else {
-				xcache_clear_cache($type);
-			}
-		}
-	}
-}
-processClear();
+			xcache_clear_cache($type, $cacheid);
+		}
+		if (isset($_POST['enable'])) {
+			xcache_enable_cache($type, $cacheid);
+		}
+		if (isset($_POST['disable'])) {
+			xcache_enable_cache($type, $cacheid, false);
+		}
+	}
+}
+processAction();
 // }}}
 // {{{ load info/list
@@ -207,4 +205,5 @@
 	$total['gc'] = null;
 	$total['istotal'] = true;
+	unset($total['compiling']);
 	$cacheinfos[] = $total;
 }
Index: /trunk/htdocs/cacher/cacher.tpl.php
===================================================================
--- /trunk/htdocs/cacher/cacher.tpl.php	(revision 1063)
+++ /trunk/htdocs/cacher/cacher.tpl.php	(revision 1064)
@@ -55,4 +55,9 @@
 	$numkeys = explode(',', 'slots,size,avail,hits,updates,skips,ooms,errors,cached,deleted');
 	$l_clear = _('Clear');
+	$l_disabled = _('Disabled');
+	$l_disable = _('Disable');
+	$l_enable = _('Enable');
+	$l_compiling = _('Compiling');
+	$l_normal = _('Normal');
 	$l_clear_confirm = _('Sure to clear?');
 	foreach ($cacheinfos as $i => $ci) {
@@ -92,6 +97,12 @@
 		}
 		else {
-			if ($ci['type'] == $type_php) {
-			$ci['status'] = $ci['compiling'] ? sprintf(_('Compiling(%s)'), age($ci['compiling'])) : _('Normal');
+			if ($ci['disabled']) {
+				$ci['status'] = $l_disabled
+					. sprintf("(%s)", age($ci['disabled']));
+			}
+			else if ($ci['type'] == $type_php) {
+				$ci['status'] = $ci['compiling']
+					? $l_compiling . sprintf("(%s)", age($ci['compiling']))
+					: $l_normal;
 			}
 			else {
@@ -100,4 +111,6 @@
 			$ci['can_readonly'] = $ci['can_readonly'] ? 'yes' : 'no';
 		}
+		$enabledisable = $ci['disabled'] ? 'enable' : 'disable';
+		$l_enabledisable = $ci['disabled'] ? $l_enable : $l_disable;
 		echo <<<EOS
 		<th>{$ci['cache_name']}</th>
@@ -117,4 +130,5 @@
 					/><input type="hidden" name="cacheid" value="{$ci['cacheid']}"
 					/><input type="submit" name="clearcache" value="{$l_clear}" class="submit" onclick="return confirm('{$l_clear_confirm}');"
+					/><input type="submit" name="{$enabledisable}" value="{$l_enabledisable}" class="submit"
 				/></div
 			></form
Index: /trunk/mod_cacher/xc_cacher.c
===================================================================
--- /trunk/mod_cacher/xc_cacher.c	(revision 1063)
+++ /trunk/mod_cacher/xc_cacher.c	(revision 1064)
@@ -69,4 +69,5 @@
 
 	time_t     compiling;
+	time_t     disabled;
 	zend_ulong updates;
 	zend_ulong hits;
@@ -131,11 +132,4 @@
 
 typedef enum { XC_TYPE_PHP, XC_TYPE_VAR } xc_entry_type_t;
-
-/* TODO */
-static inline zend_bool xc_cache_disabled()
-{
-	return 0;
-}
-/* }}} */
 
 /* any function in *_unlocked is only safe be called within locked (single thread access) area */
@@ -501,5 +495,5 @@
 {
 	TRACE("interval %lu, %lu %lu", (zend_ulong) XG(request_time), (zend_ulong) cache->cached->last_gc_expires, gc_interval);
-	if (XG(request_time) >= cache->cached->last_gc_expires + (time_t) gc_interval) {
+	if (!cache->cached->disabled && XG(request_time) >= cache->cached->last_gc_expires + (time_t) gc_interval) {
 		ENTER_LOCK(cache) {
 			if (XG(request_time) >= cache->cached->last_gc_expires + (time_t) gc_interval) {
@@ -563,5 +557,5 @@
 static XC_CACHE_APPLY_FUNC(xc_gc_deletes_one) /* {{{ */
 {
-	if (cache->cached->deletes && XG(request_time) - cache->cached->last_gc_deletes > xc_deletes_gc_interval) {
+	if (!cache->cached->disabled && cache->cached->deletes && XG(request_time) - cache->cached->last_gc_deletes > xc_deletes_gc_interval) {
 		ENTER_LOCK(cache) {
 			if (cache->cached->deletes && XG(request_time) - cache->cached->last_gc_deletes > xc_deletes_gc_interval) {
@@ -614,4 +608,5 @@
 	add_assoc_long_ex(return_value, ZEND_STRS("slots"),     cache->hentry->size);
 	add_assoc_long_ex(return_value, ZEND_STRS("compiling"), cached->compiling);
+	add_assoc_long_ex(return_value, ZEND_STRS("disabled"),  cached->disabled);
 	add_assoc_long_ex(return_value, ZEND_STRS("updates"),   cached->updates);
 	add_assoc_long_ex(return_value, ZEND_STRS("misses"),    cached->updates); /* deprecated */
@@ -2049,6 +2044,9 @@
 	xc_sandboxed_compiler_t sandboxed_compiler;
 
+	if (cache->cached->disabled) {
+		return old_compile_file(h, type TSRMLS_CC);
+	}
 	/* stale skips precheck */
-	if (XG(request_time) - cache->cached->compiling < 30) {
+	if (cache->cached->disabled || XG(request_time) - cache->cached->compiling < 30) {
 		cache->cached->skips ++;
 		return old_compile_file(h, type TSRMLS_CC);
@@ -2170,5 +2168,4 @@
 	 || strstr(PG(include_path), "://") != NULL
 #endif
-	 || xc_cache_disabled()
 	 ) {
 		TRACE("%s", "cacher not enabled");
@@ -2481,10 +2478,8 @@
 static void xc_request_shutdown(TSRMLS_D) /* {{{ */
 {
-	if (!xc_cache_disabled()) {
-		xc_entry_unholds(TSRMLS_C);
-		xc_gc_expires_php(TSRMLS_C);
-		xc_gc_expires_var(TSRMLS_C);
-		xc_gc_deletes(TSRMLS_C);
-	}
+	xc_entry_unholds(TSRMLS_C);
+	xc_gc_expires_php(TSRMLS_C);
+	xc_gc_expires_var(TSRMLS_C);
+	xc_gc_deletes(TSRMLS_C);
 #ifdef ZEND_ENGINE_2
 	zend_llist_destroy(&XG(gc_op_arrays));
@@ -2608,5 +2603,5 @@
 } /* }}} */
 /* {{{ xcache_admin_operate */
-typedef enum { XC_OP_COUNT, XC_OP_INFO, XC_OP_LIST, XC_OP_CLEAR } xcache_op_type;
+typedef enum { XC_OP_COUNT, XC_OP_INFO, XC_OP_LIST, XC_OP_CLEAR, XC_OP_ENABLE } xcache_op_type;
 static void xcache_admin_operate(xcache_op_type optype, INTERNAL_FUNCTION_PARAMETERS)
 {
@@ -2615,8 +2610,9 @@
 	xc_cache_t *caches, *cache;
 	long id = 0;
+	zend_bool enable = 1;
 
 	xcache_admin_auth_check(TSRMLS_C);
 
-	if (!xc_initized || xc_cache_disabled()) {
+	if (!xc_initized) {
 		RETURN_NULL();
 	}
@@ -2628,4 +2624,5 @@
 			}
 			break;
+
 		case XC_OP_CLEAR:
 			id = -1;
@@ -2634,4 +2631,12 @@
 			}
 			break;
+
+		case XC_OP_ENABLE:
+			id = -1;
+			if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|lb", &type, &id, &enable) == FAILURE) {
+				return;
+			}
+			break;
+
 		default:
 			if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &type, &id) == FAILURE) {
@@ -2699,4 +2704,21 @@
 			break;
 
+		case XC_OP_ENABLE:
+			if (!caches || id < -1 || id >= size) {
+				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cache not exists");
+				RETURN_FALSE;
+			}
+
+			if (id == -1) {
+				for (id = 0; id < size; ++id) {
+					caches[id].cached->disabled = !enable ? XG(request_time) : 0;
+				}
+			}
+			else {
+				caches[id].cached->disabled = !enable ? XG(request_time) : 0;
+			}
+
+			break;
+
 		default:
 			assert(0);
@@ -2732,6 +2754,13 @@
 }
 /* }}} */
-
-#define VAR_DISABLED_WARNING() do { \
+/* {{{ proto array xcache_enable_cache(int type, [ int id = -1, [ bool enable = true ] ])
+   Enable or disable cache by id on specified cache type */
+PHP_FUNCTION(xcache_enable_cache)
+{
+	xcache_admin_operate(XC_OP_ENABLE, INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+/* }}} */
+
+#define VAR_CACHE_NOT_INITIALIZED() do { \
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "XCache var cache was not initialized properly. Check php log for actual reason"); \
 } while (0)
@@ -2776,6 +2805,6 @@
 	zval *name;
 
-	if (!xc_var_caches || xc_cache_disabled()) {
-		VAR_DISABLED_WARNING();
+	if (!xc_var_caches) {
+		VAR_CACHE_NOT_INITIALIZED();
 		RETURN_NULL();
 	}
@@ -2786,4 +2815,8 @@
 	xc_entry_var_init_key(&entry_var, &entry_hash, name TSRMLS_CC);
 	cache = &xc_var_caches[entry_hash.cacheid];
+
+	if (cache->cached->disabled) {
+		RETURN_NULL();
+	}
 
 	ENTER_LOCK(cache) {
@@ -2810,6 +2843,6 @@
 	zval *value;
 
-	if (!xc_var_caches || xc_cache_disabled()) {
-		VAR_DISABLED_WARNING();
+	if (!xc_var_caches) {
+		VAR_CACHE_NOT_INITIALIZED();
 		RETURN_NULL();
 	}
@@ -2832,4 +2865,8 @@
 	xc_entry_var_init_key(&entry_var, &entry_hash, name TSRMLS_CC);
 	cache = &xc_var_caches[entry_hash.cacheid];
+
+	if (cache->cached->disabled) {
+		RETURN_NULL();
+	}
 
 	ENTER_LOCK(cache) {
@@ -2852,6 +2889,6 @@
 	zval *name;
 
-	if (!xc_var_caches || xc_cache_disabled()) {
-		VAR_DISABLED_WARNING();
+	if (!xc_var_caches) {
+		VAR_CACHE_NOT_INITIALIZED();
 		RETURN_FALSE;
 	}
@@ -2862,4 +2899,8 @@
 	xc_entry_var_init_key(&entry_var, &entry_hash, name TSRMLS_CC);
 	cache = &xc_var_caches[entry_hash.cacheid];
+
+	if (cache->cached->disabled) {
+		RETURN_FALSE;
+	}
 
 	ENTER_LOCK(cache) {
@@ -2886,6 +2927,6 @@
 	zval *name;
 
-	if (!xc_var_caches || xc_cache_disabled()) {
-		VAR_DISABLED_WARNING();
+	if (!xc_var_caches) {
+		VAR_CACHE_NOT_INITIALIZED();
 		RETURN_FALSE;
 	}
@@ -2896,4 +2937,8 @@
 	xc_entry_var_init_key(&entry_var, &entry_hash, name TSRMLS_CC);
 	cache = &xc_var_caches[entry_hash.cacheid];
+
+	if (cache->cached->disabled) {
+		RETURN_FALSE;
+	}
 
 	ENTER_LOCK(cache) {
@@ -2916,6 +2961,6 @@
 	int i, iend;
 
-	if (!xc_var_caches || xc_cache_disabled()) {
-		VAR_DISABLED_WARNING();
+	if (!xc_var_caches) {
+		VAR_CACHE_NOT_INITIALIZED();
 		RETURN_FALSE;
 	}
@@ -2927,4 +2972,8 @@
 	for (i = 0, iend = xc_var_hcache.size; i < iend; i ++) {
 		xc_cache_t *cache = &xc_var_caches[i];
+		if (cache->cached->disabled) {
+			continue;
+		}
+
 		ENTER_LOCK(cache) {
 			int entryslotid, jend;
@@ -2952,6 +3001,6 @@
 	zval oldzval;
 
-	if (!xc_var_caches || xc_cache_disabled()) {
-		VAR_DISABLED_WARNING();
+	if (!xc_var_caches) {
+		VAR_CACHE_NOT_INITIALIZED();
 		RETURN_NULL();
 	}
@@ -2969,4 +3018,8 @@
 	xc_entry_var_init_key(&entry_var, &entry_hash, name TSRMLS_CC);
 	cache = &xc_var_caches[entry_hash.cacheid];
+
+	if (cache->cached->disabled) {
+		RETURN_NULL();
+	}
 
 	ENTER_LOCK(cache) {
@@ -3034,4 +3087,5 @@
 	PHP_FE(xcache_list,              NULL)
 	PHP_FE(xcache_clear_cache,       NULL)
+	PHP_FE(xcache_enable_cache,      NULL)
 	PHP_FE(xcache_get,               NULL)
 	PHP_FE(xcache_set,               NULL)
@@ -3360,2 +3414,24 @@
 }
 /* }}} */
+void xc_cacher_disable() /* {{{ */
+{
+	time_t now = time(NULL);
+	size_t i;
+
+	if (xc_php_caches) {
+		for (i = 0; i < xc_php_hcache.size; i ++) {
+			if (xc_php_caches[i].cached) {
+				xc_php_caches[i].cached->disabled = now;
+			}
+		}
+	}
+
+	if (xc_var_caches) {
+		for (i = 0; i < xc_var_hcache.size; i ++) {
+			if (xc_var_caches[i].cached) {
+				xc_var_caches[i].cached->disabled = now;
+			}
+		}
+	}
+}
+/* }}} */
Index: /trunk/mod_cacher/xc_cacher.h
===================================================================
--- /trunk/mod_cacher/xc_cacher.h	(revision 1063)
+++ /trunk/mod_cacher/xc_cacher.h	(revision 1064)
@@ -7,5 +7,5 @@
 
 int xc_cacher_startup_module();
-int xc_cacher_disable();
+void xc_cacher_disable();
 
 #endif /* XC_CACHER_H_1CADCD7E46ABC70014D0766CE97B9741 */
