]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/DbaDatabase.php
increase windows dba timeout
[SourceForge/phpwiki.git] / lib / DbaDatabase.php
1 <?php // rcs_id('$Id$');
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 (function_exists("dba_handlers")) { // since php-4.3.0
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         }
25         $this->readonly = false;
26         if ($mode)
27             $this->open($mode);
28     }
29
30     function set_timeout($timeout) {
31         $this->_timeout = $timeout;
32     }
33     
34     function open($mode = 'w') {
35         if ($this->_dbh)
36             return;             // already open.
37         
38         $watchdog = $this->_timeout;
39
40         global $ErrorManager;
41         $this->_dba_open_error = false;
42         $ErrorManager->pushErrorHandler(new WikiMethodCb($this, '_dba_open_error_handler'));
43
44         // oops, you don't have DBA support.
45         if (!function_exists("dba_open")) {
46             echo "You don't seem to have DBA support compiled into PHP.";
47         }
48         
49         if (READONLY) {
50             $mode = 'r';
51         }
52
53         // lock supported since 4.3.0:
54         if (check_php_version(4,3,0) and (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             }
103             else {
104                 trigger_error("dba_open failed", E_USER_ERROR);
105             }
106         }
107         $this->_dbh = $dbh;
108         return !empty($dbh);
109     }
110
111     function close() {
112         if ($this->_dbh)
113             dba_close($this->_dbh);
114         $this->_dbh = false;
115     }
116
117     function exists($key) {
118         return dba_exists($key, $this->_dbh);
119     }
120     
121     function fetch($key) {
122         $val = dba_fetch($key, $this->_dbh);
123         if ($val === false)
124             return $this->_error("fetch($key)");
125         return $val;
126     }
127
128     function insert($key, $val) {
129         if (!dba_insert($key, $val, $this->_dbh))
130             return $this->_error("insert($key)");
131     }
132
133     function replace($key, $val) {
134         if (!dba_replace($key, $val, $this->_dbh))
135             return $this->_error("replace($key)");
136     }
137
138     
139     function firstkey() {
140         return dba_firstkey($this->_dbh);
141     }
142
143     function nextkey() {
144         return dba_nextkey($this->_dbh);
145     }
146
147     function delete($key) {
148         if ($this->readonly) return;
149         if (!dba_delete($key, $this->_dbh))
150             return $this->_error("delete($key)");
151     }
152
153     function get($key) {
154         return dba_fetch($key, $this->_dbh);
155     }
156
157     function set($key, $val) {
158         $dbh = &$this->_dbh;
159         if ($this->readonly) return;
160         if (dba_exists($key, $dbh)) {
161             if ($val !== false) {
162                 if (!dba_replace($key, $val, $dbh))
163                     return $this->_error("store[replace]($key)");
164             }
165             else {
166                 if (!dba_delete($key, $dbh))
167                     return $this->_error("store[delete]($key)");
168             }
169         }
170         else {
171             if (!dba_insert($key, $val, $dbh))
172                 return $this->_error("store[insert]($key)");
173         }
174     }
175
176     function sync() {
177         if (!dba_sync($this->_dbh))
178             return $this->_error("sync()");
179     }
180
181     function optimize() {
182         if (!dba_optimize($this->_dbh))
183             return $this->_error("optimize()");
184         return 1;
185     }
186     
187     function _error($mes) {
188         //trigger_error("DbaDatabase: $mes", E_USER_WARNING);
189         //return false;
190         trigger_error("$this->_file: dba error: $mes", E_USER_ERROR);
191     }
192
193     function _dump() {
194         $dbh = &$this->_dbh;
195         for ($key = $this->firstkey($dbh); $key; $key = $this->nextkey($dbh))
196             printf("%10s: %s\n", $key, $this->fetch($key));
197     }
198
199     function _dba_open_error_handler($error) {
200         $this->_dba_open_error = $error;
201         return true;
202     }
203 }
204
205 // (c-file-style: "gnu")
206 // Local Variables:
207 // mode: php
208 // tab-width: 8
209 // c-basic-offset: 4
210 // c-hanging-comment-ender-p: nil
211 // indent-tabs-mode: nil
212 // End:   
213 ?>