3 // GDBM class with live compression
7 var $oldfile; // The name of the "Old" file
8 var $newfile; // The name of the "New" file
9 var $oldr; // Resource pointer for $oldfile
10 var $newr; // Resource pointer for $newfile
11 var $copycount; // Number of keys to copy per access
12 var $error; // error string for last operation
14 function GDBM($oldfile, $newfile, $copycount=20, $handler="gdbm") {
15 $this->oldfile
= $oldfile;
16 $this->newfile
= $newfile;
17 $this->copycount
= $copycount;
18 $this->handler
= $handler;
20 $oldr = dba_open($oldfile, 'cl', $handler);
23 $this->error
= "Could not open old database";
30 $this->newfile
= false;
33 if (file_exists($newfile)) {
34 $this->newr
= dba_open($newfile, 'wl', $handler);
35 } else $this->newr
= false;
39 // Get the value for a key.
40 // If it's in the new database, return that value.
41 // If the deleted key is in the new database, return false.
42 // Otherwise, return the value in the old databae.
46 $this->copysome(true);
47 if ($this->newr
) $value = dba_fetch($key, $this->newr
);
49 if (!$value) $value = dba_fetch($key, $this->oldr
);
53 // Replace or set the value of $key to $value.
54 // If $value is blank or false, delete $key from the database
55 // Return the new value
56 function put($key, $value) {
57 if ($value == '' ||
!$value) {
58 // Blank or false value = delete the key
59 dba_delete($key, $this->oldr
);
61 dba_delete($key, $this->newr
);
62 $this->copysome(true);
66 dba_replace($key, $value, $this->newr
);
67 dba_delete($key, $this->oldr
);
68 $this->copysome(true);
70 dba_replace($key, $value, $this->oldr
);
76 // Create a new database, if there isn't one, and start copying to it
77 function startCopying() {
78 if (!$this->newr
&& $this->newfile
) {
79 $this->newr
= dba_open($this->newfile
, 'cl', $this->handler
);
84 // True if we're currently copying old to new
85 function isCopying() {
89 // Finish copying old to new, delete old, rename new to old, and reopen
90 // Do NOT start copying again.
91 function finishCopying() {
92 while ($this->newr
) $this->copysome(false);
95 // Close the database(s). Finish copying first if $finish_copying is true
96 function close($finish_copying=false) {
97 if ($finish_copying) $this->finishCopying();
99 dba_close($this->oldr
);
103 dba_close($this->newr
);
108 // Reopen the database after a close.
109 // Does nothing if alredy open
112 $this->oldr
= dba_open($this->oldfile
, 'wl', $this->handler
);
113 if (!$this->oldr
) $this->error
= "Could not reopen old file";
118 // Return the message for the last error that happened, and clear it
119 function errorMessage() {
125 // Copy $this->copycount keys from old to new database
126 function copysome($reopen) {
128 for ($i=0; $i<$this->copycount
; $i++
) {
129 $key = dba_firstkey($this->oldr
);
130 if ($key) $this->copyone($key);
132 // We're done copying.
133 $this->flipDBs($reopen);
140 // Copy one key from old to new database
141 function copyone($key) {
143 if (!dba_fetch($key, $this->newr
)) {
144 $value = dba_fetch($key, $this->oldr
);
145 if ($value) dba_replace($key, $value, $this->newr
);
147 dba_delete($key, $this->oldr
);
151 // Delete the old database, and rename new to old
152 function flipDBs($reopen) {
154 $oldsize = filesize($this->oldfile
);
155 $newsize = filesize($this->newfile
);
156 $this->error
= "old size: $oldsize, new size: $newsize";
157 if (unlink($this->oldfile
)) {
158 if (rename($this->newfile
, $this->oldfile
)) {
159 if ($reopen) $this->reopen();
160 } else $this->error
= "Could not rename new file to old file";
161 } else $this->error
= "Could not unlink old file";
166 // Test code. Uncomment to run.
168 if (file_exists('old.db')) unlink('old.db');
169 if (file_exists('new.db')) unlink('new.db');
170 $db = new GDBM('old.db', 'new.db', 1);
173 for ($i=1; $i<=$cnt; $i++) {
177 for ($j=0; $j<$loops; $j++) {
178 for ($i=1; $i<=$cnt; $i++) {
179 if (($j % 2) == 1 && ($i % 10) == 3) $db->put($i, '');
180 else $db->put($i, 10 * $db->get($i));
181 if (!$db->isCopying()) {
182 echo "Restarting copying, j=$j, i=$i\n";
183 echo " " . $db->errorMessage() . "\n";
188 for ($i=1; $i<=$cnt; $i++) {
189 echo "$i: " . $db->get($i) . "\n";
190 if (!$db->isCopying()) $db->startCopying();
195 // Copyright 2008 Bill St. Clair
197 // Licensed under the Apache License, Version 2.0 (the "License");
198 // you may not use this file except in compliance with the License.
199 // You may obtain a copy of the License at
201 // http://www.apache.org/licenses/LICENSE-2.0
203 // Unless required by applicable law or agreed to in writing, software
204 // distributed under the License is distributed on an "AS IS" BASIS,
205 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
206 // See the License for the specific language governing permissions
207 // and limitations under the License.