{ "info": { "author": "Vincent Pelletier", "author_email": "plr.vincent@gmail.com", "bugtrack_url": null, "classifiers": [ "Intended Audience :: Developers", "License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)", "Operating System :: POSIX :: Linux", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Software Development :: Libraries" ], "description": ".. contents::\n\nLinux AIO API wrapper\n\nThis is about in-kernel, file-descriptor-based asynchronous I/O.\nIt has nothing to do with the ``asyncio`` standard module.\n\nLinux AIO primer\n----------------\n\nWhen sending or expecting data, the typical issue a developer faces is knowing\nwhen the operation will complete, so the program can carry on.\n\n- read/write/recv/send: blocks until stuff happened\n- same, on a non-blocking file descriptor: errors out instead of blocking,\n developper has to implement retry somehow, and may end up wasting CPU time\n just resubmitting the same operation over and over.\n- select/poll/epoll: kernel tells the program when (re)submitting an operation\n should not block (if developer is careful to not have competing IO sources)\n\nAIO is the next level: the application expresses the intention that some IO\noperation happens when the file descriptor accepts it *and* provides\ncorresponding buffer to the kernel.\nCompared to select/poll/epoll, this avoids one round-trip to userland when the\noperation becomes possible:\n\n- kernel sends notification (ex: fd is readable)\n- program initiates actual IO (ex: read from fd)\n\nInstead, kernel only has to notify userland the operation is already completed,\nand application may either process received data, or submit more data to send.\n\nEdge cases\n----------\n\nBecause of this high level of integration, low-level implementation\nconstraints which are abstracted by higher-overhead APIs may become apparent.\n\nFor example, when submitting AIO blocks to an USB gadget endpoint file, the\nblock should be aligned to page boundaries because some USB Device Controllers\ndo not have the ability to read/write partial pages.\n\nIn python, this means ``mmap`` should be used to allocate such buffer instead\nof just any ``bytearray``.\n\nAnother place where implementation details appear is completion statuses,\n``res`` and ``res2``. Their meaning depends on the module handling operations\non used file descriptor, so python-libaio transmits these values without\nassuming their meaning (rather than, say, raise on negative values).\n\nYet another place is application-initiated closures: there is a fundamental\nrace-condition when cancelling an AIO block (maybe hardware-triggered\ncompletion will happen first, or maybe software-initiated cancellation will).\nIn any case, a completion event will be produced and application may check\nwhich origin won. A consequence of this is that AIO context closure may take\ntime: while requesting cancellation does not block, software should wait for\nhardware to hand the buffers back.\n\npython 2 Notes\n--------------\n\nIn python 2.7, a memoryview of a bytearray, despite being writable, is rejected\nby ctypes:\n\n.. code:: python\n\n >>> from ctypes import c_char\n >>> a = bytearray(b'foo')\n >>> c_char.from_buffer(a)\n c_char('f')\n >>> b = memoryview(a)\n >>> b.readonly\n False\n >>> c_char.from_buffer(b)\n Traceback (most recent call last):\n File \"\", line 1, in \n TypeError: expected a writeable buffer object\n\nThis means that it is not possible to only read or write a few bytes at the\nbeginning of a large buffer without having to copy memory.\n\nThe same code works fine with python 3.x .\n\nThis is considered a python 2.7 ctypes or memoryview bug, and not a python-libaio bug.\n\nAlso, memoryview refuses to use an mmap object:\n\n.. code:: python\n\n >>> import mmap\n >>> a = mmap.mmap(-1, 16*1024)\n >>> b = memoryview(a)\n Traceback (most recent call last):\n File \"\", line 1, in \n TypeError: cannot make memory view because object does not have the buffer interface\n >>>\n\n...but ctypes is happy with it:\n\n.. code:: python\n\n >>> import ctypes\n >>> c = (ctypes.c_char * len(a)).from_buffer(a)\n >>>\n\n...and memoryview accepts being constructed over ctype objects:\n\n.. code:: python\n\n >>> d = memoryview(c)\n >>>\n\n...and it really works !\n\n.. code:: python\n\n >>> a[0]\n '\\x00'\n >>> c[0]\n '\\x00'\n >>> d[0]\n '\\x00'\n >>> d[0] = '\\x01'\n >>> c[0]\n '\\x01'\n >>> a[0]\n '\\x01'\n >>> a[0] = '\\x02'\n >>> c[0]\n '\\x02'\n >>> d[0]\n '\\x02'\n\nThis is considered a python 2.7 memoryview or mmap bug.\n", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://github.com/vpelletier/python-libaio", "keywords": "linux aio libaio", "license": "LGPLv3+", "maintainer": "", "maintainer_email": "", "name": "libaio", "package_url": "https://pypi.org/project/libaio/", "platform": "linux", "project_url": "https://pypi.org/project/libaio/", "project_urls": { "Homepage": "http://github.com/vpelletier/python-libaio" }, "release_url": "https://pypi.org/project/libaio/0.7/", "requires_dist": null, "requires_python": "", "summary": "Linux AIO API wrapper", "version": "0.7" }, "last_serial": 5438389, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "ac2c2a4e3809ef617ebcdc3a52882aa4", "sha256": "c8efd0ac86dfce9dfcb4524d38a0b4d7e3eabed9056ff2e2ae7fe7577f98f85d" }, "downloads": -1, "filename": "libaio-0.1.tar.gz", "has_sig": false, "md5_digest": "ac2c2a4e3809ef617ebcdc3a52882aa4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5365, "upload_time": "2017-11-17T12:21:10", "url": "https://files.pythonhosted.org/packages/f3/b4/979476df4d6a99791616a70829322d66c33c339425117d51a834739154e7/libaio-0.1.tar.gz" } ], "0.2": [ { "comment_text": "", "digests": { "md5": "ad887eed2f04dcad56d300c2dd946578", "sha256": "d524522516820c48fb539d1d155419dc72077bbdf42bf62373696f4017514a9f" }, "downloads": -1, "filename": "libaio-0.2.tar.gz", "has_sig": false, "md5_digest": "ad887eed2f04dcad56d300c2dd946578", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5621, "upload_time": "2017-11-25T06:47:28", "url": "https://files.pythonhosted.org/packages/52/bd/5fdd9ff28feb23e9fed880000e0cdf38f33fb2c52026c917635913f61b73/libaio-0.2.tar.gz" } ], "0.3": [ { "comment_text": "", "digests": { "md5": "45e8b1b264e5cad80ba5b616e440d3f5", "sha256": "dbb3edbef2288f510c0a81b33ae5f4bb497ceab30dd570687950a869a39e292e" }, "downloads": -1, "filename": "libaio-0.3.tar.gz", "has_sig": false, "md5_digest": "45e8b1b264e5cad80ba5b616e440d3f5", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6745, "upload_time": "2018-07-25T03:22:59", "url": "https://files.pythonhosted.org/packages/45/ca/bad843c75cf398490a2727c95ba39bd6d5be036a9cdd2fb4c6792a9674dd/libaio-0.3.tar.gz" } ], "0.4": [ { "comment_text": "", "digests": { "md5": "53ab90b9e0193cae78ef8265f1923d0c", "sha256": "794bd26ebeb809edf4b3caa4cf83bb83b243af8712cbe2540c450742e86f6961" }, "downloads": -1, "filename": "libaio-0.4.tar.gz", "has_sig": false, "md5_digest": "53ab90b9e0193cae78ef8265f1923d0c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8547, "upload_time": "2018-09-15T14:20:26", "url": "https://files.pythonhosted.org/packages/54/db/f2f18d11e434e76427a82177aa0ff3379f87dba91e10a4eec9c9077c7e9d/libaio-0.4.tar.gz" } ], "0.5": [ { "comment_text": "", "digests": { "md5": "221e2c99b21656c7729ba8c4ecfbc596", "sha256": "7002b99aa4e27297bc1775eea1bf5dd78ee90c38557dee7cbad9224971555613" }, "downloads": -1, "filename": "libaio-0.5.tar.gz", "has_sig": false, "md5_digest": "221e2c99b21656c7729ba8c4ecfbc596", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9674, "upload_time": "2018-09-22T06:59:13", "url": "https://files.pythonhosted.org/packages/41/93/31f56257a602544028e8223a129f297b5781472a72020e9243a36b0570f3/libaio-0.5.tar.gz" } ], "0.6": [ { "comment_text": "", "digests": { "md5": "0940533caa58d61342bec7ea2b8f0701", "sha256": "d1d119cccc77cc7c6ed7c67fd170b02d9e6237f48a5ac5ade2a90f1450640501" }, "downloads": -1, "filename": "libaio-0.6.tar.gz", "has_sig": false, "md5_digest": "0940533caa58d61342bec7ea2b8f0701", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13062, "upload_time": "2019-05-30T22:25:01", "url": "https://files.pythonhosted.org/packages/fa/a5/8c66a1b9f8d8a51a2ae6a8a6f68193e8c6577cb1361a02266a336ac6ef7e/libaio-0.6.tar.gz" } ], "0.7": [ { "comment_text": "", "digests": { "md5": "7d53b022c4bb109fcf016cc8a35c1efc", "sha256": "4cb08b79ebc882a8dc25150efbd56cd11c23ae3288ed643fcff35ea234df3189" }, "downloads": -1, "filename": "libaio-0.7.tar.gz", "has_sig": false, "md5_digest": "7d53b022c4bb109fcf016cc8a35c1efc", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 45319, "upload_time": "2019-06-23T22:19:28", "url": "https://files.pythonhosted.org/packages/c3/55/7a559e6564289ce79c5ba2494cfced92610c328b66d15db3b525803ff93f/libaio-0.7.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "7d53b022c4bb109fcf016cc8a35c1efc", "sha256": "4cb08b79ebc882a8dc25150efbd56cd11c23ae3288ed643fcff35ea234df3189" }, "downloads": -1, "filename": "libaio-0.7.tar.gz", "has_sig": false, "md5_digest": "7d53b022c4bb109fcf016cc8a35c1efc", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 45319, "upload_time": "2019-06-23T22:19:28", "url": "https://files.pythonhosted.org/packages/c3/55/7a559e6564289ce79c5ba2494cfced92610c328b66d15db3b525803ff93f/libaio-0.7.tar.gz" } ] }