;************************************** ;* ;* lhs_log.pbi ;* ;* Single Logthread logger. ;* ;* For multiple logthread use lhs_log_ext.pbi ;* ;* (c) by René Linder ;* (c) by Linder Hard- und Software ;* ;* Lizenz LGPL V2.1 ;{ Short Documentation: ;* ;* lhs_log::App_Name = "Test App" ;* lhs_log::SetLogFile("test_app.log")) ;* lhs_log::SetMaxSize(32) ;* lhs_log::SetLogLevel(lhs_log::#Error) ;* lhs_log::SetLogDateFormat("%yyyy.%mm.%dd %hh:%ii:%ss") ;* lhs_log::SetLogFileDateFormat("%yyyy_%mm_%dd_%hh_%ii_%ss") ;* lhs_log::Init() ;* lhs_log::Out("Log started.", #lhs_log::#Debug) ;* lhs_log::OutL(lhs_log::#Info, "Info Level") ;* lhs_log::Close() ;} CompilerIf #PB_Compiler_Thread <> 1 CompilerError "Muss Threadsafe Kompiliert werden" ;Need to be compiled threadsafe CompilerEndIf DeclareModule lhs_log Global.s App_Name = "lhs_Logger" #Debug = 1 #NoDebug = 0 Enumeration LogLevel #Info #Warning #Error EndEnumeration Declare SetLogFile(LogFileName.s) Declare SetMaxSize(Megabyte.i) Declare SetLogLevel(Level.i) Declare SetLogFileDateFormat(DateFormat.s) Declare SetLogDateFormat(DateFormat.s) Declare Init() Declare Out(ToLog.s, debugger.i = #NoDebug) Declare OutL(LogType.i, ToLog.s, debugger.i = #NoDebug) Declare Disable() Declare Close() EndDeclareModule Module lhs_log Global File_ID.i Global log_state.i = #true CompilerIf #PB_Compiler_OS = #PB_OS_Linux Global LogFile.s = "/var/log/"+App_Name+".log" CompilerElseIf #PB_Compiler_OS = #PB_OS_Windows Global LogFile.s = GetPathPart(ProgramFilename())+App_Name+ ".log" CompilerElse CompilerError "Andere Betriebssysteme als Windows und Linux werden nicht unterstützt" ;Other Operatingsystems than Windows and Linux are currently unsupported CompilerEndIf Global Exit.i = 0 Global Mutex = CreateMutex() Global Semaphore = CreateSemaphore() Global ExitSemaphore = CreateSemaphore() Global MaxSize.q = 32 * 1024 * 1024 Global LastSize.q = 0 Global LogLevel.i = #Info Global LogFileDateFormat.s = "%yyyy_%mm_%dd_%hh_%ii_%ss" Global LogDateFormat.s = "%yyyy.%mm.%dd %hh:%ii:%ss" Global NewList Messages.s() Procedure SetMaxSize(Megabyte.i) If Megabyte > 0 And Megabyte < 1025 MaxSize = Megabyte * 1024 * 1024 Else MaxSize = 32 * 1024 * 1024 EndIf EndProcedure Procedure SetLogLevel(Level.i) Select Level Case #Info LogLevel = #Info Case #Warning LogLevel = #Warning Case #Error LogLevel = #Error Default LogLevel = #Error EndSelect EndProcedure Procedure SetLogFile(LogFileName.s) Protected.i TestFile_ID TestFile_ID = OpenFile(#PB_Any, LogFileName, #PB_File_Append | #PB_File_NoBuffering) If IsFile(TestFile_ID) LogFile = LogFileName CloseFile(TestFile_ID) ProcedureReturn #True Else ProcedureReturn #False EndIf EndProcedure Procedure SetLogFileDateFormat(DateFormat.s) If Len(DateFormat)>4 LogFileDateFormat = DateFormat EndIf EndProcedure Procedure SetLogDateFormat(DateFormat.s) If Len(DateFormat)>4 LogDateFormat = DateFormat EndIf EndProcedure Procedure CheckMaxSize() If LastSize = 0 LastSize = FileSize(LogFile) EndIf ProcedureReturn Bool(LastSize < MaxSize) EndProcedure Procedure UpdateLastSizeString(String.s) LastSize + StringByteLength(String.s) EndProcedure Procedure Disable() log_state = #False EndProcedure Procedure Enable() log_state = #True EndProcedure Procedure LogThread(nix) Shared Mutex Define ToWrite.s File_ID = OpenFile(#PB_Any, LogFile, #PB_File_Append | #PB_File_NoBuffering) If IsFile(File_ID) Repeat WaitSemaphore(Semaphore) If Exit = 1 LockMutex(Mutex) If ListSize(Messages()) > 0 Repeat FirstElement(Messages()) ToWrite = FormatDate(LogDateFormat, Date()) + " - " + Messages() UpdateLastSizeString(ToWrite):WriteStringN(File_ID, ToWrite) DeleteElement(Messages()) Until ListSize(Messages()) = 0 EndIf CloseFile(File_ID) UnlockMutex(Mutex) Break Else LockMutex(Mutex) FirstElement(Messages()) ToWrite = FormatDate(LogDateFormat, Date()) + " - " + Messages() UpdateLastSizeString(ToWrite) If Not CheckMaxSize() CloseFile(File_ID) If CopyFile(LogFile, LogFile+FormatDate(LogFileDateFormat, Date())) DeleteFile(LogFile) EndIf File_ID = OpenFile(#PB_Any, LogFile, #PB_File_Append | #PB_File_NoBuffering) EndIf WriteStringN(File_ID, ToWrite) DeleteElement(Messages()) UnlockMutex(Mutex) EndIf ForEver SignalSemaphore(ExitSemaphore) EndIf EndProcedure Procedure Init() File_ID = OpenFile(#PB_Any, LogFile, #PB_File_Append | #PB_File_NoBuffering) If IsFile(File_ID) CloseFile(File_ID) Else ProcedureReturn #False EndIf CreateThread(@LogThread(), 1) ProcedureReturn #True EndProcedure Procedure Out(ToLog.s, debugger.i = #NoDebug) If log_state Shared Mutex LockMutex(Mutex) LastElement(Messages()) AddElement(Messages()) Messages() = ToLog If debugger = #Debug Debug ToLog EndIf UnlockMutex(Mutex) SignalSemaphore(Semaphore) EndIf EndProcedure Procedure OutL(LogType.i, ToLog.s, debugger.i = #NoDebug) If LogType >= LogLevel Select LogType Case #Info ToLog = "Info: " + ToLog Case #Warning ToLog = "Warning: " + ToLog Case #Error ToLog = "Error: " + ToLog Default ToLog = "Error: " + ToLog EndSelect Out(ToLog, debugger) EndIf EndProcedure Procedure Close() Exit=1 SignalSemaphore(Semaphore) WaitSemaphore(ExitSemaphore) EndProcedure EndModule