Skip to content

Commit 9f83bdd

Browse files
Merge pull request #466 from sabinich/master
Tiny refactoring for extension.cache.dbm.php based on some errors into logfile
2 parents 4d633c6 + 966910a commit 9f83bdd

File tree

1 file changed

+196
-179
lines changed

1 file changed

+196
-179
lines changed

getid3/extension.cache.dbm.php

Lines changed: 196 additions & 179 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
* getID3_cached usage:
3434
*
3535
* require_once 'getid3/getid3.php';
36-
* require_once 'getid3/getid3/extension.cache.dbm.php';
36+
* require_once 'getid3/extension.cache.dbm.php';
3737
* $getID3 = new getID3_cached('db3', '/tmp/getid3_cache.dbm',
3838
* '/tmp/getid3_cache.lock');
3939
* $getID3->encoding = 'UTF-8';
@@ -72,182 +72,199 @@
7272

7373
class getID3_cached_dbm extends getID3
7474
{
75-
/**
76-
* @var resource
77-
*/
78-
private $dba;
79-
80-
/**
81-
* @var resource|bool
82-
*/
83-
private $lock;
84-
85-
/**
86-
* @var string
87-
*/
88-
private $cache_type;
89-
90-
/**
91-
* @var string
92-
*/
93-
private $dbm_filename;
94-
95-
/**
96-
* constructor - see top of this file for cache type and cache_options
97-
*
98-
* @param string $cache_type
99-
* @param string $dbm_filename
100-
* @param string $lock_filename
101-
*
102-
* @throws Exception
103-
* @throws getid3_exception
104-
*/
105-
public function __construct($cache_type, $dbm_filename, $lock_filename) {
106-
107-
// Check for dba extension
108-
if (!extension_loaded('dba')) {
109-
throw new Exception('PHP is not compiled with dba support, required to use DBM style cache.');
110-
}
111-
112-
// Check for specific dba driver
113-
if (!function_exists('dba_handlers') || !in_array($cache_type, dba_handlers())) {
114-
throw new Exception('PHP is not compiled --with '.$cache_type.' support, required to use DBM style cache.');
115-
}
116-
117-
// Create lock file if needed
118-
if (!file_exists($lock_filename)) {
119-
if (!touch($lock_filename)) {
120-
throw new Exception('failed to create lock file: '.$lock_filename);
121-
}
122-
}
123-
124-
// Open lock file for writing
125-
if (!is_writeable($lock_filename)) {
126-
throw new Exception('lock file: '.$lock_filename.' is not writable');
127-
}
128-
$this->lock = fopen($lock_filename, 'w');
129-
130-
// Acquire exclusive write lock to lock file
131-
flock($this->lock, LOCK_EX);
132-
133-
// Create dbm-file if needed
134-
if (!file_exists($dbm_filename)) {
135-
if (!touch($dbm_filename)) {
136-
throw new Exception('failed to create dbm file: '.$dbm_filename);
137-
}
138-
}
139-
140-
// Try to open dbm file for writing
141-
$this->dba = dba_open($dbm_filename, 'w', $cache_type);
142-
if (!$this->dba) {
143-
144-
// Failed - create new dbm file
145-
$this->dba = dba_open($dbm_filename, 'n', $cache_type);
146-
147-
if (!$this->dba) {
148-
throw new Exception('failed to create dbm file: '.$dbm_filename);
149-
}
150-
151-
// Insert getID3 version number
152-
dba_insert(getID3::VERSION, getID3::VERSION, $this->dba);
153-
}
154-
155-
// Init misc values
156-
$this->cache_type = $cache_type;
157-
$this->dbm_filename = $dbm_filename;
158-
159-
// Register destructor
160-
register_shutdown_function(array($this, '__destruct'));
161-
162-
// Check version number and clear cache if changed
163-
if (dba_fetch(getID3::VERSION, $this->dba) != getID3::VERSION) {
164-
$this->clear_cache();
165-
}
166-
167-
parent::__construct();
168-
}
169-
170-
171-
172-
/**
173-
* destructor
174-
*/
175-
public function __destruct() {
176-
177-
// Close dbm file
178-
dba_close($this->dba);
179-
180-
// Release exclusive lock
181-
flock($this->lock, LOCK_UN);
182-
183-
// Close lock file
184-
fclose($this->lock);
185-
}
186-
187-
188-
189-
/**
190-
* clear cache
191-
*
192-
* @throws Exception
193-
*/
194-
public function clear_cache() {
195-
196-
// Close dbm file
197-
dba_close($this->dba);
198-
199-
// Create new dbm file
200-
$this->dba = dba_open($this->dbm_filename, 'n', $this->cache_type);
201-
202-
if (!$this->dba) {
203-
throw new Exception('failed to clear cache/recreate dbm file: '.$this->dbm_filename);
204-
}
205-
206-
// Insert getID3 version number
207-
dba_insert(getID3::VERSION, getID3::VERSION, $this->dba);
208-
209-
// Re-register shutdown function
210-
register_shutdown_function(array($this, '__destruct'));
211-
}
212-
213-
214-
215-
/**
216-
* clear cache
217-
*
218-
* @param string $filename
219-
* @param int $filesize
220-
* @param string $original_filename
221-
* @param resource $fp
222-
*
223-
* @return mixed
224-
*/
225-
public function analyze($filename, $filesize=null, $original_filename='', $fp=null) {
226-
227-
$key = null;
228-
if (file_exists($filename)) {
229-
230-
// Calc key filename::mod_time::size - should be unique
231-
$key = $filename.'::'.filemtime($filename).'::'.filesize($filename);
232-
233-
// Loopup key
234-
$result = dba_fetch($key, $this->dba);
235-
236-
// Hit
237-
if ($result !== false) {
238-
return unserialize($result);
239-
}
240-
}
241-
242-
// Miss
243-
$result = parent::analyze($filename, $filesize, $original_filename, $fp);
244-
245-
// Save result
246-
if ($key !== null) {
247-
dba_insert($key, serialize($result), $this->dba);
248-
}
249-
250-
return $result;
251-
}
252-
75+
/**
76+
* @var resource
77+
*/
78+
private $dba;
79+
80+
/**
81+
* @var resource|bool
82+
*/
83+
private $lock;
84+
85+
/**
86+
* @var string
87+
*/
88+
private $cache_type;
89+
90+
/**
91+
* @var string
92+
*/
93+
private $dbm_filename;
94+
95+
/**
96+
* @var string
97+
*/
98+
private $lock_filename;
99+
100+
/**
101+
* constructor - see top of this file for cache type and cache_options
102+
*
103+
* @param string $cache_type
104+
* @param string $dbm_filename
105+
* @param string $lock_filename
106+
*
107+
* @throws Exception
108+
* @throws getid3_exception
109+
*/
110+
public function __construct($cache_type, $dbm_filename, $lock_filename) {
111+
112+
// Check for dba extension
113+
if (!extension_loaded('dba')) {
114+
throw new Exception('PHP is not compiled with dba support, required to use DBM style cache.');
115+
}
116+
117+
// Check for specific dba driver
118+
if (!function_exists('dba_handlers') || !in_array($cache_type, dba_handlers())) {
119+
throw new Exception('PHP is not compiled --with '.$cache_type.' support, required to use DBM style cache.');
120+
}
121+
122+
// Store lock filename for cleanup operations
123+
$this->lock_filename = $lock_filename;
124+
125+
// Create lock file if needed
126+
if (!file_exists($this->lock_filename)) {
127+
if (!touch($this->lock_filename)) {
128+
throw new Exception('failed to create lock file: '.$this->lock_filename);
129+
}
130+
}
131+
132+
// Open lock file for writing with read/write mode (w+) to prevent truncation on BSD systems
133+
$this->lock = fopen($this->lock_filename, 'w+');
134+
if (!$this->lock) {
135+
throw new Exception('Cannot open lock file: '.$this->lock_filename);
136+
}
137+
138+
// Acquire exclusive write lock to lock file
139+
if (!flock($this->lock, LOCK_EX)) {
140+
fclose($this->lock);
141+
throw new Exception('Cannot acquire lock: '.$this->lock_filename);
142+
}
143+
144+
// Store connection parameters
145+
$this->cache_type = $cache_type;
146+
$this->dbm_filename = $dbm_filename;
147+
148+
try {
149+
// Try to open existing DBM file
150+
$this->dba = dba_open($this->dbm_filename, 'w', $this->cache_type);
151+
152+
// Create new DBM file if it didn't exist
153+
if (!$this->dba) {
154+
$this->dba = dba_open($this->dbm_filename, 'n', $this->cache_type);
155+
if (!$this->dba) {
156+
throw new Exception('failed to create dbm file: '.$this->dbm_filename);
157+
}
158+
159+
// Insert getID3 version number
160+
dba_insert(getID3::VERSION, getID3::VERSION, $this->dba);
161+
}
162+
163+
// Check version number and clear cache if changed
164+
if (dba_fetch(getID3::VERSION, $this->dba) != getID3::VERSION) {
165+
$this->clear_cache();
166+
}
167+
168+
} catch (Exception $e) {
169+
$this->safe_close();
170+
throw $e;
171+
}
172+
173+
// Register destructor
174+
register_shutdown_function(array($this, '__destruct'));
175+
176+
parent::__construct();
177+
}
178+
179+
/**
180+
* Destructor - ensure proper cleanup of resources
181+
*/
182+
public function __destruct() {
183+
$this->safe_close();
184+
}
185+
186+
/**
187+
* Safely close all resources with error handling
188+
*/
189+
private function safe_close() {
190+
try {
191+
// Close DBM connection if open
192+
if (is_resource($this->dba)) {
193+
dba_close($this->dba);
194+
$this->dba = null;
195+
}
196+
197+
// Release lock if acquired
198+
if (is_resource($this->lock)) {
199+
flock($this->lock, LOCK_UN);
200+
fclose($this->lock);
201+
$this->lock = null;
202+
}
203+
} catch (Exception $e) {
204+
error_log('getID3_cached_dbm cleanup error: ' . $e->getMessage());
205+
}
206+
}
207+
208+
/**
209+
* Clear cache and recreate DBM file
210+
*
211+
* @throws Exception
212+
*/
213+
public function clear_cache() {
214+
$this->safe_close();
215+
216+
// Create new dbm file
217+
$this->dba = dba_open($this->dbm_filename, 'n', $this->cache_type);
218+
if (!$this->dba) {
219+
throw new Exception('failed to clear cache/recreate dbm file: '.$this->dbm_filename);
220+
}
221+
222+
// Insert getID3 version number
223+
dba_insert(getID3::VERSION, getID3::VERSION, $this->dba);
224+
225+
// Re-register shutdown function
226+
register_shutdown_function(array($this, '__destruct'));
227+
}
228+
229+
/**
230+
* Analyze file and cache results
231+
*
232+
* @param string $filename
233+
* @param int $filesize
234+
* @param string $original_filename
235+
* @param resource $fp
236+
*
237+
* @return mixed
238+
*/
239+
public function analyze($filename, $filesize=null, $original_filename='', $fp=null) {
240+
try {
241+
$key = null;
242+
if (file_exists($filename)) {
243+
// Calc key: filename::mod_time::size - should be unique
244+
$key = $filename.'::'.filemtime($filename).'::'.filesize($filename);
245+
246+
// Lookup key in cache
247+
$result = dba_fetch($key, $this->dba);
248+
249+
// Cache hit
250+
if ($result !== false) {
251+
return unserialize($result);
252+
}
253+
}
254+
255+
// Cache miss - perform actual analysis
256+
$result = parent::analyze($filename, $filesize, $original_filename, $fp);
257+
258+
// Store result in cache if key was generated
259+
if ($key !== null) {
260+
dba_replace($key, serialize($result), $this->dba);
261+
}
262+
263+
return $result;
264+
265+
} catch (Exception $e) {
266+
$this->safe_close();
267+
throw $e;
268+
}
269+
}
253270
}

0 commit comments

Comments
 (0)