[vlma-devel] commit: Memory-based implementation of getLogTail. (Adrien Grand )

git version control git at videolan.org
Mon Feb 23 04:34:24 CET 2009


vlma | branch: master | Adrien Grand <jpountz at videolan.org> | Mon Feb 23 04:33:27 2009 +0100| [c434c776706f971f49dd4e858a778d6ec01fed74] | committer: Adrien Grand 

Memory-based implementation of getLogTail.

> http://git.videolan.org/gitweb.cgi/vlma.git/?a=commit;h=c434c776706f971f49dd4e858a778d6ec01fed74
---

 vlma-watchdog/src/conf.py |    5 +-
 vlma-watchdog/src/vlc.py  |  106 +++++++++++++++++++++++++++++++++++----------
 2 files changed, 86 insertions(+), 25 deletions(-)

diff --git a/vlma-watchdog/src/conf.py b/vlma-watchdog/src/conf.py
index 2fc24a3..e07b023 100644
--- a/vlma-watchdog/src/conf.py
+++ b/vlma-watchdog/src/conf.py
@@ -6,8 +6,7 @@ LOG_LEVEL = 20
 # Name of the VLC executable (give the full path if vlc is not
 # available in the PATH environment variable)
 VLC_EXE = "vlc"
-VLC_LOGS = "vlc.log"
-VLC_ARGS  = "--color -vvv --ignore-config --rtsp-host 0.0.0.0:5554 --intf lua --lua-intf telnet --extraintf logger --logfile %s --logmode text" %(VLC_LOGS)
+VLC_ARGS  = "--color -vvv --ignore-config --rtsp-host 0.0.0.0:5554 --intf lua --lua-intf telnet"
 
 CPU_LOAD_THRESHOLD = 6.0
 VLC_CPU_THRESHOLD  = 80.0
@@ -20,3 +19,5 @@ SERVER_PORT = 4213
 SERVER_LOGIN = "videolan"
 SERVER_PASSWORD = "admin"
 
+# Size of the log queue to keep in memory
+LOG_TAIL_SIZE = 500
diff --git a/vlma-watchdog/src/vlc.py b/vlma-watchdog/src/vlc.py
index 8c327da..c0da896 100644
--- a/vlma-watchdog/src/vlc.py
+++ b/vlma-watchdog/src/vlc.py
@@ -15,7 +15,7 @@ global vlcInstance
 
 class VLCRunner(threading.Thread):
 
-  def __init__(self):
+  def __init__(self, queue, queue_lock, stdout_reader, stderr_reader):
     self.logger = logging.getLogger("VLC Runner")
     threading.Thread.__init__(self)
     self.setName("VLC Runner")
@@ -24,6 +24,10 @@ class VLCRunner(threading.Thread):
     self.__shouldRun = True
     self.__startTime = 0
     self.__version = None
+    self.__log_queue = queue
+    self.__log_queue_lock = queue_lock
+    self.__stdout_reader = stdout_reader
+    self.__stderr_reader = stderr_reader
 
   def run(self):
     while True:
@@ -35,7 +39,9 @@ class VLCRunner(threading.Thread):
       args = conf.VLC_ARGS.split()
       args.insert(0, conf.VLC_EXE)
       self.__startTime = math.floor(1000L * time.time())
-      process = subprocess.Popen(args)
+      process = subprocess.Popen(args, bufsize=8192, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+      self.__stdout_reader.setInput(process.stdout)
+      self.__stderr_reader.setInput(process.stderr)
       self.__pid = process.pid
       self.__lock.release()
       exit_status = os.waitpid(self.__pid, 0)[1]
@@ -45,6 +51,12 @@ class VLCRunner(threading.Thread):
       self.logger.info("VLC exited with return code %d", exit_status)
     self.logger.info("VLC has been stopped")
 
+  def getLogTail(self, lines):
+    self.__log_queue_lock.acquire()
+    result = self.__log_queue[-lines:]
+    self.__log_queue_lock.release()
+    return result
+
   def getVersion(self):
     self.__lock.acquire()
     version = self.__version
@@ -86,18 +98,61 @@ class VLCRunner(threading.Thread):
     self.join()
     self.startTime = 0
 
+
+class LogReader(threading.Thread):
+
+  def __init__(self, size, input, output, output_lock):
+    threading.Thread.__init__(self)
+    self.__size = size
+    self.__lock = threading.RLock()
+    self.__output_lock = output_lock
+    self.__output = output
+    self.__input = input
+    self.setDaemon(True)
+
+  def setInput(self, input):
+    self.__lock.acquire()
+    self.__input = input
+    self.__lock.release()
+
+  def run(self):
+    while True:
+      self.__lock.acquire()
+      ready = not self.__input is None
+      line = ""
+      if ready:
+        line = self.__input.readline().rstrip('\n')
+      self.__lock.release()
+      if not ready:
+        continue
+      self.__output_lock.acquire()
+      self.__output.append(line)
+      to_remove = len(self.__output) - self.__size
+      if to_remove > 0:
+        for i in range(to_remove):
+          self.__output.pop(0)
+      self.__output_lock.release()
+
+
 class VLC:
 
   def __init__(self):
     self.logger = logging.getLogger("VLC")
     self.runner = None
+    self.__log_queue = []
+    self.__log_queue_lock = threading.RLock()
+    self.__stdout_reader = LogReader(conf.LOG_TAIL_SIZE, None, self.__log_queue, self.__log_queue_lock)
+    self.__stderr_reader = LogReader(conf.LOG_TAIL_SIZE, None, self.__log_queue, self.__log_queue_lock)
+    self.__stdout_reader.start()
+    self.__stderr_reader.start()
 
   def start(self):
     if not self.runner is None and self.runner.isAlive():
       logger.error("Cannot start VLC, another instance is still running.")
       logger.info("Please stop VLC first")
     else:
-      self.runner = VLCRunner()
+      self.runner = VLCRunner(self.__log_queue, self.__log_queue_lock,
+                              self.__stdout_reader, self.__stderr_reader)
       self.runner.start()
 
   def stop(self):
@@ -110,26 +165,31 @@ class VLC:
     return self.runner.getVersion()
 
   def getLogTail(self, lines=50):
-    try:
-      f = open(conf.VLC_LOGS)
-    except:
-      return ""
-    avgCharsPerLine = 70
-    while True:
-      beginningOfFileReached = False
-      try:
-        pos = - avgCharsPerLine * lines
-        f.seek(pos, 2)
-      except IOError:
-        beginningOfFileReached = True
-        f.seek(0)
-      logs = f.read().split("\n")[-lines:]
-      if len(logs) < lines and not beginningOfFileReached:
-        avgcharsperline *= 1.3
-      else:
-        break
-    f.close()
-    return logs
+    return self.runner.getLogTail(lines)
+
+# Former version, file-based
+#
+#  def getLogTail(self, lines=50):
+#    try:
+#      f = open(conf.VLC_LOGS)
+#    except:
+#      return ""
+#    avgCharsPerLine = 70
+#    while True:
+#      beginningOfFileReached = False
+#      try:
+#        pos = - avgCharsPerLine * lines
+#        f.seek(pos, 2)
+#      except IOError:
+#        beginningOfFileReached = True
+#        f.seek(0)
+#      logs = f.read().split("\n")[-lines:]
+#      if len(logs) < lines and not beginningOfFileReached:
+#        avgcharsperline *= 1.3
+#      else:
+#        break
+#    f.close()
+#    return logs
 
   def restart(self):
     self.stop()



More information about the vlma-devel mailing list