logviewer: avoid memory-mapped files, make it work when opened a second time
This commit is contained in:
		
							parent
							
								
									bbaecc1697
								
							
						
					
					
						commit
						fc95de82f4
					
				| 
						 | 
					@ -17,8 +17,8 @@
 | 
				
			||||||
#agpl-3.0.txt in the docs folder of the package.
 | 
					#agpl-3.0.txt in the docs folder of the package.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import mmap
 | 
					import os
 | 
				
			||||||
import threading
 | 
					import Queue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pygtk
 | 
					import pygtk
 | 
				
			||||||
pygtk.require('2.0')
 | 
					pygtk.require('2.0')
 | 
				
			||||||
| 
						 | 
					@ -30,13 +30,16 @@ import Configuration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
log = Configuration.get_logger("logging.conf", "logview")
 | 
					log = Configuration.get_logger("logging.conf", "logview")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MAX_LINES = 100000
 | 
					MAX_LINES = 100000         # max lines to display in window
 | 
				
			||||||
 | 
					EST_CHARS_PER_LINE = 150   # used to guesstimate number of lines in log file
 | 
				
			||||||
 | 
					logfile = 'logging.out'    # name of logfile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class GuiLogView:
 | 
					class GuiLogView:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, config, mainwin):
 | 
					    def __init__(self, config, mainwin, closeq):
 | 
				
			||||||
        self.config = config
 | 
					        self.config = config
 | 
				
			||||||
        self.main_window = mainwin
 | 
					        self.main_window = mainwin
 | 
				
			||||||
 | 
					        self.closeq = closeq
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.dia = gtk.Dialog(title="Log Messages"
 | 
					        self.dia = gtk.Dialog(title="Log Messages"
 | 
				
			||||||
                             ,parent=None
 | 
					                             ,parent=None
 | 
				
			||||||
| 
						 | 
					@ -88,6 +91,7 @@ class GuiLogView:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def dialog_response_cb(self, dialog, response_id):
 | 
					    def dialog_response_cb(self, dialog, response_id):
 | 
				
			||||||
        # this is called whether close button is pressed or window is closed
 | 
					        # this is called whether close button is pressed or window is closed
 | 
				
			||||||
 | 
					        self.closeq.put(self.__class__)
 | 
				
			||||||
        dialog.destroy()
 | 
					        dialog.destroy()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_dialog(self):
 | 
					    def get_dialog(self):
 | 
				
			||||||
| 
						 | 
					@ -109,39 +113,28 @@ class GuiLogView:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def loadLog(self):
 | 
					    def loadLog(self):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #self.configStore = gtk.TreeStore(gobject.TYPE_PYOBJECT, gobject.TYPE_STRING, gobject.TYPE_STRING)
 | 
					 | 
				
			||||||
        #self.configView = gtk.TreeView(self.configStore)
 | 
					 | 
				
			||||||
        #self.configView.set_enable_tree_lines(True)
 | 
					 | 
				
			||||||
        self.liststore.clear()
 | 
					        self.liststore.clear()
 | 
				
			||||||
        self.listcols = []
 | 
					        self.listcols = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # count number of lines in file
 | 
					        # guesstimate number of lines in file
 | 
				
			||||||
        f = open('logging.out', "r+")
 | 
					        if os.path.exists(logfile):
 | 
				
			||||||
        buf = mmap.mmap(f.fileno(), 0)
 | 
					            stat_info = os.stat(logfile)
 | 
				
			||||||
        readline = buf.readline
 | 
					            lines = stat_info.st_size / EST_CHARS_PER_LINE
 | 
				
			||||||
        lines = 0
 | 
					            print "logview: size =", stat_info.st_size, "lines =", lines
 | 
				
			||||||
        while readline():
 | 
					 | 
				
			||||||
            lines += 1
 | 
					 | 
				
			||||||
        f.close()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # set startline to line number to start display from
 | 
				
			||||||
            startline = 0
 | 
					            startline = 0
 | 
				
			||||||
            if lines > MAX_LINES:
 | 
					            if lines > MAX_LINES:
 | 
				
			||||||
                # only display from startline if log file is large
 | 
					                # only display from startline if log file is large
 | 
				
			||||||
                startline = lines - MAX_LINES
 | 
					                startline = lines - MAX_LINES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        f = open('logging.out', "r+")
 | 
					 | 
				
			||||||
        buf = mmap.mmap(f.fileno(), 0)
 | 
					 | 
				
			||||||
        readline = buf.readline
 | 
					 | 
				
			||||||
            l = 0
 | 
					            l = 0
 | 
				
			||||||
        line = readline()
 | 
					            for line in open(logfile):
 | 
				
			||||||
        while line:
 | 
					 | 
				
			||||||
                # eg line:
 | 
					                # eg line:
 | 
				
			||||||
                # 2009-12-02 15:23:21,716 - config       DEBUG    config logger initialised
 | 
					                # 2009-12-02 15:23:21,716 - config       DEBUG    config logger initialised
 | 
				
			||||||
                l = l + 1
 | 
					                l = l + 1
 | 
				
			||||||
                if l > startline and len(line) > 49:
 | 
					                if l > startline and len(line) > 49:
 | 
				
			||||||
                    iter = self.liststore.append( (line[0:23], line[26:32], line[39:46], line[48:].strip(), True) )
 | 
					                    iter = self.liststore.append( (line[0:23], line[26:32], line[39:46], line[48:].strip(), True) )
 | 
				
			||||||
            line = readline()
 | 
					 | 
				
			||||||
        f.close()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def sortCols(self, col, n):
 | 
					    def sortCols(self, col, n):
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,6 +18,7 @@
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
import re
 | 
					import re
 | 
				
			||||||
 | 
					import Queue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# if path is set to use an old version of python look for a new one:
 | 
					# if path is set to use an old version of python look for a new one:
 | 
				
			||||||
# (does this work in linux?)
 | 
					# (does this work in linux?)
 | 
				
			||||||
| 
						 | 
					@ -485,14 +486,22 @@ class fpdb:
 | 
				
			||||||
        #if self.obtain_global_lock():
 | 
					        #if self.obtain_global_lock():
 | 
				
			||||||
        #    lock_set = True
 | 
					        #    lock_set = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # remove members from self.threads if close messages received
 | 
				
			||||||
 | 
					        self.process_close_messages()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        viewer = None
 | 
				
			||||||
        for i, t in enumerate(self.threads):
 | 
					        for i, t in enumerate(self.threads):
 | 
				
			||||||
            if str(t.__class__) == 'GuiLogView.GuiLogView':
 | 
					            if str(t.__class__) == 'GuiLogView.GuiLogView':
 | 
				
			||||||
                # show existing log window
 | 
					                viewer = t
 | 
				
			||||||
                t.get_dialog().present()
 | 
					                break
 | 
				
			||||||
                return
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        new_thread = GuiLogView.GuiLogView(self.config, self.window)
 | 
					        if viewer is None:
 | 
				
			||||||
 | 
					            #print "creating new log viewer"
 | 
				
			||||||
 | 
					            new_thread = GuiLogView.GuiLogView(self.config, self.window, self.closeq)
 | 
				
			||||||
            self.threads.append(new_thread)
 | 
					            self.threads.append(new_thread)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            #print "showing existing log viewer"
 | 
				
			||||||
 | 
					            viewer.get_dialog().present()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #if lock_set:
 | 
					        #if lock_set:
 | 
				
			||||||
        #    self.release_global_lock()
 | 
					        #    self.release_global_lock()
 | 
				
			||||||
| 
						 | 
					@ -502,6 +511,21 @@ class fpdb:
 | 
				
			||||||
        self.logbuffer.insert(end_iter, text)
 | 
					        self.logbuffer.insert(end_iter, text)
 | 
				
			||||||
        self.logview.scroll_to_mark(self.logbuffer.get_insert(), 0)
 | 
					        self.logview.scroll_to_mark(self.logbuffer.get_insert(), 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def process_close_messages(self):
 | 
				
			||||||
 | 
					        # check for close messages
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            while True:
 | 
				
			||||||
 | 
					                name = self.closeq.get(False)
 | 
				
			||||||
 | 
					                for i, t in enumerate(self.threads):
 | 
				
			||||||
 | 
					                    if str(t.__class__) == str(name):
 | 
				
			||||||
 | 
					                        # thread has ended so remove from list:
 | 
				
			||||||
 | 
					                        del self.threads[i]
 | 
				
			||||||
 | 
					                        break
 | 
				
			||||||
 | 
					        except Queue.Empty:
 | 
				
			||||||
 | 
					            # no close messages on queue, do nothing
 | 
				
			||||||
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __calendar_dialog(self, widget, entry):
 | 
					    def __calendar_dialog(self, widget, entry):
 | 
				
			||||||
        self.dia_confirm.set_modal(False)
 | 
					        self.dia_confirm.set_modal(False)
 | 
				
			||||||
        d = gtk.Window(gtk.WINDOW_TOPLEVEL)
 | 
					        d = gtk.Window(gtk.WINDOW_TOPLEVEL)
 | 
				
			||||||
| 
						 | 
					@ -846,6 +870,7 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt")
 | 
				
			||||||
        #done menubar
 | 
					        #done menubar
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.threads = []     # objects used by tabs - no need for threads, gtk handles it
 | 
					        self.threads = []     # objects used by tabs - no need for threads, gtk handles it
 | 
				
			||||||
 | 
					        self.closeq = Queue.Queue(20)  # used to signal ending of a thread (only logviewer for now)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.nb = gtk.Notebook()
 | 
					        self.nb = gtk.Notebook()
 | 
				
			||||||
        self.nb.set_show_tabs(True)
 | 
					        self.nb.set_show_tabs(True)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user