]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/DbaDatabase.php
Allow bold, italics or underlined for numbers
[SourceForge/phpwiki.git] / lib / DbaDatabase.php
1 <?php
2
3 require_once 'lib/ErrorManager.php';
4
5 if (isWindows())
6     define('DBA_DATABASE_DEFAULT_TIMEOUT', 60);
7 else
8     define('DBA_DATABASE_DEFAULT_TIMEOUT', 5);
9
10 class DbaDatabase
11 {
12     function DbaDatabase($filename, $mode = false, $handler = 'gdbm')
13     {
14         $this->_file = $filename;
15         $this->_handler = $handler;
16         $this->_timeout = DBA_DATABASE_DEFAULT_TIMEOUT;
17         $this->_dbh = false;
18         if (!in_array($handler, dba_handlers()))
19             $this->_error(
20                 sprintf(
21                     _("The DBA handler %s is unsupported!") . "\n" .
22                         _("Supported handlers are: %s"),
23                     $handler, join(",", dba_handlers())));
24         $this->readonly = false;
25         if ($mode)
26             $this->open($mode);
27     }
28
29     function set_timeout($timeout)
30     {
31         $this->_timeout = $timeout;
32     }
33
34     function open($mode = 'w')
35     {
36         if ($this->_dbh)
37             return; // already open.
38
39         $watchdog = $this->_timeout;
40
41         global $ErrorManager;
42         $this->_dba_open_error = false;
43         $ErrorManager->pushErrorHandler(new WikiMethodCb($this, '_dba_open_error_handler'));
44
45         // oops, you don't have DBA support.
46         if (!function_exists("dba_open")) {
47             echo "You don't seem to have DBA support compiled into PHP.";
48         }
49
50         if (READONLY) {
51             $mode = 'r';
52         }
53
54         if ((strlen($mode) == 1)) {
55             // PHP 4.3.x Windows lock bug workaround: http://bugs.php.net/bug.php?id=23975
56             if (isWindows()) {
57                 $mode .= "-"; // suppress locking, or
58             } elseif ($this->_handler != 'gdbm') { // gdbm does it internally
59                 $mode .= "d"; // else use internal locking
60             }
61         }
62         while (($dbh = dba_open($this->_file, $mode, $this->_handler)) < 1) {
63             if ($watchdog <= 0)
64                 break;
65             // "c" failed, try "w" instead.
66             if ($mode == "w"
67                 and file_exists($this->_file)
68                     and (isWindows() or !is_writable($this->_file))
69             ) {
70                 // try to continue with read-only
71                 if (!defined("READONLY"))
72                     define("READONLY", true);
73                 $GLOBALS['request']->_dbi->readonly = true;
74                 $this->readonly = true;
75                 $mode = "r";
76             }
77             if (substr($mode, 0, 1) == "c" and file_exists($this->_file) and !READONLY)
78                 $mode = "w";
79             // conflict: wait some random time to unlock (as with ethernet)
80             $secs = 0.5 + ((double)rand(1, 32767) / 32767);
81             sleep($secs);
82             $watchdog -= $secs;
83             if (strlen($mode) == 2) $mode = substr($mode, 0, -1);
84         }
85         $ErrorManager->popErrorHandler();
86
87         if (!$dbh) {
88             if (($error = $this->_dba_open_error)) {
89                 $error->errno = E_USER_ERROR;
90                 $error->errstr .= "\nfile: " . $this->_file
91                     . "\nmode: " . $mode
92                     . "\nhandler: " . $this->_handler;
93                 // try to continue with read-only
94                 if (!defined("READONLY"))
95                     define("READONLY", true);
96                 $GLOBALS['request']->_dbi->readonly = true;
97                 $this->readonly = true;
98                 if (!file_exists($this->_file)) {
99                     $ErrorManager->handleError($error);
100                     flush();
101                 }
102             } else {
103                 trigger_error("dba_open failed", E_USER_ERROR);
104             }
105         }
106         $this->_dbh = $dbh;
107         return !empty($dbh);
108     }
109
110     function close()
111     {
112         if ($this->_dbh)
113             dba_close($this->_dbh);
114         $this->_dbh = false;
115     }
116
117     function exists($key)
118     {
119         return dba_exists($key, $this->_dbh);
120     }
121
122     function fetch($key)
123     {
124         $val = dba_fetch($key, $this->_dbh);
125         if ($val === false)
126             return $this->_error("fetch($key)");
127         return $val;
128     }
129
130     function insert($key, $val)
131     {
132         if (!dba_insert($key, $val, $this->_dbh))
133             return $this->_error("insert($key)");
134     }
135
136     function replace($key, $val)
137     {
138         if (!dba_replace($key, $val, $this->_dbh))
139             return $this->_error("replace($key)");
140     }
141
142     function firstkey()
143     {
144         return dba_firstkey($this->_dbh);
145     }
146
147     function nextkey()
148     {
149         return dba_nextkey($this->_dbh);
150     }
151
152     function delete($key)
153     {
154         if ($this->readonly) return;
155         if (!dba_delete($key, $this->_dbh))
156             return $this->_error("delete($key)");
157     }
158
159     function get($key)
160     {
161         return dba_fetch($key, $this->_dbh);
162     }
163
164     function set($key, $val)
165     {
166         $dbh = &$this->_dbh;
167         if ($this->readonly) return;
168         if (dba_exists($key, $dbh)) {
169             if ($val !== false) {
170                 if (!dba_replace($key, $val, $dbh))
171                     return $this->_error("store[replace]($key)");
172             } else {
173                 if (!dba_delete($key, $dbh))
174                     return $this->_error("store[delete]($key)");
175             }
176         } else {
177             if (!dba_insert($key, $val, $dbh))
178                 return $this->_error("store[insert]($key)");
179         }
180     }
181
182     function sync()
183     {
184         if (!dba_sync($this->_dbh))
185             return $this->_error("sync()");
186     }
187
188     function optimize()
189     {
190         if (!dba_optimize($this->_dbh))
191             return $this->_error("optimize()");
192         return 1;
193     }
194
195     function _error($mes)
196     {
197         //trigger_error("DbaDatabase: $mes", E_USER_WARNING);
198         //return false;
199         trigger_error("$this->_file: dba error: $mes", E_USER_ERROR);
200     }
201
202     function _dump()
203     {
204         $dbh = &$this->_dbh;
205         for ($key = $this->firstkey($dbh); $key; $key = $this->nextkey($dbh))
206             printf("%10s: %s\n", $key, $this->fetch($key));
207     }
208
209     function _dba_open_error_handler($error)
210     {
211         $this->_dba_open_error = $error;
212         return true;
213     }
214 }
215
216 // Local Variables:
217 // mode: php
218 // tab-width: 8
219 // c-basic-offset: 4
220 // c-hanging-comment-ender-p: nil
221 // indent-tabs-mode: nil
222 // End: