
    Hmd	                     :   d dl Z d dlZd dlZd dlZd dlmZ 	 d dlZn# e$ r d dlZY nw xY w	 d dl	m
Z
 n# e$ r	 d dl
m
Z
 Y nw xY w	 d dlZn# e$ r d dlZY nw xY wd dlmZmZmZ dZdZd Zd Zd	 Z G d
 de          Z G d de          Z G d de          ZdS )    N)	Condition)Queue)Threadselectlf   g      ?c                     t          | t                    rt          j        | d          } t	          |d          r|                                }| |fS )Nrbfileno)
isinstanceintosfdopenhasattrr   )ios     >/usr/lib/x86_64-linux-gnu/glusterfs/python/syncdaemon/repce.pyioparser   #   sO    !S Ia q( HHJJq6M    c                 `    t          j        | t          j        |t                               dS )zpickle args and write out wholly in one syscall

    ie. not use the ability of pickle to dump directly to
    a stream, as that would potentially mess up messages
    by interleaving them
    N)r   writepickledumpspickle_proto)outargss     r   sendr   .   s(     HS&,t\2233333r   c                 |    t          | d          rt          j        | j                  S t          j        |           S )zload an object from input stream
    python2 and python3 compatibility, inf is sys.stdin
    and is opened as text stream by default. Hence using the
    buffer attribute in python3
    buffer)r   r   loadr   )infs    r   recvr"   8   s8     sH  {3:&&&{3r   c                   &    e Zd ZdZddZd Zd ZdS )RepceServerzRePCe is Hungarian for canola, http://hu.wikipedia.org/wiki/Repce

    ... also our homebrewed RPC backend where the transport layer is
    reduced to a pair of filehandles.

    This is the server component.
       c                     || _         t          ||          \  | _        | _        || _        t                      | _        dS )z}register a backend object .obj to which incoming messages
           are dispatched, also incoming/outcoming streams
        N)objr   r!   r   wnumr   q)selfr'   r   r   r(   s        r   __init__zRepceServer.__init__N   s7     $Q]]$(	r   c                 *   t          | j                  D ]+}t          | j                  }|                                 ,	 	 | j                            t          | j                             -# t          $ r t          j        d           Y dS w xY w)z<fire up worker threads, get messages and dispatch among themtargetTzterminating on reaching EOF.N)ranger(   r   workerstartr)   putr"   r!   EOFErrorlogginginfo)r*   r   ts      r   service_loopzRepceServer.service_loopW   s    ty!! 	 	Adk***AGGIIII	9+

4>>***+ 	9 	9 	9L7888888	9s   .A0 0BBc                 X   	 | j                             d          }|d         }|d         }d}|dk    rt          }nX	  t          | j        |          |dd          }n6#  t          j                    d         }d}t          j        d           Y nxY wt          | j
        |||           )	aM  life of a worker

        Get message, extract its id, method name and arguments
        (kwargs not supported), call method on .obj.
        Send back message id + return value.
        If method call throws an exception, rescue it, and send
        back the exception as result (with flag marking it as
        exception).
        Tr      F__repce_version__r   Nzcall failed: )r)   getrepce_versiongetattrr'   sysexc_infor4   	exceptionr   r   )r*   in_dataridrmethexcress         r   r0   zRepceServer.workerb   s    	*fjj&&G!*CAJEC+++#72'$(E22GABBK@CC7,..+CC%o666663S)))	*s    A 1BN)r%   )__name__
__module____qualname____doc__r+   r7   r0    r   r   r$   r$   D   sP            	9 	9 	9* * * * *r   r$   c                   *    e Zd ZdZd Zd Zd Zd ZdS )RepceJobzEclass representing message status we can use
    for waiting on replyc                     t          j                    t          j                    t	          j                    f| _        || _        t                      | _        d| _	        dS )zb
        - .rid: (process-wise) unique id
        - .cbk: what we do upon receiving reply
        FN)
r   getpidthread	get_identtimerB   cbkr   leverdone)r*   rR   s     r   r+   zRepceJob.__init__   sD    
 IKK!1!3!3TY[[A[[
			r   c                 J    d                     d | j        D                       S )N:c                 ,    g | ]}t          |          S rJ   )str).0xs     r   
<listcomp>z%RepceJob.__repr__.<locals>.<listcomp>   s    222AQ222r   )joinrB   r*   s    r   __repr__zRepceJob.__repr__   s%    xx22222333r   c                     | j                                          | j        s| j                                          | j                                          | j        S N)rS   acquirerT   waitreleaseresultr]   s    r   rb   zRepceJob.wait   sN    
y 	JOO
{r   c                     || _         | j                                         d| _        | j                                         | j                                         d S )NT)rd   rS   ra   rT   notifyrc   )r*   datas     r   wakeupzRepceJob.wakeup   sR    
	

r   N)rF   rG   rH   rI   r+   r^   rb   rh   rJ   r   r   rL   rL   }   sZ           4 4 4      r   rL   c                   R    e Zd ZdZd Zd Zd Zd Z G d de          Z	d Z
d	 Zd
S )RepceClientzRePCe is Hungarian for canola, http://hu.wikipedia.org/wiki/Repce

    ... also our homebrewed RPC backend where the transport layer is
    reduced to a pair of filehandles.

    This is the client component.
    c                     t          ||          \  | _        | _        i | _        t	          | j                  }|                                 d S )Nr-   )r   r!   r   jtabr   listenr1   )r*   r   r   r6   s       r   r+   zRepceClient.__init__   sB    $Q]]$(	$+&&&						r   c                     	 t          | j        fdd           t          | j                  \  }}}| j                            |          }|j        r|                    |||g           i)NTrJ   )r   r!   r"   rl   poprR   )r*   rB   rD   rE   rjobs        r   rm   zRepceClient.listen   sj    	+DH;B''' NNMCc9==%%Dx +Sz***	+r   c           	         |                     d          }|sd }t          |          }|| j        |j        <   t	          j        dt          |          d|t          |          d           t          | j        |j        |g|R   |S )zwrap arguments in a RepceJob, send them to server
           and return the RepceJob

           @cbk to pass on RepceJob can be given as kwarg.
        rR   c                 &    |d         r|d         d S )Nr   r9   rJ   rjrE   s     r   rR   zRepceClient.push.<locals>.cbk   s!    q6 !a&L! !r   call  z ...)	r;   rL   rl   rB   r4   debugreprr   r   )r*   methr   kwrR   rp   s         r   pushzRepceClient.push   s     ffUmm 	!! ! ! }}"	$(DJJJJd4jjjjIJJJTXtx-----r   c                 t    | j         |g|R i dd i}|                                \  }}|rSt          j        t	          dt          |          |t          t          |          j                                       |t          j	        dt          |          d|dt          |                     |S )zRePCe client is callabe, calling it implements a synchronous
        remote call.

        We do a .push with a cbk which does a wakeup upon receiving answer,
        then wait on the RepceJob.
        rR   c                 ,    |                      |          S r`   )rh   rs   s     r   <lambda>z&RepceClient.__call__.<locals>.<lambda>   s    299S>> r   zcall failed)callmethoderrorru   rv   z -> )
r{   rb   r4   r   r   rx   rX   typerF   rw   )r*   ry   r   rp   rD   rE   s         r   __call__zRepceClient.__call__   s     tyDD D D!#A#ABD D99;;S 	M"]"&t**$(#&tCyy'9#:#:< < < = = = IDJJJJd3iiiHIII
r   c                       e Zd ZdZd Zd ZdS )RepceClient.mprxzmethod proxy, standard trick to implement rubyesque
        method_missing in Python

        A class is a closure factory, you know what I mean, or go read
        some SICP.
        c                 "    || _         || _        d S r`   insry   )r*   r   ry   s      r   r+   zRepceClient.mprx.__init__   s    DHDIIIr   c                 (     | j         | j        g|R  S r`   r   )r*   as     r   r   zRepceClient.mprx.__call__   s    48DI*****r   N)rF   rG   rH   rI   r+   r   rJ   r   r   mprxr      s<        	 		 	 		+ 	+ 	+ 	+ 	+r   r   c                 .    |                      | |          S )aA  this implements transparent method dispatch to remote object,
           so that you don't need to call the RepceClient instance like

             rclient('how_old_are_you_if_born_in', 1979)

           but you can make it into an ordinary method call like

             rclient.how_old_are_you_if_born_in(1979)
        )r   )r*   ry   s     r   __getattr__zRepceClient.__getattr__   s     yyt$$$r   c                 `    d | d          i}	  | d          |d<   n# t           $ r Y nw xY w|S )z)used in handshake to verify compatibilityprotor:   versionobject)AttributeError)r*   ds     r   __version__zRepceClient.__version__   sT    dd.//0	$y//AhKK 	 	 	D	s    
++N)rF   rG   rH   rI   r+   rm   r{   r   r   r   r   r   rJ   r   r   rj   rj      s           + + +  "  &+ + + + +v + + + 
% 
% 
%    r   rj   )r   r>   rQ   r4   	threadingr   _threadrO   ImportErrorqueuer   cPickler   
syncdutilsr   r   r   r   r<   r   r   r"   r   r$   rL   rj   rJ   r   r   <module>r      s   
			 



           MMMMM      MMMMM * ) ) ) ) ) ) ) ) )  4 4 4	  	  	 6* 6* 6* 6* 6*& 6* 6* 6*r    v   B_ _ _ _ _& _ _ _ _ _s-    	))4 AAA 	AA