New upstream version 2.3.1++
Ondřej Surý
10 months ago
0 | <?xml version="1.0" encoding="UTF-8"?> | |
1 | <package packagerversion="1.9.4" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd"> | |
2 | <name>yac</name> | |
3 | <channel>pecl.php.net</channel> | |
4 | <summary>lockless user data cache</summary> | |
5 | <description>yac is a shared memory user data cache for PHP. it can be used to replace APC or local memcached. | |
6 | ||
7 | yac is lockless, that means, it is very fast, but there could be a chance you will get a wrong data(depends on how many key slots are allocated and how many keys are stored), so you'd better make sure that your product is not very sensitive to that.</description> | |
8 | <lead> | |
9 | <name>Xinchen Hui</name> | |
10 | <user>laruence</user> | |
11 | <email>laruence@php.net</email> | |
12 | <active>yes</active> | |
13 | </lead> | |
14 | <lead> | |
15 | <name>Wei Dai</name> | |
16 | <user>Demon</user> | |
17 | <email>zxcvdavid@gmail.com</email> | |
18 | <active>yes</active> | |
19 | </lead> | |
20 | <date>2014-10-22</date> | |
21 | <time>14:03:48</time> | |
22 | <version> | |
23 | <release>0.9.2</release> | |
24 | <api>0.9.2</api> | |
25 | </version> | |
26 | <stability> | |
27 | <release>beta</release> | |
28 | <api>beta</api> | |
29 | </stability> | |
30 | <license uri="http://www.php.net/license">PHP</license> | |
31 | <notes> | |
32 | - Add --with-system-fastlz option | |
33 | </notes> | |
34 | <contents> | |
35 | <dir name="/"> | |
36 | <file md5sum="4e7edfc9fadfe1c6b97f21d9c8f416f0" name="storage/allocator/allocators/createfilemapping.c" role="src" /> | |
37 | <file md5sum="ee1c48e027892678bab8ec40c1efd7c5" name="storage/allocator/allocators/mmap.c" role="src" /> | |
38 | <file md5sum="d719e0643e649a89ad307ee41b82e0fd" name="storage/allocator/allocators/shm.c" role="src" /> | |
39 | <file md5sum="3874d9d9784c77ec4e3acd1cd0027f1f" name="storage/allocator/allocators/posix.c" role="src" /> | |
40 | <file md5sum="9594fb0a459719d3f9b354ee7105330f" name="storage/allocator/allocators/win32.c" role="src" /> | |
41 | <file md5sum="5aa4302988e0a26b7673741de836a4d2" name="storage/allocator/yac_allocator.h" role="src" /> | |
42 | <file md5sum="a550a7e1b7e8e888400133e6b4179a9b" name="storage/allocator/yac_allocator.c" role="src" /> | |
43 | <file md5sum="6a45b887b874e2341f0d4123016d2a50" name="storage/yac_storage.h" role="src" /> | |
44 | <file md5sum="e2c10004be49e913180b28d25e006b7b" name="storage/yac_storage.c" role="src" /> | |
45 | <file md5sum="543b3b1b8571c4b9c02eafee4a6f3fa3" name="compressor/fastlz/LICENSE" role="doc" /> | |
46 | <file md5sum="fa4d2340c50946340603066b02f7e6dd" name="compressor/fastlz/README.TXT" role="doc" /> | |
47 | <file md5sum="d49275e3dcc1d23d6ce0041648be8e14" name="compressor/fastlz/fastlz.h" role="src" /> | |
48 | <file md5sum="89384a08695fc238e9fbc41b0a14b5a7" name="compressor/fastlz/fastlz.c" role="src" /> | |
49 | <file md5sum="ad8dd340dfb67d0bd65a2ec608a49c1d" name="serializer/yac_serializer.h" role="src" /> | |
50 | <file md5sum="15fc773312442c45e1eb64bbb7efea63" name="serializer/php.c" role="src" /> | |
51 | <file md5sum="bcf581d9110dbe9caf28bfe6b70f9d90" name="serializer/msgpack.c" role="src" /> | |
52 | <file md5sum="4ff407df4fb138f1fdefa97a72e4769f" name="tests/001.phpt" role="test" /> | |
53 | <file md5sum="ad4a91d346d21c285ab21b4befcb538e" name="tests/002.phpt" role="test" /> | |
54 | <file md5sum="59f0d14be6b86915ded044110b9148da" name="tests/003.phpt" role="test" /> | |
55 | <file md5sum="69b6eab19f3e907097fd41ec6dfc024a" name="tests/004.phpt" role="test" /> | |
56 | <file md5sum="bf0340a9a20b5fe5dc300f3ec907a2dc" name="tests/005.phpt" role="test" /> | |
57 | <file md5sum="44354a5ac454a1bce3b00d8f5f9d6c4c" name="tests/006.phpt" role="test" /> | |
58 | <file md5sum="10ec3265916ceaeb4cdd56efce701eb0" name="tests/007.phpt" role="test" /> | |
59 | <file md5sum="f567e7205b3eb0ea757cb09dcd55cc7e" name="tests/008.phpt" role="test" /> | |
60 | <file md5sum="c9000c4ff1b00520cfb14c0e45508b30" name="tests/009.phpt" role="test" /> | |
61 | <file md5sum="1bf41dadf4a96d8730d37d89fb8257a6" name="tests/010.phpt" role="test" /> | |
62 | <file md5sum="0f47511cd434d57d01f78ad8a65a13cb" name="tests/011.phpt" role="test" /> | |
63 | <file md5sum="4c3a616f6563f090ccf781ed6a4671af" name="tests/012.phpt" role="test" /> | |
64 | <file md5sum="717d306b5ea2e5ae1aaef6894c3aaf2a" name="tests/013.phpt" role="test" /> | |
65 | <file md5sum="56f31a4a48c4d28a14e3939ce87abdb3" name="tests/014.phpt" role="test" /> | |
66 | <file md5sum="88ff06bab70e76cc0aa6e79aa4ee7e21" name="tests/015.phpt" role="test" /> | |
67 | <file md5sum="4c4242640be3dfdccf4b46600dbe3682" name="tests/issue012.phpt" role="test" /> | |
68 | <file md5sum="ac36c858a802d2d8c791b4de479adb59" name="config.w32" role="src" /> | |
69 | <file md5sum="dd34a70236f008af999de817b93a5e3a" name="LICENSE" role="doc" /> | |
70 | <file md5sum="a3392e4d97b0d057a57453dbbad0313d" name="CREDITS" role="doc" /> | |
71 | <file md5sum="43345d5aee118e3bbc9427e5b0abbef9" name="config.m4" role="src" /> | |
72 | <file md5sum="32570599c961b469ee64b816231b58b9" name="yac.c" role="src" /> | |
73 | <file md5sum="0cafee01376ba581bf522a7764263bcd" name="php_yac.h" role="src" /> | |
74 | </dir> | |
75 | </contents> | |
76 | <dependencies> | |
77 | <required> | |
78 | <php> | |
79 | <min>5.2.0</min> | |
80 | </php> | |
81 | <pearinstaller> | |
82 | <min>1.4.0</min> | |
83 | </pearinstaller> | |
84 | </required> | |
85 | </dependencies> | |
86 | <providesextension>yac</providesextension> | |
87 | <extsrcrelease /> | |
88 | <changelog> | |
89 | <release> | |
90 | <date>2014-10-22</date> | |
91 | <version> | |
92 | <release>0.9.2</release> | |
93 | <api>0.9.2</api> | |
94 | </version> | |
95 | <stability> | |
96 | <release>beta</release> | |
97 | <api>beta</api> | |
98 | </stability> | |
99 | <license uri="http://www.php.net/license">PHP License</license> | |
100 | <notes> | |
101 | - Add --with-system-fastlz option | |
102 | </notes> | |
103 | </release> | |
104 | <release> | |
105 | <date>2014-07-25</date> | |
106 | <version> | |
107 | <release>0.9.1</release> | |
108 | <api>0.9.1</api> | |
109 | </version> | |
110 | <stability> | |
111 | <release>beta</release> | |
112 | <api>beta</api> | |
113 | </stability> | |
114 | <license uri="http://www.php.net/license">PHP License</license> | |
115 | <notes> | |
116 | - Try to fix windows build | |
117 | </notes> | |
118 | </release> | |
119 | <release> | |
120 | <date>2014-07-24</date> | |
121 | <version> | |
122 | <release>0.9.0</release> | |
123 | <api>0.9.0</api> | |
124 | </version> | |
125 | <stability> | |
126 | <release>beta</release> | |
127 | <api>beta</api> | |
128 | </stability> | |
129 | <license uri="http://www.php.net/license">PHP License</license> | |
130 | <notes> | |
131 | - first release | |
132 | </notes> | |
133 | </release> | |
134 | </changelog> | |
135 | </package> |
0 | -------------------------------------------------------------------- | |
1 | The PHP License, version 3.01 | |
2 | Copyright (c) 1999 - 2011 The PHP Group. All rights reserved. | |
3 | -------------------------------------------------------------------- | |
4 | ||
5 | Redistribution and use in source and binary forms, with or without | |
6 | modification, is permitted provided that the following conditions | |
7 | are met: | |
8 | ||
9 | 1. Redistributions of source code must retain the above copyright | |
10 | notice, this list of conditions and the following disclaimer. | |
11 | ||
12 | 2. Redistributions in binary form must reproduce the above copyright | |
13 | notice, this list of conditions and the following disclaimer in | |
14 | the documentation and/or other materials provided with the | |
15 | distribution. | |
16 | ||
17 | 3. The name "PHP" must not be used to endorse or promote products | |
18 | derived from this software without prior written permission. For | |
19 | written permission, please contact group@php.net. | |
20 | ||
21 | 4. Products derived from this software may not be called "PHP", nor | |
22 | may "PHP" appear in their name, without prior written permission | |
23 | from group@php.net. You may indicate that your software works in | |
24 | conjunction with PHP by saying "Foo for PHP" instead of calling | |
25 | it "PHP Foo" or "phpfoo" | |
26 | ||
27 | 5. The PHP Group may publish revised and/or new versions of the | |
28 | license from time to time. Each version will be given a | |
29 | distinguishing version number. | |
30 | Once covered code has been published under a particular version | |
31 | of the license, you may always continue to use it under the terms | |
32 | of that version. You may also choose to use such covered code | |
33 | under the terms of any subsequent version of the license | |
34 | published by the PHP Group. No one other than the PHP Group has | |
35 | the right to modify the terms applicable to covered code created | |
36 | under this License. | |
37 | ||
38 | 6. Redistributions of any form whatsoever must retain the following | |
39 | acknowledgment: | |
40 | "This product includes PHP software, freely available from | |
41 | <http://www.php.net/software/>". | |
42 | ||
43 | THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND | |
44 | ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | |
45 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | |
46 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP | |
47 | DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | |
48 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
49 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
50 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
51 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
52 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
53 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |
54 | OF THE POSSIBILITY OF SUCH DAMAGE. | |
55 | ||
56 | -------------------------------------------------------------------- | |
57 | ||
58 | This software consists of voluntary contributions made by many | |
59 | individuals on behalf of the PHP Group. | |
60 | ||
61 | The PHP Group can be contacted via Email at group@php.net. | |
62 | ||
63 | For more information on the PHP Group and the PHP project, | |
64 | please see <http://www.php.net>. | |
65 | ||
66 | PHP includes the Zend Engine, freely available at | |
67 | <http://www.zend.com>. |
0 | FastLZ - lightning-fast lossless compression library | |
1 | ||
2 | Copyright (C) 2007 Ariya Hidayat (ariya@kde.org) | |
3 | Copyright (C) 2006 Ariya Hidayat (ariya@kde.org) | |
4 | Copyright (C) 2005 Ariya Hidayat (ariya@kde.org) | |
5 | ||
6 | Permission is hereby granted, free of charge, to any person obtaining a copy | |
7 | of this software and associated documentation files (the "Software"), to deal | |
8 | in the Software without restriction, including without limitation the rights | |
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
10 | copies of the Software, and to permit persons to whom the Software is | |
11 | furnished to do so, subject to the following conditions: | |
12 | ||
13 | The above copyright notice and this permission notice shall be included in | |
14 | all copies or substantial portions of the Software. | |
15 | ||
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
22 | THE SOFTWARE. | |
23 |
0 | FastLZ - lightning-fast lossless compression library | |
1 | ||
2 | Author: Ariya Hidayat | |
3 | Official website: http://www.fastlz.org | |
4 | ||
5 | FastLZ is distributed using the MIT license, see file LICENSE | |
6 | for details. | |
7 | ||
8 | FastLZ consists of two files: fastlz.h and fastlz.c. Just add these | |
9 | files to your project in order to use FastLZ. For information on | |
10 | compression and decompression routines, see fastlz.h. | |
11 | ||
12 | A simple file compressor called 6pack is included as an example | |
13 | on how to use FastLZ. The corresponding decompressor is 6unpack. | |
14 | ||
15 | To compile using GCC: | |
16 | ||
17 | gcc -o 6pack 6pack.c fastlz.c | |
18 | gcc -o 6unpack 6unpack.c fastlz.c | |
19 | ||
20 | To compile using MinGW: | |
21 | ||
22 | mingw32-gcc -o 6pack 6pack.c fastlz.c | |
23 | mingw32-gcc -o 6unpack 6unpack.c fastlz.c | |
24 | ||
25 | To compile using Microsoft Visual C++: | |
26 | ||
27 | cl 6pack.c fastlz.c | |
28 | cl 6unpack.c fastlz.c | |
29 | ||
30 | To compile using Borland C++: | |
31 | ||
32 | bcc32 6pack.c fastlz.c | |
33 | bcc32 6unpack.c fastlz.c | |
34 | ||
35 | To compile using OpenWatcom C/C++: | |
36 | ||
37 | cl386 6pack.c fastlz.c | |
38 | cl386 6unpack.c fastlz.c | |
39 | ||
40 | To compile using Intel C++ compiler for Windows: | |
41 | ||
42 | icl 6pack.c fastlz.c | |
43 | icl 6unpack.c fastlz.c | |
44 | ||
45 | To compile using Intel C++ compiler for Linux: | |
46 | ||
47 | icc -o 6pack 6pack.c fastlz.c | |
48 | icc -o 6unpack 6unpack.c fastlz.c | |
49 | ||
50 | To compile 6pack using LCC-Win32: | |
51 | ||
52 | lc 6pack.c fastlz.c | |
53 | lc 6unpack.c fastlz.c | |
54 | ||
55 | To compile 6pack using Pelles C: | |
56 | ||
57 | pocc 6pack.c | |
58 | pocc 6unpack.c | |
59 | pocc fastlz.c | |
60 | polink 6pack.obj fastlz.obj | |
61 | polink 6unpack.obj fastlz.obj | |
62 | ||
63 | For speed optimization, always use proper compile flags for optimization options. | |
64 | Typical compiler flags are given below: | |
65 | ||
66 | * GCC (pre 4.2): -march=pentium -O3 -fomit-frame-pointer -mtune=pentium | |
67 | * GCC 4.2 or later: -march=pentium -O3 -fomit-frame-pointer -mtune=generic | |
68 | * Digital Mars C/C++: -o+all -5 | |
69 | * Intel C++ (Windows): /O3 /Qipo | |
70 | * Intel C++ (Linux): -O2 -march=pentium -mtune=pentium | |
71 | * Borland C++: -O2 -5 | |
72 | * LCC-Win32: -O | |
73 | * Pelles C: /O2 | |
74 |
0 | /* | |
1 | FastLZ - lightning-fast lossless compression library | |
2 | ||
3 | Copyright (C) 2007 Ariya Hidayat (ariya@kde.org) | |
4 | Copyright (C) 2006 Ariya Hidayat (ariya@kde.org) | |
5 | Copyright (C) 2005 Ariya Hidayat (ariya@kde.org) | |
6 | ||
7 | Permission is hereby granted, free of charge, to any person obtaining a copy | |
8 | of this software and associated documentation files (the "Software"), to deal | |
9 | in the Software without restriction, including without limitation the rights | |
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
11 | copies of the Software, and to permit persons to whom the Software is | |
12 | furnished to do so, subject to the following conditions: | |
13 | ||
14 | The above copyright notice and this permission notice shall be included in | |
15 | all copies or substantial portions of the Software. | |
16 | ||
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
23 | THE SOFTWARE. | |
24 | */ | |
25 | ||
26 | #if !defined(FASTLZ__COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) | |
27 | ||
28 | /* | |
29 | * Always check for bound when decompressing. | |
30 | * Generally it is best to leave it defined. | |
31 | */ | |
32 | #define FASTLZ_SAFE | |
33 | ||
34 | /* | |
35 | * Give hints to the compiler for branch prediction optimization. | |
36 | */ | |
37 | #if defined(__GNUC__) && (__GNUC__ > 2) | |
38 | #define FASTLZ_EXPECT_CONDITIONAL(c) (__builtin_expect((c), 1)) | |
39 | #define FASTLZ_UNEXPECT_CONDITIONAL(c) (__builtin_expect((c), 0)) | |
40 | #else | |
41 | #define FASTLZ_EXPECT_CONDITIONAL(c) (c) | |
42 | #define FASTLZ_UNEXPECT_CONDITIONAL(c) (c) | |
43 | #endif | |
44 | ||
45 | /* | |
46 | * Use inlined functions for supported systems. | |
47 | */ | |
48 | #if defined(__GNUC__) || defined(__DMC__) || defined(__POCC__) || defined(__WATCOMC__) || defined(__SUNPRO_C) | |
49 | #define FASTLZ_INLINE inline | |
50 | #elif defined(__BORLANDC__) || defined(_MSC_VER) || defined(__LCC__) | |
51 | #define FASTLZ_INLINE __inline | |
52 | #else | |
53 | #define FASTLZ_INLINE | |
54 | #endif | |
55 | ||
56 | /* | |
57 | * Prevent accessing more than 8-bit at once, except on x86 architectures. | |
58 | */ | |
59 | #if !defined(FASTLZ_STRICT_ALIGN) | |
60 | #define FASTLZ_STRICT_ALIGN | |
61 | #if defined(__i386__) || defined(__386) /* GNU C, Sun Studio */ | |
62 | #undef FASTLZ_STRICT_ALIGN | |
63 | #elif defined(__i486__) || defined(__i586__) || defined(__i686__) /* GNU C */ | |
64 | #undef FASTLZ_STRICT_ALIGN | |
65 | #elif defined(_M_IX86) /* Intel, MSVC */ | |
66 | #undef FASTLZ_STRICT_ALIGN | |
67 | #elif defined(__386) | |
68 | #undef FASTLZ_STRICT_ALIGN | |
69 | #elif defined(_X86_) /* MinGW */ | |
70 | #undef FASTLZ_STRICT_ALIGN | |
71 | #elif defined(__I86__) /* Digital Mars */ | |
72 | #undef FASTLZ_STRICT_ALIGN | |
73 | #endif | |
74 | #endif | |
75 | ||
76 | /* | |
77 | * FIXME: use preprocessor magic to set this on different platforms! | |
78 | */ | |
79 | typedef unsigned char flzuint8; | |
80 | typedef unsigned short flzuint16; | |
81 | typedef unsigned int flzuint32; | |
82 | ||
83 | /* prototypes */ | |
84 | int fastlz_compress(const void* input, int length, void* output); | |
85 | int fastlz_compress_level(int level, const void* input, int length, void* output); | |
86 | int fastlz_decompress(const void* input, int length, void* output, int maxout); | |
87 | ||
88 | #define MAX_COPY 32 | |
89 | #define MAX_LEN 264 /* 256 + 8 */ | |
90 | #define MAX_DISTANCE 8192 | |
91 | ||
92 | #if !defined(FASTLZ_STRICT_ALIGN) | |
93 | #define FASTLZ_READU16(p) *((const flzuint16*)(p)) | |
94 | #else | |
95 | #define FASTLZ_READU16(p) ((p)[0] | (p)[1]<<8) | |
96 | #endif | |
97 | ||
98 | #define HASH_LOG 13 | |
99 | #define HASH_SIZE (1<< HASH_LOG) | |
100 | #define HASH_MASK (HASH_SIZE-1) | |
101 | #define HASH_FUNCTION(v,p) { v = FASTLZ_READU16(p); v ^= FASTLZ_READU16(p+1)^(v>>(16-HASH_LOG));v &= HASH_MASK; } | |
102 | ||
103 | #undef FASTLZ_LEVEL | |
104 | #define FASTLZ_LEVEL 1 | |
105 | ||
106 | #undef FASTLZ_COMPRESSOR | |
107 | #undef FASTLZ_DECOMPRESSOR | |
108 | #define FASTLZ_COMPRESSOR fastlz1_compress | |
109 | #define FASTLZ_DECOMPRESSOR fastlz1_decompress | |
110 | static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output); | |
111 | static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout); | |
112 | #include "fastlz.c" | |
113 | ||
114 | #undef FASTLZ_LEVEL | |
115 | #define FASTLZ_LEVEL 2 | |
116 | ||
117 | #undef MAX_DISTANCE | |
118 | #define MAX_DISTANCE 8191 | |
119 | #define MAX_FARDISTANCE (65535+MAX_DISTANCE-1) | |
120 | ||
121 | #undef FASTLZ_COMPRESSOR | |
122 | #undef FASTLZ_DECOMPRESSOR | |
123 | #define FASTLZ_COMPRESSOR fastlz2_compress | |
124 | #define FASTLZ_DECOMPRESSOR fastlz2_decompress | |
125 | static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output); | |
126 | static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout); | |
127 | #include "fastlz.c" | |
128 | ||
129 | int fastlz_compress(const void* input, int length, void* output) | |
130 | { | |
131 | /* for short block, choose fastlz1 */ | |
132 | if(length < 65536) | |
133 | return fastlz1_compress(input, length, output); | |
134 | ||
135 | /* else... */ | |
136 | return fastlz2_compress(input, length, output); | |
137 | } | |
138 | ||
139 | int fastlz_decompress(const void* input, int length, void* output, int maxout) | |
140 | { | |
141 | /* magic identifier for compression level */ | |
142 | int level = ((*(const flzuint8*)input) >> 5) + 1; | |
143 | ||
144 | if(level == 1) | |
145 | return fastlz1_decompress(input, length, output, maxout); | |
146 | if(level == 2) | |
147 | return fastlz2_decompress(input, length, output, maxout); | |
148 | ||
149 | /* unknown level, trigger error */ | |
150 | return 0; | |
151 | } | |
152 | ||
153 | int fastlz_compress_level(int level, const void* input, int length, void* output) | |
154 | { | |
155 | if(level == 1) | |
156 | return fastlz1_compress(input, length, output); | |
157 | if(level == 2) | |
158 | return fastlz2_compress(input, length, output); | |
159 | ||
160 | return 0; | |
161 | } | |
162 | ||
163 | #else /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */ | |
164 | ||
165 | static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output) | |
166 | { | |
167 | const flzuint8* ip = (const flzuint8*) input; | |
168 | const flzuint8* ip_bound = ip + length - 2; | |
169 | const flzuint8* ip_limit = ip + length - 12; | |
170 | flzuint8* op = (flzuint8*) output; | |
171 | ||
172 | const flzuint8* htab[HASH_SIZE]; | |
173 | const flzuint8** hslot; | |
174 | flzuint32 hval; | |
175 | ||
176 | flzuint32 copy; | |
177 | ||
178 | /* sanity check */ | |
179 | if(FASTLZ_UNEXPECT_CONDITIONAL(length < 4)) | |
180 | { | |
181 | if(length) | |
182 | { | |
183 | /* create literal copy only */ | |
184 | *op++ = length-1; | |
185 | ip_bound++; | |
186 | while(ip <= ip_bound) | |
187 | *op++ = *ip++; | |
188 | return length+1; | |
189 | } | |
190 | else | |
191 | return 0; | |
192 | } | |
193 | ||
194 | /* initializes hash table */ | |
195 | for (hslot = htab; hslot < htab + HASH_SIZE; hslot++) | |
196 | *hslot = ip; | |
197 | ||
198 | /* we start with literal copy */ | |
199 | copy = 2; | |
200 | *op++ = MAX_COPY-1; | |
201 | *op++ = *ip++; | |
202 | *op++ = *ip++; | |
203 | ||
204 | /* main loop */ | |
205 | while(FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit)) | |
206 | { | |
207 | const flzuint8* ref; | |
208 | flzuint32 distance; | |
209 | ||
210 | /* minimum match length */ | |
211 | flzuint32 len = 3; | |
212 | ||
213 | /* comparison starting-point */ | |
214 | const flzuint8* anchor = ip; | |
215 | ||
216 | /* check for a run */ | |
217 | #if FASTLZ_LEVEL==2 | |
218 | if(ip[0] == ip[-1] && FASTLZ_READU16(ip-1)==FASTLZ_READU16(ip+1)) | |
219 | { | |
220 | distance = 1; | |
221 | ip += 3; | |
222 | ref = anchor - 1 + 3; | |
223 | goto match; | |
224 | } | |
225 | #endif | |
226 | ||
227 | /* find potential match */ | |
228 | HASH_FUNCTION(hval,ip); | |
229 | hslot = htab + hval; | |
230 | ref = htab[hval]; | |
231 | ||
232 | /* calculate distance to the match */ | |
233 | distance = anchor - ref; | |
234 | ||
235 | /* update hash table */ | |
236 | *hslot = anchor; | |
237 | ||
238 | /* is this a match? check the first 3 bytes */ | |
239 | if(distance==0 || | |
240 | #if FASTLZ_LEVEL==1 | |
241 | (distance >= MAX_DISTANCE) || | |
242 | #else | |
243 | (distance >= MAX_FARDISTANCE) || | |
244 | #endif | |
245 | *ref++ != *ip++ || *ref++!=*ip++ || *ref++!=*ip++) | |
246 | goto literal; | |
247 | ||
248 | #if FASTLZ_LEVEL==2 | |
249 | /* far, needs at least 5-byte match */ | |
250 | if(distance >= MAX_DISTANCE) | |
251 | { | |
252 | if(*ip++ != *ref++ || *ip++!= *ref++) | |
253 | goto literal; | |
254 | len += 2; | |
255 | } | |
256 | ||
257 | match: | |
258 | #endif | |
259 | ||
260 | /* last matched byte */ | |
261 | ip = anchor + len; | |
262 | ||
263 | /* distance is biased */ | |
264 | distance--; | |
265 | ||
266 | if(!distance) | |
267 | { | |
268 | /* zero distance means a run */ | |
269 | flzuint8 x = ip[-1]; | |
270 | while(ip < ip_bound) | |
271 | if(*ref++ != x) break; else ip++; | |
272 | } | |
273 | else | |
274 | for(;;) | |
275 | { | |
276 | /* safe because the outer check against ip limit */ | |
277 | if(*ref++ != *ip++) break; | |
278 | if(*ref++ != *ip++) break; | |
279 | if(*ref++ != *ip++) break; | |
280 | if(*ref++ != *ip++) break; | |
281 | if(*ref++ != *ip++) break; | |
282 | if(*ref++ != *ip++) break; | |
283 | if(*ref++ != *ip++) break; | |
284 | if(*ref++ != *ip++) break; | |
285 | while(ip < ip_bound) | |
286 | if(*ref++ != *ip++) break; | |
287 | break; | |
288 | } | |
289 | ||
290 | /* if we have copied something, adjust the copy count */ | |
291 | if(copy) | |
292 | /* copy is biased, '0' means 1 byte copy */ | |
293 | *(op-copy-1) = copy-1; | |
294 | else | |
295 | /* back, to overwrite the copy count */ | |
296 | op--; | |
297 | ||
298 | /* reset literal counter */ | |
299 | copy = 0; | |
300 | ||
301 | /* length is biased, '1' means a match of 3 bytes */ | |
302 | ip -= 3; | |
303 | len = ip - anchor; | |
304 | ||
305 | /* encode the match */ | |
306 | #if FASTLZ_LEVEL==2 | |
307 | if(distance < MAX_DISTANCE) | |
308 | { | |
309 | if(len < 7) | |
310 | { | |
311 | *op++ = (len << 5) + (distance >> 8); | |
312 | *op++ = (distance & 255); | |
313 | } | |
314 | else | |
315 | { | |
316 | *op++ = (7 << 5) + (distance >> 8); | |
317 | for(len-=7; len >= 255; len-= 255) | |
318 | *op++ = 255; | |
319 | *op++ = len; | |
320 | *op++ = (distance & 255); | |
321 | } | |
322 | } | |
323 | else | |
324 | { | |
325 | /* far away, but not yet in the another galaxy... */ | |
326 | if(len < 7) | |
327 | { | |
328 | distance -= MAX_DISTANCE; | |
329 | *op++ = (len << 5) + 31; | |
330 | *op++ = 255; | |
331 | *op++ = distance >> 8; | |
332 | *op++ = distance & 255; | |
333 | } | |
334 | else | |
335 | { | |
336 | distance -= MAX_DISTANCE; | |
337 | *op++ = (7 << 5) + 31; | |
338 | for(len-=7; len >= 255; len-= 255) | |
339 | *op++ = 255; | |
340 | *op++ = len; | |
341 | *op++ = 255; | |
342 | *op++ = distance >> 8; | |
343 | *op++ = distance & 255; | |
344 | } | |
345 | } | |
346 | #else | |
347 | ||
348 | if(FASTLZ_UNEXPECT_CONDITIONAL(len > MAX_LEN-2)) | |
349 | while(len > MAX_LEN-2) | |
350 | { | |
351 | *op++ = (7 << 5) + (distance >> 8); | |
352 | *op++ = MAX_LEN - 2 - 7 -2; | |
353 | *op++ = (distance & 255); | |
354 | len -= MAX_LEN-2; | |
355 | } | |
356 | ||
357 | if(len < 7) | |
358 | { | |
359 | *op++ = (len << 5) + (distance >> 8); | |
360 | *op++ = (distance & 255); | |
361 | } | |
362 | else | |
363 | { | |
364 | *op++ = (7 << 5) + (distance >> 8); | |
365 | *op++ = len - 7; | |
366 | *op++ = (distance & 255); | |
367 | } | |
368 | #endif | |
369 | ||
370 | /* update the hash at match boundary */ | |
371 | HASH_FUNCTION(hval,ip); | |
372 | htab[hval] = ip++; | |
373 | HASH_FUNCTION(hval,ip); | |
374 | htab[hval] = ip++; | |
375 | ||
376 | /* assuming literal copy */ | |
377 | *op++ = MAX_COPY-1; | |
378 | ||
379 | continue; | |
380 | ||
381 | literal: | |
382 | *op++ = *anchor++; | |
383 | ip = anchor; | |
384 | copy++; | |
385 | if(FASTLZ_UNEXPECT_CONDITIONAL(copy == MAX_COPY)) | |
386 | { | |
387 | copy = 0; | |
388 | *op++ = MAX_COPY-1; | |
389 | } | |
390 | } | |
391 | ||
392 | /* left-over as literal copy */ | |
393 | ip_bound++; | |
394 | while(ip <= ip_bound) | |
395 | { | |
396 | *op++ = *ip++; | |
397 | copy++; | |
398 | if(copy == MAX_COPY) | |
399 | { | |
400 | copy = 0; | |
401 | *op++ = MAX_COPY-1; | |
402 | } | |
403 | } | |
404 | ||
405 | /* if we have copied something, adjust the copy length */ | |
406 | if(copy) | |
407 | *(op-copy-1) = copy-1; | |
408 | else | |
409 | op--; | |
410 | ||
411 | #if FASTLZ_LEVEL==2 | |
412 | /* marker for fastlz2 */ | |
413 | *(flzuint8*)output |= (1 << 5); | |
414 | #endif | |
415 | ||
416 | return op - (flzuint8*)output; | |
417 | } | |
418 | ||
419 | static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout) | |
420 | { | |
421 | const flzuint8* ip = (const flzuint8*) input; | |
422 | const flzuint8* ip_limit = ip + length; | |
423 | flzuint8* op = (flzuint8*) output; | |
424 | flzuint8* op_limit = op + maxout; | |
425 | flzuint32 ctrl = (*ip++) & 31; | |
426 | int loop = 1; | |
427 | ||
428 | do | |
429 | { | |
430 | const flzuint8* ref = op; | |
431 | flzuint32 len = ctrl >> 5; | |
432 | flzuint32 ofs = (ctrl & 31) << 8; | |
433 | ||
434 | if(ctrl >= 32) | |
435 | { | |
436 | #if FASTLZ_LEVEL==2 | |
437 | flzuint8 code; | |
438 | #endif | |
439 | len--; | |
440 | ref -= ofs; | |
441 | if (len == 7-1) | |
442 | #if FASTLZ_LEVEL==1 | |
443 | len += *ip++; | |
444 | ref -= *ip++; | |
445 | #else | |
446 | do | |
447 | { | |
448 | code = *ip++; | |
449 | len += code; | |
450 | } while (code==255); | |
451 | code = *ip++; | |
452 | ref -= code; | |
453 | ||
454 | /* match from 16-bit distance */ | |
455 | if(FASTLZ_UNEXPECT_CONDITIONAL(code==255)) | |
456 | if(FASTLZ_EXPECT_CONDITIONAL(ofs==(31 << 8))) | |
457 | { | |
458 | ofs = (*ip++) << 8; | |
459 | ofs += *ip++; | |
460 | ref = op - ofs - MAX_DISTANCE; | |
461 | } | |
462 | #endif | |
463 | ||
464 | #ifdef FASTLZ_SAFE | |
465 | if (FASTLZ_UNEXPECT_CONDITIONAL(op + len + 3 > op_limit)) | |
466 | return 0; | |
467 | ||
468 | if (FASTLZ_UNEXPECT_CONDITIONAL(ref-1 < (flzuint8 *)output)) | |
469 | return 0; | |
470 | #endif | |
471 | ||
472 | if(FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit)) | |
473 | ctrl = *ip++; | |
474 | else | |
475 | loop = 0; | |
476 | ||
477 | if(ref == op) | |
478 | { | |
479 | /* optimize copy for a run */ | |
480 | flzuint8 b = ref[-1]; | |
481 | *op++ = b; | |
482 | *op++ = b; | |
483 | *op++ = b; | |
484 | for(; len; --len) | |
485 | *op++ = b; | |
486 | } | |
487 | else | |
488 | { | |
489 | #if !defined(FASTLZ_STRICT_ALIGN) | |
490 | const flzuint16* p; | |
491 | flzuint16* q; | |
492 | #endif | |
493 | /* copy from reference */ | |
494 | ref--; | |
495 | *op++ = *ref++; | |
496 | *op++ = *ref++; | |
497 | *op++ = *ref++; | |
498 | ||
499 | #if !defined(FASTLZ_STRICT_ALIGN) | |
500 | /* copy a byte, so that now it's word aligned */ | |
501 | if(len & 1) | |
502 | { | |
503 | *op++ = *ref++; | |
504 | len--; | |
505 | } | |
506 | ||
507 | /* copy 16-bit at once */ | |
508 | q = (flzuint16*) op; | |
509 | op += len; | |
510 | p = (const flzuint16*) ref; | |
511 | for(len>>=1; len > 4; len-=4) | |
512 | { | |
513 | *q++ = *p++; | |
514 | *q++ = *p++; | |
515 | *q++ = *p++; | |
516 | *q++ = *p++; | |
517 | } | |
518 | for(; len; --len) | |
519 | *q++ = *p++; | |
520 | #else | |
521 | for(; len; --len) | |
522 | *op++ = *ref++; | |
523 | #endif | |
524 | } | |
525 | } | |
526 | else | |
527 | { | |
528 | ctrl++; | |
529 | #ifdef FASTLZ_SAFE | |
530 | if (FASTLZ_UNEXPECT_CONDITIONAL(op + ctrl > op_limit)) | |
531 | return 0; | |
532 | if (FASTLZ_UNEXPECT_CONDITIONAL(ip + ctrl > ip_limit)) | |
533 | return 0; | |
534 | #endif | |
535 | ||
536 | *op++ = *ip++; | |
537 | for(--ctrl; ctrl; ctrl--) | |
538 | *op++ = *ip++; | |
539 | ||
540 | loop = FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit); | |
541 | if(loop) | |
542 | ctrl = *ip++; | |
543 | } | |
544 | } | |
545 | while(FASTLZ_EXPECT_CONDITIONAL(loop)); | |
546 | ||
547 | return op - (flzuint8*)output; | |
548 | } | |
549 | ||
550 | #endif /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */ |
0 | /* | |
1 | FastLZ - lightning-fast lossless compression library | |
2 | ||
3 | Copyright (C) 2007 Ariya Hidayat (ariya@kde.org) | |
4 | Copyright (C) 2006 Ariya Hidayat (ariya@kde.org) | |
5 | Copyright (C) 2005 Ariya Hidayat (ariya@kde.org) | |
6 | ||
7 | Permission is hereby granted, free of charge, to any person obtaining a copy | |
8 | of this software and associated documentation files (the "Software"), to deal | |
9 | in the Software without restriction, including without limitation the rights | |
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
11 | copies of the Software, and to permit persons to whom the Software is | |
12 | furnished to do so, subject to the following conditions: | |
13 | ||
14 | The above copyright notice and this permission notice shall be included in | |
15 | all copies or substantial portions of the Software. | |
16 | ||
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
23 | THE SOFTWARE. | |
24 | */ | |
25 | ||
26 | #ifndef FASTLZ_H | |
27 | #define FASTLZ_H | |
28 | ||
29 | #define FASTLZ_VERSION 0x000100 | |
30 | ||
31 | #define FASTLZ_VERSION_MAJOR 0 | |
32 | #define FASTLZ_VERSION_MINOR 0 | |
33 | #define FASTLZ_VERSION_REVISION 0 | |
34 | ||
35 | #define FASTLZ_VERSION_STRING "0.1.0" | |
36 | ||
37 | #if defined (__cplusplus) | |
38 | extern "C" { | |
39 | #endif | |
40 | ||
41 | /** | |
42 | Compress a block of data in the input buffer and returns the size of | |
43 | compressed block. The size of input buffer is specified by length. The | |
44 | minimum input buffer size is 16. | |
45 | ||
46 | The output buffer must be at least 5% larger than the input buffer | |
47 | and can not be smaller than 66 bytes. | |
48 | ||
49 | If the input is not compressible, the return value might be larger than | |
50 | length (input buffer size). | |
51 | ||
52 | The input buffer and the output buffer can not overlap. | |
53 | */ | |
54 | ||
55 | int fastlz_compress(const void* input, int length, void* output); | |
56 | ||
57 | /** | |
58 | Decompress a block of compressed data and returns the size of the | |
59 | decompressed block. If error occurs, e.g. the compressed data is | |
60 | corrupted or the output buffer is not large enough, then 0 (zero) | |
61 | will be returned instead. | |
62 | ||
63 | The input buffer and the output buffer can not overlap. | |
64 | ||
65 | Decompression is memory safe and guaranteed not to write the output buffer | |
66 | more than what is specified in maxout. | |
67 | */ | |
68 | ||
69 | int fastlz_decompress(const void* input, int length, void* output, int maxout); | |
70 | ||
71 | /** | |
72 | Compress a block of data in the input buffer and returns the size of | |
73 | compressed block. The size of input buffer is specified by length. The | |
74 | minimum input buffer size is 16. | |
75 | ||
76 | The output buffer must be at least 5% larger than the input buffer | |
77 | and can not be smaller than 66 bytes. | |
78 | ||
79 | If the input is not compressible, the return value might be larger than | |
80 | length (input buffer size). | |
81 | ||
82 | The input buffer and the output buffer can not overlap. | |
83 | ||
84 | Compression level can be specified in parameter level. At the moment, | |
85 | only level 1 and level 2 are supported. | |
86 | Level 1 is the fastest compression and generally useful for short data. | |
87 | Level 2 is slightly slower but it gives better compression ratio. | |
88 | ||
89 | Note that the compressed data, regardless of the level, can always be | |
90 | decompressed using the function fastlz_decompress above. | |
91 | */ | |
92 | ||
93 | int fastlz_compress_level(int level, const void* input, int length, void* output); | |
94 | ||
95 | #if defined (__cplusplus) | |
96 | } | |
97 | #endif | |
98 | ||
99 | #endif /* FASTLZ_H */ |
0 | dnl $Id$ | |
1 | dnl config.m4 for extension yac | |
2 | ||
3 | PHP_ARG_ENABLE(yac, whether to enable yac support, | |
4 | [ --enable-yac Enable yac support]) | |
5 | ||
6 | PHP_ARG_WITH(system-fastlz, wheter to use system FastLZ bibrary, | |
7 | [ --with-system-fastlz Use system FastLZ bibrary], no, no) | |
8 | ||
9 | dnl PHP_ARG_ENABLE(yac, whether to use msgpack as serializer, | |
10 | dnl [ --enable-msgpack Use Messagepack as serializer]) | |
11 | ||
12 | dnl copied from Zend Optimizer Plus | |
13 | AC_MSG_CHECKING(for sysvipc shared memory support) | |
14 | AC_TRY_RUN([ | |
15 | #include <sys/types.h> | |
16 | #include <sys/wait.h> | |
17 | #include <sys/ipc.h> | |
18 | #include <sys/shm.h> | |
19 | #include <unistd.h> | |
20 | #include <string.h> | |
21 | ||
22 | int main() { | |
23 | pid_t pid; | |
24 | int status; | |
25 | int ipc_id; | |
26 | char *shm; | |
27 | struct shmid_ds shmbuf; | |
28 | ||
29 | ipc_id = shmget(IPC_PRIVATE, 4096, (IPC_CREAT | SHM_R | SHM_W)); | |
30 | if (ipc_id == -1) { | |
31 | return 1; | |
32 | } | |
33 | ||
34 | shm = shmat(ipc_id, NULL, 0); | |
35 | if (shm == (void *)-1) { | |
36 | shmctl(ipc_id, IPC_RMID, NULL); | |
37 | return 2; | |
38 | } | |
39 | ||
40 | if (shmctl(ipc_id, IPC_STAT, &shmbuf) != 0) { | |
41 | shmdt(shm); | |
42 | shmctl(ipc_id, IPC_RMID, NULL); | |
43 | return 3; | |
44 | } | |
45 | ||
46 | shmbuf.shm_perm.uid = getuid(); | |
47 | shmbuf.shm_perm.gid = getgid(); | |
48 | shmbuf.shm_perm.mode = 0600; | |
49 | ||
50 | if (shmctl(ipc_id, IPC_SET, &shmbuf) != 0) { | |
51 | shmdt(shm); | |
52 | shmctl(ipc_id, IPC_RMID, NULL); | |
53 | return 4; | |
54 | } | |
55 | ||
56 | shmctl(ipc_id, IPC_RMID, NULL); | |
57 | ||
58 | strcpy(shm, "hello"); | |
59 | ||
60 | pid = fork(); | |
61 | if (pid < 0) { | |
62 | return 5; | |
63 | } else if (pid == 0) { | |
64 | strcpy(shm, "bye"); | |
65 | return 6; | |
66 | } | |
67 | if (wait(&status) != pid) { | |
68 | return 7; | |
69 | } | |
70 | if (!WIFEXITED(status) || WEXITSTATUS(status) != 6) { | |
71 | return 8; | |
72 | } | |
73 | if (strcmp(shm, "bye") != 0) { | |
74 | return 9; | |
75 | } | |
76 | return 0; | |
77 | } | |
78 | ],dnl | |
79 | AC_DEFINE(HAVE_SHM_IPC, 1, [Define if you have SysV IPC SHM support]) | |
80 | msg=yes,msg=no,msg=no) | |
81 | AC_MSG_RESULT([$msg]) | |
82 | ||
83 | AC_MSG_CHECKING(for mmap() using MAP_ANON shared memory support) | |
84 | AC_TRY_RUN([ | |
85 | #include <sys/types.h> | |
86 | #include <sys/wait.h> | |
87 | #include <sys/mman.h> | |
88 | #include <unistd.h> | |
89 | #include <string.h> | |
90 | ||
91 | #ifndef MAP_ANON | |
92 | # ifdef MAP_ANONYMOUS | |
93 | # define MAP_ANON MAP_ANONYMOUS | |
94 | # endif | |
95 | #endif | |
96 | #ifndef MAP_FAILED | |
97 | # define MAP_FAILED ((void*)-1) | |
98 | #endif | |
99 | ||
100 | int main() { | |
101 | pid_t pid; | |
102 | int status; | |
103 | char *shm; | |
104 | ||
105 | shm = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); | |
106 | if (shm == MAP_FAILED) { | |
107 | return 1; | |
108 | } | |
109 | ||
110 | strcpy(shm, "hello"); | |
111 | ||
112 | pid = fork(); | |
113 | if (pid < 0) { | |
114 | return 5; | |
115 | } else if (pid == 0) { | |
116 | strcpy(shm, "bye"); | |
117 | return 6; | |
118 | } | |
119 | if (wait(&status) != pid) { | |
120 | return 7; | |
121 | } | |
122 | if (!WIFEXITED(status) || WEXITSTATUS(status) != 6) { | |
123 | return 8; | |
124 | } | |
125 | if (strcmp(shm, "bye") != 0) { | |
126 | return 9; | |
127 | } | |
128 | return 0; | |
129 | } | |
130 | ],dnl | |
131 | AC_DEFINE(HAVE_SHM_MMAP_ANON, 1, [Define if you have mmap(MAP_ANON) SHM support]) | |
132 | msg=yes,msg=no,msg=no) | |
133 | AC_MSG_RESULT([$msg]) | |
134 | ||
135 | AC_MSG_CHECKING(for mmap() using /dev/zero shared memory support) | |
136 | AC_TRY_RUN([ | |
137 | #include <sys/types.h> | |
138 | #include <sys/wait.h> | |
139 | #include <sys/mman.h> | |
140 | #include <sys/stat.h> | |
141 | #include <fcntl.h> | |
142 | #include <unistd.h> | |
143 | #include <string.h> | |
144 | ||
145 | #ifndef MAP_FAILED | |
146 | # define MAP_FAILED ((void*)-1) | |
147 | #endif | |
148 | ||
149 | int main() { | |
150 | pid_t pid; | |
151 | int status; | |
152 | int fd; | |
153 | char *shm; | |
154 | ||
155 | fd = open("/dev/zero", O_RDWR, S_IRUSR | S_IWUSR); | |
156 | if (fd == -1) { | |
157 | return 1; | |
158 | } | |
159 | ||
160 | shm = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); | |
161 | if (shm == MAP_FAILED) { | |
162 | return 2; | |
163 | } | |
164 | ||
165 | strcpy(shm, "hello"); | |
166 | ||
167 | pid = fork(); | |
168 | if (pid < 0) { | |
169 | return 5; | |
170 | } else if (pid == 0) { | |
171 | strcpy(shm, "bye"); | |
172 | return 6; | |
173 | } | |
174 | if (wait(&status) != pid) { | |
175 | return 7; | |
176 | } | |
177 | if (!WIFEXITED(status) || WEXITSTATUS(status) != 6) { | |
178 | return 8; | |
179 | } | |
180 | if (strcmp(shm, "bye") != 0) { | |
181 | return 9; | |
182 | } | |
183 | return 0; | |
184 | } | |
185 | ],dnl | |
186 | AC_DEFINE(HAVE_SHM_MMAP_ZERO, 1, [Define if you have mmap("/dev/zero") SHM support]) | |
187 | msg=yes,msg=no,msg=no) | |
188 | AC_MSG_RESULT([$msg]) | |
189 | ||
190 | dnl if test "$PHP_MSGPACK" != "no"; then | |
191 | dnl AC_DEFINE(ENABLE_MSGPACK,1,[enable msgpack packager]) | |
192 | dnl ifdef([PHP_ADD_EXTENSION_DEP], | |
193 | dnl [ | |
194 | dnl PHP_ADD_EXTENSION_DEP(yac, msgpack, true) | |
195 | dnl ]) | |
196 | dnl fi | |
197 | ||
198 | YAC_FILES="yac.c storage/yac_storage.c storage/allocator/yac_allocator.c storage/allocator/allocators/shm.c storage/allocator/allocators/mmap.c serializer/php.c serializer/msgpack.c" | |
199 | if test "$PHP_SYSTEM_FASTLZ" != "no"; then | |
200 | AC_CHECK_HEADERS([fastlz.h]) | |
201 | PHP_CHECK_LIBRARY(fastlz, fastlz_compress, | |
202 | [PHP_ADD_LIBRARY(fastlz, 1, YAC_SHARED_LIBADD)], | |
203 | [AC_MSG_ERROR(FastLZ library not found)]) | |
204 | else | |
205 | YAC_FILES="${YAC_FILES} compressor/fastlz/fastlz.c" | |
206 | fi | |
207 | ||
208 | if test "$PHP_YAC" != "no"; then | |
209 | PHP_SUBST(YAC_SHARED_LIBADD) | |
210 | PHP_NEW_EXTENSION(yac, ${YAC_FILES}, $ext_shared) | |
211 | fi |
0 | // $Id$ | |
1 | // vim:ft=javascript | |
2 | ||
3 | ARG_ENABLE("yac", "enable yac support", "no"); | |
4 | ||
5 | if (PHP_YAC != "no") { | |
6 | if( CHECK_HEADER_ADD_INCLUDE("fastlz.h", "CFLAGS_YAC", PHP_YAC + ";" + configure_module_dirname + "\\compressor\\fastlz") && | |
7 | CHECK_HEADER_ADD_INCLUDE("yac_serializer.h", "CFLAGS_YAC", PHP_YAC + ";" + configure_module_dirname + "\\serializer") && | |
8 | CHECK_HEADER_ADD_INCLUDE("yac_storage.h", "CFLAGS_YAC", PHP_YAC + ";" + configure_module_dirname + "\\storage") && | |
9 | CHECK_HEADER_ADD_INCLUDE("yac_allocator.h", "CFLAGS_YAC", PHP_YAC + ";" + configure_module_dirname + "\\storage\\allocator")) { | |
10 | ||
11 | EXTENSION("yac", "yac.c"); | |
12 | ||
13 | ADD_SOURCES(configure_module_dirname + "\\compressor\\fastlz", "fastlz.c", "yac"); | |
14 | ADD_SOURCES(configure_module_dirname + "\\serializer", "php.c", "yac"); | |
15 | ADD_SOURCES(configure_module_dirname + "\\storage", "yac_storage.c", "yac"); | |
16 | ADD_SOURCES(configure_module_dirname + "\\storage\\allocator", "yac_allocator.c", "yac"); | |
17 | ADD_SOURCES(configure_module_dirname + "\\storage\\allocator\\allocators", "createfilemapping.c", "yac"); | |
18 | ||
19 | AC_DEFINE('HAVE_YAC', 1, 'Have yac library'); | |
20 | ||
21 | ADD_FLAG("CFLAGS_YAC", ' /I "' + configure_module_dirname + '" '); | |
22 | ||
23 | } else { | |
24 | WARNING("yac not enabled, headers not found"); | |
25 | } | |
26 | } | |
27 |
0 | /* | |
1 | +----------------------------------------------------------------------+ | |
2 | | Yet Another Cache | | |
3 | +----------------------------------------------------------------------+ | |
4 | | Copyright (c) 2013-2013 The PHP Group | | |
5 | +----------------------------------------------------------------------+ | |
6 | | This source file is subject to version 3.01 of the PHP license, | | |
7 | | that is bundled with this package in the file LICENSE, and is | | |
8 | | available through the world-wide-web at the following url: | | |
9 | | http://www.php.net/license/3_01.txt | | |
10 | | If you did not receive a copy of the PHP license and are unable to | | |
11 | | obtain it through the world-wide-web, please send a note to | | |
12 | | license@php.net so we can mail you a copy immediately. | | |
13 | +----------------------------------------------------------------------+ | |
14 | | Author: Xinchen Hui <laruence@php.net> | | |
15 | +----------------------------------------------------------------------+ | |
16 | */ | |
17 | ||
18 | /* $Id$ */ | |
19 | ||
20 | #ifndef PHP_YAC_H | |
21 | #define PHP_YAC_H | |
22 | ||
23 | extern zend_module_entry yac_module_entry; | |
24 | #define phpext_yac_ptr &yac_module_entry | |
25 | ||
26 | #ifdef PHP_WIN32 | |
27 | #define PHP_YAC_API __declspec(dllexport) | |
28 | #else | |
29 | #define PHP_YAC_API | |
30 | #endif | |
31 | ||
32 | #ifdef ZTS | |
33 | #include "TSRM.h" | |
34 | #endif | |
35 | ||
36 | #define PHP_YAC_VERSION "0.9.2" | |
37 | ||
38 | #define YAC_CLASS_PROPERTY_PREFIX "_prefix" | |
39 | #define YAC_ENTRY_COMPRESSED 0x0020 | |
40 | #define YAC_ENTRY_TYPE_MASK 0x1f | |
41 | #define YAC_ENTRY_ORIG_LEN_SHIT 6 | |
42 | #define YAC_ENTRY_MAX_ORIG_LEN ((1U << ((sizeof(int)*8 - YAC_ENTRY_ORIG_LEN_SHIT))) - 1) | |
43 | #define YAC_MIN_COMPRESS_THRESHOLD 1024 | |
44 | ||
45 | ZEND_BEGIN_MODULE_GLOBALS(yac) | |
46 | zend_bool enable; | |
47 | zend_bool debug; | |
48 | size_t k_msize; | |
49 | size_t v_msize; | |
50 | ulong compress_threshold; | |
51 | zend_bool enable_cli; | |
52 | #ifdef PHP_WIN32 | |
53 | char *mmap_base; | |
54 | #endif | |
55 | ZEND_END_MODULE_GLOBALS(yac) | |
56 | ||
57 | PHP_MINIT_FUNCTION(yac); | |
58 | PHP_MSHUTDOWN_FUNCTION(yac); | |
59 | PHP_RINIT_FUNCTION(yac); | |
60 | PHP_RSHUTDOWN_FUNCTION(yac); | |
61 | PHP_MINFO_FUNCTION(yac); | |
62 | ||
63 | #ifdef ZTS | |
64 | #define YAC_G(v) TSRMG(yac_globals_id, zend_yac_globals *, v) | |
65 | extern int yac_globals_id; | |
66 | #else | |
67 | #define YAC_G(v) (yac_globals.v) | |
68 | extern zend_yac_globals yac_globals; | |
69 | #endif | |
70 | ||
71 | #endif /* PHP_YAC_H */ | |
72 | /* | |
73 | * Local variables: | |
74 | * tab-width: 4 | |
75 | * c-basic-offset: 4 | |
76 | * End: | |
77 | * vim600: noet sw=4 ts=4 fdm=marker | |
78 | * vim<600: noet sw=4 ts=4 | |
79 | */ |
0 | /* | |
1 | +----------------------------------------------------------------------+ | |
2 | | Yar - Light, concurrent RPC framework | | |
3 | +----------------------------------------------------------------------+ | |
4 | | Copyright (c) 2012-2013 The PHP Group | | |
5 | +----------------------------------------------------------------------+ | |
6 | | This source file is subject to version 3.01 of the PHP license, | | |
7 | | that is bundled with this package in the file LICENSE, and is | | |
8 | | available through the world-wide-web at the following url: | | |
9 | | http://www.php.net/license/3_01.txt | | |
10 | | If you did not receive a copy of the PHP license and are unable to | | |
11 | | obtain it through the world-wide-web, please send a note to | | |
12 | | license@php.net so we can mail you a copy immediately. | | |
13 | +----------------------------------------------------------------------+ | |
14 | | Author: Xinchen Hui <laruence@php.net> | | |
15 | | Zhenyu Zhang <zhangzhenyu@php.net> | | |
16 | +----------------------------------------------------------------------+ | |
17 | */ | |
18 | ||
19 | /* $Id$ */ | |
20 | ||
21 | #ifdef HAVE_CONFIG_H | |
22 | #include "config.h" | |
23 | #endif | |
24 | ||
25 | #ifdef ENABLE_MSGPACK | |
26 | ||
27 | #include "php.h" | |
28 | #include "ext/standard/php_smart_str.h" /* for smart_str */ | |
29 | ||
30 | #include "yac_serializer.h" | |
31 | ||
32 | extern void php_msgpack_serialize(smart_str *buf, zval *val TSRMLS_DC); | |
33 | extern void php_msgpack_unserialize(zval *return_value, char *str, size_t str_len TSRMLS_DC); | |
34 | ||
35 | int yac_serializer_msgpack_pack(zval *pzval, smart_str *buf, char **msg TSRMLS_DC) /* {{{ */ { | |
36 | php_msgpack_serialize(buf, pzval TSRMLS_CC); | |
37 | return 1; | |
38 | } /* }}} */ | |
39 | ||
40 | zval * yac_serializer_msgpack_unpack(char *content, size_t len, char **msg TSRMLS_DC) /* {{{ */ { | |
41 | zval *return_value; | |
42 | MAKE_STD_ZVAL(return_value); | |
43 | ZVAL_NULL(return_value); | |
44 | php_msgpack_unserialize(return_value, content, len TSRMLS_CC); | |
45 | return return_value; | |
46 | } /* }}} */ | |
47 | ||
48 | #endif | |
49 | ||
50 | /* | |
51 | * Local variables: | |
52 | * tab-width: 4 | |
53 | * c-basic-offset: 4 | |
54 | * End: | |
55 | * vim600: noet sw=4 ts=4 fdm=marker | |
56 | * vim<600: noet sw=4 ts=4 | |
57 | */ |
0 | /* | |
1 | +----------------------------------------------------------------------+ | |
2 | | Yet Another Cache | | |
3 | +----------------------------------------------------------------------+ | |
4 | | Copyright (c) 2013-2013 The PHP Group | | |
5 | +----------------------------------------------------------------------+ | |
6 | | This source file is subject to version 3.01 of the PHP license, | | |
7 | | that is bundled with this package in the file LICENSE, and is | | |
8 | | available through the world-wide-web at the following url: | | |
9 | | http://www.php.net/license/3_01.txt | | |
10 | | If you did not receive a copy of the PHP license and are unable to | | |
11 | | obtain it through the world-wide-web, please send a note to | | |
12 | | license@php.net so we can mail you a copy immediately. | | |
13 | +----------------------------------------------------------------------+ | |
14 | | Author: Xinchen Hui <laruence@php.net> | | |
15 | +----------------------------------------------------------------------+ | |
16 | */ | |
17 | ||
18 | /* $Id$ */ | |
19 | ||
20 | #ifdef HAVE_CONFIG_H | |
21 | #include "config.h" | |
22 | #endif | |
23 | ||
24 | #if !ENABLE_MSGPACK | |
25 | ||
26 | #include "php.h" | |
27 | #include "ext/standard/php_var.h" /* for serialize */ | |
28 | #include "ext/standard/php_smart_str.h" /* for smart_str */ | |
29 | ||
30 | #include "yac_serializer.h" | |
31 | ||
32 | int yac_serializer_php_pack(zval *pzval, smart_str *buf, char **msg TSRMLS_DC) /* {{{ */ { | |
33 | php_serialize_data_t var_hash; | |
34 | ||
35 | PHP_VAR_SERIALIZE_INIT(var_hash); | |
36 | php_var_serialize(buf, &pzval, &var_hash TSRMLS_CC); | |
37 | PHP_VAR_SERIALIZE_DESTROY(var_hash); | |
38 | ||
39 | return 1; | |
40 | } /* }}} */ | |
41 | ||
42 | zval * yac_serializer_php_unpack(char *content, size_t len, char **msg TSRMLS_DC) /* {{{ */ { | |
43 | zval *return_value; | |
44 | const unsigned char *p; | |
45 | php_unserialize_data_t var_hash; | |
46 | p = (const unsigned char*)content; | |
47 | ||
48 | MAKE_STD_ZVAL(return_value); | |
49 | ZVAL_FALSE(return_value); | |
50 | PHP_VAR_UNSERIALIZE_INIT(var_hash); | |
51 | if (!php_var_unserialize(&return_value, &p, p + len, &var_hash TSRMLS_CC)) { | |
52 | zval_ptr_dtor(&return_value); | |
53 | PHP_VAR_UNSERIALIZE_DESTROY(var_hash); | |
54 | spprintf(msg, 0, "unpack error at offset %ld of %ld bytes", (long)((char*)p - content), len); | |
55 | return NULL; | |
56 | } | |
57 | PHP_VAR_UNSERIALIZE_DESTROY(var_hash); | |
58 | ||
59 | return return_value; | |
60 | } /* }}} */ | |
61 | ||
62 | #endif | |
63 | ||
64 | /* | |
65 | * Local variables: | |
66 | * tab-width: 4 | |
67 | * c-basic-offset: 4 | |
68 | * End: | |
69 | * vim600: noet sw=4 ts=4 fdm=marker | |
70 | * vim<600: noet sw=4 ts=4 | |
71 | */ |
0 | /* | |
1 | +----------------------------------------------------------------------+ | |
2 | | Yet Another Cache | | |
3 | +----------------------------------------------------------------------+ | |
4 | | Copyright (c) 2013-2013 The PHP Group | | |
5 | +----------------------------------------------------------------------+ | |
6 | | This source file is subject to version 3.01 of the PHP license, | | |
7 | | that is bundled with this package in the file LICENSE, and is | | |
8 | | available through the world-wide-web at the following url: | | |
9 | | http://www.php.net/license/3_01.txt | | |
10 | | If you did not receive a copy of the PHP license and are unable to | | |
11 | | obtain it through the world-wide-web, please send a note to | | |
12 | | license@php.net so we can mail you a copy immediately. | | |
13 | +----------------------------------------------------------------------+ | |
14 | | Author: Xinchen Hui <laruence@php.net> | | |
15 | +----------------------------------------------------------------------+ | |
16 | */ | |
17 | ||
18 | /* $Id$ */ | |
19 | ||
20 | #ifndef YAC_SERIALIZER_H | |
21 | #define YAC_SERIALIZER_H | |
22 | ||
23 | #if ENABLE_MSGPACK | |
24 | int yac_serializer_msgpack_pack(zval *pzval, smart_str *buf, char **msg TSRMLS_DC); | |
25 | zval * yac_serializer_msgpack_unpack(char *content, size_t len, char **msg TSRMLS_DC); | |
26 | #else | |
27 | int yac_serializer_php_pack(zval *pzval, smart_str *buf, char **msg TSRMLS_DC); | |
28 | zval * yac_serializer_php_unpack(char *content, size_t len, char **msg TSRMLS_DC); | |
29 | #endif | |
30 | ||
31 | #endif /* YAC_SERIALIZER_H */ | |
32 | ||
33 | /* | |
34 | * Local variables: | |
35 | * tab-width: 4 | |
36 | * c-basic-offset: 4 | |
37 | * End: | |
38 | * vim600: noet sw=4 ts=4 fdm=marker | |
39 | * vim<600: noet sw=4 ts=4 | |
40 | */ |
0 | /* | |
1 | +----------------------------------------------------------------------+ | |
2 | | Yet Another Cache | | |
3 | +----------------------------------------------------------------------+ | |
4 | | Copyright (c) 2013-2013 The PHP Group | | |
5 | +----------------------------------------------------------------------+ | |
6 | | This source file is subject to version 3.01 of the PHP license, | | |
7 | | that is bundled with this package in the file LICENSE, and is | | |
8 | | available through the world-wide-web at the following url: | | |
9 | | http://www.php.net/license/3_01.txt | | |
10 | | If you did not receive a copy of the PHP license and are unable to | | |
11 | | obtain it through the world-wide-web, please send a note to | | |
12 | | license@php.net so we can mail you a copy immediately. | | |
13 | +----------------------------------------------------------------------+ | |
14 | | Authors: Xinchen Hui <laruence@php.net> | | |
15 | | Dmitry Stogov <dmitry@zend.com> | | |
16 | | Wei Dai <zxcvdavid@gmail.com> | | |
17 | +----------------------------------------------------------------------+ | |
18 | */ | |
19 | ||
20 | #include "php.h" | |
21 | ||
22 | #include "php_yac.h" | |
23 | #include "storage/yac_storage.h" | |
24 | #include "storage/allocator/yac_allocator.h" | |
25 | ||
26 | #include <stdio.h> | |
27 | #include <windows.h> | |
28 | #include <Lmcons.h> | |
29 | ||
30 | #define ACCEL_FILEMAP_NAME "Yac.SharedMemoryArea" | |
31 | #define ACCEL_FILEMAP_BASE "Yac.MemoryBase" | |
32 | #define MAX_MAP_RETRIES 25 | |
33 | ||
34 | static HANDLE memfile = NULL; | |
35 | static void *mapping_base; | |
36 | ||
37 | typedef struct { | |
38 | yac_shared_segment common; | |
39 | unsigned long size; | |
40 | } yac_shared_segment_create_file; | |
41 | ||
42 | #ifdef USE_FILE_MAPPING | |
43 | static char *create_name_with_username(char *name) | |
44 | { | |
45 | static char newname[MAXPATHLEN + UNLEN + 4]; | |
46 | char uname[UNLEN + 1]; | |
47 | DWORD unsize = UNLEN; | |
48 | ||
49 | GetUserName(uname, &unsize); | |
50 | snprintf(newname, sizeof(newname) - 1, "%s@%s", name, uname); | |
51 | return newname; | |
52 | } | |
53 | ||
54 | static char *get_mmap_base_file(void) { | |
55 | static char windir[MAXPATHLEN+UNLEN + 3 + sizeof("\\\\@")]; | |
56 | char uname[UNLEN + 1]; | |
57 | DWORD unsize = UNLEN; | |
58 | int l; | |
59 | ||
60 | GetTempPath(MAXPATHLEN, windir); | |
61 | GetUserName(uname, &unsize); | |
62 | l = strlen(windir); | |
63 | snprintf(windir + l, sizeof(windir) - l - 1, "\\%s@%s", ACCEL_FILEMAP_BASE, uname); | |
64 | return windir; | |
65 | } | |
66 | ||
67 | static int yac_shared_alloc_reattach(size_t requested_size, char **error_in) | |
68 | { | |
69 | void *wanted_mapping_base; | |
70 | char *mmap_base_file = get_mmap_base_file(); | |
71 | FILE *fp = fopen(mmap_base_file, "r"); | |
72 | MEMORY_BASIC_INFORMATION info; | |
73 | ||
74 | if (!fp) { | |
75 | *error_in="fopen"; | |
76 | return ALLOC_FAILURE; | |
77 | } | |
78 | ||
79 | if (!fscanf(fp, "%p", &wanted_mapping_base)) { | |
80 | *error_in="read mapping base"; | |
81 | fclose(fp); | |
82 | return ALLOC_FAILURE; | |
83 | } | |
84 | fclose(fp); | |
85 | ||
86 | /* Check if the requested address space is free */ | |
87 | if (VirtualQuery(wanted_mapping_base, &info, sizeof(info)) == 0) { | |
88 | *error_in="VirtualQuery"; | |
89 | return ALLOC_FAILURE; | |
90 | } | |
91 | ||
92 | if (info.State != MEM_FREE) { | |
93 | *error_in="info.State"; | |
94 | return ALLOC_FAILURE; | |
95 | } | |
96 | ||
97 | if (info.RegionSize < requested_size) { | |
98 | *error_in="info.RegionSize"; | |
99 | return ALLOC_FAILURE; | |
100 | } | |
101 | ||
102 | mapping_base = MapViewOfFileEx(memfile, FILE_MAP_ALL_ACCESS, 0, 0, 0, wanted_mapping_base); | |
103 | ||
104 | if (mapping_base == NULL) { | |
105 | return ALLOC_FAIL_MAPPING; | |
106 | } | |
107 | ||
108 | return SUCCESSFULLY_REATTACHED; | |
109 | } | |
110 | ||
111 | static int create_segments(unsigned long k_size, unsigned long v_size, yac_shared_segment_create_file **shared_segments_p, int *shared_segments_count, char **error_in) /* {{{ */ { | |
112 | int ret; | |
113 | unsigned long allocate_size, occupied_size = 0; | |
114 | unsigned int i, segment_size, segments_num = 1024, is_reattach = 0; | |
115 | int map_retries = 0; | |
116 | yac_shared_segment_create_file first_segment; | |
117 | void *default_mapping_base_set[] = {0, 0}; | |
118 | /* TODO: | |
119 | improve fixed addresses on x64. It still makes no sense to do it as Windows addresses are virtual per se and can or should be randomized anyway | |
120 | through Address Space Layout Radomization (ASLR). We can still let the OS do its job and be sure that each process gets the same address if | |
121 | desired. Not done yet, @zend refused but did not remember the exact reason, pls add info here if one of you know why :) | |
122 | */ | |
123 | #if defined(_WIN64) | |
124 | void *vista_mapping_base_set[] = { (void *) 0x0000100000000000, (void *) 0x0000200000000000, (void *) 0x0000300000000000, (void *) 0x0000700000000000, 0 }; | |
125 | #else | |
126 | void *vista_mapping_base_set[] = { (void *) 0x20000000, (void *) 0x21000000, (void *) 0x30000000, (void *) 0x31000000, (void *) 0x50000000, 0 }; | |
127 | #endif | |
128 | void **wanted_mapping_base = default_mapping_base_set; | |
129 | TSRMLS_FETCH(); | |
130 | ||
131 | k_size = YAC_SMM_ALIGNED_SIZE(k_size); | |
132 | v_size = YAC_SMM_ALIGNED_SIZE(v_size); | |
133 | while ((v_size / segments_num) < YAC_SMM_SEGMENT_MIN_SIZE) { | |
134 | segments_num >>= 1; | |
135 | } | |
136 | ||
137 | segment_size = v_size / segments_num; | |
138 | ++segments_num; | |
139 | ||
140 | allocate_size = k_size + v_size; | |
141 | ||
142 | /* Mapping retries: When Apache2 restarts, the parent process startup routine | |
143 | can be called before the child process is killed. In this case, the map will fail | |
144 | and we have to sleep some time (until the child releases the mapping object) and retry.*/ | |
145 | do { | |
146 | memfile = OpenFileMapping(FILE_MAP_WRITE, 0, create_name_with_username(ACCEL_FILEMAP_NAME)); | |
147 | if (memfile == NULL) { | |
148 | break; | |
149 | } | |
150 | ||
151 | ret = yac_shared_alloc_reattach((size_t)k_size, error_in); | |
152 | if (ret == ALLOC_FAIL_MAPPING) { | |
153 | /* Mapping failed, wait for mapping object to get freed and retry */ | |
154 | CloseHandle(memfile); | |
155 | memfile = NULL; | |
156 | Sleep(1000 * (map_retries + 1)); | |
157 | } else if (ret == SUCCESSFULLY_REATTACHED) { | |
158 | is_reattach = 1; | |
159 | break; | |
160 | } else { | |
161 | return ret; | |
162 | } | |
163 | } while (++map_retries < MAX_MAP_RETRIES); | |
164 | ||
165 | if (map_retries == MAX_MAP_RETRIES) { | |
166 | *error_in = "OpenFileMapping"; | |
167 | return 0; | |
168 | } | |
169 | ||
170 | *shared_segments_p = (yac_shared_segment_create_file *)calloc(1, segments_num * sizeof(yac_shared_segment_create_file)); | |
171 | if(!*shared_segments_p) { | |
172 | *error_in = "calloc"; | |
173 | return 0; | |
174 | } | |
175 | *shared_segments_count = segments_num; | |
176 | ||
177 | /* Starting from windows Vista, heap randomization occurs which might cause our mapping base to | |
178 | be taken (fail to map). So under Vista, we try to map into a hard coded predefined addresses | |
179 | in high memory. */ | |
180 | if (!YAC_G(mmap_base) || !*YAC_G(mmap_base)) { | |
181 | do { | |
182 | OSVERSIONINFOEX osvi; | |
183 | SYSTEM_INFO si; | |
184 | ||
185 | ZeroMemory(&si, sizeof(SYSTEM_INFO)); | |
186 | ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); | |
187 | ||
188 | osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); | |
189 | ||
190 | if (! GetVersionEx ((OSVERSIONINFO *) &osvi)) { | |
191 | osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); | |
192 | if (!GetVersionEx((OSVERSIONINFO *)&osvi)) { | |
193 | break; | |
194 | } | |
195 | } | |
196 | ||
197 | GetSystemInfo(&si); | |
198 | ||
199 | /* Are we running Vista ? */ | |
200 | if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion == 6) { | |
201 | wanted_mapping_base = vista_mapping_base_set; | |
202 | } | |
203 | } while (0); | |
204 | } else { | |
205 | char *s = YAC_G(mmap_base); | |
206 | ||
207 | /* skip leading 0x, %p assumes hexdeciaml format anyway */ | |
208 | if (*s == '0' && *(s + 1) == 'x') { | |
209 | s += 2; | |
210 | } | |
211 | if (sscanf(s, "%p", &default_mapping_base_set[0]) != 1) { | |
212 | *error_in = "mapping"; | |
213 | return 0; | |
214 | } | |
215 | } | |
216 | ||
217 | if (is_reattach == 0) { | |
218 | memfile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, allocate_size, create_name_with_username(ACCEL_FILEMAP_NAME)); | |
219 | if (memfile == NULL) { | |
220 | *error_in = "CreateFileMapping"; | |
221 | return 0; | |
222 | } | |
223 | ||
224 | do { | |
225 | first_segment.common.p = mapping_base = MapViewOfFileEx(memfile, FILE_MAP_ALL_ACCESS, 0, 0, 0, *wanted_mapping_base); | |
226 | if (wanted_mapping_base == NULL) { | |
227 | break; | |
228 | } | |
229 | *wanted_mapping_base++; | |
230 | } while (!mapping_base); | |
231 | } | |
232 | ||
233 | if(mapping_base == NULL) { | |
234 | *error_in = "MapViewOfFileEx"; | |
235 | return 0; | |
236 | } else { | |
237 | char *mmap_base_file = get_mmap_base_file(); | |
238 | FILE *fp = fopen(mmap_base_file, "w"); | |
239 | if (!fp) { | |
240 | *error_in = "get_mmap_base_file"; | |
241 | return 0; | |
242 | } | |
243 | fprintf(fp, "%p", mapping_base); | |
244 | fclose(fp); | |
245 | } | |
246 | ||
247 | first_segment.common.p = mapping_base; | |
248 | first_segment.size = allocate_size; | |
249 | first_segment.common.size = k_size; | |
250 | first_segment.common.pos = 0; | |
251 | ||
252 | (*shared_segments_p)[0] = first_segment; | |
253 | ||
254 | occupied_size = k_size; | |
255 | for (i = 1; i < segments_num; i++) { | |
256 | (*shared_segments_p)[i].size = 0; | |
257 | (*shared_segments_p)[i].common.pos = 0; | |
258 | (*shared_segments_p)[i].common.p = (void *)((char *)first_segment.common.p + occupied_size); | |
259 | if ((allocate_size - occupied_size) >= YAC_SMM_ALIGNED_SIZE(segment_size)) { | |
260 | (*shared_segments_p)[i].common.size = YAC_SMM_ALIGNED_SIZE(segment_size); | |
261 | occupied_size += YAC_SMM_ALIGNED_SIZE(segment_size); | |
262 | } else { | |
263 | (*shared_segments_p)[i].common.size = (allocate_size - occupied_size); | |
264 | break; | |
265 | } | |
266 | } | |
267 | ||
268 | return 1; | |
269 | } | |
270 | /* }}} */ | |
271 | ||
272 | static int detach_segment(yac_shared_segment *shared_segment) /* {{{ */ { | |
273 | if (!shared_segment->size && mapping_base) { | |
274 | UnmapViewOfFile(mapping_base); | |
275 | CloseHandle(memfile); | |
276 | } | |
277 | return 0; | |
278 | } | |
279 | /* }}} */ | |
280 | ||
281 | static unsigned long segment_type_size(void) /* {{{ */ { | |
282 | return sizeof(yac_shared_segment_create_file); | |
283 | } | |
284 | /* }}} */ | |
285 | ||
286 | yac_shared_memory_handlers yac_alloc_create_file_handlers = /* {{{ */ { | |
287 | create_segments, | |
288 | detach_segment, | |
289 | segment_type_size | |
290 | }; | |
291 | /* }}} */ | |
292 | #endif /* USE_CREATE_FILE */ | |
293 | ||
294 | /* | |
295 | * Local variables: | |
296 | * tab-width: 4 | |
297 | * c-basic-offset: 4 | |
298 | * End: | |
299 | * vim600: noet sw=4 ts=4 fdm=marker | |
300 | * vim<600: noet sw=4 ts=4 | |
301 | */ |
0 | /* | |
1 | +----------------------------------------------------------------------+ | |
2 | | Yet Another Cache | | |
3 | +----------------------------------------------------------------------+ | |
4 | | Copyright (c) 2013-2013 The PHP Group | | |
5 | +----------------------------------------------------------------------+ | |
6 | | This source file is subject to version 3.01 of the PHP license, | | |
7 | | that is bundled with this package in the file LICENSE, and is | | |
8 | | available through the world-wide-web at the following url: | | |
9 | | http://www.php.net/license/3_01.txt | | |
10 | | If you did not receive a copy of the PHP license and are unable to | | |
11 | | obtain it through the world-wide-web, please send a note to | | |
12 | | license@php.net so we can mail you a copy immediately. | | |
13 | +----------------------------------------------------------------------+ | |
14 | | Authors: Xinchen Hui <laruence@php.net> | | |
15 | +----------------------------------------------------------------------+ | |
16 | */ | |
17 | ||
18 | #include "storage/yac_storage.h" | |
19 | #include "storage/allocator/yac_allocator.h" | |
20 | ||
21 | #ifdef USE_MMAP | |
22 | ||
23 | #include <sys/types.h> | |
24 | #include <sys/stat.h> | |
25 | #include <stdio.h> | |
26 | #include <stdlib.h> | |
27 | #include <sys/mman.h> | |
28 | ||
29 | #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS) | |
30 | # define MAP_ANONYMOUS MAP_ANON | |
31 | #endif | |
32 | ||
33 | #ifndef MAP_FAILED | |
34 | #define MAP_FAILED (void *)-1 | |
35 | #endif | |
36 | ||
37 | typedef struct { | |
38 | yac_shared_segment common; | |
39 | unsigned long size; | |
40 | } yac_shared_segment_mmap; | |
41 | ||
42 | static int create_segments(unsigned long k_size, unsigned long v_size, yac_shared_segment_mmap **shared_segments_p, int *shared_segments_count, char **error_in) /* {{{ */ { | |
43 | yac_shared_segment *shared_segment; | |
44 | unsigned long allocate_size, occupied_size = 0; | |
45 | unsigned int i, segment_size, segments_num = 1024; | |
46 | yac_shared_segment_mmap first_segment; | |
47 | ||
48 | k_size = YAC_SMM_ALIGNED_SIZE(k_size); | |
49 | v_size = YAC_SMM_ALIGNED_SIZE(v_size); | |
50 | while ((v_size / segments_num) < YAC_SMM_SEGMENT_MIN_SIZE) { | |
51 | segments_num >>= 1; | |
52 | } | |
53 | ||
54 | segment_size = v_size / segments_num; | |
55 | ++segments_num; | |
56 | ||
57 | allocate_size = k_size + v_size; | |
58 | ||
59 | first_segment.common.p = mmap(0, allocate_size, PROT_READ | PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); | |
60 | if (first_segment.common.p == MAP_FAILED) { | |
61 | *error_in = "mmap"; | |
62 | return 0; | |
63 | } | |
64 | first_segment.size = allocate_size; | |
65 | first_segment.common.size = k_size; | |
66 | first_segment.common.pos = 0; | |
67 | ||
68 | *shared_segments_p = (yac_shared_segment_mmap *)calloc(1, segments_num * sizeof(yac_shared_segment_mmap)); | |
69 | if (!*shared_segments_p) { | |
70 | munmap(first_segment.common.p, first_segment.size); | |
71 | *error_in = "calloc"; | |
72 | return 0; | |
73 | } else { | |
74 | *shared_segments_p[0] = first_segment; | |
75 | } | |
76 | *shared_segments_count = segments_num; | |
77 | ||
78 | occupied_size = k_size; | |
79 | for (i = 1; i < segments_num; i++) { | |
80 | (*shared_segments_p)[i].size = 0; | |
81 | (*shared_segments_p)[i].common.pos = 0; | |
82 | (*shared_segments_p)[i].common.p = first_segment.common.p + occupied_size; | |
83 | if ((allocate_size - occupied_size) >= YAC_SMM_ALIGNED_SIZE(segment_size)) { | |
84 | (*shared_segments_p)[i].common.size = YAC_SMM_ALIGNED_SIZE(segment_size); | |
85 | occupied_size += YAC_SMM_ALIGNED_SIZE(segment_size); | |
86 | } else { | |
87 | (*shared_segments_p)[i].common.size = (allocate_size - occupied_size); | |
88 | break; | |
89 | } | |
90 | } | |
91 | ||
92 | return 1; | |
93 | } | |
94 | /* }}} */ | |
95 | ||
96 | static int detach_segment(yac_shared_segment *shared_segment) /* {{{ */ { | |
97 | if (shared_segment->size) { | |
98 | munmap(shared_segment->p, shared_segment->size); | |
99 | } | |
100 | return 0; | |
101 | } | |
102 | /* }}} */ | |
103 | ||
104 | static unsigned long segment_type_size(void) /* {{{ */ { | |
105 | return sizeof(yac_shared_segment_mmap); | |
106 | } | |
107 | /* }}} */ | |
108 | ||
109 | yac_shared_memory_handlers yac_alloc_mmap_handlers = /* {{{ */ { | |
110 | create_segments, | |
111 | detach_segment, | |
112 | segment_type_size | |
113 | }; | |
114 | /* }}} */ | |
115 | ||
116 | #endif /* USE_MMAP */ | |
117 | ||
118 | /* | |
119 | * Local variables: | |
120 | * tab-width: 4 | |
121 | * c-basic-offset: 4 | |
122 | * End: | |
123 | * vim600: noet sw=4 ts=4 fdm=marker | |
124 | * vim<600: noet sw=4 ts=4 | |
125 | */ |
0 | /* | |
1 | +----------------------------------------------------------------------+ | |
2 | | Zend Optimizer+ | | |
3 | +----------------------------------------------------------------------+ | |
4 | | Copyright (c) 1998-2013 The PHP Group | | |
5 | +----------------------------------------------------------------------+ | |
6 | | This source file is subject to version 3.01 of the PHP license, | | |
7 | | that is bundled with this package in the file LICENSE, and is | | |
8 | | available through the world-wide-web at the following url: | | |
9 | | http://www.php.net/license/3_01.txt | | |
10 | | If you did not receive a copy of the PHP license and are unable to | | |
11 | | obtain it through the world-wide-web, please send a note to | | |
12 | | license@php.net so we can mail you a copy immediately. | | |
13 | +----------------------------------------------------------------------+ | |
14 | | Authors: Andi Gutmans <andi@zend.com> | | |
15 | | Zeev Suraski <zeev@zend.com> | | |
16 | | Stanislav Malyshev <stas@zend.com> | | |
17 | | Dmitry Stogov <dmitry@zend.com> | | |
18 | +----------------------------------------------------------------------+ | |
19 | */ | |
20 | ||
21 | #include "zend_shared_alloc.h" | |
22 | ||
23 | #ifdef USE_SHM_OPEN | |
24 | ||
25 | #include <sys/types.h> | |
26 | #include <sys/stat.h> | |
27 | #include <stdio.h> | |
28 | #include <fcntl.h> | |
29 | #include <sys/mman.h> | |
30 | #include <unistd.h> | |
31 | #include <stdlib.h> | |
32 | ||
33 | typedef struct { | |
34 | zend_shared_segment common; | |
35 | int shm_fd; | |
36 | } zend_shared_segment_posix; | |
37 | ||
38 | static int create_segments(size_t requested_size, zend_shared_segment_posix ***shared_segments_p, int *shared_segments_count, char **error_in) | |
39 | { | |
40 | zend_shared_segment_posix *shared_segment; | |
41 | char shared_segment_name[sizeof("/ZendAccelerator.") + 20]; | |
42 | ||
43 | *shared_segments_count = 1; | |
44 | *shared_segments_p = (zend_shared_segment_posix **) calloc(1, sizeof(zend_shared_segment_posix) + sizeof(void *)); | |
45 | if (!*shared_segments_p) { | |
46 | *error_in = "calloc"; | |
47 | return ALLOC_FAILURE; | |
48 | } | |
49 | shared_segment = (zend_shared_segment_posix *)((char *)(*shared_segments_p) + sizeof(void *)); | |
50 | (*shared_segments_p)[0] = shared_segment; | |
51 | ||
52 | sprintf(shared_segment_name, "/ZendAccelerator.%d", getpid()); | |
53 | shared_segment->shm_fd = shm_open(shared_segment_name, O_RDWR|O_CREAT|O_TRUNC, 0600); | |
54 | if (shared_segment->shm_fd == -1) { | |
55 | *error_in = "shm_open"; | |
56 | return ALLOC_FAILURE; | |
57 | } | |
58 | ||
59 | if (ftruncate(shared_segment->shm_fd, requested_size) != 0) { | |
60 | *error_in = "ftruncate"; | |
61 | shm_unlink(shared_segment_name); | |
62 | return ALLOC_FAILURE; | |
63 | } | |
64 | ||
65 | shared_segment->common.p = mmap(0, requested_size, PROT_READ | PROT_WRITE, MAP_SHARED, shared_segment->shm_fd, 0); | |
66 | if (shared_segment->common.p == MAP_FAILED) { | |
67 | *error_in = "mmap"; | |
68 | shm_unlink(shared_segment_name); | |
69 | return ALLOC_FAILURE; | |
70 | } | |
71 | shm_unlink(shared_segment_name); | |
72 | ||
73 | shared_segment->common.pos = 0; | |
74 | shared_segment->common.size = requested_size; | |
75 | ||
76 | return ALLOC_SUCCESS; | |
77 | } | |
78 | ||
79 | static int detach_segment(zend_shared_segment_posix *shared_segment) | |
80 | { | |
81 | munmap(shared_segment->common.p, shared_segment->common.size); | |
82 | close(shared_segment->shm_fd); | |
83 | return 0; | |
84 | } | |
85 | ||
86 | static size_t segment_type_size(void) | |
87 | { | |
88 | return sizeof(zend_shared_segment_posix); | |
89 | } | |
90 | ||
91 | zend_shared_memory_handlers zend_alloc_posix_handlers = { | |
92 | (create_segments_t)create_segments, | |
93 | (detach_segment_t)detach_segment, | |
94 | segment_type_size | |
95 | }; | |
96 | ||
97 | #endif /* USE_SHM_OPEN */ |
0 | /* | |
1 | +----------------------------------------------------------------------+ | |
2 | | Yet Another Cache | | |
3 | +----------------------------------------------------------------------+ | |
4 | | Copyright (c) 2013-2013 The PHP Group | | |
5 | +----------------------------------------------------------------------+ | |
6 | | This source file is subject to version 3.01 of the PHP license, | | |
7 | | that is bundled with this package in the file LICENSE, and is | | |
8 | | available through the world-wide-web at the following url: | | |
9 | | http://www.php.net/license/3_01.txt | | |
10 | | If you did not receive a copy of the PHP license and are unable to | | |
11 | | obtain it through the world-wide-web, please send a note to | | |
12 | | license@php.net so we can mail you a copy immediately. | | |
13 | +----------------------------------------------------------------------+ | |
14 | | Authors: Xinchen Hui <laruence@php.net> | | |
15 | +----------------------------------------------------------------------+ | |
16 | */ | |
17 | ||
18 | #include "storage/yac_storage.h" | |
19 | #include "storage/allocator/yac_allocator.h" | |
20 | ||
21 | #ifdef USE_SHM | |
22 | ||
23 | #if defined(__FreeBSD__) | |
24 | # include <machine/param.h> | |
25 | #endif | |
26 | #include <sys/types.h> | |
27 | #include <sys/shm.h> | |
28 | #include <sys/ipc.h> | |
29 | #include <dirent.h> | |
30 | #include <signal.h> | |
31 | #include <stdio.h> | |
32 | #include <stdlib.h> | |
33 | #include <unistd.h> | |
34 | #include <errno.h> | |
35 | ||
36 | #include <sys/stat.h> | |
37 | #include <fcntl.h> | |
38 | ||
39 | typedef struct { | |
40 | yac_shared_segment common; | |
41 | int shm_id; | |
42 | } yac_shared_segment_shm; | |
43 | ||
44 | static int create_segments(size_t k_size, size_t v_size, yac_shared_segment_shm **shared_segments_p, int *shared_segments_count, char **error_in) /* {{{ */ { | |
45 | struct shmid_ds sds; | |
46 | int shm_id, shmget_flags; | |
47 | yac_shared_segment_shm *shared_segments, first_segment; | |
48 | unsigned int i, j, allocate_size, allocated_num, segments_num, segment_size; | |
49 | ||
50 | shmget_flags = IPC_CREAT|SHM_R|SHM_W|IPC_EXCL; | |
51 | segments_num = 1024; | |
52 | while ((v_size / segments_num) < YAC_SMM_SEGMENT_MIN_SIZE) { | |
53 | segments_num >>= 1; | |
54 | } | |
55 | segment_size = v_size / segments_num; | |
56 | allocate_size = YAC_SMM_SEGMENT_MAX_SIZE; | |
57 | ||
58 | while ((shm_id = shmget(IPC_PRIVATE, allocate_size, shmget_flags)) < 0) { | |
59 | allocate_size >>= 1; | |
60 | } | |
61 | ||
62 | if (shm_id < 0) { | |
63 | /* this should never happen */ | |
64 | *error_in = "shmget"; | |
65 | return 0; | |
66 | } | |
67 | ||
68 | if (allocate_size < YAC_SMM_SEGMENT_MIN_SIZE) { | |
69 | /* this should never happen */ | |
70 | *error_in = "shmget"; | |
71 | return 0; | |
72 | } | |
73 | ||
74 | if (k_size <= allocate_size) { | |
75 | first_segment.shm_id = shm_id; | |
76 | first_segment.common.pos = 0; | |
77 | first_segment.common.size = allocate_size; | |
78 | first_segment.common.p = shmat(shm_id, NULL, 0); | |
79 | shmctl(shm_id, IPC_RMID, &sds); | |
80 | if (first_segment.common.p == (void *)-1) { | |
81 | *error_in = "shmat"; | |
82 | return 0; | |
83 | } | |
84 | } else { | |
85 | shmctl(shm_id, IPC_RMID, &sds); | |
86 | *error_in = "shmget"; | |
87 | return 0; | |
88 | } | |
89 | ||
90 | allocated_num = (v_size % allocate_size)? (v_size / allocate_size) + 1 : (v_size / allocate_size); | |
91 | shared_segments = (yac_shared_segment_shm *)calloc(1, (allocated_num) * sizeof(yac_shared_segment_shm)); | |
92 | if (!shared_segments) { | |
93 | *error_in = "calloc"; | |
94 | return 0; | |
95 | } | |
96 | ||
97 | for (i = 0; i < allocated_num; i ++) { | |
98 | shm_id = shmget(IPC_PRIVATE, allocate_size, shmget_flags); | |
99 | if (shm_id == -1) { | |
100 | *error_in = "shmget"; | |
101 | for (j = 0; j < i; j++) { | |
102 | shmdt(shared_segments[j].common.p); | |
103 | } | |
104 | free(shared_segments); | |
105 | return 0; | |
106 | } | |
107 | shared_segments[i].shm_id = shm_id; | |
108 | shared_segments[i].common.pos = 0; | |
109 | shared_segments[i].common.size = allocate_size; | |
110 | shared_segments[i].common.p = shmat(shm_id, NULL, 0); | |
111 | shmctl(shm_id, IPC_RMID, &sds); | |
112 | if (shared_segments[i].common.p == (void *)-1) { | |
113 | *error_in = "shmat"; | |
114 | for (j = 0; j < i; j++) { | |
115 | shmdt(shared_segments[j].common.p); | |
116 | } | |
117 | free(shared_segments); | |
118 | return 0; | |
119 | } | |
120 | } | |
121 | ||
122 | ++segments_num; | |
123 | *shared_segments_p = (yac_shared_segment_shm *)calloc(1, segments_num * sizeof(yac_shared_segment_shm)); | |
124 | if (!*shared_segments_p) { | |
125 | free(shared_segments); | |
126 | *error_in = "calloc"; | |
127 | return 0; | |
128 | } else { | |
129 | *shared_segments_p[0] = first_segment; | |
130 | } | |
131 | *shared_segments_count = segments_num; | |
132 | ||
133 | j = 0; | |
134 | for (i = 1; i < segments_num; i++) { | |
135 | if (shared_segments[j].common.pos == 0) { | |
136 | (*shared_segments_p)[i].shm_id = shared_segments[j].shm_id; | |
137 | } | |
138 | ||
139 | if ((shared_segments[j].common.size - shared_segments[j].common.pos) >= (2 * YAC_SMM_ALIGNED_SIZE(segment_size))) { | |
140 | (*shared_segments_p)[i].common.pos = 0; | |
141 | (*shared_segments_p)[i].common.size = YAC_SMM_ALIGNED_SIZE(segment_size); | |
142 | (*shared_segments_p)[i].common.p = shared_segments[j].common.p + YAC_SMM_ALIGNED_SIZE(shared_segments[j].common.pos); | |
143 | shared_segments[j].common.pos += YAC_SMM_ALIGNED_SIZE(segment_size); | |
144 | } else { | |
145 | (*shared_segments_p)[i].common.pos = 0; | |
146 | (*shared_segments_p)[i].common.size = shared_segments[j].common.size - shared_segments[j].common.pos; | |
147 | (*shared_segments_p)[i].common.p = shared_segments[j].common.p + YAC_SMM_ALIGNED_SIZE(shared_segments[j].common.pos); | |
148 | j++; | |
149 | } | |
150 | } | |
151 | ||
152 | free(shared_segments); | |
153 | ||
154 | return 1; | |
155 | } | |
156 | /* }}} */ | |
157 | ||
158 | static int detach_segment(yac_shared_segment_shm *shared_segment) /* {{{ */ { | |
159 | if (shared_segment->shm_id) { | |
160 | shmdt(shared_segment->common.p); | |
161 | } | |
162 | return 1; | |
163 | } | |
164 | /* }}} */ | |
165 | ||
166 | static size_t segment_type_size(void) /* {{{ */ { | |
167 | return sizeof(yac_shared_segment_shm); | |
168 | } | |
169 | /* }}} */ | |
170 | ||
171 | yac_shared_memory_handlers yac_alloc_shm_handlers = /* {{{ */ { | |
172 | (create_segments_t)create_segments, | |
173 | (detach_segment_t)detach_segment, | |
174 | segment_type_size | |
175 | }; | |
176 | /* }}} */ | |
177 | ||
178 | #endif /* USE_SHM */ | |
179 | ||
180 | /* | |
181 | * Local variables: | |
182 | * tab-width: 4 | |
183 | * c-basic-offset: 4 | |
184 | * End: | |
185 | * vim600: noet sw=4 ts=4 fdm=marker | |
186 | * vim<600: noet sw=4 ts=4 | |
187 | */ |
0 | /* | |
1 | +----------------------------------------------------------------------+ | |
2 | | Yet Another Cache | | |
3 | +----------------------------------------------------------------------+ | |
4 | | Copyright (c) 2013-2013 The PHP Group | | |
5 | +----------------------------------------------------------------------+ | |
6 | | This source file is subject to version 3.01 of the PHP license, | | |
7 | | that is bundled with this package in the file LICENSE, and is | | |
8 | | available through the world-wide-web at the following url: | | |
9 | | http://www.php.net/license/3_01.txt | | |
10 | | If you did not receive a copy of the PHP license and are unable to | | |
11 | | obtain it through the world-wide-web, please send a note to | | |
12 | | license@php.net so we can mail you a copy immediately. | | |
13 | +----------------------------------------------------------------------+ | |
14 | | Authors: Xinchen Hui <laruence@php.net> | | |
15 | +----------------------------------------------------------------------+ | |
16 | */ | |
17 | ||
18 | #include "ZendAccelerator.h" | |
19 | #include "zend_shared_alloc.h" | |
20 | #include "zend_accelerator_util_funcs.h" | |
21 | #include <winbase.h> | |
22 | #include <process.h> | |
23 | #include <LMCONS.H> | |
24 | ||
25 | #define ACCEL_FILEMAP_NAME "ZendOptimizer+.SharedMemoryArea" | |
26 | #define ACCEL_MUTEX_NAME "ZendOptimizer+.SharedMemoryMutex" | |
27 | #define ACCEL_FILEMAP_BASE_DEFAULT 0x01000000 | |
28 | #define ACCEL_FILEMAP_BASE "ZendOptimizer+.MemoryBase" | |
29 | #define ACCEL_EVENT_SOURCE "Zend Optimizer+" | |
30 | ||
31 | static HANDLE memfile = NULL, memory_mutex = NULL; | |
32 | static void *mapping_base; | |
33 | ||
34 | #define MAX_MAP_RETRIES 25 | |
35 | ||
36 | static void zend_win_error_message(int type, char *msg, int err) | |
37 | { | |
38 | LPVOID lpMsgBuf; | |
39 | HANDLE h; | |
40 | char *ev_msgs[2]; | |
41 | ||
42 | FormatMessage( | |
43 | FORMAT_MESSAGE_ALLOCATE_BUFFER | | |
44 | FORMAT_MESSAGE_FROM_SYSTEM | | |
45 | FORMAT_MESSAGE_IGNORE_INSERTS, | |
46 | NULL, | |
47 | err, | |
48 | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language | |
49 | (LPTSTR) &lpMsgBuf, | |
50 | 0, | |
51 | NULL | |
52 | ); | |
53 | ||
54 | h = RegisterEventSource(NULL, TEXT(ACCEL_EVENT_SOURCE)); | |
55 | ev_msgs[0] = msg; | |
56 | ev_msgs[1] = lpMsgBuf; | |
57 | ReportEvent(h, // event log handle | |
58 | EVENTLOG_ERROR_TYPE, // event type | |
59 | 0, // category zero | |
60 | err, // event identifier | |
61 | NULL, // no user security identifier | |
62 | 2, // one substitution string | |
63 | 0, // no data | |
64 | ev_msgs, // pointer to string array | |
65 | NULL); // pointer to data | |
66 | DeregisterEventSource(h); | |
67 | ||
68 | LocalFree( lpMsgBuf ); | |
69 | ||
70 | zend_accel_error(type, msg); | |
71 | } | |
72 | ||
73 | static char *create_name_with_username(char *name) | |
74 | { | |
75 | static char newname[MAXPATHLEN + UNLEN + 4]; | |
76 | char uname[UNLEN + 1]; | |
77 | DWORD unsize = UNLEN; | |
78 | ||
79 | GetUserName(uname, &unsize); | |
80 | snprintf(newname, sizeof(newname) - 1, "%s@%s", name, uname); | |
81 | return newname; | |
82 | } | |
83 | ||
84 | static char *get_mmap_base_file(void) | |
85 | { | |
86 | static char windir[MAXPATHLEN+UNLEN + 3 + sizeof("\\\\@")]; | |
87 | char uname[UNLEN + 1]; | |
88 | DWORD unsize = UNLEN; | |
89 | int l; | |
90 | ||
91 | GetTempPath(MAXPATHLEN, windir); | |
92 | GetUserName(uname, &unsize); | |
93 | l = strlen(windir); | |
94 | snprintf(windir + l, sizeof(windir) - l - 1, "\\%s@%s", ACCEL_FILEMAP_BASE, uname); | |
95 | return windir; | |
96 | } | |
97 | ||
98 | void zend_shared_alloc_create_lock(void) | |
99 | { | |
100 | memory_mutex = CreateMutex(NULL, FALSE, create_name_with_username(ACCEL_MUTEX_NAME)); | |
101 | if (!memory_mutex) { | |
102 | zend_accel_error(ACCEL_LOG_FATAL, "Cannot create mutex"); | |
103 | return; | |
104 | } | |
105 | ReleaseMutex(memory_mutex); | |
106 | } | |
107 | ||
108 | void zend_shared_alloc_lock_win32(void) | |
109 | { | |
110 | DWORD waitRes = WaitForSingleObject(memory_mutex, INFINITE); | |
111 | ||
112 | if (waitRes == WAIT_FAILED) { | |
113 | zend_accel_error(ACCEL_LOG_ERROR, "Cannot lock mutex"); | |
114 | } | |
115 | } | |
116 | ||
117 | void zend_shared_alloc_unlock_win32(void) | |
118 | { | |
119 | ReleaseMutex(memory_mutex); | |
120 | } | |
121 | ||
122 | static int zend_shared_alloc_reattach(size_t requested_size, char **error_in) | |
123 | { | |
124 | int err; | |
125 | void *wanted_mapping_base; | |
126 | char *mmap_base_file = get_mmap_base_file(); | |
127 | FILE *fp = fopen(mmap_base_file, "r"); | |
128 | MEMORY_BASIC_INFORMATION info; | |
129 | ||
130 | err = GetLastError(); | |
131 | if (!fp) { | |
132 | zend_win_error_message(ACCEL_LOG_WARNING, mmap_base_file, err); | |
133 | zend_win_error_message(ACCEL_LOG_FATAL, "Unable to open base address file", err); | |
134 | *error_in="fopen"; | |
135 | return ALLOC_FAILURE; | |
136 | } | |
137 | if (!fscanf(fp, "%p", &wanted_mapping_base)) { | |
138 | err = GetLastError(); | |
139 | zend_win_error_message(ACCEL_LOG_FATAL, "Unable to read base address", err); | |
140 | *error_in="read mapping base"; | |
141 | fclose(fp); | |
142 | return ALLOC_FAILURE; | |
143 | } | |
144 | fclose(fp); | |
145 | ||
146 | /* Check if the requested address space is free */ | |
147 | if (VirtualQuery(wanted_mapping_base, &info, sizeof(info)) == 0 || | |
148 | info.State != MEM_FREE || | |
149 | info.RegionSize < requested_size) { | |
150 | err = ERROR_INVALID_ADDRESS; | |
151 | zend_win_error_message(ACCEL_LOG_FATAL, "Unable to reattach to base address", err); | |
152 | return ALLOC_FAILURE; | |
153 | } | |
154 | ||
155 | mapping_base = MapViewOfFileEx(memfile, FILE_MAP_ALL_ACCESS, 0, 0, 0, wanted_mapping_base); | |
156 | err = GetLastError(); | |
157 | ||
158 | if (mapping_base == NULL) { | |
159 | if (err == ERROR_INVALID_ADDRESS) { | |
160 | zend_win_error_message(ACCEL_LOG_FATAL, "Unable to reattach to base address", err); | |
161 | return ALLOC_FAILURE; | |
162 | } | |
163 | return ALLOC_FAIL_MAPPING; | |
164 | } | |
165 | smm_shared_globals = (zend_smm_shared_globals *) (((char *) mapping_base) + sizeof(zend_shared_memory_block_header)); | |
166 | ||
167 | return SUCCESSFULLY_REATTACHED; | |
168 | } | |
169 | ||
170 | static int create_segments(size_t requested_size, zend_shared_segment ***shared_segments_p, int *shared_segments_count, char **error_in) | |
171 | { | |
172 | int err, ret; | |
173 | zend_shared_segment *shared_segment; | |
174 | int map_retries = 0; | |
175 | void *default_mapping_base_set[] = { 0, 0 }; | |
176 | void *vista_mapping_base_set[] = { (void *)0x20000000, (void *)0x21000000, (void *)0x30000000, (void *)0x31000000, (void *)0x50000000, 0 }; | |
177 | void **wanted_mapping_base = default_mapping_base_set; | |
178 | TSRMLS_FETCH(); | |
179 | ||
180 | zend_shared_alloc_lock_win32(); | |
181 | /* Mapping retries: When Apache2 restarts, the parent process startup routine | |
182 | can be called before the child process is killed. In this case, the map will fail | |
183 | and we have to sleep some time (until the child releases the mapping object) and retry.*/ | |
184 | do { | |
185 | memfile = OpenFileMapping(FILE_MAP_WRITE, 0, create_name_with_username(ACCEL_FILEMAP_NAME)); | |
186 | err = GetLastError(); | |
187 | if (memfile == NULL) { | |
188 | break; | |
189 | } | |
190 | ||
191 | ret = zend_shared_alloc_reattach(requested_size, error_in); | |
192 | err = GetLastError(); | |
193 | if (ret == ALLOC_FAIL_MAPPING) { | |
194 | /* Mapping failed, wait for mapping object to get freed and retry */ | |
195 | CloseHandle(memfile); | |
196 | memfile = NULL; | |
197 | Sleep(1000 * (map_retries + 1)); | |
198 | } else { | |
199 | zend_shared_alloc_unlock_win32(); | |
200 | return ret; | |
201 | } | |
202 | } while (++map_retries < MAX_MAP_RETRIES); | |
203 | ||
204 | if (map_retries == MAX_MAP_RETRIES) { | |
205 | zend_shared_alloc_unlock_win32(); | |
206 | zend_win_error_message(ACCEL_LOG_FATAL, "Unable to open file mapping", err); | |
207 | *error_in = "OpenFileMapping"; | |
208 | return ALLOC_FAILURE; | |
209 | } | |
210 | ||
211 | /* creating segment here */ | |
212 | *shared_segments_count = 1; | |
213 | *shared_segments_p = (zend_shared_segment **) calloc(1, sizeof(zend_shared_segment)+sizeof(void *)); | |
214 | if (!*shared_segments_p) { | |
215 | zend_shared_alloc_unlock_win32(); | |
216 | zend_win_error_message(ACCEL_LOG_FATAL, "calloc() failed", GetLastError()); | |
217 | *error_in = "calloc"; | |
218 | return ALLOC_FAILURE; | |
219 | } | |
220 | shared_segment = (zend_shared_segment *)((char *)(*shared_segments_p) + sizeof(void *)); | |
221 | (*shared_segments_p)[0] = shared_segment; | |
222 | ||
223 | memfile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, requested_size, | |
224 | create_name_with_username(ACCEL_FILEMAP_NAME)); | |
225 | err = GetLastError(); | |
226 | if (memfile == NULL) { | |
227 | zend_shared_alloc_unlock_win32(); | |
228 | zend_win_error_message(ACCEL_LOG_FATAL, "Unable to create file mapping", err); | |
229 | *error_in = "CreateFileMapping"; | |
230 | return ALLOC_FAILURE; | |
231 | } | |
232 | ||
233 | /* Starting from windows Vista, heap randomization occurs which might cause our mapping base to | |
234 | be taken (fail to map). So under Vista, we try to map into a hard coded predefined addresses | |
235 | in high memory. */ | |
236 | if (!ZCG(accel_directives).mmap_base || !*ZCG(accel_directives).mmap_base) { | |
237 | do { | |
238 | OSVERSIONINFOEX osvi; | |
239 | SYSTEM_INFO si; | |
240 | ||
241 | ZeroMemory(&si, sizeof(SYSTEM_INFO)); | |
242 | ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); | |
243 | ||
244 | osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); | |
245 | ||
246 | if (! GetVersionEx ((OSVERSIONINFO *) &osvi)) { | |
247 | osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); | |
248 | if (!GetVersionEx((OSVERSIONINFO *)&osvi)) { | |
249 | break; | |
250 | } | |
251 | } | |
252 | ||
253 | GetSystemInfo(&si); | |
254 | ||
255 | /* Are we running Vista ? */ | |
256 | if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion == 6) { | |
257 | /* Assert that platform is 32 bit (for 64 bit we need to test a different set */ | |
258 | if (si.wProcessorArchitecture != PROCESSOR_ARCHITECTURE_INTEL) { | |
259 | DebugBreak(); | |
260 | } | |
261 | ||
262 | wanted_mapping_base = vista_mapping_base_set; | |
263 | } | |
264 | } while (0); | |
265 | } else { | |
266 | char *s = ZCG(accel_directives).mmap_base; | |
267 | ||
268 | /* skip leading 0x, %p assumes hexdeciaml format anyway */ | |
269 | if (*s == '0' && *(s + 1) == 'x') { | |
270 | s += 2; | |
271 | } | |
272 | if (sscanf(s, "%p", &default_mapping_base_set[0]) != 1) { | |
273 | zend_shared_alloc_unlock_win32(); | |
274 | zend_win_error_message(ACCEL_LOG_FATAL, "Bad mapping address specified in zend_optimizerplus.mmap_base", err); | |
275 | return ALLOC_FAILURE; | |
276 | } | |
277 | } | |
278 | ||
279 | do { | |
280 | shared_segment->p = mapping_base = MapViewOfFileEx(memfile, FILE_MAP_ALL_ACCESS, 0, 0, 0, *wanted_mapping_base); | |
281 | if (*wanted_mapping_base == NULL) { /* Auto address (NULL) is the last option on the array */ | |
282 | break; | |
283 | } | |
284 | wanted_mapping_base++; | |
285 | } while (!mapping_base); | |
286 | ||
287 | err = GetLastError(); | |
288 | if (mapping_base == NULL) { | |
289 | zend_shared_alloc_unlock_win32(); | |
290 | zend_win_error_message(ACCEL_LOG_FATAL, "Unable to create view for file mapping", err); | |
291 | *error_in = "MapViewOfFile"; | |
292 | return ALLOC_FAILURE; | |
293 | } else { | |
294 | char *mmap_base_file = get_mmap_base_file(); | |
295 | FILE *fp = fopen(mmap_base_file, "w"); | |
296 | err = GetLastError(); | |
297 | if (!fp) { | |
298 | zend_shared_alloc_unlock_win32(); | |
299 | zend_win_error_message(ACCEL_LOG_WARNING, mmap_base_file, err); | |
300 | zend_win_error_message(ACCEL_LOG_FATAL, "Unable to write base address", err); | |
301 | return ALLOC_FAILURE; | |
302 | } | |
303 | fprintf(fp, "%p\n", mapping_base); | |
304 | fclose(fp); | |
305 | } | |
306 | ||
307 | shared_segment->pos = 0; | |
308 | shared_segment->size = requested_size; | |
309 | ||
310 | zend_shared_alloc_unlock_win32(); | |
311 | ||
312 | return ALLOC_SUCCESS; | |
313 | } | |
314 | ||
315 | static int detach_segment(zend_shared_segment *shared_segment) | |
316 | { | |
317 | zend_shared_alloc_lock_win32(); | |
318 | if (mapping_base) { | |
319 | UnmapViewOfFile(mapping_base); | |
320 | } | |
321 | CloseHandle(memfile); | |
322 | zend_shared_alloc_unlock_win32(); | |
323 | CloseHandle(memory_mutex); | |
324 | return 0; | |
325 | } | |
326 | ||
327 | static size_t segment_type_size(void) | |
328 | { | |
329 | return sizeof(zend_shared_segment); | |
330 | } | |
331 | ||
332 | zend_shared_memory_handlers zend_alloc_win32_handlers = { | |
333 | create_segments, | |
334 | detach_segment, | |
335 | segment_type_size | |
336 | }; |
0 | /* | |
1 | +----------------------------------------------------------------------+ | |
2 | | Yet Another Cache | | |
3 | +----------------------------------------------------------------------+ | |
4 | | Copyright (c) 2013-2013 The PHP Group | | |
5 | +----------------------------------------------------------------------+ | |
6 | | This source file is subject to version 3.01 of the PHP license, | | |
7 | | that is bundled with this package in the file LICENSE, and is | | |
8 | | available through the world-wide-web at the following url: | | |
9 | | http://www.php.net/license/3_01.txt | | |
10 | | If you did not receive a copy of the PHP license and are unable to | | |
11 | | obtain it through the world-wide-web, please send a note to | | |
12 | | license@php.net so we can mail you a copy immediately. | | |
13 | +----------------------------------------------------------------------+ | |
14 | | Authors: Xinchen Hui <laruence@php.net> | | |
15 | +----------------------------------------------------------------------+ | |
16 | */ | |
17 | ||
18 | #include <errno.h> | |
19 | #include <time.h> | |
20 | #include <sys/types.h> | |
21 | ||
22 | #include "php.h" | |
23 | #include "storage/yac_storage.h" | |
24 | #include "yac_allocator.h" | |
25 | ||
26 | static const yac_shared_memory_handlers *shared_memory_handler = NULL; | |
27 | static const char *shared_model; | |
28 | ||
29 | int yac_allocator_startup(unsigned long k_size, unsigned long size, char **msg) /* {{{ */ { | |
30 | char *p; | |
31 | yac_shared_segment *segments = NULL; | |
32 | int i, segments_num, segments_array_size, segment_size; | |
33 | const yac_shared_memory_handlers *he; | |
34 | ||
35 | if ((he = &yac_shared_memory_handler)) { | |
36 | int ret = he->create_segments(k_size, size, &segments, &segments_num, msg); | |
37 | ||
38 | if (!ret) { | |
39 | if (segments) { | |
40 | int i; | |
41 | for (i = 0; i < segments_num; i++) { | |
42 | if (segments[i].p && segments[i].p != (void *)-1) { | |
43 | he->detach_segment(&segments[i]); | |
44 | } | |
45 | } | |
46 | free(segments); | |
47 | } | |
48 | return 0; | |
49 | } | |
50 | } else { | |
51 | return 0; | |
52 | } | |
53 | ||
54 | segment_size = he->segment_type_size(); | |
55 | segments_array_size = (segments_num - 1) * segment_size; | |
56 | ||
57 | yac_storage = segments[0].p; | |
58 | memcpy(&YAC_SG(first_seg), (char *)(&segments[0]), segment_size); | |
59 | ||
60 | YAC_SG(segments_num) = segments_num - 1; | |
61 | YAC_SG(segments_num_mask) = YAC_SG(segments_num) - 1; | |
62 | YAC_SG(segments) = (yac_shared_segment **)((char *)yac_storage + YAC_SMM_ALIGNED_SIZE(sizeof(yac_storage_globals) + segment_size - sizeof(yac_shared_segment))); | |
63 | ||
64 | p = (char *)YAC_SG(segments) + (sizeof(void *) * YAC_SG(segments_num)); | |
65 | memcpy(p, (char *)segments + segment_size, segments_array_size); | |
66 | for (i = 0; i < YAC_SG(segments_num); i++) { | |
67 | YAC_SG(segments)[i] = (yac_shared_segment *)p; | |
68 | p += segment_size; | |
69 | } | |
70 | YAC_SG(slots) = (yac_kv_key *)((char *)YAC_SG(segments) | |
71 | + (YAC_SG(segments_num) * sizeof(void *)) + YAC_SMM_ALIGNED_SIZE(segments_array_size)); | |
72 | ||
73 | free(segments); | |
74 | ||
75 | return 1; | |
76 | } | |
77 | /* }}} */ | |
78 | ||
79 | void yac_allocator_shutdown(void) /* {{{ */ { | |
80 | yac_shared_segment **segments; | |
81 | const yac_shared_memory_handlers *he; | |
82 | ||
83 | segments = YAC_SG(segments); | |
84 | if (segments) { | |
85 | if ((he = &yac_shared_memory_handler)) { | |
86 | int i = 0; | |
87 | for (i = 0; i < YAC_SG(segments_num); i++) { | |
88 | he->detach_segment(segments[i]); | |
89 | } | |
90 | he->detach_segment(&YAC_SG(first_seg)); | |
91 | } | |
92 | } | |
93 | } | |
94 | /* }}} */ | |
95 | ||
96 | static inline void *yac_allocator_alloc_algo2(unsigned long size, int hash) /* {{{ */ { | |
97 | yac_shared_segment *segment; | |
98 | unsigned int seg_size, retry, pos, current; | |
99 | ||
100 | current = hash & YAC_SG(segments_num_mask); | |
101 | /* do we really need lock here? it depends the real life exam */ | |
102 | retry = 3; | |
103 | do_retry: | |
104 | segment = YAC_SG(segments)[current]; | |
105 | seg_size = segment->size; | |
106 | pos = segment->pos; | |
107 | if ((seg_size - pos) >= size) { | |
108 | do_alloc: | |
109 | pos += size; | |
110 | segment->pos = pos; | |
111 | if (segment->pos == pos) { | |
112 | return (void *)((char *)segment->p + (pos - size)); | |
113 | } else if (retry--) { | |
114 | goto do_retry; | |
115 | } | |
116 | return NULL; | |
117 | } else { | |
118 | int i, max; | |
119 | max = (YAC_SG(segments_num) > 4)? 4 : YAC_SG(segments_num); | |
120 | for (i = 1; i < max; i++) { | |
121 | segment = YAC_SG(segments)[(current + i) & YAC_SG(segments_num_mask)]; | |
122 | seg_size = segment->size; | |
123 | pos = segment->pos; | |
124 | if ((seg_size - pos) >= size) { | |
125 | current = (current + i) & YAC_SG(segments_num_mask); | |
126 | goto do_alloc; | |
127 | } | |
128 | } | |
129 | segment->pos = 0; | |
130 | pos = 0; | |
131 | ++YAC_SG(recycles); | |
132 | goto do_alloc; | |
133 | } | |
134 | } | |
135 | /* }}} */ | |
136 | ||
137 | #if 0 | |
138 | static inline void *yac_allocator_alloc_algo1(unsigned long size) /* {{{ */ { | |
139 | int i, j, picked_seg, atime; | |
140 | picked_seg = (YAC_SG(current_seg) + 1) & YAC_SG(segments_num_mask); | |
141 | ||
142 | atime = YAC_SG(segments)[picked_seg]->atime; | |
143 | for (i = 0; i < 10; i++) { | |
144 | j = (picked_seg + 1) & YAC_SG(segments_num_mask); | |
145 | if (YAC_SG(segments)[j]->atime < atime) { | |
146 | picked_seg = j; | |
147 | atime = YAC_SG(segments)[j]->atime; | |
148 | } | |
149 | } | |
150 | ||
151 | YAC_SG(current_seg) = picked_seg; | |
152 | YAC_SG(segments)[picked_seg]->pos = 0; | |
153 | return yac_allocator_alloc_algo2(size); | |
154 | } | |
155 | /* }}} */ | |
156 | #endif | |
157 | ||
158 | unsigned long yac_allocator_real_size(unsigned long size) /* {{{ */ { | |
159 | unsigned long real_size = YAC_SMM_TRUE_SIZE(size); | |
160 | ||
161 | if (real_size > YAC_SG(segments)[0]->size) { | |
162 | return 0; | |
163 | } | |
164 | ||
165 | return real_size; | |
166 | } | |
167 | /* }}} */ | |
168 | ||
169 | void * yac_allocator_raw_alloc(unsigned long real_size, int hash) /* {{{ */ { | |
170 | ||
171 | return yac_allocator_alloc_algo2(real_size, hash); | |
172 | /* | |
173 | if (YAC_SG(exhausted)) { | |
174 | return yac_allocator_alloc_algo1(real_size); | |
175 | } else { | |
176 | void *p; | |
177 | if ((p = yac_allocator_alloc_algo2(real_size))) { | |
178 | return p; | |
179 | } | |
180 | return yac_allocator_alloc_algo1(real_size); | |
181 | } | |
182 | */ | |
183 | } | |
184 | /* }}} */ | |
185 | ||
186 | #if 0 | |
187 | void yac_allocator_touch(void *p, unsigned long atime) /* {{{ */ { | |
188 | yac_shared_block_header h = *(yac_shared_block_header *)(p - sizeof(yac_shared_block_header)); | |
189 | ||
190 | if (h.seg >= YAC_SG(segments_num)) { | |
191 | return; | |
192 | } | |
193 | ||
194 | YAC_SG(segments)[h.seg]->atime = atime; | |
195 | } | |
196 | /* }}} */ | |
197 | #endif | |
198 | ||
199 | /* | |
200 | * Local variables: | |
201 | * tab-width: 4 | |
202 | * c-basic-offset: 4 | |
203 | * End: | |
204 | * vim600: noet sw=4 ts=4 fdm=marker | |
205 | * vim<600: noet sw=4 ts=4 | |
206 | */ |
0 | /* | |
1 | +----------------------------------------------------------------------+ | |
2 | | Yet Another Cache | | |
3 | +----------------------------------------------------------------------+ | |
4 | | Copyright (c) 2013-2013 The PHP Group | | |
5 | +----------------------------------------------------------------------+ | |
6 | | This source file is subject to version 3.01 of the PHP license, | | |
7 | | that is bundled with this package in the file LICENSE, and is | | |
8 | | available through the world-wide-web at the following url: | | |
9 | | http://www.php.net/license/3_01.txt | | |
10 | | If you did not receive a copy of the PHP license and are unable to | | |
11 | | obtain it through the world-wide-web, please send a note to | | |
12 | | license@php.net so we can mail you a copy immediately. | | |
13 | +----------------------------------------------------------------------+ | |
14 | | Authors: Xinchen Hui <laruence@php.net> | | |
15 | +----------------------------------------------------------------------+ | |
16 | */ | |
17 | ||
18 | #ifndef YAC_ALLOCATOR_H | |
19 | #define YAC_ALLOCATOR_H | |
20 | ||
21 | #ifdef HAVE_CONFIG_H | |
22 | #include "config.h" | |
23 | #endif | |
24 | ||
25 | #define YAC_SMM_ALIGNMENT 8 | |
26 | #define YAC_SMM_ALIGNMENT_LOG2 3 | |
27 | #define YAC_SMM_ALIGNMENT_MASK ~(YAC_SMM_ALIGNMENT - 1) | |
28 | #define YAC_SMM_BLOCK_HEADER_SIZE YAC_SMM_ALIGNED_SIZE(sizeof(yac_shared_block_header)) | |
29 | ||
30 | #define YAC_SMM_MAIN_SEG_SIZE (4*1024*1024) | |
31 | #define YAC_SMM_SEGMENT_MAX_SIZE (32*1024*1024) | |
32 | #define YAC_SMM_SEGMENT_MIN_SIZE (4*1024*1024) | |
33 | #define YAC_SMM_MIN_BLOCK_SIZE 128 | |
34 | #define YAC_SMM_ALIGNED_SIZE(x) (((x) + YAC_SMM_ALIGNMENT - 1) & YAC_SMM_ALIGNMENT_MASK) | |
35 | #define YAC_SMM_TRUE_SIZE(x) ((x < YAC_SMM_MIN_BLOCK_SIZE)? (YAC_SMM_MIN_BLOCK_SIZE) : (YAC_SMM_ALIGNED_SIZE(x))) | |
36 | ||
37 | #ifdef PHP_WIN32 | |
38 | # define USE_FILE_MAPPING 1 | |
39 | # define inline __inline | |
40 | #elif defined(HAVE_SHM_MMAP_ANON) | |
41 | # define USE_MMAP 1 | |
42 | #elif defined(HAVE_SHM_IPC) | |
43 | # define USE_SHM 1 | |
44 | #else | |
45 | #error(no builtin shared memory supported) | |
46 | #endif | |
47 | ||
48 | #define ALLOC_FAILURE 0 | |
49 | #define ALLOC_SUCCESS 1 | |
50 | #define FAILED_REATTACHED 2 | |
51 | #define SUCCESSFULLY_REATTACHED 4 | |
52 | #define ALLOC_FAIL_MAPPING 8 | |
53 | ||
54 | typedef int (*create_segments_t)(unsigned long k_size, unsigned long v_size, yac_shared_segment **shared_segments, int *shared_segment_count, char **error_in); | |
55 | typedef int (*detach_segment_t)(yac_shared_segment *shared_segment); | |
56 | ||
57 | typedef struct { | |
58 | create_segments_t create_segments; | |
59 | detach_segment_t detach_segment; | |
60 | unsigned long (*segment_type_size)(void); | |
61 | } yac_shared_memory_handlers; | |
62 | ||
63 | typedef struct { | |
64 | const char *name; | |
65 | yac_shared_memory_handlers *handler; | |
66 | } yac_shared_memory_handler_entry; | |
67 | ||
68 | int yac_allocator_startup(unsigned long first_seg_size, unsigned long size, char **err); | |
69 | void yac_allocator_shutdown(void); | |
70 | unsigned long yac_allocator_real_size(unsigned long size); | |
71 | void *yac_allocator_raw_alloc(unsigned long real_size, int seg); | |
72 | int yac_allocator_free(void *p); | |
73 | ||
74 | static inline void * yac_allocator_alloc(unsigned long size, int seg) { | |
75 | unsigned long real_size = yac_allocator_real_size(size); | |
76 | if (!real_size) { | |
77 | return (void *)0; | |
78 | } | |
79 | return yac_allocator_raw_alloc(real_size, seg); | |
80 | } | |
81 | ||
82 | #if defined(USE_MMAP) | |
83 | extern yac_shared_memory_handlers yac_alloc_mmap_handlers; | |
84 | #define yac_shared_memory_handler yac_alloc_mmap_handlers | |
85 | #define YAC_SHARED_MEMORY_HANDLER_NAME "mmap" | |
86 | #elif defined(USE_SHM) | |
87 | extern yac_shared_memory_handlers yac_alloc_shm_handlers; | |
88 | #define yac_shared_memory_handler yac_alloc_shm_handlers | |
89 | #define YAC_SHARED_MEMORY_HANDLER_NAME "shm" | |
90 | #elif defined(USE_FILE_MAPPING) | |
91 | extern yac_shared_memory_handlers yac_alloc_create_file_handlers; | |
92 | #define yac_shared_memory_handler yac_alloc_create_file_handlers | |
93 | #define YAC_SHARED_MEMORY_HANDLER_NAME "file_mapping" | |
94 | #endif | |
95 | ||
96 | #endif /* YAC_ALLOCATOR_H */ |
0 | /* | |
1 | +----------------------------------------------------------------------+ | |
2 | | Yet Another Cache | | |
3 | +----------------------------------------------------------------------+ | |
4 | | Copyright (c) 2013-2013 The PHP Group | | |
5 | +----------------------------------------------------------------------+ | |
6 | | This source file is subject to version 3.01 of the PHP license, | | |
7 | | that is bundled with this package in the file LICENSE, and is | | |
8 | | available through the world-wide-web at the following url: | | |
9 | | http://www.php.net/license/3_01.txt | | |
10 | | If you did not receive a copy of the PHP license and are unable to | | |
11 | | obtain it through the world-wide-web, please send a note to | | |
12 | | license@php.net so we can mail you a copy immediately. | | |
13 | +----------------------------------------------------------------------+ | |
14 | | Author: Xinchen Hui <laruence@php.net> | | |
15 | +----------------------------------------------------------------------+ | |
16 | */ | |
17 | ||
18 | /* $Id$ */ | |
19 | ||
20 | #include "php.h" | |
21 | #include "yac_storage.h" | |
22 | #include "allocator/yac_allocator.h" | |
23 | ||
24 | yac_storage_globals *yac_storage; | |
25 | ||
26 | static inline unsigned int yac_storage_align_size(unsigned int size) /* {{{ */ { | |
27 | int bits = 0; | |
28 | while ((size = size >> 1)) { | |
29 | ++bits; | |
30 | } | |
31 | return (1 << bits); | |
32 | } | |
33 | /* }}} */ | |
34 | ||
35 | int yac_storage_startup(unsigned long fsize, unsigned long size, char **msg) /* {{{ */ { | |
36 | unsigned long real_size; | |
37 | ||
38 | if (!yac_allocator_startup(fsize, size, msg)) { | |
39 | return 0; | |
40 | } | |
41 | ||
42 | size = YAC_SG(first_seg).size - ((char *)YAC_SG(slots) - (char *)yac_storage); | |
43 | real_size = yac_storage_align_size(size / sizeof(yac_kv_key)); | |
44 | if (!((size / sizeof(yac_kv_key)) & ~(real_size << 1))) { | |
45 | real_size <<= 1; | |
46 | } | |
47 | ||
48 | YAC_SG(slots_size) = real_size; | |
49 | YAC_SG(slots_mask) = real_size - 1; | |
50 | YAC_SG(slots_num) = 0; | |
51 | YAC_SG(fails) = 0; | |
52 | YAC_SG(hits) = 0; | |
53 | YAC_SG(miss) = 0; | |
54 | YAC_SG(kicks) = 0; | |
55 | ||
56 | memset((char *)YAC_SG(slots), 0, sizeof(yac_kv_key) * real_size); | |
57 | ||
58 | return 1; | |
59 | } | |
60 | /* }}} */ | |
61 | ||
62 | void yac_storage_shutdown(void) /* {{{ */ { | |
63 | yac_allocator_shutdown(); | |
64 | } | |
65 | /* }}} */ | |
66 | ||
67 | /* {{{ MurmurHash2 (Austin Appleby) | |
68 | */ | |
69 | static inline ulong yac_inline_hash_func1(char *data, unsigned int len) { | |
70 | unsigned int h, k; | |
71 | ||
72 | h = 0 ^ len; | |
73 | ||
74 | while (len >= 4) { | |
75 | k = data[0]; | |
76 | k |= data[1] << 8; | |
77 | k |= data[2] << 16; | |
78 | k |= data[3] << 24; | |
79 | ||
80 | k *= 0x5bd1e995; | |
81 | k ^= k >> 24; | |
82 | k *= 0x5bd1e995; | |
83 | ||
84 | h *= 0x5bd1e995; | |
85 | h ^= k; | |
86 | ||
87 | data += 4; | |
88 | len -= 4; | |
89 | } | |
90 | ||
91 | switch (len) { | |
92 | case 3: | |
93 | h ^= data[2] << 16; | |
94 | case 2: | |
95 | h ^= data[1] << 8; | |
96 | case 1: | |
97 | h ^= data[0]; | |
98 | h *= 0x5bd1e995; | |
99 | } | |
100 | ||
101 | h ^= h >> 13; | |
102 | h *= 0x5bd1e995; | |
103 | h ^= h >> 15; | |
104 | ||
105 | return h; | |
106 | } | |
107 | /* }}} */ | |
108 | ||
109 | /* {{{ DJBX33A (Daniel J. Bernstein, Times 33 with Addition) | |
110 | * | |
111 | * This is Daniel J. Bernstein's popular `times 33' hash function as | |
112 | * posted by him years ago on comp->lang.c. It basically uses a function | |
113 | * like ``hash(i) = hash(i-1) * 33 + str[i]''. This is one of the best | |
114 | * known hash functions for strings. Because it is both computed very | |
115 | * fast and distributes very well. | |
116 | * | |
117 | * The magic of number 33, i.e. why it works better than many other | |
118 | * constants, prime or not, has never been adequately explained by | |
119 | * anyone. So I try an explanation: if one experimentally tests all | |
120 | * multipliers between 1 and 256 (as RSE did now) one detects that even | |
121 | * numbers are not useable at all. The remaining 128 odd numbers | |
122 | * (except for the number 1) work more or less all equally well. They | |
123 | * all distribute in an acceptable way and this way fill a hash table | |
124 | * with an average percent of approx. 86%. | |
125 | * | |
126 | * If one compares the Chi^2 values of the variants, the number 33 not | |
127 | * even has the best value. But the number 33 and a few other equally | |
128 | * good numbers like 17, 31, 63, 127 and 129 have nevertheless a great | |
129 | * advantage to the remaining numbers in the large set of possible | |
130 | * multipliers: their multiply operation can be replaced by a faster | |
131 | * operation based on just one shift plus either a single addition | |
132 | * or subtraction operation. And because a hash function has to both | |
133 | * distribute good _and_ has to be very fast to compute, those few | |
134 | * numbers should be preferred and seems to be the reason why Daniel J. | |
135 | * Bernstein also preferred it. | |
136 | * | |
137 | * | |
138 | * -- Ralf S. Engelschall <rse@engelschall.com> | |
139 | */ | |
140 | ||
141 | static inline ulong yac_inline_hash_func2(char *key, uint len) { | |
142 | register ulong hash = 5381; | |
143 | ||
144 | /* variant with the hash unrolled eight times */ | |
145 | for (; len >= 8; len -= 8) { | |
146 | hash = ((hash << 5) + hash) + *key++; | |
147 | hash = ((hash << 5) + hash) + *key++; | |
148 | hash = ((hash << 5) + hash) + *key++; | |
149 | hash = ((hash << 5) + hash) + *key++; | |
150 | hash = ((hash << 5) + hash) + *key++; | |
151 | hash = ((hash << 5) + hash) + *key++; | |
152 | hash = ((hash << 5) + hash) + *key++; | |
153 | hash = ((hash << 5) + hash) + *key++; | |
154 | } | |
155 | switch (len) { | |
156 | case 7: hash = ((hash << 5) + hash) + *key++; /* fallthrough... */ | |
157 | case 6: hash = ((hash << 5) + hash) + *key++; /* fallthrough... */ | |
158 | case 5: hash = ((hash << 5) + hash) + *key++; /* fallthrough... */ | |
159 | case 4: hash = ((hash << 5) + hash) + *key++; /* fallthrough... */ | |
160 | case 3: hash = ((hash << 5) + hash) + *key++; /* fallthrough... */ | |
161 | case 2: hash = ((hash << 5) + hash) + *key++; /* fallthrough... */ | |
162 | case 1: hash = ((hash << 5) + hash) + *key++; break; | |
163 | case 0: break; | |
164 | default: break; | |
165 | } | |
166 | return hash; | |
167 | } | |
168 | /* }}} */ | |
169 | ||
170 | /* {{{ COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or | |
171 | * code or tables extracted from it, as desired without restriction. | |
172 | * | |
173 | * First, the polynomial itself and its table of feedback terms. The | |
174 | * polynomial is | |
175 | * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 | |
176 | * | |
177 | * Note that we take it "backwards" and put the highest-order term in | |
178 | * the lowest-order bit. The X^32 term is "implied"; the LSB is the | |
179 | * X^31 term, etc. The X^0 term (usually shown as "+1") results in | |
180 | * the MSB being 1 | |
181 | * | |
182 | * Note that the usual hardware shift register implementation, which | |
183 | * is what we're using (we're merely optimizing it by doing eight-bit | |
184 | * chunks at a time) shifts bits into the lowest-order term. In our | |
185 | * implementation, that means shifting towards the right. Why do we | |
186 | * do it this way? Because the calculated CRC must be transmitted in | |
187 | * order from highest-order term to lowest-order term. UARTs transmit | |
188 | * characters in order from LSB to MSB. By storing the CRC this way | |
189 | * we hand it to the UART in the order low-byte to high-byte; the UART | |
190 | * sends each low-bit to hight-bit; and the result is transmission bit | |
191 | * by bit from highest- to lowest-order term without requiring any bit | |
192 | * shuffling on our part. Reception works similarly | |
193 | * | |
194 | * The feedback terms table consists of 256, 32-bit entries. Notes | |
195 | * | |
196 | * The table can be generated at runtime if desired; code to do so | |
197 | * is shown later. It might not be obvious, but the feedback | |
198 | * terms simply represent the results of eight shift/xor opera | |
199 | * tions for all combinations of data and CRC register values | |
200 | * | |
201 | * The values must be right-shifted by eight bits by the "updcrc | |
202 | * logic; the shift must be unsigned (bring in zeroes). On some | |
203 | * hardware you could probably optimize the shift in assembler by | |
204 | * using byte-swap instructions | |
205 | * polynomial $edb88320 | |
206 | * | |
207 | * | |
208 | * CRC32 code derived from work by Gary S. Brown. | |
209 | */ | |
210 | ||
211 | static unsigned int crc32_tab[] = { | |
212 | 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, | |
213 | 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, | |
214 | 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, | |
215 | 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, | |
216 | 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, | |
217 | 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, | |
218 | 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, | |
219 | 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, | |
220 | 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, | |
221 | 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, | |
222 | 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, | |
223 | 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, | |
224 | 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, | |
225 | 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, | |
226 | 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, | |
227 | 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, | |
228 | 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, | |
229 | 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, | |
230 | 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, | |
231 | 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, | |
232 | 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, | |
233 | 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, | |
234 | 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, | |
235 | 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, | |
236 | 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, | |
237 | 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, | |
238 | 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, | |
239 | 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, | |
240 | 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, | |
241 | 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, | |
242 | 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, | |
243 | 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, | |
244 | 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, | |
245 | 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, | |
246 | 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, | |
247 | 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, | |
248 | 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, | |
249 | 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, | |
250 | 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, | |
251 | 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, | |
252 | 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, | |
253 | 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, | |
254 | 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d | |
255 | }; | |
256 | ||
257 | static inline unsigned int crc32(char *buf, unsigned int size) { | |
258 | const char *p; | |
259 | register int crc = 0; | |
260 | ||
261 | p = buf; | |
262 | while (size--) { | |
263 | crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); | |
264 | } | |
265 | ||
266 | return crc ^ ~0U; | |
267 | } | |
268 | /* }}} */ | |
269 | ||
270 | static inline unsigned int yac_crc32(char *data, unsigned int size) /* {{{ */ { | |
271 | if (size < YAC_FULL_CRC_THRESHOLD) { | |
272 | return crc32(data, size); | |
273 | } else { | |
274 | int i = 0; | |
275 | char crc_contents[YAC_FULL_CRC_THRESHOLD]; | |
276 | int head = YAC_FULL_CRC_THRESHOLD >> 2; | |
277 | int tail = YAC_FULL_CRC_THRESHOLD >> 4; | |
278 | int body = YAC_FULL_CRC_THRESHOLD - head - tail; | |
279 | char *p = data + head; | |
280 | char *q = crc_contents + head; | |
281 | int step = (size - tail - head) / body; | |
282 | ||
283 | memcpy(crc_contents, data, head); | |
284 | for (; i < body; i++, q++, p+= step) { | |
285 | *q = *p; | |
286 | } | |
287 | memcpy(q, p, tail); | |
288 | ||
289 | return crc32(crc_contents, YAC_FULL_CRC_THRESHOLD); | |
290 | } | |
291 | } | |
292 | /* }}} */ | |
293 | ||
294 | int yac_storage_find(char *key, unsigned int len, char **data, unsigned int *size, unsigned int *flag, int *cas, unsigned long tv) /* {{{ */ { | |
295 | ulong h, hash, seed; | |
296 | yac_kv_key k, *p; | |
297 | yac_kv_val v; | |
298 | ||
299 | hash = h = yac_inline_hash_func1(key, len); | |
300 | p = &(YAC_SG(slots)[h & YAC_SG(slots_mask)]); | |
301 | k = *p; | |
302 | if (k.val) { | |
303 | char *s; | |
304 | uint i; | |
305 | if (k.h == hash && YAC_KEY_KLEN(k) == len) { | |
306 | v = *(k.val); | |
307 | if (!memcmp(k.key, key, len)) { | |
308 | s = USER_ALLOC(YAC_KEY_VLEN(k) + 1); | |
309 | memcpy(s, (char *)k.val->data, YAC_KEY_VLEN(k)); | |
310 | do_verify: | |
311 | if (k.len != v.len) { | |
312 | USER_FREE(s); | |
313 | ++YAC_SG(miss); | |
314 | return 0; | |
315 | } | |
316 | ||
317 | if (k.ttl) { | |
318 | if (k.ttl <= tv) { | |
319 | ++YAC_SG(miss); | |
320 | USER_FREE(s); | |
321 | return 0; | |
322 | } | |
323 | } | |
324 | ||
325 | if (k.crc != yac_crc32(s, YAC_KEY_VLEN(k))) { | |
326 | USER_FREE(s); | |
327 | ++YAC_SG(miss); | |
328 | return 0; | |
329 | } | |
330 | s[YAC_KEY_VLEN(k)] = '\0'; | |
331 | k.val->atime = tv; | |
332 | *data = s; | |
333 | *size = YAC_KEY_VLEN(k); | |
334 | *flag = k.flag; | |
335 | ++YAC_SG(hits); | |
336 | return 1; | |
337 | } | |
338 | } | |
339 | ||
340 | seed = yac_inline_hash_func2(key, len); | |
341 | for (i = 0; i < 3; i++) { | |
342 | h += seed & YAC_SG(slots_mask); | |
343 | p = &(YAC_SG(slots)[h & YAC_SG(slots_mask)]); | |
344 | k = *p; | |
345 | if (k.h == hash && YAC_KEY_KLEN(k) == len) { | |
346 | v = *(k.val); | |
347 | if (!memcmp(k.key, key, len)) { | |
348 | s = USER_ALLOC(YAC_KEY_VLEN(k) + 1); | |
349 | memcpy(s, (char *)k.val->data, YAC_KEY_VLEN(k)); | |
350 | goto do_verify; | |
351 | } | |
352 | } | |
353 | } | |
354 | } | |
355 | ||
356 | ++YAC_SG(miss); | |
357 | ||
358 | return 0; | |
359 | } | |
360 | /* }}} */ | |
361 | ||
362 | void yac_storage_delete(char *key, unsigned int len, int ttl, unsigned long tv) /* {{{ */ { | |
363 | ulong hash, h, seed; | |
364 | yac_kv_key k, *p; | |
365 | ||
366 | hash = h = yac_inline_hash_func1(key, len); | |
367 | p = &(YAC_SG(slots)[h & YAC_SG(slots_mask)]); | |
368 | k = *p; | |
369 | if (k.val) { | |
370 | uint i; | |
371 | if (k.h == hash && YAC_KEY_KLEN(k) == len) { | |
372 | if (!memcmp((char *)k.key, key, len)) { | |
373 | if (ttl == 0) { | |
374 | p->ttl = 1; | |
375 | } else { | |
376 | p->ttl = ttl + tv; | |
377 | } | |
378 | return; | |
379 | } | |
380 | } | |
381 | ||
382 | seed = yac_inline_hash_func2(key, len); | |
383 | for (i = 0; i < 3; i++) { | |
384 | h += seed & YAC_SG(slots_mask); | |
385 | p = &(YAC_SG(slots)[h & YAC_SG(slots_mask)]); | |
386 | k = *p; | |
387 | if (k.val == NULL) { | |
388 | return; | |
389 | } else if (k.h == hash && YAC_KEY_KLEN(k) == len && !memcmp((char *)k.key, key, len)) { | |
390 | p->ttl = 1; | |
391 | return; | |
392 | } | |
393 | } | |
394 | } | |
395 | } | |
396 | /* }}} */ | |
397 | ||
398 | int yac_storage_update(char *key, unsigned int len, char *data, unsigned int size, unsigned int flag, int ttl, int add, unsigned long tv) /* {{{ */ { | |
399 | ulong hash, h; | |
400 | int idx = 0, is_valid; | |
401 | yac_kv_key *p, k, *paths[4]; | |
402 | yac_kv_val *val, *s; | |
403 | unsigned long real_size; | |
404 | ||
405 | hash = h = yac_inline_hash_func1(key, len); | |
406 | paths[idx++] = p = &(YAC_SG(slots)[h & YAC_SG(slots_mask)]); | |
407 | k = *p; | |
408 | if (k.val) { | |
409 | /* Found the exact match */ | |
410 | if (k.h == hash && YAC_KEY_KLEN(k) == len && !memcmp((char *)k.key, key, len)) { | |
411 | do_update: | |
412 | is_valid = 0; | |
413 | if (k.crc == yac_crc32(k.val->data, YAC_KEY_VLEN(k))) { | |
414 | is_valid = 1; | |
415 | } | |
416 | if (add && (!k.ttl || k.ttl > tv) && is_valid) { | |
417 | return 0; | |
418 | } | |
419 | if (k.size >= size && is_valid) { | |
420 | s = USER_ALLOC(sizeof(yac_kv_val) + size - 1); | |
421 | memcpy(s->data, data, size); | |
422 | if (ttl) { | |
423 | k.ttl = (ulong)tv + ttl; | |
424 | } else { | |
425 | k.ttl = 0; | |
426 | } | |
427 | s->atime = tv; | |
428 | YAC_KEY_SET_LEN(*s, len, size); | |
429 | memcpy((char *)k.val, (char *)s, sizeof(yac_kv_val) + size - 1); | |
430 | k.crc = yac_crc32(s->data, size); | |
431 | k.flag = flag; | |
432 | memcpy(k.key, key, len); | |
433 | YAC_KEY_SET_LEN(k, len, size); | |
434 | *p = k; | |
435 | USER_FREE(s); | |
436 | return 1; | |
437 | } else { | |
438 | uint msize; | |
439 | real_size = yac_allocator_real_size(sizeof(yac_kv_val) + (size * YAC_STORAGE_FACTOR) - 1); | |
440 | if (!real_size) { | |
441 | ++YAC_SG(fails); | |
442 | return 0; | |
443 | } | |
444 | msize = sizeof(yac_kv_val) + size - 1; | |
445 | s = USER_ALLOC(sizeof(yac_kv_val) + size - 1); | |
446 | memcpy(s->data, data, size); | |
447 | s->atime = tv; | |
448 | YAC_KEY_SET_LEN(*s, len, size); | |
449 | val = yac_allocator_raw_alloc(real_size, (int)hash); | |
450 | if (val) { | |
451 | memcpy((char *)val, (char *)s, msize); | |
452 | if (ttl) { | |
453 | k.ttl = tv + ttl; | |
454 | } else { | |
455 | k.ttl = 0; | |
456 | } | |
457 | k.crc = yac_crc32(s->data, size); | |
458 | k.val = val; | |
459 | k.flag = flag; | |
460 | k.size = real_size; | |
461 | memcpy(k.key, key, len); | |
462 | YAC_KEY_SET_LEN(k, len, size); | |
463 | *p = k; | |
464 | USER_FREE(s); | |
465 | return 1; | |
466 | } | |
467 | ++YAC_SG(fails); | |
468 | USER_FREE(s); | |
469 | return 0; | |
470 | } | |
471 | } else { | |
472 | uint i; | |
473 | ulong seed, max_atime; | |
474 | ||
475 | seed = yac_inline_hash_func2(key, len); | |
476 | for (i = 0; i < 3; i++) { | |
477 | h += seed & YAC_SG(slots_mask); | |
478 | paths[idx++] = p = &(YAC_SG(slots)[h & YAC_SG(slots_mask)]); | |
479 | k = *p; | |
480 | if (k.val == NULL) { | |
481 | goto do_add; | |
482 | } else if (k.h == hash && YAC_KEY_KLEN(k) == len && !memcmp((char *)k.key, key, len)) { | |
483 | /* Found the exact match */ | |
484 | goto do_update; | |
485 | } | |
486 | } | |
487 | ||
488 | --idx; | |
489 | max_atime = paths[idx]->val->atime; | |
490 | for (i = 0; i < idx; i++) { | |
491 | if ((paths[i]->ttl && paths[i]->ttl <= tv) || paths[i]->len != paths[i]->val->len) { | |
492 | p = paths[i]; | |
493 | goto do_add; | |
494 | } else if (paths[i]->val->atime < max_atime) { | |
495 | max_atime = paths[i]->val->atime; | |
496 | p = paths[i]; | |
497 | } | |
498 | } | |
499 | ++YAC_SG(kicks); | |
500 | k = *p; | |
501 | k.h = hash; | |
502 | ||
503 | goto do_update; | |
504 | } | |
505 | } else { | |
506 | do_add: | |
507 | real_size = yac_allocator_real_size(sizeof(yac_kv_val) + (size * YAC_STORAGE_FACTOR) - 1); | |
508 | if (!real_size) { | |
509 | ++YAC_SG(fails); | |
510 | return 0; | |
511 | } | |
512 | s = USER_ALLOC(sizeof(yac_kv_val) + size - 1); | |
513 | memcpy(s->data, data, size); | |
514 | s->atime = tv; | |
515 | YAC_KEY_SET_LEN(*s, len, size); | |
516 | val = yac_allocator_raw_alloc(real_size, (int)hash); | |
517 | if (val) { | |
518 | memcpy((char *)val, (char *)s, sizeof(yac_kv_val) + size - 1); | |
519 | if (p->val == NULL) { | |
520 | ++YAC_SG(slots_num); | |
521 | } | |
522 | k.h = hash; | |
523 | k.val = val; | |
524 | k.flag = flag; | |
525 | k.size = real_size; | |
526 | k.crc = yac_crc32(s->data, size); | |
527 | memcpy(k.key, key, len); | |
528 | YAC_KEY_SET_LEN(k, len, size); | |
529 | if (ttl) { | |
530 | k.ttl = tv + ttl; | |
531 | } else { | |
532 | k.ttl = 0; | |
533 | } | |
534 | *p = k; | |
535 | USER_FREE(s); | |
536 | return 1; | |
537 | } | |
538 | ++YAC_SG(fails); | |
539 | USER_FREE(s); | |
540 | } | |
541 | ||
542 | return 0; | |
543 | } | |
544 | /* }}} */ | |
545 | ||
546 | void yac_storage_flush(void) /* {{{ */ { | |
547 | YAC_SG(slots_num) = 0; | |
548 | memset((char *)YAC_SG(slots), 0, sizeof(yac_kv_key) * YAC_SG(slots_size)); | |
549 | } | |
550 | /* }}} */ | |
551 | ||
552 | yac_storage_info * yac_storage_get_info(void) /* {{{ */ { | |
553 | yac_storage_info *info = USER_ALLOC(sizeof(yac_storage_info)); | |
554 | ||
555 | info->k_msize = (unsigned long)YAC_SG(first_seg).size; | |
556 | info->v_msize = (unsigned long)YAC_SG(segments)[0]->size * (unsigned long)YAC_SG(segments_num); | |
557 | info->segment_size = YAC_SG(segments)[0]->size; | |
558 | info->segments_num = YAC_SG(segments_num); | |
559 | info->hits = YAC_SG(hits); | |
560 | info->miss = YAC_SG(miss); | |
561 | info->fails = YAC_SG(fails); | |
562 | info->kicks = YAC_SG(kicks); | |
563 | info->recycles = YAC_SG(recycles); | |
564 | info->slots_size = YAC_SG(slots_size); | |
565 | info->slots_num = YAC_SG(slots_num); | |
566 | ||
567 | return info; | |
568 | } | |
569 | /* }}} */ | |
570 | ||
571 | void yac_storage_free_info(yac_storage_info *info) /* {{{ */ { | |
572 | USER_FREE(info); | |
573 | } | |
574 | /* }}} */ | |
575 | ||
576 | yac_item_list * yac_storage_dump(unsigned int limit) /* {{{ */ { | |
577 | yac_kv_key k; | |
578 | yac_item_list *item, *list = NULL; | |
579 | ||
580 | if (YAC_SG(slots_num)) { | |
581 | unsigned int i = 0, n = 0; | |
582 | for (; i<YAC_SG(slots_size) && n < YAC_SG(slots_num) && n < limit; i++) { | |
583 | k = YAC_SG(slots)[i]; | |
584 | if (k.val) { | |
585 | item = USER_ALLOC(sizeof(yac_item_list)); | |
586 | item->index = i; | |
587 | item->h = k.h; | |
588 | item->crc = k.crc; | |
589 | item->ttl = k.ttl; | |
590 | item->k_len = YAC_KEY_KLEN(k); | |
591 | item->v_len = YAC_KEY_VLEN(k); | |
592 | item->flag = k.flag; | |
593 | item->size = k.size; | |
594 | memcpy(item->key, k.key, YAC_STORAGE_MAX_KEY_LEN); | |
595 | item->next = list; | |
596 | list = item; | |
597 | ++n; | |
598 | } | |
599 | } | |
600 | } | |
601 | ||
602 | return list; | |
603 | } | |
604 | /* }}} */ | |
605 | ||
606 | void yac_storage_free_list(yac_item_list *list) /* {{{ */ { | |
607 | yac_item_list *l; | |
608 | while (list) { | |
609 | l = list; | |
610 | list = list->next; | |
611 | USER_FREE(l); | |
612 | } | |
613 | } | |
614 | /* }}} */ | |
615 | ||
616 | const char * yac_storage_shared_memory_name(void) /* {{{ */ { | |
617 | return YAC_SHARED_MEMORY_HANDLER_NAME; | |
618 | } | |
619 | /* }}} */ | |
620 | ||
621 | /* | |
622 | * Local variables: | |
623 | * tab-width: 4 | |
624 | * c-basic-offset: 4 | |
625 | * End: | |
626 | * vim600: noet sw=4 ts=4 fdm=marker | |
627 | * vim<600: noet sw=4 ts=4 | |
628 | */ |
0 | /* | |
1 | +----------------------------------------------------------------------+ | |
2 | | Yet Another Cache | | |
3 | +----------------------------------------------------------------------+ | |
4 | | Copyright (c) 2013-2013 The PHP Group | | |
5 | +----------------------------------------------------------------------+ | |
6 | | This source file is subject to version 3.01 of the PHP license, | | |
7 | | that is bundled with this package in the file LICENSE, and is | | |
8 | | available through the world-wide-web at the following url: | | |
9 | | http://www.php.net/license/3_01.txt | | |
10 | | If you did not receive a copy of the PHP license and are unable to | | |
11 | | obtain it through the world-wide-web, please send a note to | | |
12 | | license@php.net so we can mail you a copy immediately. | | |
13 | +----------------------------------------------------------------------+ | |
14 | | Author: Xinchen Hui <laruence@php.net> | | |
15 | +----------------------------------------------------------------------+ | |
16 | */ | |
17 | ||
18 | /* $Id$ */ | |
19 | ||
20 | #ifndef YAC_STORAGE_H | |
21 | #define YAC_STORAGE_H | |
22 | ||
23 | #define YAC_STORAGE_MAX_ENTRY_LEN (1 << 20) | |
24 | #define YAC_STORAGE_MAX_KEY_LEN (48) | |
25 | #define YAC_STORAGE_FACTOR (1.25) | |
26 | #define YAC_KEY_KLEN_MASK (255) | |
27 | #define YAC_KEY_VLEN_BITS (8) | |
28 | #define YAC_KEY_KLEN(k) ((k).len & YAC_KEY_KLEN_MASK) | |
29 | #define YAC_KEY_VLEN(k) ((k).len >> YAC_KEY_VLEN_BITS) | |
30 | #define YAC_KEY_SET_LEN(k, kl, vl) ((k).len = (vl << YAC_KEY_VLEN_BITS) | (kl & YAC_KEY_KLEN_MASK)) | |
31 | #define YAC_FULL_CRC_THRESHOLD 256 | |
32 | ||
33 | #define USER_ALLOC emalloc | |
34 | #define USER_FREE efree | |
35 | ||
36 | typedef struct { | |
37 | unsigned long atime; | |
38 | unsigned int len; | |
39 | char data[1]; | |
40 | } yac_kv_val; | |
41 | ||
42 | typedef struct { | |
43 | unsigned long h; | |
44 | unsigned long crc; | |
45 | unsigned int ttl; | |
46 | unsigned int len; | |
47 | unsigned int flag; | |
48 | unsigned int size; | |
49 | yac_kv_val *val; | |
50 | unsigned char key[YAC_STORAGE_MAX_KEY_LEN]; | |
51 | } yac_kv_key; | |
52 | ||
53 | typedef struct _yac_item_list { | |
54 | unsigned int index; | |
55 | unsigned long h; | |
56 | unsigned long crc; | |
57 | unsigned int ttl; | |
58 | unsigned int k_len; | |
59 | unsigned int v_len; | |
60 | unsigned int flag; | |
61 | unsigned int size; | |
62 | unsigned char key[YAC_STORAGE_MAX_KEY_LEN]; | |
63 | struct _yac_item_list *next; | |
64 | } yac_item_list; | |
65 | ||
66 | typedef struct { | |
67 | volatile unsigned int pos; | |
68 | unsigned int size; | |
69 | void *p; | |
70 | } yac_shared_segment; | |
71 | ||
72 | typedef struct { | |
73 | unsigned long k_msize; | |
74 | unsigned long v_msize; | |
75 | unsigned int segments_num; | |
76 | unsigned int segment_size; | |
77 | unsigned int slots_num; | |
78 | unsigned int slots_size; | |
79 | unsigned int miss; | |
80 | unsigned int fails; | |
81 | unsigned int kicks; | |
82 | unsigned int recycles; | |
83 | unsigned long hits; | |
84 | } yac_storage_info; | |
85 | ||
86 | typedef struct { | |
87 | yac_kv_key *slots; | |
88 | unsigned int slots_mask; | |
89 | unsigned int slots_num; | |
90 | unsigned int slots_size; | |
91 | unsigned int miss; | |
92 | unsigned int fails; | |
93 | unsigned int kicks; | |
94 | unsigned int recycles; | |
95 | unsigned long hits; | |
96 | yac_shared_segment **segments; | |
97 | unsigned int segments_num; | |
98 | unsigned int segments_num_mask; | |
99 | yac_shared_segment first_seg; | |
100 | } yac_storage_globals; | |
101 | ||
102 | extern yac_storage_globals *yac_storage; | |
103 | ||
104 | #define YAC_SG(element) (yac_storage->element) | |
105 | ||
106 | int yac_storage_startup(unsigned long first_size, unsigned long size, char **err); | |
107 | void yac_storage_shutdown(void); | |
108 | int yac_storage_find(char *key, unsigned int len, char **data, unsigned int *size, unsigned int *flag, int *cas, unsigned long tv); | |
109 | int yac_storage_update(char *key, unsigned int len, char *data, unsigned int size, unsigned int falg, int ttl, int add, unsigned long tv); | |
110 | void yac_storage_delete(char *key, unsigned int len, int ttl, unsigned long tv); | |
111 | void yac_storage_flush(void); | |
112 | const char * yac_storage_shared_memory_name(void); | |
113 | yac_storage_info * yac_storage_get_info(void); | |
114 | void yac_storage_free_info(yac_storage_info *info); | |
115 | yac_item_list * yac_storage_dump(unsigned int limit); | |
116 | void yac_storage_free_list(yac_item_list *list); | |
117 | #define yac_storage_exists(ht, key, len) yac_storage_find(ht, key, len, NULL) | |
118 | ||
119 | #endif /* YAC_STORAGE_H */ | |
120 | ||
121 | /* | |
122 | * Local variables: | |
123 | * tab-width: 4 | |
124 | * c-basic-offset: 4 | |
125 | * End: | |
126 | * vim600: noet sw=4 ts=4 fdm=marker | |
127 | * vim<600: noet sw=4 ts=4 | |
128 | */ |
0 | --TEST-- | |
1 | Check for yac presence | |
2 | --SKIPIF-- | |
3 | <?php if (!extension_loaded("yac")) print "skip"; ?> | |
4 | --FILE-- | |
5 | <?php | |
6 | echo "yac extension is available"; | |
7 | /* | |
8 | you can add regression tests for your extension here | |
9 | ||
10 | the output of your test code has to be equal to the | |
11 | text in the --EXPECT-- section below for the tests | |
12 | to pass, differences between the output and the | |
13 | expected text are interpreted as failure | |
14 | ||
15 | see php5/README.TESTING for further information on | |
16 | writing regression tests | |
17 | */ | |
18 | ?> | |
19 | --EXPECT-- | |
20 | yac extension is available |
0 | --TEST-- | |
1 | Check for yac basic functions | |
2 | --SKIPIF-- | |
3 | <?php if (!extension_loaded("yac")) print "skip"; ?> | |
4 | <?php if (YAC_SERIALIZER != "PHP") print "skip"; ?> | |
5 | --INI-- | |
6 | yac.enable=1 | |
7 | yac.enable_cli=1 | |
8 | yac.keys_memory_size=4M | |
9 | yac.values_memory_size=32M | |
10 | --FILE-- | |
11 | <?php | |
12 | $yac = new Yac(); | |
13 | ||
14 | $key = "foo"; | |
15 | $value = "dummy"; | |
16 | ||
17 | var_dump($yac->set($key, $value)); | |
18 | var_dump($yac->get($key)); | |
19 | ||
20 | $value = NULL; | |
21 | var_dump($yac->set($key, $value)); | |
22 | var_dump($yac->get($key)); | |
23 | ||
24 | $value = TRUE; | |
25 | var_dump($yac->set($key, $value)); | |
26 | var_dump($yac->get($key)); | |
27 | ||
28 | $value = FALSE; | |
29 | var_dump($yac->set($key, $value)); | |
30 | var_dump($yac->get($key)); | |
31 | ||
32 | $value = range(1, 5); | |
33 | var_dump($yac->set($key, $value)); | |
34 | var_dump($yac->get($key)); | |
35 | ||
36 | $value = 9234324; | |
37 | var_dump($yac->set($key, $value)); | |
38 | var_dump($yac->get($key)); | |
39 | ||
40 | $value = 9234324.123456; | |
41 | var_dump($yac->set($key, $value)); | |
42 | var_dump($yac->get($key)); | |
43 | ||
44 | $value = new StdClass();; | |
45 | var_dump($yac->set($key, $value)); | |
46 | var_dump($yac->get($key)); | |
47 | ||
48 | $value = fopen("php://input", "r"); | |
49 | var_dump($yac->set($key, $value)); | |
50 | ||
51 | $value = range(1, 5); | |
52 | var_dump($yac->set($key, $value)); | |
53 | var_dump($yac->delete($key)); | |
54 | var_dump($yac->get($key)); | |
55 | ||
56 | ?> | |
57 | --EXPECTF-- | |
58 | bool(true) | |
59 | string(5) "dummy" | |
60 | bool(true) | |
61 | NULL | |
62 | bool(true) | |
63 | bool(true) | |
64 | bool(true) | |
65 | bool(false) | |
66 | bool(true) | |
67 | array(5) { | |
68 | [0]=> | |
69 | int(1) | |
70 | [1]=> | |
71 | int(2) | |
72 | [2]=> | |
73 | int(3) | |
74 | [3]=> | |
75 | int(4) | |
76 | [4]=> | |
77 | int(5) | |
78 | } | |
79 | bool(true) | |
80 | int(9234324) | |
81 | bool(true) | |
82 | float(9234324.123456) | |
83 | bool(true) | |
84 | object(stdClass)#3 (0) { | |
85 | } | |
86 | ||
87 | Warning: Yac::set(): Type 'IS_RESOURCE' cannot be stored in %s002.php on line %d | |
88 | bool(false) | |
89 | bool(true) | |
90 | bool(true) | |
91 | bool(false) |
0 | --TEST-- | |
1 | Check for yac errors | |
2 | --SKIPIF-- | |
3 | <?php if (!extension_loaded("yac")) print "skip"; ?> | |
4 | --INI-- | |
5 | yac.enable=1 | |
6 | yac.enable_cli=1 | |
7 | yac.keys_memory_size=4M | |
8 | yac.values_memory_size=32M | |
9 | --FILE-- | |
10 | <?php | |
11 | $yac = new Yac(); | |
12 | ||
13 | $key = str_repeat("k", YAC_MAX_KEY_LEN - 1); | |
14 | $value = NULL; | |
15 | ||
16 | var_dump($yac->set($key, $value)); | |
17 | var_dump($yac->get($key)); | |
18 | ||
19 | $key = str_repeat("k", YAC_MAX_KEY_LEN); | |
20 | var_dump($yac->set($key, $value)); | |
21 | var_dump($yac->get($key)); | |
22 | ||
23 | $key = str_repeat("k", YAC_MAX_KEY_LEN + 1); | |
24 | var_dump($yac->set($key, $value)); | |
25 | var_dump($yac->get($key)); | |
26 | ||
27 | $yac = new Yac("dummy"); | |
28 | var_dump($yac->set($key, $value)); | |
29 | var_dump($yac->get($key)); | |
30 | ?> | |
31 | --EXPECTF-- | |
32 | bool(true) | |
33 | NULL | |
34 | bool(true) | |
35 | NULL | |
36 | ||
37 | Warning: Yac::set(): Key can not be longer than 48 bytes in %s003.php on line %d | |
38 | bool(false) | |
39 | ||
40 | Warning: Yac::get(): Key can not be longer than 48 bytes in %s003.php on line %d | |
41 | bool(false) | |
42 | ||
43 | Warning: Yac::set(): Key(include prefix) can not be longer than 48 bytes in %s003.php on line %d | |
44 | bool(false) | |
45 | ||
46 | Warning: Yac::get(): Key(include prefix) can not be longer than 48 bytes in %s003.php on line %d | |
47 | bool(false) |
0 | --TEST-- | |
1 | Check for yac ttl | |
2 | --SKIPIF-- | |
3 | <?php if (!extension_loaded("yac")) print "skip"; ?> | |
4 | --INI-- | |
5 | yac.enable=1 | |
6 | yac.enable_cli=1 | |
7 | yac.keys_memory_size=4M | |
8 | yac.values_memory_size=32M | |
9 | --FILE-- | |
10 | <?php | |
11 | $yac = new Yac(); | |
12 | ||
13 | $key = "foo"; | |
14 | $value = "dummy"; | |
15 | ||
16 | var_dump($yac->set($key, $value, 1)); | |
17 | var_dump($yac->get($key)); | |
18 | sleep(1); | |
19 | var_dump($yac->get($key)); | |
20 | ||
21 | var_dump($yac->set($key, $value)); | |
22 | var_dump($yac->get($key)); | |
23 | var_dump($yac->delete($key, 1)); | |
24 | var_dump($yac->get($key)); | |
25 | sleep(1); | |
26 | var_dump($yac->get($key)); | |
27 | ||
28 | ?> | |
29 | --EXPECTF-- | |
30 | bool(true) | |
31 | string(5) "dummy" | |
32 | bool(false) | |
33 | bool(true) | |
34 | string(5) "dummy" | |
35 | bool(true) | |
36 | string(5) "dummy" | |
37 | bool(false) |
0 | --TEST-- | |
1 | Check for yac non-string key | |
2 | --SKIPIF-- | |
3 | <?php if (!extension_loaded("yac")) print "skip"; ?> | |
4 | --INI-- | |
5 | yac.enable=1 | |
6 | yac.enable_cli=1 | |
7 | yac.keys_memory_size=4M | |
8 | yac.values_memory_size=32M | |
9 | --FILE-- | |
10 | <?php | |
11 | $yac = new Yac(); | |
12 | ||
13 | $key = md5(12345); | |
14 | $value = "dummy"; | |
15 | ||
16 | var_dump($yac->set($key, $value, 1)); | |
17 | var_dump($yac->get($key)); | |
18 | ||
19 | $key = 12345.12345; | |
20 | var_dump($yac->set($key, $value, 1)); | |
21 | var_dump($yac->get($key)); | |
22 | ||
23 | $key = range(1, 2); | |
24 | var_dump($yac->set($key, $value, 1)); | |
25 | var_dump($yac->get($key)); | |
26 | ||
27 | $key = new StdClass(); | |
28 | var_dump($yac->set($key, $value, 1)); | |
29 | var_dump($yac->get($key)); | |
30 | ?> | |
31 | --EXPECTF-- | |
32 | bool(true) | |
33 | string(5) "dummy" | |
34 | bool(true) | |
35 | string(5) "dummy" | |
36 | bool(true) | |
37 | array(2) { | |
38 | [1]=> | |
39 | int(2) | |
40 | [2]=> | |
41 | bool(false) | |
42 | } | |
43 | ||
44 | Catchable fatal error: Object of class stdClass could not be converted to string in %s005.php on line %d |
0 | --TEST-- | |
1 | Check for yac multi set/get | |
2 | --SKIPIF-- | |
3 | <?php if (!extension_loaded("yac")) print "skip"; ?> | |
4 | --INI-- | |
5 | yac.enable=1 | |
6 | yac.enable_cli=1 | |
7 | yac.keys_memory_size=4M | |
8 | yac.values_memory_size=32M | |
9 | --FILE-- | |
10 | <?php | |
11 | ||
12 | $yac = new Yac(); | |
13 | ||
14 | for ($i = 0; $i<1000; $i++) { | |
15 | $key = "xxx" . rand(1, 100000); | |
16 | $value = str_repeat("a", rand(1, 100000)); | |
17 | ||
18 | if (!$yac->set($key, $value)) { | |
19 | var_dump($key, $value); | |
20 | var_dump("write " . $i); | |
21 | } | |
22 | ||
23 | if ($value != ($new = $yac->get($key))) { | |
24 | var_dump($new); | |
25 | var_dump("read " . $i); | |
26 | } | |
27 | } | |
28 | ||
29 | var_dump($i); | |
30 | --EXPECTF-- | |
31 | int(1000) |
0 | --TEST-- | |
1 | Check for yac info | |
2 | --SKIPIF-- | |
3 | <?php if (!extension_loaded("yac")) print "skip"; ?> | |
4 | --INI-- | |
5 | yac.enable=1 | |
6 | yac.enable_cli=1 | |
7 | yac.keys_memory_size=4M | |
8 | yac.values_memory_size=32M | |
9 | --FILE-- | |
10 | <?php | |
11 | ||
12 | $yac = new Yac(); | |
13 | ||
14 | for ($i = 0; $i<1000; $i++) { | |
15 | $key = "xxx" . rand(1, 1000); | |
16 | $value = str_repeat("a", rand(1, 100000)); | |
17 | ||
18 | if (!$yac->set($key, $value)) { | |
19 | var_dump($key, $value); | |
20 | var_dump("write " . $i); | |
21 | } | |
22 | ||
23 | if ($value != ($new = $yac->get($key))) { | |
24 | var_dump($new); | |
25 | var_dump("read " . $i); | |
26 | } | |
27 | } | |
28 | ||
29 | $info = $yac->info(); | |
30 | var_dump($info['slots_used'] <= 1000); | |
31 | var_dump($info['hits']); | |
32 | var_dump($info['miss']); | |
33 | var_dump($info['fails']); | |
34 | var_dump($info['kicks']); | |
35 | --EXPECTF-- | |
36 | bool(true) | |
37 | int(1000) | |
38 | int(0) | |
39 | int(0) | |
40 | int(0) |
0 | --TEST-- | |
1 | Check for yac prefix | |
2 | --SKIPIF-- | |
3 | <?php if (!extension_loaded("yac")) print "skip"; ?> | |
4 | --INI-- | |
5 | yac.enable=1 | |
6 | yac.enable_cli=1 | |
7 | yac.keys_memory_size=4M | |
8 | yac.values_memory_size=32M | |
9 | --FILE-- | |
10 | <?php | |
11 | $yac = new Yac("dummy_"); | |
12 | $yac2 = new Yac(); | |
13 | ||
14 | $key = "bar"; | |
15 | $value = true; | |
16 | ||
17 | $yac->set($key, $value); | |
18 | var_dump($yac->get($key)); //true | |
19 | var_dump($yac2->get($key)); //false | |
20 | var_dump($yac2->get("dummy_" . $key)); //true | |
21 | ||
22 | $yac2->delete($key); //fail | |
23 | var_dump($yac->get($key)); //true | |
24 | ||
25 | $yac->delete($key); //okey | |
26 | var_dump($yac->get($key)); //false | |
27 | ||
28 | $yac->set($key, $value); | |
29 | $yac2->delete("dummy_" . $key); //okey | |
30 | var_dump($yac->get($key)); //false | |
31 | ?> | |
32 | --EXPECTF-- | |
33 | bool(true) | |
34 | bool(false) | |
35 | bool(true) | |
36 | bool(true) | |
37 | bool(false) | |
38 | bool(false) |
0 | --TEST-- | |
1 | Check for yac multi ops | |
2 | --SKIPIF-- | |
3 | <?php if (!extension_loaded("yac")) print "skip"; ?> | |
4 | --INI-- | |
5 | yac.enable=1 | |
6 | yac.enable_cli=1 | |
7 | yac.keys_memory_size=4M | |
8 | yac.values_memory_size=32M | |
9 | --FILE-- | |
10 | <?php | |
11 | $yac = new Yac(); | |
12 | ||
13 | $values = array(); | |
14 | $chars = 'abcdefghijklmnopqrstuvwxyz0123456789'; | |
15 | for ($i = 0; $i < 100; $i++) { | |
16 | $key = substr(str_shuffle($chars), 0, rand(16, 32)); | |
17 | $value = md5($key . rand(1, 10000)); | |
18 | $values[$key] = $value; | |
19 | } | |
20 | ||
21 | $numbers = count($values); | |
22 | ||
23 | var_dump($yac->set($values)); | |
24 | ||
25 | $keys = array_keys($values); | |
26 | $ret = $yac->get($keys); | |
27 | var_dump(count(array_filter($ret)) == $numbers); | |
28 | ||
29 | $disable = array_slice($keys, 0, -10); | |
30 | $yac->delete($disable); | |
31 | ||
32 | $ret = $yac->get($keys); | |
33 | var_dump(count(array_filter($ret)) == 10); | |
34 | ?> | |
35 | --EXPECTF-- | |
36 | bool(true) | |
37 | bool(true) | |
38 | bool(true) |
0 | --TEST-- | |
1 | Check for yac::flush | |
2 | --SKIPIF-- | |
3 | <?php if (!extension_loaded("yac")) print "skip"; ?> | |
4 | --INI-- | |
5 | yac.enable=1 | |
6 | yac.enable_cli=1 | |
7 | yac.keys_memory_size=4M | |
8 | yac.values_memory_size=32M | |
9 | --FILE-- | |
10 | <?php | |
11 | $yac = new Yac(); | |
12 | ||
13 | $values = array(); | |
14 | $chars = 'abcdefghijklmnopqrstuvwxyz0123456789'; | |
15 | for ($i = 0; $i < 100; $i++) { | |
16 | $key = substr(str_shuffle($chars), 0, rand(16, 32)); | |
17 | $value = md5($key . rand(1, 10000)); | |
18 | $values[$key] = $value; | |
19 | } | |
20 | ||
21 | $numbers = count($values); | |
22 | ||
23 | var_dump($yac->set($values)); | |
24 | ||
25 | $yac->flush(); | |
26 | ||
27 | var_dump($yac->get($key)); | |
28 | $info = $yac->info(); | |
29 | var_dump($info['slots_used']); | |
30 | ?> | |
31 | --EXPECTF-- | |
32 | bool(true) | |
33 | bool(false) | |
34 | int(0) |
0 | --TEST-- | |
1 | Check for yac::add | |
2 | --SKIPIF-- | |
3 | <?php if (!extension_loaded("yac")) print "skip"; ?> | |
4 | --INI-- | |
5 | yac.enable=1 | |
6 | yac.enable_cli=1 | |
7 | yac.keys_memory_size=4M | |
8 | yac.values_memory_size=32M | |
9 | --FILE-- | |
10 | <?php | |
11 | $yac = new Yac(); | |
12 | ||
13 | $key = "dummy"; | |
14 | $value = "foo"; | |
15 | var_dump($yac->add($key, $value)); // true | |
16 | var_dump($yac->add($key, $value)); // false | |
17 | var_dump($yac->set($key, $value)); // true | |
18 | var_dump($yac->get($key)); // foo | |
19 | var_dump($yac->delete($key)); // true | |
20 | $value = "bar"; | |
21 | var_dump($yac->add($key, $value, 1)); //true | |
22 | var_dump($yac->add($key, $value, 1)); //false | |
23 | var_dump($yac->get($key)); //bar | |
24 | sleep(1); | |
25 | var_dump($yac->add($key, $value)); //true | |
26 | ||
27 | ?> | |
28 | --EXPECTF-- | |
29 | bool(true) | |
30 | bool(false) | |
31 | bool(true) | |
32 | string(3) "foo" | |
33 | bool(true) | |
34 | bool(true) | |
35 | bool(false) | |
36 | string(3) "bar" | |
37 | bool(true) |
0 | --TEST-- | |
1 | Check for functional apis | |
2 | --SKIPIF-- | |
3 | <?php | |
4 | if (!extension_loaded("yac")) print "skip"; | |
5 | print "skip Functional style APIs are not enabled"; | |
6 | ?> | |
7 | --INI-- | |
8 | yac.enable=1 | |
9 | yac.enable_cli=1 | |
10 | yac.keys_memory_size=4M | |
11 | yac.values_memory_size=32M | |
12 | --FILE-- | |
13 | <?php | |
14 | $key = "dummy"; | |
15 | $value = "foo"; | |
16 | var_dump(yac_set($key, $value)); //true | |
17 | var_dump(yac_add($key, $value)); //false | |
18 | var_dump(yac_get($key)); //foo | |
19 | var_dump(yac_delete($key)); //true | |
20 | var_dump(yac_set($key, $value)); //true | |
21 | var_dump(yac_flush()); //true | |
22 | $info = yac_info(); | |
23 | var_dump($info['slots_used']); //0 | |
24 | ?> | |
25 | --EXPECTF-- | |
26 | bool(true) | |
27 | bool(false) | |
28 | string(3) "foo" | |
29 | bool(true) | |
30 | bool(true) | |
31 | bool(true) | |
32 | int(0) |
0 | --TEST-- | |
1 | Check for ttl bug | |
2 | --INI-- | |
3 | yac.enable=1 | |
4 | yac.enable_cli=1 | |
5 | yac.keys_memory_size=4M | |
6 | yac.values_memory_size=32M | |
7 | --FILE-- | |
8 | <?php | |
9 | $yac = new Yac(); | |
10 | $yac->set('test', 1, 1); | |
11 | sleep(2); | |
12 | var_dump($yac->get('test')); | |
13 | ?> | |
14 | --EXPECTF-- | |
15 | bool(false) |
0 | --TEST-- | |
1 | Check for ttl bug | |
2 | --SKIPIF-- | |
3 | <?php if (!extension_loaded("yac")) print "skip"; ?> | |
4 | <?php if (YAC_SERIALIZER != "PHP") print "skip"; ?> | |
5 | --INI-- | |
6 | yac.enable=1 | |
7 | yac.enable_cli=1 | |
8 | yac.keys_memory_size=4M | |
9 | yac.values_memory_size=32M | |
10 | yac.compress_threshold=1024 | |
11 | --FILE-- | |
12 | <?php | |
13 | error_reporting(E_ALL); | |
14 | $yac = new Yac(); | |
15 | ||
16 | for($i = 0; $i<100; $i++) { | |
17 | $value[] = ($i + 100000)."sdfsfsfsfs"; | |
18 | } | |
19 | ||
20 | $yac->set('test', $value); | |
21 | ||
22 | echo count($yac->get('test')); | |
23 | ?> | |
24 | --EXPECTF-- | |
25 | 100 |
0 | --TEST-- | |
1 | Check for Yac::dump | |
2 | --INI-- | |
3 | yac.enable=1 | |
4 | yac.enable_cli=1 | |
5 | yac.keys_memory_size=4M | |
6 | yac.values_memory_size=32M | |
7 | yac.compress_threshold=1024 | |
8 | --FILE-- | |
9 | <?php | |
10 | $yac = new Yac(); | |
11 | ||
12 | for ($i = 0; $i<100; $i++) { | |
13 | $yac->set("key". $i, "kjslkdfkldasjkf"); | |
14 | } | |
15 | for ($i = 0; $i<100; $i++) { | |
16 | $yac->set("key". $i, "kjslkdfkldasjkf"); | |
17 | } | |
18 | ||
19 | var_dump(count($yac->dump(1000))); | |
20 | --EXPECTF-- | |
21 | int(100) |
0 | --TEST-- | |
1 | ISSUE #12 segfault if use mmap&k_size bigger than 4M | |
2 | --SKIPIF-- | |
3 | <?php if (!extension_loaded("yac")) print "skip"; ?> | |
4 | --INI-- | |
5 | yac.enable=1 | |
6 | yac.enable_cli=1 | |
7 | yac.keys_memory_size=8M | |
8 | yac.values_memory_size=128M | |
9 | --FILE-- | |
10 | <?php | |
11 | $yac = new Yac(); | |
12 | $i = 0; | |
13 | while (true) { | |
14 | $yac->set(rand(), strval(rand()), 2); | |
15 | $i++; | |
16 | if ($i > 20000) { | |
17 | break; | |
18 | } | |
19 | } | |
20 | ?> | |
21 | OKEY | |
22 | --EXPECTF-- | |
23 | OKEY |
0 | /* | |
1 | +----------------------------------------------------------------------+ | |
2 | | Yet Another Cache | | |
3 | +----------------------------------------------------------------------+ | |
4 | | Copyright (c) 2013-2013 The PHP Group | | |
5 | +----------------------------------------------------------------------+ | |
6 | | This source file is subject to version 3.01 of the PHP license, | | |
7 | | that is bundled with this package in the file LICENSE, and is | | |
8 | | available through the world-wide-web at the following url: | | |
9 | | http://www.php.net/license/3_01.txt | | |
10 | | If you did not receive a copy of the PHP license and are unable to | | |
11 | | obtain it through the world-wide-web, please send a note to | | |
12 | | license@php.net so we can mail you a copy immediately. | | |
13 | +----------------------------------------------------------------------+ | |
14 | | Author: Xinchen Hui <laruence@php.net> | | |
15 | +----------------------------------------------------------------------+ | |
16 | */ | |
17 | ||
18 | /* $Id$ */ | |
19 | ||
20 | #ifdef HAVE_CONFIG_H | |
21 | #include "config.h" | |
22 | #endif | |
23 | ||
24 | #include <time.h> | |
25 | ||
26 | #include "php.h" | |
27 | #include "php_ini.h" | |
28 | #include "ext/standard/info.h" | |
29 | #include "ext/standard/php_smart_str.h" /* for smart_str */ | |
30 | #include "SAPI.h" | |
31 | ||
32 | #include "php_yac.h" | |
33 | #include "storage/yac_storage.h" | |
34 | #include "serializer/yac_serializer.h" | |
35 | #ifdef HAVE_FASTLZ_H | |
36 | #include <fastlz.h> | |
37 | #else | |
38 | #include "compressor/fastlz/fastlz.h" | |
39 | #endif | |
40 | ||
41 | zend_class_entry *yac_class_ce; | |
42 | ||
43 | ZEND_DECLARE_MODULE_GLOBALS(yac); | |
44 | ||
45 | /** {{{ ARG_INFO | |
46 | */ | |
47 | ZEND_BEGIN_ARG_INFO_EX(arginfo_yac_constructor, 0, 0, 0) | |
48 | ZEND_ARG_INFO(0, prefix) | |
49 | ZEND_END_ARG_INFO() | |
50 | ||
51 | ZEND_BEGIN_ARG_INFO_EX(arginfo_yac_add, 0, 0, 1) | |
52 | ZEND_ARG_INFO(0, keys) | |
53 | ZEND_ARG_INFO(0, value) | |
54 | ZEND_ARG_INFO(0, ttl) | |
55 | ZEND_END_ARG_INFO() | |
56 | ||
57 | ZEND_BEGIN_ARG_INFO_EX(arginfo_yac_get, 0, 0, 1) | |
58 | ZEND_ARG_INFO(0, keys) | |
59 | ZEND_END_ARG_INFO() | |
60 | ||
61 | ZEND_BEGIN_ARG_INFO_EX(arginfo_yac_delete, 0, 0, 1) | |
62 | ZEND_ARG_INFO(0, keys) | |
63 | ZEND_ARG_INFO(0, ttl) | |
64 | ZEND_END_ARG_INFO() | |
65 | ||
66 | ZEND_BEGIN_ARG_INFO_EX(arginfo_yac_void, 0, 0, 0) | |
67 | ZEND_END_ARG_INFO() | |
68 | /* }}} */ | |
69 | ||
70 | static PHP_INI_MH(OnChangeKeysMemoryLimit) /* {{{ */ { | |
71 | if (new_value) { | |
72 | YAC_G(k_msize) = zend_atol(new_value, new_value_length); | |
73 | } | |
74 | return SUCCESS; | |
75 | } | |
76 | /* }}} */ | |
77 | ||
78 | static PHP_INI_MH(OnChangeValsMemoryLimit) /* {{{ */ { | |
79 | if (new_value) { | |
80 | YAC_G(v_msize) = zend_atol(new_value, new_value_length); | |
81 | } | |
82 | return SUCCESS; | |
83 | } | |
84 | /* }}} */ | |
85 | ||
86 | static PHP_INI_MH(OnChangeCompressThreshold) /* {{{ */ { | |
87 | if (new_value) { | |
88 | YAC_G(compress_threshold) = zend_atol(new_value, new_value_length); | |
89 | if (YAC_G(compress_threshold) < YAC_MIN_COMPRESS_THRESHOLD) { | |
90 | YAC_G(compress_threshold) = YAC_MIN_COMPRESS_THRESHOLD; | |
91 | } | |
92 | } | |
93 | return SUCCESS; | |
94 | } | |
95 | /* }}} */ | |
96 | ||
97 | /* {{{ PHP_INI | |
98 | */ | |
99 | PHP_INI_BEGIN() | |
100 | STD_PHP_INI_BOOLEAN("yac.enable", "1", PHP_INI_SYSTEM, OnUpdateBool, enable, zend_yac_globals, yac_globals) | |
101 | STD_PHP_INI_BOOLEAN("yac.debug", "0", PHP_INI_ALL, OnUpdateBool, debug, zend_yac_globals, yac_globals) | |
102 | STD_PHP_INI_ENTRY("yac.keys_memory_size", "4M", PHP_INI_SYSTEM, OnChangeKeysMemoryLimit, k_msize, zend_yac_globals, yac_globals) | |
103 | STD_PHP_INI_ENTRY("yac.values_memory_size", "64M", PHP_INI_SYSTEM, OnChangeValsMemoryLimit, v_msize, zend_yac_globals, yac_globals) | |
104 | STD_PHP_INI_ENTRY("yac.compress_threshold", "-1", PHP_INI_SYSTEM, OnChangeCompressThreshold, compress_threshold, zend_yac_globals, yac_globals) | |
105 | STD_PHP_INI_ENTRY("yac.enable_cli", "0", PHP_INI_SYSTEM, OnUpdateBool, enable_cli, zend_yac_globals, yac_globals) | |
106 | PHP_INI_END() | |
107 | /* }}} */ | |
108 | ||
109 | static int yac_add_impl(char *prefix, uint prefix_len, char *key, uint len, zval *value, int ttl, int add TSRMLS_DC) /* {{{ */ { | |
110 | int ret = 0, flag = Z_TYPE_P(value); | |
111 | char *msg, buf[YAC_STORAGE_MAX_KEY_LEN]; | |
112 | time_t tv; | |
113 | ||
114 | if ((len + prefix_len) > YAC_STORAGE_MAX_KEY_LEN) { | |
115 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Key%s can not be longer than %d bytes", | |
116 | prefix_len? "(include prefix)" : "", YAC_STORAGE_MAX_KEY_LEN); | |
117 | return ret; | |
118 | } | |
119 | ||
120 | if (prefix_len) { | |
121 | len = snprintf(buf, sizeof(buf), "%s%s", prefix, key); | |
122 | key = (char *)buf; | |
123 | } | |
124 | ||
125 | ||
126 | tv = time(NULL); | |
127 | switch (Z_TYPE_P(value)) { | |
128 | case IS_NULL: | |
129 | ret = yac_storage_update(key, len, (char *)&flag, sizeof(int), flag, ttl, add, tv); | |
130 | break; | |
131 | case IS_BOOL: | |
132 | case IS_LONG: | |
133 | ret = yac_storage_update(key, len, (char *)&Z_LVAL_P(value), sizeof(long), flag, ttl, add, tv); | |
134 | break; | |
135 | case IS_DOUBLE: | |
136 | ret = yac_storage_update(key, len, (char *)&Z_DVAL_P(value), sizeof(double), flag, ttl, add, tv); | |
137 | break; | |
138 | case IS_STRING: | |
139 | case IS_CONSTANT: | |
140 | { | |
141 | if (Z_STRLEN_P(value) > YAC_G(compress_threshold) || Z_STRLEN_P(value) > YAC_STORAGE_MAX_ENTRY_LEN) { | |
142 | int compressed_len; | |
143 | char *compressed; | |
144 | ||
145 | /* if longer than this, then we can not stored the length in flag */ | |
146 | if (Z_STRLEN_P(value) > YAC_ENTRY_MAX_ORIG_LEN) { | |
147 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Value is too long(%d bytes) to be stored", Z_STRLEN_P(value)); | |
148 | return ret; | |
149 | } | |
150 | ||
151 | compressed = emalloc(Z_STRLEN_P(value) * 1.05); | |
152 | compressed_len = fastlz_compress(Z_STRVAL_P(value), Z_STRLEN_P(value), compressed); | |
153 | if (!compressed_len || compressed_len > Z_STRLEN_P(value)) { | |
154 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Compression failed"); | |
155 | efree(compressed); | |
156 | return ret; | |
157 | } | |
158 | ||
159 | if (compressed_len > YAC_STORAGE_MAX_ENTRY_LEN) { | |
160 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Value is too long(%d bytes) to be stored", Z_STRLEN_P(value)); | |
161 | efree(compressed); | |
162 | return ret; | |
163 | } | |
164 | ||
165 | flag |= YAC_ENTRY_COMPRESSED; | |
166 | flag |= (Z_STRLEN_P(value) << YAC_ENTRY_ORIG_LEN_SHIT); | |
167 | ret = yac_storage_update(key, len, compressed, compressed_len, flag, ttl, add, tv); | |
168 | efree(compressed); | |
169 | } else { | |
170 | ret = yac_storage_update(key, len, Z_STRVAL_P(value), Z_STRLEN_P(value), flag, ttl, add, tv); | |
171 | } | |
172 | } | |
173 | break; | |
174 | case IS_ARRAY: | |
175 | #ifdef IS_CONSTANT_ARRAY | |
176 | case IS_CONSTANT_ARRAY: | |
177 | #endif | |
178 | case IS_OBJECT: | |
179 | { | |
180 | smart_str buf = {0}; | |
181 | #if ENABLE_MSGPACK | |
182 | if (yac_serializer_msgpack_pack(value, &buf, &msg TSRMLS_CC)) { | |
183 | #else | |
184 | ||
185 | if (yac_serializer_php_pack(value, &buf, &msg TSRMLS_CC)) { | |
186 | #endif | |
187 | if (buf.len > YAC_G(compress_threshold) || buf.len > YAC_STORAGE_MAX_ENTRY_LEN) { | |
188 | int compressed_len; | |
189 | char *compressed; | |
190 | ||
191 | if (buf.len > YAC_ENTRY_MAX_ORIG_LEN) { | |
192 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Value is too big to be stored"); | |
193 | return ret; | |
194 | } | |
195 | ||
196 | compressed = emalloc(buf.len * 1.05); | |
197 | compressed_len = fastlz_compress(buf.c, buf.len, compressed); | |
198 | if (!compressed_len || compressed_len > buf.len) { | |
199 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Compression failed"); | |
200 | efree(compressed); | |
201 | return ret; | |
202 | } | |
203 | ||
204 | if (compressed_len > YAC_STORAGE_MAX_ENTRY_LEN) { | |
205 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Value is too big to be stored"); | |
206 | efree(compressed); | |
207 | return ret; | |
208 | } | |
209 | ||
210 | flag |= YAC_ENTRY_COMPRESSED; | |
211 | flag |= (buf.len << YAC_ENTRY_ORIG_LEN_SHIT); | |
212 | ret = yac_storage_update(key, len, compressed, compressed_len, flag, ttl, add, tv); | |
213 | efree(compressed); | |
214 | } else { | |
215 | ret = yac_storage_update(key, len, buf.c, buf.len, flag, ttl, add, tv); | |
216 | } | |
217 | smart_str_free(&buf); | |
218 | } else { | |
219 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Serialization failed"); | |
220 | smart_str_free(&buf); | |
221 | } | |
222 | } | |
223 | break; | |
224 | case IS_RESOURCE: | |
225 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type 'IS_RESOURCE' cannot be stored"); | |
226 | break; | |
227 | default: | |
228 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported valued type to be stored '%d'", flag); | |
229 | break; | |
230 | } | |
231 | ||
232 | return ret; | |
233 | } | |
234 | /* }}} */ | |
235 | ||
236 | static int yac_add_multi_impl(char *prefix, uint prefix_len, zval *kvs, int ttl, int add TSRMLS_DC) /* {{{ */ { | |
237 | HashTable *ht = Z_ARRVAL_P(kvs); | |
238 | ||
239 | for (zend_hash_internal_pointer_reset(ht); | |
240 | zend_hash_has_more_elements(ht) == SUCCESS; | |
241 | zend_hash_move_forward(ht)) { | |
242 | char *key; | |
243 | ulong idx; | |
244 | zval **value; | |
245 | uint len, should_free = 0; | |
246 | ||
247 | if (zend_hash_get_current_data(ht, (void **)&value) == FAILURE) { | |
248 | continue; | |
249 | } | |
250 | ||
251 | switch (zend_hash_get_current_key_ex(ht, &key, &len, &idx, 0, NULL)) { | |
252 | case HASH_KEY_IS_LONG: | |
253 | len = spprintf(&key, 0, "%lu", idx) + 1; | |
254 | should_free = 1; | |
255 | case HASH_KEY_IS_STRING: | |
256 | if (yac_add_impl(prefix, prefix_len, key, len - 1, *value, ttl, add TSRMLS_CC)) { | |
257 | if (should_free) { | |
258 | efree(key); | |
259 | } | |
260 | continue; | |
261 | } else { | |
262 | if (should_free) { | |
263 | efree(key); | |
264 | } | |
265 | return 0; | |
266 | } | |
267 | default: | |
268 | continue; | |
269 | } | |
270 | } | |
271 | ||
272 | return 1; | |
273 | } | |
274 | /* }}} */ | |
275 | ||
276 | static zval * yac_get_impl(char * prefix, uint prefix_len, char *key, uint len, uint *cas TSRMLS_DC) /* {{{ */ { | |
277 | zval *ret = NULL; | |
278 | uint flag, size = 0; | |
279 | char *data, *msg, buf[YAC_STORAGE_MAX_KEY_LEN]; | |
280 | time_t tv; | |
281 | ||
282 | if ((len + prefix_len) > YAC_STORAGE_MAX_KEY_LEN) { | |
283 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Key%s can not be longer than %d bytes", | |
284 | prefix_len? "(include prefix)" : "", YAC_STORAGE_MAX_KEY_LEN); | |
285 | return ret; | |
286 | } | |
287 | ||
288 | if (prefix_len) { | |
289 | len = snprintf(buf, sizeof(buf), "%s%s", prefix, key); | |
290 | key = (char *)buf; | |
291 | } | |
292 | ||
293 | tv = time(NULL); | |
294 | if (yac_storage_find(key, len, &data, &size, &flag, (int *)cas, tv)) { | |
295 | switch ((flag & YAC_ENTRY_TYPE_MASK)) { | |
296 | case IS_NULL: | |
297 | if (size == sizeof(int)) { | |
298 | MAKE_STD_ZVAL(ret); | |
299 | ZVAL_NULL(ret); | |
300 | } | |
301 | efree(data); | |
302 | break; | |
303 | case IS_BOOL: | |
304 | case IS_LONG: | |
305 | if (size == sizeof(long)) { | |
306 | MAKE_STD_ZVAL(ret); | |
307 | Z_TYPE_P(ret) = flag; | |
308 | Z_LVAL_P(ret) = *(long*)data; | |
309 | } | |
310 | efree(data); | |
311 | break; | |
312 | case IS_DOUBLE: | |
313 | if (size == sizeof(double)) { | |
314 | MAKE_STD_ZVAL(ret); | |
315 | Z_TYPE_P(ret) = flag; | |
316 | Z_DVAL_P(ret) = *(double*)data; | |
317 | } | |
318 | efree(data); | |
319 | break; | |
320 | case IS_STRING: | |
321 | case IS_CONSTANT: | |
322 | { | |
323 | if ((flag & YAC_ENTRY_COMPRESSED)) { | |
324 | size_t orig_len = ((uint)flag >> YAC_ENTRY_ORIG_LEN_SHIT); | |
325 | char *origin = emalloc(orig_len + 1); | |
326 | uint length; | |
327 | length = fastlz_decompress(data, size, origin, orig_len); | |
328 | if (!length) { | |
329 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Decompression failed"); | |
330 | efree(data); | |
331 | efree(origin); | |
332 | return ret; | |
333 | } | |
334 | MAKE_STD_ZVAL(ret); | |
335 | ZVAL_STRINGL(ret, origin, length, 0); | |
336 | efree(data); | |
337 | } else { | |
338 | MAKE_STD_ZVAL(ret); | |
339 | ZVAL_STRINGL(ret, data, size, 0); | |
340 | Z_TYPE_P(ret) = flag; | |
341 | } | |
342 | } | |
343 | break; | |
344 | case IS_ARRAY: | |
345 | #ifdef IS_CONSTANT_ARRAY | |
346 | case IS_CONSTANT_ARRAY: | |
347 | #endif | |
348 | case IS_OBJECT: | |
349 | { | |
350 | if ((flag & YAC_ENTRY_COMPRESSED)) { | |
351 | size_t length, orig_len = ((uint)flag >> YAC_ENTRY_ORIG_LEN_SHIT); | |
352 | char *origin = emalloc(orig_len + 1); | |
353 | length = fastlz_decompress(data, size, origin, orig_len); | |
354 | if (!length) { | |
355 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Decompression failed"); | |
356 | efree(data); | |
357 | efree(origin); | |
358 | return ret; | |
359 | } | |
360 | efree(data); | |
361 | data = origin; | |
362 | size = length; | |
363 | } | |
364 | #if ENABLE_MSGPACK | |
365 | ret = yac_serializer_msgpack_unpack(data, size, &msg TSRMLS_CC); | |
366 | #else | |
367 | ret = yac_serializer_php_unpack(data, size, &msg TSRMLS_CC); | |
368 | #endif | |
369 | if (!ret) { | |
370 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unserialization failed"); | |
371 | } | |
372 | efree(data); | |
373 | } | |
374 | break; | |
375 | default: | |
376 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unexpected valued type '%d'", flag); | |
377 | break; | |
378 | } | |
379 | } | |
380 | ||
381 | return ret; | |
382 | } | |
383 | /* }}} */ | |
384 | ||
385 | static zval * yac_get_multi_impl(char *prefix, uint prefix_len, zval *keys, zval *cas TSRMLS_DC) /* {{{ */ { | |
386 | zval *ret; | |
387 | HashTable *ht = Z_ARRVAL_P(keys); | |
388 | ||
389 | MAKE_STD_ZVAL(ret); | |
390 | array_init(ret); | |
391 | ||
392 | for (zend_hash_internal_pointer_reset(ht); | |
393 | zend_hash_has_more_elements(ht) == SUCCESS; | |
394 | zend_hash_move_forward(ht)) { | |
395 | uint cas; | |
396 | zval **value, *v; | |
397 | ||
398 | if (zend_hash_get_current_data(ht, (void **)&value) == FAILURE) { | |
399 | continue; | |
400 | } | |
401 | ||
402 | switch (Z_TYPE_PP(value)) { | |
403 | case IS_STRING: | |
404 | if ((v = yac_get_impl(prefix, prefix_len, Z_STRVAL_PP(value), Z_STRLEN_PP(value), &cas TSRMLS_CC))) { | |
405 | add_assoc_zval_ex(ret, Z_STRVAL_PP(value), Z_STRLEN_PP(value) + 1, v); | |
406 | } else { | |
407 | add_assoc_bool_ex(ret, Z_STRVAL_PP(value), Z_STRLEN_PP(value) + 1, 0); | |
408 | } | |
409 | continue; | |
410 | default: | |
411 | { | |
412 | zval copy; | |
413 | int use_copy; | |
414 | zend_make_printable_zval(*value, ©, &use_copy); | |
415 | if ((v = yac_get_impl(prefix, prefix_len, Z_STRVAL(copy), Z_STRLEN(copy), &cas TSRMLS_CC))) { | |
416 | add_assoc_zval_ex(ret, Z_STRVAL(copy), Z_STRLEN(copy) + 1, v); | |
417 | } else { | |
418 | add_assoc_bool_ex(ret, Z_STRVAL(copy), Z_STRLEN(copy) + 1, 0); | |
419 | } | |
420 | zval_dtor(©); | |
421 | } | |
422 | continue; | |
423 | } | |
424 | } | |
425 | ||
426 | return ret; | |
427 | } | |
428 | /* }}} */ | |
429 | ||
430 | void yac_delete_impl(char *prefix, uint prefix_len, char *key, uint len, int ttl TSRMLS_DC) /* {{{ */ { | |
431 | char buf[YAC_STORAGE_MAX_KEY_LEN]; | |
432 | time_t tv = 0; | |
433 | ||
434 | if ((len + prefix_len) > YAC_STORAGE_MAX_KEY_LEN) { | |
435 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Key%s can not be longer than %d bytes", | |
436 | prefix_len? "(include prefix)" : "", YAC_STORAGE_MAX_KEY_LEN); | |
437 | return; | |
438 | } | |
439 | ||
440 | if (prefix_len) { | |
441 | len = snprintf(buf, sizeof(buf), "%s%s", prefix, key); | |
442 | key = (char *)buf; | |
443 | } | |
444 | ||
445 | if (ttl) { | |
446 | tv = (ulong)time(NULL); | |
447 | } | |
448 | ||
449 | yac_storage_delete(key, len, ttl, tv); | |
450 | } | |
451 | /* }}} */ | |
452 | ||
453 | static void yac_delete_multi_impl(char *prefix, uint prefix_len, zval *keys, int ttl TSRMLS_DC) /* {{{ */ { | |
454 | HashTable *ht = Z_ARRVAL_P(keys); | |
455 | ||
456 | for (zend_hash_internal_pointer_reset(ht); | |
457 | zend_hash_has_more_elements(ht) == SUCCESS; | |
458 | zend_hash_move_forward(ht)) { | |
459 | zval **value; | |
460 | ||
461 | if (zend_hash_get_current_data(ht, (void **)&value) == FAILURE) { | |
462 | continue; | |
463 | } | |
464 | ||
465 | switch (Z_TYPE_PP(value)) { | |
466 | case IS_STRING: | |
467 | yac_delete_impl(prefix, prefix_len, Z_STRVAL_PP(value), Z_STRLEN_PP(value), ttl TSRMLS_CC); | |
468 | continue; | |
469 | default: | |
470 | { | |
471 | zval copy; | |
472 | int use_copy; | |
473 | zend_make_printable_zval(*value, ©, &use_copy); | |
474 | yac_delete_impl(prefix, prefix_len, Z_STRVAL(copy), Z_STRLEN(copy), ttl TSRMLS_CC); | |
475 | zval_dtor(©); | |
476 | } | |
477 | continue; | |
478 | } | |
479 | } | |
480 | } | |
481 | /* }}} */ | |
482 | ||
483 | /** {{{ proto public Yac::__construct([string $prefix]) | |
484 | */ | |
485 | PHP_METHOD(yac, __construct) { | |
486 | char *prefix; | |
487 | uint len = 0; | |
488 | ||
489 | if (!YAC_G(enable)) { | |
490 | return; | |
491 | } | |
492 | ||
493 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &prefix, &len) == FAILURE) { | |
494 | return; | |
495 | } | |
496 | ||
497 | if (len == 0) { | |
498 | return; | |
499 | } | |
500 | ||
501 | zend_update_property_stringl(yac_class_ce, getThis(), ZEND_STRS(YAC_CLASS_PROPERTY_PREFIX) - 1, prefix, len TSRMLS_CC); | |
502 | ||
503 | } | |
504 | /* }}} */ | |
505 | ||
506 | /** {{{ proto public Yac::add(mixed $keys, mixed $value[, int $ttl]) | |
507 | */ | |
508 | PHP_METHOD(yac, add) { | |
509 | long ttl = 0; | |
510 | zval *keys, *prefix, *value = NULL; | |
511 | char *sprefix = NULL; | |
512 | uint ret, prefix_len = 0; | |
513 | ||
514 | if (!YAC_G(enable)) { | |
515 | RETURN_FALSE; | |
516 | } | |
517 | ||
518 | switch (ZEND_NUM_ARGS()) { | |
519 | case 1: | |
520 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &keys) == FAILURE) { | |
521 | return; | |
522 | } | |
523 | break; | |
524 | case 2: | |
525 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &keys, &value) == FAILURE) { | |
526 | return; | |
527 | } | |
528 | if (Z_TYPE_P(keys) == IS_ARRAY) { | |
529 | if (Z_TYPE_P(value) == IS_LONG) { | |
530 | ttl = Z_LVAL_P(value); | |
531 | value = NULL; | |
532 | } else { | |
533 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "ttl parameter must be an integer"); | |
534 | return; | |
535 | } | |
536 | } | |
537 | break; | |
538 | case 3: | |
539 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zzl", &keys, &value, &ttl) == FAILURE) { | |
540 | return; | |
541 | } | |
542 | break; | |
543 | default: | |
544 | WRONG_PARAM_COUNT; | |
545 | } | |
546 | ||
547 | prefix = zend_read_property(yac_class_ce, getThis(), ZEND_STRS(YAC_CLASS_PROPERTY_PREFIX) - 1, 0 TSRMLS_CC); | |
548 | sprefix = Z_STRVAL_P(prefix); | |
549 | prefix_len = Z_STRLEN_P(prefix); | |
550 | ||
551 | if (Z_TYPE_P(keys) == IS_ARRAY) { | |
552 | ret = yac_add_multi_impl(sprefix, prefix_len, keys, ttl, 1 TSRMLS_CC); | |
553 | } else if (Z_TYPE_P(keys) == IS_STRING) { | |
554 | ret = yac_add_impl(sprefix, prefix_len, Z_STRVAL_P(keys), Z_STRLEN_P(keys), value, ttl, 1 TSRMLS_CC); | |
555 | } else { | |
556 | zval copy; | |
557 | int use_copy; | |
558 | zend_make_printable_zval(keys, ©, &use_copy); | |
559 | ret = yac_add_impl(sprefix, prefix_len, Z_STRVAL(copy), Z_STRLEN(copy), value, ttl, 1 TSRMLS_CC); | |
560 | zval_dtor(©); | |
561 | } | |
562 | ||
563 | RETURN_BOOL(ret? 1 : 0); | |
564 | } | |
565 | /* }}} */ | |
566 | ||
567 | /** {{{ proto public Yac::set(mixed $keys, mixed $value[, int $ttl]) | |
568 | */ | |
569 | PHP_METHOD(yac, set) { | |
570 | long ttl = 0; | |
571 | zval *keys, *prefix, *value = NULL; | |
572 | char *sprefix = NULL; | |
573 | uint ret, prefix_len = 0; | |
574 | ||
575 | if (!YAC_G(enable)) { | |
576 | RETURN_FALSE; | |
577 | } | |
578 | ||
579 | switch (ZEND_NUM_ARGS()) { | |
580 | case 1: | |
581 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &keys) == FAILURE) { | |
582 | return; | |
583 | } | |
584 | break; | |
585 | case 2: | |
586 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &keys, &value) == FAILURE) { | |
587 | return; | |
588 | } | |
589 | if (Z_TYPE_P(keys) == IS_ARRAY) { | |
590 | if (Z_TYPE_P(value) == IS_LONG) { | |
591 | ttl = Z_LVAL_P(value); | |
592 | value = NULL; | |
593 | } else { | |
594 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "ttl parameter must be an integer"); | |
595 | return; | |
596 | } | |
597 | } | |
598 | break; | |
599 | case 3: | |
600 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zzl", &keys, &value, &ttl) == FAILURE) { | |
601 | return; | |
602 | } | |
603 | break; | |
604 | default: | |
605 | WRONG_PARAM_COUNT; | |
606 | } | |
607 | ||
608 | prefix = zend_read_property(yac_class_ce, getThis(), ZEND_STRS(YAC_CLASS_PROPERTY_PREFIX) - 1, 0 TSRMLS_CC); | |
609 | sprefix = Z_STRVAL_P(prefix); | |
610 | prefix_len = Z_STRLEN_P(prefix); | |
611 | ||
612 | if (Z_TYPE_P(keys) == IS_ARRAY) { | |
613 | ret = yac_add_multi_impl(sprefix, prefix_len, keys, ttl, 0 TSRMLS_CC); | |
614 | } else if (Z_TYPE_P(keys) == IS_STRING) { | |
615 | ret = yac_add_impl(sprefix, prefix_len, Z_STRVAL_P(keys), Z_STRLEN_P(keys), value, ttl, 0 TSRMLS_CC); | |
616 | } else { | |
617 | zval copy; | |
618 | int use_copy; | |
619 | zend_make_printable_zval(keys, ©, &use_copy); | |
620 | ret = yac_add_impl(sprefix, prefix_len, Z_STRVAL(copy), Z_STRLEN(copy), value, ttl, 0 TSRMLS_CC); | |
621 | zval_dtor(©); | |
622 | } | |
623 | ||
624 | RETURN_BOOL(ret? 1 : 0); | |
625 | } | |
626 | /* }}} */ | |
627 | ||
628 | /** {{{ proto public Yac::get(mixed $keys[, int &$cas]) | |
629 | */ | |
630 | PHP_METHOD(yac, get) { | |
631 | char *sprefix = NULL; | |
632 | uint prefix_len = 0, lcas = 0; | |
633 | zval *ret, *keys, *prefix, *cas = NULL; | |
634 | ||
635 | if (!YAC_G(enable)) { | |
636 | RETURN_FALSE; | |
637 | } | |
638 | ||
639 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|z", &keys, &cas) == FAILURE) { | |
640 | return; | |
641 | } | |
642 | ||
643 | prefix = zend_read_property(yac_class_ce, getThis(), ZEND_STRS(YAC_CLASS_PROPERTY_PREFIX) - 1, 0 TSRMLS_CC); | |
644 | sprefix = Z_STRVAL_P(prefix); | |
645 | prefix_len = Z_STRLEN_P(prefix); | |
646 | ||
647 | if (Z_TYPE_P(keys) == IS_ARRAY) { | |
648 | ret = yac_get_multi_impl(sprefix, prefix_len, keys, cas TSRMLS_CC); | |
649 | } else if (Z_TYPE_P(keys) == IS_STRING) { | |
650 | ret = yac_get_impl(sprefix, prefix_len, Z_STRVAL_P(keys), Z_STRLEN_P(keys), &lcas TSRMLS_CC); | |
651 | } else { | |
652 | zval copy; | |
653 | int use_copy; | |
654 | zend_make_printable_zval(keys, ©, &use_copy); | |
655 | ret = yac_get_impl(sprefix, prefix_len, Z_STRVAL(copy), Z_STRLEN(copy), &lcas TSRMLS_CC); | |
656 | zval_dtor(©); | |
657 | } | |
658 | ||
659 | if (ret) { | |
660 | RETURN_ZVAL(ret, 1, 1); | |
661 | } else { | |
662 | RETURN_FALSE; | |
663 | } | |
664 | } | |
665 | /* }}} */ | |
666 | ||
667 | /** {{{ proto public Yac::delete(mixed $key[, int $delay = 0]) | |
668 | */ | |
669 | PHP_METHOD(yac, delete) { | |
670 | long time = 0; | |
671 | zval *keys, *prefix; | |
672 | char *sprefix = NULL; | |
673 | uint prefix_len = 0; | |
674 | ||
675 | if (!YAC_G(enable)) { | |
676 | RETURN_FALSE; | |
677 | } | |
678 | ||
679 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", &keys, &time) == FAILURE) { | |
680 | return; | |
681 | } | |
682 | ||
683 | prefix = zend_read_property(yac_class_ce, getThis(), ZEND_STRS(YAC_CLASS_PROPERTY_PREFIX) - 1, 0 TSRMLS_CC); | |
684 | sprefix = Z_STRVAL_P(prefix); | |
685 | prefix_len = Z_STRLEN_P(prefix); | |
686 | ||
687 | if (Z_TYPE_P(keys) == IS_ARRAY) { | |
688 | yac_delete_multi_impl(sprefix, prefix_len, keys, time TSRMLS_CC); | |
689 | } else if (Z_TYPE_P(keys) == IS_STRING) { | |
690 | yac_delete_impl(sprefix, prefix_len, Z_STRVAL_P(keys), Z_STRLEN_P(keys), time TSRMLS_CC); | |
691 | } else { | |
692 | zval copy; | |
693 | int use_copy; | |
694 | zend_make_printable_zval(keys, ©, &use_copy); | |
695 | yac_delete_impl(sprefix, prefix_len, Z_STRVAL(copy), Z_STRLEN(copy), time TSRMLS_CC); | |
696 | zval_dtor(©); | |
697 | } | |
698 | ||
699 | RETURN_TRUE; | |
700 | } | |
701 | /* }}} */ | |
702 | ||
703 | /** {{{ proto public Yac::flush(void) | |
704 | */ | |
705 | PHP_METHOD(yac, flush) { | |
706 | ||
707 | if (!YAC_G(enable)) { | |
708 | RETURN_FALSE; | |
709 | } | |
710 | ||
711 | yac_storage_flush(); | |
712 | ||
713 | RETURN_TRUE; | |
714 | } | |
715 | /* }}} */ | |
716 | ||
717 | /** {{{ proto public Yac::info(void) | |
718 | */ | |
719 | PHP_METHOD(yac, info) { | |
720 | yac_storage_info *inf; | |
721 | ||
722 | if (!YAC_G(enable)) { | |
723 | RETURN_FALSE; | |
724 | } | |
725 | ||
726 | inf = yac_storage_get_info(); | |
727 | ||
728 | array_init(return_value); | |
729 | ||
730 | add_assoc_long(return_value, "memory_size", inf->k_msize + inf->v_msize); | |
731 | add_assoc_long(return_value, "slots_memory_size", inf->k_msize); | |
732 | add_assoc_long(return_value, "values_memory_size", inf->v_msize); | |
733 | add_assoc_long(return_value, "segment_size", inf->segment_size); | |
734 | add_assoc_long(return_value, "segment_num", inf->segments_num); | |
735 | add_assoc_long(return_value, "miss", inf->miss); | |
736 | add_assoc_long(return_value, "hits", inf->hits); | |
737 | add_assoc_long(return_value, "fails", inf->fails); | |
738 | add_assoc_long(return_value, "kicks", inf->kicks); | |
739 | add_assoc_long(return_value, "recycles", inf->recycles); | |
740 | add_assoc_long(return_value, "slots_size", inf->slots_size); | |
741 | add_assoc_long(return_value, "slots_used", inf->slots_num); | |
742 | ||
743 | yac_storage_free_info(inf); | |
744 | } | |
745 | /* }}} */ | |
746 | ||
747 | /** {{{ proto public Yac::dump(int $limit) | |
748 | */ | |
749 | PHP_METHOD(yac, dump) { | |
750 | long limit = 100; | |
751 | yac_item_list *list, *l; | |
752 | ||
753 | if (!YAC_G(enable)) { | |
754 | RETURN_FALSE; | |
755 | } | |
756 | ||
757 | array_init(return_value); | |
758 | ||
759 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &limit) == FAILURE) { | |
760 | return; | |
761 | } | |
762 | ||
763 | list = l = yac_storage_dump(limit); | |
764 | for (; l; l = l->next) { | |
765 | zval *item; | |
766 | MAKE_STD_ZVAL(item); | |
767 | array_init(item); | |
768 | add_assoc_long(item, "index", l->index); | |
769 | add_assoc_long(item, "hash", l->h); | |
770 | add_assoc_long(item, "crc", l->crc); | |
771 | add_assoc_long(item, "ttl", l->ttl); | |
772 | add_assoc_long(item, "k_len", l->k_len); | |
773 | add_assoc_long(item, "v_len", l->v_len); | |
774 | add_assoc_long(item, "size", l->size); | |
775 | add_assoc_string(item, "key", l->key, 1); | |
776 | add_next_index_zval(return_value, item); | |
777 | } | |
778 | ||
779 | yac_storage_free_list(list); | |
780 | return; | |
781 | } | |
782 | /* }}} */ | |
783 | ||
784 | #if 0 | |
785 | only OO-style APIs is supported now | |
786 | /* {{{{ proto bool yac_add(mixed $keys, mixed $value[, int $ttl]) | |
787 | */ | |
788 | PHP_FUNCTION(yac_add) | |
789 | { | |
790 | PHP_MN(yac_add)(INTERNAL_FUNCTION_PARAM_PASSTHRU); | |
791 | } | |
792 | /* }}} */ | |
793 | ||
794 | /* {{{ proto bool yac_set(mixed $keys, mixed $value[, int $ttl]) | |
795 | */ | |
796 | PHP_FUNCTION(yac_set) | |
797 | { | |
798 | PHP_MN(yac_set)(INTERNAL_FUNCTION_PARAM_PASSTHRU); | |
799 | } | |
800 | /* }}} */ | |
801 | ||
802 | /* {{{ proto bool yac_get(mixed $keys[, int &$cas]) | |
803 | */ | |
804 | PHP_FUNCTION(yac_get) | |
805 | { | |
806 | PHP_MN(yac_get)(INTERNAL_FUNCTION_PARAM_PASSTHRU); | |
807 | } | |
808 | /* }}} */ | |
809 | ||
810 | /* {{{ proto bool yac_delete(mixed $keys[, int $delay = 0]) | |
811 | */ | |
812 | PHP_FUNCTION(yac_delete) | |
813 | { | |
814 | PHP_MN(yac_delete)(INTERNAL_FUNCTION_PARAM_PASSTHRU); | |
815 | } | |
816 | /* }}} */ | |
817 | ||
818 | /* {{{ proto bool yac_flush(void) | |
819 | */ | |
820 | PHP_FUNCTION(yac_flush) | |
821 | { | |
822 | PHP_MN(yac_flush)(INTERNAL_FUNCTION_PARAM_PASSTHRU); | |
823 | } | |
824 | /* }}} */ | |
825 | ||
826 | /* {{{ proto bool yac_info(void) | |
827 | */ | |
828 | PHP_FUNCTION(yac_info) | |
829 | { | |
830 | PHP_MN(yac_info)(INTERNAL_FUNCTION_PARAM_PASSTHRU); | |
831 | } | |
832 | /* }}} */ | |
833 | ||
834 | /* {{{ yac_functions[] */ | |
835 | zend_function_entry yac_functions[] = { | |
836 | PHP_FE(yac_add, arginfo_yac_add) | |
837 | PHP_FE(yac_set, arginfo_yac_add) | |
838 | PHP_FE(yac_get, arginfo_yac_get) | |
839 | PHP_FE(yac_delete, arginfo_yac_delete) | |
840 | PHP_FE(yac_flush, arginfo_yac_void) | |
841 | PHP_FE(yac_info, arginfo_yac_void) | |
842 | {NULL, NULL} | |
843 | }; | |
844 | /* }}} */ | |
845 | #endif | |
846 | ||
847 | /** {{{ yac_methods | |
848 | */ | |
849 | zend_function_entry yac_methods[] = { | |
850 | PHP_ME(yac, __construct, arginfo_yac_constructor, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) | |
851 | PHP_ME(yac, add, arginfo_yac_add, ZEND_ACC_PUBLIC) | |
852 | PHP_ME(yac, set, arginfo_yac_add, ZEND_ACC_PUBLIC) | |
853 | PHP_ME(yac, get, arginfo_yac_get, ZEND_ACC_PUBLIC) | |
854 | PHP_ME(yac, delete, arginfo_yac_delete, ZEND_ACC_PUBLIC) | |
855 | PHP_ME(yac, flush, arginfo_yac_void, ZEND_ACC_PUBLIC) | |
856 | PHP_ME(yac, info, arginfo_yac_void, ZEND_ACC_PUBLIC) | |
857 | PHP_ME(yac, dump, arginfo_yac_void, ZEND_ACC_PUBLIC) | |
858 | {NULL, NULL, NULL} | |
859 | }; | |
860 | /* }}} */ | |
861 | ||
862 | /* {{{ PHP_GINIT_FUNCTION | |
863 | */ | |
864 | PHP_GINIT_FUNCTION(yac) | |
865 | { | |
866 | yac_globals->enable = 1; | |
867 | yac_globals->k_msize = (4 * 1024 * 1024); | |
868 | yac_globals->v_msize = (64 * 1024 * 1024); | |
869 | yac_globals->debug = 0; | |
870 | yac_globals->compress_threshold = -1; | |
871 | yac_globals->enable_cli = 0; | |
872 | #ifdef PHP_WIN32 | |
873 | yac_globals->mmap_base = NULL; | |
874 | #endif | |
875 | } | |
876 | /* }}} */ | |
877 | ||
878 | /* {{{ PHP_MINIT_FUNCTION | |
879 | */ | |
880 | PHP_MINIT_FUNCTION(yac) | |
881 | { | |
882 | char *msg; | |
883 | zend_class_entry ce; | |
884 | ||
885 | REGISTER_INI_ENTRIES(); | |
886 | ||
887 | if(!YAC_G(enable_cli) && !strcmp(sapi_module.name, "cli")) { | |
888 | YAC_G(enable) = 0; | |
889 | } | |
890 | ||
891 | if (YAC_G(enable)) { | |
892 | if (!yac_storage_startup(YAC_G(k_msize), YAC_G(v_msize), &msg)) { | |
893 | php_error(E_ERROR, "Shared memory allocator startup failed at '%s': %s", msg, strerror(errno)); | |
894 | return FAILURE; | |
895 | } | |
896 | } | |
897 | ||
898 | REGISTER_STRINGL_CONSTANT("YAC_VERSION", PHP_YAC_VERSION, sizeof(PHP_YAC_VERSION) - 1, CONST_PERSISTENT | CONST_CS); | |
899 | REGISTER_LONG_CONSTANT("YAC_MAX_KEY_LEN", YAC_STORAGE_MAX_KEY_LEN, CONST_PERSISTENT | CONST_CS); | |
900 | REGISTER_LONG_CONSTANT("YAC_MAX_VALUE_RAW_LEN", YAC_ENTRY_MAX_ORIG_LEN, CONST_PERSISTENT | CONST_CS); | |
901 | REGISTER_LONG_CONSTANT("YAC_MAX_RAW_COMPRESSED_LEN", YAC_STORAGE_MAX_ENTRY_LEN, CONST_PERSISTENT | CONST_CS); | |
902 | #if ENABLE_MSGPACK | |
903 | REGISTER_STRINGL_CONSTANT("YAC_SERIALIZER", "PHP", sizeof("MSGPACK") -1, CONST_PERSISTENT | CONST_CS); | |
904 | #else | |
905 | REGISTER_STRINGL_CONSTANT("YAC_SERIALIZER", "PHP", sizeof("PHP") -1, CONST_PERSISTENT | CONST_CS); | |
906 | #endif | |
907 | ||
908 | INIT_CLASS_ENTRY(ce, "Yac", yac_methods); | |
909 | yac_class_ce = zend_register_internal_class(&ce TSRMLS_CC); | |
910 | zend_declare_property_stringl(yac_class_ce, ZEND_STRS(YAC_CLASS_PROPERTY_PREFIX) - 1, "", 0, ZEND_ACC_PROTECTED TSRMLS_CC); | |
911 | ||
912 | return SUCCESS; | |
913 | } | |
914 | /* }}} */ | |
915 | ||
916 | /* {{{ PHP_MSHUTDOWN_FUNCTION | |
917 | */ | |
918 | PHP_MSHUTDOWN_FUNCTION(yac) | |
919 | { | |
920 | UNREGISTER_INI_ENTRIES(); | |
921 | if (YAC_G(enable)) { | |
922 | yac_storage_shutdown(); | |
923 | } | |
924 | return SUCCESS; | |
925 | } | |
926 | /* }}} */ | |
927 | ||
928 | /* {{{ PHP_MINFO_FUNCTION | |
929 | */ | |
930 | PHP_MINFO_FUNCTION(yac) | |
931 | { | |
932 | php_info_print_table_start(); | |
933 | php_info_print_table_header(2, "yac support", "enabled"); | |
934 | php_info_print_table_row(2, "Version", PHP_YAC_VERSION); | |
935 | php_info_print_table_row(2, "Shared Memory", yac_storage_shared_memory_name()); | |
936 | #if ENABLE_MSGPACK | |
937 | php_info_print_table_row(2, "Serializer", "msgpack"); | |
938 | #else | |
939 | php_info_print_table_row(2, "Serializer", "php"); | |
940 | #endif | |
941 | php_info_print_table_end(); | |
942 | ||
943 | DISPLAY_INI_ENTRIES(); | |
944 | ||
945 | if (YAC_G(enable)) { | |
946 | char buf[64]; | |
947 | yac_storage_info *inf; | |
948 | inf = yac_storage_get_info(); | |
949 | ||
950 | php_info_print_table_start(); | |
951 | php_info_print_table_colspan_header(2, "Cache info"); | |
952 | snprintf(buf, sizeof(buf), "%ld", inf->k_msize + inf->v_msize); | |
953 | php_info_print_table_row(2, "Total Shared Memory Usage(memory_size)", buf); | |
954 | snprintf(buf, sizeof(buf), "%ld", inf->k_msize); | |
955 | php_info_print_table_row(2, "Total Shared Memory Usage for keys(keys_memory_size)", buf); | |
956 | snprintf(buf, sizeof(buf), "%ld", inf->v_msize); | |
957 | php_info_print_table_row(2, "Total Shared Memory Usage for values(values_memory_size)", buf); | |
958 | snprintf(buf, sizeof(buf), "%ld", inf->segment_size); | |
959 | php_info_print_table_row(2, "Size of Shared Memory Segment(segment_size)", buf); | |
960 | snprintf(buf, sizeof(buf), "%ld", inf->segments_num); | |
961 | php_info_print_table_row(2, "Number of Segments (segment_num)", buf); | |
962 | snprintf(buf, sizeof(buf), "%ld", inf->slots_size); | |
963 | php_info_print_table_row(2, "Total Slots Number(slots_size)", buf); | |
964 | snprintf(buf, sizeof(buf), "%ld", inf->slots_num); | |
965 | php_info_print_table_row(2, "Total Used Slots(slots_num)", buf); | |
966 | php_info_print_table_end(); | |
967 | ||
968 | yac_storage_free_info(inf); | |
969 | } | |
970 | } | |
971 | /* }}} */ | |
972 | ||
973 | #ifdef COMPILE_DL_YAC | |
974 | ZEND_GET_MODULE(yac) | |
975 | #endif | |
976 | ||
977 | /* {{{ yac_module_entry | |
978 | */ | |
979 | zend_module_entry yac_module_entry = { | |
980 | STANDARD_MODULE_HEADER, | |
981 | "yac", | |
982 | NULL, /* yac_functions, */ | |
983 | PHP_MINIT(yac), | |
984 | PHP_MSHUTDOWN(yac), | |
985 | NULL, | |
986 | NULL, | |
987 | PHP_MINFO(yac), | |
988 | PHP_YAC_VERSION, | |
989 | PHP_MODULE_GLOBALS(yac), | |
990 | PHP_GINIT(yac), | |
991 | NULL, | |
992 | NULL, | |
993 | STANDARD_MODULE_PROPERTIES_EX | |
994 | }; | |
995 | /* }}} */ | |
996 | ||
997 | /* | |
998 | * Local variables: | |
999 | * tab-width: 4 | |
1000 | * c-basic-offset: 4 | |
1001 | * End: | |
1002 | * vim600: noet sw=4 ts=4 fdm=marker | |
1003 | * vim<600: noet sw=4 ts=4 | |
1004 | */ |