3
]ð]n@  ã               @   s  d Z ddlmZmZ ddlmZ ddlmZ ddlm	Z	m
Z
 dZdZdZdZd	Zd/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G dd„ deƒZG dd„ deƒZG dd „ d eƒZeeeeefZd1d!d"„Zd2ZG d(d)„ d)eƒZd*d+„ ZG d,d-„ d-eƒZ d.S )3zBUtilities for choosing which member of a replica set to read from.é    )ÚabcÚinteger_types)Úmax_staleness_selectors)ÚConfigurationError)Ú member_with_tags_server_selectorÚ#secondary_with_tags_server_selectoré   é   é   é   ÚprimaryÚprimaryPreferredÚ	secondaryÚsecondaryPreferredÚnearestc             C   sj   | dkr| S t | tƒs$td| f ƒ‚t| ƒdkr>td| f ƒ‚x&| D ]}t |tjƒsDtd|f ƒ‚qDW | S )z3Validate tag sets for a MongoReplicaSetClient.
    Nz#Tag sets %r invalid, must be a listr   zETag sets %r invalid, must be None or contain at least one set of tagszqTag set %r invalid, must be an instance of dict, bson.son.SON or other type that inherits from collection.Mapping)Ú
isinstanceÚlistÚ	TypeErrorÚlenÚ
ValueErrorr   ÚMapping)Útag_setsÚtags© r   ú;/tmp/pip-build-20mum3z4/pymongo/pymongo/read_preferences.pyÚ_validate_tag_sets(   s    


r   c             C   s   d|  S )Nz6maxStalenessSeconds must be a positive integer, not %sr   )Úmax_stalenessr   r   r   Ú_invalid_max_staleness_msg@   s    r   c             C   s:   | dkrdS t | tƒs"tt| ƒƒ‚| dkr6tt| ƒƒ‚| S )zValidate max_staleness.r   r   éÿÿÿÿr   )r   r   r   r   r   )r   r   r   r   Ú_validate_max_stalenessF   s    
r   c               @   sš   e Zd ZdZd"Zd$dd	„Zed
d„ ƒZedd„ ƒZedd„ ƒZ	edd„ ƒZ
edd„ ƒZedd„ ƒZedd„ ƒZdd„ Zdd„ Zdd„ Zdd„ Zd d!„ ZdS )%Ú_ServerModez)Base class for all read preferences.
    Ú__mongos_modeÚ__modeÚ
__tag_setsÚ__max_stalenessNr   c             C   s(   t | | _|| _t|ƒ| _t|ƒ| _d S )N)Ú_MONGOS_MODESÚ_ServerMode__mongos_modeÚ_ServerMode__moder   Ú_ServerMode__tag_setsr   Ú_ServerMode__max_staleness)ÚselfÚmoder   r   r   r   r   Ú__init__Z   s    

z_ServerMode.__init__c             C   s   | j jS )z*The name of this read preference.
        )Ú	__class__Ú__name__)r*   r   r   r   Úname`   s    z_ServerMode.namec             C   s   | j S )z1The mongos mode of this read preference.
        )r&   )r*   r   r   r   Úmongos_modef   s    z_ServerMode.mongos_modec             C   s<   d| j i}| jdi gfkr$| j|d< | jdkr8| j|d< |S )z'Read preference as a document.
        r+   Nr   r   ZmaxStalenessSecondsr   )r&   r(   r)   )r*   Údocr   r   r   Údocumentl   s    



z_ServerMode.documentc             C   s   | j S )z3The mode of this read preference instance.
        )r'   )r*   r   r   r   r+   w   s    z_ServerMode.modec             C   s   | j rt| j ƒS i gS )a{  Set ``tag_sets`` to a list of dictionaries like [{'dc': 'ny'}] to
        read only from members whose ``dc`` tag has the value ``"ny"``.
        To specify a priority-order for tag sets, provide a list of
        tag sets: ``[{'dc': 'ny'}, {'dc': 'la'}, {}]``. A final, empty tag
        set, ``{}``, means "read from any member that matches the mode,
        ignoring tags." MongoReplicaSetClient tries each set of tags in turn
        until it finds a set of tags with at least one matching member.

           .. seealso:: `Data-Center Awareness
               <http://www.mongodb.org/display/DOCS/Data+Center+Awareness>`_
        )r(   r   )r*   r   r   r   r   }   s    z_ServerMode.tag_setsc             C   s   | j S )zÏThe maximum estimated length of time (in seconds) a replica set
        secondary can fall behind the primary in replication before it will
        no longer be selected for operations, or -1 for no maximum.)r)   )r*   r   r   r   r   Œ   s    z_ServerMode.max_stalenessc             C   s   | j dkrdS dS )a‚  The wire protocol version the server must support.

        Some read preferences impose version requirements on all servers (e.g.
        maxStalenessSeconds requires MongoDB 3.4 / maxWireVersion 5).

        All servers' maxWireVersion must be at least this read preference's
        `min_wire_version`, or the driver raises
        :exc:`~pymongo.errors.ConfigurationError`.
        r   r   é   r   )r)   )r*   r   r   r   Úmin_wire_version“   s    z_ServerMode.min_wire_versionc             C   s   d| j | j| jf S )Nz!%s(tag_sets=%r, max_staleness=%r))r/   r(   r)   )r*   r   r   r   Ú__repr__    s    z_ServerMode.__repr__c             C   s2   t |tƒr.| j|jko,| j|jko,| j|jkS tS )N)r   r    r+   r   r   ÚNotImplemented)r*   Úotherr   r   r   Ú__eq__¤   s
    
z_ServerMode.__eq__c             C   s
   | |k S )Nr   )r*   r7   r   r   r   Ú__ne__«   s    z_ServerMode.__ne__c             C   s   | j | j| jdœS )zeReturn value of object for pickling.

        Needed explicitly because __slots__() defined.
        )r+   r   r   )r'   r(   r)   )r*   r   r   r   Ú__getstate__®   s    z_ServerMode.__getstate__c             C   s6   |d | _ t| j  | _t|d ƒ| _t|d ƒ| _dS )zRestore from pickling.r+   r   r   N)r'   r%   r&   r   r(   r   r)   )r*   Úvaluer   r   r   Ú__setstate__·   s    
z_ServerMode.__setstate__)r!   r"   r#   r$   r   )Nr   )r.   Ú
__module__Ú__qualname__Ú__doc__Ú	__slots__r,   Úpropertyr/   r0   r2   r+   r   r   r4   r5   r8   r9   r:   r<   r   r   r   r   r    T   s   
	r    c                   s<   e Zd ZdZf Z‡ fdd„Zdd„ Zdd„ Zdd	„ Z‡  Z	S )
ÚPrimaryaG  Primary read preference.

    * When directly connected to one mongod queries are allowed if the server
      is standalone or a replica set primary.
    * When connected to a mongos queries are sent to the primary of a shard.
    * When connected to a replica set queries are sent to the primary of
      the replica set.
    c                s   t t| ƒjtƒ d S )N)ÚsuperrB   r,   Ú_PRIMARY)r*   )r-   r   r   r,   Ë   s    zPrimary.__init__c             C   s   |j S )z*Apply this read preference to a Selection.)Úprimary_selection)r*   Ú	selectionr   r   r   Ú__call__Î   s    zPrimary.__call__c             C   s   dS )Nz	Primary()r   )r*   r   r   r   r5   Ò   s    zPrimary.__repr__c             C   s   t |tƒr|jtkS tS )N)r   r    r+   rD   r6   )r*   r7   r   r   r   r8   Õ   s    

zPrimary.__eq__)
r.   r=   r>   r?   r@   r,   rG   r5   r8   Ú__classcell__r   r   )r-   r   rB   ¿   s   rB   c                   s.   e Zd ZdZf Zd	‡ fdd„	Zdd„ Z‡  ZS )
ÚPrimaryPreferredaQ  PrimaryPreferred read preference.

    * When directly connected to one mongod queries are allowed to standalone
      servers, to a replica set primary, or to replica set secondaries.
    * When connected to a mongos queries are sent to the primary of a shard if
      available, otherwise a shard secondary.
    * When connected to a replica set queries are sent to the primary if
      available, otherwise a secondary.

    :Parameters:
      - `tag_sets`: The :attr:`~tag_sets` to use if the primary is not
        available.
      - `max_staleness`: (integer, in seconds) The maximum estimated
        length of time a replica set secondary can fall behind the primary in
        replication before it will no longer be selected for operations.
        Default -1, meaning no maximum. If it is set, it must be at least
        90 seconds.
    Nr   c                s   t t| ƒjt||ƒ d S )N)rC   rI   r,   Ú_PRIMARY_PREFERRED)r*   r   r   )r-   r   r   r,   ñ   s    zPrimaryPreferred.__init__c             C   s&   |j r|jS t| jtj| j|ƒƒS dS )z(Apply this read preference to Selection.N)r   rE   r   r   r   Úselectr   )r*   rF   r   r   r   rG   ö   s    zPrimaryPreferred.__call__r   )Nr   )r.   r=   r>   r?   r@   r,   rG   rH   r   r   )r-   r   rI   Û   s   rI   c                   s.   e Zd ZdZf Zd	‡ fdd„	Zdd„ Z‡  ZS )
Ú	Secondarya]  Secondary read preference.

    * When directly connected to one mongod queries are allowed to standalone
      servers, to a replica set primary, or to replica set secondaries.
    * When connected to a mongos queries are distributed among shard
      secondaries. An error is raised if no secondaries are available.
    * When connected to a replica set queries are distributed among
      secondaries. An error is raised if no secondaries are available.

    :Parameters:
      - `tag_sets`: The :attr:`~tag_sets` for this read preference.
      - `max_staleness`: (integer, in seconds) The maximum estimated
        length of time a replica set secondary can fall behind the primary in
        replication before it will no longer be selected for operations.
        Default -1, meaning no maximum. If it is set, it must be at least
        90 seconds.
    Nr   c                s   t t| ƒjt||ƒ d S )N)rC   rL   r,   Ú
_SECONDARY)r*   r   r   )r-   r   r   r,     s    zSecondary.__init__c             C   s   t | jtj| j|ƒƒS )z(Apply this read preference to Selection.)r   r   r   rK   r   )r*   rF   r   r   r   rG     s    zSecondary.__call__r   )Nr   )r.   r=   r>   r?   r@   r,   rG   rH   r   r   )r-   r   rL     s   rL   c                   s.   e Zd ZdZf Zd	‡ fdd„	Zdd„ Z‡  ZS )
ÚSecondaryPreferreda^  SecondaryPreferred read preference.

    * When directly connected to one mongod queries are allowed to standalone
      servers, to a replica set primary, or to replica set secondaries.
    * When connected to a mongos queries are distributed among shard
      secondaries, or the shard primary if no secondary is available.
    * When connected to a replica set queries are distributed among
      secondaries, or the primary if no secondary is available.

    :Parameters:
      - `tag_sets`: The :attr:`~tag_sets` for this read preference.
      - `max_staleness`: (integer, in seconds) The maximum estimated
        length of time a replica set secondary can fall behind the primary in
        replication before it will no longer be selected for operations.
        Default -1, meaning no maximum. If it is set, it must be at least
        90 seconds.
    Nr   c                s   t t| ƒjt||ƒ d S )N)rC   rN   r,   Ú_SECONDARY_PREFERRED)r*   r   r   )r-   r   r   r,   6  s    zSecondaryPreferred.__init__c             C   s(   t | jtj| j|ƒƒ}|r|S |jS dS )z(Apply this read preference to Selection.N)r   r   r   rK   r   rE   )r*   rF   Zsecondariesr   r   r   rG   ;  s    zSecondaryPreferred.__call__r   )Nr   )r.   r=   r>   r?   r@   r,   rG   rH   r   r   )r-   r   rN   !  s   rN   c                   s.   e Zd ZdZf Zd	‡ fdd„	Zdd„ Z‡  ZS )
ÚNearestaø  Nearest read preference.

    * When directly connected to one mongod queries are allowed to standalone
      servers, to a replica set primary, or to replica set secondaries.
    * When connected to a mongos queries are distributed among all members of
      a shard.
    * When connected to a replica set queries are distributed among all
      members.

    :Parameters:
      - `tag_sets`: The :attr:`~tag_sets` for this read preference.
      - `max_staleness`: (integer, in seconds) The maximum estimated
        length of time a replica set secondary can fall behind the primary in
        replication before it will no longer be selected for operations.
        Default -1, meaning no maximum. If it is set, it must be at least
        90 seconds.
    Nr   c                s   t t| ƒjt||ƒ d S )N)rC   rP   r,   Ú_NEAREST)r*   r   r   )r-   r   r   r,   ]  s    zNearest.__init__c             C   s   t | jtj| j|ƒƒS )z(Apply this read preference to Selection.)r   r   r   rK   r   )r*   rF   r   r   r   rG   `  s    zNearest.__call__r   )Nr   )r.   r=   r>   r?   r@   r,   rG   rH   r   r   )r-   r   rP   H  s   rP   c             C   sB   | t kr4|d i gfkrtdƒ‚|dkr.tdƒ‚tƒ S t|  ||ƒS )Nz4Read preference primary cannot be combined with tagsr   zCRead preference primary cannot be combined with maxStalenessSecondsr   )rD   r   rB   Ú_ALL_READ_PREFERENCES)r+   r   r   r   r   r   Úmake_read_preferencel  s    rS   ÚPRIMARYÚPRIMARY_PREFERREDÚ	SECONDARYÚSECONDARY_PREFERREDÚNEARESTc               @   s.   e Zd ZdZeƒ Zeƒ Zeƒ Z	e
ƒ Zeƒ ZdS )ÚReadPreferenceaD  An enum that defines the read preference modes supported by PyMongo.

    See :doc:`/examples/high_availability` for code examples.

    A read preference is used in three cases:

    :class:`~pymongo.mongo_client.MongoClient` connected to a single mongod:

    - ``PRIMARY``: Queries are allowed if the server is standalone or a replica
      set primary.
    - All other modes allow queries to standalone servers, to a replica set
      primary, or to replica set secondaries.

    :class:`~pymongo.mongo_client.MongoClient` initialized with the
    ``replicaSet`` option:

    - ``PRIMARY``: Read from the primary. This is the default, and provides the
      strongest consistency. If no primary is available, raise
      :class:`~pymongo.errors.AutoReconnect`.

    - ``PRIMARY_PREFERRED``: Read from the primary if available, or if there is
      none, read from a secondary.

    - ``SECONDARY``: Read from a secondary. If no secondary is available,
      raise :class:`~pymongo.errors.AutoReconnect`.

    - ``SECONDARY_PREFERRED``: Read from a secondary if available, otherwise
      from the primary.

    - ``NEAREST``: Read from any member.

    :class:`~pymongo.mongo_client.MongoClient` connected to a mongos, with a
    sharded cluster of replica sets:

    - ``PRIMARY``: Read from the primary of the shard, or raise
      :class:`~pymongo.errors.OperationFailure` if there is none.
      This is the default.

    - ``PRIMARY_PREFERRED``: Read from the primary of the shard, or if there is
      none, read from a secondary of the shard.

    - ``SECONDARY``: Read from a secondary of the shard, or raise
      :class:`~pymongo.errors.OperationFailure` if there is none.

    - ``SECONDARY_PREFERRED``: Read from a secondary of the shard if available,
      otherwise from the shard primary.

    - ``NEAREST``: Read from any shard member.
    N)r.   r=   r>   r?   rB   rT   rI   rU   rL   rV   rN   rW   rP   rX   r   r   r   r   rY   �  s   1rY   c             C   s
   t j| ƒS )z7Get the read preference mode from mongos/uri name.
    )r%   Úindex)r/   r   r   r   Úread_pref_mode_from_nameº  s    r[   c               @   s0   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
S )ÚMovingAveragez0Tracks an exponentially-weighted moving average.c             C   s
   d | _ d S )N)Úaverage)r*   r   r   r   r,   Â  s    zMovingAverage.__init__c             C   s6   |dk rd S | j d kr|| _ nd| j  d|  | _ d S )Nr   gš™™™™™é?gš™™™™™É?)r]   )r*   Úsampler   r   r   Ú
add_sampleÅ  s
    
zMovingAverage.add_samplec             C   s   | j S )z6Get the calculated average, or None if no samples yet.)r]   )r*   r   r   r   ÚgetÒ  s    zMovingAverage.getc             C   s
   d | _ d S )N)r]   )r*   r   r   r   ÚresetÖ  s    zMovingAverage.resetN)r.   r=   r>   r?   r,   r_   r`   ra   r   r   r   r   r\   À  s
   r\   N)r   r   r   r   r   r   )r   )rT   rU   rV   rW   rX   )!r?   Zbson.py3compatr   r   Zpymongor   Zpymongo.errorsr   Zpymongo.server_selectorsr   r   rD   rJ   rM   rO   rQ   r%   r   r   r   Úobjectr    rB   rI   rL   rN   rP   rR   rS   Z_MODESrY   r[   r\   r   r   r   r   Ú<module>   sD       k& ' 

    9