@asyncio.coroutine<EOL><INDENT>def drain(self, sid=None):<DEDENT>
if self.is_draining:<EOL><INDENT>return<EOL><DEDENT>if self.is_closed:<EOL><INDENT>raise ErrConnectionClosed<EOL><DEDENT>if self.is_connecting or self.is_reconnecting:<EOL><INDENT>raise ErrConnectionReconnecting<EOL><DEDENT>if sid is not None:<EOL><INDENT>return self._drain_sub(sid)<EOL><DEDENT>self._status = Client.DRAINING_SUBS<EOL>drain_tasks = []<EOL>for ssid, sub in self._subs.items():<EOL><INDENT>task = self._drain_sub(ssid)<EOL>drain_tasks.append(task)<EOL><DEDENT>drain_is_done = asyncio.gather(*drain_tasks)<EOL>try:<EOL><INDENT>yield from asyncio.wait_for(drain_is_done, self.options["<STR_LIT>"])<EOL><DEDENT>except asyncio.TimeoutError:<EOL><INDENT>drain_is_done.exception()<EOL>drain_is_done.cancel()<EOL>if self._error_cb is not None:<EOL><INDENT>yield from self._error_cb(ErrDrainTimeout)<EOL><DEDENT><DEDENT>except asyncio.CancelledError:<EOL><INDENT>pass<EOL><DEDENT>finally:<EOL><INDENT>self._status = Client.DRAINING_PUBS<EOL>yield from self.flush()<EOL>yield from self._close(Client.CLOSED)<EOL><DEDENT>
Drain will put a connection into a drain state. All subscriptions will
immediately be put into a drain state. Upon completion, the publishers
will be drained and can not publish any additional messages. Upon draining
of the publishers, the connection will be closed. Use the `closed_cb'
option to know when the connection has moved from draining to closed.

If a sid is passed, just the subscription with that sid will be drained
without closing the connection.