From 3e6d8baf87290e7f37c50451f2f41b5cb3abef5c Mon Sep 17 00:00:00 2001 From: toimtoimtoim Date: Sat, 10 Nov 2018 22:52:46 +0200 Subject: [PATCH] improve api, cleanup and many other things --- .travis.yml | 1 - README.md | 48 ++++++--- composer.lock | 234 ++++++++++++++++------------------------ examples/read_rrd.php | 38 +++++++ examples/rrd_to_csv.php | 34 ++++++ src/Rra/Rra.php | 63 ++++++----- src/Rra/RraInfo.php | 57 ++++------ src/RrdDs.php | 79 +++++++++----- src/RrdFile.php | 58 +++++++--- src/RrdHeader.php | 29 +++-- src/RrdReader.php | 140 ++++++++++++++++-------- src/RrdRowValue.php | 106 ++++++++++++++++++ tests/RrdFileTest.php | 4 +- tests/RrdReaderTest.php | 128 +++++++++++++++------- 14 files changed, 664 insertions(+), 355 deletions(-) create mode 100644 examples/read_rrd.php create mode 100644 examples/rrd_to_csv.php create mode 100644 src/RrdRowValue.php diff --git a/.travis.yml b/.travis.yml index 60638d7..8002f83 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,6 @@ cache: - $HOME/.composer/cache php: - - 7.0 - 7.1 - 7.2 diff --git a/README.md b/README.md index fdac2cf..550da30 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,7 @@ # Pure PHP RRDtool file reader +[![Build Status](https://travis-ci.org/aldas/rrd-php-reader.svg?branch=master)](https://travis-ci.org/aldas/rrd-php-reader) +[![codecov](https://codecov.io/gh/aldas/rrd-php-reader/branch/master/graph/badge.svg)](https://codecov.io/gh/aldas/rrd-php-reader) + > Because on windows php ext-rrd can not read rrd files created on unix and vice versa. > See https://github.com/oetiker/rrdtool-1.x/issues/759 @@ -7,31 +10,46 @@ This library supports reading: * rrds created on 64bit linux from 64bit Windows * rrds created on 64bit Windows from 64bit Linux -**Only meant to export/dump data out of rrd file. No support for consolidation function etc** +**Only meant to export/dump data out of rrd file.** -Original repository: http://javascriptrrd.sourceforge.net/ +This library is based on [javascriptRRD](http://javascriptrrd.sourceforge.net/) ## Example +Convert RRD to CSV: [rrd_to_csv.php](examples/rrd_to_csv.php) +``` +$reader = RrdReader::createFromPath('path/to/my_rrd.rrd'); + +$fp = fopen('output.csv', 'wb'); +$reader->outputAsCsv($fp, [ + 'ds' => 'value' +]); +fclose($fp); ``` -use RrdPhpReader\RrdReader; + +Filter rrd: [read_rrd.php](examples/read_rrd.php) +``` $reader = RrdReader::createFromPath('path/to/my_rrd.rrd'); -$data = $reader->setDs('value')->setRraIndex(0)->getAsArray(); +$traversable = $reader->getAll([ + 'ds' => 'value', + 'row_filter_callback' => function (int $timestamp, float $value, RrdDs $ds, RraInfo $rra) { + return $value < 8; + } +]); + +/** @var RrdRowValue $value */ +foreach ($traversable as $value) { + echo $value . PHP_EOL; +} ``` -`$data` structure would be +Output would be: ``` -[ - 'value' => [ <--- datasource as first level keys - 0 => [ <--- rra index as key - 1521054891 => 6, <--- timestamp => value - 1521054892 => 7, - 1521054893 => 8, - 1521054894 => 9, - ] - ] -]; +timestamp=1521054891, value=6.000000, cf=AVERAGE, ds=value, step=1 +timestamp=1521054892, value=7.000000, cf=AVERAGE, ds=value, step=1 +timestamp=1521054891, value=6.000000, cf=MAX, ds=value, step=1 +timestamp=1521054892, value=7.000000, cf=MAX, ds=value, step=1 ``` diff --git a/composer.lock b/composer.lock index 661528d..12a74b9 100644 --- a/composer.lock +++ b/composer.lock @@ -1,7 +1,7 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], "content-hash": "496d5592906d476e5ff1367d87cb2482", @@ -63,25 +63,28 @@ }, { "name": "myclabs/deep-copy", - "version": "1.7.0", + "version": "1.8.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e" + "reference": "3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", - "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8", + "reference": "3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": "^7.1" + }, + "replace": { + "myclabs/deep-copy": "self.version" }, "require-dev": { "doctrine/collections": "^1.0", "doctrine/common": "^2.6", - "phpunit/phpunit": "^4.1" + "phpunit/phpunit": "^7.1" }, "type": "library", "autoload": { @@ -104,26 +107,26 @@ "object", "object graph" ], - "time": "2017-10-19T19:58:43+00:00" + "time": "2018-06-11T23:09:50+00:00" }, { "name": "phar-io/manifest", - "version": "1.0.1", + "version": "1.0.3", "source": { "type": "git", "url": "https://github.com/phar-io/manifest.git", - "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0" + "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/2df402786ab5368a0169091f61a7c1e0eb6852d0", - "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", + "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", "shasum": "" }, "require": { "ext-dom": "*", "ext-phar": "*", - "phar-io/version": "^1.0.1", + "phar-io/version": "^2.0", "php": "^5.6 || ^7.0" }, "type": "library", @@ -159,20 +162,20 @@ } ], "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "time": "2017-03-05T18:14:27+00:00" + "time": "2018-07-08T19:23:20+00:00" }, { "name": "phar-io/version", - "version": "1.0.1", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/phar-io/version.git", - "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df" + "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/a70c0ced4be299a63d32fa96d9281d03e94041df", - "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df", + "url": "https://api.github.com/repos/phar-io/version/zipball/45a2ec53a73c70ce41d55cedef9063630abaf1b6", + "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6", "shasum": "" }, "require": { @@ -206,7 +209,7 @@ } ], "description": "Library for handling version information and constraints", - "time": "2017-03-05T17:38:23+00:00" + "time": "2018-07-08T19:19:57+00:00" }, { "name": "phpdocumentor/reflection-common", @@ -362,33 +365,33 @@ }, { "name": "phpspec/prophecy", - "version": "1.7.5", + "version": "1.8.0", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "dfd6be44111a7c41c2e884a336cc4f461b3b2401" + "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/dfd6be44111a7c41c2e884a336cc4f461b3b2401", - "reference": "dfd6be44111a7c41c2e884a336cc4f461b3b2401", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4ba436b55987b4bf311cb7c6ba82aa528aac0a06", + "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.3|^7.0", "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", - "sebastian/comparator": "^1.1|^2.0", + "sebastian/comparator": "^1.1|^2.0|^3.0", "sebastian/recursion-context": "^1.0|^2.0|^3.0" }, "require-dev": { "phpspec/phpspec": "^2.5|^3.2", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5" + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.7.x-dev" + "dev-master": "1.8.x-dev" } }, "autoload": { @@ -421,31 +424,31 @@ "spy", "stub" ], - "time": "2018-02-19T10:16:54+00:00" + "time": "2018-08-05T17:53:17+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "6.0.1", + "version": "6.1.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "f8ca4b604baf23dab89d87773c28cc07405189ba" + "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f8ca4b604baf23dab89d87773c28cc07405189ba", - "reference": "f8ca4b604baf23dab89d87773c28cc07405189ba", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", + "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", "shasum": "" }, "require": { "ext-dom": "*", "ext-xmlwriter": "*", "php": "^7.1", - "phpunit/php-file-iterator": "^1.4.2", + "phpunit/php-file-iterator": "^2.0", "phpunit/php-text-template": "^1.2.1", "phpunit/php-token-stream": "^3.0", "sebastian/code-unit-reverse-lookup": "^1.0.1", - "sebastian/environment": "^3.0", + "sebastian/environment": "^3.1 || ^4.0", "sebastian/version": "^2.0.1", "theseer/tokenizer": "^1.1" }, @@ -458,7 +461,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "6.0-dev" + "dev-master": "6.1-dev" } }, "autoload": { @@ -484,29 +487,32 @@ "testing", "xunit" ], - "time": "2018-02-02T07:01:41+00:00" + "time": "2018-10-31T16:06:48+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "1.4.5", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" + "reference": "050bedf145a257b1ff02746c31894800e5122946" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", - "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/050bedf145a257b1ff02746c31894800e5122946", + "reference": "050bedf145a257b1ff02746c31894800e5122946", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -521,7 +527,7 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -531,7 +537,7 @@ "filesystem", "iterator" ], - "time": "2017-11-27T13:52:08+00:00" + "time": "2018-09-13T20:33:42+00:00" }, { "name": "phpunit/php-text-template", @@ -625,16 +631,16 @@ }, { "name": "phpunit/php-token-stream", - "version": "3.0.0", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "21ad88bbba7c3d93530d93994e0a33cd45f02ace" + "reference": "c99e3be9d3e85f60646f152f9002d46ed7770d18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/21ad88bbba7c3d93530d93994e0a33cd45f02ace", - "reference": "21ad88bbba7c3d93530d93994e0a33cd45f02ace", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/c99e3be9d3e85f60646f152f9002d46ed7770d18", + "reference": "c99e3be9d3e85f60646f152f9002d46ed7770d18", "shasum": "" }, "require": { @@ -670,51 +676,55 @@ "keywords": [ "tokenizer" ], - "time": "2018-02-01T13:16:43+00:00" + "time": "2018-10-30T05:52:18+00:00" }, { "name": "phpunit/phpunit", - "version": "7.0.2", + "version": "7.4.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "e2f8aa21bc54b6ba218bdd4f9e0dac1e9bc3b4e9" + "reference": "c151651fb6ed264038d486ea262e243af72e5e64" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e2f8aa21bc54b6ba218bdd4f9e0dac1e9bc3b4e9", - "reference": "e2f8aa21bc54b6ba218bdd4f9e0dac1e9bc3b4e9", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c151651fb6ed264038d486ea262e243af72e5e64", + "reference": "c151651fb6ed264038d486ea262e243af72e5e64", "shasum": "" }, "require": { + "doctrine/instantiator": "^1.1", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", - "myclabs/deep-copy": "^1.6.1", - "phar-io/manifest": "^1.0.1", - "phar-io/version": "^1.0", + "myclabs/deep-copy": "^1.7", + "phar-io/manifest": "^1.0.2", + "phar-io/version": "^2.0", "php": "^7.1", "phpspec/prophecy": "^1.7", - "phpunit/php-code-coverage": "^6.0", - "phpunit/php-file-iterator": "^1.4.3", + "phpunit/php-code-coverage": "^6.0.7", + "phpunit/php-file-iterator": "^2.0.1", "phpunit/php-text-template": "^1.2.1", "phpunit/php-timer": "^2.0", - "phpunit/phpunit-mock-objects": "^6.0", - "sebastian/comparator": "^2.1", + "sebastian/comparator": "^3.0", "sebastian/diff": "^3.0", - "sebastian/environment": "^3.1", + "sebastian/environment": "^3.1 || ^4.0", "sebastian/exporter": "^3.1", "sebastian/global-state": "^2.0", "sebastian/object-enumerator": "^3.0.3", - "sebastian/resource-operations": "^1.0", + "sebastian/resource-operations": "^2.0", "sebastian/version": "^2.0.1" }, + "conflict": { + "phpunit/phpunit-mock-objects": "*" + }, "require-dev": { "ext-pdo": "*" }, "suggest": { + "ext-soap": "*", "ext-xdebug": "*", "phpunit/php-invoker": "^2.0" }, @@ -724,7 +734,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "7.0-dev" + "dev-master": "7.4-dev" } }, "autoload": { @@ -750,63 +760,7 @@ "testing", "xunit" ], - "time": "2018-02-26T07:03:12+00:00" - }, - { - "name": "phpunit/phpunit-mock-objects", - "version": "6.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "e3249dedc2d99259ccae6affbc2684eac37c2e53" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/e3249dedc2d99259ccae6affbc2684eac37c2e53", - "reference": "e3249dedc2d99259ccae6affbc2684eac37c2e53", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.0.5", - "php": "^7.1", - "phpunit/php-text-template": "^1.2.1", - "sebastian/exporter": "^3.1" - }, - "require-dev": { - "phpunit/phpunit": "^7.0" - }, - "suggest": { - "ext-soap": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "6.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Mock Object library for PHPUnit", - "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", - "keywords": [ - "mock", - "xunit" - ], - "time": "2018-02-15T05:27:38+00:00" + "time": "2018-10-23T05:57:41+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -855,30 +809,30 @@ }, { "name": "sebastian/comparator", - "version": "2.1.3", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9" + "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/34369daee48eafb2651bea869b4b15d75ccc35f9", - "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/5de4fc177adf9bce8df98d8d141a7559d7ccf6da", + "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da", "shasum": "" }, "require": { - "php": "^7.0", - "sebastian/diff": "^2.0 || ^3.0", + "php": "^7.1", + "sebastian/diff": "^3.0", "sebastian/exporter": "^3.1" }, "require-dev": { - "phpunit/phpunit": "^6.4" + "phpunit/phpunit": "^7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1.x-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -915,20 +869,20 @@ "compare", "equality" ], - "time": "2018-02-01T13:46:46+00:00" + "time": "2018-07-12T15:12:46+00:00" }, { "name": "sebastian/diff", - "version": "3.0.0", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "e09160918c66281713f1c324c1f4c4c3037ba1e8" + "reference": "366541b989927187c4ca70490a35615d3fef2dce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/e09160918c66281713f1c324c1f4c4c3037ba1e8", - "reference": "e09160918c66281713f1c324c1f4c4c3037ba1e8", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/366541b989927187c4ca70490a35615d3fef2dce", + "reference": "366541b989927187c4ca70490a35615d3fef2dce", "shasum": "" }, "require": { @@ -971,7 +925,7 @@ "unidiff", "unified diff" ], - "time": "2018-02-01T13:45:15+00:00" + "time": "2018-06-10T07:54:39+00:00" }, { "name": "sebastian/environment", @@ -1288,25 +1242,25 @@ }, { "name": "sebastian/resource-operations", - "version": "1.0.0", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" + "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", - "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/4d7a795d35b889bf80a0cc04e08d77cedfa917a9", + "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9", "shasum": "" }, "require": { - "php": ">=5.6.0" + "php": "^7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -1326,7 +1280,7 @@ ], "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "time": "2015-07-28T20:34:47+00:00" + "time": "2018-10-04T04:07:39+00:00" }, { "name": "sebastian/version", diff --git a/examples/read_rrd.php b/examples/read_rrd.php new file mode 100644 index 0000000..51add9d --- /dev/null +++ b/examples/read_rrd.php @@ -0,0 +1,38 @@ +getAll([ + 'ds' => 'value', + 'row_filter_callback' => function (int $timestamp, float $value, RrdDs $ds, RraInfo $rra) { + return $value < 8; + } +]); + + +/** @var RrdRowValue $value */ +foreach ($traversable as $value) { + echo $value . PHP_EOL; +} diff --git a/examples/rrd_to_csv.php b/examples/rrd_to_csv.php new file mode 100644 index 0000000..3c51683 --- /dev/null +++ b/examples/rrd_to_csv.php @@ -0,0 +1,34 @@ +outputAsCsv($fp, [ + 'ds' => 'value' +]); +fclose($fp); + diff --git a/src/Rra/Rra.php b/src/Rra/Rra.php index c97bef7..8c78a20 100644 --- a/src/Rra/Rra.php +++ b/src/Rra/Rra.php @@ -9,61 +9,48 @@ class Rra { - /** - * @var RrdData - */ + /** @var RrdData */ private $rrdData; - /** - * @var RraInfo - */ + /** @var RraInfo */ private $rraInfo; - private $rra_ptr_idx; - private $header_size; - private $prev_row_cnts; - private $ds_cnt; - private $base_rrd_db_idx; + private $dataSourceCount; + private $baseOffsetIndex; private $cur_row; - private $row_cnt; + private $rowCount; private $row_size; - public function __construct(RrdData $rrdData, $rra_ptr_idx, RraInfo $rra_info, $header_size, $prev_row_cnts, $ds_cnt) + public function __construct(RrdData $rrdData, $rra_ptr_idx, RraInfo $rra_info, $dataSourceCount, int $rraBaseOffsetIndex) { - $this->rrdData = $rrdData; - $this->rra_ptr_idx = $rra_ptr_idx; $this->rraInfo = $rra_info; - $this->header_size = $header_size; - $this->prev_row_cnts = $prev_row_cnts; - $this->ds_cnt = $ds_cnt; - - - $this->row_cnt = $rra_info->getNrRows(); + $this->dataSourceCount = $dataSourceCount; + $this->row_size = $dataSourceCount * 8; + $this->rowCount = $rra_info->getRowCount(); - $this->row_size = $ds_cnt * 8; - $this->base_rrd_db_idx = $header_size + $prev_row_cnts * $this->row_size; + $this->baseOffsetIndex = $rraBaseOffsetIndex; // get imediately, since it will be needed often $this->cur_row = $rrdData->getLongAt($rra_ptr_idx); } - private function calc_idx(int $row_idx, int $ds_idx) + private function calculateIndex(int $row_idx, int $ds_idx) { - if (($row_idx >= 0) && ($row_idx < $this->row_cnt)) { - if (($ds_idx >= 0) && ($ds_idx < $this->ds_cnt)) { + if (($row_idx >= 0) && ($row_idx < $this->rowCount)) { + if (($ds_idx >= 0) && ($ds_idx < $this->dataSourceCount)) { // it is round robin, starting from cur_row+1 $real_row_idx = $row_idx + $this->cur_row + 1; - if ($real_row_idx >= $this->row_cnt) { - $real_row_idx -= $this->row_cnt; + if ($real_row_idx >= $this->rowCount) { + $real_row_idx -= $this->rowCount; } return $this->row_size * $real_row_idx + $ds_idx * 8; } - throw new RrdRangeException("DS idx ({$row_idx}) out of range [0-{$this->ds_cnt})."); + throw new RrdRangeException("DS idx ({$row_idx}) out of range [0-{$this->dataSourceCount})."); } - throw new RrdRangeException("Row idx ({$row_idx}) out of range [0-{$this->row_cnt})."); + throw new RrdRangeException("Row idx ({$row_idx}) out of range [0-{$this->rowCount})."); } @@ -74,12 +61,12 @@ public function getIdx(): int public function getRowCount(): int { - return $this->row_cnt; + return $this->rraInfo->getRowCount(); } public function getDsCount(): int { - return $this->ds_cnt; + return $this->dataSourceCount; } public function getStep(): int @@ -94,11 +81,21 @@ public function getCFName(): string public function getRow($row_idx, $ds_idx): float { - return $this->rrdData->getDoubleAt($this->base_rrd_db_idx + $this->calc_idx($row_idx, $ds_idx)); + return $this->rrdData->getDoubleAt($this->baseOffsetIndex + $this->calculateIndex($row_idx, $ds_idx)); } public function __destruct() { $this->rrdData = null; } + + public function __toString() + { + return $this->rraInfo->__toString(); + } + + public function getRraInfo(): RraInfo + { + return $this->rraInfo; + } } \ No newline at end of file diff --git a/src/Rra/RraInfo.php b/src/Rra/RraInfo.php index 72af3ab..7073670 100644 --- a/src/Rra/RraInfo.php +++ b/src/Rra/RraInfo.php @@ -3,38 +3,21 @@ namespace RrdPhpReader\Rra; - -use RrdPhpReader\RrdData; - class RraInfo { - /** - * @var RrdData - */ - private $rrd_data; + private $rowCount; + private $pdpStep; + private $pdpPerRow; - private $rra_def_idx; - private $int_align; - private $row_cnt; - private $pdp_step; - private $my_idx; - private $rra_pdp_cnt_idx; - - public function __construct(RrdData $rrd_data, $rra_def_idx, $int_align, $row_cnt, $pdp_step, $my_idx) - { - $this->rrd_data = $rrd_data; - $this->rra_def_idx = $rra_def_idx; - $this->int_align = $int_align; - $this->row_cnt = $row_cnt; - $this->pdp_step = $pdp_step; - $this->my_idx = $my_idx; - - $this->rra_pdp_cnt_idx = $rra_def_idx + (int)(ceil(20 / $int_align) * $int_align + $int_align); - } + /** @var string */ + private $cfName; - public function getIdx(): int + public function __construct(string $cfName, $rowCount, $pdpStep, $pdpPerRow) { - return $this->my_idx; + $this->rowCount = $rowCount; + $this->pdpStep = $pdpStep; + $this->pdpPerRow = $pdpPerRow; + $this->cfName = $cfName; } /** @@ -42,9 +25,9 @@ public function getIdx(): int * * @return int */ - public function getNrRows(): int + public function getRowCount(): int { - return $this->row_cnt; + return $this->rowCount; } /** @@ -54,7 +37,7 @@ public function getNrRows(): int */ public function getPdpPerRow(): int { - return $this->rrd_data->getLongAt($this->rra_pdp_cnt_idx); + return $this->pdpPerRow; } /** @@ -64,7 +47,7 @@ public function getPdpPerRow(): int */ public function getStep(): int { - return $this->pdp_step * $this->getPdpPerRow(); + return $this->pdpStep * $this->getPdpPerRow(); } /** @@ -74,12 +57,18 @@ public function getStep(): int */ public function getCFName(): string { - return $this->rrd_data->getCStringAt($this->rra_def_idx, 20); + return $this->cfName; } - public function __destruct() + public function __toString() { - $this->rrd_data = null; + return sprintf( + 'cf=%s, step=%d, pdpPerRow=%d, rowCount=%d', + $this->getCFName(), + $this->getStep(), + $this->getPdpPerRow(), + $this->getRowCount() + ); } } \ No newline at end of file diff --git a/src/RrdDs.php b/src/RrdDs.php index d5736ae..b41eb81 100644 --- a/src/RrdDs.php +++ b/src/RrdDs.php @@ -5,55 +5,82 @@ class RrdDs { - /** - * @var RrdData - */ - private $rrdData; + /** @var int */ + private $dsIndex; - /** - * @var int - */ - private $dataIndex; + /** @var string */ + private $name; - /** - * @var int - */ - private $dsIndex; + /** @var string */ + private $type; - public function __construct(RrdData $rrdData, int $dataIndex, int $dsIndex) - { - $this->rrdData = $rrdData; - $this->dataIndex = $dataIndex; - $this->dsIndex = $dsIndex; - } + /** @var float */ + private $min; - public function getIndex(): int + /** @var float */ + private $max; + + public function __construct(int $dsIndex, string $name, string $type, float $min, float $max) { - return $this->dsIndex; + $this->dsIndex = $dsIndex; + $this->name = $name; + $this->type = $type; + $this->min = $min; + $this->max = $max; } + /** + * @return string + */ public function getName(): string { - return $this->rrdData->getCStringAt($this->dataIndex, 20); + return $this->name; } public function getType(): string { - return $this->rrdData->getCStringAt($this->dataIndex + 20, 20); + return $this->type; } public function getMin(): float { - return $this->rrdData->getDoubleAt($this->dataIndex + 48); + return $this->min; } public function getMax(): float { - return $this->rrdData->getDoubleAt($this->dataIndex + 56); + return $this->max; } - public function __destruct() + public function getIndex(): int { - $this->rrdData = null; + return $this->dsIndex; + } + + public function __toString() + { + return sprintf( + 'name=%s, type=%s, min=%f, max=%f', + $this->getName(), + $this->getType(), + $this->getMin(), + $this->getMax() + ); + } + + public static function fromData(RrdData $rrdData, int $dataIndex, int $dsIndex): RrdDs + { + $name = $rrdData->getCStringAt($dataIndex, 20); + $type = $rrdData->getCStringAt($dataIndex + 20, 20); + $min = $rrdData->getDoubleAt($dataIndex + 48); + $max = $rrdData->getDoubleAt($dataIndex + 56); + + return new self( + $dsIndex, + $name, + $type, + $min, + $max + ); } } \ No newline at end of file diff --git a/src/RrdFile.php b/src/RrdFile.php index 39ed84b..34e346e 100644 --- a/src/RrdFile.php +++ b/src/RrdFile.php @@ -8,14 +8,10 @@ class RrdFile { - /** - * @var RrdHeader - */ + /** @var RrdHeader */ private $header; - /** - * @var RrdData - */ + /** @var RrdData */ private $rrdData; public function __construct(RrdData $rrdData) @@ -24,15 +20,14 @@ public function __construct(RrdData $rrdData) $this->header = new RrdHeader($rrdData); } - public function getHeader(): RrdHeader { return $this->header; } - public function getMinStep(): int + public function getStep(): int { - return $this->header->getMinStep(); + return $this->header->getStep(); } public function getLastUpdate(): int @@ -40,9 +35,9 @@ public function getLastUpdate(): int return $this->header->getLastUpdate(); } - public function getNrDSs(): int + public function getDsCount(): int { - return $this->header->getNrDSs(); + return $this->header->getDsCount(); } public function getDS($ds): RrdDs @@ -53,9 +48,24 @@ public function getDS($ds): RrdDs return $this->header->getDSbyIdx($ds); } - public function getNrRRAs(): int + /** + * Return associative array (key=>ds) of all datasources in RRD file + * + * @return RrdDs[] + */ + public function getAllDS(): array { - return $this->header->getNrRRAs(); + $dataSources = []; + for ($i = 0; $i < $this->getDsCount(); $i++) { + $rrdDs = $this->getDS($i); + $dataSources[$rrdDs->getName()] = $rrdDs; + } + return $dataSources; + } + + public function getRraCount(): int + { + return $this->header->getRraCount(); } public function getRRAInfo(int $idx): RraInfo @@ -66,16 +76,32 @@ public function getRRAInfo(int $idx): RraInfo public function getRRA(int $idx): Rra { $rra_info = $this->header->getRRAInfo($idx); + return new Rra( $this->rrdData, $this->header->rra_ptr_idx + ($idx * $this->header->rra_ptr_el_size), $rra_info, - $this->header->header_size, - $this->header->rra_def_row_cnt_sums[$idx], - $this->header->getNrDSs() + $this->header->getDsCount(), + $this->header->getRraBaseOffsetIndex($idx) ); } + + /** + * Return all RRAs in RRD file + * + * @return Rra[] + */ + public function getAllRRAs(): array + { + $rras = []; + $rraCount = $this->getRraCount(); + for ($i = 0; $i < $rraCount; $i++) { + $rras[$i] = $this->getRRA($i); + } + return $rras; + } + public function __destruct() { $this->header = null; diff --git a/src/RrdHeader.php b/src/RrdHeader.php index 80f04e8..dc44d4a 100644 --- a/src/RrdHeader.php +++ b/src/RrdHeader.php @@ -292,7 +292,7 @@ private function calculateIndexes() /** * https://github.com/oetiker/rrdtool-1.x/blob/f1770608cdf15283dc44eada2a8a12a21825ee71/src/rrd_format.h#L289 - * + * * typedef struct live_head_t { * time_t last_up; // when was rrd last updated * long last_up_usec; // micro seconds part of the update timestamp. Always >= 0 @@ -333,7 +333,11 @@ private function loadRowCounts() } } - public function getMinStep(): int + /** + * Get base step value for RRD. Specifies the base interval in seconds with which data will be fed into the RRD + * @return int + */ + public function getStep(): int { return $this->pdp_step; } @@ -343,7 +347,7 @@ public function getLastUpdate(): int return $this->rrdData->getLongAt($this->live_head_idx); } - public function getNrDSs(): int + public function getDsCount(): int { return $this->ds_cnt; } @@ -370,7 +374,7 @@ public function getDSNames(): array public function getDSbyIdx(int $idx): RrdDs { if (($idx >= 0) && ($idx < $this->ds_cnt)) { - return new RrdDs( + return RrdDs::fromData( $this->rrdData, $this->ds_def_idx + $this->ds_el_size * $idx, $idx @@ -396,7 +400,7 @@ public function getDSbyName(string $name): RrdDs throw new RrdRangeException("DS name {$name} unknown."); } - public function getNrRRAs(): int + public function getRraCount(): int { return $this->rra_cnt; } @@ -409,14 +413,16 @@ public function getNrRRAs(): int public function getRRAInfo(int $idx): RraInfo { if (($idx >= 0) && ($idx < $this->rra_cnt)) { + $rra_def_idx = $this->rra_def_idx + $idx * $this->rra_def_el_size; + $cfName = $this->rrdData->getCStringAt($rra_def_idx, 20); + $rra_pdp_cnt_idx = $rra_def_idx + (int)(ceil(20 / $this->int_align) * $this->int_align + $this->int_align); + $pdpPerRow = $this->rrdData->getLongAt($rra_pdp_cnt_idx); return new RraInfo( - $this->rrdData, - $rra_def_idx, - $this->int_align, + $cfName, $this->rra_def_row_cnts[$idx], $this->pdp_step, - $idx + $pdpPerRow ); } throw new RrdRangeException("RRA idx ({$idx}) out of range [0-{$this->rra_cnt})."); @@ -427,4 +433,9 @@ public function __destruct() $this->rrdData = null; } + public function getRraBaseOffsetIndex(int $rraIdx): int + { + return $this->header_size + $this->rra_def_row_cnt_sums[$rraIdx] * ($this->ds_cnt * 8); + } + } \ No newline at end of file diff --git a/src/RrdReader.php b/src/RrdReader.php index d9de20b..9f445ac 100644 --- a/src/RrdReader.php +++ b/src/RrdReader.php @@ -4,25 +4,20 @@ namespace RrdPhpReader; +use InvalidArgumentException; use RrdPhpReader\Exception\RrdException; use RrdPhpReader\Rra\Rra; +use Traversable; class RrdReader { - /** - * @var RrdFile - */ - private $rrdFile = null; + const OPTION_DS = 'ds'; + const OPTION_RRA_INDEX = 'rra_index'; + const OPTION_RRA_FILTER_CALLBACK = 'rra_filter_callback'; + const OPTION_ROW_FILTER_CALLBACK = 'row_filter_callback'; - /** - * @var string - */ - private $ds = null; - - /** - * @var int - */ - private $rraIndex; + /** @var RrdFile */ + private $rrdFile; protected function __construct(RrdFile $rrdFile) { @@ -52,57 +47,116 @@ public static function create(RrdData $data) return new static(new RrdFile($data)); } - public function getAsArray(): array + /** + * @param array|null $options + * @return Traversable + */ + public function getAll(array $options = null): Traversable + { + $dataSources = $this->getDataSources($options); + $rras = $this->getRras($options); + + return $this->extractRows($dataSources, $rras, $options); + } + + /** + * @return RrdRowValue[] + */ + public function getAllAsArray(array $options = null): array { - /** @var RrdDs[] $ds */ - $ds = []; - if ($this->ds !== null) { - $ds[$this->ds] = $this->rrdFile->getDS($this->ds); + return iterator_to_array($this->getAll($options)); + } + + /** + * @return RrdDs[] + */ + public function getDataSources(array $options = null): array + { + $dataSources = []; + $dsName = $options[static::OPTION_DS] ?? null; + + if ($dsName !== null) { + $dataSources[$dsName] = $this->rrdFile->getDS($dsName); } else { - for ($i = 0; $i < $this->rrdFile->getNrDSs(); $i++) { - $rrdDs = $this->rrdFile->getDS($i); - $ds[$rrdDs->getName()] = $rrdDs; - } + $dataSources = $this->rrdFile->getAllDS(); } - /** @var Rra[] $rras */ - $rras = []; - if ($this->rraIndex !== null) { - $rras[$this->rraIndex] = $this->rrdFile->getRRA($this->rraIndex); - } else { - for ($i = 0; $i < $this->rrdFile->getNrRRAs(); $i++) { - $rras[$i] = $this->rrdFile->getRRA($i); + return $dataSources; + } + + /** + * @return Rra[] + */ + private function getRras(array $options = null): array + { + $rraIndex = $options[static::OPTION_RRA_INDEX] ?? null; + if ($rraIndex !== null) { + $rras[$rraIndex] = $this->rrdFile->getRRA((int)$rraIndex); + return $rras; + } + + $rras = $this->rrdFile->getAllRRAs(); + $rraFilterCallback = $options[static::OPTION_RRA_FILTER_CALLBACK] ?? null; + if (!is_string($rraFilterCallback) && is_callable($rraFilterCallback)) { + $tmpRras = []; + foreach ($rras as $rra) { + if ($rraFilterCallback($rra)) { + $tmpRras[] = $rra; + } + } + $rras = $tmpRras; } + return $rras; + } - $data = []; + /** + * Iterator returning data by timestamp => RrdRowValue pairs + * + * @param RrdDs[] $dataSources + * @param Rra[] $rras + * @param array|null $options + * + * @return Traversable + */ + private function extractRows(array $dataSources, array $rras, array $options = null) + { + $rowCallback = $options[static::OPTION_ROW_FILTER_CALLBACK] ?? null; + $hasRowCallback = !is_string($rowCallback) && is_callable($rowCallback); $time = $this->rrdFile->getLastUpdate(); - foreach ($rras as $rraIndex => $rra) { + foreach ($rras as $index => $rra) { $rowCount = $rra->getRowCount(); $step = $rra->getStep(); $startTimestamp = $time - ($step * $rowCount); $currentTimestamp = $startTimestamp; for ($row = 0; $row < $rowCount; $row++) { $currentTimestamp += $step; - foreach ($ds as $dsName => $dsTmp) { - $data[$dsName][$rraIndex][$currentTimestamp] = $rra->getRow($row, $dsTmp->getIndex()); + foreach ($dataSources as $dsName => $dsTmp) { + $rowValue = $rra->getRow($row, $dsTmp->getIndex()); + if ($hasRowCallback && !$rowCallback($currentTimestamp, $rowValue, $dsTmp, $rra->getRraInfo())) { + continue; + } + yield new RrdRowValue($currentTimestamp, $rowValue, $dsName, $rra->getRraInfo()); } } } - - return $data; } - public function setDs(string $ds): RrdReader + public function outputAsCsv($handle, array $options = null) { - $this->ds = $ds; - return $this; - } + if (!is_resource($handle)) { + throw new InvalidArgumentException('resource expected, ' . gettype($handle) . ' given'); + } + $delimiter = $options['delimiter'] ?? ','; + + fputcsv($handle, RrdRowValue::asHeader(), $delimiter); + + $it = $this->getAll($options); + /** @var RrdRowValue $value */ + foreach ($it as $value) { + fputcsv($handle, $value->asArray(), $delimiter); + } - public function setRraIndex(int $rraIndex): RrdReader - { - $this->rraIndex = $rraIndex; - return $this; } } \ No newline at end of file diff --git a/src/RrdRowValue.php b/src/RrdRowValue.php new file mode 100644 index 0000000..8a13000 --- /dev/null +++ b/src/RrdRowValue.php @@ -0,0 +1,106 @@ +timestamp = $timestamp; + $this->value = $value; + $this->ds = $ds; + $this->rra = $rra; + } + + /** + * @return int + */ + public function getTimestamp(): int + { + return $this->timestamp; + } + + /** + * @return float + */ + public function getValue(): float + { + return $this->value; + } + + /** + * @return string + */ + public function getDs(): string + { + return $this->ds; + } + + /** + * consolidation function + * + * @return string + */ + public function getCf(): string + { + return $this->rra->getCFName(); + } + + /** + * @return RraInfo + */ + public function getRra(): RraInfo + { + return $this->rra; + } + + public function __toString() + { + return sprintf( + 'timestamp=%d, value=%f, cf=%s, ds=%s, step=%d', + $this->timestamp, + $this->value, + $this->rra->getCFName(), + $this->ds, + $this->rra->getStep() + ); + } + + public function asArray(): array + { + return [ + 'timestamp' => $this->timestamp, + 'value' => $this->value, + 'cf' => $this->rra->getCFName(), + 'ds' => $this->ds, + 'step' => $this->rra->getStep() + ]; + } + + public static function asHeader(): array + { + return [ + 'timestamp', + 'value', + 'cf', + 'ds', + 'step', + ]; + } +} \ No newline at end of file diff --git a/tests/RrdFileTest.php b/tests/RrdFileTest.php index 300d25f..9741eb3 100644 --- a/tests/RrdFileTest.php +++ b/tests/RrdFileTest.php @@ -13,7 +13,7 @@ protected function checkFile($filename) $rrdFile = new RrdFile(new RrdData(FileUtils::getContents($filename))); $this->assertEquals(1521054894, $rrdFile->getLastUpdate()); // initial value from 1521054885 + (10-1) - $this->assertEquals(2, $rrdFile->getNrDSs()); + $this->assertEquals(2, $rrdFile->getDsCount()); $this->assertEquals( ['value', 'extra_value'], $rrdFile->getHeader()->getDSNames() @@ -61,7 +61,7 @@ public function testShouldThrowExceptionForHugeData() private function getRraData(RrdFile $rrdFile, int $dsIndex): array { $rras = []; - for ($i = 0; $i < $rrdFile->getNrRRAs(); $i++) { + for ($i = 0; $i < $rrdFile->getRraCount(); $i++) { $rra = $rrdFile->getRRA($i); $data = []; diff --git a/tests/RrdReaderTest.php b/tests/RrdReaderTest.php index 8aa65ba..6eeccab 100644 --- a/tests/RrdReaderTest.php +++ b/tests/RrdReaderTest.php @@ -4,63 +4,119 @@ use PHPUnit\Framework\TestCase; +use RrdPhpReader\Rra\RraInfo; use RrdPhpReader\RrdReader; +use RrdPhpReader\RrdRowValue; class RrdReaderTest extends TestCase { - const EXAMPLE_FOR_VALUE = [ - 1521054891 => 6.0, - 1521054892 => 7.0, - 1521054893 => 8.0, - 1521054894 => 9.0, - ]; - - const EXAMPLE_FOR_EXTRA_VALUE = [ - 1521054891 => 2.0, - 1521054892 => 1.5, - 1521054893 => 1.0, - 1521054894 => 0.5, - ]; - - public function testReadDataForSpecificDsRra() + private static $EXAMPLE_FOR_VALUE; + private static $EXAMPLE_FOR_VALUE_MAX; + private static $EXAMPLE_FOR_EXTRA_VALUE; + private static $EXAMPLE_FOR_EXTRA_VALUE_MAX; + + public static function setUpBeforeClass() { - $reader = RrdReader::createFromString(FileUtils::getContents('rrd_linux_x86_64.rrd')); + $rraAverage = new RraInfo('AVERAGE', 4, 1, 1); + $rraMax = new RraInfo('MAX', 4, 1, 1); + + self::$EXAMPLE_FOR_VALUE = [ + new RrdRowValue(1521054891, 6.0, 'value', $rraAverage), + new RrdRowValue(1521054892, 7.0, 'value', $rraAverage), + new RrdRowValue(1521054893, 8.0, 'value', $rraAverage), + new RrdRowValue(1521054894, 9.0, 'value', $rraAverage), + ]; + self::$EXAMPLE_FOR_VALUE_MAX = [ + new RrdRowValue(1521054891, 6.0, 'value', $rraMax), + new RrdRowValue(1521054892, 7.0, 'value', $rraMax), + new RrdRowValue(1521054893, 8.0, 'value', $rraMax), + new RrdRowValue(1521054894, 9.0, 'value', $rraMax), + ]; + self::$EXAMPLE_FOR_EXTRA_VALUE = [ + new RrdRowValue(1521054891, 2.0, 'extra_value', $rraAverage), + new RrdRowValue(1521054892, 1.5, 'extra_value', $rraAverage), + new RrdRowValue(1521054893, 1.0, 'extra_value', $rraAverage), + new RrdRowValue(1521054894, 0.5, 'extra_value', $rraAverage), + ]; + self::$EXAMPLE_FOR_EXTRA_VALUE_MAX = [ + new RrdRowValue(1521054891, 2.0, 'extra_value', $rraMax), + new RrdRowValue(1521054892, 1.5, 'extra_value', $rraMax), + new RrdRowValue(1521054893, 1.0, 'extra_value', $rraMax), + new RrdRowValue(1521054894, 0.5, 'extra_value', $rraMax), + ]; + } - $data = $reader->setDs('value')->setRraIndex(0)->getAsArray(); + public function allArchFiles(): array + { + return [ + 'rrd_linux_x86_64' => ['rrd_linux_x86_64.rrd'], + 'rrd_windows_x86_64' => ['rrd_windows_x86_64.rrd'], + 'rrd_windows_server_x86_64' => ['rrd_windows_server_x86_64.rrd'], + ]; + } + + /** + * @dataProvider allArchFiles + */ + public function testReadDataForSpecificDsRra(string $testRrd) + { + $reader = RrdReader::createFromString(FileUtils::getContents($testRrd)); + + $data = $reader->getAllAsArray(['ds' => 'value', 'rra_index' => 0]); $this->assertEquals( - self::EXAMPLE_FOR_VALUE, - $data['value'][0] + self::$EXAMPLE_FOR_VALUE, + $data ); } - public function testReadDataAllRras() + /** + * @dataProvider allArchFiles + */ + public function testReadDataAllRras(string $testRrd) { - $reader = RrdReader::createFromString(FileUtils::getContents('rrd_linux_x86_64.rrd')); + $reader = RrdReader::createFromString(FileUtils::getContents($testRrd)); - $data = $reader->setDs('value')->getAsArray(); + $data = $reader->getAllAsArray(['ds' => 'value']); - $this->assertEquals(self::EXAMPLE_FOR_VALUE, $data['value'][0]); - $this->assertEquals(self::EXAMPLE_FOR_VALUE, $data['value'][1]); + $this->assertEquals(self::$EXAMPLE_FOR_VALUE[0], $data[0]); + $this->assertEquals(self::$EXAMPLE_FOR_VALUE[3], $data[3]); + $this->assertEquals(self::$EXAMPLE_FOR_VALUE_MAX[0], $data[4]); + $this->assertEquals(self::$EXAMPLE_FOR_VALUE_MAX[3], $data[7]); } - public function testReadDataAllDsAllRras() + /** + * @dataProvider allArchFiles + */ + public function testReadDataAllDsAllRras(string $testRrd) { - $reader = RrdReader::createFromString(FileUtils::getContents('rrd_linux_x86_64.rrd')); + $reader = RrdReader::createFromString(FileUtils::getContents($testRrd)); + + $data = $reader->getAllAsArray(); + + $this->assertEquals(self::$EXAMPLE_FOR_VALUE[0], $data[0]); + $this->assertEquals(self::$EXAMPLE_FOR_EXTRA_VALUE[0], $data[1]); + + $this->assertEquals(self::$EXAMPLE_FOR_VALUE[3], $data[6]); + $this->assertEquals(self::$EXAMPLE_FOR_EXTRA_VALUE[3], $data[7]); + + $this->assertEquals(self::$EXAMPLE_FOR_VALUE_MAX[0], $data[8]); + $this->assertEquals(self::$EXAMPLE_FOR_EXTRA_VALUE_MAX[0], $data[9]); + + $this->assertEquals(self::$EXAMPLE_FOR_VALUE_MAX[3], $data[14]); + $this->assertEquals(self::$EXAMPLE_FOR_EXTRA_VALUE_MAX[3], $data[15]); - $data = $reader->getAsArray(); - $this->assertEquals(self::EXAMPLE_FOR_VALUE, $data['value'][0]); - $this->assertEquals(self::EXAMPLE_FOR_VALUE, $data['value'][1]); - $this->assertEquals(self::EXAMPLE_FOR_EXTRA_VALUE, $data['extra_value'][0]); - $this->assertEquals(self::EXAMPLE_FOR_EXTRA_VALUE, $data['extra_value'][1]); } - public function testReadDataAllDsSpecificRra() + /** + * @dataProvider allArchFiles + */ + public function testReadDataAllDsSpecificRra(string $testRrd) { - $reader = RrdReader::createFromString(FileUtils::getContents('rrd_linux_x86_64.rrd')); + $reader = RrdReader::createFromString(FileUtils::getContents($testRrd)); - $data = $reader->setRraIndex(1)->getAsArray(); + $data = $reader->getAllAsArray(['ds' => 'value', 'rra_index' => 1]); - $this->assertEquals(self::EXAMPLE_FOR_VALUE, $data['value'][1]); - $this->assertEquals(self::EXAMPLE_FOR_EXTRA_VALUE, $data['extra_value'][1]); + $this->assertEquals(self::$EXAMPLE_FOR_VALUE_MAX[0], $data[0]); + $this->assertEquals(self::$EXAMPLE_FOR_VALUE_MAX[3], $data[3]); } } \ No newline at end of file