[Sugar-devel] [PATCH] Add cpu and memory resource indicator to frame

Marco Pesenti Gritti marco at marcopg.org
Sat Jul 10 05:39:02 EDT 2010


On 10 Jul 2010, at 08:43, Anish Mangal <anishmangal2002 at gmail.com> wrote:
>> diff --git a/extensions/deviceicon/resources.py b/extensions/deviceicon/resources.py
>> new file mode 100644
>> index 0000000..7503bef
>> --- /dev/null
>> +++ b/extensions/deviceicon/resources.py
>> @@ -0,0 +1,188 @@
>> +# Copyright (C) Anish Mangal <anishmangal2002 at gmail.com>
>> +#
>> +# This program is free software; you can redistribute it and/or modify
>> +# it under the terms of the GNU General Public License as published by
>> +# the Free Software Foundation; either version 2 of the License, or
>> +# (at your option) any later version.
>> +#
>> +# This program is distributed in the hope that it will be useful,
>> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> +# GNU General Public License for more details.
>> +#
>> +# You should have received a copy of the GNU General Public License
>> +# along with this program; if not, write to the Free Software
>> +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
>> +
>> +from gettext import gettext as _
>> +import logging
>> +import os
>> +
>> +import gobject
>> +import gtk
>> +import gconf
>> +
>> +from sugar.graphics.tray import TrayIcon
>> +from sugar.graphics.xocolor import XoColor
>> +from sugar.graphics.palette import Palette
>> +from sugar.graphics import style
>> +
>> +from jarabe.frame.frameinvoker import FrameWidgetInvoker
>> +
>> +class DeviceView(TrayIcon):
>> +
>> +    FRAME_POSITION_RELATIVE = 500
>> +
>> +    def __init__(self):
>> +        client = gconf.client_get_default()
>> +        color = XoColor(client.get_string('/desktop/sugar/user/color'))
>> +        TrayIcon.__init__(self, icon_name='computer', xo_color=color)
>> +        self.set_palette_invoker(FrameWidgetInvoker(self))
>> +
>> +    def create_palette(self):
>> +        palette = ResourcePalette(_('System resources'))
>> +        palette.set_group_id('frame')
>> +        return palette
>> +
>> +class ResourcePalette(Palette):
>> +
>> +    def __init__(self, primary_text):
>> +        Palette.__init__(self, label=primary_text)
>> +
>> +        self._popup_cb_id = self.connect('popup', self._popup_cb)
>> +        self._popdown_cb_id = self.connect('popdown', self._popdown_cb)
>> +
>> +        self.vbox = gtk.VBox()
>> +        self.set_content(self.vbox)
>> +
>> +        self._cpu_text = gtk.Label()
>> +        self.vbox.pack_start(self._cpu_text, padding=style.DEFAULT_PADDING)
>> +        self._cpu_text.show()
>> +
>> +        self._cpu_bar = gtk.ProgressBar()
>> +        self._cpu_bar.set_size_request(
>> +            style.zoom(style.GRID_CELL_SIZE * 4), -1)
>> +        self.vbox.pack_start(self._cpu_bar, padding=style.DEFAULT_PADDING)
>> +        self._cpu_bar.show()
>> +
>> +        self._memory_text = gtk.Label()
>> +        self.vbox.pack_start(self._memory_text, padding=style.DEFAULT_PADDING)
>> +        self._memory_text.show()
>> +
>> +        self._memory_bar = gtk.ProgressBar()
>> +        self._memory_bar.set_size_request(
>> +            style.zoom(style.GRID_CELL_SIZE * 4), -1)
>> +        self.vbox.pack_start(self._memory_bar, padding=style.DEFAULT_PADDING)
>> +        self._memory_bar.show()
>> +
>> +        self.vbox.show()
>> +
>> +        try:
>> +            self._cpu_times = self._get_cpu_times_list()
>> +        except Exception:
>> +            logging.exception('An error ocurred while attempting to '
>> +                'read /proc/stat')

Which exceptions do you expect to happen and in which situations? Catch all exceptions are generally a bad idea.


>> +            self._remove_callbacks()
>> +
>> +    def _get_cpu_times_list(self):
>> +        """Return various cpu times as read from /proc/stat
>> +
>> +        This method returns the following cpu times measured
>> +        in jiffies (1/100 of a second for x86 systems)
>> +        as an ordered list of numbers - [user, nice,
>> +        system, idle, iowait] where,
>> +
>> +        user: normal processes executing in user mode
>> +        nice: niced processes executing in user mode
>> +        system: processes executing in kernel mode
>> +        idle: twiddling thumbs
>> +        iowait: waiting for I/O to complete
>> +
>> +        Note: For systems having 2 or more CPU's, the above
>> +        numbers would be the cumulative sum of these times
>> +        for all CPU's present in the system.
>> +
>> +        """
>> +        return [int(count)
>> +           for count in file('/proc/stat').readline().split()[1:6]]
>> +
>> +    def _percentage_cpu_available(self):
>> +        """
>> +        Return free CPU resources as a percentage
>> +
>> +        """
>> +        _cpu_times_new = self._get_cpu_times_list()
>> +        _cpu_times_current = [(new - old)
>> +            for new, old in zip(_cpu_times_new, self._cpu_times)]
>> +        user, nice, system, idle, iowait = _cpu_times_current
>> +        cpu_free = (idle + iowait) * 100.0 / sum(_cpu_times_current)
>> +        self._cpu_times = self._get_cpu_times_list()
>> +        return cpu_free
>> +
>> +    def _percentage_memory_available(self):
>> +        """
>> +        Return free memory as a percentage
>> +
>> +        """
>> +        for line in file('/proc/meminfo'):
>> +            name, value, unit = line.split()[:3]
>> +            if 'MemTotal:' == name:
>> +                total = int(value)
>> +            elif 'MemFree:' == name:
>> +                free = int(value)
>> +            elif 'Buffers:' == name:
>> +                buffers = int(value)
>> +            elif 'Cached:' == name:
>> +                cached = int(value)
>> +            elif 'Active:' == name:
>> +                break
>> +        return (free + buffers + cached) * 100.0 / total
>> +
>> +    def __timer_cb(self):
>> +        try:
>> +            cpu_free = self._percentage_cpu_available()
>> +            memory_free = self._percentage_memory_available()
>> +            self._cpu_text.set_label(_('CPU free: %d%%' % cpu_free))
>> +            self._cpu_bar.set_fraction(cpu_free/100.0)

Space around the operator

>> +            self._memory_text.set_label(_('Memory free: %d%%' % memory_free))
>> +            self._memory_bar.set_fraction(memory_free/100.0)

Same


>> +            return True
>> +        except Exception:
>> +            logging.exception('An error ocurred while trying to '
>> +                'retrieve resource usage statistics')
>> +            self._remove_callbacks()
>> +            return False

Same here. Also the UI code should be moved outside the try so that we don't cover errors in it.

>> 
>> +    def _remove_callbacks(self):
>> +        """
>> +        Stop computing usage statistics and display and error message
>> +        since we've hit an exception.
>> +
>> +        """
>> +        self.disconnect(self._popup_cb_id)
>> +        self.disconnect(self._popdown_cb_id)
>> +
>> +        # Use the existing _cpu_text label to display the error. Remove
>> +        # everything else.
>> +        self._cpu_text.set_size_request(
>> +            style.zoom(style.GRID_CELL_SIZE * 4), -1)
>> +        self._cpu_text.set_line_wrap(True)
>> +        self._cpu_text.set_text(_('Cannot compute CPU and memory usage '
>> +            'statistics!'))
>> +        self.vbox.remove(self._cpu_bar)
>> +        self.vbox.remove(self._memory_text)
>> +        self.vbox.remove(self._memory_bar)

This method does a lot more than disconnecting callbacks. The naming should reflect that or the method should be split.

Thanks!
Marco


More information about the Sugar-devel mailing list