Browse Source

revert MemcachedEngine

euromark 12 years ago
parent
commit
aa5e03fa3e
2 changed files with 94 additions and 108 deletions
  1. 68 84
      Lib/Cache/Engine/MemcachedEngine.php
  2. 26 24
      View/Helper/FormExtHelper.php

+ 68 - 84
Lib/Cache/Engine/MemcachedEngine.php

@@ -6,45 +6,58 @@
  * PHP 5
  *
  * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
- * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
+ * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  *
  * Licensed under The MIT License
  * Redistributions of files must retain the above copyright notice.
  *
- * @copyright     Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
+ * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  * @link          http://cakephp.org CakePHP(tm) Project
  * @package       Cake.Cache.Engine
  * @since         CakePHP(tm) v 1.2.0.4933
- * @license       MIT License (http://www.opensource.org/licenses/mit-license.php)
+ * @license       http://www.opensource.org/licenses/mit-license.php MIT License
  */
 
 /**
- * Memcached storage engine for cache. This is the new more powerful memcache class (see MemcacheEngine for the former one).
+ * Memcached storage engine for cache.  Memcached has some limitations in the amount of
+ * control you have over expire times far in the future. See MemcachedEngine::write() for
+ * more information.
+ *
+ * Cache::clear() is not implemented due to lack of support from memcached api.
+ * If clear() support is primordial to you, use the default memcache engine.
+ *
+ * Main advantage of this Memcached engine over the Memcache engine is
+ * support of binary protocol, and igbibnary serialization
+ * (if memcached extension compiled with --enable-igbinary).
+ * Compressed keys can also be incremented/decremented.
  *
  * @package       Cake.Cache.Engine
  */
 class MemcachedEngine extends CacheEngine {
 
 /**
- * Contains the compiled group names
- * (prefixed witht the global configuration prefix)
- *
- * @var array
- **/
-	protected $_compiledGroupNames = array();
-
-/**
- * Memcache wrapper.
+ * Memcached wrapper.
  *
  * @var Memcache
  */
 	protected $_Memcached = null;
 
 /**
+ * @var string Keyname of the cache entry holding all the others key name
+ */
+	protected $_keys = '_keys';
+
+/**
+ * @var string Token used to separe each keyname in the $_keys string
+ */
+	protected $_keySeparator = '|';
+
+/**
  * Settings
  *
  *  - servers = string or array of memcache servers, default => 127.0.0.1. If an
  *    array MemcacheEngine will use them as a pool.
+ *  - compress = boolean, default => false
  *
  * @var array
  */
@@ -74,24 +87,51 @@ class MemcachedEngine extends CacheEngine {
 		);
 		parent::init($settings);
 
-		if (is_string($this->settings['servers'])) {
+		$this->_keys .= $this->settings['prefix'];
+
+		if (!is_array($this->settings['servers'])) {
 			$this->settings['servers'] = array($this->settings['servers']);
 		}
 		if (!isset($this->_Memcached)) {
 			$return = false;
-			$this->_Memcached = new Memcached();
-			foreach ($this->settings['servers'] as $server) {
-				list($host, $port) = $this->_parseServerString($server);
-				if ($this->_Memcached->addServer($host, $port)) {
+			$this->_Memcached = new Memcached($this->settings['persistent'] ? 'mc' : null);
+			$this->_setOptions();
+
+			if (!count($this->_Memcached->getServerList())) {
+				$servers = array();
+				foreach ($this->settings['servers'] as $server) {
+					$servers[] = $this->_parseServerString($server);
+				}
+
+				if ($this->_Memcached->addServers($servers)) {
 					$return = true;
 				}
+
 			}
+
+			if (!$this->_Memcached->get($this->_keys)) $this->_Memcached->set($this->_keys, '');
 			return $return;
 		}
+
 		return true;
 	}
 
 /**
+ * Settings the memcached instance
+ *
+ */
+	protected function _setOptions() {
+		$this->_Memcached->setOption(Memcached::OPT_LIBKETAMA_COMPATIBLE, true);
+		$this->_Memcached->setOption(Memcached::OPT_BINARY_PROTOCOL, true);
+
+		if (Memcached::HAVE_IGBINARY) {
+			$this->_Memcached->setOption(Memcached::OPT_SERIALIZER, Memcached::SERIALIZER_IGBINARY);
+		}
+
+		$this->_Memcached->setOption(Memcached::OPT_COMPRESSION, (bool)$this->settings['compress']);
+	}
+
+/**
  * Parses the server address into the host/port. Handles both IPv6 and IPv4
  * addresses and Unix sockets
  *
@@ -99,10 +139,10 @@ class MemcachedEngine extends CacheEngine {
  * @return array Array containing host, port
  */
 	protected function _parseServerString($server) {
-		if ($server[0] == 'u') {
+		if ($server[0] === 'u') {
 			return array($server, 0);
 		}
-		if (substr($server, 0, 1) == '[') {
+		if (substr($server, 0, 1) === '[') {
 			$position = strpos($server, ']:');
 			if ($position !== false) {
 				$position++;
@@ -116,7 +156,7 @@ class MemcachedEngine extends CacheEngine {
 			$host = substr($server, 0, $position);
 			$port = substr($server, $position + 1);
 		}
-		return array($host, $port);
+		return array($host, (int)$port);
 	}
 
 /**
@@ -134,6 +174,8 @@ class MemcachedEngine extends CacheEngine {
 		if ($duration > 30 * DAY) {
 			$duration = 0;
 		}
+
+		$this->_Memcached->append($this->_keys, str_replace($this->settings['prefix'], '', $this->_keySeparator . $key));
 		return $this->_Memcached->set($key, $value, $duration);
 	}
 
@@ -188,71 +230,13 @@ class MemcachedEngine extends CacheEngine {
  * @return boolean True if the cache was successfully cleared, false otherwise
  */
 	public function clear($check) {
-		if ($check) {
-			return true;
-		}
-		foreach ($this->_Memcached->getExtendedStats('slabs') as $slabs) {
-			foreach (array_keys($slabs) as $slabId) {
-				if (!is_numeric($slabId)) {
-					continue;
-				}
+		$keys = array_slice(explode($this->_keySeparator, $this->_Memcached->get($this->_keys)), 1);
 
-				foreach ($this->_Memcached->getExtendedStats('cachedump', $slabId) as $stats) {
-					if (!is_array($stats)) {
-						continue;
-					}
-					foreach (array_keys($stats) as $key) {
-						if (strpos($key, $this->settings['prefix']) === 0) {
-							$this->_Memcached->delete($key);
-						}
-					}
-				}
-			}
-		}
-		return true;
-	}
+		foreach($keys as $key)
+			$this->_Memcached->delete($this->settings['prefix'] . $key);
 
-/**
- * Returns the `group value` for each of the configured groups
- * If the group initial value was not found, then it initializes
- * the group accordingly.
- *
- * @return array
- **/
-	public function groups() {
-		if (empty($this->_compiledGroupNames)) {
-			foreach ($this->settings['groups'] as $group) {
-				$this->_compiledGroupNames[] = $this->settings['prefix'] . $group;
-			}
-		}
-
-		$groups = $this->_Memcached->get($this->_compiledGroupNames);
-		if (count($groups) !== count($this->settings['groups'])) {
-			foreach ($this->_compiledGroupNames as $group) {
-				if (!isset($groups[$group])) {
-					$this->_Memcached->set($group, 1, false, 0);
-					$groups[$group] = 1;
-				}
-			}
-			ksort($groups);
-		}
-
-		$result = array();
-		$groups = array_values($groups);
-		foreach ($this->settings['groups'] as $i => $group) {
-			$result[] = $group . $groups[$i];
-		}
-
-		return $result;
-	}
+		$this->_Memcached->delete($this->_keys);
 
-/**
- * Increments the group value to simulate deletion of all keys under a group
- * old values will remain in storage until they expire.
- *
- * @return boolean success
- **/
-	public function clearGroup($group) {
-		return (bool)$this->_Memcached->increment($this->settings['prefix'] . $group);
+		return true;
 	}
 }

+ 26 - 24
View/Helper/FormExtHelper.php

@@ -24,7 +24,7 @@ class FormExtHelper extends FormHelper {
 	public $helpers = array('Html', 'Js', 'Tools.Common');
 
 	public $settings = array(
-		'webroot' => true # false => tools plugin
+		'webroot' => true // true => APP webroot, false => tools plugin
 	);
 
 	public $scriptsAdded = array(
@@ -459,8 +459,8 @@ class FormExtHelper extends FormHelper {
 							$this->Html->script('datepicker/datepicker', false);
 							$this->Html->css('common/datepicker', null, array('inline'=>false));
 						} else {
-							$this->Common->script(array('Tools.Js|datepicker/lang/' . $lang, 'Tools.Js|datepicker/datepicker'), false);
-							$this->Common->css(array('Tools.Js|datepicker/datepicker'), null, array('inline'=>false));
+							$this->Common->script(array('Tools.Asset|datepicker/lang/' . $lang, 'Tools.Asset|datepicker/datepicker'), false);
+							$this->Common->css(array('Tools.Asset|datepicker/datepicker'), null, array('inline'=>false));
 						}
 						$this->scriptsAdded['date'] = true;
 						break;
@@ -503,10 +503,10 @@ class FormExtHelper extends FormHelper {
 		}
 
 		if (strpos($field, '.') !== false) {
-			list($model, $field) = explode('.', $field, 2);
+			list($modelName, $field) = explode('.', $field, 2);
 		} else {
 			$entity = $this->entity();
-			$model = $this->model();
+			$modelName = $this->model();
 		}
 
 		$defaultOptions = array(
@@ -529,23 +529,22 @@ class FormExtHelper extends FormHelper {
 			$error = '';
 		}
 
-		$fieldname = Inflector::camelize($field);
+		$fieldName = Inflector::camelize($field);
 		$script = '
 <script type="text/javascript">
 	// <![CDATA[
 		var opts = {
-			formElements:{"'.$model.$fieldname.'":"Y","'.$model.$fieldname.'-mm":"m","'.$model.$fieldname.'-dd":"d"},
-			showWeeks:true,
-			statusFormat:"l-cc-sp-d-sp-F-sp-Y",
-
-			// Position the button within a wrapper span with an id of "button-wrapper"
-			positioned:"button-wrapper"
+			formElements: {"'. $modelName . $fieldName. '":"%Y", "' . $modelName . $fieldName . '-mm":"%m", "' . $modelName . $fieldName . '-dd":"%d"},
+			showWeeks: true,
+			statusFormat: "%l, %d. %F %Y",
+			' . (!empty($callbacks) ? $callbacks : '') . '
+			positioned: "button-' . $modelName . $fieldName . '"
 		};
 		datePickerController.createDatePicker(opts);
 	// ]]>
 </script>
 		';
-		return '<div class="input date'.(!empty($error)?' error':'').'">'.$this->label($model.'.'.$field, $options['label']).''.$select.''.$error.'</div>'.$script;
+		return '<div class="input date'.(!empty($error)?' error':'').'">'.$this->label($modelName.'.'.$field, $options['label']).''.$select.''.$error.'</div>'.$script;
 	}
 
 	/**
@@ -658,7 +657,7 @@ class FormExtHelper extends FormHelper {
 		if (!empty($callbacks)) {
 			//callbackFunctions:{"create":...,"dateset":[updateBox]},
 			$c = $callbacks['update'];
-			$callbacks = 'callbackFunctions:{"dateset":['.$c.']},';
+			$callbacks = 'callbackFunctions:{"dateset":[' . $c . ']},';
 		}
 
 		if (!empty($customOptions['type']) && $customOptions['type'] === 'text') {
@@ -666,12 +665,13 @@ class FormExtHelper extends FormHelper {
 <script type="text/javascript">
 	// <![CDATA[
 		var opts = {
-			formElements:{"'.$modelName.$fieldName.'":"d-dt-m-dt-Y"},
-			showWeeks:true,
-			statusFormat:"l-cc-sp-d-sp-F-sp-Y",
-			'.(!empty($callbacks)?$callbacks:'').'
-			// Position the button within a wrapper span with an id of "button-wrapper"
-			positioned:"button-wrapper"
+			formElements: {"' . $modelName . $fieldName . '":"%Y", "' . $modelName . $fieldName . '-mm":"%m", "' . $modelName . $fieldName . '-dd":"%d"},
+			showWeeks: true,
+			fillGrid: true,
+			constrainSelection: true,
+			statusFormat: "%l, %d. %F %Y",
+			' . (!empty($callbacks) ? $callbacks : '') . '
+			positioned: "button-' . $modelName . $fieldName . '"
 		};
 		datePickerController.createDatePicker(opts);
 	// ]]>
@@ -691,12 +691,14 @@ class FormExtHelper extends FormHelper {
 <script type="text/javascript">
 	// <![CDATA[
 		var opts = {
-			formElements:{"'.$modelName.$fieldName.'":"Y","'.$modelName.$fieldName.'-mm":"m","'.$modelName.$fieldName.'-dd":"d"},
+			formElements:{"' . $modelName . $fieldName . '":"%Y", "' . $modelName . $fieldName . '-mm":"%m", "' . $modelName . $fieldName . '-dd":"%d"},
 			showWeeks:true,
-			statusFormat:"l-cc-sp-d-sp-F-sp-Y",
-			'.(!empty($callbacks)?$callbacks:'').'
+			fillGrid:true,
+			constrainSelection:true,
+			statusFormat:"%l, %d. %F %Y",
+			' . (!empty($callbacks) ? $callbacks : '') . '
 			// Position the button within a wrapper span with an id of "button-wrapper"
-			positioned:"button-wrapper"
+			positioned:"button-' . $modelName . $fieldName . '"
 		};
 		datePickerController.createDatePicker(opts);
 	// ]]>