~ubuntu-branches/ubuntu/quantal/gallery2/quantal

« back to all changes in this revision

Viewing changes to modules/core/test/phpunit/LockTest.class

  • Committer: Bazaar Package Importer
  • Author(s): Michael C. Schultheiss
  • Date: 2007-09-10 20:22:19 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20070910202219-0jsuntvqge4ade6b
Tags: 2.2.3-2
Add Slovak translation of Debconf templates.  (Thanks to 
Ivan Masá.  Closes: #441671)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
<?php
2
 
/*
3
 
 * Gallery - a web based photo album viewer and editor
4
 
 * Copyright (C) 2000-2007 Bharat Mediratta
5
 
 *
6
 
 * This program is free software; you can redistribute it and/or modify
7
 
 * it under the terms of the GNU General Public License as published by
8
 
 * the Free Software Foundation; either version 2 of the License, or (at
9
 
 * your option) any later version.
10
 
 *
11
 
 * This program is distributed in the hope that it will be useful, but
12
 
 * WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 
 * General Public License for more details.
15
 
 *
16
 
 * You should have received a copy of the GNU General Public License
17
 
 * along with this program; if not, write to the Free Software
18
 
 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
19
 
 */
20
 
 
21
 
GalleryCoreApi::requireOnce('modules/core/classes/DatabaseLockSystem.class');
22
 
GalleryCoreApi::requireOnce('modules/core/classes/FlockLockSystem.class');
23
 
 
24
 
/**
25
 
 * Lock tests.
26
 
 * @package GalleryCore
27
 
 * @subpackage PHPUnit
28
 
 * @author Bharat Mediratta <bharat@menalto.com>
29
 
 * @version $Revision: 15799 $
30
 
 */
31
 
class LockTest extends GalleryTestCase {
32
 
 
33
 
    function LockTest($methodName) {
34
 
        $this->GalleryTestCase($methodName);
35
 
    }
36
 
 
37
 
    function setUp() {
38
 
        global $gallery;
39
 
        parent::setUp();
40
 
 
41
 
        list ($ret, $this->_album) = $this->_createRandomAlbum($this->_getRootId());
42
 
        if ($ret) {
43
 
            return $this->failWithStatus($ret);
44
 
        }
45
 
        $this->_markForCleanup($this->_album);
46
 
 
47
 
        list ($ret, $this->_item) = $this->_createRandomDataItem($this->_album->getId());
48
 
        if ($ret) {
49
 
            return $this->failWithStatus($ret);
50
 
        }
51
 
 
52
 
        $storage =& $gallery->getStorage();
53
 
        $ret = $storage->checkPoint();
54
 
        if ($ret) {
55
 
            return $this->failWithStatus($ret);
56
 
        }
57
 
    }
58
 
 
59
 
    function _tryAllLockSystems($testFunction) {
60
 
        global $gallery;
61
 
        $testFunction = '_' . $testFunction;
62
 
 
63
 
        $gallery->_lockSystem = new DatabaseLockSystem();
64
 
        $this->$testFunction('dblock');
65
 
        $gallery->_lockSystem->releaseAllLocks();
66
 
        $gallery->_lockSystem->releaseQueue();
67
 
 
68
 
        $gallery->_lockSystem = new FlockLockSystem();
69
 
        $this->$testFunction('flock');
70
 
        $gallery->_lockSystem->releaseAllLocks();
71
 
        $gallery->_lockSystem->releaseQueue();
72
 
    }
73
 
 
74
 
    function testOneWriteLock() {
75
 
        return $this->_tryAllLockSystems('testOneWriteLock');
76
 
    }
77
 
 
78
 
    function _testOneWriteLock($lockSystem) {
79
 
        $targetId = $this->_item->getId();
80
 
 
81
 
        list ($ret, $lockId) = GalleryCoreApi::acquireWriteLock($targetId);
82
 
        if ($ret) {
83
 
            return $this->failWithStatus($ret);
84
 
        }
85
 
 
86
 
        $this->assert(is_int($lockId), "$lockSystem: lock id is not an integer");
87
 
 
88
 
        $this->assert(GalleryCoreApi::isWriteLocked($targetId), $lockSystem);
89
 
 
90
 
        $ret = GalleryCoreApi::releaseLocks($lockId);
91
 
        if ($ret) {
92
 
            return $this->failWithStatus($ret);
93
 
        }
94
 
    }
95
 
 
96
 
    function testManyWriteLocks() {
97
 
        return $this->_tryAllLockSystems('testManyWriteLocks');
98
 
    }
99
 
 
100
 
    function _testManyWriteLocks($lockSystem) {
101
 
        global $gallery;
102
 
 
103
 
        $ids = array($gallery->getActiveUserId(), $this->_getRootId(), $this->_item->getId());
104
 
 
105
 
        list ($ret, $lockId) = GalleryCoreApi::acquireWriteLock($ids);
106
 
        if ($ret) {
107
 
            return $this->failWithStatus($ret);
108
 
        }
109
 
 
110
 
        $this->assert(is_int($lockId), "$lockSystem: lock id is not an integer");
111
 
 
112
 
        foreach ($ids as $id) {
113
 
            $this->assert(GalleryCoreApi::isWriteLocked($id), "$lockSystem: $id");
114
 
        }
115
 
 
116
 
        $ret = GalleryCoreApi::releaseLocks($lockId);
117
 
        if ($ret) {
118
 
            return $this->failWithStatus($ret);
119
 
        }
120
 
    }
121
 
 
122
 
    function testOneReadLock() {
123
 
        return $this->_tryAllLockSystems('testOneReadLock');
124
 
    }
125
 
 
126
 
    function _testOneReadLock($lockSystem) {
127
 
        $targetId = $this->_album->getId();
128
 
 
129
 
        list ($ret, $lockId) = GalleryCoreApi::acquireReadLock($targetId);
130
 
        if ($ret) {
131
 
            return $this->failWithStatus($ret);
132
 
        }
133
 
 
134
 
        $this->assert(is_int($lockId), "$lockSystem: lock id is not an integer");
135
 
 
136
 
        $this->assert(GalleryCoreApi::isReadLocked($targetId), $lockSystem);
137
 
 
138
 
        $ret = GalleryCoreApi::releaseLocks($lockId);
139
 
        if ($ret) {
140
 
            return $this->failWithStatus($ret);
141
 
        }
142
 
    }
143
 
 
144
 
    function testManyReadLocks() {
145
 
        return $this->_tryAllLockSystems('testManyReadLocks');
146
 
    }
147
 
 
148
 
    function _testManyReadLocks($lockSystem) {
149
 
        global $gallery;
150
 
 
151
 
        $ids = array($gallery->getActiveUserId(), $this->_getRootId(), $this->_item->getId());
152
 
 
153
 
        list ($ret, $lockId) = GalleryCoreApi::acquireReadLock($ids);
154
 
        if ($ret) {
155
 
            return $this->failWithStatus($ret);
156
 
        }
157
 
 
158
 
        $this->assert(is_int($lockId), "$lockSystem: lock id is not an integer");
159
 
 
160
 
        foreach ($ids as $id) {
161
 
            $this->assert(GalleryCoreApi::isReadLocked($id), "$lockSystem: $id");
162
 
        }
163
 
 
164
 
        $ret = GalleryCoreApi::releaseLocks($lockId);
165
 
        if ($ret) {
166
 
            return $this->failWithStatus($ret);
167
 
        }
168
 
    }
169
 
 
170
 
    function testAcquireReadLockParents() {
171
 
        return $this->_tryAllLockSystems('testAcquireReadLockParents');
172
 
    }
173
 
 
174
 
    function _testAcquireReadLockParents($lockSystem) {
175
 
        global $gallery;
176
 
 
177
 
        /* Create a hierarchy */
178
 
        $parentId = $this->_album->getId();
179
 
        for ($i = 0; $i < 3; $i++) {
180
 
            list ($ret, $this->_subAlbums[$i]) = $this->_createRandomAlbum($parentId);
181
 
            if ($ret) {
182
 
                return $this->failWithStatus($ret);
183
 
            }
184
 
            $parentId = $this->_subAlbums[$i]->getId();
185
 
        }
186
 
 
187
 
        list ($ret, $lockId) = GalleryCoreApi::acquireReadLockParents(
188
 
            $this->_subAlbums[2]->getId());
189
 
        if ($ret) {
190
 
            return $this->failWithStatus($ret);
191
 
        }
192
 
 
193
 
        $this->assert(is_int($lockId), "$lockSystem: lock id is not an integer");
194
 
 
195
 
        /* Verify that they're all locked except the item itself */
196
 
        $this->assert(!GalleryCoreApi::isReadLocked($this->_subAlbums[2]->getId()),
197
 
                      "$lockSystem: a2");
198
 
        $this->assert(GalleryCoreApi::isReadLocked($this->_subAlbums[1]->getId()),
199
 
                      "$lockSystem: a1");
200
 
        $this->assert(GalleryCoreApi::isReadLocked($this->_subAlbums[0]->getId()),
201
 
                      "$lockSystem: a0");
202
 
        $this->assert(GalleryCoreApi::isReadLocked($this->_album->getId()), "$lockSystem: p");
203
 
        $this->assert(GalleryCoreApi::isReadLocked($this->_getRootId()), "$lockSystem: r");
204
 
 
205
 
        /* Release locks */
206
 
        $ret = GalleryCoreApi::releaseLocks($lockId);
207
 
        if ($ret) {
208
 
            return $this->failWithStatus($ret);
209
 
        }
210
 
    }
211
 
 
212
 
    function testAcquireReadLockParentsOnRoot() {
213
 
        return $this->_tryAllLockSystems('testAcquireReadLockParentsOnRoot');
214
 
    }
215
 
 
216
 
    function _testAcquireReadLockParentsOnRoot($lockSystem) {
217
 
        global $gallery;
218
 
 
219
 
        list ($ret, $lockId) = GalleryCoreApi::acquireReadLockParents($this->_getRootId());
220
 
        if ($ret) {
221
 
            return $this->failWithStatus($ret);
222
 
        }
223
 
 
224
 
        /* Verify that the root is not read locked */
225
 
        $this->assert(!GalleryCoreApi::isReadLocked($this->_getRootId()),
226
 
                      "$lockSystem: Root should not be locked");
227
 
 
228
 
        /* Release locks */
229
 
        $ret = GalleryCoreApi::releaseLocks($lockId);
230
 
        if ($ret) {
231
 
            return $this->failWithStatus($ret);
232
 
        }
233
 
    }
234
 
 
235
 
    /**
236
 
     * Test acquiring a write lock on an entity that has already been read locked.  We don't
237
 
     * currently require this ability, but it could be useful if adding or deleting an item from an
238
 
     * album triggered an update to that album.  Uncomment this test if this type of locking is ever
239
 
     * used.  (Note that Windows has problems doing this with flock based locks, so we may avoid
240
 
     * any functionality that needs this.)
241
 
     */
242
 
    /*
243
 
    function testReadLockToWriteLock() {
244
 
        return $this->_tryAllLockSystems('testReadLockToWriteLock');
245
 
    }
246
 
    */
247
 
 
248
 
    function _testReadLockToWriteLock($lockSystem) {
249
 
        /* Read lock parents, then attempt to write lock direct parent */
250
 
        list ($ret, $lockId) = GalleryCoreApi::acquireReadLockParents($this->_item->getId());
251
 
        if ($ret) {
252
 
            return $this->failWithStatus($ret);
253
 
        }
254
 
 
255
 
        foreach (array($this->_getRootId(), $this->_album->getId()) as $id) {
256
 
            $this->assert(GalleryCoreApi::isReadLocked($id), "$lockSystem: read lock: $id");
257
 
        }
258
 
 
259
 
        list ($ret, $writeLockId) = GalleryCoreApi::acquireWriteLock($this->_album->getId());
260
 
        if ($ret) {
261
 
            return $this->failWithStatus($ret);
262
 
        }
263
 
 
264
 
        $this->assert(is_int($writeLockId), "$lockSystem: lock id is not an integer");
265
 
 
266
 
        $this->assert(GalleryCoreApi::isWriteLocked($this->_album->getId()),
267
 
                      "$lockSystem: write lock");
268
 
        $this->assert(GalleryCoreApi::isReadLocked($this->_getRootId()), "$lockSystem: read lock");
269
 
 
270
 
        /* Release locks */
271
 
        $ret = GalleryCoreApi::releaseLocks(array($lockId, $writeLockId));
272
 
        if ($ret) {
273
 
            return $this->failWithStatus($ret);
274
 
        }
275
 
    }
276
 
 
277
 
    /*
278
 
     * Verify that releaseLocks accepts sloppy input (null entries or empty list) so that error
279
 
     * handling code can pass in whatever array it has and not worry about cleaning it up to have
280
 
     * only valid locks.
281
 
     */
282
 
    function testReleaseNull() {
283
 
        return $this->_tryAllLockSystems('testReleaseNull');
284
 
    }
285
 
 
286
 
    function _testReleaseNull($lockSystem) {
287
 
        $targetId = $this->_item->getId();
288
 
        $lockIds = array();
289
 
 
290
 
        list ($ret, $lockIds[]) = GalleryCoreApi::acquireWriteLock($targetId);
291
 
        if ($ret) {
292
 
            return $this->failWithStatus($ret);
293
 
        }
294
 
 
295
 
        $this->assert(GalleryCoreApi::isWriteLocked($targetId), $lockSystem);
296
 
 
297
 
        $lockIds[] = null;
298
 
        $ret = GalleryCoreApi::releaseLocks($lockIds);
299
 
        if ($ret) {
300
 
            $this->assert(false, $lockSystem);
301
 
            return $this->failWithStatus($ret);
302
 
        }
303
 
 
304
 
        $this->assert(!GalleryCoreApi::isWriteLocked($targetId), $lockSystem . ' unlock');
305
 
    }
306
 
 
307
 
    /* See comment above */
308
 
    function testReleaseEmpty() {
309
 
        return $this->_tryAllLockSystems('testReleaseEmpty');
310
 
    }
311
 
 
312
 
    function _testReleaseEmpty($lockSystem) {
313
 
        $ret = GalleryCoreApi::releaseLocks(array());
314
 
        if ($ret) {
315
 
            $this->assert(false, $lockSystem);
316
 
            return $this->failWithStatus($ret);
317
 
        }
318
 
    }
319
 
 
320
 
    /**
321
 
     * Verify that locks are not being released before commit on transactional databases.
322
 
     * http://sourceforge.net/tracker/index.php?func=detail&aid=1345508&group_id=7130&atid=107130
323
 
     */
324
 
    function testReleaseLocksNotBeforeCommit() {
325
 
        global $gallery;
326
 
        $storage =& $gallery->getStorage();
327
 
 
328
 
        list ($ret, $lockId) = GalleryCoreApi::acquireWriteLock($this->_item->getId());
329
 
        if ($ret) {
330
 
            return $this->failWithStatus($ret);
331
 
        }
332
 
 
333
 
        $this->_item->setTitle($this->_item->getTitle() . 'changed');
334
 
        $ret = $this->_item->save();
335
 
        if ($ret) {
336
 
            GalleryCoreApi::releaseLocks($lockId);
337
 
            return $this->failWithStatus($ret);
338
 
        }
339
 
 
340
 
        $ret = GalleryCoreApi::releaseLocks($lockId);
341
 
        if ($ret) {
342
 
            return $this->failWithStatus($ret);
343
 
        }
344
 
 
345
 
        /* Temporarily clear the existing lock information to simulate another request */
346
 
        $queuedLocks = $gallery->_lockSystem->_releaseQueue;
347
 
        $locks = $gallery->_lockSystem->_locks;
348
 
        $gallery->_lockSystem->_releaseQueue = array();
349
 
        $gallery->_lockSystem->_locks = array();
350
 
 
351
 
        /* This should time out if the previous lock is queued */
352
 
        list ($ret, $secondLockId) = GalleryCoreApi::acquireWriteLock($this->_item->getId(), 5);
353
 
        if ($ret) {
354
 
            $this->assertEquals($ret->getErrorCode(), GALLERY_ERROR | ERROR_LOCK_TIMEOUT,
355
 
                'The lock acquisition should have timed out.');
356
 
            if ($ret->getErrorCode() != (GALLERY_ERROR | ERROR_LOCK_TIMEOUT)) {
357
 
                return $this->failWithStatus($ret);
358
 
            }
359
 
        } else {
360
 
            /* Lock successfully acquired, this should only happen on nontransactional databases */
361
 
            $this->assert(!$storage->isTransactional(), 'Lock acquired on transactional database.');
362
 
 
363
 
            $ret = GalleryCoreApi::releaseLocks($secondLockId);
364
 
            if ($ret) {
365
 
                return $this->failWithStatus($ret);
366
 
            }
367
 
        }
368
 
 
369
 
        /* Restore lock information and force their release. */
370
 
        $gallery->_lockSystem->_releaseQueue = $queuedLocks;
371
 
        $gallery->_lockSystem->_locks = $locks;
372
 
        $ret = $gallery->_lockSystem->releaseQueue();
373
 
        if ($ret) {
374
 
            return $this->failWithStatus($ret);
375
 
        }
376
 
    }
377
 
 
378
 
    function testRelockRead() {
379
 
        /* Read lock, release, relock before committing transaction */
380
 
        global $gallery;
381
 
        $storage =& $gallery->getStorage();
382
 
 
383
 
        list ($ret, $lockId) = GalleryCoreApi::acquireReadLock($this->_item->getId());
384
 
        if ($ret) {
385
 
            return $this->failWithStatus($ret);
386
 
        }
387
 
 
388
 
        $ret = GalleryCoreApi::releaseLocks($lockId);
389
 
        if ($ret) {
390
 
            return $this->failWithStatus($ret);
391
 
        }
392
 
 
393
 
        $this->assert(count($gallery->_lockSystem->_releaseQueue) == 1
394
 
                      || !$storage->isTransactional(), 'release first lock');
395
 
 
396
 
        list ($ret, $lockId) = GalleryCoreApi::acquireReadLock($this->_item->getId());
397
 
        if ($ret) {
398
 
            return $this->failWithStatus($ret);
399
 
        }
400
 
 
401
 
        $this->assert(is_int($lockId), 'lock id is not an integer');
402
 
 
403
 
        /* Release queue unaffected */
404
 
        $this->assert(count($gallery->_lockSystem->_releaseQueue) == 1
405
 
                      || !$storage->isTransactional(), 'get second lock');
406
 
 
407
 
        $ret = GalleryCoreApi::releaseLocks($lockId);
408
 
        if ($ret) {
409
 
            return $this->failWithStatus($ret);
410
 
        }
411
 
 
412
 
        /* Release queue unaffected, multiple read locks are ok */
413
 
        $this->assert(count($gallery->_lockSystem->_releaseQueue) == 2
414
 
                      || !$storage->isTransactional(), 'release second lock');
415
 
    }
416
 
 
417
 
    function testWriteThenRead() {
418
 
        /* Write lock, release, then acquire read lock before committing transaction */
419
 
        global $gallery;
420
 
        $storage =& $gallery->getStorage();
421
 
 
422
 
        list ($ret, $lockId) = GalleryCoreApi::acquireWriteLock($this->_item->getId());
423
 
        if ($ret) {
424
 
            return $this->failWithStatus($ret);
425
 
        }
426
 
 
427
 
        $ret = GalleryCoreApi::releaseLocks($lockId);
428
 
        if ($ret) {
429
 
            return $this->failWithStatus($ret);
430
 
        }
431
 
 
432
 
        $this->assert(count($gallery->_lockSystem->_releaseQueue) == 1
433
 
                      || !$storage->isTransactional(), 'release write lock');
434
 
 
435
 
        list ($ret, $lockId) = GalleryCoreApi::acquireReadLock($this->_item->getId());
436
 
        if ($ret) {
437
 
            return $this->failWithStatus($ret);
438
 
        }
439
 
 
440
 
        $this->assert(is_int($lockId), 'lock id is not an integer');
441
 
 
442
 
        /* Had to release that write lock in order to get new read lock */
443
 
        $this->assert(empty($gallery->_lockSystem->_releaseQueue), 'release queue should be empty');
444
 
 
445
 
        $ret = GalleryCoreApi::releaseLocks($lockId);
446
 
        if ($ret) {
447
 
            return $this->failWithStatus($ret);
448
 
        }
449
 
    }
450
 
 
451
 
    function testWriteThenReadPartial() {
452
 
        /* Write lock, release, then acquire a read lock for one entity in that write lock */
453
 
        global $gallery;
454
 
        $storage =& $gallery->getStorage();
455
 
 
456
 
        list ($ret, $lockId) = GalleryCoreApi::acquireWriteLock(array($this->_album->getId(),
457
 
                                                                      $this->_item->getId()));
458
 
        if ($ret) {
459
 
            return $this->failWithStatus($ret);
460
 
        }
461
 
 
462
 
        $ret = GalleryCoreApi::releaseLocks($lockId);
463
 
        if ($ret) {
464
 
            return $this->failWithStatus($ret);
465
 
        }
466
 
 
467
 
        $this->assert((count($gallery->_lockSystem->_releaseQueue) == 1
468
 
                && count($gallery->_lockSystem->_releaseQueue[$lockId]['ids']) == 2)
469
 
            || !$storage->isTransactional(), 'release write lock');
470
 
 
471
 
        list ($ret, $newLockId) = GalleryCoreApi::acquireReadLock($this->_item->getId());
472
 
        if ($ret) {
473
 
            return $this->failWithStatus($ret);
474
 
        }
475
 
 
476
 
        $this->assert(is_int($newLockId), 'lock id is not an integer');
477
 
 
478
 
        /* Removed single entity from pending write lock in order to get new read lock */
479
 
        $this->assert((count($gallery->_lockSystem->_releaseQueue) == 1
480
 
                && count($gallery->_lockSystem->_releaseQueue[$lockId]['ids']) == 1)
481
 
            || !$storage->isTransactional(), 'pending write lock should have one entity');
482
 
 
483
 
        $ret = GalleryCoreApi::releaseLocks($newLockId);
484
 
        if ($ret) {
485
 
            return $this->failWithStatus($ret);
486
 
        }
487
 
    }
488
 
 
489
 
    function testRelockWrite() {
490
 
        /* Write lock, release, relock before committing transaction */
491
 
        global $gallery;
492
 
        $storage =& $gallery->getStorage();
493
 
 
494
 
        list ($ret, $lockId) = GalleryCoreApi::acquireWriteLock($this->_item->getId());
495
 
        if ($ret) {
496
 
            return $this->failWithStatus($ret);
497
 
        }
498
 
 
499
 
        $ret = GalleryCoreApi::releaseLocks($lockId);
500
 
        if ($ret) {
501
 
            return $this->failWithStatus($ret);
502
 
        }
503
 
 
504
 
        $this->assert(count($gallery->_lockSystem->_releaseQueue) == 1
505
 
                      || !$storage->isTransactional(), 'release first lock');
506
 
 
507
 
        list ($ret, $lockId) = GalleryCoreApi::acquireWriteLock($this->_item->getId());
508
 
        if ($ret) {
509
 
            return $this->failWithStatus($ret);
510
 
        }
511
 
 
512
 
        $this->assert(is_int($lockId), 'lock id is not an integer');
513
 
 
514
 
        /* Real lock moved to new lockId which clears out queued lock */
515
 
        $this->assert(empty($gallery->_lockSystem->_releaseQueue), 'release queue should be empty');
516
 
        $ret = GalleryCoreApi::releaseLocks($lockId);
517
 
        if ($ret) {
518
 
            return $this->failWithStatus($ret);
519
 
        }
520
 
    }
521
 
 
522
 
    function testRelockWritePartial() {
523
 
        /* Write lock, release, then acquire new write lock for one id in previous lock */
524
 
        global $gallery;
525
 
        $storage =& $gallery->getStorage();
526
 
 
527
 
        list ($ret, $lockId) = GalleryCoreApi::acquireWriteLock(array($this->_album->getId(),
528
 
                                                                      $this->_item->getId()));
529
 
        if ($ret) {
530
 
            return $this->failWithStatus($ret);
531
 
        }
532
 
 
533
 
        $ret = GalleryCoreApi::releaseLocks($lockId);
534
 
        if ($ret) {
535
 
            return $this->failWithStatus($ret);
536
 
        }
537
 
 
538
 
        $this->assert((count($gallery->_lockSystem->_releaseQueue) == 1
539
 
                && count($gallery->_lockSystem->_releaseQueue[$lockId]['ids']) == 2)
540
 
            || !$storage->isTransactional(), 'release first lock');
541
 
 
542
 
        list ($ret, $newLockId) = GalleryCoreApi::acquireWriteLock($this->_item->getId());
543
 
        if ($ret) {
544
 
            return $this->failWithStatus($ret);
545
 
        }
546
 
 
547
 
        $this->assert(is_int($newLockId), 'lock id is not an integer');
548
 
 
549
 
        /* One id moved to new lockId */
550
 
        $this->assert((count($gallery->_lockSystem->_releaseQueue) == 1
551
 
                && count($gallery->_lockSystem->_releaseQueue[$lockId]['ids']) == 1)
552
 
            || !$storage->isTransactional(), 'acquire new lock');
553
 
 
554
 
        $ret = GalleryCoreApi::releaseLocks($newLockId);
555
 
        if ($ret) {
556
 
            return $this->failWithStatus($ret);
557
 
        }
558
 
    }
559
 
 
560
 
    function testRelockWriteMore() {
561
 
        /* Write lock, release, then acquire new write lock with more ids than previous lock */
562
 
        global $gallery;
563
 
        $storage =& $gallery->getStorage();
564
 
 
565
 
        list ($ret, $lockId) = GalleryCoreApi::acquireWriteLock($this->_item->getId());
566
 
        if ($ret) {
567
 
            return $this->failWithStatus($ret);
568
 
        }
569
 
 
570
 
        $ret = GalleryCoreApi::releaseLocks($lockId);
571
 
        if ($ret) {
572
 
            return $this->failWithStatus($ret);
573
 
        }
574
 
 
575
 
        $this->assert((count($gallery->_lockSystem->_releaseQueue) == 1
576
 
                && count($gallery->_lockSystem->_releaseQueue[$lockId]['ids']) == 1)
577
 
            || !$storage->isTransactional(), 'release first lock');
578
 
 
579
 
        list ($ret, $lockId) = GalleryCoreApi::acquireWriteLock(array($this->_album->getId(),
580
 
                                                                      $this->_item->getId()));
581
 
        if ($ret) {
582
 
            return $this->failWithStatus($ret);
583
 
        }
584
 
 
585
 
        $this->assert(is_int($lockId), 'lock id is not an integer');
586
 
 
587
 
        /* Real lock moved to new lockId which clears out queued lock */
588
 
        $this->assert(empty($gallery->_lockSystem->_releaseQueue), 'release queue should be empty');
589
 
 
590
 
        $ret = GalleryCoreApi::releaseLocks($lockId);
591
 
        if ($ret) {
592
 
            return $this->failWithStatus($ret);
593
 
        }
594
 
    }
595
 
 
596
 
    function testReadThenWrite() {
597
 
        /* Read lock, release, then acquire write lock before committing transaction */
598
 
        global $gallery;
599
 
        $storage =& $gallery->getStorage();
600
 
 
601
 
        list ($ret, $lockId) = GalleryCoreApi::acquireReadLock($this->_item->getId());
602
 
        if ($ret) {
603
 
            return $this->failWithStatus($ret);
604
 
        }
605
 
 
606
 
        $ret = GalleryCoreApi::releaseLocks($lockId);
607
 
        if ($ret) {
608
 
            return $this->failWithStatus($ret);
609
 
        }
610
 
 
611
 
        $this->assert(count($gallery->_lockSystem->_releaseQueue) == 1
612
 
                      || !$storage->isTransactional(), 'release read lock');
613
 
 
614
 
        list ($ret, $lockId) = GalleryCoreApi::acquireWriteLock($this->_item->getId());
615
 
        if ($ret) {
616
 
            return $this->failWithStatus($ret);
617
 
        }
618
 
 
619
 
        $this->assert(is_int($lockId), 'lock id is not an integer');
620
 
 
621
 
        /* Had to release that read lock in order to get new write lock */
622
 
        $this->assert(empty($gallery->_lockSystem->_releaseQueue), 'release queue should be empty');
623
 
 
624
 
        $ret = GalleryCoreApi::releaseLocks($lockId);
625
 
        if ($ret) {
626
 
            return $this->failWithStatus($ret);
627
 
        }
628
 
    }
629
 
 
630
 
    function testReadThenWritePartial() {
631
 
        /* Read lock, release, then acquire a write lock for one entity in that read lock */
632
 
        global $gallery;
633
 
        $storage =& $gallery->getStorage();
634
 
 
635
 
        list ($ret, $lockId) = GalleryCoreApi::acquireReadLock(array($this->_item->getId(),
636
 
                                                                     $this->_album->getId()));
637
 
        if ($ret) {
638
 
            return $this->failWithStatus($ret);
639
 
        }
640
 
 
641
 
        $ret = GalleryCoreApi::releaseLocks($lockId);
642
 
        if ($ret) {
643
 
            return $this->failWithStatus($ret);
644
 
        }
645
 
 
646
 
        $this->assert((count($gallery->_lockSystem->_releaseQueue) == 1
647
 
                && count($gallery->_lockSystem->_releaseQueue[$lockId]['ids']) == 2)
648
 
            || !$storage->isTransactional(), 'release read lock');
649
 
 
650
 
        list ($ret, $newLockId) = GalleryCoreApi::acquireWriteLock($this->_item->getId());
651
 
        if ($ret) {
652
 
            return $this->failWithStatus($ret);
653
 
        }
654
 
 
655
 
        $this->assert(is_int($newLockId), 'lock id is not an integer');
656
 
 
657
 
        /* Removed single entity from pending read lock in order to get new write lock */
658
 
        $this->assert((count($gallery->_lockSystem->_releaseQueue) == 1
659
 
                && count($gallery->_lockSystem->_releaseQueue[$lockId]['ids']) == 1)
660
 
            || !$storage->isTransactional(), 'pending read lock should have one entity');
661
 
 
662
 
        $ret = GalleryCoreApi::releaseLocks($newLockId);
663
 
        if ($ret) {
664
 
            return $this->failWithStatus($ret);
665
 
        }
666
 
    }
667
 
 
668
 
    function testReadReadAgainThenWrite() {
669
 
        return $this->_tryAllLockSystems('testReadReadAgainThenWrite');
670
 
    }
671
 
 
672
 
    /* Acquire a write lock when item is in multiple locks in the release queue */
673
 
    function _testReadReadAgainThenWrite($lockSystem) {
674
 
        global $gallery;
675
 
        $storage =& $gallery->getStorage();
676
 
 
677
 
        $itemId = $this->_item->getId();
678
 
        list ($ret, $lockId) = GalleryCoreApi::acquireReadLock($itemId);
679
 
        if ($ret) {
680
 
            return $this->failWithStatus($ret);
681
 
        }
682
 
 
683
 
        $ret = GalleryCoreApi::releaseLocks($lockId);
684
 
        if ($ret) {
685
 
            return $this->failWithStatus($ret);
686
 
        }
687
 
 
688
 
        list ($ret, $lockId) = GalleryCoreApi::acquireReadLock($itemId);
689
 
        if ($ret) {
690
 
            return $this->failWithStatus($ret);
691
 
        }
692
 
 
693
 
        $ret = GalleryCoreApi::releaseLocks($lockId);
694
 
        if ($ret) {
695
 
            return $this->failWithStatus($ret);
696
 
        }
697
 
 
698
 
        $this->assert(count($gallery->_lockSystem->_releaseQueue) == 2
699
 
                      || !$storage->isTransactional(), "$lockSystem: release read lock");
700
 
 
701
 
        list ($ret, $lockId) = GalleryCoreApi::acquireWriteLock($itemId);
702
 
        if ($ret) {
703
 
            return $this->failWithStatus($ret);
704
 
        }
705
 
 
706
 
        $this->assert(is_int($lockId), "$lockSystem: lock id is not an integer");
707
 
 
708
 
        /* Had to release that read locks in order to get new write lock */
709
 
        $this->assert(empty($gallery->_lockSystem->_releaseQueue),
710
 
                      "$lockSystem: release queue should be empty");
711
 
 
712
 
        $ret = GalleryCoreApi::releaseLocks($lockId);
713
 
        if ($ret) {
714
 
            return $this->failWithStatus($ret);
715
 
        }
716
 
    }
717
 
}
718
 
?>