{"id":19826254,"url":"https://github.com/aternosorg/php-rados-ffi","last_synced_at":"2025-07-07T19:33:36.033Z","repository":{"id":229170212,"uuid":"769266134","full_name":"aternosorg/php-rados-ffi","owner":"aternosorg","description":"An object oriented PHP library for using librados with FFI.","archived":false,"fork":false,"pushed_at":"2024-04-08T14:53:39.000Z","size":330,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-25T10:55:05.447Z","etag":null,"topics":["ceph","ffi","librados","php","rados"],"latest_commit_sha":null,"homepage":"https://packagist.org/packages/aternos/rados-ffi","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-2.1","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/aternosorg.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2024-03-08T17:27:20.000Z","updated_at":"2024-03-22T14:10:19.000Z","dependencies_parsed_at":"2024-03-30T18:42:04.551Z","dependency_job_id":null,"html_url":"https://github.com/aternosorg/php-rados-ffi","commit_stats":null,"previous_names":["aternosorg/php-rados-ffi"],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aternosorg%2Fphp-rados-ffi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aternosorg%2Fphp-rados-ffi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aternosorg%2Fphp-rados-ffi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aternosorg%2Fphp-rados-ffi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aternosorg","download_url":"https://codeload.github.com/aternosorg/php-rados-ffi/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241181767,"owners_count":19923506,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ceph","ffi","librados","php","rados"],"created_at":"2024-11-12T11:09:53.890Z","updated_at":"2025-02-28T16:33:43.534Z","avatar_url":"https://github.com/aternosorg.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# php-rados-ffi\nAn object oriented PHP library for using librados with FFI.\n\n## Requirements\n- Linux\n- PHP 8.1 or later\n- php-ffi\n- librados\n\n## Installation\n```bash\ncomposer require aternos/rados-ffi\n```\n\n## Why not phprados?\n\nThe [phprados](https://github.com/ceph/phprados) extension is a native \nPHP extension that provides bindings to librados. Unfortunately, it has been\nlargely unmaintained for the past few years. While it does compile for the latest version of PHP,\nmany of the included rados functions [do not work as intended and can cause crashes](https://github.com/ceph/phprados/pull/35).\nAdditionally, phprados only adds bindings for a small subset of the librados API.\n\nphp-rados-ffi provides a modern, object-oriented, and complete interface to librados using PHP's FFI system.\nThrough FFI, PHP can load shared libraries like librados and call their functions directly.\nThis allows using librados without a native PHP extension, making it easier to install and safer to update.\n\n## Usage\n\nBefore the library can be used, the librados shared library must be loaded.\nThis can be done using the `initialize()` method of the [`Rados`](src/Rados.php) class.\n```php\n$rados = \\Aternos\\Rados\\Rados::getInstance()-\u003einitialize();\n```\n\n### Preloading\n\nTo preload librados, ensure that FFI preloading is enabled and add the following line to your `opcache.preload` file:\n```php\n\\Aternos\\Rados\\Rados::getInstance()-\u003epreload();\n```\n\nRados can then be initialized by calling `initializePreloaded()` instead of `initialize()`.\n\n```php\n$rados = \\Aternos\\Rados\\Rados::getInstance()-\u003einitializePreloaded();\n```\n\n### Cluster\n\nThe [`Rados`](src/Rados.php) instance can then be used to create a [`Cluster`](src/Cluster/Cluster.php) instance, \nwhich is used to connect to a Ceph cluster.\n\n```php\n$cluster = $rados-\u003ecreateCluster();\n$cluster-\u003econfigReadFile('/etc/ceph/ceph.conf');\n$cluster-\u003econnect();\n```\n\nOnce connected, a [`Cluster`](src/Cluster/Cluster.php) object can be used to perform operations and \nrequest information about the cluster.\nIt is, for example, possible to ping monitors, request the cluster's ID, or list pools.\n\n```php\nvar_dump($cluster-\u003epingMonitor(\"mon1\"));\nvar_dump($cluster-\u003egetClusterFsid());\n\nforeach ($cluster-\u003egetPools() as $pool) {\n    echo $pool-\u003egetName() . PHP_EOL;\n}\n```\n\n### Pool\n\n[`Pool`](src/Cluster/Pool/Pool.php) objects contain general information about a pool, and can be used to obtain an [`IOContext`](src/Cluster/Pool/IOContext.php).\n```php\n$ioContext = $pool-\u003ecreateIOContext();\n```\n\n### IOContext\n\n[`IOContext`](src/Cluster/Pool/IOContext.php) objects are used to perform operations on a pool. \nIt can, for example, be used to iterate over objects in the pool, or to get a specific object.\n\n```php\nforeach ($ioContext-\u003ecreateObjectIterator() as $entry) {\n    echo $entry-\u003egetObject()-\u003egetId() . PHP_EOL;\n}\n\n$object = $ioContext-\u003egetObject(\"object1\");\n```\n\n### RadosObject\n\nA `RadosObject` represents an object in a Ceph pool, \nand can be used to read and write data or modify attributes.\n\n```php\n// Write full object\n$object-\u003ewriteFull(\"Hello, World\");\n\n// Write at offset\n$object-\u003ewrite(\"World\", 7);\n\n//Append to object\n$object-\u003eappend(\"!\");\n\n// Read from object\necho $object-\u003eread(13, 0) . PHP_EOL;\n```\n\n### Async operations and completions\n\nMany IO operations can be performed asynchronously. Asynchronous operations return \na [`ResultCompletion`](src/Completion/ResultCompletion.php) object, which can be used to track the status of \nthe operation and to wait for its completion.\n\n```php\n$completion = $object-\u003ewriteFullAsync(\"Hello, World\");\n```\n\nTo check the status of a completion, the `isComplete()` method can be used.\n```php\nif ($completion-\u003eisComplete()) {\n    echo \"Operation is complete\" . PHP_EOL;\n}\n```\n\nIt is also possible to block until the operation is complete using the `waitForComplete()` method.\n```php\n$completion-\u003ewaitForComplete();\n$completion-\u003eisComplete(); // true\n```\n\nCompletions can be canceled by calling the `cancel()` method.\n```php\n$completion-\u003ecancel();\n```\n\nThe result of the operation can be obtained using the `getResult()` method. The type\nof the result depends on the operation that was performed.\n```php\n$result = $completion-\u003egetResult();\n```\n\nIf the operation failed, the `getResult()` method will throw an exception.\n\nLikewise, an exception will be thrown if the operation was not completed yet.\nTo avoid this, `waitAndGetResult()` can be used to block until the operation \nis complete and to get the result.\n```php\n$result = $completion-\u003ewaitAndGetResult();\n```\n\n### Object operations\n\n[Object operations](https://docs.ceph.com/en/latest/rados/api/librados/#breathe-section-title-object-operations) allow \nperforming multiple tasks on an object atomically. Write and read operations can be created by calling \n`$rados-\u003ecreateWriteOperation()` and `$rados-\u003ecreateReadOperation()` respectively.\n\n```php\n$object = $ioContext-\u003egetObject(\"object1\");\n\n$operation = $rados-\u003ecreateWriteOperation();\n$operation-\u003eaddTask(new \\Aternos\\Rados\\Operation\\Common\\Task\\AssertExistsTask());\n$operation-\u003eaddTask(new \\Aternos\\Rados\\Operation\\Write\\Task\\AppendTask(\"Hello, World\"));\n$operation-\u003eoperate($object);\n```\n\nSome tasks, especially in read operations, will return data. This data can be accessed by\ncalling `getResult()` on the task object after the operation has been completed.\n\nIf the task failed, `getResult()` may throw an exception.\n\n```php\n$object = $ioContext-\u003egetObject(\"object1\");\n$object-\u003ewriteFull(\"Hello, World\");\n\n$operation = $rados-\u003ecreateReadOperation();\n$task = new \\Aternos\\Rados\\Operation\\Read\\Task\\ReadTask(0, 12);\n$operation-\u003eaddTask($task);\n$operation-\u003eoperate($object);\n\necho $task-\u003egetResult() . PHP_EOL;\n```\n\nIf a single task in an operation fails, the entire operation will fail.\nThis can be avoided by adding the `OperationTaskFlag::FailOK` flag to tasks that are allowed to fail.\n\n```php\n$task = new \\Aternos\\Rados\\Operation\\Common\\Task\\CompareExtTask(\"Hello_\", 0);\n$task-\u003esetFlags([\\Aternos\\Rados\\Constants\\OperationTaskFlag::FailOK]);\n```\n\nOperations can also be executed asynchronously, using the `operateAsync()` method.\n\n#### Available tasks\n\n##### Common\n\n- [`AssertExistsTask`](src/Operation/Common/Task/AssertExistsTask.php)\n- [`AssertVersionTask`](src/Operation/Common/Task/AssertVersionTask.php)\n- [`CompareExtTask`](src/Operation/Common/Task/CompareExtTask.php)\n- [`CompareXAttributeTask`](src/Operation/Common/Task/CompareXAttributeTask.php)\n- [`OMapCompareTask`](src/Operation/Common/Task/OMapCompareTask.php)\n\n##### Read\n\n- [`ChecksumTask`](src/Operation/Read/Task/ChecksumTask.php)\n- [`ExecuteTask`](src/Operation/Read/Task/ExecuteTask.php) (with output data)\n- [`GetXAttributesTask`](src/Operation/Read/Task/GetXAttributesTask.php)\n- [`OMapGetByKeysTask`](src/Operation/Read/Task/OMapGetByKeysTask.php)\n- [`OMapGetKeysTask`](src/Operation/Read/Task/OMapGetKeysTask.php)\n- [`OMapGetTask`](src/Operation/Read/Task/OMapGetTask.php)\n- [`ReadTask`](src/Operation/Read/Task/ReadTask.php)\n- [`StatTask`](src/Operation/Read/Task/StatTask.php)\n\n##### Write\n\n- [`AppendTask`](src/Operation/Write/Task/AppendTask.php)\n- [`CreateObjectTask`](src/Operation/Write/Task/CreateObjectTask.php)\n- [`ExecuteTask`](src/Operation/Write/Task/ExecuteTask.php) (without output data)\n- [`OMapClearTask`](src/Operation/Write/Task/OMapClearTask.php)\n- [`OMapRemoveKeyRangeTask`](src/Operation/Write/Task/OMapRemoveKeyRangeTask.php)\n- [`OMapRemoveKeysTask`](src/Operation/Write/Task/OMapRemoveKeysTask.php)\n- [`OMapSetTask`](src/Operation/Write/Task/OMapSetTask.php)\n- [`RemoveTask`](src/Operation/Write/Task/RemoveTask.php)\n- [`RemoveXAttributeTask`](src/Operation/Write/Task/RemoveXAttributeTask.php)\n- [`SetAllocHintTask`](src/Operation/Write/Task/SetAllocHintTask.php)\n- [`SetXAttributeTask`](src/Operation/Write/Task/SetXAttributeTask.php)\n- [`TruncateTask`](src/Operation/Write/Task/TruncateTask.php)\n- [`WriteFullTask`](src/Operation/Write/Task/WriteFullTask.php)\n- [`WriteSameTask`](src/Operation/Write/Task/WriteSameTask.php)\n- [`WriteTask`](src/Operation/Write/Task/WriteTask.php)\n- [`ZeroTask`](src/Operation/Write/Task/ZeroTask.php)\n\n### Exceptions and error handling\n\nIf a Rados operation fails, it will throw a [`RadosException`](src/Exception/RadosException.php).  \nThe error code returned from librados can be obtained using the `getCode()` method.\n\nTo check whether an error has a specific error code, the `is()` method can be used.\n\n```php\ntry {\n    $cluster-\u003egetPool(\"nonexistent\")-\u003ecreateIOContext();\n} catch (\\Aternos\\Rados\\Exception\\RadosException $e) {\n    if ($e-\u003eis(\\Aternos\\Rados\\Generated\\Errno::ENOENT)) {\n        echo \"Pool does not exist\" . PHP_EOL;\n    }\n}\n```\n\n## Available Rados features\nThis library aims to implement the full librados API. \nThere are, however, some features can't be implemented due to limitations in PHP's FFI system.\n\n### Not planned\n- Callback functions for completions\n- Watch/Notify\n- Log callbacks\n\nPHP callback functions can be passed to C functions using FFI,\nbut they can only be called (more or less) safely from the main thread.\nSince both completions and watches can be called from any thread,\nusing PHP callback functions is not feasible.\n\n### Implemented, but not really supported\nSome librados features are poorly documented to a point where I do not understand what they are supposed to do.\nThese features have bindings in this library, but I can't guarantee that they work as intended.\nCurrently, this includes:\n- Self-managed snapshots\n- rados_(un)set_pool_full_try\n\n## How to not segfault\n\nThe library uses FFI to call into the librados shared library. \nTo avoid crashes from incorrect usage of librados, only call methods and constructors \nthat are `public` and not marked as `@internal` in the source code.\n\nMethods marked as `@internal` are not part of the public API and should not be called directly.\n\n## License\n\nphp-rados-ffi - PHP library for Ceph RADOS using FFI  \nCopyright (C) 2024 Aternos GmbH  \n\nThis is free software; you can redistribute it and/or\nmodify it under the terms of the GNU Lesser General Public\nLicense version 2.1, as published by the Free Software\nFoundation.  See file LICENSE.\n\nThis library is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n\nDocumentation comments in this library are derived from documentation comments from librados.\nThe file includes/librados.h is generated from librados.h, which is part of Ceph.\nSource code for Ceph is available at https://github.com/ceph/ceph\n\nCeph - scalable distributed file system  \nCopyright (C) 2004-2012 Sage Weil \u003csage@newdream.net\u003e  \n\nThis is free software; you can redistribute it and/or\nmodify it under the terms of the GNU Lesser General Public\nLicense version 2.1, as published by the Free Software\nFoundation.  See file LICENSE.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faternosorg%2Fphp-rados-ffi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faternosorg%2Fphp-rados-ffi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faternosorg%2Fphp-rados-ffi/lists"}