# HG changeset patch # User Edouard Tisserant # Date 1359532452 -39600 # Node ID 401e44bae7c073e8d3ccb46895883fe45426d1e4 # Parent 697d8b77d7163fe80753e5761d294befde19bb9d Now logging have 4 levels diff -r 697d8b77d716 -r 401e44bae7c0 ProjectController.py --- a/ProjectController.py Tue Jan 29 23:41:00 2013 +0100 +++ b/ProjectController.py Wed Jan 30 18:54:12 2013 +1100 @@ -25,7 +25,7 @@ from dialogs import DiscoveryDialog from PLCControler import PLCControler from plcopen.structures import IEC_KEYWORDS -from targets.typemapping import DebugTypesSize +from targets.typemapping import DebugTypesSize, LogLevelsCount, LogLevels from ConfigTreeNode import ConfigTreeNode base_folder = os.path.split(sys.path[0])[0] @@ -113,7 +113,7 @@ self.DebugThread = None self.debug_break = False self.previous_plcstate = None - self.previous_log_count = None + self.previous_log_count = [None]*LogLevelsCount # copy ConfNodeMethods so that it can be later customized self.StatusMethods = [dic.copy() for dic in self.StatusMethods] @@ -1077,24 +1077,26 @@ self.CompareLocalAndRemotePLC() def UpdatePLCLog(self, log_count): - if log_count and self.previous_log_count != log_count: - # XXX replace dump to console with dedicated log panel. - to_console = [''] - dump_end = max( # request message sent after the last one we already got - self.previous_log_count - 1 if self.previous_log_count is not None else -1, - log_count - 100) # 100 is purely arbitrary number - # dedicated panel should only ask for a small range, - # depending on how user navigate in the panel - # and only ask for last one in follow mode - for msgidx in xrange(log_count-1, dump_end,-1): - msg = self._connector.GetLogMessage(msgidx) - if msg is not None : - to_console.insert(0, '#' + repr(msgidx) + ": " + msg) - else: - to_console.insert(0, 'No log before #'+repr(msgidx)) - break; - self.logger.write("\n".join(to_console)) - self.previous_log_count = log_count + if log_count : + for level, count, prev in zip(xrange(LogLevelsCount), log_count,self.previous_log_count): + if count is not None and prev != count: + # XXX replace dump to console with dedicated log panel. + to_console = [''] + dump_end = max( # request message sent after the last one we already got + prev - 1 if prev is not None else -1, + count - 100) # 100 is purely arbitrary number + # dedicated panel should only ask for a small range, + # depending on how user navigate in the panel + # and only ask for last one in follow mode + for msgidx in xrange(count-1, dump_end,-1): + msg = self._connector.GetLogMessage(level, msgidx) + if msg is not None : + to_console.insert(0, LogLevels[level]+ ':#' + repr(msgidx) + ": " + msg) + else: + to_console.insert(0, LogLevels[level]+ ': No log before #'+repr(msgidx)) + break; + self.logger.write("\n".join(to_console)) + self.previous_log_count[level] = count def UpdateMethodsFromPLCStatus(self): status = None @@ -1289,7 +1291,7 @@ while (not self.debug_break) and (self._connector is not None): Trace = self._connector.GetTraceVariables() if(Trace): - plc_status, log_count, debug_tick, debug_vars = Trace + plc_status, debug_tick, debug_vars = Trace else: plc_status = None debug_getvar_retry += 1 @@ -1331,7 +1333,7 @@ def _connect_debug(self): self.previous_plcstate = None - self.previous_log_count = None + self.previous_log_count = [None]*LogLevelsCount if self.AppFrame: self.AppFrame.ResetGraphicViewers() self.RegisterDebugVarToConnector() @@ -1511,7 +1513,7 @@ else: self.logger.write_error(_("No PLC to transfer (did build succeed ?)\n")) - self.previous_log_count = None + self.previous_log_count = [None]*LogLevelsCount wx.CallAfter(self.UpdateMethodsFromPLCStatus) diff -r 697d8b77d716 -r 401e44bae7c0 connectors/PYRO/__init__.py --- a/connectors/PYRO/__init__.py Tue Jan 29 23:41:00 2013 +0100 +++ b/connectors/PYRO/__init__.py Wed Jan 30 18:54:12 2013 +1100 @@ -140,7 +140,7 @@ if self.RemotePLCObjectProxyCopy is None: self.RemotePLCObjectProxyCopy = copy.copy(confnodesroot._connector.GetPyroProxy()) return self.RemotePLCObjectProxyCopy.GetTraceVariables() - GetTraceVariables = PyroCatcher(_PyroGetTraceVariables,("Broken",-1,None,None)) + GetTraceVariables = PyroCatcher(_PyroGetTraceVariables,("Broken",None,None)) def _PyroGetPLCstatus(self): return RemotePLCObjectProxy.GetPLCstatus() diff -r 697d8b77d716 -r 401e44bae7c0 runtime/PLCObject.py --- a/runtime/PLCObject.py Tue Jan 29 23:41:00 2013 +0100 +++ b/runtime/PLCObject.py Wed Jan 30 18:54:12 2013 +1100 @@ -25,7 +25,8 @@ import Pyro.core as pyro from threading import Timer, Thread, Lock, Semaphore import ctypes, os, commands, types, sys -from targets.typemapping import SameEndianessTypeTranslator as TypeTranslator +from targets.typemapping import LogLevelsDefault, LogLevelsCount, SameEndianessTypeTranslator as TypeTranslator + if os.name in ("nt", "ce"): from _ctypes import LoadLibrary as dlopen @@ -80,25 +81,29 @@ if self.statuschange is not None: self.statuschange(self.PLCStatus) - def LogMessage(self, msg): - return self._LogMessage(msg, len(msg)) - - - def GetLogCount(self): + def LogMessage(self, *args): + if len(args) == 2: + level, msg = args + else: + level = LogLevelsDefault + msg, = args + return self._LogMessage(level, msg, len(msg)) + + + def GetLogCount(self, level): if self._GetLogCount is not None : - return int(self._GetLogCount()) - elif self._loading_error is not None: + return int(self._GetLogCount(level)) + elif self._loading_error is not None and level==0: return 1; - - def GetLogMessage(self, msgid): + def GetLogMessage(self, level, msgid): if self._GetLogMessage is not None: maxsz = len(self._log_read_buffer)-1 - sz = self._GetLogMessage(msgid, self._log_read_buffer, maxsz) + sz = self._GetLogMessage(level, msgid, self._log_read_buffer, maxsz) if sz and sz <= maxsz: self._log_read_buffer[sz] = '\x00' return self._log_read_buffer.value - elif self._loading_error is not None : + elif self._loading_error is not None and level==0: return self._loading_error return None @@ -171,15 +176,16 @@ self._GetLogCount = self.PLClibraryHandle.GetLogCount self._GetLogCount.restype = ctypes.c_uint32 + self._GetLogCount.argtypes = [ctypes.c_uint8] self._LogMessage = self.PLClibraryHandle.LogMessage self._LogMessage.restype = ctypes.c_int - self._LogMessage.argtypes = [ctypes.c_char_p, ctypes.c_uint32] + self._LogMessage.argtypes = [ctypes.c_uint8, ctypes.c_char_p, ctypes.c_uint32] self._log_read_buffer = ctypes.create_string_buffer(1<<14) #16K self._GetLogMessage = self.PLClibraryHandle.GetLogMessage self._GetLogMessage.restype = ctypes.c_uint32 - self._GetLogMessage.argtypes = [ctypes.c_uint32, ctypes.c_char_p, ctypes.c_uint32] + self._GetLogMessage.argtypes = [ctypes.c_uint8, ctypes.c_uint32, ctypes.c_char_p, ctypes.c_uint32] self._loading_error = None return True @@ -206,7 +212,7 @@ self._resumeDebug = lambda:None self._PythonIterator = lambda:"" self._GetLogCount = None - self._LogMessage = lambda m,s:PLCprint("OFF LOG :"+m) + self._LogMessage = lambda l,m,s:PLCprint("OFF LOG :"+m) self._GetLogMessage = None self.PLClibraryHandle = None # Unload library explicitely @@ -293,8 +299,6 @@ self.evaluator(self.FinishRuntimePy) def StartPLC(self): - PLCprint("StartPLC") - self.LogMessage("Hello Log") if self.CurrentPLCFilename is not None and self.PLCStatus == "Stopped": c_argv = ctypes.c_char_p * len(self.argv) error = None @@ -304,14 +308,15 @@ self.PythonThread = Thread(target=self.PythonThreadProc) self.PythonThread.start() self.StartSem.acquire() + self.LogMessage("PLC started") else: - PLCprint(_("Problem starting PLC : error %d" % res)) + self.LogMessage(_("Problem starting PLC : error %d" % res)) self.PLCStatus = "Broken" self.StatusChange() def StopPLC(self): - PLCprint("StopPLC") if self.PLCStatus == "Started": + self.LogMessage("PLC stopped") self._stopPLC() self.PythonThread.join() return True @@ -330,10 +335,10 @@ return True def GetPLCstatus(self): - return self.PLCStatus, self.GetLogCount() + return self.PLCStatus, map(self.GetLogCount,xrange(LogLevelsCount)) def NewPLC(self, md5sum, data, extrafiles): - PLCprint("NewPLC (%s)"%md5sum) + self.LogMessage("NewPLC (%s)"%md5sum) if self.PLCStatus in ["Stopped", "Empty", "Broken"]: NewFileName = md5sum + lib_ext extra_files_log = os.path.join(self.workingdir,"extra_files.txt") @@ -451,10 +456,10 @@ self._FreeDebugData() self.PLClibraryLock.release() if offset and offset == size.value: - return self.PLCStatus, self.GetLogCount(), tick.value, res + return self.PLCStatus, tick.value, res #elif size.value: #PLCprint("Debug error - wrong buffer unpack ! %d != %d"%(offset, size.value)) - return self.PLCStatus, self.GetLogCount(), None, [] + return self.PLCStatus, None, [] def RemoteExec(self, script, **kwargs): try: diff -r 697d8b77d716 -r 401e44bae7c0 targets/plc_debug.c --- a/targets/plc_debug.c Tue Jan 29 23:41:00 2013 +0100 +++ b/targets/plc_debug.c Wed Jan 30 18:54:12 2013 +1100 @@ -306,25 +306,31 @@ /* LOGGING */ +#define LOG_LEVELS 4 +#define LOG_CRITICAL 0 +#define LOG_WARNING 1 +#define LOG_INFO 2 +#define LOG_DEBUG 4 + #define LOG_BUFFER_SIZE (1<<14) /*16Ko*/ #define LOG_BUFFER_MASK (LOG_BUFFER_SIZE-1) -static char LogBuff[LOG_BUFFER_SIZE]; -void inline copy_to_log(uint32_t buffpos, void* buf, uint32_t size){ +static char LogBuff[LOG_LEVELS][LOG_BUFFER_SIZE]; +void inline copy_to_log(uint8_t level, uint32_t buffpos, void* buf, uint32_t size){ if(buffpos + size < LOG_BUFFER_SIZE){ - memcpy(&LogBuff[buffpos], buf, size); + memcpy(&LogBuff[level][buffpos], buf, size); }else{ uint32_t remaining = LOG_BUFFER_SIZE - buffpos - 1; - memcpy(&LogBuff[buffpos], buf, remaining); - memcpy(LogBuff, buf + remaining, size - remaining); - } -} -void inline copy_from_log(uint32_t buffpos, void* buf, uint32_t size){ + memcpy(&LogBuff[level][buffpos], buf, remaining); + memcpy(LogBuff[level], buf + remaining, size - remaining); + } +} +void inline copy_from_log(uint8_t level, uint32_t buffpos, void* buf, uint32_t size){ if(buffpos + size < LOG_BUFFER_SIZE){ - memcpy(buf, &LogBuff[buffpos], size); + memcpy(buf, &LogBuff[level][buffpos], size); }else{ uint32_t remaining = LOG_BUFFER_SIZE - buffpos; - memcpy(buf, &LogBuff[buffpos], remaining); - memcpy(buf + remaining, LogBuff, size - remaining); + memcpy(buf, &LogBuff[level][buffpos], remaining); + memcpy(buf + remaining, LogBuff[level], size - remaining); } } @@ -345,10 +351,10 @@ |63 ... 32|31 ... 0| | Message | Buffer | | counter | Index | */ -static uint64_t LogCursor = 0x0; +static uint64_t LogCursor[LOG_LEVELS] = {0x0,0x0,0x0,0x0}; /* Store one log message of give size */ -int LogMessage(char* buf, uint32_t size){ +int LogMessage(uint8_t level, char* buf, uint32_t size){ if(size < LOG_BUFFER_SIZE - sizeof(mTail)){ uint32_t buffpos; mTail tail; @@ -358,34 +364,34 @@ succeeds non interrupted */ uint64_t new_cursor, old_cursor; do{ - old_cursor = LogCursor; + old_cursor = LogCursor[level]; buffpos = (uint32_t)old_cursor; tail.msgidx = (old_cursor >> 32); new_cursor = ((uint64_t)(tail.msgidx + 1)<<32) | (uint64_t)((buffpos + size + sizeof(mTail)) & LOG_BUFFER_MASK); - }while(!__sync_bool_compare_and_swap(&LogCursor,old_cursor,new_cursor)); - - copy_to_log(buffpos, buf, size); + }while(!__sync_bool_compare_and_swap(&LogCursor[level],old_cursor,new_cursor)); + + copy_to_log(level, buffpos, buf, size); tail.msgsize = size; /*XXX tick*/ /*XXX RTC*/ - copy_to_log((buffpos + size) & LOG_BUFFER_MASK, &tail, sizeof(mTail)); + copy_to_log(level, (buffpos + size) & LOG_BUFFER_MASK, &tail, sizeof(mTail)); return 1; /* Success */ }else{ char mstr[] = "Logging error : message too big"; - LogMessage(mstr, sizeof(mstr)); + LogMessage(LOG_CRITICAL, mstr, sizeof(mstr)); } return 0; } -uint32_t GetLogCount(){ - return (uint64_t)LogCursor >> 32; +uint32_t GetLogCount(uint8_t level){ + return (uint64_t)LogCursor[level] >> 32; } /* Return message size and content */ -uint32_t GetLogMessage(uint32_t msgidx, char* buf, uint32_t max_size){ - uint64_t cursor = LogCursor; +uint32_t GetLogMessage(uint8_t level, uint32_t msgidx, char* buf, uint32_t max_size){ + uint64_t cursor = LogCursor[level]; if(cursor){ /* seach cursor */ uint32_t stailpos = (uint32_t)cursor; @@ -398,13 +404,13 @@ do { smsgidx = tail.msgidx; stailpos = (stailpos - sizeof(mTail) - tail.msgsize ) & LOG_BUFFER_MASK; - copy_from_log(stailpos, &tail, sizeof(mTail)); + copy_from_log(level, stailpos, &tail, sizeof(mTail)); }while((tail.msgidx == smsgidx - 1) && (tail.msgidx > msgidx)); if(tail.msgidx == msgidx){ uint32_t sbuffpos = (stailpos - tail.msgsize ) & LOG_BUFFER_MASK; uint32_t totalsize = tail.msgsize; /*sizeof(mTail);*/ - copy_from_log(sbuffpos, buf, totalsize > max_size ? max_size : totalsize); + copy_from_log(level, sbuffpos, buf, totalsize > max_size ? max_size : totalsize); return totalsize; } } diff -r 697d8b77d716 -r 401e44bae7c0 targets/typemapping.py --- a/targets/typemapping.py Tue Jan 29 23:41:00 2013 +0100 +++ b/targets/typemapping.py Wed Jan 30 18:54:12 2013 +1100 @@ -76,3 +76,7 @@ # Construct debugger natively supported types DebugTypesSize = dict([(key,sizeof(t)) for key,(t,p,u) in SameEndianessTypeTranslator.iteritems() if t is not None]) +LogLevels = ["CRITICAL","WARNING","INFO","DEBUG"] +LogLevelsCount = len(LogLevels) +LogLevelsDict = dict(zip(LogLevels,range(LogLevelsCount))) +LogLevelsDefault = LogLevelsDict["DEBUG"] diff -r 697d8b77d716 -r 401e44bae7c0 tests/logging/plc.xml --- a/tests/logging/plc.xml Tue Jan 29 23:41:00 2013 +0100 +++ b/tests/logging/plc.xml Wed Jan 30 18:54:12 2013 +1100 @@ -8,7 +8,7 @@ productVersion="1" creationDateTime="2013-01-29T14:01:00"/> + modificationDateTime="2013-01-30T18:24:53"> @@ -22,7 +22,23 @@ - + + + + + + + + + + + + + + + + + @@ -37,6 +53,14 @@ + + + + + + + + @@ -50,7 +74,7 @@ + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -292,6 +287,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +