Friendica Communications Platform (please note that this is a clone of the repository at github, issues are handled there) https://friendi.ca
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

210 lines
6.3 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. <?php
  2. /**
  3. * @file include/cache.php
  4. *
  5. * @brief Class for storing data for a short time
  6. */
  7. use \Friendica\Core\Config;
  8. use \Friendica\Core\PConfig;
  9. class Cache {
  10. /**
  11. * @brief Check for memcache and open a connection if configured
  12. *
  13. * @return object|boolean The memcache object - or "false" if not successful
  14. */
  15. public static function memcache() {
  16. if (!function_exists('memcache_connect')) {
  17. return false;
  18. }
  19. if (!Config::get('system', 'memcache')) {
  20. return false;
  21. }
  22. $memcache_host = Config::get('system', 'memcache_host', '127.0.0.1');
  23. $memcache_port = Config::get('system', 'memcache_port', 11211);
  24. $memcache = new Memcache;
  25. if (!$memcache->connect($memcache_host, $memcache_port)) {
  26. return false;
  27. }
  28. return $memcache;
  29. }
  30. /**
  31. * @brief Return the duration for a given cache level
  32. *
  33. * @param integer $level Cache level
  34. *
  35. * @return integer The cache duration in seconds
  36. */
  37. private function duration($level) {
  38. switch($level) {
  39. case CACHE_MONTH;
  40. $seconds = 2592000;
  41. break;
  42. case CACHE_WEEK;
  43. $seconds = 604800;
  44. break;
  45. case CACHE_DAY;
  46. $seconds = 86400;
  47. break;
  48. case CACHE_HOUR;
  49. $seconds = 3600;
  50. break;
  51. case CACHE_HALF_HOUR;
  52. $seconds = 1800;
  53. break;
  54. case CACHE_QUARTER_HOUR;
  55. $seconds = 900;
  56. break;
  57. case CACHE_FIVE_MINUTES;
  58. $seconds = 300;
  59. break;
  60. case CACHE_MINUTE;
  61. $seconds = 60;
  62. break;
  63. }
  64. return $seconds;
  65. }
  66. /**
  67. * @brief Fetch cached data according to the key
  68. *
  69. * @param string $key The key to the cached data
  70. *
  71. * @return mixed Cached $value or "null" if not found
  72. */
  73. public static function get($key) {
  74. $memcache = self::memcache();
  75. if (is_object($memcache)) {
  76. // We fetch with the hostname as key to avoid problems with other applications
  77. $cached = $memcache->get(get_app()->get_hostname().":".$key);
  78. $value = @unserialize($cached);
  79. // Only return a value if the serialized value is valid.
  80. // We also check if the db entry is a serialized
  81. // boolean 'false' value (which we want to return).
  82. if ($cached === serialize(false) || $value !== false) {
  83. return $value;
  84. }
  85. return null;
  86. }
  87. // Frequently clear cache
  88. self::clear($duration);
  89. $r = q("SELECT `v` FROM `cache` WHERE `k`='%s' LIMIT 1",
  90. dbesc($key)
  91. );
  92. if (dbm::is_result($r)) {
  93. $cached = $r[0]['v'];
  94. $value = @unserialize($cached);
  95. // Only return a value if the serialized value is valid.
  96. // We also check if the db entry is a serialized
  97. // boolean 'false' value (which we want to return).
  98. if ($cached === serialize(false) || $value !== false) {
  99. return $value;
  100. }
  101. }
  102. return null;
  103. }
  104. /**
  105. * @brief Put data in the cache according to the key
  106. *
  107. * The input $value can have multiple formats.
  108. *
  109. * @param string $key The key to the cached data
  110. * @param mixed $valie The value that is about to be stored
  111. * @param integer $duration The cache lifespan
  112. */
  113. public static function set($key, $value, $duration = CACHE_MONTH) {
  114. // Do we have an installed memcache? Use it instead.
  115. $memcache = self::memcache();
  116. if (is_object($memcache)) {
  117. // We store with the hostname as key to avoid problems with other applications
  118. $memcache->set(get_app()->get_hostname().":".$key, serialize($value), MEMCACHE_COMPRESSED, self::duration($duration));
  119. return;
  120. }
  121. /// @todo store the cache data in the same way like the config data
  122. q("REPLACE INTO `cache` (`k`,`v`,`expire_mode`,`updated`) VALUES ('%s','%s',%d,'%s')",
  123. dbesc($key),
  124. dbesc(serialize($value)),
  125. intval($duration),
  126. dbesc(datetime_convert()));
  127. }
  128. /**
  129. * @brief Remove outdated data from the cache
  130. *
  131. * @param integer $maxlevel The maximum cache level that is to be cleared
  132. */
  133. public static function clear($max_level = CACHE_MONTH) {
  134. // Clear long lasting cache entries only once a day
  135. if (get_config("system", "cache_cleared_day") < time() - self::duration(CACHE_DAY)) {
  136. if ($max_level == CACHE_MONTH) {
  137. q("DELETE FROM `cache` WHERE `updated` < '%s' AND `expire_mode` = %d",
  138. dbesc(datetime_convert('UTC','UTC',"now - 30 days")), intval(CACHE_MONTH));
  139. }
  140. if ($max_level <= CACHE_WEEK) {
  141. q("DELETE FROM `cache` WHERE `updated` < '%s' AND `expire_mode` = %d",
  142. dbesc(datetime_convert('UTC','UTC',"now - 7 days")), intval(CACHE_WEEK));
  143. }
  144. if ($max_level <= CACHE_DAY) {
  145. q("DELETE FROM `cache` WHERE `updated` < '%s' AND `expire_mode` = %d",
  146. dbesc(datetime_convert('UTC','UTC',"now - 1 days")), intval(CACHE_DAY));
  147. }
  148. set_config("system", "cache_cleared_day", time());
  149. }
  150. if (($max_level <= CACHE_HOUR) AND (get_config("system", "cache_cleared_hour")) < time() - self::duration(CACHE_HOUR)) {
  151. q("DELETE FROM `cache` WHERE `updated` < '%s' AND `expire_mode` = %d",
  152. dbesc(datetime_convert('UTC','UTC',"now - 1 hours")), intval(CACHE_HOUR));
  153. set_config("system", "cache_cleared_hour", time());
  154. }
  155. if (($max_level <= CACHE_HALF_HOUR) AND (get_config("system", "cache_cleared_half_hour")) < time() - self::duration(CACHE_HALF_HOUR)) {
  156. q("DELETE FROM `cache` WHERE `updated` < '%s' AND `expire_mode` = %d",
  157. dbesc(datetime_convert('UTC','UTC',"now - 30 minutes")), intval(CACHE_HALF_HOUR));
  158. set_config("system", "cache_cleared_half_hour", time());
  159. }
  160. if (($max_level <= CACHE_QUARTER_HOUR) AND (get_config("system", "cache_cleared_quarter_hour")) < time() - self::duration(CACHE_QUARTER_HOUR)) {
  161. q("DELETE FROM `cache` WHERE `updated` < '%s' AND `expire_mode` = %d",
  162. dbesc(datetime_convert('UTC','UTC',"now - 15 minutes")), intval(CACHE_QUARTER_HOUR));
  163. set_config("system", "cache_cleared_quarter_hour", time());
  164. }
  165. if (($max_level <= CACHE_FIVE_MINUTES) AND (get_config("system", "cache_cleared_five_minute")) < time() - self::duration(CACHE_FIVE_MINUTES)) {
  166. q("DELETE FROM `cache` WHERE `updated` < '%s' AND `expire_mode` = %d",
  167. dbesc(datetime_convert('UTC','UTC',"now - 5 minutes")), intval(CACHE_FIVE_MINUTES));
  168. set_config("system", "cache_cleared_five_minute", time());
  169. }
  170. if (($max_level <= CACHE_MINUTE) AND (get_config("system", "cache_cleared_minute")) < time() - self::duration(CACHE_MINUTE)) {
  171. q("DELETE FROM `cache` WHERE `updated` < '%s' AND `expire_mode` = %d",
  172. dbesc(datetime_convert('UTC','UTC',"now - 1 minutes")), intval(CACHE_MINUTE));
  173. set_config("system", "cache_cleared_minute", time());
  174. }
  175. }
  176. }