filelock.php

Simple file locks for php
git clone git://git.finwo.net/lib/filelock.php
Log | Files | Refs | README | LICENSE

commit ef59cd8f4e9869d0122f22ab5d93807495cd032b
parent 7299cb83df8b2fe3908d463fb1fc0e18dd5e97e1
Author: finwo <finwo@pm.me>
Date:   Mon, 23 Jan 2017 13:32:00 +0100

Project init

Diffstat:
A.gitignore | 3+++
A.travis.yml | 11+++++++++++
MLICENSE | 2+-
AREADME.md | 18++++++++++++++++++
Acomposer.json | 18++++++++++++++++++
Acomposer.lock | 19+++++++++++++++++++
Aphpunit.xml | 19+++++++++++++++++++
Asrc/FileLock.php | 98+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/LintTest.php | 33+++++++++++++++++++++++++++++++++
9 files changed, 220 insertions(+), 1 deletion(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1,3 @@ +/.idea/ +.zedstate +/vendor/ diff --git a/.travis.yml b/.travis.yml @@ -0,0 +1,11 @@ +language: php +php: + - '5.3' + - '5.4' + - '5.5' + - '5.6' + - '7.0' + +install: + - yes '' | pecl install -f memcached + - composer update --prefer-dist diff --git a/LICENSE b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2017 Robin Bron +Copyright (c) 2017 Finwo Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md @@ -0,0 +1,18 @@ +# finwo / filelock + +[![Build Status](https://travis-ci.org/finwo/php-filelock.svg?branch=master)](https://travis-ci.org/finwo/php-filelock) + +----- + +### Contributing + +After checking the [Github issues](https://github.com/finwo/php-filelock/issues) and confirming that your request isn't already being worked on, feel free to spawn a new fork of the develop branch & send in a pull request. + + +The develop branch is merged periodically into the master after confirming it's stable, to make sure the master always contains a production-ready version. + +----- + +### Changelog +- 2017-01-23 + - Project init diff --git a/composer.json b/composer.json @@ -0,0 +1,18 @@ +{ + "name" : "finwo/filelock", + "minimum-stability": "stable", + "authors" : [ + { + "name" : "Robin Bron", + "email": "robin@finwo.nl" + } + ], + "autoload" : { + "psr-4": { + "Finwo\\FileLock\\": "src" + } + }, + "require" : { + "php": ">=5.3" + } +} diff --git a/composer.lock b/composer.lock @@ -0,0 +1,19 @@ +{ + "_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", + "This file is @generated automatically" + ], + "content-hash": "89f6ee34b0376cb520f72b058dfd4d92", + "packages": [], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": ">=5.3" + }, + "platform-dev": [] +} diff --git a/phpunit.xml b/phpunit.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<phpunit bootstrap="vendor/autoload.php" colors="true"> + + <testsuites> + <testsuite name="finwo/filelock test suite"> + <directory>./tests/</directory> + </testsuite> + </testsuites> + + <filter> + <whitelist> + <directory>./</directory> + <exclude> + <directory>./tests</directory> + </exclude> + </whitelist> + </filter> +</phpunit> diff --git a/src/FileLock.php b/src/FileLock.php @@ -0,0 +1,98 @@ +<?php + +namespace Finwo\FileLock; + +class FileLock +{ + /** + * @var string + */ + protected $filename = null; + + // 10 ms + const LOCK_WAIT = 10000; + + /** + * FileLock constructor. + * + * @param $filename + */ + public function __construct( $filename ) + { + $this->filename = $filename; + } + + /** + * @param int $hash + * + * @return resource + */ + protected static function getResource( $hash ) + { + static $resource = null; + if(is_null($resource)) { + $resource = sem_get($hash); + } + return $resource; + } + + /** + * @param string $filename + * + * @return bool + */ + public static function _acquire( $filename ) + { + if (function_exists('sem_get')) { + @sem_acquire(self::getResource(hexdec(md5($filename)))); + return true; + } else { + // Generate filename + $lockfile = $filename.'.lock'; + + // Wait until lock expired or gone + while(file_exists($lockfile)) { + $lockExpires = intval(@file_get_contents($lockfile)); + if($lockExpires<time()) { + unlink($lockfile); + } else { + usleep(self::LOCK_WAIT); + } + } + + // Create a lock + return file_put_contents($lockfile, sprintf("%d",time()+5)) !== false; + } + } + + /** + * @param string $filename + * + * @return bool + */ + public static function _release( $filename ) + { + if(function_exists('sem_get')) { + @sem_release(self::getResource(hexdec(md5($filename)))); + return true; + } else { + return @unlink($filename.'.lock'); + } + } + + /** + * @return bool + */ + public function acquire() { + return self::_acquire($this->filename); + } + + /** + * @return bool + */ + public function release() { + return self::_release($this->filename); + } + + +} diff --git a/tests/LintTest.php b/tests/LintTest.php @@ -0,0 +1,33 @@ +<?php + +class LintTest extends \PHPUnit_Framework_TestCase +{ + public function testSrc() + { + // Main entry + $fileList = \glob('src/'); + + // Loop through known files + while ( $inode = \array_shift($fileList) ) { + + // Try to iterate deeper + if ( is_dir($inode) ) { + $fileList = \array_merge($fileList, \glob(\realpath($inode).'/*')); + continue; + } + + // If we're a PHP file + if (\preg_match('/^.+\.(php|inc)$/i', $inode)) { + // Run a unit test + $this->lintFile($inode); + } + + } + } + + private function lintFile($filename = '') + { + // And actually run the test (with proper error message) + $this->assertContains('No syntax errors', \exec(\sprintf('php -l "%s"', $filename), $out), \sprintf("%s contains syntax errors", $filename)); + } +}