From f3c64b9a0837dd03584b67179267e1e0ca8edadd Mon Sep 17 00:00:00 2001 From: jason Date: Mon, 23 Jan 2017 20:18:42 -0700 Subject: update docs --- .gitignore | 0 .nojekyll | 0 _sources/api.rst.txt | 15 + _sources/api.txt | 0 _sources/client.rst.txt | 3 + _sources/client.txt | 0 _sources/client/jobs.rst.txt | 3 + _sources/client/jobs.txt | 0 _sources/client/messages.rst.txt | 3 + _sources/client/messages.txt | 0 _sources/contributing.rst.txt | 14 + _sources/contributing.txt | 0 _sources/exceptions.rst.txt | 2 + _sources/exceptions.txt | 0 _sources/getting_started.txt | 0 _sources/glossary.txt | 0 _sources/index.rst.txt | 18 + _sources/index.txt | 0 _sources/jobmanager.rst.txt | 3 + _sources/jobmanager.txt | 0 _sources/poller.rst.txt | 3 + _sources/poller.txt | 0 _sources/protocol.rst.txt | 260 + _sources/protocol.txt | 0 _sources/receiver.rst.txt | 3 + _sources/receiver.txt | 0 _sources/router.rst.txt | 3 + _sources/router.txt | 0 _sources/sender.rst.txt | 3 + _sources/sender.txt | 0 _sources/settings_file.rst.txt | 51 + _sources/settings_file.txt | 0 _sources/style.txt | 0 _sources/using.rst.txt | 14 + _sources/using.txt | 0 _sources/utils.txt | 0 _sources/utils/classes.rst.txt | 3 + _sources/utils/classes.txt | 0 _sources/utils/devices.rst.txt | 3 + _sources/utils/devices.txt | 0 _sources/utils/index.rst.txt | 3 + _sources/utils/index.txt | 0 _sources/utils/messages.rst.txt | 3 + _sources/utils/messages.txt | 0 _sources/utils/settings.rst.txt | 3 + _sources/utils/settings.txt | 0 _sources/utils/timeutils.rst.txt | 3 + _sources/utils/timeutils.txt | 0 _static/ajax-loader.gif | Bin _static/basic.css | 79 +- _static/classic.css | 0 _static/comment-bright.png | Bin 3500 -> 756 bytes _static/comment-close.png | Bin 3578 -> 829 bytes _static/comment.png | Bin 3445 -> 641 bytes _static/css/badge_only.css | 0 _static/css/theme.css | 0 _static/doctools.js | 28 +- _static/down-pressed.png | Bin 347 -> 222 bytes _static/down.png | Bin 347 -> 202 bytes _static/file.png | Bin 358 -> 286 bytes _static/fonts/Inconsolata-Bold.ttf | Bin _static/fonts/Inconsolata-Regular.ttf | Bin _static/fonts/Lato-Bold.ttf | Bin _static/fonts/Lato-Regular.ttf | Bin _static/fonts/RobotoSlab-Bold.ttf | Bin _static/fonts/RobotoSlab-Regular.ttf | Bin _static/fonts/fontawesome-webfont.eot | Bin _static/fonts/fontawesome-webfont.svg | 0 _static/fonts/fontawesome-webfont.ttf | Bin _static/fonts/fontawesome-webfont.woff | Bin _static/jquery-1.11.1.js | 0 _static/jquery-3.1.0.js | 10074 +++++++++++++++++++++++++++++++ _static/jquery.js | 8 +- _static/js/modernizr.min.js | 0 _static/js/theme.js | 0 _static/minus.png | Bin 173 -> 90 bytes _static/plus.png | Bin 173 -> 90 bytes _static/pygments.css | 4 + _static/searchtools.js | 166 +- _static/sidebar.js | 0 _static/underscore-1.3.1.js | 0 _static/underscore.js | 0 _static/up-pressed.png | Bin 345 -> 214 bytes _static/up.png | Bin 345 -> 203 bytes _static/websupport.js | 4 +- api.html | 11 +- client.html | 11 +- client/jobs.html | 17 +- client/messages.html | 99 +- contributing.html | 11 +- exceptions.html | 13 +- genindex.html | 1135 ++-- getting_started.html | 0 glossary.html | 0 index.html | 15 +- jobmanager.html | 47 +- objects.inv | Bin 1468 -> 1831 bytes poller.html | 25 +- protocol.html | 55 +- py-modindex.html | 41 +- receiver.html | 52 +- router.html | 68 +- search.html | 7 +- searchindex.js | 2 +- sender.html | 55 +- settings_file.html | 11 +- style.html | 0 using.html | 11 +- utils.html | 0 utils/classes.html | 100 +- utils/devices.html | 13 +- utils/index.html | 22 +- utils/messages.html | 35 +- utils/settings.html | 13 +- utils/timeutils.html | 15 +- 115 files changed, 11581 insertions(+), 1082 deletions(-) mode change 100644 => 100755 .gitignore mode change 100644 => 100755 .nojekyll create mode 100644 _sources/api.rst.txt mode change 100644 => 100755 _sources/api.txt create mode 100644 _sources/client.rst.txt mode change 100644 => 100755 _sources/client.txt create mode 100644 _sources/client/jobs.rst.txt mode change 100644 => 100755 _sources/client/jobs.txt create mode 100644 _sources/client/messages.rst.txt mode change 100644 => 100755 _sources/client/messages.txt create mode 100644 _sources/contributing.rst.txt mode change 100644 => 100755 _sources/contributing.txt create mode 100644 _sources/exceptions.rst.txt mode change 100644 => 100755 _sources/exceptions.txt mode change 100644 => 100755 _sources/getting_started.txt mode change 100644 => 100755 _sources/glossary.txt create mode 100644 _sources/index.rst.txt mode change 100644 => 100755 _sources/index.txt create mode 100644 _sources/jobmanager.rst.txt mode change 100644 => 100755 _sources/jobmanager.txt create mode 100644 _sources/poller.rst.txt mode change 100644 => 100755 _sources/poller.txt create mode 100644 _sources/protocol.rst.txt mode change 100644 => 100755 _sources/protocol.txt create mode 100644 _sources/receiver.rst.txt mode change 100644 => 100755 _sources/receiver.txt create mode 100644 _sources/router.rst.txt mode change 100644 => 100755 _sources/router.txt create mode 100644 _sources/sender.rst.txt mode change 100644 => 100755 _sources/sender.txt create mode 100644 _sources/settings_file.rst.txt mode change 100644 => 100755 _sources/settings_file.txt mode change 100644 => 100755 _sources/style.txt create mode 100644 _sources/using.rst.txt mode change 100644 => 100755 _sources/using.txt mode change 100644 => 100755 _sources/utils.txt create mode 100644 _sources/utils/classes.rst.txt mode change 100644 => 100755 _sources/utils/classes.txt create mode 100644 _sources/utils/devices.rst.txt mode change 100644 => 100755 _sources/utils/devices.txt create mode 100644 _sources/utils/index.rst.txt mode change 100644 => 100755 _sources/utils/index.txt create mode 100644 _sources/utils/messages.rst.txt mode change 100644 => 100755 _sources/utils/messages.txt create mode 100644 _sources/utils/settings.rst.txt mode change 100644 => 100755 _sources/utils/settings.txt create mode 100644 _sources/utils/timeutils.rst.txt mode change 100644 => 100755 _sources/utils/timeutils.txt mode change 100644 => 100755 _static/ajax-loader.gif mode change 100644 => 100755 _static/basic.css mode change 100644 => 100755 _static/classic.css mode change 100644 => 100755 _static/comment-bright.png mode change 100644 => 100755 _static/comment-close.png mode change 100644 => 100755 _static/comment.png mode change 100644 => 100755 _static/css/badge_only.css mode change 100644 => 100755 _static/css/theme.css mode change 100644 => 100755 _static/doctools.js mode change 100644 => 100755 _static/down-pressed.png mode change 100644 => 100755 _static/down.png mode change 100644 => 100755 _static/file.png mode change 100644 => 100755 _static/fonts/Inconsolata-Bold.ttf mode change 100644 => 100755 _static/fonts/Inconsolata-Regular.ttf mode change 100644 => 100755 _static/fonts/Lato-Bold.ttf mode change 100644 => 100755 _static/fonts/Lato-Regular.ttf mode change 100644 => 100755 _static/fonts/RobotoSlab-Bold.ttf mode change 100644 => 100755 _static/fonts/RobotoSlab-Regular.ttf mode change 100644 => 100755 _static/fonts/fontawesome-webfont.eot mode change 100644 => 100755 _static/fonts/fontawesome-webfont.svg mode change 100644 => 100755 _static/fonts/fontawesome-webfont.ttf mode change 100644 => 100755 _static/fonts/fontawesome-webfont.woff mode change 100644 => 100755 _static/jquery-1.11.1.js create mode 100644 _static/jquery-3.1.0.js mode change 100644 => 100755 _static/jquery.js mode change 100644 => 100755 _static/js/modernizr.min.js mode change 100644 => 100755 _static/js/theme.js mode change 100644 => 100755 _static/minus.png mode change 100644 => 100755 _static/plus.png mode change 100644 => 100755 _static/pygments.css mode change 100644 => 100755 _static/searchtools.js mode change 100644 => 100755 _static/sidebar.js mode change 100644 => 100755 _static/underscore-1.3.1.js mode change 100644 => 100755 _static/underscore.js mode change 100644 => 100755 _static/up-pressed.png mode change 100644 => 100755 _static/up.png mode change 100644 => 100755 _static/websupport.js mode change 100644 => 100755 api.html mode change 100644 => 100755 client.html mode change 100644 => 100755 client/jobs.html mode change 100644 => 100755 client/messages.html mode change 100644 => 100755 contributing.html mode change 100644 => 100755 exceptions.html mode change 100644 => 100755 genindex.html mode change 100644 => 100755 getting_started.html mode change 100644 => 100755 glossary.html mode change 100644 => 100755 index.html mode change 100644 => 100755 jobmanager.html mode change 100644 => 100755 objects.inv mode change 100644 => 100755 poller.html mode change 100644 => 100755 protocol.html mode change 100644 => 100755 py-modindex.html mode change 100644 => 100755 receiver.html mode change 100644 => 100755 router.html mode change 100644 => 100755 search.html mode change 100644 => 100755 sender.html mode change 100644 => 100755 settings_file.html mode change 100644 => 100755 style.html mode change 100644 => 100755 using.html mode change 100644 => 100755 utils.html mode change 100644 => 100755 utils/classes.html mode change 100644 => 100755 utils/devices.html mode change 100644 => 100755 utils/index.html mode change 100644 => 100755 utils/messages.html mode change 100644 => 100755 utils/settings.html mode change 100644 => 100755 utils/timeutils.html diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/.nojekyll b/.nojekyll old mode 100644 new mode 100755 diff --git a/_sources/api.rst.txt b/_sources/api.rst.txt new file mode 100644 index 0000000..8351355 --- /dev/null +++ b/_sources/api.rst.txt @@ -0,0 +1,15 @@ +################# +API Documentation +################# + +.. toctree:: + :maxdepth: 2 + + client + exceptions + jobmanager + poller + receiver + router + sender + utils/index diff --git a/_sources/api.txt b/_sources/api.txt old mode 100644 new mode 100755 diff --git a/_sources/client.rst.txt b/_sources/client.rst.txt new file mode 100644 index 0000000..dad4ee4 --- /dev/null +++ b/_sources/client.rst.txt @@ -0,0 +1,3 @@ +.. automodule:: eventmq.client + :members: + :special-members: diff --git a/_sources/client.txt b/_sources/client.txt old mode 100644 new mode 100755 diff --git a/_sources/client/jobs.rst.txt b/_sources/client/jobs.rst.txt new file mode 100644 index 0000000..a4acb3b --- /dev/null +++ b/_sources/client/jobs.rst.txt @@ -0,0 +1,3 @@ +.. automodule:: eventmq.client.jobs + :members: + :special-members: diff --git a/_sources/client/jobs.txt b/_sources/client/jobs.txt old mode 100644 new mode 100755 diff --git a/_sources/client/messages.rst.txt b/_sources/client/messages.rst.txt new file mode 100644 index 0000000..f89b9d5 --- /dev/null +++ b/_sources/client/messages.rst.txt @@ -0,0 +1,3 @@ +.. automodule:: eventmq.client.messages + :members: + :special-members: diff --git a/_sources/client/messages.txt b/_sources/client/messages.txt old mode 100644 new mode 100755 diff --git a/_sources/contributing.rst.txt b/_sources/contributing.rst.txt new file mode 100644 index 0000000..2489abb --- /dev/null +++ b/_sources/contributing.rst.txt @@ -0,0 +1,14 @@ +####################### +Contributing to EventMQ +####################### + +A few tips when working on the code + + * Use relative imports. If you use absolute imports then when you `import eventmq.exceptions` it's possible that you receive in return a different version of eventmq. exceptions installed somewhere else on the system. + +.. toctree:: + :maxdepth: 1 + + protocol + Source Code + Issues diff --git a/_sources/contributing.txt b/_sources/contributing.txt old mode 100644 new mode 100755 diff --git a/_sources/exceptions.rst.txt b/_sources/exceptions.rst.txt new file mode 100644 index 0000000..04f9c5a --- /dev/null +++ b/_sources/exceptions.rst.txt @@ -0,0 +1,2 @@ +.. automodule:: eventmq.exceptions + :members: diff --git a/_sources/exceptions.txt b/_sources/exceptions.txt old mode 100644 new mode 100755 diff --git a/_sources/getting_started.txt b/_sources/getting_started.txt old mode 100644 new mode 100755 diff --git a/_sources/glossary.txt b/_sources/glossary.txt old mode 100644 new mode 100755 diff --git a/_sources/index.rst.txt b/_sources/index.rst.txt new file mode 100644 index 0000000..25fc86f --- /dev/null +++ b/_sources/index.rst.txt @@ -0,0 +1,18 @@ +##################### +EventMQ Documentation +##################### + +.. toctree:: + :maxdepth: 2 + + using + api + contributing + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/_sources/index.txt b/_sources/index.txt old mode 100644 new mode 100755 diff --git a/_sources/jobmanager.rst.txt b/_sources/jobmanager.rst.txt new file mode 100644 index 0000000..65b439d --- /dev/null +++ b/_sources/jobmanager.rst.txt @@ -0,0 +1,3 @@ +.. automodule:: eventmq.jobmanager + :members: + :special-members: diff --git a/_sources/jobmanager.txt b/_sources/jobmanager.txt old mode 100644 new mode 100755 diff --git a/_sources/poller.rst.txt b/_sources/poller.rst.txt new file mode 100644 index 0000000..1aab472 --- /dev/null +++ b/_sources/poller.rst.txt @@ -0,0 +1,3 @@ +.. automodule:: eventmq.poller + :members: + :special-members: diff --git a/_sources/poller.txt b/_sources/poller.txt old mode 100644 new mode 100755 diff --git a/_sources/protocol.rst.txt b/_sources/protocol.rst.txt new file mode 100644 index 0000000..66b6829 --- /dev/null +++ b/_sources/protocol.rst.txt @@ -0,0 +1,260 @@ +****************************** +EventMQ Protocol Specification +****************************** +*The status of this document is alpha and subject to heavy change* + +Goals +===== +The EventMQ Protocol (eMQP) defines a reliable service-oriented request-reply and pub-sub dialog between a set of clients, a broker, and a set of workers. + +The goals are to: + + * Specify a protocol to follow when implementing a component to EventMQ. + * Allow requests to be routed to workers by an abstracted service name (named queues). + * Detect disconnected peers through heartbeating. + * Allow for message tracing and debugging. + + +License +======= +This Specification is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 2.1 of the License, or (at your option) any later version. + +This Specification is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + +Language +======== +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119[[1](http://tools.ietf.org/html/rfc2119)]. + +Architecture +============ +insert pretty picture here + +Topology +-------- +eMQP connects a set of client applications (e.g. web servers), a broker, and a pool of workers. Clients connect to the broker as well as the workers. + +'Clients' is defined as application issuing requests and 'workers' as applications that process these requests. (Workers consist of a `JobManager` and a pool of `Worker` resources where the job executes.) + +The EventMQ broker handles a set of named queues. The broker SHOULD serve clients on a fair request and MAY deliver requests to workers on any basis, including 0MQ's built-in round robin or least-recently used. + +ROUTER Addressing +----------------- +In the case of request-reply, the broker MUST use a ROUTER socket to accept requests from both clients and workers. The broker MAY use a seperate socket implementing a subset of eMQP, or MAY use a single socket implementing all of eMQP. + +From the 0MQ manual[[2](http://api.zeromq.org/master:zmq-socket)] +> When receiving messages a ROUTER socket shall prepend a message part containing the identity of the originating peer to the message before passing it to the application. When sending messages a ROUTER socket shall remove the first part of the message and use it to determine the identity of the peer the message shall be routed to. + +This extra frame is not shown in the specifications below. + +Global Frames +------------- +An **ACK** command consists of a 4-frame multipart message, formatted as follows. + +====== ============== =========== +FRAME Value Description +====== ============== =========== +0 _EMPTY_ leave empty +1 eMQP/1.0 Protocol version +2 ACK command +3 _MSGID_ A unique id for the msg +4 _MSGID_ The message id of the message this ACK is acknowledging +====== ============== =========== + +A **REPLY** frame consists of a 5-frame multipart message, formatted as follows. + +====== ============== =========== +FRAME Value Description +====== ============== =========== +0 _EMPTY_ leave empty +1 eMQP/1.0 Protocol version +2 REPLY command +3 _MSGID_ A unique id for the msg +4 _MSG_ The reply to respond with +====== ============== =========== + +A **HEARTBEAT** frame consists of a + +====== ============== =========== +FRAME Value Description +====== ============== =========== +0 _EMPTY_ leave empty +1 eMQP/1.0 Protocol version +2 HEARTBEAT command +3 _MSGID_ A unique id for the msg +4 _UNIX_TS_ A unix timestamp +====== ============== =========== + +A **DISCONNECT** frame consists of + +====== ============== =========== +FRAME Value Description +====== ============== =========== +0 _EMPTY_ leave empty +1 eMQP/1.0 Protocol version +2 DISCONNECT command +3 _MSGID_ A unique id for the msg +====== ============== =========== + +A **KBAI** frame consists of + +====== ============== =========== +FRAME Value Description +====== ============== =========== +0 _EMPTY_ leave empty +1 eMQP/1.0 Protocol version +2 KBAI command +3 _MSGID_ A unique id for the msg +====== ============== =========== + +eMQP / Client +------------- +A **REQUEST** command consists of a 7-frame multipart message, formatted as follows. + +====== ============== =========== +FRAME Value Description +====== ============== =========== +0 _EMPTY_ leave empty +1 eMQP/1.0 Protocol version +2 REQUEST command +3 _MSGID_ A unique id for the msg +4 _QUEUE_NAME_ the name of the queue the request should be sent to +5 _HEADERS_ dictionary of headers. can be an empty set +6 _MSG_ The message to send +====== ============== =========== + +A **PUBLISH** command consists of a 7-frame multipart messag, formatted as follows. + +====== ============== =========== +FRAME Value Description +====== ============== =========== +0 _EMPTY_ leave empty +1 eMQP/1.0 Protocol version +2 PUBLISH command +3 _MSGID_ A unique id for the msg +4 _TOPIC_NAME_ the name of the topic this message should be published across +5 _HEADERS_ csv list of headers +6 _MSG_ The message to send +====== ============== =========== + +A **SCHEDULE** command consists of a 7-frame multipart message, formatted as follows. + +====== ============== =========== +FRAME Value Description +====== ============== =========== +0 _EMPTY_ leave empty +1 eMQP/1.0 Protocol version +2 SCHEDULE command +3 _MSGID_ A unique id for the msg +4 _QUEUE_NAME_ name of queue that the job should run in +5 _HEADERS_ csv list of headers for this message +6 _MSG_ The message to send +====== ============== =========== + +An **UNSCHEDULE** command consists of a 7-frame multipart message, formatted as follows. + +====== ============== =========== +FRAME Value Description +====== ============== =========== +0 _EMPTY_ leave empty +1 eMQP/1.0 Protocol version +2 UNSCHEDULE command +3 _MSGID_ A unique id for the msg +4 _QUEUE_NAME_ ignored for this command, broadcasted to all queues +5 _HEADERS_ csv list of headers for this message +6 _MSG_ The message to send +====== ============== =========== + +eMQP / Scheduler +---------------- +An **INFORM** command consists of a 6-frame multipart message, formatted as follows. + +====== ============== =========== +FRAME Value Description +====== ============== =========== +0 _EMPTY_ leave empty +1 eMQP/1.0 Protocol version +2 INFORM command +3 _MSGID_ A unique id for the msg +4 Queues. Unused for scheduler +5 scheduler type of peer connecting +====== ============== =========== + +eMQP / Worker +------------- +An **INFORM** command consists of a 5-frame multipart message, formatted as follows. + +====== ============== =========== +FRAME Value Description +====== ============== =========== +0 _EMPTY_ leave empty +1 eMQP/1.0 Protocol version +2 INFORM command +3 _MSGID_ A unique id for the msg +4 _QUEUES_ csv seperated arrays containing an int and a string for weight and name. e.g. [40, 'email'] +5 worker type of peer connecting +====== ============== =========== + +A **READY** frame consists of a 4-frame multipart message, formatted as follows. + +====== ============== =========== +FRAME Value Description +====== ============== =========== +0 _EMPTY_ leave empty +1 eMQP/1.0 Protocol version +2 READY command +3 _MSGID_ A unique id for the msg +====== ============== =========== + +eMQP / Publisher +---------------- +A **PUBLISH** frame consists of a 6-frame multipart message, formatted as follows. + +====== ============== =========== +FRAME Value Description +====== ============== =========== +0 _EMPTY_ leave empty +1 eMQP/1.0 Protocol version +2 PUBLISH command +3 _MSGID_ A unique id for the msg +4 TOPIC A topic to publish to +5 MSG Message to be published +====== ============== =========== + + +Heartbeating +------------ + * HEARTBEAT commands are valid at any time after an INFORM command. + * Any command except DISCONNECT act as a heartbeat. Peers SHOULD NOT send HEARTBEAT commands while sending other commands. + * Worker and broker MUST send heartbeats at regular and agreed-upon intervals. + * Scheduler and broker MUST send heartbeats at regular and agreed-upon intervals. + * If the worker detects that the broker disconnected it SHOULD restart the conversation. + * If the broker detects that a worker has disconnected it should stop sending it a message of any type. + * If the scheduler detects that the broker disconnects it SHOULD restart the conversation. + +Headers +--------------- +Headers MUST be 0 to many comma seperated values inserted into the header field. If there are no headers required, an empty string MUST be sent where headers are required. + +Below is a table which defines and describes the headers. + + +================= ======= ======= ======== ======= =========== +Header REQUEST PUBLISH SCHEDULE Default Description +================= ======= ======= ======== ======= =========== +reply-requested X False Once the job is finished, send a reply back with information from the job. If there is no information reply with a True value. +retry-count:# X 0 Retry a failed job this many times before accepting defeat. +timeout:# X 0 Kill the job after X seconds, defaults to never timing out (0) +guarantee X False Ensure the job completes by letting someone else worry about a success reply. +nohaste X False When scheduling a job, set this to True if you don't want the job to run immediately as it's scheduled. Instead, it will run for the first time when the interval has elapsed. +================= ======= ======= ======== ======= =========== + +DISCONNECT and KBAI +=================== +When a component receives a DISCONNECT command it: + * MUST send a KBAI command to all connected components. + * MUST stop sending and receiving any messages + * MUST allow any pending messages or jobs to complete. + +When a component receives a KBAI command it: + * MUST stop sending any messages to the disconnecting component. + * SHOULD Clean up references to the disconnecting component. diff --git a/_sources/protocol.txt b/_sources/protocol.txt old mode 100644 new mode 100755 diff --git a/_sources/receiver.rst.txt b/_sources/receiver.rst.txt new file mode 100644 index 0000000..854349c --- /dev/null +++ b/_sources/receiver.rst.txt @@ -0,0 +1,3 @@ +.. automodule:: eventmq.receiver + :members: + :special-members: diff --git a/_sources/receiver.txt b/_sources/receiver.txt old mode 100644 new mode 100755 diff --git a/_sources/router.rst.txt b/_sources/router.rst.txt new file mode 100644 index 0000000..9f7f576 --- /dev/null +++ b/_sources/router.rst.txt @@ -0,0 +1,3 @@ +.. automodule:: eventmq.router + :members: + :special-members: diff --git a/_sources/router.txt b/_sources/router.txt old mode 100644 new mode 100755 diff --git a/_sources/sender.rst.txt b/_sources/sender.rst.txt new file mode 100644 index 0000000..67a1338 --- /dev/null +++ b/_sources/sender.rst.txt @@ -0,0 +1,3 @@ +.. automodule:: eventmq.sender + :members: + :special-members: diff --git a/_sources/sender.txt b/_sources/sender.txt old mode 100644 new mode 100755 diff --git a/_sources/settings_file.rst.txt b/_sources/settings_file.rst.txt new file mode 100644 index 0000000..cd37b6a --- /dev/null +++ b/_sources/settings_file.rst.txt @@ -0,0 +1,51 @@ +############################## +Server Settings (eventmq.conf) +############################## +EventMQ uses a standard INI style config file found at ``/etc/eventmq.conf``. + +****** +Router +****** + +********* +Scheduler +********* + +*********** +Job Manager +*********** + +concurrent_jobs +=============== +Default: 4 + +This is the number of concurrent jobs the indiviudal job manager should execute +at a time. If you are using the multiprocess or threading model this number +becomes important as you will want to control the load on your server. If the +load equals the number of cores on the server, processes will begin waiting for +cpu cycles and things will begin to slow down. + +A safe number to choose if your jobs block a lot would be (2 * cores). If your +jobs are cpu intensive you will want to set this number to the number of cores +you have or (cores - 1) to leave cycles for the os and other processes. This is +something that will have to be tuned based on the jobs that are +running. Grouping similar jobs in named queues will help you tune this number. + +queues +====== +Default: (10, default) + +Semi-colon seperated list of queues to process jobs for with thier +weights. Example: ``queues=(10, data_process); (15, email)``. With these +weights and the ``CONCURRENT_JOBS`` setting, you should be able to tune managers +running jobs locally pretty efficiently. If you have a larger box with a weight +of 50 on q1 and 8 concurrent jobs and a smaller box with a weight 30 and 4 +concurrent jobs, the q1 jobs will be sent to the large box until it is no longer +accepting jobs. At this point jobs will start to be sent to the next highest +number until the large box is ready to accept another q1 job. + +.. note:: + + It is recommended that you have some workers listening for jobs on your + default queue so that anything that is not explicitly assigned will still be + run. diff --git a/_sources/settings_file.txt b/_sources/settings_file.txt old mode 100644 new mode 100755 diff --git a/_sources/style.txt b/_sources/style.txt old mode 100644 new mode 100755 diff --git a/_sources/using.rst.txt b/_sources/using.rst.txt new file mode 100644 index 0000000..4e5ee10 --- /dev/null +++ b/_sources/using.rst.txt @@ -0,0 +1,14 @@ +############# +Using EventMQ +############# + +.. toctree:: + :maxdepth: 2 + + settings_file + +**************************** +Client Environment Variables +**************************** + +``EMQ_BROKER_ADDR`` is the address a client should use to connect to the broker. The client can be any application using EventMQ. diff --git a/_sources/using.txt b/_sources/using.txt old mode 100644 new mode 100755 diff --git a/_sources/utils.txt b/_sources/utils.txt old mode 100644 new mode 100755 diff --git a/_sources/utils/classes.rst.txt b/_sources/utils/classes.rst.txt new file mode 100644 index 0000000..ab48e06 --- /dev/null +++ b/_sources/utils/classes.rst.txt @@ -0,0 +1,3 @@ +.. automodule:: eventmq.utils.classes + :members: + :special-members: diff --git a/_sources/utils/classes.txt b/_sources/utils/classes.txt old mode 100644 new mode 100755 diff --git a/_sources/utils/devices.rst.txt b/_sources/utils/devices.rst.txt new file mode 100644 index 0000000..ef68c27 --- /dev/null +++ b/_sources/utils/devices.rst.txt @@ -0,0 +1,3 @@ +.. automodule:: eventmq.utils.devices + :members: + :special-members: diff --git a/_sources/utils/devices.txt b/_sources/utils/devices.txt old mode 100644 new mode 100755 diff --git a/_sources/utils/index.rst.txt b/_sources/utils/index.rst.txt new file mode 100644 index 0000000..02904ed --- /dev/null +++ b/_sources/utils/index.rst.txt @@ -0,0 +1,3 @@ +.. automodule:: eventmq.utils + :members: + :special-members: diff --git a/_sources/utils/index.txt b/_sources/utils/index.txt old mode 100644 new mode 100755 diff --git a/_sources/utils/messages.rst.txt b/_sources/utils/messages.rst.txt new file mode 100644 index 0000000..e49897c --- /dev/null +++ b/_sources/utils/messages.rst.txt @@ -0,0 +1,3 @@ +.. automodule:: eventmq.utils.messages + :members: + :special-members: diff --git a/_sources/utils/messages.txt b/_sources/utils/messages.txt old mode 100644 new mode 100755 diff --git a/_sources/utils/settings.rst.txt b/_sources/utils/settings.rst.txt new file mode 100644 index 0000000..1334f15 --- /dev/null +++ b/_sources/utils/settings.rst.txt @@ -0,0 +1,3 @@ +.. automodule:: eventmq.utils.settings + :members: + :special-members: diff --git a/_sources/utils/settings.txt b/_sources/utils/settings.txt old mode 100644 new mode 100755 diff --git a/_sources/utils/timeutils.rst.txt b/_sources/utils/timeutils.rst.txt new file mode 100644 index 0000000..952c896 --- /dev/null +++ b/_sources/utils/timeutils.rst.txt @@ -0,0 +1,3 @@ +.. automodule:: eventmq.utils.timeutils + :members: + :special-members: diff --git a/_sources/utils/timeutils.txt b/_sources/utils/timeutils.txt old mode 100644 new mode 100755 diff --git a/_static/ajax-loader.gif b/_static/ajax-loader.gif old mode 100644 new mode 100755 diff --git a/_static/basic.css b/_static/basic.css old mode 100644 new mode 100755 index 9fa77d8..7ed0e58 --- a/_static/basic.css +++ b/_static/basic.css @@ -4,7 +4,7 @@ * * Sphinx stylesheet -- basic theme. * - * :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ @@ -52,6 +52,8 @@ div.sphinxsidebar { width: 230px; margin-left: -100%; font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; } div.sphinxsidebar ul { @@ -83,10 +85,6 @@ div.sphinxsidebar #searchbox input[type="text"] { width: 170px; } -div.sphinxsidebar #searchbox input[type="submit"] { - width: 30px; -} - img { border: 0; max-width: 100%; @@ -124,6 +122,8 @@ ul.keywordmatches li.goodmatch a { table.contentstable { width: 90%; + margin-left: auto; + margin-right: auto; } table.contentstable p.biglink { @@ -151,9 +151,14 @@ table.indextable td { vertical-align: top; } -table.indextable dl, table.indextable dd { +table.indextable ul { margin-top: 0; margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; } table.indextable tr.pcap { @@ -185,8 +190,22 @@ div.genindex-jumpbox { padding: 0.4em; } +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + /* -- general body styles --------------------------------------------------- */ +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + a.headerlink { visibility: hidden; } @@ -212,10 +231,6 @@ div.body td { text-align: left; } -.field-list ul { - padding-left: 1em; -} - .first { margin-top: 0 !important; } @@ -332,10 +347,6 @@ table.docutils td, table.docutils th { border-bottom: 1px solid #aaa; } -table.field-list td, table.field-list th { - border: 0 !important; -} - table.footnote td, table.footnote th { border: 0 !important; } @@ -372,6 +383,20 @@ div.figure p.caption span.caption-number { div.figure p.caption span.caption-text { } +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} /* -- other body styles ----------------------------------------------------- */ @@ -422,15 +447,6 @@ dl.glossary dt { font-size: 1.1em; } -.field-list ul { - margin: 0; - padding-left: 1em; -} - -.field-list p { - margin: 0; -} - .optional { font-size: 1.3em; } @@ -489,6 +505,13 @@ pre { overflow-y: hidden; /* fixes display issues on Chrome browsers */ } +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; +} + td.linenos pre { padding: 5px 0px; border: 0; @@ -580,6 +603,16 @@ span.eqno { float: right; } +span.eqno a.headerlink { + position: relative; + left: 0px; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + /* -- printout stylesheet --------------------------------------------------- */ @media print { diff --git a/_static/classic.css b/_static/classic.css old mode 100644 new mode 100755 diff --git a/_static/comment-bright.png b/_static/comment-bright.png old mode 100644 new mode 100755 index 551517b..15e27ed Binary files a/_static/comment-bright.png and b/_static/comment-bright.png differ diff --git a/_static/comment-close.png b/_static/comment-close.png old mode 100644 new mode 100755 index 09b54be..4d91bcf Binary files a/_static/comment-close.png and b/_static/comment-close.png differ diff --git a/_static/comment.png b/_static/comment.png old mode 100644 new mode 100755 index 92feb52..dfbc0cb Binary files a/_static/comment.png and b/_static/comment.png differ diff --git a/_static/css/badge_only.css b/_static/css/badge_only.css old mode 100644 new mode 100755 diff --git a/_static/css/theme.css b/_static/css/theme.css old mode 100644 new mode 100755 diff --git a/_static/doctools.js b/_static/doctools.js old mode 100644 new mode 100755 index c7bfe76..8163495 --- a/_static/doctools.js +++ b/_static/doctools.js @@ -4,7 +4,7 @@ * * Sphinx JavaScript utilities for all documentation. * - * :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ @@ -124,6 +124,7 @@ var Documentation = { this.fixFirefoxAnchorBug(); this.highlightSearchWords(); this.initIndexTable(); + }, /** @@ -252,6 +253,29 @@ var Documentation = { }); var url = parts.join('/'); return path.substring(url.lastIndexOf('/') + 1, path.length - 1); + }, + + initOnKeyListeners: function() { + $(document).keyup(function(event) { + var activeElementType = document.activeElement.tagName; + // don't navigate when in search box or textarea + if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT') { + switch (event.keyCode) { + case 37: // left + var prevHref = $('link[rel="prev"]').prop('href'); + if (prevHref) { + window.location.href = prevHref; + return false; + } + case 39: // right + var nextHref = $('link[rel="next"]').prop('href'); + if (nextHref) { + window.location.href = nextHref; + return false; + } + } + } + }); } }; @@ -260,4 +284,4 @@ _ = Documentation.gettext; $(document).ready(function() { Documentation.init(); -}); +}); \ No newline at end of file diff --git a/_static/down-pressed.png b/_static/down-pressed.png old mode 100644 new mode 100755 index 7c30d00..5756c8c Binary files a/_static/down-pressed.png and b/_static/down-pressed.png differ diff --git a/_static/down.png b/_static/down.png old mode 100644 new mode 100755 index f48098a..1b3bdad Binary files a/_static/down.png and b/_static/down.png differ diff --git a/_static/file.png b/_static/file.png old mode 100644 new mode 100755 index 254c60b..a858a41 Binary files a/_static/file.png and b/_static/file.png differ diff --git a/_static/fonts/Inconsolata-Bold.ttf b/_static/fonts/Inconsolata-Bold.ttf old mode 100644 new mode 100755 diff --git a/_static/fonts/Inconsolata-Regular.ttf b/_static/fonts/Inconsolata-Regular.ttf old mode 100644 new mode 100755 diff --git a/_static/fonts/Lato-Bold.ttf b/_static/fonts/Lato-Bold.ttf old mode 100644 new mode 100755 diff --git a/_static/fonts/Lato-Regular.ttf b/_static/fonts/Lato-Regular.ttf old mode 100644 new mode 100755 diff --git a/_static/fonts/RobotoSlab-Bold.ttf b/_static/fonts/RobotoSlab-Bold.ttf old mode 100644 new mode 100755 diff --git a/_static/fonts/RobotoSlab-Regular.ttf b/_static/fonts/RobotoSlab-Regular.ttf old mode 100644 new mode 100755 diff --git a/_static/fonts/fontawesome-webfont.eot b/_static/fonts/fontawesome-webfont.eot old mode 100644 new mode 100755 diff --git a/_static/fonts/fontawesome-webfont.svg b/_static/fonts/fontawesome-webfont.svg old mode 100644 new mode 100755 diff --git a/_static/fonts/fontawesome-webfont.ttf b/_static/fonts/fontawesome-webfont.ttf old mode 100644 new mode 100755 diff --git a/_static/fonts/fontawesome-webfont.woff b/_static/fonts/fontawesome-webfont.woff old mode 100644 new mode 100755 diff --git a/_static/jquery-1.11.1.js b/_static/jquery-1.11.1.js old mode 100644 new mode 100755 diff --git a/_static/jquery-3.1.0.js b/_static/jquery-3.1.0.js new file mode 100644 index 0000000..f2fc274 --- /dev/null +++ b/_static/jquery-3.1.0.js @@ -0,0 +1,10074 @@ +/*eslint-disable no-unused-vars*/ +/*! + * jQuery JavaScript Library v3.1.0 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2016-07-07T21:44Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var document = window.document; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var concat = arr.concat; + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + + + + function DOMEval( code, doc ) { + doc = doc || document; + + var script = doc.createElement( "script" ); + + script.text = code; + doc.head.appendChild( script ).parentNode.removeChild( script ); + } +/* global Symbol */ +// Defining this global in .eslintrc would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.1.0", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }, + + // Support: Android <=4.0 only + // Make sure we trim BOM and NBSP + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, + + // Matches dashed string for camelizing + rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num != null ? + + // Return just the one element from the set + ( num < 0 ? this[ num + this.length ] : this[ num ] ) : + + // Return all the elements in a clean array + slice.call( this ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = jQuery.isArray( copy ) ) ) ) { + + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray( src ) ? src : []; + + } else { + clone = src && jQuery.isPlainObject( src ) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isFunction: function( obj ) { + return jQuery.type( obj ) === "function"; + }, + + isArray: Array.isArray, + + isWindow: function( obj ) { + return obj != null && obj === obj.window; + }, + + isNumeric: function( obj ) { + + // As of jQuery 3.0, isNumeric is limited to + // strings and numbers (primitives or objects) + // that can be coerced to finite numbers (gh-2662) + var type = jQuery.type( obj ); + return ( type === "number" || type === "string" ) && + + // parseFloat NaNs numeric-cast false positives ("") + // ...but misinterprets leading-number strings, particularly hex literals ("0x...") + // subtraction forces infinities to NaN + !isNaN( obj - parseFloat( obj ) ); + }, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + + /* eslint-disable no-unused-vars */ + // See https://github.com/eslint/eslint/issues/6125 + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + type: function( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; + }, + + // Evaluates a script in a global context + globalEval: function( code ) { + DOMEval( code ); + }, + + // Convert dashed to camelCase; used by the css and data modules + // Support: IE <=9 - 11, Edge 12 - 13 + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // Support: Android <=4.0 only + trim: function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + var tmp, args, proxy; + + if ( typeof context === "string" ) { + tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + args = slice.call( arguments, 2 ); + proxy = function() { + return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || jQuery.guid++; + + return proxy; + }, + + now: Date.now, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), +function( i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = jQuery.type( obj ); + + if ( type === "function" || jQuery.isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.0 + * https://sizzlejs.com/ + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2016-01-04 + */ +(function( window ) { + +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox<24 + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + high < 0 ? + // BMP codepoint + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + disabledAncestor = addCombinator( + function( elem ) { + return elem.disabled === true; + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { + + // ID selector + if ( (m = match[1]) ) { + + // Document context + if ( nodeType === 9 ) { + if ( (elem = context.getElementById( m )) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && (elem = newContext.getElementById( m )) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( (m = match[3]) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !compilerCache[ selector + " " ] && + (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + + if ( nodeType !== 1 ) { + newContext = context; + newSelector = selector; + + // qSA looks outside Element context, which is not what we want + // Thanks to Andrew Dupont for this workaround technique + // Support: IE <=8 + // Exclude object elements + } else if ( context.nodeName.toLowerCase() !== "object" ) { + + // Capture the context ID, setting it first if necessary + if ( (nid = context.getAttribute( "id" )) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", (nid = expando) ); + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[i] = "#" + nid + " " + toSelector( groups[i] ); + } + newSelector = groups.join( "," ); + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key + " " ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement("fieldset"); + + try { + return !!fn( el ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + // Known :disabled false positives: + // IE: *[disabled]:not(button, input, select, textarea, optgroup, option, menuitem, fieldset) + // not IE: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Check form elements and option elements for explicit disabling + return "label" in elem && elem.disabled === disabled || + "form" in elem && elem.disabled === disabled || + + // Check non-disabled form elements for fieldset[disabled] ancestors + "form" in elem && elem.disabled === false && ( + // Support: IE6-11+ + // Ancestry is covered for us + elem.isDisabled === disabled || + + // Otherwise, assume any non-