]> git.parisson.com Git - deefuzzer.git/commitdiff
Move thread execution detection into create loop (as we can't restart dead threads)
authorachbed <github@achbed.org>
Sun, 11 Jan 2015 22:58:34 +0000 (16:58 -0600)
committerachbed <github@achbed.org>
Sun, 11 Jan 2015 22:58:34 +0000 (16:58 -0600)
Altered create loop to run all the time (instead of only at station creation)
Fixed issue where streams would not be closed if an error occurred in playlist advancement
Fixed issue where saved playlist position could result in an index overflow
Added maxretry value (determines how many times to attempt a station thread restart)
Fixed minor documentation things

Signed-off-by: achbed <github@achbed.org>
deefuzzer/core.py
deefuzzer/station.py
example/deefuzzer_doc.xml

index ad7097d9757e1a5e51e4126af67b05725ec9da02..60648a21b87f48b1b5faa382093e87b74e778505 100644 (file)
@@ -61,6 +61,7 @@ class DeeFuzzer(Thread):
     logqueue = Queue.Queue()
     mainLoop = False
     ignoreErrors = False
+    maxretry = 0
 
     def __init__(self, conf_file):
         Thread.__init__(self)
@@ -83,9 +84,13 @@ class DeeFuzzer(Thread):
                 self.m3u = str(self.conf['deefuzzer'][key])
 
             elif key == 'ignoreerrors':
-                # Load station definitions from the main config file
+                # Ignore errors and continue as long as possible
                 self.ignoreErrors = bool(self.conf['deefuzzer'][key])
 
+            elif key == 'maxretry':
+                # Maximum number of attempts to restart the stations on crash.
+                self.maxretry = bool(self.conf['deefuzzer'][key])
+
             elif key == 'station':
                 # Load station definitions from the main config file
                 if not isinstance(self.conf['deefuzzer'][key], list):
@@ -260,56 +265,75 @@ class DeeFuzzer(Thread):
             ns_new = len(self.station_settings)
             if(ns_new > ns):
                 self._info('Loading new stations')
-                for i in range(0, ns_new):
+            
+            for i in range(0, ns_new):
+                try:
+                    name = ''
+                    if 'station_name' in self.station_settings[i].keys():
+                        name = self.station_settings[i]['station_name']
+                    
+                    if not 'retries' in self.station_settings[i].keys():
+                        self.station_settings[i]['retries'] = 0
+                        
                     try:
-                        if 'station_name' in self.station_settings[i].keys():
-                            continue
+                        if 'station_instance' in self.station_settings[i].keys():
+                            # Check for station running here
+                            if self.station_settings[i]['station_instance'].isAlive():
+                                # Station exists and is alive.  Don't recreate.
+                                self.station_settings[i]['retries'] = 0
+                                continue
+                            
+                            if self.maxretry < 0 or self.station_settings[i]['retries'] <= self.maxretry:
+                                # Station passed the max retries count is will not be reloaded
+                                continue
+                                
+                            self.station_settings[i]['retries'] = self.station_settings[i]['retries'] + 1
+                            self._info('Restarting station ' + name + ' (try ' + str(self.station_settings[i]['retries']) + ')')
+                    except Exception as e:
+                        self._err('Error checking status for ' + name)
+                        self._err(str(e))
+                        if not ignoreErrors:
+                            raise
 
-                        # Apply station defaults if they exist
-                        if 'stationdefaults' in self.conf['deefuzzer']:
-                            if isinstance(self.conf['deefuzzer']['stationdefaults'], dict):
-                                self.station_settings[i] = merge_defaults(self.station_settings[i], self.conf['deefuzzer']['stationdefaults'])
+                    # Apply station defaults if they exist
+                    if 'stationdefaults' in self.conf['deefuzzer']:
+                        if isinstance(self.conf['deefuzzer']['stationdefaults'], dict):
+                            self.station_settings[i] = merge_defaults(self.station_settings[i], self.conf['deefuzzer']['stationdefaults'])
 
+                    if name == '':
                         name = 'Station ' + str(i)
-                        if 'info' in self.station_settings[i].keys():
-                            if 'short_name' in self.station_settings[i]['infos']:
-                                name = self.station_settings[i]['infos']['short_name']
-                                y = 1
-                                while name in self.station_instances.keys():
-                                    y = y + 1
-                                    name = self.station_settings[i]['infos']['short_name'] + " " + str(y)
-
-                        self.station_settings[i]['station_name'] = name
-                        namehash = hashlib.md5(name).hexdigest()
-                        self.station_settings[i]['station_statusfile'] = os.sep.join([self.log_dir, namehash])
-
-                        new_station = Station(self.station_settings[i], q, self.logqueue, self.m3u)
-                        if new_station.valid:
-                            self.station_instances[name] = new_station
-                            self.station_instances[name].start()
-                            self._info('Started station ' + name)
-                        else:
-                            self._err('Error validating station ' + name)
-                    except Exception:
-                        self._err('Error starting station ' + name)
-                        if not self.ignoreErrors:
-                            raise
-                        continue
-
-                ns = ns_new
+                    
+                    if 'info' in self.station_settings[i].keys():
+                        if 'short_name' in self.station_settings[i]['infos']:
+                            name = self.station_settings[i]['infos']['short_name']
+                            y = 1
+                            while name in self.station_instances.keys():
+                                y = y + 1
+                                name = self.station_settings[i]['infos']['short_name'] + " " + str(y)
+
+                    self.station_settings[i]['station_name'] = name
+                    namehash = hashlib.md5(name).hexdigest()
+                    self.station_settings[i]['station_statusfile'] = os.sep.join([self.log_dir, namehash])
+
+                    new_station = Station(self.station_settings[i], q, self.logqueue, self.m3u)
+                    if new_station.valid:
+                        self.station_settings[i]['station_instance'] = new_station
+                        self.station_settings[i]['station_instance'].start()
+                        self._info('Started station ' + name)
+                    else:
+                        self._err('Error validating station ' + name)
+                except Exception:
+                    self._err('Error creating station ' + name)
+                    if not ignoreErrors:
+                        raise
+                    continue
 
                 if self.m3u:
                     self.set_m3u_playlist()
-
-            for i in self.station_instances.keys():
-                try:
-                    if not self.station_instances[i].isAlive():
-                        self.station_instances[i].start()
-                        self._info('Restarted crashed station ' + i)
-                except:
-                    pass
-
+                    
+            ns = ns_new
             self.mainLoop = True
+
             time.sleep(5)
             # end main loop
 
index 80e0c958bb4d95d6e5ddccac2fcb8a2c501a6698..c6c92b90c93c4be54664110f91f9ed9be5dc39e2 100644 (file)
@@ -449,7 +449,7 @@ class Station(Thread):
 
             if not self.counter:
                 self.id = 0
-                if self.starting_id > -1:
+                if self.starting_id > -1 and self.starting_id < lp_new:
                     self.id = self.starting_id
                 self.playlist = new_playlist
                 self.lp = lp_new
@@ -795,6 +795,7 @@ class Station(Thread):
 
                     if not self.icecastloop_nextmedia():
                         self._info('Something wrong happened in icecastloop_nextmedia.  Ending.')
+                        self.channel_close()
                         return
 
                     self.icecastloop_metadata()
index bf314e602274fe0cf39e1c53e41d453f4493eb18..b51348ae91effa07576f88071b67eb0297945883 100644 (file)
     <!-- Whether or not to skip stations that fail instead of dying completely.  0 will raise
           all errors and report them to the console, 1 will log the error and continue.  -->
     <ignoreerrors>0</ignoreerrors>
+    <!-- How many times to attempt to restart a station thread that died for any reason.
+         -1 will attempt to restart unlimited times, 0 will not attempt a restart, and any
+         positive value will attempt to restart that many times.  The counter is reset when
+         the next subsequent check finds the station operational.  Default is 0 (no retry) -->
+    <maxretry>0</maxretry>
     <stationdefaults>
       <!-- This tag allows a common default configuration to be set for all stations.  This
            is useful when defining many stations that will share many common configuration
@@ -29,7 +34,7 @@
             <dir>/path/to/jingles</dir>
             <!-- If '1', some media will be played between each main track of the playlist. '0' does nothing. -->
             <mode>0</mode>
-            <!-- If '1', the jingle playlist will be randomized. '0' for aphanumeric order -->
+            <!-- If '1', the jingle playlist will be randomized. '0' for alphanumeric order -->
             <shuffle>1</shuffle>
         </jingles>
     </stationdefaults>
             <dir>/path/to/jingles</dir>
             <!-- If '1', some media will be played between each main track of the playlist. '0' does nothing. -->
             <mode>0</mode>
-            <!-- If '1', the jingle playlist will be randomized. '0' for aphanumeric order -->
+            <!-- If '1', the jingle playlist will be randomized. '0' for alphanumeric order -->
             <shuffle>1</shuffle>
         </jingles>
         <media>
             <!-- The mean bitrate of the media -->
             <bitrate>96</bitrate>
-            <!-- The path to the directory containing all the media. It will be analyse recursively. -->
+            <!-- The path to the directory containing all the media. It will be analyzed recursively. -->
             <dir>/path/to/mp3/</dir>
             <!-- The audio format of the media. Can be 'mp3' or 'ogg' -->
             <format>mp3</format>
@@ -74,9 +79,9 @@
             <m3u>/path/to/m3u_file</m3u>
             <!-- The ogg quality of the ogg vorbis media -->
             <ogg_quality>4</ogg_quality>
-            <!-- The samplerate of the media -->
+            <!-- The sample rate of the media -->
             <samplerate>48000</samplerate>
-            <!-- If '1', the playlist will be randomized. '0' for aphanumeric order -->
+            <!-- If '1', the playlist will be randomized. '0' for alphanumeric order -->
             <shuffle>0</shuffle>
             <!-- The number of channels - or voices - of the media. '1' for mono, '2' for stereo. -->
             <voices>2</voices>
         </twitter>
     </station>
 
-    <!-- Note that you can add many different stations in the same config file, thanks to the multi-threaded architecure ! -->
+    <!-- Note that you can add many different stations in the same config file, thanks to the multi-threaded architecture ! -->
 
     <!-- The stationfolder option allows auto-creation of stations based on a folder structure.  See the readme
          for details. -->