--- a/functions.php Fri Jun 12 11:57:08 2009 -0400
+++ b/functions.php Fri Jun 12 13:47:12 2009 -0400
@@ -140,33 +140,56 @@
$playlist_last_md5 = '';
-function rebuild_playlist()
+function rebuild_playlist($force = false, $from_ipc = false)
{
// import what we need
global $playlist, $amarok_home;
// sync and load the playlist file
- $playlist_file = dcop_action('playlist', 'saveCurrentPlaylist');
+ // if we're coming from IPC, don't call DCOP, just load the existing file
+ // this prevents the file from being generated 20 times and thus sometimes
+ // causing simplexml to read a half-written file
+ if ( !$from_ipc )
+ {
+ $playlist_file = dcop_action('playlist', 'saveCurrentPlaylist');
+ }
+ else
+ {
+ $playlist_file = $from_ipc;
+ }
// do we have amarok's home?
if ( !$amarok_home )
$amarok_home = dirname($playlist_file);
// check MD5 - if it's not changed, exit to save CPU cycles
global $playlist_last_md5;
$effective_md5 = md5_playlist_file($playlist_file);
- if ( $playlist_last_md5 == $effective_md5 )
+ if ( $playlist_last_md5 == $effective_md5 && !$force )
{
return true;
}
status('Rebuilding playlist cache');
$playlist_last_md5 = $effective_md5;
- // start XML parser
- try
+ $originalplaylist = $playlist_file;
+ $xml = false;
+ $unlinkplaylist = false;
+ while ( !$xml )
{
- $xml = simplexml_load_file($playlist_file);
+ // start XML parser
+ try
+ {
+ $xml = @simplexml_load_file($playlist_file);
+ if ( $xml )
+ break;
+
+ // if we can't load it, just wait - another process might have it loaded
+ warning('Could not load playlist file; maybe another Greyhound thread has it loaded? Waiting half a second.');
+ usleep(500000);
+ }
+ catch ( Exception $e )
+ {
+ burnout("Caught exception trying to load playlist file:\n$e");
+ }
}
- catch ( Exception $e )
- {
- burnout("Caught exception trying to load playlist file:\n$e");
- }
+
$attribs = $xml->attributes();
if ( @$attribs['product'] != 'Amarok' )
{
@@ -186,11 +209,33 @@
);
$playlist[] = $item;
}
- // if we're a child process, signal the parent to update
- if ( defined('HTTPD_WS_CHILD') )
+ if ( $unlinkplaylist )
+ {
+ unlink($playlist_file);
+ }
+ // tell all other worker threads to reload the playlist as well
+ global $httpd;
+ if ( is_object($httpd) && !$from_ipc )
{
- global $httpd;
- posix_kill($httpd->parent_pid, SIGHUP);
+ $httpd->threader->ipc_send(array(
+ 'action' => 'reloadplaylist',
+ 'propagate' => true,
+ 'playlist_file' => $playlist_file
+ ));
+ }
+}
+
+function rebuild_playlist_ipc($command, $threader)
+{
+ status('IPC playlist rebuild received');
+ if ( isset($command['playlist']) )
+ {
+ status('IPC playlist rebuild: using playlist sent in IPC packet; length: ' . strlen($command['playlist']));
+ $GLOBALS['playlist'] = $command['playlist'];
+ }
+ else
+ {
+ rebuild_playlist(true, $command['playlist_file']);
}
}