Created
May 31, 2023 01:27
-
-
Save snower/adcf300f3daff99549dbe1949982a5dc to your computer and use it in GitHub Desktop.
logging_file_lock_handler
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
# 14-8-20 | |
# create by: snower | |
import os | |
import time | |
import struct | |
import fcntl | |
from logging.handlers import RotatingFileHandler, TimedRotatingFileHandler | |
class RotatingFileHandler(RotatingFileHandler): | |
def __init__(self, *args, **kwargs): | |
super(RotatingFileHandler, self).__init__(*args, **kwargs) | |
self._lock_fd = 0 | |
self._lock_version = 0 | |
self._version = 0 | |
self.init_lock() | |
def init_lock(self): | |
try: | |
self.acquire_lock() | |
self._version = self._lock_version | |
finally: | |
self.release_lock() | |
def acquire_lock(self): | |
if self._lock_fd == 0: | |
self._lock_fd = os.open(self.baseFilename + ".lock", os.O_CREAT | os.O_RDWR) | |
fcntl.flock(self._lock_fd, fcntl.LOCK_EX) | |
v = os.read(self._lock_fd, 4) | |
if len(v) == 4: | |
self._lock_version, = struct.unpack("!I", v) | |
os.lseek(self._lock_fd, 0, os.SEEK_SET) | |
def release_lock(self): | |
if self._lock_fd: | |
os.fsync(self._lock_fd) | |
fcntl.flock(self._lock_fd, fcntl.LOCK_UN) | |
os.close(self._lock_fd) | |
self._lock_fd = 0 | |
def doRollover(self): | |
""" | |
Do a rollover, as described in __init__(). | |
""" | |
if self.stream: | |
self.stream.close() | |
self.stream = None | |
try: | |
self.acquire_lock() | |
if self._lock_version == self._version: | |
if self.backupCount > 0: | |
for i in range(self.backupCount - 1, 0, -1): | |
sfn = "%s.%d" % (self.baseFilename, i) | |
dfn = "%s.%d" % (self.baseFilename, i + 1) | |
if os.path.exists(sfn): | |
# print "%s -> %s" % (sfn, dfn) | |
if os.path.exists(dfn): | |
os.remove(dfn) | |
os.rename(sfn, dfn) | |
dfn = self.baseFilename + ".1" | |
if os.path.exists(dfn): | |
os.remove(dfn) | |
# Issue 18940: A file may not have been created if delay is True. | |
if os.path.exists(self.baseFilename): | |
os.rename(self.baseFilename, dfn) | |
os.write(self._lock_fd, struct.pack("!I", self._lock_version + 1)) | |
self._version += 1 | |
finally: | |
self.release_lock() | |
if not self.delay: | |
self.stream = self._open() | |
class TimedRotatingFileHandler(TimedRotatingFileHandler): | |
def __init__(self, *args, **kwargs): | |
super(TimedRotatingFileHandler, self).__init__(*args, **kwargs) | |
self._lock_fd = 0 | |
self._lock_version = 0 | |
self._version = 0 | |
self.init_lock() | |
def init_lock(self): | |
try: | |
self.acquire_lock() | |
self._version = self._lock_version | |
finally: | |
self.release_lock() | |
def acquire_lock(self): | |
if self._lock_fd == 0: | |
self._lock_fd = os.open(self.baseFilename + ".lock", os.O_CREAT | os.O_RDWR) | |
fcntl.flock(self._lock_fd, fcntl.LOCK_EX) | |
v = os.read(self._lock_fd, 4) | |
if len(v) == 4: | |
self._lock_version, = struct.unpack("!I", v) | |
os.lseek(self._lock_fd, 0, os.SEEK_SET) | |
def release_lock(self): | |
if self._lock_fd: | |
os.fsync(self._lock_fd) | |
fcntl.flock(self._lock_fd, fcntl.LOCK_UN) | |
os.close(self._lock_fd) | |
self._lock_fd = 0 | |
def rename_file(self): | |
# get the time that this sequence started at and make it a TimeTuple | |
t = self.rolloverAt - self.interval | |
if self.utc: | |
timeTuple = time.gmtime(t) | |
else: | |
timeTuple = time.localtime(t) | |
dfn = self.baseFilename + "." + time.strftime(self.suffix, timeTuple) | |
if os.path.exists(dfn): | |
os.remove(dfn) | |
os.rename(self.baseFilename, dfn) | |
if self.backupCount > 0: | |
# find the oldest log file and delete it | |
#s = glob.glob(self.baseFilename + ".20*") | |
# if len(s) > self.backupCount: | |
# s.sort() | |
# os.remove(s[0]) | |
for s in self.getFilesToDelete(): | |
os.remove(s) | |
def doRollover(self): | |
if self.stream: | |
self.stream.close() | |
self.stream = None | |
try: | |
self.acquire_lock() | |
if self._lock_version == self._version: | |
self.rename_file() | |
os.write(self._lock_fd, struct.pack("!I", self._lock_version + 1)) | |
self._version += 1 | |
finally: | |
self.release_lock() | |
# print "%s -> %s" % (self.baseFilename, dfn) | |
self.mode = 'a' | |
self.stream = self._open() | |
currentTime = int(time.time()) | |
newRolloverAt = self.computeRollover(currentTime) | |
while newRolloverAt <= currentTime: | |
newRolloverAt = newRolloverAt + self.interval | |
# If DST changes and midnight or weekly rollover, adjust for this. | |
if (self.when == 'MIDNIGHT' or self.when.startswith('W')) and not self.utc: | |
dstNow = time.localtime(currentTime)[-1] | |
dstAtRollover = time.localtime(newRolloverAt)[-1] | |
if dstNow != dstAtRollover: | |
if not dstNow: # DST kicks in before next rollover, so we need to deduct an hour | |
newRolloverAt = newRolloverAt - 3600 | |
else: # DST bows out before next rollover, so we need to add an hour | |
newRolloverAt = newRolloverAt + 3600 | |
self.rolloverAt = newRolloverAt |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment