Add support for newer process table format
This commit is contained in:
parent
f657ac5816
commit
9404c87519
@ -73,6 +73,37 @@
|
||||
/* empty - used to show sections for manually triggered OOMs */
|
||||
}
|
||||
|
||||
.js-pstable_sort_col0 {
|
||||
/* empty - used to sort process table */
|
||||
}
|
||||
.js-pstable_sort_col1 {
|
||||
/* empty - used to sort process table */
|
||||
}
|
||||
.js-pstable_sort_col2 {
|
||||
/* empty - used to sort process table */
|
||||
}
|
||||
.js-pstable_sort_col3 {
|
||||
/* empty - used to sort process table */
|
||||
}
|
||||
.js-pstable_sort_col4 {
|
||||
/* empty - used to sort process table */
|
||||
}
|
||||
.js-pstable_sort_col5 {
|
||||
/* empty - used to sort process table */
|
||||
}
|
||||
.js-pstable_sort_col6 {
|
||||
/* empty - used to sort process table */
|
||||
}
|
||||
.js-pstable_sort_col7 {
|
||||
/* empty - used to sort process table */
|
||||
}
|
||||
.js-pstable_sort_col8 {
|
||||
/* empty - used to sort process table */
|
||||
}
|
||||
.js-pstable_sort_col9 {
|
||||
/* empty - used to sort process table */
|
||||
}
|
||||
|
||||
.js-swap-active--show {
|
||||
/* empty - used to show if the swap space is activated */
|
||||
}
|
||||
@ -144,6 +175,9 @@
|
||||
.pstable__row-oom-score-adj--width {
|
||||
width: 16ch;
|
||||
}
|
||||
.pstable__row-notes--width {
|
||||
width: 20ch;
|
||||
}
|
||||
.pstable__row-sort--width {
|
||||
padding-left: unset;
|
||||
padding-right: unset;
|
||||
@ -749,51 +783,51 @@ window.onerror = function (msg, url, lineNo, columnNo, error) {
|
||||
<td></td>
|
||||
<td class="terminal " colspan="2">
|
||||
<table class="pstable__table--noborder">
|
||||
<thead>
|
||||
<thead id="pstable_header">
|
||||
<tr>
|
||||
<td class="pstable__row-numeric--width">pid
|
||||
<td class="pstable__row-numeric--width"><span>pid</span>
|
||||
<a class="pstable__row-sort--width" href="javascript:void(0);"
|
||||
id="pstable_sort_pid" onclick="OOMAnalyser.OOMDisplayInstance.sort_pstable('pid')"></a>
|
||||
id="js-pstable_sort_col0" onclick="OOMAnalyser.OOMDisplayInstance.sort_pstable(0)"></a>
|
||||
</td>
|
||||
<td class="pstable__row-numeric--width">uid
|
||||
<a class="pstable__row-sort--width" href="javascript:void(0);"
|
||||
id="pstable_sort_uid" onclick="OOMAnalyser.OOMDisplayInstance.sort_pstable('uid')"></a>
|
||||
id="js-pstable_sort_col1" onclick="OOMAnalyser.OOMDisplayInstance.sort_pstable(1)"></a>
|
||||
</td>
|
||||
<td class="pstable__row-numeric--width">tgid
|
||||
<a class="pstable__row-sort--width" href="javascript:void(0);"
|
||||
id="pstable_sort_tgid" onclick="OOMAnalyser.OOMDisplayInstance.sort_pstable('tgid')"></a>
|
||||
id="js-pstable_sort_col2" onclick="OOMAnalyser.OOMDisplayInstance.sort_pstable(2)"></a>
|
||||
</td>
|
||||
<td class="pstable__row-pages--width">total_vm
|
||||
<a class="pstable__row-sort--width" href="javascript:void(0);"
|
||||
id="pstable_sort_total_vm_pages" onclick="OOMAnalyser.OOMDisplayInstance.sort_pstable('total_vm_pages')"></a>
|
||||
id="js-pstable_sort_col3" onclick="OOMAnalyser.OOMDisplayInstance.sort_pstable(3)"></a>
|
||||
</td>
|
||||
<td class="pstable__row-pages--width">rss
|
||||
<a class="pstable__row-sort--width" href="javascript:void(0);"
|
||||
id="pstable_sort_rss_pages" onclick="OOMAnalyser.OOMDisplayInstance.sort_pstable('rss_pages')"></a>
|
||||
id="js-pstable_sort_col4" onclick="OOMAnalyser.OOMDisplayInstance.sort_pstable(4)"></a>
|
||||
</td>
|
||||
<td class="pstable__row-pages--width">nr_ptes
|
||||
<a class="pstable__row-sort--width" href="javascript:void(0);"
|
||||
id="pstable_sort_nr_ptes_pages" onclick="OOMAnalyser.OOMDisplayInstance.sort_pstable('nr_ptes_pages')"></a>
|
||||
id="js-pstable_sort_col5" onclick="OOMAnalyser.OOMDisplayInstance.sort_pstable(5)"></a>
|
||||
</td>
|
||||
<td class="pstable__row-pages--width">swapents
|
||||
<a class="pstable__row-sort--width" href="javascript:void(0);"
|
||||
id="pstable_sort_swapents_pages" onclick="OOMAnalyser.OOMDisplayInstance.sort_pstable('swapents_pages')"></a>
|
||||
id="js-pstable_sort_col6" onclick="OOMAnalyser.OOMDisplayInstance.sort_pstable(6)"></a>
|
||||
</td>
|
||||
<td class="pstable__row-oom-score-adj--width">oom_score_adj
|
||||
<a class="pstable__row-sort--width" href="javascript:void(0);"
|
||||
id="pstable_sort_oom_score_adj" onclick="OOMAnalyser.OOMDisplayInstance.sort_pstable('oom_score_adj')"></a>
|
||||
id="js-pstable_sort_col7" onclick="OOMAnalyser.OOMDisplayInstance.sort_pstable(7)"></a>
|
||||
</td>
|
||||
<td>name
|
||||
<td class="pstable__row-notes--width">name
|
||||
<a class="pstable__row-sort--width" href="javascript:void(0);"
|
||||
id="pstable_sort_name" onclick="OOMAnalyser.OOMDisplayInstance.sort_pstable('name')"></a>
|
||||
id="js-pstable_sort_col8" onclick="OOMAnalyser.OOMDisplayInstance.sort_pstable(8)"></a>
|
||||
</td>
|
||||
<td>notes
|
||||
<td class="pstable__row-notes--width">notes
|
||||
<a class="pstable__row-sort--width" href="javascript:void(0);"
|
||||
id="pstable_sort_notes" onclick="OOMAnalyser.OOMDisplayInstance.sort_pstable('notes')"></a>
|
||||
id="js-pstable_sort_col9" onclick="OOMAnalyser.OOMDisplayInstance.sort_pstable(9)"></a>
|
||||
</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="process_table">
|
||||
<tbody id="pstable_content">
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
@ -898,6 +932,7 @@ window.onerror = function (msg, url, lineNo, columnNo, error) {
|
||||
<li>Add support for systems w/o swap (suggested by Mikko Rantalainen)</li>
|
||||
<li>Add support for newer kernels (suggested by Mikko Rantalainen)</li>
|
||||
<li>Add support for journalctl output (suggested by Mikko Rantalainen)</li>
|
||||
<li>Add support for newer process table format</li>
|
||||
<li>...</li>
|
||||
</ol>
|
||||
|
||||
|
227
OOMAnalyser.py
227
OOMAnalyser.py
@ -347,15 +347,31 @@ class BaseKernelConfig:
|
||||
(see https://github.com/torvalds/linux/commit/e67d4ca79aaf9d13a00d229b1b1c96b86828e8ba#diff-020720d0699e3ae1afb6fcd815ca8500)
|
||||
"""
|
||||
|
||||
ps_table_items = ['pid', 'uid', 'tgid', 'total_vm_pages', 'rss_pages', 'nr_ptes_pages', 'swapents_pages',
|
||||
'oom_score_adj']
|
||||
pstable_items = ['pid', 'uid', 'tgid', 'total_vm_pages', 'rss_pages', 'nr_ptes_pages', 'swapents_pages',
|
||||
'oom_score_adj', 'name', 'notes']
|
||||
"""Elements of the process table"""
|
||||
|
||||
pstable_html = ['PID', 'UID', 'TGID', 'Total VM', 'RSS', 'Page Table Entries', 'Swap Entries', 'OOM Adjustment',
|
||||
'Name', 'Notes']
|
||||
"""
|
||||
Headings of the process table columns
|
||||
"""
|
||||
|
||||
pstable_non_ints = ['pid', 'name', 'notes']
|
||||
"""Columns that are not converted to an integer"""
|
||||
|
||||
REC_PROCESS_LINE = re.compile(
|
||||
r'^\[(?P<pid>[ \d]+)\]\s+(?P<uid>\d+)\s+(?P<tgid>\d+)\s+(?P<total_vm_pages>\d+)\s+(?P<rss_pages>\d+)\s+'
|
||||
r'(?P<nr_ptes_pages>\d+)\s+(?P<swapents_pages>\d+)\s+(?P<oom_score_adj>-?\d+)\s+(?P<name>.+)\s*')
|
||||
"""Match content of process table"""
|
||||
|
||||
pstable_start = '[ pid ]'
|
||||
"""
|
||||
Pattern to find the start of the process table
|
||||
|
||||
:type: str
|
||||
"""
|
||||
|
||||
rec_version4kconfig = re.compile('.+')
|
||||
"""RE to match kernel version to kernel configuration"""
|
||||
|
||||
@ -416,7 +432,32 @@ class KernelConfig_4_9(KernelConfig_4_6):
|
||||
self.EXTRACT_PATTERN.update(self.EXTRACT_PATTERN_OVERLAY_49)
|
||||
|
||||
|
||||
class KernelConfig_5_0(KernelConfig_4_9):
|
||||
class KernelConfig_4_15(KernelConfig_4_9):
|
||||
# Support changes:
|
||||
# * mm: consolidate page table accounting (af5b0f6a09e42c9f4fa87735f2a366748767b686)
|
||||
|
||||
# nr_ptes -> pgtables_bytes
|
||||
# pr_info("[ pid ] uid tgid total_vm rss nr_ptes nr_pmds nr_puds swapents oom_score_adj name\n");
|
||||
# pr_info("[ pid ] uid tgid total_vm rss pgtables_bytes swapents oom_score_adj name\n");
|
||||
REC_PROCESS_LINE = re.compile(
|
||||
r'^\[(?P<pid>[ \d]+)\]\s+(?P<uid>\d+)\s+(?P<tgid>\d+)\s+(?P<total_vm_pages>\d+)\s+(?P<rss_pages>\d+)\s+'
|
||||
r'(?P<pgtables_bytes>\d+)\s+(?P<swapents_pages>\d+)\s+(?P<oom_score_adj>-?\d+)\s+(?P<name>.+)\s*')
|
||||
|
||||
pstable_items = ['pid', 'uid', 'tgid', 'total_vm_pages', 'rss_pages', 'pgtables_bytes', 'swapents_pages',
|
||||
'oom_score_adj', 'name', 'notes']
|
||||
|
||||
pstable_html = ['PID', 'UID', 'TGID', 'Total VM', 'RSS', 'Page Table Bytes', 'Swap Entries Pages',
|
||||
'OOM Adjustment', 'Name', 'Notes']
|
||||
|
||||
|
||||
class KernelConfig_4_19(KernelConfig_4_15):
|
||||
# Support changes:
|
||||
# * mm, oom: describe task memory unit, larger PID pad (c3b78b11efbb2865433abf9d22c004ffe4a73f5c)
|
||||
|
||||
pstable_start = '[ pid ]'
|
||||
|
||||
|
||||
class KernelConfig_5_0(KernelConfig_4_19):
|
||||
# Support changes:
|
||||
# * "mm, oom: reorganize the oom report in dump_header" (ef8444ea01d7442652f8e1b8a8b94278cb57eafd)
|
||||
|
||||
@ -488,6 +529,8 @@ class KernelConfigRhel7(BaseKernelConfig):
|
||||
AllKernelConfigs = [
|
||||
KernelConfig_5_8(),
|
||||
KernelConfig_5_0(),
|
||||
KernelConfig_4_15(),
|
||||
KernelConfig_4_19(),
|
||||
KernelConfig_4_9(),
|
||||
KernelConfig_4_6(),
|
||||
KernelConfigRhel7(),
|
||||
@ -931,21 +974,24 @@ class OOMAnalyser:
|
||||
call_trace += "{}\n".format(line.strip())
|
||||
self.oom_result.details['call_trace'] = call_trace
|
||||
|
||||
# extract process table
|
||||
self.oom_result.details['_ps'] = {}
|
||||
self.oom_entity.find_text('[ pid ]')
|
||||
self._extract_pstable()
|
||||
|
||||
def _extract_pstable(self):
|
||||
"""Extract process table"""
|
||||
self.oom_result.details['_pstable'] = {}
|
||||
self.oom_entity.find_text(self.oom_result.kconfig.pstable_start)
|
||||
for line in self.oom_entity:
|
||||
if not line.startswith('['):
|
||||
break
|
||||
if line.startswith('[ pid ]'):
|
||||
if line.startswith(self.oom_result.kconfig.pstable_start):
|
||||
continue
|
||||
match = self.oom_result.kconfig.REC_PROCESS_LINE.match(line)
|
||||
if match:
|
||||
details = match.groupdict()
|
||||
details['notes'] = ''
|
||||
pid = details.pop('pid')
|
||||
self.oom_result.details['_ps'][pid] = {}
|
||||
self.oom_result.details['_ps'][pid].update(details)
|
||||
self.oom_result.details['_pstable'][pid] = {}
|
||||
self.oom_result.details['_pstable'][pid].update(details)
|
||||
|
||||
def _hex2flags(self, hexvalue, flag_definition):
|
||||
"""\
|
||||
@ -1025,7 +1071,7 @@ class OOMAnalyser:
|
||||
if self.oom_result.details[item] is None:
|
||||
self.oom_result.details[item] = '<not found>'
|
||||
continue
|
||||
if item.endswith('_kb') or item.endswith('_pages') or item.endswith('_pid') or \
|
||||
if item.endswith('_bytes') or item.endswith('_kb') or item.endswith('_pages') or item.endswith('_pid') or \
|
||||
item in ['killed_proc_score', 'trigger_proc_order', 'trigger_proc_oomscore']:
|
||||
try:
|
||||
self.oom_result.details[item] = int(self.oom_result.details[item])
|
||||
@ -1034,9 +1080,9 @@ class OOMAnalyser:
|
||||
|
||||
# __pragma__ ('nojsiter')
|
||||
|
||||
def _convert_numeric_process_values_to_integer(self):
|
||||
def _convert_pstable_values_to_integer(self):
|
||||
"""Convert numeric values in process table to integer values"""
|
||||
ps = self.oom_result.details['_ps']
|
||||
ps = self.oom_result.details['_pstable']
|
||||
ps_index = []
|
||||
# TODO Check if transcrypt issue: pragma jsiter for the whole block "for pid_str in ps: ..."
|
||||
# sets item in "for item in ['uid',..." to 0 instead of 'uid'
|
||||
@ -1044,13 +1090,17 @@ class OOMAnalyser:
|
||||
for pid_str in ps.keys():
|
||||
converted = {}
|
||||
process = ps[pid_str]
|
||||
for item in self.oom_result.kconfig.ps_table_items:
|
||||
if item == 'pid':
|
||||
for item in self.oom_result.kconfig.pstable_items:
|
||||
if item in self.oom_result.kconfig.pstable_non_ints:
|
||||
continue
|
||||
try:
|
||||
converted[item] = int(process[item])
|
||||
except:
|
||||
error('Converting process parameter "{}={}" to integer failed'.format(item, process[item]))
|
||||
if item not in process:
|
||||
pitem = '<not in process table>'
|
||||
else:
|
||||
pitem = process[item]
|
||||
error('Converting process parameter "{}={}" to integer failed'.format(item, pitem))
|
||||
|
||||
converted['name'] = process['name']
|
||||
converted['notes'] = process['notes']
|
||||
@ -1060,7 +1110,7 @@ class OOMAnalyser:
|
||||
ps_index.append(pid_int)
|
||||
|
||||
ps_index.sort(key=int)
|
||||
self.oom_result.details['_ps_index'] = ps_index
|
||||
self.oom_result.details['_pstable_index'] = ps_index
|
||||
|
||||
def _calc_pstable_values(self):
|
||||
"""Set additional notes to processes listed in the process table"""
|
||||
@ -1068,12 +1118,12 @@ class OOMAnalyser:
|
||||
kpid = self.oom_result.details['killed_proc_pid']
|
||||
|
||||
# sometimes the trigger process isn't part of the process table
|
||||
if tpid in self.oom_result.details['_ps']:
|
||||
self.oom_result.details['_ps'][tpid]['notes'] = 'trigger process'
|
||||
if tpid in self.oom_result.details['_pstable']:
|
||||
self.oom_result.details['_pstable'][tpid]['notes'] = 'trigger process'
|
||||
|
||||
# assume the killed process may also not part of the process table
|
||||
if kpid in self.oom_result.details['_ps']:
|
||||
self.oom_result.details['_ps'][kpid]['notes'] = 'killed process'
|
||||
if kpid in self.oom_result.details['_pstable']:
|
||||
self.oom_result.details['_pstable'][kpid]['notes'] = 'killed process'
|
||||
|
||||
def _calc_trigger_process_values(self):
|
||||
"""Calculate all values related with the trigger process"""
|
||||
@ -1138,8 +1188,8 @@ class OOMAnalyser:
|
||||
else:
|
||||
self.oom_result.details['system_total_ramswap_kb'] = self.oom_result.details['system_total_ram_kb']
|
||||
total_rss_pages = 0
|
||||
for pid in self.oom_result.details['_ps'].keys():
|
||||
total_rss_pages += self.oom_result.details['_ps'][pid]['rss_pages']
|
||||
for pid in self.oom_result.details['_pstable'].keys():
|
||||
total_rss_pages += self.oom_result.details['_pstable'][pid]['rss_pages']
|
||||
self.oom_result.details['system_total_ram_used_kb'] = total_rss_pages * self.oom_result.details['page_size_kb']
|
||||
|
||||
self.oom_result.details['system_total_used_percent'] = int(100 *
|
||||
@ -1176,7 +1226,7 @@ class OOMAnalyser:
|
||||
@see: self.details
|
||||
"""
|
||||
self._convert_numeric_results_to_integer()
|
||||
self._convert_numeric_process_values_to_integer()
|
||||
self._convert_pstable_values_to_integer()
|
||||
self._calc_pstable_values()
|
||||
|
||||
self._determinate_platform_and_distribution()
|
||||
@ -1442,8 +1492,12 @@ oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=/,mems_allowed=0,glob
|
||||
Out of memory: Killed process 651 (unattended-upgr) total-vm:108020kB, anon-rss:8380kB, file-rss:12548kB, shmem-rss:0kB, UID:0 pgtables:104kB oom_score_adj:0
|
||||
'''
|
||||
|
||||
sorted_column = None
|
||||
"""Processes will sort by values in this column"""
|
||||
sorted_column_number = None
|
||||
"""
|
||||
Processes will sort by values in this column
|
||||
|
||||
@type: int
|
||||
"""
|
||||
|
||||
sort_order = None
|
||||
"""Sort order for process values"""
|
||||
@ -1534,6 +1588,12 @@ Out of memory: Killed process 651 (unattended-upgr) total-vm:108020kB, anon-rss:
|
||||
else:
|
||||
content = "{} pages".format(content)
|
||||
|
||||
if item.endswith('_bytes') and isinstance(content, int):
|
||||
if content == 1:
|
||||
content = "{} Byte".format(content)
|
||||
else:
|
||||
content = "{} Bytes".format(content)
|
||||
|
||||
if item.endswith('_kb') and isinstance(content, int):
|
||||
if content == 1:
|
||||
content = "{} kByte".format(content)
|
||||
@ -1568,21 +1628,41 @@ Out of memory: Killed process 651 (unattended-upgr) total-vm:108020kB, anon-rss:
|
||||
|
||||
toc_content.innerHTML = new_toc
|
||||
|
||||
def update_process_table(self):
|
||||
def pstable_fill_HTML(self):
|
||||
"""
|
||||
Re-create the process table with additional information
|
||||
Create the process table with additional information
|
||||
"""
|
||||
new_table = ''
|
||||
table_content = document.getElementById('process_table')
|
||||
# update table heading
|
||||
for i, element in enumerate(document.querySelectorAll('#pstable_header > tr > td')):
|
||||
element.classList.remove('pstable__row-pages--width', 'pstable__row-numeric--width',
|
||||
'pstable__row-oom-score-adj--width')
|
||||
|
||||
for pid in self.oom_result.details['_ps_index']:
|
||||
key = self.oom_result.kconfig.pstable_items[i]
|
||||
if key in ['notes', 'names']:
|
||||
klass = 'pstable__row-notes--width'
|
||||
elif key == 'oom_score_adj':
|
||||
klass = 'pstable__row-oom-score-adj--width'
|
||||
elif key.endswith('_bytes') or key.endswith('_kb') or key.endswith('_pages'):
|
||||
klass = 'pstable__row-pages--width'
|
||||
else:
|
||||
klass = "pstable__row-numeric--width"
|
||||
element.firstChild.textContent = self.oom_result.kconfig.pstable_html[i]
|
||||
element.classList.add(klass)
|
||||
|
||||
# create new table
|
||||
new_table = ''
|
||||
table_content = document.getElementById('pstable_content')
|
||||
for pid in self.oom_result.details['_pstable_index']:
|
||||
if pid == self.oom_result.details['trigger_proc_pid']:
|
||||
css_class = 'class="js-pstable__triggerproc--bgcolor"'
|
||||
elif pid == self.oom_result.details['killed_proc_pid']:
|
||||
css_class = 'class="js-pstable__killedproc--bgcolor"'
|
||||
else:
|
||||
css_class = ''
|
||||
process = self.oom_result.details['_ps'][pid]
|
||||
process = self.oom_result.details['_pstable'][pid]
|
||||
fmt_list = [process[i] for i in self.oom_result.kconfig.pstable_items if not i == 'pid']
|
||||
fmt_list.insert(0, css_class)
|
||||
fmt_list.insert(1, pid)
|
||||
line = """
|
||||
<tr {}>
|
||||
<td>{}</td>
|
||||
@ -1596,32 +1676,22 @@ Out of memory: Killed process 651 (unattended-upgr) total-vm:108020kB, anon-rss:
|
||||
<td>{}</td>
|
||||
<td>{}</td>
|
||||
</tr>
|
||||
""".format(css_class, pid, process['uid'], process['tgid'], process['total_vm_pages'], process['rss_pages'],
|
||||
process['nr_ptes_pages'], process['swapents_pages'], process['oom_score_adj'], process['name'],
|
||||
process['notes'])
|
||||
""".format(*fmt_list)
|
||||
new_table += line
|
||||
|
||||
table_content.innerHTML = new_table
|
||||
|
||||
self.set_sort_triangle()
|
||||
|
||||
def set_sort_triangle(self):
|
||||
def pstable_set_sort_triangle(self):
|
||||
"""Set the sorting symbols for all columns in the process table"""
|
||||
# TODO Check operator overloading
|
||||
# Operator overloading (Pragma opov) does not work in this context.
|
||||
# self.oom_result.kconfig.ps_table_items + ['notes'] will compile to a string
|
||||
# "pid,uid,tgid,total_vm_pages,rss_pages,nr_ptes_pages,swapents_pages,oom_score_adjNotes" and not to an
|
||||
# array
|
||||
ps_table_and_notes = self.oom_result.kconfig.ps_table_items[:]
|
||||
ps_table_and_notes.append('notes')
|
||||
for column_name in ps_table_and_notes:
|
||||
element_id = "pstable_sort_{}".format(column_name)
|
||||
for column_name in self.oom_result.kconfig.pstable_items:
|
||||
column_number = self.oom_result.kconfig.pstable_items.index(column_name)
|
||||
element_id = "js-pstable_sort_col{}".format(column_number)
|
||||
element = document.getElementById(element_id)
|
||||
if not element:
|
||||
internal_error('Missing id "{}" in process table.'.format(element_id))
|
||||
continue
|
||||
|
||||
if column_name == self.sorted_column:
|
||||
if column_number == self.sorted_column_number:
|
||||
if self.sort_order == 'descending':
|
||||
element.innerHTML = self.svg_array_down
|
||||
else:
|
||||
@ -1645,22 +1715,31 @@ Out of memory: Killed process 651 (unattended-upgr) total-vm:108020kB, anon-rss:
|
||||
while element.firstChild:
|
||||
element.removeChild(element.firstChild)
|
||||
|
||||
# clear process table
|
||||
element = document.getElementById('process_table')
|
||||
while element.firstChild:
|
||||
element.removeChild(element.firstChild)
|
||||
|
||||
# reset sort triangles
|
||||
self.sorted_column = None
|
||||
self.sort_order = None
|
||||
self.set_sort_triangle()
|
||||
|
||||
# remove svg charts
|
||||
for element_id in ('svg_swap', 'svg_ram'):
|
||||
element = document.getElementById(element_id)
|
||||
while element.firstChild:
|
||||
element.removeChild(element.firstChild)
|
||||
|
||||
self._clear_pstable()
|
||||
|
||||
def _clear_pstable(self):
|
||||
"""Clear process table"""
|
||||
element = document.getElementById('pstable_content')
|
||||
while element.firstChild:
|
||||
element.removeChild(element.firstChild)
|
||||
|
||||
# reset sort triangles
|
||||
self.sorted_column_number = None
|
||||
self.sort_order = None
|
||||
self.pstable_set_sort_triangle()
|
||||
|
||||
# reset table heading
|
||||
for i, element in enumerate(document.querySelectorAll('#pstable_header > tr > td')):
|
||||
element.classList.remove('pstable__row-pages--width', 'pstable__row-numeric--width',
|
||||
'pstable__row-oom-score-adj--width')
|
||||
element.firstChild.textContent = "col {}".format(i + 1)
|
||||
|
||||
def svg_create_element(self, height, width, css_class):
|
||||
"""Return an empty SVG element"""
|
||||
svg = document.createElementNS(self.svg_namespace, 'svg')
|
||||
@ -1832,7 +1911,8 @@ Out of memory: Killed process 651 (unattended-upgr) total-vm:108020kB, anon-rss:
|
||||
hide_elements('.js-killed-proc-score--show')
|
||||
|
||||
# generate process table
|
||||
self.update_process_table()
|
||||
self.pstable_fill_HTML()
|
||||
self.pstable_set_sort_triangle()
|
||||
|
||||
# show/hide swap space
|
||||
if self.oom_result.swap_active:
|
||||
@ -1883,23 +1963,28 @@ Out of memory: Killed process 651 (unattended-upgr) total-vm:108020kB, anon-rss:
|
||||
element.textContent = self.oom_result.oom_text
|
||||
self.toggle_oom(show=False)
|
||||
|
||||
def sort_pstable(self, column_name):
|
||||
"""Sort process table by the values in the given column"""
|
||||
def sort_pstable(self, column_number):
|
||||
"""
|
||||
Sort process table by values
|
||||
|
||||
:param int column_number: Number of column to sort
|
||||
"""
|
||||
# TODO Check operator overloading
|
||||
# Operator overloading (Pragma opov) does not work in this context.
|
||||
# self.oom_result.kconfig.ps_table_items + ['notes'] will compile to a string
|
||||
# self.oom_result.kconfig.pstable_items + ['notes'] will compile to a string
|
||||
# "pid,uid,tgid,total_vm_pages,rss_pages,nr_ptes_pages,swapents_pages,oom_score_adjNotes" and not to an
|
||||
# array
|
||||
ps_table_and_notes = self.oom_result.kconfig.ps_table_items[:]
|
||||
ps_table_and_notes = self.oom_result.kconfig.pstable_items[:]
|
||||
ps_table_and_notes.append('notes')
|
||||
column_name = ps_table_and_notes[column_number]
|
||||
if column_name not in ps_table_and_notes:
|
||||
internal_error('Can not sort process table with an unknown column name "{}"'.format(column_name))
|
||||
return
|
||||
|
||||
# reset sort order if the column has changes
|
||||
if column_name != self.sorted_column:
|
||||
if column_number != self.sorted_column_number:
|
||||
self.sort_order = None
|
||||
self.sorted_column = column_name
|
||||
self.sorted_column_number = column_number
|
||||
|
||||
if not self.sort_order or self.sort_order == 'descending':
|
||||
self.sort_order = 'ascending'
|
||||
@ -1908,19 +1993,17 @@ Out of memory: Killed process 651 (unattended-upgr) total-vm:108020kB, anon-rss:
|
||||
self.sort_order = 'descending'
|
||||
self.sort_psindex_by_column(column_name, True)
|
||||
|
||||
self.sorted_column = column_name
|
||||
|
||||
self.update_process_table()
|
||||
self.pstable_fill_HTML()
|
||||
self.pstable_set_sort_triangle()
|
||||
|
||||
def sort_psindex_by_column(self, column_name, reverse=False):
|
||||
"""
|
||||
Sort the pid list '_ps_index' based on the values in the process dict '_ps'.
|
||||
Sort the pid list '_pstable_index' based on the values in the process dict '_pstable'.
|
||||
|
||||
Is uses bubble sort with all disadvantages but just a few lines of code
|
||||
"""
|
||||
|
||||
ps = self.oom_result.details['_ps']
|
||||
ps_index = self.oom_result.details['_ps_index']
|
||||
ps = self.oom_result.details['_pstable']
|
||||
ps_index = self.oom_result.details['_pstable_index']
|
||||
|
||||
def getvalue(column, pos):
|
||||
if column == 'pid':
|
||||
@ -1928,7 +2011,7 @@ Out of memory: Killed process 651 (unattended-upgr) total-vm:108020kB, anon-rss:
|
||||
else:
|
||||
value = ps[ps_index[pos]][column]
|
||||
# JS sorts alphanumeric by default, convert values explicit to integers to sort numerically
|
||||
if column not in ['name', 'notes'] and value is not js_undefined:
|
||||
if column not in self.oom_result.kconfig.pstable_non_ints and value is not js_undefined:
|
||||
value = int(value)
|
||||
return value
|
||||
|
||||
|
6
test.py
6
test.py
@ -199,6 +199,9 @@ class TestInBrowser(TestBase):
|
||||
self.assertTrue('OOM killer was automatically triggered' in explanation.text,
|
||||
'Missing text "OOM killer was automatically triggered"')
|
||||
|
||||
head = self.driver.find_element_by_id('pstable_header')
|
||||
self.assertTrue('Page Table Entries' in head.text, 'Missing column head line "Page Table Entries"')
|
||||
|
||||
self.check_swap_active()
|
||||
|
||||
def check_results_ubuntu2110(self):
|
||||
@ -216,6 +219,9 @@ class TestInBrowser(TestBase):
|
||||
self.assertFalse('with an OOM score of' in explanation.text,
|
||||
'No OOM score but text "with an OOM score of"')
|
||||
|
||||
head = self.driver.find_element_by_id('pstable_header')
|
||||
self.assertTrue('Page Table Bytes' in head.text, 'Missing column head line "Page Table Bytes"')
|
||||
|
||||
self.check_swap_inactive()
|
||||
|
||||
def check_swap_inactive(self):
|
||||
|
Loading…
Reference in New Issue
Block a user