public static function set($type, $id, $object) { $loc = CacheLocal::get(); if (!$loc->enabled) { return false; } $key = Cache::key($type, $id); if (is_object($object)) { $r = clone $object; } else { $r = $object; } $loc->cache[$key] = $r; }
function getNoticeIds($offset, $limit, $sinceId, $maxId) { $cache = Cache::instance(); // We cache self::CACHE_WINDOW elements at the tip of the stream. // If the cache won't be hit, just generate directly. if (empty($cache) || $sinceId != 0 || $maxId != 0 || is_null($limit) || $offset + $limit > self::CACHE_WINDOW) { return $this->stream->getNoticeIds($offset, $limit, $sinceId, $maxId); } // Check the cache to see if we have the stream. $idkey = Cache::key($this->cachekey); $idstr = $cache->get($idkey); if ($idstr !== false) { // Cache hit! Woohoo! $window = explode(',', $idstr); $ids = array_slice($window, $offset, $limit); return $ids; } if ($this->useLast) { // Check the cache to see if we have a "last-known-good" version. // The actual cache gets blown away when new notices are added, but // the "last" value holds a lot of info. We might need to only generate // a few at the "tip", which can bound our queries and save lots // of time. $laststr = $cache->get($idkey . ';last'); if ($laststr !== false) { $window = explode(',', $laststr); $last_id = $window[0]; $new_ids = $this->stream->getNoticeIds(0, self::CACHE_WINDOW, $last_id, 0); $new_window = array_merge($new_ids, $window); $new_windowstr = implode(',', $new_window); $result = $cache->set($idkey, $new_windowstr); $result = $cache->set($idkey . ';last', $new_windowstr); $ids = array_slice($new_window, $offset, $limit); return $ids; } } // No cache hits :( Generate directly and stick the results // into the cache. Note we generate the full cache window. $window = $this->stream->getNoticeIds(0, self::CACHE_WINDOW, 0, 0); $windowstr = implode(',', $window); $result = $cache->set($idkey, $windowstr); if ($this->useLast) { $result = $cache->set($idkey . ';last', $windowstr); } // Return just the slice that was requested $ids = array_slice($window, $offset, $limit); return $ids; }
function handle($args) { parent::handle($args); $c = Cache::instance(); if (!empty($c)) { $cacheKey = Cache::key(MinifyPlugin::cacheKey . ':' . $this->file . '?v=' . empty($this->v) ? '' : $this->v); $out = $c->get($cacheKey); } if (empty($out)) { $out = $this->minify($this->file); } if (!empty($c)) { $c->set($cacheKey, $out); } $sec = session_cache_expire() * 60; header('Cache-Control: public, max-age=' . $sec); header('Pragma: public'); $this->raw($out); }
static function getFavesCount($notice_id) { $c = Cache::instance(); if (!empty($c)) { $cnt = $c->get(Cache::key('notice:favorites_count:' . $notice_id)); if (is_integer($cnt)) { return (int) $cnt; } } $original = Notice::staticGet('id', $notice_id); $cnt = $original->favorites_count; if (!empty($c)) { $c->set(Cache::key('notice:favorites_count:' . $notice_id), $cnt); } return empty($cnt) ? 0 : $cnt; }
static function cacheSet($keyPart, $value, $flag = null, $expiry = null) { $c = self::memcache(); if (empty($c)) { return false; } $cacheKey = Cache::key($keyPart); return $c->set($cacheKey, $value, $flag, $expiry); }
function onStartStyleElement($action, &$code, &$type, &$media) { if ($this->minifyInlineCss && $type == 'text/css') { $c = Cache::instance(); if (!empty($c)) { $cacheKey = Cache::key(self::cacheKey . ':' . crc32($code)); $out = $c->get($cacheKey); } if (empty($out)) { $out = $this->minifyCss($code); } if (!empty($c)) { $c->set($cacheKey, $out); } if (!empty($out)) { $code = $out; } } }
function getNotices($y, $m, $d, $i) { $n = Notice::cacheGet("sitemap:notice:{$y}:{$m}:{$d}:{$i}"); if ($n === false) { $notice = new Notice(); $begindt = sprintf('%04d-%02d-%02d 00:00:00', $y, $m, $d); // XXX: estimates 1d == 24h, which screws up days // with leap seconds (1d == 24h + 1s). Thankfully they're // few and far between. $theend = strtotime($begindt) + 24 * 60 * 60; $enddt = common_sql_date($theend); $notice->selectAdd(); $notice->selectAdd('id, created'); $notice->whereAdd("created >= '{$begindt}'"); $notice->whereAdd("created < '{$enddt}'"); $notice->whereAdd('is_local = ' . Notice::LOCAL_PUBLIC); $notice->orderBy('created'); $offset = ($i - 1) * SitemapPlugin::NOTICES_PER_MAP; $limit = SitemapPlugin::NOTICES_PER_MAP; $notice->limit($offset, $limit); $notice->find(); $n = array(); while ($notice->fetch()) { $n[] = array($notice->id, $notice->created); } $c = Cache::instance(); if (!empty($c)) { $c->set(Cache::key("sitemap:notice:{$y}:{$m}:{$d}:{$i}"), $n, Cache::COMPRESSED, time() > $theend ? time() + 90 * 24 * 60 * 60 : time() + 5 * 60); } } return $n; }
* * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); $helptext = <<<ENDOFHELP uncache_users.php <idfile> Uncache users listed in an ID file, default 'ids.txt'. ENDOFHELP; require_once INSTALLDIR . '/scripts/commandline.inc'; $id_file = count($args) > 1 ? $args[0] : 'ids.txt'; common_log(LOG_INFO, 'Updating user inboxes.'); $ids = file($id_file); $memc = Cache::instance(); foreach ($ids as $id) { $user = User::staticGet('id', $id); if (!$user) { common_log(LOG_WARNING, 'No such user: '******'user:notices_with_friends:' . $user->id)); $memc->delete(Cache::key('user:notices_with_friends:' . $user->id . ';last')); }
function getUsers($y, $m, $d, $i) { $u = User::cacheGet("sitemap:user:{$y}:{$m}:{$d}:{$i}"); if ($u === false) { $user = new User(); $begindt = sprintf('%04d-%02d-%02d 00:00:00', $y, $m, $d); // XXX: estimates 1d == 24h, which screws up days // with leap seconds (1d == 24h + 1s). Thankfully they're // few and far between. $theend = strtotime($begindt) + 24 * 60 * 60; $enddt = common_sql_date($theend); $user->selectAdd(); $user->selectAdd('nickname'); $user->whereAdd("created >= '{$begindt}'"); $user->whereAdd("created < '{$enddt}'"); $user->orderBy('created'); $offset = ($i - 1) * SitemapPlugin::USERS_PER_MAP; $limit = SitemapPlugin::USERS_PER_MAP; $user->limit($offset, $limit); $user->find(); while ($user->fetch()) { $u[] = $user->nickname; } $c = Cache::instance(); if (!empty($c)) { $c->set(Cache::key("sitemap:user:{$y}:{$m}:{$d}:{$i}"), $u, Cache::COMPRESSED, time() > $theend ? time() + 90 * 24 * 60 * 60 : time() + 5 * 60); } } return $u; }
function getFacebookUser($id) { $key = Cache::key(sprintf("FacebookBridgePlugin:userdata:%s", $id)); $c = Cache::instance(); if ($c) { $obj = $c->get($key); if ($obj) { return $obj; } } $url = sprintf("https://graph.facebook.com/%s", $id); $client = new HTTPClient(); $resp = $client->get($url); if (!$resp->isOK()) { return null; } $user = json_decode($resp->getBody()); if ($user->error) { return null; } if ($c) { $c->set($key, $user); } return $user; }
/** * Create a cache key for data dependent on code * * For cache elements that are dependent on changes in code, this creates * a more-or-less fingerprint of the current running code and adds it to * the cache key. In the case of an upgrade of core, or addition or * removal of plugins, a new unique fingerprint is generated and used. * * There can still be problems with a) differences in versions of the * plugins and b) people running code between official versions. This is * usually a problem only for experienced users like developers, who know * how to clear their cache. * * For sites that run code between versions (like the status.net cloud), * there's an additional build number configuration setting. * * @param string $extra the real part of the key * * @return string full key */ static function codeKey($extra) { static $prefix = null; if (empty($prefix)) { $plugins = StatusNet::getActivePlugins(); $names = array(); foreach ($plugins as $plugin) { $names[] = $plugin[0]; } $names = array_unique($names); asort($names); // Unique enough. $uniq = crc32(implode(',', $names)); $build = common_config('site', 'build'); $prefix = STATUSNET_VERSION . ':' . $build . ':' . $uniq; } return Cache::key($prefix . ':' . $extra); }
include_once "{$lib}/class/file.php"; include_once "{$lib}/share/link.php"; include_once "{$lib}/share/stdio.php"; include_once "{$lib}/share/string.php"; pieLoadLocale(); pieHead(); $_REQUEST['limit'] = intval(@$_REQUEST['limit']); if ($_REQUEST['limit'] < 1) { $_REQUEST['limit'] = 10; } if ($_REQUEST['limit'] > 100) { $_REQUEST['limit'] = 100; } $page = new Page(); $cache = new Cache(); $cid = $cache->key('latest', array()); if ($GLOBALS['pie']['query_caching'] && $cache->exists($cid)) { // Use existing cache. $dump = trim(file_get_contents($cache->file($cid))); $cache->update($cid); $dump = explode("\n", $dump); $data = array(); foreach ($dump as $i) { $data[] = $i; } } else { // Determine latest page changes. $data = array(); for ($name = $page->first(); $name; $name = $page->next()) { $data[] = $page->stamp . "\t{$name}"; }
function get_ldap_connection($config = null) { if ($config == null) { $config = $this->ldap_config; } $config_id = crc32(serialize($config)); if (array_key_exists($config_id, self::$ldap_connections)) { $ldap = self::$ldap_connections[$config_id]; } else { //cannot use Net_LDAP2::connect() as StatusNet uses //PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'handleError'); //PEAR handling can be overridden on instance objects, so we do that. $ldap = new Net_LDAP2($config); $ldap->setErrorHandling(PEAR_ERROR_RETURN); $err = $ldap->bind(); if (Net_LDAP2::isError($err)) { // if we were called with a config, assume caller will handle // incorrect username/password (LDAP_INVALID_CREDENTIALS) if (isset($config) && $err->getCode() == 0x31) { // TRANS: Exception thrown in the LDAP Common plugin when LDAP server is not available. // TRANS: %s is the error message. throw new LdapInvalidCredentialsException(sprintf(_m('Could not connect to LDAP server: %s'), $err->getMessage())); } // TRANS: Exception thrown in the LDAP Common plugin when LDAP server is not available. // TRANS: %s is the error message. throw new Exception(sprintf(_m('Could not connect to LDAP server: %s.'), $err->getMessage())); } $c = Cache::instance(); if (!empty($c)) { $cacheObj = new MemcacheSchemaCache(array('c' => $c, 'cacheKey' => Cache::key('ldap_schema:' . $config_id))); $ldap->registerSchemaCache($cacheObj); } self::$ldap_connections[$config_id] = $ldap; } return $ldap; }
// A file with the name already exists. if (!$file->read($name, 0)) { pieError("FileReadError"); } if ($file->meta['author'] == $GLOBALS['pie']['user'] && !@$_REQUEST['append']) { // The upload is an update by the same user. // Delete the previous version before saving the new one. if (!$file->replace($name)) { pieError("FileWriteError"); } } } // Check for cached thumbnail images of former versions. if ($GLOBALS['pie']['image_caching']) { $cache = new Cache(); $cid = $cache->key('image', array('file' => $name)); if ($cache->exists($cid)) { $cache->delete($cid); } } else { $thumbnail = $GLOBALS['pie']['run_path'] . "/temp/_thumbnail_" . pieEncodeName($name); if (file_exists($thumbnail)) { unlink($thumbnail); } } // Prepare meta data of the file: $file->name = $name; $file->meta = array('stamp' => time(), 'author' => $GLOBALS['pie']['user']); // .. file size if ($_FILES['upload']['size']) { $file->meta['size'] = $_FILES['upload']['size'];
// We are trying to affect an other author's work // ... which is only suitable for admins. if (!pieIsSuperuser($GLOBALS['pie']['user'])) { pieError("AuthorDiffers", array('action' => "{$context}history")); } } // Ask user for acknowledgement to delete the page. pieError("AskApproval"); } // Delete the resource: if (!$object->delete($target)) { pieError("DeleteError"); } if ($context == "page") { // Do what is to be done with pages. if ($object->meta['type'] != "alias") { // Delete the cache, if available. $cache = new Cache(); $cid = $cache->key('page', array('page' => $target)); if ($cache->exists($cid)) { $cache->delete($cid); } if ($cache->exists($cache->key('latest', array()))) { $cache->delete($cache->key('latest', array())); } } $object->unlock($GLOBALS['pie']['user']); } pieLog("alter"); pieNotice("DeleteSuccessful"); pieTail();
if (!$page->isValidName(@$_REQUEST['page'])) { pieError('PageNameInvalid'); } if (!$page->exists(@$_REQUEST['page'])) { pieError('PageNotFound'); } if (@$_REQUEST['old'] > 0 && @$_REQUEST['new'] > 0) { $diff = new Increment(); if (!($old = $diff->readPage($_REQUEST['page'], $_REQUEST['old']))) { pieError('SourceVersionMissing'); } if (!($new = $diff->readPage($_REQUEST['page'], $_REQUEST['new']))) { pieError('SourceVersionMissing'); } $cache = new Cache(); $cid = $cache->key('diff', array('old' => $_REQUEST['old'], 'new' => $_REQUEST['new'])); if ($GLOBALS['pie']['query_caching'] && $cache->exists($cid)) { // Use existing cache. $data = file_get_contents($cache->file($cid)); $cache->update($cid); } else { // Create diff from two versions. if (!($data = $diff->diff($old['source'], $new['source']))) { pieError('DiffError'); } } if ($GLOBALS['pie']['query_caching']) { // Write to cache. if (!($f = fopen($cache->file($cid), 'w'))) { pieError('CacheWriteError'); }
} $total++; } // Walk directory for the second time. This time, encountered // files (and pages contained therein) are imported for real. rewinddir($dh); while (($file = readdir($dh)) !== false) { if ($file == "." || $file == "..") { continue; } if (!importFile($_REQUEST['path'] . "/{$file}")) { pieError("ImportError", array('page' => htmlspecialchars($file))); } $count++; } } elseif (is_readable($_REQUEST['path'])) { // Just one file is to be imported. if (!importFile($_REQUEST['path'])) { pieError("ImportError", array('page' => htmlspecialchars($_REQUEST['path']))); } $total = 1; $count = 1; } // Update the cache. $cache = new Cache(); if ($cache->exists($cache->key('latest', array()))) { $cache->delete($cache->key('latest', array())); } pieLog("alter"); pieNotice("ImportSuccess", array('total' => $total, 'count' => $count)); pieTail();
/** * Grab a list of profile who have favored this notice. * * @return ArrayWrapper masquerading as a Fave */ static function byNotice($noticeId) { $c = self::memcache(); $key = Cache::key('fave:by_notice:' . $noticeId); $wrapper = $c->get($key); if (!$wrapper) { // @fixme caching & scalability! $fave = new Fave(); $fave->notice_id = $noticeId; $fave->find(); $list = array(); while ($fave->fetch()) { $list[] = clone $fave; } $wrapper = new ArrayWrapper($list); $c->set($key, $wrapper); } return $wrapper; }
/** * etag for file * * This returns the same data (inode, size, mtime) as Apache would, * but in decimal instead of hex. * * @return string etag http header */ function etag() { if (common_config('site', 'use_x_sendfile')) { return null; } $cache = Cache::instance(); if ($cache) { $key = Cache::key('attachments:etag:' . $this->path); $etag = $cache->get($key); if ($etag === false) { $etag = crc32(file_get_contents($this->path)); $cache->set($key, $etag); } return $etag; } $stat = stat($this->path); return '"' . $stat['ino'] . '-' . $stat['size'] . '-' . $stat['mtime'] . '"'; }
define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); $shortoptions = "t:l:v:k:"; $helptext = <<<ENDOFHELP USAGE: showcache.php <args> shows the cached object based on the args -t table Table to look up -l column Column to look up, default "id" -v value Value to look up -k key Key to look up; other args are ignored ENDOFHELP; require_once INSTALLDIR . '/scripts/commandline.inc'; $karg = get_option_value('k'); if (!empty($karg)) { $k = Cache::key($karg); } else { $table = get_option_value('t'); if (empty($table)) { die("No table or key specified\n"); } $column = get_option_value('l'); if (empty($column)) { $column = 'id'; } $value = get_option_value('v'); $k = Memcached_DataObject::cacheKey($table, $column, $value); } print "Checking key '{$k}'...\n"; $c = Cache::instance(); if (empty($c)) {
function _blowSettingsCache() { $c = self::memcache(); if (!empty($c)) { $c->delete(Cache::key(self::settingsKey)); } }
$cid = $cache->key('page', array('page' => $_REQUEST['page'])); if (!($f = fopen($cache->file($cid), 'w'))) { pieError("CacheWriteError"); } if (!fwrite($f, $compiler->output)) { pieError("CacheWriteError"); } fclose($f); } // Clean up. if (file_exists($preview)) { unlink($preview); } if ($GLOBALS['pie']['edit_timeout']) { pieExpireDirectory($GLOBALS['pie']['run_path'] . "/temp", $GLOBALS['pie']['edit_timeout']); } $page->unlock($GLOBALS['pie']['user']); // Purge list of latest changes. if ($GLOBALS['pie']['query_caching']) { $cache = new Cache(); $cache->delete($cache->key('latest', array())); } // Print output. pieLog("edit"); pieNotice("PageUpdated"); if ($GLOBALS['pie']['context'] == 'edit') { print "<div class=\"output\">\n" . $compiler->output . "</div>\n"; } else { print "<hr />\n<br />\n" . $compiler->output; } pieTail();
function repeatStream($limit = 100) { $cache = Cache::instance(); if (empty($cache)) { $ids = $this->_repeatStreamDirect($limit); } else { $idstr = $cache->get(Cache::key('notice:repeats:' . $this->id)); if ($idstr !== false) { if (empty($idstr)) { $ids = array(); } else { $ids = explode(',', $idstr); } } else { $ids = $this->_repeatStreamDirect(100); $cache->set(Cache::key('notice:repeats:' . $this->id), implode(',', $ids)); } if ($limit < 100) { // We do a max of 100, so slice down to limit $ids = array_slice($ids, 0, $limit); } } return NoticeStream::getStreamByIds($ids); }
pieRequireUser(); } else { pieRequireSuperuser(); } pieHead(); if (@$_REQUEST['page']) { // Purge the cache of a single page. $_REQUEST['page'] = pieGetOption($_REQUEST['page']); $_REQUEST['page'] = pieBeautifyName($_REQUEST['page']); if (!$page->isValidName($_REQUEST['page'])) { pieError('PageNameInvalid'); } if (!$page->exists($_REQUEST['page'])) { pieError('PageNotFound'); } $cid = $cache->key('page', array('page' => $_REQUEST['page'])); if (!$cache->exists($cid)) { pieError('PurgeSuccess'); } if ($cache->delete($cid)) { pieNotice('PurgeSuccess'); } else { pieError('PurgeError'); } } else { // Purge the caches of all pages. if ($cache->expire('page', 0)) { pieNotice('ExpirationSuccess'); } else { pieError('ExpirationError'); }
function cacheKey($attrs) { $key = 'geonames:' . implode(',', array_keys($attrs)) . ':' . Cache::keyize(implode(',', array_values($attrs))); if ($this->cachePrefix) { return $this->cachePrefix . ':' . $key; } else { return Cache::key($key); } }
function blowNoticeCount() { $c = Cache::instance(); if (!empty($c)) { $c->delete(Cache::key('profile:notice_count:' . $this->id)); } }
function common_cache_key($extra) { return Cache::key($extra); }
// Determine image file type. $type = $file->meta['type']; $name = $file->fileName($file->name, 0); if (!file_exists($name)) { pieErrorImage(); } if ((list($ow, $oh) = getimagesize($name, $_REQUEST['stamp'])) === false) { pieErrorImage(); } if ($ow <= $max && $oh <= $max) { dumpFile($name, $type); } // Check the cache for the thumbnail image. if ($GLOBALS['pie']['image_caching']) { $cache = new Cache(); $cid = $cache->key('image', array('file' => $_REQUEST['file'])); $path = $cache->file($cid); } else { $path = $GLOBALS['pie']['run_path'] . '/temp/_thumbnail_' . sha1($_REQUEST['file']); } if (file_exists($path)) { touch($path); dumpFile($path, $type); } // Determine image geometry and aspect ratio: if (!function_exists('imagecreatetruecolor')) { dumpFile($name, $type); } if ($oh > $ow) { // Portrait format $ratio = $max / $oh;
/** * Removes an item from the cache */ public function delete($type, $id){ $cache = Cache::getLibrary(); if ($cache) { $cache->remove(Cache::key($type, $id)); } $loc = CacheLocal::get(); if ($loc->enabled && isset($loc->cache[Cache::key($type, $id)])) { unset($loc->cache[Cache::key($type, $id)]); } }
/** * Create a cache key for data dependent on code * * For cache elements that are dependent on changes in code, this creates * a more-or-less fingerprint of the current running code and adds it to * the cache key. In the case of an upgrade of core, or addition or * removal of plugins, a new unique fingerprint is generated and used. * * There can still be problems with a) differences in versions of the * plugins and b) people running code between official versions. This is * usually a problem only for experienced users like developers, who know * how to clear their cache. * * For sites that run code between versions (like the status.net cloud), * there's an additional build number configuration setting. * * @param string $extra the real part of the key * * @return string full key */ static function codeKey($extra) { static $prefix = null; if (empty($prefix)) { $names = array(); foreach (GNUsocial::getActivePlugins() as $plugin => $attrs) { $names[] = $plugin; } asort($names); // Unique enough. $uniq = crc32(implode(',', $names)); $build = common_config('site', 'build'); $prefix = GNUSOCIAL_VERSION . ':' . $build . ':' . $uniq; } return Cache::key($prefix . ':' . $extra); }