Patchwork [bitbake-devel,1/1] monitordisk.py: monitor disks based on path

login
register
mail settings
Submitter Robert Yang
Date March 15, 2013, 7:42 a.m.
Message ID <3155e730627817a772d95ddab04372ff13c33b82.1363313983.git.liezhi.yang@windriver.com>
Download mbox | patch
Permalink /patch/46243/
State New
Headers show

Comments

Robert Yang - March 15, 2013, 7:42 a.m.
The previous monitor is based on the disk, and one disk only can have
one action, this limits its function, for example we set this in the
current local.conf:

BB_DISKMON_DIRS = "\
    STOPTASKS,${TMPDIR},1G,100K \
    STOPTASKS,${DL_DIR},1G,100K \
    STOPTASKS,${SSTATE_DIR},1G,100K \
    ABORT,${TMPDIR},100M,1K \
    ABORT,${DL_DIR},100M,1K \
    ABORT,${SSTATE_DIR},100GM,1K"

Before:
  * If TMPDIR, DL_DIR and SSTATE_DIR are on the same disk partition,
    only the last line "ABORT,${SSTATE_DIR},100GM,1K" works

  * If TMPDIR, DL_DIR and SSTATE_DIR are on the different disk partitions,
    only the last three lines (ABORT) work.

These are not what we expect, now:
  * We monitor the disk based on the path and action, so all the six lines
    will work no matter whether they are on the same disk partition or
    not.

  * The out put format will be:
    WARNING: The free space of /path/to/directory (device) is running low (XXGB left)

[YOCTO #3995]

Signed-off-by: Robert Yang <liezhi.yang@windriver.com>
---
 bitbake/lib/bb/monitordisk.py |   73 +++++++++++++++++++++++------------------
 1 files changed, 41 insertions(+), 32 deletions(-)

Patch

diff --git a/bitbake/lib/bb/monitordisk.py b/bitbake/lib/bb/monitordisk.py
index 1c1e614..a71dd9f 100644
--- a/bitbake/lib/bb/monitordisk.py
+++ b/bitbake/lib/bb/monitordisk.py
@@ -107,7 +107,7 @@  def getDiskData(BBDirs, configuration):
                 printErr("Invalid disk space value in BB_DISKMON_DIRS: %s" % pathSpaceInodeRe.group(3))
                 return None
         else:
-            # 0 means that it is not specified
+            # None means that it is not specified
             minSpace = None
 
         minInode = pathSpaceInodeRe.group(4)
@@ -117,7 +117,7 @@  def getDiskData(BBDirs, configuration):
                 printErr("Invalid inode value in BB_DISKMON_DIRS: %s" % pathSpaceInodeRe.group(4))
                 return None
         else:
-            # 0 means that it is not specified
+            # None means that it is not specified
             minInode = None
 
         if minSpace is None and minInode is None:
@@ -127,8 +127,9 @@  def getDiskData(BBDirs, configuration):
         # DL_DIR may not exist at the very beginning
         if not os.path.exists(path):
             bb.utils.mkdirhier(path)
-        mountedDev = getMountedDev(path)
-        devDict[mountedDev] = [action, path, minSpace, minInode]
+        dev = getMountedDev(path)
+        # Use path/action as the key
+        devDict[os.path.join(path, action)] = [dev, minSpace, minInode]
 
     return devDict
 
@@ -192,10 +193,10 @@  class diskMonitor:
                     # This is for STOPTASKS and ABORT, to avoid print the message repeatly
                     # during waiting the tasks to finish
                     self.checked = {}
-                    for dev in self.devDict:
-                        self.preFreeS[dev] = 0
-                        self.preFreeI[dev] = 0
-                        self.checked[dev] = False
+                    for k in self.devDict:
+                        self.preFreeS[k] = 0
+                        self.preFreeI[k] = 0
+                        self.checked[k] = False
                     if self.spaceInterval is None and self.inodeInterval is None:
                         self.enableMonitor = False
 
@@ -204,53 +205,61 @@  class diskMonitor:
         """ Take action for the monitor """
 
         if self.enableMonitor:
-            for dev in self.devDict:
-                st = os.statvfs(self.devDict[dev][1])
+            for k in self.devDict:
+                path = os.path.dirname(k)
+                action = os.path.basename(k)
+                dev = self.devDict[k][0]
+                minSpace = self.devDict[k][1]
+                minInode = self.devDict[k][2]
+
+                st = os.statvfs(path)
 
                 # The free space, float point number
                 freeSpace = st.f_bavail * st.f_frsize
 
-                if self.devDict[dev][2] and freeSpace < self.devDict[dev][2]:
+                if minSpace and freeSpace < minSpace:
                     # Always show warning, the self.checked would always be False if the action is WARN
-                    if self.preFreeS[dev] == 0 or self.preFreeS[dev] - freeSpace > self.spaceInterval and not self.checked[dev]:
-                        logger.warn("The free space of %s is running low (%.3fGB left)" % (dev, freeSpace / 1024 / 1024 / 1024.0))
-                        self.preFreeS[dev] = freeSpace
+                    if self.preFreeS[k] == 0 or self.preFreeS[k] - freeSpace > self.spaceInterval and not self.checked[k]:
+                        logger.warn("The free space of %s (%s) is running low (%.3fGB left)" % \
+                                (path, dev, freeSpace / 1024 / 1024 / 1024.0))
+                        self.preFreeS[k] = freeSpace
 
-                    if self.devDict[dev][0] == "STOPTASKS" and not self.checked[dev]:
+                    if action == "STOPTASKS" and not self.checked[k]:
                         logger.error("No new tasks can be excuted since the disk space monitor action is \"STOPTASKS\"!")
-                        self.checked[dev] = True
+                        self.checked[k] = True
                         rq.finish_runqueue(False)
-                        bb.event.fire(bb.event.DiskFull(dev, 'disk', freeSpace, self.devDict[dev][1]), self.configuration)
-                    elif self.devDict[dev][0] == "ABORT" and not self.checked[dev]:
+                        bb.event.fire(bb.event.DiskFull(dev, 'disk', freeSpace, path), self.configuration)
+                    elif action == "ABORT" and not self.checked[k]:
                         logger.error("Immediately abort since the disk space monitor action is \"ABORT\"!")
-                        self.checked[dev] = True
+                        self.checked[k] = True
                         rq.finish_runqueue(True)
-                        bb.event.fire(bb.event.DiskFull(dev, 'disk', freeSpace, self.devDict[dev][1]), self.configuration)
+                        bb.event.fire(bb.event.DiskFull(dev, 'disk', freeSpace, path), self.configuration)
 
                 # The free inodes, float point number
                 freeInode = st.f_favail
 
-                if self.devDict[dev][3] and freeInode < self.devDict[dev][3]:
+                if minInode and freeInode < minInode:
                     # Some fs formats' (e.g., btrfs) statvfs.f_files (inodes) is
                     # zero, this is a feature of the fs, we disable the inode
                     # checking for such a fs.
                     if st.f_files == 0:
-                        logger.warn("Inode check for %s is unavaliable, remove it from disk monitor" % dev)
-                        self.devDict[dev][3] = None
+                        logger.warn("Inode check for %s is unavaliable, will remove it from disk monitor" % path)
+                        minInode = None
                         continue
                     # Always show warning, the self.checked would always be False if the action is WARN
-                    if self.preFreeI[dev] == 0 or self.preFreeI[dev] - freeInode > self.inodeInterval and not self.checked[dev]:
-                        logger.warn("The free inode of %s is running low (%.3fK left)" % (dev, freeInode / 1024.0))
-                        self.preFreeI[dev] = freeInode
+                    if self.preFreeI[k] == 0 or self.preFreeI[k] - freeInode > self.inodeInterval and not self.checked[k]:
+                        logger.warn("The free inode of %s (%s) is running low (%.3fK left)" % \
+                                (path, dev, freeInode / 1024.0))
+                        self.preFreeI[k] = freeInode
 
-                    if self.devDict[dev][0]  == "STOPTASKS" and not self.checked[dev]:
+                    if action  == "STOPTASKS" and not self.checked[k]:
                         logger.error("No new tasks can be excuted since the disk space monitor action is \"STOPTASKS\"!")
-                        self.checked[dev] = True
+                        self.checked[k] = True
                         rq.finish_runqueue(False)
-                        bb.event.fire(bb.event.DiskFull(dev, 'inode', freeSpace, self.devDict[dev][1]), self.configuration)
-                    elif self.devDict[dev][0]  == "ABORT" and not self.checked[dev]:
+                        bb.event.fire(bb.event.DiskFull(dev, 'inode', freeInode, path), self.configuration)
+                    elif action  == "ABORT" and not self.checked[k]:
                         logger.error("Immediately abort since the disk space monitor action is \"ABORT\"!")
-                        self.checked[dev] = True
+                        self.checked[k] = True
                         rq.finish_runqueue(True)
-                        bb.event.fire(bb.event.DiskFull(dev, 'inode', freeSpace, self.devDict[dev][1]), self.configuration)
+                        bb.event.fire(bb.event.DiskFull(dev, 'inode', freeInode, path), self.configuration)
         return