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 /* ***** BEGIN LICENSE BLOCK *****
196 * Version: MPL 1.1/GPL 2.0/LGPL 2.1/Apache 2.0
198 * The contents of this file are subject to the Mozilla Public License Version
199 * 1.1 (the "License"); you may not use this file except in compliance with
200 * the License. You may obtain a copy of the License at
201 * http://www.mozilla.org/MPL/
203 * Software distributed under the License is distributed on an "AS IS" basis,
204 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
205 * for the specific language governing rights and limitations under the
208 * The Original Code is LoomClient PHP library
210 * The Initial Developer of the Original Code is
212 * Portions created by the Initial Developer are Copyright (C) 2008
213 * the Initial Developer. All Rights Reserved.
216 * Bill St. Clair <bill@billstclair.com>
218 * Alternatively, the contents of this file may be used under the
219 * terms of the GNU General Public License Version 2 or later (the
220 * "GPL"), the GNU Lesser General Public License Version 2.1 or later
221 * (the "LGPL"), or The Apache License Version 2.0 (the "AL"), in
222 * which case the provisions of the GPL, LGPL, or AL are applicable
223 * instead of those above. If you wish to allow use of your version of
224 * this file only under the terms of the GPL, the LGPL, or the AL, and
225 * not to allow others to use your version of this file under the
226 * terms of the MPL, indicate your decision by deleting the provisions
227 * above and replace them with the notice and other provisions
228 * required by the GPL or the LGPL. If you do not delete the
229 * provisions above, a recipient may use your version of this file
230 * under the terms of any one of the MPL, the GPL the LGPL, or the AL.
231 ****** END LICENSE BLOCK ***** */