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