PluginProbe
WP Database Backup – Unlimited Database & Files Backup by Backup for WP / 6.11
WP Database Backup – Unlimited Database & Files Backup by Backup for WP v6.11
7.13 7.12 trunk 1.1 2.1.1 5.9 6.0 6.1 6.10 6.11 6.12 6.12.1 6.2 6.3 6.4 6.5 6.5.1 6.6 6.7 6.8 6.9 7.0 7.0.1 7.1 7.10 All 34 releases
wp-database-backup / includes / admin / Destination / Google / google-api-php-client / src / cache / Google_FileCache.php

Google_FileCache.php in WP Database Backup – Unlimited Database & Files Backup by Backup for WP 6.11, at includes/admin/Destination/Google/google-api-php-client/src/cache/Google_FileCache.php

138 lines 4.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 * Copyright 2008 Google Inc.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 /*
19 * This class implements a basic on disk storage. While that does
20 * work quite well it's not the most elegant and scalable solution.
21 * It will also get you into a heap of trouble when you try to run
22 * this in a clustered environment. In those cases please use the
23 * MySql back-end
24 *
25 * @author Chris Chabot <chabotc@google.com>
26 */
27 class Google_FileCache extends Google_Cache {
28 private $path;
29
30 public function __construct() {
31 global $apiConfig;
32 $this->path = $apiConfig['ioFileCache_directory'];
33 }
34
35 private function isLocked($storageFile) {
36 // our lock file convention is simple: /the/file/path.lock
37 return file_exists($storageFile . '.lock');
38 }
39
40 private function createLock($storageFile) {
41 $storageDir = dirname($storageFile);
42 if (! is_dir($storageDir)) {
43 // @codeCoverageIgnoreStart
44 if (! @mkdir($storageDir, 0755, true)) {
45 // make sure the failure isn't because of a concurrency issue
46 if (! is_dir($storageDir)) {
47 throw new Google_CacheException("Could not create storage directory: $storageDir");
48 }
49 }
50 // @codeCoverageIgnoreEnd
51 }
52 @touch($storageFile . '.lock');
53 }
54
55 private function removeLock($storageFile) {
56 // suppress all warnings, if some other process removed it that's ok too
57 @unlink($storageFile . '.lock');
58 }
59
60 private function waitForLock($storageFile) {
61 // 20 x 250 = 5 seconds
62 $tries = 20;
63 $cnt = 0;
64 do {
65 // make sure PHP picks up on file changes. This is an expensive action but really can't be avoided
66 clearstatcache();
67 // 250 ms is a long time to sleep, but it does stop the server from burning all resources on polling locks..
68 usleep(250);
69 $cnt ++;
70 } while ($cnt <= $tries && $this->isLocked($storageFile));
71 if ($this->isLocked($storageFile)) {
72 // 5 seconds passed, assume the owning process died off and remove it
73 $this->removeLock($storageFile);
74 }
75 }
76
77 private function getCacheDir($hash) {
78 // use the first 2 characters of the hash as a directory prefix
79 // this should prevent slowdowns due to huge directory listings
80 // and thus give some basic amount of scalability
81 return $this->path . '/' . substr($hash, 0, 2);
82 }
83
84 private function getCacheFile($hash) {
85 return $this->getCacheDir($hash) . '/' . $hash;
86 }
87
88 public function get($key, $expiration = false) {
89 $storageFile = $this->getCacheFile(md5($key));
90 // See if this storage file is locked, if so we wait up to 5 seconds for the lock owning process to
91 // complete it's work. If the lock is not released within that time frame, it's cleaned up.
92 // This should give us a fair amount of 'Cache Stampeding' protection
93 if ($this->isLocked($storageFile)) {
94 $this->waitForLock($storageFile);
95 }
96 if (file_exists($storageFile) && is_readable($storageFile)) {
97 $now = time();
98 if (! $expiration || (($mtime = @filemtime($storageFile)) !== false && ($now - $mtime) < $expiration)) {
99 if (($data = @file_get_contents($storageFile)) !== false) {
100 $data = unserialize($data);
101 return $data;
102 }
103 }
104 }
105 return false;
106 }
107
108 public function set($key, $value) {
109 $storageDir = $this->getCacheDir(md5($key));
110 $storageFile = $this->getCacheFile(md5($key));
111 if ($this->isLocked($storageFile)) {
112 // some other process is writing to this file too, wait until it's done to prevent hiccups
113 $this->waitForLock($storageFile);
114 }
115 if (! is_dir($storageDir)) {
116 if (! @mkdir($storageDir, 0755, true)) {
117 throw new Google_CacheException("Could not create storage directory: $storageDir");
118 }
119 }
120 // we serialize the whole request object, since we don't only want the
121 // responseContent but also the postBody used, headers, size, etc
122 $data = serialize($value);
123 $this->createLock($storageFile);
124 if (! @file_put_contents($storageFile, $data)) {
125 $this->removeLock($storageFile);
126 throw new Google_CacheException("Could not store data in the file");
127 }
128 $this->removeLock($storageFile);
129 }
130
131 public function delete($key) {
132 $file = $this->getCacheFile(md5($key));
133 if (! @unlink($file)) {
134 throw new Google_CacheException("Cache file could not be deleted");
135 }
136 }
137 }
138