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