/home/lnzliplg/public_html/daemon.zip
PK���\�
��NN&__pycache__/application.cpython-36.pycnu�[���3

�<�e��@s�ddlmZmZmZmZmZmZmZddlm	Z	ddl
ZddlZddlm
Z
ddlmZddlZddlZddlZddlZddlZddljZddlmZejj�ZdgZGd	d�de�ZdS)
�)�storage�units�monitors�plugins�profiles�exports�hardware)�TunedExceptionN�)�
controller)�daemon)�GlobalConfig�Applicationc@s�eZdZddd�Zdd�Zdd�Zdd	�Zd
d�Zdd
�Zdd�Z	e
jfdd�Zdd�Z
dd�Ze
jfdd�Zedd��Zedd��Zdd�ZdS)rNc	Csptjdtjjtj�df�d|_d|_t	j
�}t	j|�}|dkrJt�n||_
|j
jtj�rjtjd�n
tjd�tj�}|j
jdtj�}tj|d�}tj�}tj�}	tjj�}
tjj�|_tj|||||	|
|j
|j�}t|j
jtj tj!��}t"j#|||||j
�}
tj�}tj$�}tj%tj&�}tj'||||j
|j�}t(j)|
|||j
|�|_*t+j,|j*|j
�|_-|j.�d|_/dS)NzTuneD: %s, kernel: %s�z8dynamic tuning is enabled (can be overridden in plugins)z#dynamic tuning is globally disabled�udev_buffer_size)�buffer_size)0�log�info�tuned�versionZTUNED_VERSION_STR�os�uname�_dbus_exporter�_unix_socket_exporterrZPickleProviderZFactoryr
�config�get_bool�constsZCFG_DYNAMIC_TUNINGrZ
RepositoryZget_sizeZCFG_DEF_UDEV_BUFFER_SIZErZ	InventoryZ
DeviceMatcherZDeviceMatcherUdevr�instancer�	variables�	Variables�int�getZCFG_DEFAULT_INSTANCE_PRIORITYZ!CFG_DEF_DEFAULT_INSTANCE_PRIORITYrZManagerZMergerZLocatorZLOAD_DIRECTORIES�LoaderrZDaemon�_daemonrZ
Controller�_controller�
_init_signals�	_pid_file)�selfZprofile_namerZstorage_providerZstorage_factoryZmonitors_repositoryrZhardware_inventoryZdevice_matcherZdevice_matcher_udevZplugin_instance_factoryZplugins_repositoryZdef_instance_priorityZunit_managerZprofile_factoryZprofile_mergerZprofile_locatorZprofile_loader�r(�!/usr/lib/python3.6/application.py�__init__s<



zApplication.__init__cs��fdd�}tj�|�dS)Ncs�|kr��dS)Nr()Z_signal_numberZ_frame)�handler�
signal_numberr(r)�handler_wrapper@sz3Application._handle_signal.<locals>.handler_wrapper)�signal)r'r,r+r-r()r+r,r)�_handle_signal?szApplication._handle_signalcCs:|jtj|jj�|jtj|jj�|jtj|jj�dS)N)r/r.�SIGHUPr$Zsighup�SIGINTZ	terminate�SIGTERM)r'r(r(r)r%EszApplication._init_signalscCs6|jdk	rtd��tjj||||�|_tj|j�dS)Nz&DBus interface is already initialized.)rr	rZdbusZDBusExporter�register_exporter)r'Zbus_nameZobject_nameZinterface_name�	namespacer(r(r)�attach_to_dbusJs
zApplication.attach_to_dbuscCsj|jdk	rtd��tjj|jjtj�|jjtj	�|jjtj
�|jjtj�|jjtj
��|_tj|j�dS)Nz-Unix socket interface is already initialized.)rr	rZunix_socketZUnixSocketExporterrr!rZCFG_UNIX_SOCKET_PATHZCFG_UNIX_SOCKET_SIGNAL_PATHSZCFG_UNIX_SOCKET_OWNERSHIPZget_intZCFG_UNIX_SOCKET_PERMISIONSZ#CFG_UNIX_SOCKET_CONNECTIONS_BACKLOGr3)r'r(r(r)�attach_to_unix_socketQs
z!Application.attach_to_unix_socketcCstj|j�dS)N)rZregister_objectr$)r'r(r(r)�register_controller\szApplication.register_controllercCs�tj|�tj|gggtj�\}}}t|�dkrBtj|�td��tj|d�}tj|�t|�dkrltd��ytj	d|�d}Wntj
k
r�td��YnX|dkr�td	��d
S)z|
		Wait till the child signalizes that the initialization is complete by writing
		some uninteresting data into the pipe.
		r
z=Cannot daemonize, timeout when waiting for the child process.�rz:Cannot daemonize, no response from child process received.�?z?Cannot daemonize, invalid response from child process received.Tz0Cannot daemonize, child process reports failure.N)r�close�selectrZDAEMONIZE_PARENT_TIMEOUT�lenr	�read�struct�unpack�error)r'�parent_in_fd�child_out_fdZ
read_readyZdropZresponse�valr(r(r)�_daemonize_parent_s


zApplication._daemonize_parentcCs�||_|j�yltjj|j�}tjj|�s4tj|�tjtj|jtj	tj
BtjBd�d��}|jdtj
��WdQRXWn>ttfk
r�}ztjd|jt|�f�WYdd}~XnXdS)Ni��wz%dzcannot write the PID to %s: %s)r&�_delete_pid_filer�path�dirname�exists�makedirs�fdopen�open�O_CREAT�O_TRUNC�O_WRONLY�write�getpid�OSError�IOErrorr�critical�str)r'�pid_fileZdir_name�fr@r(r(r)�write_pid_filexs
( zApplication.write_pid_filecCs^tjj|j�rZytj|j�Wn:tk
rX}ztjd|jt|�f�WYdd}~XnXdS)Nz&cannot remove existing PID file %s, %s)	rrGrIr&�unlinkrRrZwarningrU)r'r@r(r(r)rF�s
zApplication._delete_pid_filecCs*tj|�tjd�tj�tjd�ytj�}|dkrBtjd�Wn^tk
r�}zBt	j
dt|��tj
dd�}tj||�tj|�td��WYdd}~XnXtdd	�}tj|j�tjj��tj|j�tjj��tj|j�tjj��|j|�t	jd
�tj
dd�}tj||�tj|�dS)zy
		Finishes daemonizing process, writes a PID file and signalizes to the parent
		that the initialization is complete.
		�/rz"cannot daemonize, fork() error: %sr9Fz'Cannot daemonize, second fork() failed.Nz	/dev/nullzw+zsuccessfully daemonizedT)rr:�chdir�setsid�umask�fork�sys�exitrRrrTrUr>�packrPr	rL�dup2�fileno�stdin�stdout�stderrrX�debug)r'rVrArB�pidr@rC�fdr(r(r)�_daemonize_child�s.






zApplication._daemonize_childcCs�tj�}ytj�}WnFtk
rZ}z*tj|d�tj|d�td��WYdd}~XnXy2|dkr||j|�tjd�n|j	|f|��Wn"|dkr��n
tjd�YnXdS)z�
		Daemonizes the application. In case of failure, TunedException is raised
		in the parent process. If the operation is successfull, the main process
		is terminated and only child process returns from this method.
		rr
z Cannot daemonize, fork() failed.N)
r�piper^rRr:r	rDr_r`rj)r'rVZparent_child_fdsZ	child_pidr@r(r(r)�	daemonize�s 
zApplication.daemonizecCs|jS)N)r#)r'r(r(r)r�szApplication.daemoncCs|jS)N)r$)r'r(r(r)r�szApplication.controllercCsj|r|jjtjd�|jjtjtj�s0tjd�|jj	�}|jjtjtj�rTt
j�|jdk	rf|j
�|S)NTzrUsing one shot no daemon mode, most of the functionality will be not available, it can be changed in global config)r�setrZ
CFG_DAEMONrZCFG_DEF_DAEMONr�warnr$�runr�stopr&rF)r'r�resultr(r(r)ro�s


zApplication.run)NN)�__name__�
__module__�__qualname__r*r/r%r5r6r7rDrZPID_FILErXrFrjrl�propertyrrror(r(r(r)rs
+
")rrrrrrrrZtuned.exceptionsr	Z
tuned.logsZ
tuned.version�rrr.rr_r;r>Ztuned.constsrZtuned.utils.global_configr
Zlogsr!r�__all__�objectrr(r(r(r)�<module>s$

PK���\�
��NN,__pycache__/application.cpython-36.opt-1.pycnu�[���3

�<�e��@s�ddlmZmZmZmZmZmZmZddlm	Z	ddl
ZddlZddlm
Z
ddlmZddlZddlZddlZddlZddlZddljZddlmZejj�ZdgZGd	d�de�ZdS)
�)�storage�units�monitors�plugins�profiles�exports�hardware)�TunedExceptionN�)�
controller)�daemon)�GlobalConfig�Applicationc@s�eZdZddd�Zdd�Zdd�Zdd	�Zd
d�Zdd
�Zdd�Z	e
jfdd�Zdd�Z
dd�Ze
jfdd�Zedd��Zedd��Zdd�ZdS)rNc	Csptjdtjjtj�df�d|_d|_t	j
�}t	j|�}|dkrJt�n||_
|j
jtj�rjtjd�n
tjd�tj�}|j
jdtj�}tj|d�}tj�}tj�}	tjj�}
tjj�|_tj|||||	|
|j
|j�}t|j
jtj tj!��}t"j#|||||j
�}
tj�}tj$�}tj%tj&�}tj'||||j
|j�}t(j)|
|||j
|�|_*t+j,|j*|j
�|_-|j.�d|_/dS)NzTuneD: %s, kernel: %s�z8dynamic tuning is enabled (can be overridden in plugins)z#dynamic tuning is globally disabled�udev_buffer_size)�buffer_size)0�log�info�tuned�versionZTUNED_VERSION_STR�os�uname�_dbus_exporter�_unix_socket_exporterrZPickleProviderZFactoryr
�config�get_bool�constsZCFG_DYNAMIC_TUNINGrZ
RepositoryZget_sizeZCFG_DEF_UDEV_BUFFER_SIZErZ	InventoryZ
DeviceMatcherZDeviceMatcherUdevr�instancer�	variables�	Variables�int�getZCFG_DEFAULT_INSTANCE_PRIORITYZ!CFG_DEF_DEFAULT_INSTANCE_PRIORITYrZManagerZMergerZLocatorZLOAD_DIRECTORIES�LoaderrZDaemon�_daemonrZ
Controller�_controller�
_init_signals�	_pid_file)�selfZprofile_namerZstorage_providerZstorage_factoryZmonitors_repositoryrZhardware_inventoryZdevice_matcherZdevice_matcher_udevZplugin_instance_factoryZplugins_repositoryZdef_instance_priorityZunit_managerZprofile_factoryZprofile_mergerZprofile_locatorZprofile_loader�r(�!/usr/lib/python3.6/application.py�__init__s<



zApplication.__init__cs��fdd�}tj�|�dS)Ncs�|kr��dS)Nr()Z_signal_numberZ_frame)�handler�
signal_numberr(r)�handler_wrapper@sz3Application._handle_signal.<locals>.handler_wrapper)�signal)r'r,r+r-r()r+r,r)�_handle_signal?szApplication._handle_signalcCs:|jtj|jj�|jtj|jj�|jtj|jj�dS)N)r/r.�SIGHUPr$Zsighup�SIGINTZ	terminate�SIGTERM)r'r(r(r)r%EszApplication._init_signalscCs6|jdk	rtd��tjj||||�|_tj|j�dS)Nz&DBus interface is already initialized.)rr	rZdbusZDBusExporter�register_exporter)r'Zbus_nameZobject_nameZinterface_name�	namespacer(r(r)�attach_to_dbusJs
zApplication.attach_to_dbuscCsj|jdk	rtd��tjj|jjtj�|jjtj	�|jjtj
�|jjtj�|jjtj
��|_tj|j�dS)Nz-Unix socket interface is already initialized.)rr	rZunix_socketZUnixSocketExporterrr!rZCFG_UNIX_SOCKET_PATHZCFG_UNIX_SOCKET_SIGNAL_PATHSZCFG_UNIX_SOCKET_OWNERSHIPZget_intZCFG_UNIX_SOCKET_PERMISIONSZ#CFG_UNIX_SOCKET_CONNECTIONS_BACKLOGr3)r'r(r(r)�attach_to_unix_socketQs
z!Application.attach_to_unix_socketcCstj|j�dS)N)rZregister_objectr$)r'r(r(r)�register_controller\szApplication.register_controllercCs�tj|�tj|gggtj�\}}}t|�dkrBtj|�td��tj|d�}tj|�t|�dkrltd��ytj	d|�d}Wntj
k
r�td��YnX|dkr�td	��d
S)z|
		Wait till the child signalizes that the initialization is complete by writing
		some uninteresting data into the pipe.
		r
z=Cannot daemonize, timeout when waiting for the child process.�rz:Cannot daemonize, no response from child process received.�?z?Cannot daemonize, invalid response from child process received.Tz0Cannot daemonize, child process reports failure.N)r�close�selectrZDAEMONIZE_PARENT_TIMEOUT�lenr	�read�struct�unpack�error)r'�parent_in_fd�child_out_fdZ
read_readyZdropZresponse�valr(r(r)�_daemonize_parent_s


zApplication._daemonize_parentcCs�||_|j�yltjj|j�}tjj|�s4tj|�tjtj|jtj	tj
BtjBd�d��}|jdtj
��WdQRXWn>ttfk
r�}ztjd|jt|�f�WYdd}~XnXdS)Ni��wz%dzcannot write the PID to %s: %s)r&�_delete_pid_filer�path�dirname�exists�makedirs�fdopen�open�O_CREAT�O_TRUNC�O_WRONLY�write�getpid�OSError�IOErrorr�critical�str)r'�pid_fileZdir_name�fr@r(r(r)�write_pid_filexs
( zApplication.write_pid_filecCs^tjj|j�rZytj|j�Wn:tk
rX}ztjd|jt|�f�WYdd}~XnXdS)Nz&cannot remove existing PID file %s, %s)	rrGrIr&�unlinkrRrZwarningrU)r'r@r(r(r)rF�s
zApplication._delete_pid_filecCs*tj|�tjd�tj�tjd�ytj�}|dkrBtjd�Wn^tk
r�}zBt	j
dt|��tj
dd�}tj||�tj|�td��WYdd}~XnXtdd	�}tj|j�tjj��tj|j�tjj��tj|j�tjj��|j|�t	jd
�tj
dd�}tj||�tj|�dS)zy
		Finishes daemonizing process, writes a PID file and signalizes to the parent
		that the initialization is complete.
		�/rz"cannot daemonize, fork() error: %sr9Fz'Cannot daemonize, second fork() failed.Nz	/dev/nullzw+zsuccessfully daemonizedT)rr:�chdir�setsid�umask�fork�sys�exitrRrrTrUr>�packrPr	rL�dup2�fileno�stdin�stdout�stderrrX�debug)r'rVrArB�pidr@rC�fdr(r(r)�_daemonize_child�s.






zApplication._daemonize_childcCs�tj�}ytj�}WnFtk
rZ}z*tj|d�tj|d�td��WYdd}~XnXy2|dkr||j|�tjd�n|j	|f|��Wn"|dkr��n
tjd�YnXdS)z�
		Daemonizes the application. In case of failure, TunedException is raised
		in the parent process. If the operation is successfull, the main process
		is terminated and only child process returns from this method.
		rr
z Cannot daemonize, fork() failed.N)
r�piper^rRr:r	rDr_r`rj)r'rVZparent_child_fdsZ	child_pidr@r(r(r)�	daemonize�s 
zApplication.daemonizecCs|jS)N)r#)r'r(r(r)r�szApplication.daemoncCs|jS)N)r$)r'r(r(r)r�szApplication.controllercCsj|r|jjtjd�|jjtjtj�s0tjd�|jj	�}|jjtjtj�rTt
j�|jdk	rf|j
�|S)NTzrUsing one shot no daemon mode, most of the functionality will be not available, it can be changed in global config)r�setrZ
CFG_DAEMONrZCFG_DEF_DAEMONr�warnr$�runr�stopr&rF)r'r�resultr(r(r)ro�s


zApplication.run)NN)�__name__�
__module__�__qualname__r*r/r%r5r6r7rDrZPID_FILErXrFrjrl�propertyrrror(r(r(r)rs
+
")rrrrrrrrZtuned.exceptionsr	Z
tuned.logsZ
tuned.version�rrr.rr_r;r>Ztuned.constsrZtuned.utils.global_configr
Zlogsr!r�__all__�objectrr(r(r(r)�<module>s$

PK���\���±*�*'__pycache__/daemon.cpython-36.opt-1.pycnu�[���3

�<�e�3�@s�ddlZddlZddlZddlZddlmZddlmZddl	j
Z
ddlmZddlm
Z
ddlmZddlZejj�ZGdd�de�ZdS)	�N)�TunedException)�InvalidProfileException)�commands)�exports)�ProfileRecommenderc@seZdZd;dd�Zdd�Zdd�Zdd	�Zd
d�Zdd
�Zdd�Z	d<dd�Z
edd��Zedd��Z
edd��Zedd��Zedd��Zdd�Zdd �Zd!d"�Zd#d$�Zd%d&�Zd'd(�Zd)d*�Zd+d,�Zd-d.�Zd/d0�Zd1d2�Zd3d4�Zd5d6�Zd7d8�Zd=d9d:�ZdS)>�DaemonNcCs�tjd�tj|_ttj�|_ttj�|_	tj
|_d|_tj
|_|dk	r�|jtjtj�|_t|jtjtj��|_t|jtjtj��|_	|jtjtj
�|_|jtjtj�|_|jtjtj
�|_||_|jdkr�ttj�|_|j	dkr�d|_n|j	|jkr�|j|_	|j	|j|_tjd|j�|j�rJtjd�tjd|j|j|jf�t|jd�|_||_||_|j�t �|_!y|j"|�Wn2t#k
�r�}ztj$d	|�WYdd}~XnXdS)
Nzinitializing daemonTrFz$using sleep interval of %d second(s)z8dynamic tuning is enabled (can be overridden by plugins)zFusing update interval of %d second(s) (%d times of the sleep interval))Zis_hardcodedz:Cannot set initial profile. No tunings will be enabled: %s)%�log�debug�constsZCFG_DEF_DAEMON�_daemon�intZCFG_DEF_SLEEP_INTERVAL�_sleep_intervalZCFG_DEF_UPDATE_INTERVALZ_update_intervalZCFG_DEF_DYNAMIC_TUNING�_dynamic_tuningZ_recommend_commandZCFG_DEF_ROLLBACK�	_rollbackZget_boolZ
CFG_DAEMON�getZCFG_SLEEP_INTERVALZCFG_UPDATE_INTERVALZCFG_DYNAMIC_TUNINGZCFG_RECOMMEND_COMMANDZCFG_DEF_RECOMMEND_COMMAND�CFG_ROLLBACK�_application�
_sleep_cycles�infor�_profile_recommender�
_unit_manager�_profile_loader�
_init_threadsr�_cmd�
_init_profiler�error)�selfZunit_manager�profile_loader�
profile_names�configZapplication�e�r!�/usr/lib/python3.6/daemon.py�__init__sF



zDaemon.__init__cCsFd|_tj�|_tj�|_tj�|_tj�|_|jj�tj�|_dS)N)	�_thread�	threadingZEvent�
_terminate�_terminate_profile_switch�	_not_used�_sighup_processing�set�_profile_applied)rr!r!r"r7s




zDaemon._init_threadscCs|jd�dS)zARead configuration files again and load profile according to themN)r)rr!r!r"�reload_profile_configCszDaemon.reload_profile_configcCs�d}|jj�}|dkrP|j�\}}|dkrrd}|r<|d7}n|d7}tj|�n"|dkrr|rhtjd�n
tjd�d|_d|_g|_d|_|j	|||�dS)NTz.No profile is preset, running in manual mode. z(Only post-loaded profile will be enabledzNo profile will be enabled.�)
rZget_post_loaded_profile�_get_startup_profilerr�_profile�_manual�_active_profiles�_post_loaded_profile�set_all_profiles)rr�manual�post_loaded_profile�msgr!r!r"rGs&


zDaemon._init_profilecCs�|pd}|j�}|jr2tjd|j�||jg}x:|D]2}||jjj�kr8d|}|j|d|�t|��q8Wy.|r�|j	j
|�|_nd|_||_|j�|_
WnJtk
r�}z.ddj|�|f}|j|d|�t|��WYdd}~XnXdS)Nr-zUsing post-loaded profile '%s'z%Requested profile '%s' doesn't exist.FzCannot load profile(s) '%s': %s� )�splitr2rrrZprofile_locatorZget_known_names�_notify_profile_changedrr�loadr/r0r1r�join)rrr4Zprofile_list�profile�errstrr r!r!r"�_load_profiles`s*

zDaemon._load_profilescCs2|j�r"d}|j|d|�t|��|j||�dS)Nz/Cannot set profile while the daemon is running.F)�
is_runningr9rr>)rrr4r=r!r!r"�set_profilezszDaemon.set_profilecCs4|sd|_n$t|j��dkr*d}t|��n||_dS)N�zYWhitespace is not allowed in profile names; only a single post-loaded profile is allowed.)r2�lenr8r)r�profile_namer=r!r!r"�_set_post_loaded_profile�s
zDaemon._set_post_loaded_profileFcCsV|j�r"d}|j|d|�t|��|j|�|j||�|rR|j||�|j|�dS)Nz/Cannot set profile while the daemon is running.F)r?r9rrDr>�_save_active_profile�_save_post_loaded_profile)rZactive_profilesr4r5Zsave_instantlyr=r!r!r"r3�s
zDaemon.set_all_profilescCs|jS)N)r/)rr!r!r"r<�szDaemon.profilecCs|jS)N)r0)rr!r!r"r4�sz
Daemon.manualcCs|jr|jSdS)N)r/r2)rr!r!r"r5�szDaemon.post_loaded_profilecCs|jS)N)r)rr!r!r"�profile_recommender�szDaemon.profile_recommendercCs|jS)N)r)rr!r!r"r�szDaemon.profile_loadercCs |jdk	rtjtj|||�|S)N)rrZsend_signalr
ZSIGNAL_PROFILE_CHANGED)rr�resultr=r!r!r"r9�s
zDaemon._notify_profile_changedcCsj|jjddgdgd�\}}|dkr&dS|dd�dkr:dS|jjddgdgd�\}}tjd	|�dkoh|S)
NZ	systemctlzis-system-runningr)Z	no_errorsF�Zstoppingz	list-jobsz0\b(shutdown|reboot|halt|poweroff)\.target.*start)rZexecute�re�search)rZretcode�outr!r!r"�_full_rollback_required�szDaemon._full_rollback_requiredcCs�|jdkrtd��|jj|jj�|jdj|j�|j�|j	|j
�|jj�|jj
�tjd|jj�|jrxtj�dj|j�}|j|dd�|jj�|j�r|j}x\|jj|j|j��s|jr�|d8}|dkr�|j}tjd�|jj�tjd	�|jj�q�W|jj�d}x.|jj|j |j��rD|d
k�rD|d7}�qW|j!j"��rZt#j$}njt#j%}|j&��svtjd�nN|j'dk�r�t#j(}tjd
t#j)t#j*f�n$|j�r�tjd�t#j$}n
tjd�|j�r�|jj+|�|jj,�dS)Nz2Cannot start the daemon without setting a profile.r7z'static tuning from profile '%s' appliedTZOKrArzupdating monitorszperforming tunings�z1terminating TuneD due to system shutdown / rebootZnot_on_exitzMterminating TuneD and not rolling back any changes due to '%s' option in '%s'z+terminating TuneD, rolling back all changesz"terminating TuneD in one-shot mode)-r/rrZcreateZunitsrEr;r1r0rFr2Zstart_tuningr+r*rr�namerr�startr9r)�clearrr�waitr&r
rr	Zupdate_monitorsZ
update_tuningr(r'�is_setr
Z
ROLLBACK_FULLZ
ROLLBACK_SOFTrMrZ
ROLLBACK_NONErZGLOBAL_CONFIG_FILEZstop_tuningZdestroy_all)rrZ
_sleep_cnt�iZrollbackr!r!r"�_thread_code�sX







"



zDaemon._thread_codecCsHy|jj||�Wn0tk
rB}ztjt|��WYdd}~XnXdS)N)rZsave_active_profilerrr�str)rrr4r r!r!r"rEszDaemon._save_active_profilecCsFy|jj|�Wn0tk
r@}ztjt|��WYdd}~XnXdS)N)rZsave_post_loaded_profilerrrrV)rrCr r!r!r"rFsz Daemon._save_post_loaded_profilecCs&tjd�|jj�}tjd|�|S)NzWRunning in automatic mode, checking what profile is recommended for your configuration.zUsing '%s' profile)rrrZ	recommend)rr<r!r!r"�_get_recommended_profiles

zDaemon._get_recommended_profilecCs2|jj�\}}|dkr|dk	}|s*|j�}||fS)N)rZget_active_profilerW)rr<r4r!r!r"r.szDaemon._get_startup_profilecCs|jjj�S)z$Return all accessible plugin classes)r�plugins_repositoryZload_all_plugins)rr!r!r"�get_all_plugins"szDaemon.get_all_pluginscCs.y|jjj|�}Wntk
r&dSX|jS)zReturn plugin class docstringr-)rrX�load_plugin�ImportError�__doc__)r�plugin_name�plugin_classr!r!r"�get_plugin_documentation&s
zDaemon.get_plugin_documentationcCs0y|jjj|�}Wntk
r&iSX|j�S)z�Return plugin's parameters and their hints

		Parameters:
		plugin_name -- plugins name

		Return:
		dictionary -- {parameter_name: hint}
		)rrXrZr[Zget_config_options_hints)rr]r^r!r!r"�get_plugin_hints0s	
zDaemon.get_plugin_hintscCs
|jdk	S)N)r/)rr!r!r"�
is_enabledAszDaemon.is_enabledcCs|jdk	o|jj�S)N)r$Zis_alive)rr!r!r"r?DszDaemon.is_runningcCs`|j�rdS|jdkrdStjd�|jj�tj|jd�|_	|j
j�|jj�|j	j
�dS)NFzstarting tuning)�targetT)r?r/rrr(r*r%ZThreadrUr$r'rQr&rP)rr!r!r"rPGs





zDaemon.startcCs||j�stjd�dS|jdkr.tjd�dS|jj�sFtjd�dS|jj�tjd|jj	�|j
j|�}|jj�|S)NzTuneD is not runningFzno profile is setzprofile is not appliedzverifying profile(s): %s)
r?rrr/r+rSr(rQrrOrZ
verify_tuningr*)rZignore_missing�retr!r!r"�verify_profileVs






zDaemon.verify_profilecCsB|j�sdStjd�|r$|jj�|jj�|jj�d|_dS)NFzstopping tuningT)r?rrr'r*r&r$r;)rZprofile_switchr!r!r"�stopls



zDaemon.stop)NNN)F)F) �__name__�
__module__�__qualname__r#rr,rr>r@rDr3�propertyr<r4r5rGrr9rMrUrErFrWr.rYr_r`rar?rPrdrer!r!r!r"rs8
&	

	G
r)�os�errnor%Z
tuned.logsZtunedZtuned.exceptionsrZtuned.profiles.exceptionsrZtuned.constsr
Ztuned.utils.commandsrrZtuned.utils.profile_recommenderrrJZlogsrr�objectrr!r!r!r"�<module>s

PK���\?˸���#__pycache__/__init__.cpython-36.pycnu�[���3

�<�eK�@sddlTddlTddlTdS)�)�*N)ZapplicationZ
controllerZdaemon�rr�/usr/lib/python3.6/__init__.py�<module>sPK���\���±*�*!__pycache__/daemon.cpython-36.pycnu�[���3

�<�e�3�@s�ddlZddlZddlZddlZddlmZddlmZddl	j
Z
ddlmZddlm
Z
ddlmZddlZejj�ZGdd�de�ZdS)	�N)�TunedException)�InvalidProfileException)�commands)�exports)�ProfileRecommenderc@seZdZd;dd�Zdd�Zdd�Zdd	�Zd
d�Zdd
�Zdd�Z	d<dd�Z
edd��Zedd��Z
edd��Zedd��Zedd��Zdd�Zdd �Zd!d"�Zd#d$�Zd%d&�Zd'd(�Zd)d*�Zd+d,�Zd-d.�Zd/d0�Zd1d2�Zd3d4�Zd5d6�Zd7d8�Zd=d9d:�ZdS)>�DaemonNcCs�tjd�tj|_ttj�|_ttj�|_	tj
|_d|_tj
|_|dk	r�|jtjtj�|_t|jtjtj��|_t|jtjtj��|_	|jtjtj
�|_|jtjtj�|_|jtjtj
�|_||_|jdkr�ttj�|_|j	dkr�d|_n|j	|jkr�|j|_	|j	|j|_tjd|j�|j�rJtjd�tjd|j|j|jf�t|jd�|_||_||_|j�t �|_!y|j"|�Wn2t#k
�r�}ztj$d	|�WYdd}~XnXdS)
Nzinitializing daemonTrFz$using sleep interval of %d second(s)z8dynamic tuning is enabled (can be overridden by plugins)zFusing update interval of %d second(s) (%d times of the sleep interval))Zis_hardcodedz:Cannot set initial profile. No tunings will be enabled: %s)%�log�debug�constsZCFG_DEF_DAEMON�_daemon�intZCFG_DEF_SLEEP_INTERVAL�_sleep_intervalZCFG_DEF_UPDATE_INTERVALZ_update_intervalZCFG_DEF_DYNAMIC_TUNING�_dynamic_tuningZ_recommend_commandZCFG_DEF_ROLLBACK�	_rollbackZget_boolZ
CFG_DAEMON�getZCFG_SLEEP_INTERVALZCFG_UPDATE_INTERVALZCFG_DYNAMIC_TUNINGZCFG_RECOMMEND_COMMANDZCFG_DEF_RECOMMEND_COMMAND�CFG_ROLLBACK�_application�
_sleep_cycles�infor�_profile_recommender�
_unit_manager�_profile_loader�
_init_threadsr�_cmd�
_init_profiler�error)�selfZunit_manager�profile_loader�
profile_names�configZapplication�e�r!�/usr/lib/python3.6/daemon.py�__init__sF



zDaemon.__init__cCsFd|_tj�|_tj�|_tj�|_tj�|_|jj�tj�|_dS)N)	�_thread�	threadingZEvent�
_terminate�_terminate_profile_switch�	_not_used�_sighup_processing�set�_profile_applied)rr!r!r"r7s




zDaemon._init_threadscCs|jd�dS)zARead configuration files again and load profile according to themN)r)rr!r!r"�reload_profile_configCszDaemon.reload_profile_configcCs�d}|jj�}|dkrP|j�\}}|dkrrd}|r<|d7}n|d7}tj|�n"|dkrr|rhtjd�n
tjd�d|_d|_g|_d|_|j	|||�dS)NTz.No profile is preset, running in manual mode. z(Only post-loaded profile will be enabledzNo profile will be enabled.�)
rZget_post_loaded_profile�_get_startup_profilerr�_profile�_manual�_active_profiles�_post_loaded_profile�set_all_profiles)rr�manual�post_loaded_profile�msgr!r!r"rGs&


zDaemon._init_profilecCs�|pd}|j�}|jr2tjd|j�||jg}x:|D]2}||jjj�kr8d|}|j|d|�t|��q8Wy.|r�|j	j
|�|_nd|_||_|j�|_
WnJtk
r�}z.ddj|�|f}|j|d|�t|��WYdd}~XnXdS)Nr-zUsing post-loaded profile '%s'z%Requested profile '%s' doesn't exist.FzCannot load profile(s) '%s': %s� )�splitr2rrrZprofile_locatorZget_known_names�_notify_profile_changedrr�loadr/r0r1r�join)rrr4Zprofile_list�profile�errstrr r!r!r"�_load_profiles`s*

zDaemon._load_profilescCs2|j�r"d}|j|d|�t|��|j||�dS)Nz/Cannot set profile while the daemon is running.F)�
is_runningr9rr>)rrr4r=r!r!r"�set_profilezszDaemon.set_profilecCs4|sd|_n$t|j��dkr*d}t|��n||_dS)N�zYWhitespace is not allowed in profile names; only a single post-loaded profile is allowed.)r2�lenr8r)r�profile_namer=r!r!r"�_set_post_loaded_profile�s
zDaemon._set_post_loaded_profileFcCsV|j�r"d}|j|d|�t|��|j|�|j||�|rR|j||�|j|�dS)Nz/Cannot set profile while the daemon is running.F)r?r9rrDr>�_save_active_profile�_save_post_loaded_profile)rZactive_profilesr4r5Zsave_instantlyr=r!r!r"r3�s
zDaemon.set_all_profilescCs|jS)N)r/)rr!r!r"r<�szDaemon.profilecCs|jS)N)r0)rr!r!r"r4�sz
Daemon.manualcCs|jr|jSdS)N)r/r2)rr!r!r"r5�szDaemon.post_loaded_profilecCs|jS)N)r)rr!r!r"�profile_recommender�szDaemon.profile_recommendercCs|jS)N)r)rr!r!r"r�szDaemon.profile_loadercCs |jdk	rtjtj|||�|S)N)rrZsend_signalr
ZSIGNAL_PROFILE_CHANGED)rr�resultr=r!r!r"r9�s
zDaemon._notify_profile_changedcCsj|jjddgdgd�\}}|dkr&dS|dd�dkr:dS|jjddgdgd�\}}tjd	|�dkoh|S)
NZ	systemctlzis-system-runningr)Z	no_errorsF�Zstoppingz	list-jobsz0\b(shutdown|reboot|halt|poweroff)\.target.*start)rZexecute�re�search)rZretcode�outr!r!r"�_full_rollback_required�szDaemon._full_rollback_requiredcCs�|jdkrtd��|jj|jj�|jdj|j�|j�|j	|j
�|jj�|jj
�tjd|jj�|jrxtj�dj|j�}|j|dd�|jj�|j�r|j}x\|jj|j|j��s|jr�|d8}|dkr�|j}tjd�|jj�tjd	�|jj�q�W|jj�d}x.|jj|j |j��rD|d
k�rD|d7}�qW|j!j"��rZt#j$}njt#j%}|j&��svtjd�nN|j'dk�r�t#j(}tjd
t#j)t#j*f�n$|j�r�tjd�t#j$}n
tjd�|j�r�|jj+|�|jj,�dS)Nz2Cannot start the daemon without setting a profile.r7z'static tuning from profile '%s' appliedTZOKrArzupdating monitorszperforming tunings�z1terminating TuneD due to system shutdown / rebootZnot_on_exitzMterminating TuneD and not rolling back any changes due to '%s' option in '%s'z+terminating TuneD, rolling back all changesz"terminating TuneD in one-shot mode)-r/rrZcreateZunitsrEr;r1r0rFr2Zstart_tuningr+r*rr�namerr�startr9r)�clearrr�waitr&r
rr	Zupdate_monitorsZ
update_tuningr(r'�is_setr
Z
ROLLBACK_FULLZ
ROLLBACK_SOFTrMrZ
ROLLBACK_NONErZGLOBAL_CONFIG_FILEZstop_tuningZdestroy_all)rrZ
_sleep_cnt�iZrollbackr!r!r"�_thread_code�sX







"



zDaemon._thread_codecCsHy|jj||�Wn0tk
rB}ztjt|��WYdd}~XnXdS)N)rZsave_active_profilerrr�str)rrr4r r!r!r"rEszDaemon._save_active_profilecCsFy|jj|�Wn0tk
r@}ztjt|��WYdd}~XnXdS)N)rZsave_post_loaded_profilerrrrV)rrCr r!r!r"rFsz Daemon._save_post_loaded_profilecCs&tjd�|jj�}tjd|�|S)NzWRunning in automatic mode, checking what profile is recommended for your configuration.zUsing '%s' profile)rrrZ	recommend)rr<r!r!r"�_get_recommended_profiles

zDaemon._get_recommended_profilecCs2|jj�\}}|dkr|dk	}|s*|j�}||fS)N)rZget_active_profilerW)rr<r4r!r!r"r.szDaemon._get_startup_profilecCs|jjj�S)z$Return all accessible plugin classes)r�plugins_repositoryZload_all_plugins)rr!r!r"�get_all_plugins"szDaemon.get_all_pluginscCs.y|jjj|�}Wntk
r&dSX|jS)zReturn plugin class docstringr-)rrX�load_plugin�ImportError�__doc__)r�plugin_name�plugin_classr!r!r"�get_plugin_documentation&s
zDaemon.get_plugin_documentationcCs0y|jjj|�}Wntk
r&iSX|j�S)z�Return plugin's parameters and their hints

		Parameters:
		plugin_name -- plugins name

		Return:
		dictionary -- {parameter_name: hint}
		)rrXrZr[Zget_config_options_hints)rr]r^r!r!r"�get_plugin_hints0s	
zDaemon.get_plugin_hintscCs
|jdk	S)N)r/)rr!r!r"�
is_enabledAszDaemon.is_enabledcCs|jdk	o|jj�S)N)r$Zis_alive)rr!r!r"r?DszDaemon.is_runningcCs`|j�rdS|jdkrdStjd�|jj�tj|jd�|_	|j
j�|jj�|j	j
�dS)NFzstarting tuning)�targetT)r?r/rrr(r*r%ZThreadrUr$r'rQr&rP)rr!r!r"rPGs





zDaemon.startcCs||j�stjd�dS|jdkr.tjd�dS|jj�sFtjd�dS|jj�tjd|jj	�|j
j|�}|jj�|S)NzTuneD is not runningFzno profile is setzprofile is not appliedzverifying profile(s): %s)
r?rrr/r+rSr(rQrrOrZ
verify_tuningr*)rZignore_missing�retr!r!r"�verify_profileVs






zDaemon.verify_profilecCsB|j�sdStjd�|r$|jj�|jj�|jj�d|_dS)NFzstopping tuningT)r?rrr'r*r&r$r;)rZprofile_switchr!r!r"�stopls



zDaemon.stop)NNN)F)F) �__name__�
__module__�__qualname__r#rr,rr>r@rDr3�propertyr<r4r5rGrr9rMrUrErFrWr.rYr_r`rar?rPrdrer!r!r!r"rs8
&	

	G
r)�os�errnor%Z
tuned.logsZtunedZtuned.exceptionsrZtuned.profiles.exceptionsrZtuned.constsr
Ztuned.utils.commandsrrZtuned.utils.profile_recommenderrrJZlogsrr�objectrr!r!r!r"�<module>s

PK���\|��cs5s5%__pycache__/controller.cpython-36.pycnu�[���3

`��g�4�@s�ddlmZddlZddlZddlmZddlZddljZddlm	Z	dgZ
ejj�Z
Gdd�de�ZGdd�dejjj�ZdS)	�)�exportsN)�TunedException)�commands�
Controllerc@s,eZdZdd�Zdd�Zdd�Zdd�Zd	S)
�
TimerStorecCst�|_tj�|_dS)N)�dict�_timers�	threadingZLock�_timers_lock)�self�r� /usr/lib/python3.6/controller.py�__init__szTimerStore.__init__c
Cs |j�||j|<WdQRXdS)N)r
r)r�token�timerrrr
�store_timerszTimerStore.store_timercCsB|j�2y|j|}|j�|j|=WnYnXWdQRXdS)N)r
r�cancel)rrrrrr
�
drop_timers
zTimerStore.drop_timerc	Cs<|j�,x|jj�D]}|j�qW|jj�WdQRXdS)N)r
r�valuesr�clear)rrrrr
�
cancel_allszTimerStore.cancel_allN)�__name__�
__module__�__qualname__rrrrrrrr
r
s	rcs�eZdZdZ�fdd�Zdd�Zdd�Zdd	�Zej	d
�dd��Z
d
d�Zejdd�dUdd��Z
ejdd�dVdd��Zejdd�dWdd��ZdXdd�Zejdd�dYdd��Zejdd�dZdd ��Zd!d"�Zejdd#�d[d$d%��Zejdd#�d\d&d'��Zejdd�d]d(d)��Zejdd*�d^d+d,��Zejdd�d_d-d.��Zejdd�d`d/d0��Zejdd�dad1d2��Zejdd3�dbd4d5��Zejdd6�dcd7d8��Zejdd9�ddd:d;��Zejdd�ded<d=��Zejdd�dfd>d?��Zejdd�dgd@dA��Z ejddB�dhdCdD��Z!ejdd�didEdF��Z"ejddG�djdHdI��Z#ejdd�dkdJdK��Z$ejdLd#�dldMdN��Z%ejddO�dmdPdQ��Z&ejddR�dndSdT��Z'�Z(S)orz�
	Controller's purpose is to keep the program running, start/stop the tuning,
	and export the controller interface (currently only over D-Bus).
	cs8tt|�j�||_||_tj�|_t�|_	t
�|_dS)N)�superrr�_daemon�_global_configr	ZEvent�
_terminater�_cmdr�_timer_store)r�daemonZ
global_config)�	__class__rr
r+s
zController.__init__cCsxtjd�|j�}|jjtjtj�}|r6|r6tj�|rb|j	j
�x|jj|j	d�s`tj
�qFWtjd�|j�dS)z1
		Controller main loop. The call is blocking.
		zstarting controller�zterminating controllerN)�log�info�startr�get_bool�consts�
CFG_DAEMON�CFG_DEF_DAEMONrrrr�waitZperiod_check�stop)r�resr rrr
�run3s



zController.runcCs|jj�dS)N)r�set)rrrr
�	terminateFszController.terminatecCs0|jjj�s,|jjj�|j�s,|jjj�dS)N)rZ_sighup_processingZis_setr.�reloadr)rrrr
�sighupIszController.sighupZsbscCsdS)Nr)r�profile_name�resultZerrstrrrr
�profile_changedOszController.profile_changedcCstjj|�|jj|�dS)N)�tuned�logs�log_capture_finishrr)rrrrr
�_log_capture_abortXszController._log_capture_abortZii�sNcCsf|dkrdStjj|�}|dkr$dS|dkrVtj||j|gd�}|jj||�|j�|dkrbdS|S)N�r)�args)	r5r6�log_capture_startr	ZTimerr8rrr%)rZ	log_levelZtimeout�callerrrrrr
r<\szController.log_capture_startcCs4|dkrdStjj|�}|jj|�|dkr0dS|S)Nr:)r5r6r7rr)rrr=r,rrr
r7js
zController.log_capture_finishr:�bcCsD|dkrdS|jjtjtj�r:|jj�r,dS|jj�s:dS|jj�S)Nr:FT)	rr&r'r(r)r�
is_running�
is_enabledr%)rr=rrr
r%rs

zController.startFcCs,|jj�sd}n|jj|d�}|jj�|S)NT)�profile_switch)rr?r+rr)rrAr,rrr
�_stop}s


zController._stopcCs|dkrdS|jdd�S)Nr:F)rA)rB)rr=rrr
r+�szController.stopcCsp|dkrdS|jj�r*|jdd�}|s*dSy|jj�Wn.tk
rf}ztjd|�dSd}~XnX|j�S)Nr:FT)rAzFailed to reload TuneD: %s)rr?rBZreload_profile_configrr#�errorr%)rr=Zstop_ok�errr
r0�s
zController.reloadcCs�|jj�}d}d}d}z�y$|r,|jjdd�|jj||�Wnftjjk
r�}zFd}t|�}|r�|jjj	|kr�t
jd|�d}nt
jd|�WYdd}~XnXWd|r�|r�t
jd|�n|s�t
j
d�|jj�X||fS)	N�OKTF)rAz@Failed to reapply profile '%s'. Did it change on disk and break?zFailed to apply profile '%s'z>Applying previously applied (possibly out-dated) profile '%s'.z$Applying previously applied profile.)rr?r+Zset_profiler5�
exceptionsr�str�profile�namer#rC�warnr$r%)rr2�manualZwas_running�msg�successZreapplyrDrrr
�_switch_profile�s,
$
zController._switch_profilez(bs)cCs(|dkrdS|jj|�sdS|j|d�S)Nr:F�Unauthorized�Invalid profile_nameT)FrO)FrP)r�
is_valid_namerN)rr2r=rrr
�switch_profile�s
zController.switch_profilecCs |dkrdS|j�}|j|d�S)Nr:FrO)FrO)�recommend_profilerN)rr=r2rrr
�auto_profile�szController.auto_profilecCs*|dkrdS|jjdk	r"|jjjSdSdS)Nr:)rrHrI)rr=rrr
�active_profile�s

zController.active_profilez(ss)cCs�|dkrdS|jj}|dkrpy"|jj�\}}|dkr<|dk	}Wn0tk
rn}zd}t|�}||fSd}~XnX|rztjntj}|dfS)Nr:�unknownrO)rVrO)	rrKrZget_active_profilerrGr'ZACTIVE_PROFILE_MANUALZACTIVE_PROFILE_AUTO)rr=rKrHrD�moderCrrr
�profile_mode�szController.profile_modecCs|dkrdS|jjpdS)Nr:)r�post_loaded_profile)rr=rrr
rY�szController.post_loaded_profilecCsB|dkrdS|jj�r |jj�|jj�r>|jjddddd�dS)Nr:FT)Zsave_instantly)rr?r+r@Zset_all_profiles)rr=rrr
�disable�s


zController.disablecCs|dkrdS|jj�S)Nr:F)rr?)rr=rrr
r?�szController.is_running�ascCs|dkrgS|jjjj�S)Nr:)r�profile_loader�profile_locatorZget_known_names)rr=rrr
�profiles�szController.profilesza(ss)cCs|dkrgS|jjjj�S)Nr:)rr\r]Zget_known_names_summary)rr=rrr
�	profiles2�szController.profiles2z(bsss)cCsT|dks|jj|�rdS|dks*|dkr2|j�}t|jjjj|tj	tj
gdg��S)Nr:F)Fr:r:r:)rrQrU�tuplerr\r]Zget_profile_attrsr'ZPROFILE_ATTR_SUMMARYZPROFILE_ATTR_DESCRIPTION)rr2r=rrr
�profile_infos
zController.profile_infocCs|dkrdS|jjj�S)Nr:)rZprofile_recommenderZ	recommend)rr=rrr
rS
szController.recommend_profilecCs|dkrdS|jjdd�S)Nr:F)�ignore_missing)r�verify_profile)rr=rrr
rcszController.verify_profilecCs|dkrdS|jjdd�S)Nr:FT)rb)rrc)rr=rrr
�verify_profile_ignore_missingsz(Controller.verify_profile_ignore_missingz	a{sa{ss}}cCsz|dkriSi}xd|jj�D]V}|jjd�djdd�d}|j�}i||<x$|j�D]\}}t|�|||<qVWqW|S)zuReturn dictionary with accesible plugins

		Return:
		dictionary -- {plugin_name: {parameter_name: default_value}}
		r:�.r"�_���)r�get_all_pluginsr�splitZ_get_config_options�itemsrG)rr=ZpluginsZplugin_class�plugin_nameZconf_options�key�valrrr
rhszController.get_all_pluginscCs*|dks|jj|�rdS|jjt|��S)z"Return docstring of plugin's classr:)rrQr�get_plugin_documentationrG)rrkr=rrr
rn.sz#Controller.get_plugin_documentationza{ss}cCs*|dks|jj|�riS|jjt|��S)z�Return dictionary with plugin's parameters and their hints

		Parameters:
		plugin_name -- name of plugin

		Return:
		dictionary -- {parameter_name: hint}
		r:)rrQr�get_plugin_hintsrG)rrkr=rrr
ro5s
zController.get_plugin_hintscCsD|dks|jj|�rdS|jjr@|jjjr@|jjjj|�dSdS)z�Allows to dynamically add sockets to send signals to

		Parameters:
		path -- path to socket to register for sending signals

		Return:
		bool -- True on success
		r:FT)rrQrZ_applicationZ_unix_socket_exporterZregister_signal_path)r�pathr=rrr
�register_socket_signal_pathCs
z&Controller.register_socket_signal_pathZssc
Cs�|dkrdS|jj|�sdS|jj|�s,dSd}x2|jjjD]$}|j|kr<tjd|j�d}Pq<W|s�d|}tj|�d|fSt	|jj
|��}tjd	|jt|�f�x�|jjjD]�}|j|@}	t
|	�r�||	8}tjd
t|	�|j|jf�|jj|jjk�r6d|j|jjt|	�|j|jjf}tj|�d|fS|jj||	�|jj||	�q�Wt
|��r~dt|�}tj|�d|fSdS)Nr:FrO�Invalid devices�Invalid instance_namezFound instance '%s'.TzInstance '%s' not foundz-Instance '%s' trying to acquire devices '%s'.z8Moving devices '%s' from instance '%s' to instance '%s'.ztTarget instance '%s' is of type '%s', but devices '%s' are currently handled by instance '%s' which is of type '%s'.z2Ignoring devices not handled by any instance '%s'.rE)FrO)Frr)Frs)TrE)rrQr�
_unit_manager�	instancesrIr#�debugrCr.Zdevstr2devsrG�processed_devices�lenr$�pluginZ_remove_devices_nocheckZ_add_devices_nocheck)
rZdevices�
instance_namer=�foundZinstance_target�retsZdevs�instanceZdevs_movingrrr
�instance_acquire_devicesWsJ





z#Controller.instance_acquire_devicesz	(bsa(ss))cs�|dkrddgfS|jj��s(ddgfS�dkr\�|j�j�kr\d�}tj|�d|gfStdd�|jjj	�}�dkr�t�fdd�|�}d	d
t
tdd�|��fS)aReturn a list of active instances of a plugin or all active instances

		Parameters:
		plugin_name -- name of the plugin or an empty string

		Return:
		bool -- True on success
		string -- error message or "OK"
		list of string pairs -- [(instance_name, plugin_name)]
		r:FrOzInvalid plugin_namezPlugin '%s' does not existcSs|jS)N)Zactive)r}rrr
�<lambda>�sz*Controller.get_instances.<locals>.<lambda>cs|jj�kS)N)ryrI)r})rkrr
r�sTrEcSs|j|jjfS)N)rIry)r}rrr
r�s)rrQrh�keysr#rC�filterrrtru�list�map)rrkr=r|rur)rkr
�
get_instancess



zController.get_instancesz(bsas)cCsv|dkrddgfS|jj|�s(ddgfSx0|jjjD]"}|j|kr4ddtt|j��fSq4Wd|}t	j
|�d|gfS)z�Return a list of devices assigned to an instance

		Parameters:
		instance_name -- name of the instance

		Return:
		bool -- True on success
		string -- error message or "OK"
		list of strings -- device names
		r:FrOzInvalid instance_nameTrEzInstance '%s' not found)rrQrrtrurI�sortedr�rwr#rC)rrzr=r}r|rrr
�instance_get_devices�s



zController.instance_get_devices)N)N)N)F)N)N)N)N)N)N)N)N)N)N)N)N)N)N)N)N)N)N)N)N)N)N))rrr�__doc__rr-r/r1r�signalr4r8Zexportr<r7r%rBr+r0rNrRrTrUrXrYrZr?r^r_rarSrcrdrhrnrorqr~r�r��
__classcell__rr)r!r
r%sv	

























'

)r5rZ
tuned.logsZtuned.exceptionsrr	Ztuned.constsr'Ztuned.utils.commandsr�__all__r6�getr#�objectrZ
interfacesZExportableInterfacerrrrr
�<module>s

PK���\?˸���)__pycache__/__init__.cpython-36.opt-1.pycnu�[���3

�<�eK�@sddlTddlTddlTdS)�)�*N)ZapplicationZ
controllerZdaemon�rr�/usr/lib/python3.6/__init__.py�<module>sPK���\|��cs5s5+__pycache__/controller.cpython-36.opt-1.pycnu�[���3

`��g�4�@s�ddlmZddlZddlZddlmZddlZddljZddlm	Z	dgZ
ejj�Z
Gdd�de�ZGdd�dejjj�ZdS)	�)�exportsN)�TunedException)�commands�
Controllerc@s,eZdZdd�Zdd�Zdd�Zdd�Zd	S)
�
TimerStorecCst�|_tj�|_dS)N)�dict�_timers�	threadingZLock�_timers_lock)�self�r� /usr/lib/python3.6/controller.py�__init__szTimerStore.__init__c
Cs |j�||j|<WdQRXdS)N)r
r)r�token�timerrrr
�store_timerszTimerStore.store_timercCsB|j�2y|j|}|j�|j|=WnYnXWdQRXdS)N)r
r�cancel)rrrrrr
�
drop_timers
zTimerStore.drop_timerc	Cs<|j�,x|jj�D]}|j�qW|jj�WdQRXdS)N)r
r�valuesr�clear)rrrrr
�
cancel_allszTimerStore.cancel_allN)�__name__�
__module__�__qualname__rrrrrrrr
r
s	rcs�eZdZdZ�fdd�Zdd�Zdd�Zdd	�Zej	d
�dd��Z
d
d�Zejdd�dUdd��Z
ejdd�dVdd��Zejdd�dWdd��ZdXdd�Zejdd�dYdd��Zejdd�dZdd ��Zd!d"�Zejdd#�d[d$d%��Zejdd#�d\d&d'��Zejdd�d]d(d)��Zejdd*�d^d+d,��Zejdd�d_d-d.��Zejdd�d`d/d0��Zejdd�dad1d2��Zejdd3�dbd4d5��Zejdd6�dcd7d8��Zejdd9�ddd:d;��Zejdd�ded<d=��Zejdd�dfd>d?��Zejdd�dgd@dA��Z ejddB�dhdCdD��Z!ejdd�didEdF��Z"ejddG�djdHdI��Z#ejdd�dkdJdK��Z$ejdLd#�dldMdN��Z%ejddO�dmdPdQ��Z&ejddR�dndSdT��Z'�Z(S)orz�
	Controller's purpose is to keep the program running, start/stop the tuning,
	and export the controller interface (currently only over D-Bus).
	cs8tt|�j�||_||_tj�|_t�|_	t
�|_dS)N)�superrr�_daemon�_global_configr	ZEvent�
_terminater�_cmdr�_timer_store)r�daemonZ
global_config)�	__class__rr
r+s
zController.__init__cCsxtjd�|j�}|jjtjtj�}|r6|r6tj�|rb|j	j
�x|jj|j	d�s`tj
�qFWtjd�|j�dS)z1
		Controller main loop. The call is blocking.
		zstarting controller�zterminating controllerN)�log�info�startr�get_bool�consts�
CFG_DAEMON�CFG_DEF_DAEMONrrrr�waitZperiod_check�stop)r�resr rrr
�run3s



zController.runcCs|jj�dS)N)r�set)rrrr
�	terminateFszController.terminatecCs0|jjj�s,|jjj�|j�s,|jjj�dS)N)rZ_sighup_processingZis_setr.�reloadr)rrrr
�sighupIszController.sighupZsbscCsdS)Nr)r�profile_name�resultZerrstrrrr
�profile_changedOszController.profile_changedcCstjj|�|jj|�dS)N)�tuned�logs�log_capture_finishrr)rrrrr
�_log_capture_abortXszController._log_capture_abortZii�sNcCsf|dkrdStjj|�}|dkr$dS|dkrVtj||j|gd�}|jj||�|j�|dkrbdS|S)N�r)�args)	r5r6�log_capture_startr	ZTimerr8rrr%)rZ	log_levelZtimeout�callerrrrrr
r<\szController.log_capture_startcCs4|dkrdStjj|�}|jj|�|dkr0dS|S)Nr:)r5r6r7rr)rrr=r,rrr
r7js
zController.log_capture_finishr:�bcCsD|dkrdS|jjtjtj�r:|jj�r,dS|jj�s:dS|jj�S)Nr:FT)	rr&r'r(r)r�
is_running�
is_enabledr%)rr=rrr
r%rs

zController.startFcCs,|jj�sd}n|jj|d�}|jj�|S)NT)�profile_switch)rr?r+rr)rrAr,rrr
�_stop}s


zController._stopcCs|dkrdS|jdd�S)Nr:F)rA)rB)rr=rrr
r+�szController.stopcCsp|dkrdS|jj�r*|jdd�}|s*dSy|jj�Wn.tk
rf}ztjd|�dSd}~XnX|j�S)Nr:FT)rAzFailed to reload TuneD: %s)rr?rBZreload_profile_configrr#�errorr%)rr=Zstop_ok�errr
r0�s
zController.reloadcCs�|jj�}d}d}d}z�y$|r,|jjdd�|jj||�Wnftjjk
r�}zFd}t|�}|r�|jjj	|kr�t
jd|�d}nt
jd|�WYdd}~XnXWd|r�|r�t
jd|�n|s�t
j
d�|jj�X||fS)	N�OKTF)rAz@Failed to reapply profile '%s'. Did it change on disk and break?zFailed to apply profile '%s'z>Applying previously applied (possibly out-dated) profile '%s'.z$Applying previously applied profile.)rr?r+Zset_profiler5�
exceptionsr�str�profile�namer#rC�warnr$r%)rr2�manualZwas_running�msg�successZreapplyrDrrr
�_switch_profile�s,
$
zController._switch_profilez(bs)cCs(|dkrdS|jj|�sdS|j|d�S)Nr:F�Unauthorized�Invalid profile_nameT)FrO)FrP)r�
is_valid_namerN)rr2r=rrr
�switch_profile�s
zController.switch_profilecCs |dkrdS|j�}|j|d�S)Nr:FrO)FrO)�recommend_profilerN)rr=r2rrr
�auto_profile�szController.auto_profilecCs*|dkrdS|jjdk	r"|jjjSdSdS)Nr:)rrHrI)rr=rrr
�active_profile�s

zController.active_profilez(ss)cCs�|dkrdS|jj}|dkrpy"|jj�\}}|dkr<|dk	}Wn0tk
rn}zd}t|�}||fSd}~XnX|rztjntj}|dfS)Nr:�unknownrO)rVrO)	rrKrZget_active_profilerrGr'ZACTIVE_PROFILE_MANUALZACTIVE_PROFILE_AUTO)rr=rKrHrD�moderCrrr
�profile_mode�szController.profile_modecCs|dkrdS|jjpdS)Nr:)r�post_loaded_profile)rr=rrr
rY�szController.post_loaded_profilecCsB|dkrdS|jj�r |jj�|jj�r>|jjddddd�dS)Nr:FT)Zsave_instantly)rr?r+r@Zset_all_profiles)rr=rrr
�disable�s


zController.disablecCs|dkrdS|jj�S)Nr:F)rr?)rr=rrr
r?�szController.is_running�ascCs|dkrgS|jjjj�S)Nr:)r�profile_loader�profile_locatorZget_known_names)rr=rrr
�profiles�szController.profilesza(ss)cCs|dkrgS|jjjj�S)Nr:)rr\r]Zget_known_names_summary)rr=rrr
�	profiles2�szController.profiles2z(bsss)cCsT|dks|jj|�rdS|dks*|dkr2|j�}t|jjjj|tj	tj
gdg��S)Nr:F)Fr:r:r:)rrQrU�tuplerr\r]Zget_profile_attrsr'ZPROFILE_ATTR_SUMMARYZPROFILE_ATTR_DESCRIPTION)rr2r=rrr
�profile_infos
zController.profile_infocCs|dkrdS|jjj�S)Nr:)rZprofile_recommenderZ	recommend)rr=rrr
rS
szController.recommend_profilecCs|dkrdS|jjdd�S)Nr:F)�ignore_missing)r�verify_profile)rr=rrr
rcszController.verify_profilecCs|dkrdS|jjdd�S)Nr:FT)rb)rrc)rr=rrr
�verify_profile_ignore_missingsz(Controller.verify_profile_ignore_missingz	a{sa{ss}}cCsz|dkriSi}xd|jj�D]V}|jjd�djdd�d}|j�}i||<x$|j�D]\}}t|�|||<qVWqW|S)zuReturn dictionary with accesible plugins

		Return:
		dictionary -- {plugin_name: {parameter_name: default_value}}
		r:�.r"�_���)r�get_all_pluginsr�splitZ_get_config_options�itemsrG)rr=ZpluginsZplugin_class�plugin_nameZconf_options�key�valrrr
rhszController.get_all_pluginscCs*|dks|jj|�rdS|jjt|��S)z"Return docstring of plugin's classr:)rrQr�get_plugin_documentationrG)rrkr=rrr
rn.sz#Controller.get_plugin_documentationza{ss}cCs*|dks|jj|�riS|jjt|��S)z�Return dictionary with plugin's parameters and their hints

		Parameters:
		plugin_name -- name of plugin

		Return:
		dictionary -- {parameter_name: hint}
		r:)rrQr�get_plugin_hintsrG)rrkr=rrr
ro5s
zController.get_plugin_hintscCsD|dks|jj|�rdS|jjr@|jjjr@|jjjj|�dSdS)z�Allows to dynamically add sockets to send signals to

		Parameters:
		path -- path to socket to register for sending signals

		Return:
		bool -- True on success
		r:FT)rrQrZ_applicationZ_unix_socket_exporterZregister_signal_path)r�pathr=rrr
�register_socket_signal_pathCs
z&Controller.register_socket_signal_pathZssc
Cs�|dkrdS|jj|�sdS|jj|�s,dSd}x2|jjjD]$}|j|kr<tjd|j�d}Pq<W|s�d|}tj|�d|fSt	|jj
|��}tjd	|jt|�f�x�|jjjD]�}|j|@}	t
|	�r�||	8}tjd
t|	�|j|jf�|jj|jjk�r6d|j|jjt|	�|j|jjf}tj|�d|fS|jj||	�|jj||	�q�Wt
|��r~dt|�}tj|�d|fSdS)Nr:FrO�Invalid devices�Invalid instance_namezFound instance '%s'.TzInstance '%s' not foundz-Instance '%s' trying to acquire devices '%s'.z8Moving devices '%s' from instance '%s' to instance '%s'.ztTarget instance '%s' is of type '%s', but devices '%s' are currently handled by instance '%s' which is of type '%s'.z2Ignoring devices not handled by any instance '%s'.rE)FrO)Frr)Frs)TrE)rrQr�
_unit_manager�	instancesrIr#�debugrCr.Zdevstr2devsrG�processed_devices�lenr$�pluginZ_remove_devices_nocheckZ_add_devices_nocheck)
rZdevices�
instance_namer=�foundZinstance_target�retsZdevs�instanceZdevs_movingrrr
�instance_acquire_devicesWsJ





z#Controller.instance_acquire_devicesz	(bsa(ss))cs�|dkrddgfS|jj��s(ddgfS�dkr\�|j�j�kr\d�}tj|�d|gfStdd�|jjj	�}�dkr�t�fdd�|�}d	d
t
tdd�|��fS)aReturn a list of active instances of a plugin or all active instances

		Parameters:
		plugin_name -- name of the plugin or an empty string

		Return:
		bool -- True on success
		string -- error message or "OK"
		list of string pairs -- [(instance_name, plugin_name)]
		r:FrOzInvalid plugin_namezPlugin '%s' does not existcSs|jS)N)Zactive)r}rrr
�<lambda>�sz*Controller.get_instances.<locals>.<lambda>cs|jj�kS)N)ryrI)r})rkrr
r�sTrEcSs|j|jjfS)N)rIry)r}rrr
r�s)rrQrh�keysr#rC�filterrrtru�list�map)rrkr=r|rur)rkr
�
get_instancess



zController.get_instancesz(bsas)cCsv|dkrddgfS|jj|�s(ddgfSx0|jjjD]"}|j|kr4ddtt|j��fSq4Wd|}t	j
|�d|gfS)z�Return a list of devices assigned to an instance

		Parameters:
		instance_name -- name of the instance

		Return:
		bool -- True on success
		string -- error message or "OK"
		list of strings -- device names
		r:FrOzInvalid instance_nameTrEzInstance '%s' not found)rrQrrtrurI�sortedr�rwr#rC)rrzr=r}r|rrr
�instance_get_devices�s



zController.instance_get_devices)N)N)N)F)N)N)N)N)N)N)N)N)N)N)N)N)N)N)N)N)N)N)N)N)N)N))rrr�__doc__rr-r/r1r�signalr4r8Zexportr<r7r%rBr+r0rNrRrTrUrXrYrZr?r^r_rarSrcrdrhrnrorqr~r�r��
__classcell__rr)r!r
r%sv	

























'

)r5rZ
tuned.logsZtuned.exceptionsrr	Ztuned.constsr'Ztuned.utils.commandsr�__all__r6�getr#�objectrZ
interfacesZExportableInterfacerrrrr
�<module>s

PK���\��U
�4�4
controller.pynu�[���from tuned import exports
import tuned.logs
import tuned.exceptions
from tuned.exceptions import TunedException
import threading
import tuned.consts as consts
from tuned.utils.commands import commands

__all__ = ["Controller"]

log = tuned.logs.get()

class TimerStore(object):
	def __init__(self):
		self._timers = dict()
		self._timers_lock = threading.Lock()

	def store_timer(self, token, timer):
		with self._timers_lock:
			self._timers[token] = timer

	def drop_timer(self, token):
		with self._timers_lock:
			try:
				timer = self._timers[token]
				timer.cancel()
				del self._timers[token]
			except:
				pass

	def cancel_all(self):
		with self._timers_lock:
			for timer in self._timers.values():
				timer.cancel()
			self._timers.clear()

class Controller(tuned.exports.interfaces.ExportableInterface):
	"""
	Controller's purpose is to keep the program running, start/stop the tuning,
	and export the controller interface (currently only over D-Bus).
	"""

	def __init__(self, daemon, global_config):
		super(Controller, self).__init__()
		self._daemon = daemon
		self._global_config = global_config
		self._terminate = threading.Event()
		self._cmd = commands()
		self._timer_store = TimerStore()

	def run(self):
		"""
		Controller main loop. The call is blocking.
		"""
		log.info("starting controller")
		res = self.start()
		daemon = self._global_config.get_bool(consts.CFG_DAEMON, consts.CFG_DEF_DAEMON)
		if not res and daemon:
			exports.start()

		if daemon:
			self._terminate.clear()
			# we have to pass some timeout, otherwise signals will not work
			while not self._cmd.wait(self._terminate, 1):
				exports.period_check()

		log.info("terminating controller")
		self.stop()

	def terminate(self):
		self._terminate.set()

	def sighup(self):
		if not self._daemon._sighup_processing.is_set():
			self._daemon._sighup_processing.set()
			if not self.reload():
				self._daemon._sighup_processing.clear()

	@exports.signal("sbs")
	def profile_changed(self, profile_name, result, errstr):
		pass

	# exports decorator checks the authorization (currently through polkit), caller is None if
	# no authorization was performed (i.e. the call should process as authorized), string
	# identifying caller (with DBus it's the caller bus name) if authorized and empty
	# string if not authorized, caller must be the last argument

	def _log_capture_abort(self, token):
		tuned.logs.log_capture_finish(token)
		self._timer_store.drop_timer(token)

	@exports.export("ii", "s")
	def log_capture_start(self, log_level, timeout, caller = None):
		if caller == "":
			return ""
		token = tuned.logs.log_capture_start(log_level)
		if token is None:
			return ""
		if timeout > 0:
			timer = threading.Timer(timeout,
					self._log_capture_abort, args = [token])
			self._timer_store.store_timer(token, timer)
			timer.start()
		return "" if token is None else token

	@exports.export("s", "s")
	def log_capture_finish(self, token, caller = None):
		if caller == "":
			return ""
		res = tuned.logs.log_capture_finish(token)
		self._timer_store.drop_timer(token)
		return "" if res is None else res

	@exports.export("", "b")
	def start(self, caller = None):
		if caller == "":
			return False
		if self._global_config.get_bool(consts.CFG_DAEMON, consts.CFG_DEF_DAEMON):
			if self._daemon.is_running():
				return True
			elif not self._daemon.is_enabled():
				return False
		return self._daemon.start()

	def _stop(self, profile_switch = False):
		if not self._daemon.is_running():
			res = True
		else:
			res = self._daemon.stop(profile_switch = profile_switch)
		self._timer_store.cancel_all()
		return res

	@exports.export("", "b")
	def stop(self, caller = None):
		if caller == "":
			return False
		return self._stop(profile_switch = False)

	@exports.export("", "b")
	def reload(self, caller = None):
		if caller == "":
			return False
		if self._daemon.is_running():
			stop_ok = self._stop(profile_switch = True)
			if not stop_ok:
				return False
		try:
			self._daemon.reload_profile_config()
		except TunedException as e:
			log.error("Failed to reload TuneD: %s" % e)
			return False
		return self.start()

	def _switch_profile(self, profile_name, manual):
		was_running = self._daemon.is_running()
		msg = "OK"
		success = True
		reapply = False
		try:
			if was_running:
				self._daemon.stop(profile_switch = True)
			self._daemon.set_profile(profile_name, manual)
		except tuned.exceptions.TunedException as e:
			success = False
			msg = str(e)
			if was_running and self._daemon.profile.name == profile_name:
				log.error("Failed to reapply profile '%s'. Did it change on disk and break?" % profile_name)
				reapply = True
			else:
				log.error("Failed to apply profile '%s'" % profile_name)
		finally:
			if was_running:
				if reapply:
					log.warn("Applying previously applied (possibly out-dated) profile '%s'." % profile_name)
				elif not success:
					log.info("Applying previously applied profile.")
				self._daemon.start()

		return (success, msg)

	@exports.export("s", "(bs)")
	def switch_profile(self, profile_name, caller = None):
		if caller == "":
			return (False, "Unauthorized")
		if not self._cmd.is_valid_name(profile_name):
			return (False, "Invalid profile_name")
		return self._switch_profile(profile_name, True)

	@exports.export("", "(bs)")
	def auto_profile(self, caller = None):
		if caller == "":
			return (False, "Unauthorized")
		profile_name = self.recommend_profile()
		return self._switch_profile(profile_name, False)

	@exports.export("", "s")
	def active_profile(self, caller = None):
		if caller == "":
			return ""
		if self._daemon.profile is not None:
			return self._daemon.profile.name
		else:
			return ""

	@exports.export("", "(ss)")
	def profile_mode(self, caller = None):
		if caller == "":
			return "unknown", "Unauthorized"
		manual = self._daemon.manual
		if manual is None:
			# This means no profile is applied. Check the preset value.
			try:
				profile, manual = self._cmd.get_active_profile()
				if manual is None:
					manual = profile is not None
			except TunedException as e:
				mode = "unknown"
				error = str(e)
				return mode, error
		mode = consts.ACTIVE_PROFILE_MANUAL if manual else consts.ACTIVE_PROFILE_AUTO
		return mode, ""

	@exports.export("", "s")
	def post_loaded_profile(self, caller = None):
		if caller == "":
			return ""
		return self._daemon.post_loaded_profile or ""

	@exports.export("", "b")
	def disable(self, caller = None):
		if caller == "":
			return False
		if self._daemon.is_running():
			self._daemon.stop()
		if self._daemon.is_enabled():
			self._daemon.set_all_profiles(None, True, None,
						      save_instantly=True)
		return True

	@exports.export("", "b")
	def is_running(self, caller = None):
		if caller == "":
			return False
		return self._daemon.is_running()

	@exports.export("", "as")
	def profiles(self, caller = None):
		if caller == "":
			return []
		return self._daemon.profile_loader.profile_locator.get_known_names()

	@exports.export("", "a(ss)")
	def profiles2(self, caller = None):
		if caller == "":
			return []
		return self._daemon.profile_loader.profile_locator.get_known_names_summary()

	@exports.export("s", "(bsss)")
	def profile_info(self, profile_name, caller = None):
		if caller == "" or not self._cmd.is_valid_name(profile_name):
			return (False, "", "", "")
		if profile_name is None or profile_name == "":
			profile_name = self.active_profile()
		return tuple(self._daemon.profile_loader.profile_locator.get_profile_attrs(profile_name, [consts.PROFILE_ATTR_SUMMARY, consts.PROFILE_ATTR_DESCRIPTION], [""]))

	@exports.export("", "s")
	def recommend_profile(self, caller = None):
		if caller == "":
			return ""
		return self._daemon.profile_recommender.recommend()

	@exports.export("", "b")
	def verify_profile(self, caller = None):
		if caller == "":
			return False
		return self._daemon.verify_profile(ignore_missing = False)

	@exports.export("", "b")
	def verify_profile_ignore_missing(self, caller = None):
		if caller == "":
			return False
		return self._daemon.verify_profile(ignore_missing = True)

	@exports.export("", "a{sa{ss}}")
	def get_all_plugins(self, caller = None):
		"""Return dictionary with accesible plugins

		Return:
		dictionary -- {plugin_name: {parameter_name: default_value}}
		"""
		if caller == "":
			return {}
		plugins = {}
		for plugin_class in self._daemon.get_all_plugins():
			plugin_name = plugin_class.__module__.split(".")[-1].split("_", 1)[1]
			conf_options = plugin_class._get_config_options()
			plugins[plugin_name] = {}
			for key, val in conf_options.items():
				plugins[plugin_name][key] = str(val)
		return plugins

	@exports.export("s","s")
	def get_plugin_documentation(self, plugin_name, caller = None):
		"""Return docstring of plugin's class"""
		if caller == "" or not self._cmd.is_valid_name(plugin_name):
			return ""
		return self._daemon.get_plugin_documentation(str(plugin_name))

	@exports.export("s","a{ss}")
	def get_plugin_hints(self, plugin_name, caller = None):
		"""Return dictionary with plugin's parameters and their hints

		Parameters:
		plugin_name -- name of plugin

		Return:
		dictionary -- {parameter_name: hint}
		"""
		if caller == "" or not self._cmd.is_valid_name(plugin_name):
			return {}
		return self._daemon.get_plugin_hints(str(plugin_name))

	@exports.export("s", "b")
	def register_socket_signal_path(self, path, caller = None):
		"""Allows to dynamically add sockets to send signals to

		Parameters:
		path -- path to socket to register for sending signals

		Return:
		bool -- True on success
		"""
		if caller == "" or not self._cmd.is_valid_name(path):
			return False
		if self._daemon._application and self._daemon._application._unix_socket_exporter:
			self._daemon._application._unix_socket_exporter.register_signal_path(path)
			return True
		return False

	# devices - devices to migrate from other instances, string of form "dev1,dev2,dev3,..."
	#	or "cpulist:CPULIST", where CPULIST is e.g. "0-3,6,8-9"
	# instance_name - instance where to migrate devices
	@exports.export("ss", "(bs)")
	def instance_acquire_devices(self, devices, instance_name, caller = None):
		if caller == "":
			return (False, "Unauthorized")
		if not self._cmd.is_valid_name(devices):
			return (False, "Invalid devices")
		if not self._cmd.is_valid_name(instance_name):
			return (False, "Invalid instance_name")
		found = False
		for instance_target in self._daemon._unit_manager.instances:
			if instance_target.name == instance_name:
				log.debug("Found instance '%s'." % instance_target.name)
				found = True
				break
		if not found:
			rets = "Instance '%s' not found" % instance_name
			log.error(rets)
			return (False, rets)
		devs = set(self._cmd.devstr2devs(devices))
		log.debug("Instance '%s' trying to acquire devices '%s'." % (instance_target.name, str(devs)))
		for instance in self._daemon._unit_manager.instances:
			devs_moving = instance.processed_devices & devs
			if len(devs_moving):
				devs -= devs_moving
				log.info("Moving devices '%s' from instance '%s' to instance '%s'." % (str(devs_moving),
					instance.name, instance_target.name))
				if (instance.plugin.name != instance_target.plugin.name):
					rets = "Target instance '%s' is of type '%s', but devices '%s' are currently handled by " \
						"instance '%s' which is of type '%s'." % (instance_target.name,
						instance_target.plugin.name, str(devs_moving), instance.name, instance.plugin.name)
					log.error(rets)
					return (False, rets)
				instance.plugin._remove_devices_nocheck(instance, devs_moving)
				instance_target.plugin._add_devices_nocheck(instance_target, devs_moving)
		if (len(devs)):
			rets = "Ignoring devices not handled by any instance '%s'." % str(devs)
			log.info(rets)
			return (False, rets)
		return (True, "OK")

	@exports.export("s", "(bsa(ss))")
	def get_instances(self, plugin_name, caller = None):
		"""Return a list of active instances of a plugin or all active instances

		Parameters:
		plugin_name -- name of the plugin or an empty string

		Return:
		bool -- True on success
		string -- error message or "OK"
		list of string pairs -- [(instance_name, plugin_name)]
		"""
		if caller == "":
			return (False, "Unauthorized", [])
		if not self._cmd.is_valid_name(plugin_name):
			return (False, "Invalid plugin_name", [])
		if plugin_name != "" and plugin_name not in self.get_all_plugins().keys():
			rets = "Plugin '%s' does not exist" % plugin_name
			log.error(rets)
			return (False, rets, [])
		instances = filter(lambda instance: instance.active, self._daemon._unit_manager.instances)
		if plugin_name != "":
			instances = filter(lambda instance: instance.plugin.name == plugin_name, instances)
		return (True, "OK", list(map(lambda instance: (instance.name, instance.plugin.name), instances)))

	@exports.export("s", "(bsas)")
	def instance_get_devices(self, instance_name, caller = None):
		"""Return a list of devices assigned to an instance

		Parameters:
		instance_name -- name of the instance

		Return:
		bool -- True on success
		string -- error message or "OK"
		list of strings -- device names
		"""
		if caller == "":
			return (False, "Unauthorized", [])
		if not self._cmd.is_valid_name(instance_name):
			return (False, "Invalid instance_name", [])
		for instance in self._daemon._unit_manager.instances:
			if instance.name == instance_name:
				return (True, "OK", sorted(list(instance.processed_devices)))
		rets = "Instance '%s' not found" % instance_name
		log.error(rets)
		return (False, rets, [])
PK���\C$���3�3	daemon.pynu�[���import os
import errno
import threading
import tuned.logs
from tuned.exceptions import TunedException
from tuned.profiles.exceptions import InvalidProfileException
import tuned.consts as consts
from tuned.utils.commands import commands
from tuned import exports
from tuned.utils.profile_recommender import ProfileRecommender
import re

log = tuned.logs.get()


class Daemon(object):
	def __init__(self, unit_manager, profile_loader, profile_names=None, config=None, application=None):
		log.debug("initializing daemon")
		self._daemon = consts.CFG_DEF_DAEMON
		self._sleep_interval = int(consts.CFG_DEF_SLEEP_INTERVAL)
		self._update_interval = int(consts.CFG_DEF_UPDATE_INTERVAL)
		self._dynamic_tuning = consts.CFG_DEF_DYNAMIC_TUNING
		self._recommend_command = True
		self._rollback = consts.CFG_DEF_ROLLBACK
		if config is not None:
			self._daemon = config.get_bool(consts.CFG_DAEMON, consts.CFG_DEF_DAEMON)
			self._sleep_interval = int(config.get(consts.CFG_SLEEP_INTERVAL, consts.CFG_DEF_SLEEP_INTERVAL))
			self._update_interval = int(config.get(consts.CFG_UPDATE_INTERVAL, consts.CFG_DEF_UPDATE_INTERVAL))
			self._dynamic_tuning = config.get_bool(consts.CFG_DYNAMIC_TUNING, consts.CFG_DEF_DYNAMIC_TUNING)
			self._recommend_command = config.get_bool(consts.CFG_RECOMMEND_COMMAND, consts.CFG_DEF_RECOMMEND_COMMAND)
			self._rollback = config.get(consts.CFG_ROLLBACK, consts.CFG_DEF_ROLLBACK)
		self._application = application
		if self._sleep_interval <= 0:
			self._sleep_interval = int(consts.CFG_DEF_SLEEP_INTERVAL)
		if self._update_interval == 0:
			self._dynamic_tuning = False
		elif self._update_interval < self._sleep_interval:
			self._update_interval = self._sleep_interval
		self._sleep_cycles = self._update_interval // self._sleep_interval
		log.info("using sleep interval of %d second(s)" % self._sleep_interval)
		if self._dynamic_tuning:
			log.info("dynamic tuning is enabled (can be overridden by plugins)")
			log.info("using update interval of %d second(s) (%d times of the sleep interval)" % (self._sleep_cycles * self._sleep_interval, self._sleep_cycles))

		self._profile_recommender = ProfileRecommender(is_hardcoded = not self._recommend_command)
		self._unit_manager = unit_manager
		self._profile_loader = profile_loader
		self._init_threads()
		self._cmd = commands()
		try:
			self._init_profile(profile_names)
		except TunedException as e:
			log.error("Cannot set initial profile. No tunings will be enabled: %s" % e)

	def _init_threads(self):
		self._thread = None
		self._terminate = threading.Event()
		# Flag which is set if terminating due to profile_switch
		self._terminate_profile_switch = threading.Event()
		# Flag which is set if there is no operation in progress
		self._not_used = threading.Event()
		# Flag which is set if SIGHUP is being processed
		self._sighup_processing = threading.Event()
		self._not_used.set()
		self._profile_applied = threading.Event()

	def reload_profile_config(self):
		"""Read configuration files again and load profile according to them"""
		self._init_profile(None)

	def _init_profile(self, profile_names):
		manual = True
		post_loaded_profile = self._cmd.get_post_loaded_profile()
		if profile_names is None:
			(profile_names, manual) = self._get_startup_profile()
			if profile_names is None:
				msg = "No profile is preset, running in manual mode. "
				if post_loaded_profile:
					msg += "Only post-loaded profile will be enabled"
				else:
					msg += "No profile will be enabled."
				log.info(msg)
		# Passed through '-p' cmdline option
		elif profile_names == "":
			if post_loaded_profile:
				log.info("Only post-loaded profile will be enabled")
			else:
				log.info("No profile will be enabled.")

		self._profile = None
		self._manual = None
		self._active_profiles = []
		self._post_loaded_profile = None
		self.set_all_profiles(profile_names, manual, post_loaded_profile)

	def _load_profiles(self, profile_names, manual):
		profile_names = profile_names or ""
		profile_list = profile_names.split()

		if self._post_loaded_profile:
			log.info("Using post-loaded profile '%s'"
				 % self._post_loaded_profile)
			profile_list = profile_list + [self._post_loaded_profile]
		for profile in profile_list:
			if profile not in self.profile_loader.profile_locator.get_known_names():
				errstr = "Requested profile '%s' doesn't exist." % profile
				self._notify_profile_changed(profile_names, False, errstr)
				raise TunedException(errstr)
		try:
			if profile_list:
				self._profile = self._profile_loader.load(profile_list)
			else:
				self._profile = None

			self._manual = manual
			self._active_profiles = profile_names.split()
		except InvalidProfileException as e:
			errstr = "Cannot load profile(s) '%s': %s" % (" ".join(profile_list), e)
			self._notify_profile_changed(profile_names, False, errstr)
			raise TunedException(errstr)

	def set_profile(self, profile_names, manual):
		if self.is_running():
			errstr = "Cannot set profile while the daemon is running."
			self._notify_profile_changed(profile_names, False,
						     errstr)
			raise TunedException(errstr)

		self._load_profiles(profile_names, manual)

	def _set_post_loaded_profile(self, profile_name):
		if not profile_name:
			self._post_loaded_profile = None
		elif len(profile_name.split()) > 1:
			errstr = "Whitespace is not allowed in profile names; only a single post-loaded profile is allowed."
			raise TunedException(errstr)
		else:
			self._post_loaded_profile = profile_name

	def set_all_profiles(self, active_profiles, manual, post_loaded_profile,
			     save_instantly=False):
		if self.is_running():
			errstr = "Cannot set profile while the daemon is running."
			self._notify_profile_changed(active_profiles, False,
						     errstr)
			raise TunedException(errstr)

		self._set_post_loaded_profile(post_loaded_profile)
		self._load_profiles(active_profiles, manual)

		if save_instantly:
			self._save_active_profile(active_profiles, manual)
			self._save_post_loaded_profile(post_loaded_profile)

	@property
	def profile(self):
		return self._profile

	@property
	def manual(self):
		return self._manual

	@property
	def post_loaded_profile(self):
		# Return the profile name only if the profile is active. If
		# the profile is not active, then the value is meaningless.
		return self._post_loaded_profile if self._profile else None

	@property
	def profile_recommender(self):
		return self._profile_recommender

	@property
	def profile_loader(self):
		return self._profile_loader

	# send notification when profile is changed (everything is setup) or if error occured
	# result: True - OK, False - error occured
	def _notify_profile_changed(self, profile_names, result, errstr):
		if self._application is not None:
			exports.send_signal(consts.SIGNAL_PROFILE_CHANGED, profile_names, result, errstr)
		return errstr

	def _full_rollback_required(self):
		retcode, out = self._cmd.execute(["systemctl", "is-system-running"], no_errors = [0])
		if retcode < 0:
			return False
		if out[:8] == "stopping":
			return False
		retcode, out = self._cmd.execute(["systemctl", "list-jobs"], no_errors = [0])
		return re.search(r"\b(shutdown|reboot|halt|poweroff)\.target.*start", out) is None and not retcode

	def _thread_code(self):
		if self._profile is None:
			raise TunedException("Cannot start the daemon without setting a profile.")

		self._unit_manager.create(self._profile.units)
		self._save_active_profile(" ".join(self._active_profiles),
					  self._manual)
		self._save_post_loaded_profile(self._post_loaded_profile)
		self._unit_manager.start_tuning()
		self._profile_applied.set()
		log.info("static tuning from profile '%s' applied" % self._profile.name)
		if self._daemon:
			exports.start()
		profile_names = " ".join(self._active_profiles)
		self._notify_profile_changed(profile_names, True, "OK")
		self._sighup_processing.clear()

		if self._daemon:
			# In python 2 interpreter with applied patch for rhbz#917709 we need to periodically
			# poll, otherwise the python will not have chance to update events / locks (due to GIL)
			# and e.g. DBus control will not work. The polling interval of 1 seconds (which is
			# the default) is still much better than 50 ms polling with unpatched interpreter.
			# For more details see TuneD rhbz#917587.
			_sleep_cnt = self._sleep_cycles
			while not self._cmd.wait(self._terminate, self._sleep_interval):
				if self._dynamic_tuning:
					_sleep_cnt -= 1
					if _sleep_cnt <= 0:
						_sleep_cnt = self._sleep_cycles
						log.debug("updating monitors")
						self._unit_manager.update_monitors()
						log.debug("performing tunings")
						self._unit_manager.update_tuning()

		self._profile_applied.clear()

		# wait for others to complete their tasks, use timeout 3 x sleep_interval to prevent
		# deadlocks
		i = 0
		while not self._cmd.wait(self._not_used, self._sleep_interval) and i < 3:
			i += 1

		# if terminating due to profile switch
		if self._terminate_profile_switch.is_set():
			rollback = consts.ROLLBACK_FULL
		else:
			# Assume only soft rollback is needed. Soft rollback means reverting all
			# non-persistent tunings applied by a plugin instance. In contrast to full
			# rollback, information about what to revert is kept in RAM (volatile
			# memory) -- TuneD data structures.
			# With systemd TuneD detects system shutdown and in such a case it doesn't
			# perform full cleanup. If the system is not shutting down, it means that TuneD
			# was explicitly stopped by the user and in such case do the full cleanup. On
			# systems without systemd, full cleanup is never performed.
			rollback = consts.ROLLBACK_SOFT
			if not self._full_rollback_required():
				log.info("terminating TuneD due to system shutdown / reboot")
			elif self._rollback == "not_on_exit":
				# no rollback on TuneD exit whatsoever
				rollback = consts.ROLLBACK_NONE
				log.info("terminating TuneD and not rolling back any changes due to '%s' option in '%s'" % (consts.CFG_ROLLBACK, consts.GLOBAL_CONFIG_FILE))
			else:
				if self._daemon:
					log.info("terminating TuneD, rolling back all changes")
					rollback = consts.ROLLBACK_FULL
				else:
					log.info("terminating TuneD in one-shot mode")
		if self._daemon:
			self._unit_manager.stop_tuning(rollback)
		self._unit_manager.destroy_all()

	def _save_active_profile(self, profile_names, manual):
		try:
			self._cmd.save_active_profile(profile_names, manual)
		except TunedException as e:
			log.error(str(e))

	def _save_post_loaded_profile(self, profile_name):
		try:
			self._cmd.save_post_loaded_profile(profile_name)
		except TunedException as e:
			log.error(str(e))

	def _get_recommended_profile(self):
		log.info("Running in automatic mode, checking what profile is recommended for your configuration.")
		profile = self._profile_recommender.recommend()
		log.info("Using '%s' profile" % profile)
		return profile

	def _get_startup_profile(self):
		profile, manual = self._cmd.get_active_profile()
		if manual is None:
			manual = profile is not None
		if not manual:
			profile = self._get_recommended_profile()
		return profile, manual

	def get_all_plugins(self):
		"""Return all accessible plugin classes"""
		return self._unit_manager.plugins_repository.load_all_plugins()

	def get_plugin_documentation(self, plugin_name):
		"""Return plugin class docstring"""
		try:
			plugin_class = self._unit_manager.plugins_repository.load_plugin(
				plugin_name
			)
		except ImportError:
			return ""
		return plugin_class.__doc__

	def get_plugin_hints(self, plugin_name):
		"""Return plugin's parameters and their hints

		Parameters:
		plugin_name -- plugins name

		Return:
		dictionary -- {parameter_name: hint}
		"""
		try:
			plugin_class = self._unit_manager.plugins_repository.load_plugin(
				plugin_name
			)
		except ImportError:
			return {}
		return plugin_class.get_config_options_hints()

	def is_enabled(self):
		return self._profile is not None

	def is_running(self):
		return self._thread is not None and self._thread.is_alive()

	def start(self):
		if self.is_running():
			return False

		if self._profile is None:
			return False

		log.info("starting tuning")
		self._not_used.set()
		self._thread = threading.Thread(target=self._thread_code)
		self._terminate_profile_switch.clear()
		self._terminate.clear()
		self._thread.start()
		return True

	def verify_profile(self, ignore_missing):
		if not self.is_running():
			log.error("TuneD is not running")
			return False

		if self._profile is None:
			log.error("no profile is set")
			return False

		if not self._profile_applied.is_set():
			log.error("profile is not applied")
			return False

		# using daemon, the main loop mustn't exit before our completion
		self._not_used.clear()
		log.info("verifying profile(s): %s" % self._profile.name)
		ret = self._unit_manager.verify_tuning(ignore_missing)
		# main loop is allowed to exit
		self._not_used.set()
		return ret

	# profile_switch is helper telling plugins whether the stop is due to profile switch
	def stop(self, profile_switch = False):
		if not self.is_running():
			return False
		log.info("stopping tuning")
		if profile_switch:
			self._terminate_profile_switch.set()
		self._terminate.set()
		self._thread.join()
		self._thread = None

		return True
PK���\J���KK__init__.pynu�[���from .application import *
from .controller import *
from .daemon import *
PK���\����application.pynu�[���from tuned import storage, units, monitors, plugins, profiles, exports, hardware
from tuned.exceptions import TunedException
import tuned.logs
import tuned.version
from . import controller
from . import daemon
import signal
import os
import sys
import select
import struct
import tuned.consts as consts
from tuned.utils.global_config import GlobalConfig

log = tuned.logs.get()

__all__ = ["Application"]

class Application(object):
	def __init__(self, profile_name = None, config = None):
		# os.uname()[2] is for the python-2.7 compatibility, it's the release string
		# like e.g. '5.15.13-100.fc34.x86_64'
		log.info("TuneD: %s, kernel: %s" % (tuned.version.TUNED_VERSION_STR, os.uname()[2]))
		self._dbus_exporter = None
		self._unix_socket_exporter = None

		storage_provider = storage.PickleProvider()
		storage_factory = storage.Factory(storage_provider)

		self.config = GlobalConfig() if config is None else config
		if self.config.get_bool(consts.CFG_DYNAMIC_TUNING):
			log.info("dynamic tuning is enabled (can be overridden in plugins)")
		else:
			log.info("dynamic tuning is globally disabled")

		monitors_repository = monitors.Repository()
		udev_buffer_size = self.config.get_size("udev_buffer_size", consts.CFG_DEF_UDEV_BUFFER_SIZE)
		hardware_inventory = hardware.Inventory(buffer_size=udev_buffer_size)
		device_matcher = hardware.DeviceMatcher()
		device_matcher_udev = hardware.DeviceMatcherUdev()
		plugin_instance_factory = plugins.instance.Factory()
		self.variables = profiles.variables.Variables()

		plugins_repository = plugins.Repository(monitors_repository, storage_factory, hardware_inventory,\
			device_matcher, device_matcher_udev, plugin_instance_factory, self.config, self.variables)
		def_instance_priority = int(self.config.get(consts.CFG_DEFAULT_INSTANCE_PRIORITY, consts.CFG_DEF_DEFAULT_INSTANCE_PRIORITY))
		unit_manager = units.Manager(
				plugins_repository, monitors_repository,
				def_instance_priority, hardware_inventory, self.config)

		profile_factory = profiles.Factory()
		profile_merger = profiles.Merger()
		profile_locator = profiles.Locator(consts.LOAD_DIRECTORIES)
		profile_loader = profiles.Loader(profile_locator, profile_factory, profile_merger, self.config, self.variables)

		self._daemon = daemon.Daemon(unit_manager, profile_loader, profile_name, self.config, self)
		self._controller = controller.Controller(self._daemon, self.config)

		self._init_signals()

		self._pid_file = None

	def _handle_signal(self, signal_number, handler):
		def handler_wrapper(_signal_number, _frame):
			if signal_number == _signal_number:
				handler()
		signal.signal(signal_number, handler_wrapper)

	def _init_signals(self):
		self._handle_signal(signal.SIGHUP, self._controller.sighup)
		self._handle_signal(signal.SIGINT, self._controller.terminate)
		self._handle_signal(signal.SIGTERM, self._controller.terminate)

	def attach_to_dbus(self, bus_name, object_name, interface_name, namespace):
		if self._dbus_exporter is not None:
			raise TunedException("DBus interface is already initialized.")

		self._dbus_exporter = exports.dbus.DBusExporter(bus_name, interface_name, object_name, namespace)
		exports.register_exporter(self._dbus_exporter)

	def attach_to_unix_socket(self):
		if self._unix_socket_exporter is not None:
			raise TunedException("Unix socket interface is already initialized.")

		self._unix_socket_exporter = exports.unix_socket.UnixSocketExporter(self.config.get(consts.CFG_UNIX_SOCKET_PATH),
																			self.config.get(consts.CFG_UNIX_SOCKET_SIGNAL_PATHS),
																			self.config.get(consts.CFG_UNIX_SOCKET_OWNERSHIP),
																			self.config.get_int(consts.CFG_UNIX_SOCKET_PERMISIONS),
																			self.config.get_int(consts.CFG_UNIX_SOCKET_CONNECTIONS_BACKLOG))
		exports.register_exporter(self._unix_socket_exporter)

	def register_controller(self):
		exports.register_object(self._controller)

	def _daemonize_parent(self, parent_in_fd, child_out_fd):
		"""
		Wait till the child signalizes that the initialization is complete by writing
		some uninteresting data into the pipe.
		"""
		os.close(child_out_fd)
		(read_ready, drop, drop) = select.select([parent_in_fd], [], [], consts.DAEMONIZE_PARENT_TIMEOUT)

		if len(read_ready) != 1:
			os.close(parent_in_fd)
			raise TunedException("Cannot daemonize, timeout when waiting for the child process.")

		response = os.read(parent_in_fd, 8)
		os.close(parent_in_fd)

		if len(response) == 0:
			raise TunedException("Cannot daemonize, no response from child process received.")

		try:
			val = struct.unpack("?", response)[0]
		except struct.error:
			raise TunedException("Cannot daemonize, invalid response from child process received.")
		if val != True:
			raise TunedException("Cannot daemonize, child process reports failure.")

	def write_pid_file(self, pid_file = consts.PID_FILE):
		self._pid_file = pid_file
		self._delete_pid_file()
		try:
			dir_name = os.path.dirname(self._pid_file)
			if not os.path.exists(dir_name):
				os.makedirs(dir_name)

			with os.fdopen(os.open(self._pid_file, os.O_CREAT|os.O_TRUNC|os.O_WRONLY , 0o644), "w") as f:
				f.write("%d" % os.getpid())
		except (OSError,IOError) as error:
			log.critical("cannot write the PID to %s: %s" % (self._pid_file, str(error)))

	def _delete_pid_file(self):
		if os.path.exists(self._pid_file):
			try:
				os.unlink(self._pid_file)
			except OSError as error:
				log.warning("cannot remove existing PID file %s, %s" % (self._pid_file, str(error)))

	def _daemonize_child(self, pid_file, parent_in_fd, child_out_fd):
		"""
		Finishes daemonizing process, writes a PID file and signalizes to the parent
		that the initialization is complete.
		"""
		os.close(parent_in_fd)

		os.chdir("/")
		os.setsid()
		os.umask(0)

		try:
			pid = os.fork()
			if pid > 0:
				sys.exit(0)
		except OSError as error:
			log.critical("cannot daemonize, fork() error: %s" % str(error))
			val = struct.pack("?", False)
			os.write(child_out_fd, val)
			os.close(child_out_fd)
			raise TunedException("Cannot daemonize, second fork() failed.")

		fd = open("/dev/null", "w+")
		os.dup2(fd.fileno(), sys.stdin.fileno())
		os.dup2(fd.fileno(), sys.stdout.fileno())
		os.dup2(fd.fileno(), sys.stderr.fileno())

		self.write_pid_file(pid_file)

		log.debug("successfully daemonized")
		val = struct.pack("?", True)
		os.write(child_out_fd, val)
		os.close(child_out_fd)

	def daemonize(self, pid_file = consts.PID_FILE):
		"""
		Daemonizes the application. In case of failure, TunedException is raised
		in the parent process. If the operation is successfull, the main process
		is terminated and only child process returns from this method.
		"""
		parent_child_fds = os.pipe()
		try:
			child_pid = os.fork()
		except OSError as error:
			os.close(parent_child_fds[0])
			os.close(parent_child_fds[1])
			raise TunedException("Cannot daemonize, fork() failed.")

		try:
			if child_pid > 0:
				self._daemonize_parent(*parent_child_fds)
				sys.exit(0)
			else:
				self._daemonize_child(pid_file, *parent_child_fds)
		except:
			# pass exceptions only into parent process
			if child_pid > 0:
				raise
			else:
				sys.exit(1)

	@property
	def daemon(self):
		return self._daemon

	@property
	def controller(self):
		return self._controller

	def run(self, daemon):
		# override global config if ran from command line with daemon option (-d)
		if daemon:
			self.config.set(consts.CFG_DAEMON, True)
		if not self.config.get_bool(consts.CFG_DAEMON, consts.CFG_DEF_DAEMON):
			log.warn("Using one shot no daemon mode, most of the functionality will be not available, it can be changed in global config")
		result = self._controller.run()
		if self.config.get_bool(consts.CFG_DAEMON, consts.CFG_DEF_DAEMON):
			exports.stop()

		if self._pid_file is not None:
			self._delete_pid_file()

		return result
PK���\�
��NN&__pycache__/application.cpython-36.pycnu�[���PK���\�
��NN,�__pycache__/application.cpython-36.opt-1.pycnu�[���PK���\���±*�*'N?__pycache__/daemon.cpython-36.opt-1.pycnu�[���PK���\?˸���#Vj__pycache__/__init__.cpython-36.pycnu�[���PK���\���±*�*!^k__pycache__/daemon.cpython-36.pycnu�[���PK���\|��cs5s5%`�__pycache__/controller.cpython-36.pycnu�[���PK���\?˸���)(�__pycache__/__init__.cpython-36.opt-1.pycnu�[���PK���\|��cs5s5+6�__pycache__/controller.cpython-36.opt-1.pycnu�[���PK���\��U
�4�4
controller.pynu�[���PK���\C$���3�3	8daemon.pynu�[���PK���\J���KKl__init__.pynu�[���PK���\�����lapplication.pynu�[���PKea�