[Sugar-devel] [PATCH] Add cpu and memory resource indicator to frame
Anish Mangal
anishmangal2002 at gmail.com
Wed Jul 28 15:43:52 EDT 2010
Sorry! I thought the attachments would remain as is. I'll git send-email this.
On Thu, Jul 29, 2010 at 1:09 AM, Anish Mangal <anishmangal2002 at gmail.com> wrote:
> Thank you for reviewing this patch. However, after receiving feedback
> from Py. I've modified some of its functionality. The two patches
> attached implement that functionality. I've updated the parallel
> thread "[DESIGN] Displaying the current status of system resources
> (such as memory, cpu)" to augment further discussion on this.
>
> --
> Anish
>
> On Sat, Jul 10, 2010 at 3:09 PM, Marco Pesenti Gritti <marco at marcopg.org> wrote:
>> 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