???<!-- GIF89;a -->
123123123123
.....................................................................................................................................???<!-- GIF89;a -->
123123123123
.....................................................................................................................................3
bfZ<              
   @   s  d dl mZ d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dl	Z	d dl
mZ ejjdZyd dlmZ e ZW n   dZY nX dZe se red ed	 esed
 esed ejd d dlmZmZ d dlmZmZmZmZ d dlmZmZ G dd de Z!G dd de!Z"dZ#dZ$dZ%dZ&dZ'G dd de Z(dd Z)dd Z*dd Z+G dd de!Z,G d d! d!e!Z-G d"d# d#e!Z.d$d% Z/dS )&    )print_functionN)cmdlinez/proc/self/io)VmStatFTz<Could not run iotop as some of the requirements are not met:z- Linux >= 2.6.20 withz~  - I/O accounting support (CONFIG_TASKSTATS, CONFIG_TASK_DELAY_ACCT, CONFIG_TASK_IO_ACCOUNTING, kernel.task_delayacct sysctl)z0  - VM event counters (CONFIG_VM_EVENT_COUNTERS)   )iopriovmstat)
ConnectionNETLINK_GENERICU32AttrNLM_F_REQUEST)
ControllerGeNlMessagec               @   s   e Zd ZdZdd ZdS )DumpableObjectzFBase class for all objects that allows easy introspection when printedc             C   s$   dt t| d d tj| jf S )Nz%s: %s>r   )strtypepprintZpformat__dict__)self r   /usr/lib/python3.6/data.py__repr__?   s    zDumpableObject.__repr__N)__name__
__module____qualname____doc__r   r   r   r   r   r   =   s   r   c               @   sL   e Zd ZdddddgZdZdd ZdddZdd Zdd Ze	dd Z
dS )Statsblkio_delay_total(   swapin_delay_total8   
read_bytes   write_bytes   cancelled_write_bytes  Nc             C   sP   | j }x6tjD ],\}}|||d  }tjd|d ||< qW tjsLt t_d S )N   Qr   )r   r   members_offsetsstructunpackhas_blkio_delay_totalsysctl_task_delayacct)r   Ztask_stats_buffersdnameoffsetdatar   r   r   __init__R   s    zStats.__init__r   c       	      C   sB   |j }| j }|j }x*tjD ] \}}|| |||   ||< qW dS )z3Update destination from operator(self, other_stats)N)r   r   r)   )	r   other_statsdestinationcoeffZddr.   Zodmemberr0   r   r   r   
accumulate]   s
    zStats.accumulatec             C   s   | j ||ddS )z*Update destination with self - other_statsr   )r5   r   )r7   )r   r3   r4   r   r   r   deltae   s    zStats.deltac             C   s.   | j }x"tjD ]\}}|| dkrdS qW dS )Nr   FT)r   r   r)   )r   r.   r/   r0   r   r   r   is_all_zeroi   s
    zStats.is_all_zeroc              C   s0   t jt } | j}xt jD ]\}}d||< qW | S )Nr   )r   __new__r   r)   )statsZstdr/   r0   r   r   r   build_all_zerop   s
    
zStats.build_all_zero)r   r   )r   r    )r!   r"   )r#   r$   )r%   r&   )r   )r   r   r   r)   r,   r2   r7   r8   r9   staticmethodr<   r   r   r   r   r   G   s   
r         c               @   s$   e Zd Zdd Zdd Zdd ZdS )TaskStatsNetlinkc             C   s*   || _ tt| _t| j}|jd| _d S )NZ	TASKSTATS)optionsr   r	   
connectionr   Zget_family_id	family_id)r   rA   Z
controllerr   r   r   r2      s    

zTaskStatsNetlink.__init__c             C   s   t | jttt|gtdS )N)cmdattrsflags)r   rC   TASKSTATS_CMD_GETr
   TASKSTATS_CMD_ATTR_PIDr   )r   tidr   r   r   build_request   s    
zTaskStatsNetlink.build_requestc             C   s   |j j| j ytj| j}W n4 tk
rR } z|jtjkr@d S  W Y d d }~X nX x,|jj	 D ]\}}|t
kr`|j }P q`W d S |t j}t|dk rd S tjd|d d d }|dkstt|S )Ni  H   r   r>   )task_stats_requestsendrB   r   ZrecvOSErrorerrnoZESRCHrE   itemsTASKSTATS_TYPE_AGGR_PIDnestedTASKSTATS_TYPE_STATSr1   lenr*   r+   AssertionErrorr   )r   threadZreplyeZ	attr_typeZ
attr_valueZtaskstats_dataZtaskstats_versionr   r   r   get_single_task_stats   s$    
z&TaskStatsNetlink.get_single_task_statsN)r   r   r   r2   rJ   rY   r   r   r   r   r@      s   r@   c             C   s   g | _ d}x| jpg D ]t}yt|}W nR tk
rx   ytj|}W n( tk
rl   td|tj	d d}Y nX |j
}Y nX |s| j j| qW |rtjd dS )zDBuild options.uids from options.users by resolving usernames to UIDsFzUnknown user:)fileTr   N)uidsZusersint
ValueErrorpwdgetpwnamKeyErrorprintsysstderrZpw_uidappendexit)rA   erroruuidZpasswdr   r   r   	find_uids   s     
ri   c             C   sT   i }y6x0t d|  D ] }|jdd\}}|j ||< qW W n tk
rN   Y nX |S )Nz/proc/%d/statusz:	r   )opensplitstripIOError)pidZresult_dictlinekeyvaluer   r   r   parse_proc_pid_status   s    rr   c             C   s<   y
| j dS  tk
r$   | jdS  tk
r6   | S X d S )Nzutf-8Zstring_escape)decodeUnicodeDecodeErrorencodeAttributeError)sr   r   r   safe_utf8_decode   s    

rx   c               @   s0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )
ThreadInfozStats for a single threadc             C   s.   || _ d| _d | _tjt| _|j|| _d S )NT)rI   markstats_totalr   r:   stats_deltarJ   rM   )r   rI   taskstats_connectionr   r   r   r2      s
    zThreadInfo.__init__c             C   s   t j| jS )N)r   getrI   )r   r   r   r   
get_ioprio   s    zThreadInfo.get_ioprioc             C   s   t jt j| j||S )N)r   
set_ioprioZIOPRIO_WHO_PROCESSrI   )r   ioprio_classioprio_datar   r   r   r      s    zThreadInfo.set_ioprioc             C   s&   | j s|| _ |j| j | j || _ d S )N)r{   r8   r|   )r   r;   r   r   r   update_stats   s    zThreadInfo.update_statsN)r   r   r   r   r2   r   r   r   r   r   r   r   ry      s
   ry   c               @   sh   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dd Zdd Zdd Zdd ZdS )ProcessInfozStats for a single process (a single line in the output): if
    options.processes is set, it is a collection of threads, otherwise a single
    thread.c             C   s:   || _ d | _d | _i | _tj | _tj | _tj | _	d S )N)
rn   rh   userthreadsr   r<   r|   stats_accumtimeZstats_accum_timestamp)r   rn   r   r   r   r2      s    

zProcessInfo.__init__c             C   s:   |j r|j r| j|j krdS |jr6| j |jkr6dS dS )NFT)pids	processesrn   r[   get_uid)r   rA   r   r   r   is_monitored   s    zProcessInfo.is_monitoredc             C   sZ   | j r| j S ytjd| j tj }W n tk
r>   d }Y nX || j krVd | _|| _ |S )Nz/proc/%d)rh   osstatrn   ST_UIDrO   r   )r   rh   r   r   r   r     s    

zProcessInfo.get_uidc             C   s\   | j  }|d k	rR| j rRyttj|j| _W n" ttfk
rP   t|| _Y nX | jpZdS )Nz{none})	r   r   rx   r^   getpwuidZpw_namer`   rv   r   )r   rh   r   r   r   get_user  s    zProcessInfo.get_userc             C   s
  yt d| j }|jd}W n tk
r0   dS X t| j}|sb|jdd}|rZd| }nd}|S d}t|jd| j}|| jkrt|jdd}|jdd}||kr|d	| 7 }|jd
}	|	d jdr|	d j	dd }
|	d |
d  |	d< dj
|	j }t|| S )Nz/proc/%d/cmdlinei   z{no such process}Name z[%s]z	{no name}ZTgidz [%s] r   /r    )rj   rn   readrm   rr   r~   r\   rk   
startswithrfindjoinrl   rx   )r   Zproc_cmdliner   Zproc_statusZproc_status_namesuffixtgidZ	tgid_nameZthread_namepartsZfirst_command_charr   r   r   get_cmdline  s2    



zProcessInfo.get_cmdlinec             C   s6   |r| j j  S x | jj D ]}|jj sdS qW dS )NTF)r   r9   r   valuesr|   )r   Zaccumulatedtr   r   r   did_some_io<  s    
zProcessInfo.did_some_ioc             C   s0   t dd | jj D }t|dkr,|j S dS )Nc             s   s   | ]}|j  V  qd S )N)r   ).0r   r   r   r   	<genexpr>E  s    z)ProcessInfo.get_ioprio.<locals>.<genexpr>r   z?dif)setr   r   rU   pop)r   Z
prioritiesr   r   r   r   D  s    zProcessInfo.get_ioprioc             C   s$   x| j j D ]}|j|| qW d S )N)r   r   r   )r   r   r   rW   r   r   r   r   J  s    zProcessInfo.set_ioprioc             C   s   t j| j S )N)r   Zsort_keyr   )r   r   r   r   ioprio_sort_keyN  s    zProcessInfo.ioprio_sort_keyc             C   s*   | j j|d }|s&t||}|| j |< |S )N)r   r~   ry   )r   rI   r}   rW   r   r   r   
get_threadQ  s
    

zProcessInfo.get_threadc             C   s   t j }x*| jj D ]\}}|js|j|j| qW tdd | jj D | _t| j}|s`dS | j	|  _	| j
|  _
|| _| jj| j| j dS )Nc             S   s   g | ]\}}|j s||fqS r   )rz   )r   rI   rW   r   r   r   
<listcomp>]  s    z,ProcessInfo.update_stats.<locals>.<listcomp>FT)r   r<   r   rQ   rz   r7   r|   dictrU   r   r   r   )r   r|   rI   rW   Z
nr_threadsr   r   r   r   X  s    
zProcessInfo.update_statsN)r   r   r   r   r2   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r      s   		r   c               @   sD   e Zd Zdd Zdd Zdd Zdd Zd	d
 Zdd Zdd Z	dS )ProcessListc             C   s2   i | _ || _|| _tj | _tj | _| j  d S )N)r   r}   rA   r   	timestampr   r   update_process_counts)r   r}   rA   r   r   r   r2   m  s    

zProcessList.__init__c             C   s8   | j j|d}|s$t|}|| j |< |j| jr4|S dS )zyEither get the specified PID from self.processes or build a new
        ProcessInfo if we see this PID for the first timeN)r   r~   r   r   rA   )r   rn   processr   r   r   get_processx  s    
zProcessList.get_processc             C   s   | j jr| j jS tjd}| j jr0dd |D S g }x`|D ]X}d|d   koTdkn  r:y"|jtttjd| d  W q: tk
r   Y q:X q:W |S )	Nz/procc             S   s0   g | ](}d |d   kodkn  rt |qS )0r   9)r\   )r   r   r   r   r   r     s    z*ProcessList.list_tgids.<locals>.<listcomp>r   r   r   z/proc/z/task)	rA   r   r   listdirr   extendmapr\   rO   )r   Ztgidstidsr   r   r   r   
list_tgids  s    

"
zProcessList.list_tgidsc             C   sf   | j js|gS yttttjd| }W n tk
r>   g S X | j jrbtt	| j jj
t	|}|S )Nz/proc/%d/task)rA   r   listr   r\   r   r   rO   r   r   intersection)r   r   r   r   r   r   	list_tids  s    zProcessList.list_tidsc       
      C   s   t j  }|| j | _|| _d }}x|| j D ]p}| j|}|s@q,xZ| j|D ]L}|j|| j}| jj|}|rL|j	| |j
}	||	j7 }||	j7 }d|_qLW q,W ||f| jj fS )Nr   F)r   r   Zdurationr   r   r   r   r}   rY   r   r|   r!   r#   rz   r   r8   )
r   Znew_timestampZ
total_readZtotal_writer   r   rI   rW   r;   r8   r   r   r   r     s$    



z!ProcessList.update_process_countsc             C   sT   x,| j j D ]}x|jj D ]
}d|_qW qW | j }tdd | j j D | _ |S )NTc             S   s    g | ]\}}|j  r||fqS r   )r   )r   rn   r   r   r   r   r     s    z1ProcessList.refresh_processes.<locals>.<listcomp>)r   r   r   rz   r   r   rQ   )r   r   rW   Ztotal_read_and_writer   r   r   refresh_processes  s    zProcessList.refresh_processesc             C   s
   i | _ d S )N)r   )r   r   r   r   clear  s    zProcessList.clearN)
r   r   r   r2   r   r   r   r   r   r   r   r   r   r   r   l  s   r   c               C   s   dt  j kS )a|   WAS:
    try:
        with open('/proc/sys/kernel/task_delayacct') as f:
            return bool(int(f.read().strip()))
    except FileNotFoundError:
        return None


    Because /proc/sys/kernel/task_delayacct doesn't exist on RHEL8,
    it always returns None, which is equivalent to False in the end.

    On RHEL8, delayacct_on kernel variable is enabled by default
    Znodelayacct)r   keysr   r   r   r   r-     s    r-   )0Z
__future__r   rP   r   r   r^   r   r*   rb   r   Zprocfsr   pathexistsZioaccountingZiotop.vmstatr   Zvmstat_fZvm_event_countersra   re   Ziotopr   r   Ziotop.netlinkr   r	   r
   r   Ziotop.genetlinkr   r   objectr   r   rG   rH   rR   ZTASKSTATS_TYPE_PIDrT   r@   ri   rr   rx   ry   r   r   r-   r   r   r   r   <module>   sV   



5) ^