Codebase list php-yac / 1d0077f
New upstream version 2.2.1+0.9.2 Ondřej Surý 3 years ago
84 changed file(s) with 5557 addition(s) and 4678 deletion(s). Raw diff Collapse all Expand all
22 <name>yac</name>
33 <channel>pecl.php.net</channel>
44 <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&apos;d better make sure that your product is not very sensitive to that.</description>
5 <description>yac is a fast, lock-free, shared memory user data cache for PHP. it can be used to replace APC or local memcached.</description>
86 <lead>
97 <name>Xinchen Hui</name>
108 <user>laruence</user>
119 <email>laruence@php.net</email>
1210 <active>yes</active>
1311 </lead>
14 <developer>
15 <name>Wei Dai</name>
16 <user>Demon</user>
17 <email>zxcvdavid@gmail.com</email>
18 <active>yes</active>
19 </developer>
20 <date>2020-03-19</date>
21 <time>04:42:02</time>
12 <date>2020-05-15</date>
13 <time>04:17:14</time>
2214 <version>
23 <release>2.0.4</release>
24 <api>2.0.4</api>
15 <release>2.2.1</release>
16 <api>2.2.1</api>
2517 </version>
2618 <stability>
27 <release>beta</release>
28 <api>beta</api>
19 <release>stable</release>
20 <api>stable</api>
2921 </stability>
3022 <license uri="http://www.php.net/license">PHP</license>
3123 <notes>
32 - Fixed PHP-7.4 windows build
24 - Refactor key manipulation, avoding memory allocation
25 - Refactor Yac::__set/__get by using native objects_handler
3326 </notes>
3427 <contents>
3528 <dir name="/">
3730 <file md5sum="ba23da7a1141b5b0b1222641f9948d46" name="storage/allocator/allocators/mmap.c" role="src" />
3831 <file md5sum="d719e0643e649a89ad307ee41b82e0fd" name="storage/allocator/allocators/shm.c" role="src" />
3932 <file md5sum="5aa4302988e0a26b7673741de836a4d2" name="storage/allocator/yac_allocator.h" role="src" />
40 <file md5sum="135ac2305a28288ae89099679e0e070b" name="storage/allocator/yac_allocator.c" role="src" />
41 <file md5sum="6a45b887b874e2341f0d4123016d2a50" name="storage/yac_storage.h" role="src" />
42 <file md5sum="cd0ba257e1ced1d07188f7bfb3d5f6fd" name="storage/yac_storage.c" role="src" />
33 <file md5sum="65411ac45fa24b952f0fe8a570b5f2b8" name="storage/allocator/yac_allocator.c" role="src" />
34 <file md5sum="38742caebaa3a6cad4e298c9f7dd1ec4" name="storage/yac_storage.h" role="src" />
35 <file md5sum="fb944b23ed1d05c06e76e5317f3c5136" name="storage/yac_storage.c" role="src" />
36 <file md5sum="2c7bdae5e04ba2dbd2dfd95b9545b320" name="storage/yac_atomic.h" role="src" />
4337 <file md5sum="543b3b1b8571c4b9c02eafee4a6f3fa3" name="compressor/fastlz/LICENSE" role="doc" />
44 <file md5sum="fa4d2340c50946340603066b02f7e6dd" name="compressor/fastlz/README.TXT" role="doc" />
38 <file md5sum="4c76809627c49a1b1082a20699fb4482" name="compressor/fastlz/README.TXT" role="doc" />
4539 <file md5sum="d49275e3dcc1d23d6ce0041648be8e14" name="compressor/fastlz/fastlz.h" role="src" />
4640 <file md5sum="89384a08695fc238e9fbc41b0a14b5a7" name="compressor/fastlz/fastlz.c" role="src" />
47 <file md5sum="bf1cbe22980777ba06be4a1d7d03266d" name="serializer/yac_serializer.h" role="src" />
48 <file md5sum="b0f27e20d0823e891413aee3fe97a120" name="serializer/php.c" role="src" />
49 <file md5sum="af01e88cd9b050363a069a526d07989b" name="serializer/msgpack.c" role="src" />
41 <file md5sum="ceccb8a1237d9291ed527b12184cac7c" name="serializer/yac_serializer.h" role="src" />
42 <file md5sum="6bb7b710c83d297c24a6bb7b6d906235" name="serializer/php.c" role="src" />
43 <file md5sum="eb1f7ba8afb1d199e108ea2a8ed5ef9e" name="serializer/msgpack.c" role="src" />
44 <file md5sum="f4433aa570612f012eb1a9b57d4ce889" name="serializer/json.c" role="src" />
45 <file md5sum="292f300c457afe1c5d7b6c52dd7a9b6d" name="serializer/igbinary.c" role="src" />
5046 <file md5sum="4ff407df4fb138f1fdefa97a72e4769f" name="tests/001.phpt" role="test" />
51 <file md5sum="ad4a91d346d21c285ab21b4befcb538e" name="tests/002.phpt" role="test" />
52 <file md5sum="59f0d14be6b86915ded044110b9148da" name="tests/003.phpt" role="test" />
47 <file md5sum="702ee40db31edb24c2c633ae6ce9a29e" name="tests/002.phpt" role="test" />
48 <file md5sum="809b97bbef7dd58aafd905660043446b" name="tests/003.phpt" role="test" />
5349 <file md5sum="69b6eab19f3e907097fd41ec6dfc024a" name="tests/004.phpt" role="test" />
5450 <file md5sum="0c45c663d4bb4580344278d93d72697c" name="tests/005.phpt" role="test" />
5551 <file md5sum="44354a5ac454a1bce3b00d8f5f9d6c4c" name="tests/006.phpt" role="test" />
5955 <file md5sum="1bf41dadf4a96d8730d37d89fb8257a6" name="tests/010.phpt" role="test" />
6056 <file md5sum="0f47511cd434d57d01f78ad8a65a13cb" name="tests/011.phpt" role="test" />
6157 <file md5sum="4c3a616f6563f090ccf781ed6a4671af" name="tests/012.phpt" role="test" />
62 <file md5sum="717d306b5ea2e5ae1aaef6894c3aaf2a" name="tests/013.phpt" role="test" />
63 <file md5sum="56f31a4a48c4d28a14e3939ce87abdb3" name="tests/014.phpt" role="test" />
64 <file md5sum="88ff06bab70e76cc0aa6e79aa4ee7e21" name="tests/015.phpt" role="test" />
58 <file md5sum="59924bf44844ea20bf3ab073e9bd28e3" name="tests/013.phpt" role="test" />
59 <file md5sum="07101b0387d80a78d298472b50e10fc7" name="tests/014.phpt" role="test" />
60 <file md5sum="5493a51288d0b3950c3bb2013eb54571" name="tests/015.phpt" role="test" />
61 <file md5sum="e8be5f292141214466103bf22d38c93e" name="tests/016.phpt" role="test" />
62 <file md5sum="6c78da4fb6a77aa333d60c12aeec3e10" name="tests/017.phpt" role="test" />
63 <file md5sum="d9f4f5ce592bffa74cb2a41cedadea0d" name="tests/018.phpt" role="test" />
64 <file md5sum="6c8431543f431d8805dcceada3ab944f" name="tests/019.phpt" role="test" />
65 <file md5sum="2705ab4cd8d284adcc48ee9afcd8d482" name="tests/020.phpt" role="test" />
66 <file md5sum="6bb18debb309f320cd2061ba103f7e67" name="tests/021.phpt" role="test" />
67 <file md5sum="544fd003bea3e33b8c4ed4dc1e5126b3" name="tests/022.phpt" role="test" />
68 <file md5sum="bd7b561c2df8c52bdec8c52fa2909733" name="tests/023.phpt" role="test" />
6569 <file md5sum="4c4242640be3dfdccf4b46600dbe3682" name="tests/issue012.phpt" role="test" />
6670 <file md5sum="ac36c858a802d2d8c791b4de479adb59" name="config.w32" role="src" />
6771 <file md5sum="dd34a70236f008af999de817b93a5e3a" name="LICENSE" role="doc" />
6872 <file md5sum="e4313698b2307a62bdbac09fd596ae53" name="CREDITS" role="doc" />
69 <file md5sum="38d7ad86c61e3e0a6fc0e95dffd5f90c" name="config.m4" role="src" />
70 <file md5sum="5f7b041ae7f25719318e368f38cb5fdd" name="yac.c" role="src" />
71 <file md5sum="3e22c72def09200431f3f971c88e52da" name="php_yac.h" role="src" />
73 <file md5sum="655d9ecb38f3f2fb2025d8f1202ca243" name="config.m4" role="src" />
74 <file md5sum="05be4e0f96781cb052139b4dc5bd0148" name="yac.c" role="src" />
75 <file md5sum="8ea02c4b57d3b2faa1ad89ecaf929a6d" name="php_yac.h" role="src" />
7276 </dir>
7377 </contents>
7478 <dependencies>
8286 </required>
8387 </dependencies>
8488 <providesextension>yac</providesextension>
85 <extsrcrelease />
89 <extsrcrelease>
90 <configureoption default="no" name="enable-igbinary" prompt="enable igbinary serializer support?" />
91 <configureoption default="no" name="enable-json" prompt="enable json serializer support?" />
92 <configureoption default="no" name="enable-msgpack" prompt="enable msgpack serializer support?" />
93 </extsrcrelease>
8694 <changelog>
95 <release>
96 <date>2020-03-31</date>
97 <version>
98 <release>2.2.1</release>
99 <api>2.2.1</api>
100 </version>
101 <stability>
102 <release>stable</release>
103 <api>stable</api>
104 </stability>
105 <license uri="http://www.php.net/license">PHP License</license>
106 <notes>
107 - Refactor key manipulation, avoding memory allocation
108 - Refactor Yac::__set/__get by using native objects_handler
109 </notes>
110 </release>
111 <release>
112 <date>2020-03-31</date>
113 <version>
114 <release>2.2.0</release>
115 <api>2.2.0</api>
116 </version>
117 <stability>
118 <release>stable</release>
119 <api>stable</api>
120 </stability>
121 <license uri="http://www.php.net/license">PHP License</license>
122 <notes>
123 - Added json serializer
124 - Added igbinary serializer
125 - change yac.serilalizer to string, &quot;php&quot;, &quot;json&quot; etc
126 </notes>
127 </release>
128 <release>
129 <date>2020-03-27</date>
130 <version>
131 <release>2.1.2</release>
132 <api>2.1.2</api>
133 </version>
134 <stability>
135 <release>stable</release>
136 <api>stable</api>
137 </stability>
138 <license uri="http://www.php.net/license">PHP License</license>
139 <notes>
140 - Fixed compiler warning of redefinition of macros
141 - Fixed crc32c only pick the first byte
142 - Also use crc32_u32 in 64 bits
143 </notes>
144 </release>
145 <release>
146 <date>2020-03-25</date>
147 <version>
148 <release>2.1.1</release>
149 <api>2.1.1</api>
150 </version>
151 <stability>
152 <release>stable</release>
153 <api>stable</api>
154 </stability>
155 <license uri="http://www.php.net/license">PHP License</license>
156 <notes>
157 - Fixed Build in 32bits
158 </notes>
159 </release>
160 <release>
161 <date>2020-03-25</date>
162 <version>
163 <release>2.1.0</release>
164 <api>2.1.0</api>
165 </version>
166 <stability>
167 <release>stable</release>
168 <api>stable</api>
169 </stability>
170 <license uri="http://www.php.net/license">PHP License</license>
171 <notes>
172 - Implemnented CAS based lock-free protection
173 - Use SSE4.2 _mm_crc32 instead of normal crc32 to make speedup
174 - Some optimization to avoding memory usage
175 </notes>
176 </release>
87177 <release>
88178 <date>2020-03-19</date>
89179 <version>
+0
-4
yac-2.0.4/CREDITS less more
0 yac
1
2 Xinchen Hui
3 Wei Dai
+0
-68
yac-2.0.4/LICENSE less more
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
-24
yac-2.0.4/compressor/fastlz/LICENSE less more
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
-75
yac-2.0.4/compressor/fastlz/README.TXT less more
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
-551
yac-2.0.4/compressor/fastlz/fastlz.c less more
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
-100
yac-2.0.4/compressor/fastlz/fastlz.h less more
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
-218
yac-2.0.4/config.m4 less more
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, whether to use system FastLZ library,
7 [ --with-system-fastlz Use system FastLZ library], 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 PHP_ADD_BUILD_DIR([$ext_builddir/storage])
212 PHP_ADD_BUILD_DIR([$ext_builddir/storage/allocator])
213 PHP_ADD_BUILD_DIR([$ext_builddir/storage/allocator/allocators])
214 PHP_ADD_BUILD_DIR([$ext_builddir/serializer])
215 PHP_ADD_BUILD_DIR([$ext_builddir/compressor])
216 PHP_ADD_BUILD_DIR([$ext_builddir/compressor/fastlz])
217 fi
+0
-28
yac-2.0.4/config.w32 less more
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
-80
yac-2.0.4/php_yac.h less more
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 "2.0.4"
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 zend_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
-56
yac-2.0.4/serializer/msgpack.c less more
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 "zend_smart_str.h" /* for smart_str */
29
30 #include "yac_serializer.h"
31
32 extern void php_msgpack_serialize(smart_str *buf, zval *val);
33 extern void php_msgpack_unserialize(zval *return_value, char *str, size_t str_len);
34
35 int yac_serializer_msgpack_pack(zval *pzval, smart_str *buf, char **msg) /* {{{ */ {
36 php_msgpack_serialize(buf, pzval);
37 return 1;
38 } /* }}} */
39
40 zval * yac_serializer_msgpack_unpack(char *content, size_t len, char **msg, zval *rv) /* {{{ */ {
41 ZVAL_NULL(rv);
42 php_msgpack_unserialize(rv, content, len);
43 return rv;
44 } /* }}} */
45
46 #endif
47
48 /*
49 * Local variables:
50 * tab-width: 4
51 * c-basic-offset: 4
52 * End:
53 * vim600: noet sw=4 ts=4 fdm=marker
54 * vim<600: noet sw=4 ts=4
55 */
+0
-70
yac-2.0.4/serializer/php.c less more
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 "zend_smart_str.h"
29
30 #include "yac_serializer.h"
31
32 int yac_serializer_php_pack(zval *pzval, smart_str *buf, char **msg) /* {{{ */ {
33 php_serialize_data_t var_hash;
34
35 PHP_VAR_SERIALIZE_INIT(var_hash);
36 php_var_serialize(buf, pzval, &var_hash);
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, zval *rv) /* {{{ */ {
43 const unsigned char *p;
44 php_unserialize_data_t var_hash;
45 p = (const unsigned char*)content;
46
47 ZVAL_FALSE(rv);
48 PHP_VAR_UNSERIALIZE_INIT(var_hash);
49 if (!php_var_unserialize(rv, &p, p + len, &var_hash)) {
50 zval_ptr_dtor(rv);
51 PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
52 spprintf(msg, 0, "unpack error at offset %ld of %ld bytes", (long)((char*)p - content), len);
53 return NULL;
54 }
55 PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
56
57 return rv;
58 } /* }}} */
59
60 #endif
61
62 /*
63 * Local variables:
64 * tab-width: 4
65 * c-basic-offset: 4
66 * End:
67 * vim600: noet sw=4 ts=4 fdm=marker
68 * vim<600: noet sw=4 ts=4
69 */
+0
-41
yac-2.0.4/serializer/yac_serializer.h less more
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);
25 zval * yac_serializer_msgpack_unpack(char *content, size_t len, char **msg, zval *rv);
26 #else
27 int yac_serializer_php_pack(zval *pzval, smart_str *buf, char **msg);
28 zval * yac_serializer_php_unpack(char *content, size_t len, char **msg, zval *rv);
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
-303
yac-2.0.4/storage/allocator/allocators/createfilemapping.c less more
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 <demon@php.net> |
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 static char newname[MAXPATHLEN + UNLEN + 4];
45 char uname[UNLEN + 1];
46 DWORD unsize = UNLEN;
47
48 GetUserName(uname, &unsize);
49 snprintf(newname, sizeof(newname) - 1, "%s@%s", name, uname);
50 return newname;
51 }
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
68 static int yac_shared_alloc_reattach(size_t requested_size, char **error_in) /* {{{ */ {
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
112 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) /* {{{ */ {
113 int ret;
114 unsigned long allocate_size, occupied_size = 0;
115 unsigned int i, segment_size, segments_num = 1024, is_reattach = 0;
116 int map_retries = 0;
117 yac_shared_segment_create_file first_segment;
118 void *default_mapping_base_set[] = {0, 0};
119 /* TODO:
120 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
121 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
122 desired. Not done yet, @zend refused but did not remember the exact reason, pls add info here if one of you know why :)
123 */
124 #if defined(_WIN64)
125 void *vista_mapping_base_set[] = { (void *) 0x0000100000000000, (void *) 0x0000200000000000, (void *) 0x0000300000000000, (void *) 0x0000700000000000, 0 };
126 #else
127 void *vista_mapping_base_set[] = { (void *) 0x20000000, (void *) 0x21000000, (void *) 0x30000000, (void *) 0x31000000, (void *) 0x50000000, 0 };
128 #endif
129 void **wanted_mapping_base = default_mapping_base_set;
130
131
132 k_size = YAC_SMM_ALIGNED_SIZE(k_size);
133 v_size = YAC_SMM_ALIGNED_SIZE(v_size);
134 while ((v_size / segments_num) < YAC_SMM_SEGMENT_MIN_SIZE) {
135 segments_num >>= 1;
136 }
137
138 segment_size = v_size / segments_num;
139 ++segments_num;
140
141 allocate_size = k_size + v_size;
142
143 /* Mapping retries: When Apache2 restarts, the parent process startup routine
144 can be called before the child process is killed. In this case, the map will fail
145 and we have to sleep some time (until the child releases the mapping object) and retry.*/
146 do {
147 memfile = OpenFileMapping(FILE_MAP_WRITE, 0, create_name_with_username(ACCEL_FILEMAP_NAME));
148 if (memfile == NULL) {
149 break;
150 }
151
152 ret = yac_shared_alloc_reattach((size_t)k_size, error_in);
153 if (ret == ALLOC_FAIL_MAPPING) {
154 /* Mapping failed, wait for mapping object to get freed and retry */
155 CloseHandle(memfile);
156 memfile = NULL;
157 Sleep(1000 * (map_retries + 1));
158 } else if (ret == SUCCESSFULLY_REATTACHED) {
159 is_reattach = 1;
160 break;
161 } else {
162 return ret;
163 }
164 } while (++map_retries < MAX_MAP_RETRIES);
165
166 if (map_retries == MAX_MAP_RETRIES) {
167 *error_in = "OpenFileMapping";
168 return 0;
169 }
170
171 *shared_segments_p = (yac_shared_segment_create_file *)calloc(1, segments_num * sizeof(yac_shared_segment_create_file));
172 if(!*shared_segments_p) {
173 *error_in = "calloc";
174 return 0;
175 }
176 *shared_segments_count = segments_num;
177
178 /* Starting from windows Vista, heap randomization occurs which might cause our mapping base to
179 be taken (fail to map). So under Vista, we try to map into a hard coded predefined addresses
180 in high memory. */
181 if (!YAC_G(mmap_base) || !*YAC_G(mmap_base)) {
182 do {
183 OSVERSIONINFOEX osvi;
184 SYSTEM_INFO si;
185
186 ZeroMemory(&si, sizeof(SYSTEM_INFO));
187 ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
188
189 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
190
191 if (! GetVersionEx ((OSVERSIONINFO *) &osvi)) {
192 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
193 if (!GetVersionEx((OSVERSIONINFO *)&osvi)) {
194 break;
195 }
196 }
197
198 GetSystemInfo(&si);
199
200 /* Are we running Vista ? */
201 if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion == 6) {
202 wanted_mapping_base = vista_mapping_base_set;
203 }
204 } while (0);
205 } else {
206 char *s = YAC_G(mmap_base);
207
208 /* skip leading 0x, %p assumes hexdeciaml format anyway */
209 if (*s == '0' && *(s + 1) == 'x') {
210 s += 2;
211 }
212 if (sscanf(s, "%p", &default_mapping_base_set[0]) != 1) {
213 *error_in = "mapping";
214 return 0;
215 }
216 }
217
218 if (is_reattach == 0) {
219 memfile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, allocate_size, create_name_with_username(ACCEL_FILEMAP_NAME));
220 if (memfile == NULL) {
221 *error_in = "CreateFileMapping";
222 return 0;
223 }
224
225 do {
226 first_segment.common.p = mapping_base = MapViewOfFileEx(memfile, FILE_MAP_ALL_ACCESS, 0, 0, 0, *wanted_mapping_base);
227 if (wanted_mapping_base == NULL) {
228 break;
229 }
230 *wanted_mapping_base++;
231 } while (!mapping_base);
232 }
233
234 if(mapping_base == NULL) {
235 *error_in = "MapViewOfFileEx";
236 return 0;
237 } else {
238 char *mmap_base_file = get_mmap_base_file();
239 FILE *fp = fopen(mmap_base_file, "w");
240 if (!fp) {
241 *error_in = "get_mmap_base_file";
242 return 0;
243 }
244 fprintf(fp, "%p", mapping_base);
245 fclose(fp);
246 }
247
248 first_segment.common.p = mapping_base;
249 first_segment.size = allocate_size;
250 first_segment.common.size = k_size;
251 first_segment.common.pos = 0;
252
253 (*shared_segments_p)[0] = first_segment;
254
255 occupied_size = k_size;
256 for (i = 1; i < segments_num; i++) {
257 (*shared_segments_p)[i].size = 0;
258 (*shared_segments_p)[i].common.pos = 0;
259 (*shared_segments_p)[i].common.p = (void *)((char *)first_segment.common.p + occupied_size);
260 if ((allocate_size - occupied_size) >= YAC_SMM_ALIGNED_SIZE(segment_size)) {
261 (*shared_segments_p)[i].common.size = YAC_SMM_ALIGNED_SIZE(segment_size);
262 occupied_size += YAC_SMM_ALIGNED_SIZE(segment_size);
263 } else {
264 (*shared_segments_p)[i].common.size = (allocate_size - occupied_size);
265 break;
266 }
267 }
268
269 return 1;
270 }
271 /* }}} */
272
273 static int detach_segment(yac_shared_segment *shared_segment) /* {{{ */ {
274 if (!shared_segment->size && mapping_base) {
275 UnmapViewOfFile(mapping_base);
276 CloseHandle(memfile);
277 }
278 return 0;
279 }
280 /* }}} */
281
282 static unsigned long segment_type_size(void) /* {{{ */ {
283 return sizeof(yac_shared_segment_create_file);
284 }
285 /* }}} */
286
287 yac_shared_memory_handlers yac_alloc_create_file_handlers = /* {{{ */ {
288 (create_segments_t)create_segments,
289 detach_segment,
290 segment_type_size
291 };
292 /* }}} */
293 #endif /* USE_CREATE_FILE */
294
295 /*
296 * Local variables:
297 * tab-width: 4
298 * c-basic-offset: 4
299 * End:
300 * vim600: noet sw=4 ts=4 fdm=marker
301 * vim<600: noet sw=4 ts=4
302 */
+0
-125
yac-2.0.4/storage/allocator/allocators/mmap.c less more
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 unsigned long allocate_size, occupied_size = 0;
44 unsigned int i, segment_size, segments_num = 1024;
45 yac_shared_segment_mmap first_segment;
46
47 k_size = YAC_SMM_ALIGNED_SIZE(k_size);
48 v_size = YAC_SMM_ALIGNED_SIZE(v_size);
49 while ((v_size / segments_num) < YAC_SMM_SEGMENT_MIN_SIZE) {
50 segments_num >>= 1;
51 }
52
53 segment_size = v_size / segments_num;
54 ++segments_num;
55
56 allocate_size = k_size + v_size;
57
58 first_segment.common.p = mmap(0, allocate_size, PROT_READ | PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
59 if (first_segment.common.p == MAP_FAILED) {
60 *error_in = "mmap";
61 return 0;
62 }
63 first_segment.size = allocate_size;
64 first_segment.common.size = k_size;
65 first_segment.common.pos = 0;
66
67 *shared_segments_p = (yac_shared_segment_mmap *)calloc(1, segments_num * sizeof(yac_shared_segment_mmap));
68 if (!*shared_segments_p) {
69 munmap(first_segment.common.p, first_segment.size);
70 *error_in = "calloc";
71 return 0;
72 } else {
73 *shared_segments_p[0] = first_segment;
74 }
75 *shared_segments_count = segments_num;
76
77 occupied_size = k_size;
78 for (i = 1; i < segments_num; i++) {
79 (*shared_segments_p)[i].size = 0;
80 (*shared_segments_p)[i].common.pos = 0;
81 (*shared_segments_p)[i].common.p = first_segment.common.p + occupied_size;
82 if ((allocate_size - occupied_size) >= YAC_SMM_ALIGNED_SIZE(segment_size)) {
83 (*shared_segments_p)[i].common.size = YAC_SMM_ALIGNED_SIZE(segment_size);
84 occupied_size += YAC_SMM_ALIGNED_SIZE(segment_size);
85 } else {
86 (*shared_segments_p)[i].common.size = (allocate_size - occupied_size);
87 break;
88 }
89 }
90
91 return 1;
92 }
93 /* }}} */
94
95 static int detach_segment(yac_shared_segment *shared_segment) /* {{{ */ {
96 if (shared_segment->size) {
97 munmap(shared_segment->p, shared_segment->size);
98 }
99 return 0;
100 }
101 /* }}} */
102
103 static unsigned long segment_type_size(void) /* {{{ */ {
104 return sizeof(yac_shared_segment_mmap);
105 }
106 /* }}} */
107
108 yac_shared_memory_handlers yac_alloc_mmap_handlers = /* {{{ */ {
109 (create_segments_t)create_segments,
110 detach_segment,
111 segment_type_size
112 };
113 /* }}} */
114
115 #endif /* USE_MMAP */
116
117 /*
118 * Local variables:
119 * tab-width: 4
120 * c-basic-offset: 4
121 * End:
122 * vim600: noet sw=4 ts=4 fdm=marker
123 * vim<600: noet sw=4 ts=4
124 */
+0
-188
yac-2.0.4/storage/allocator/allocators/shm.c less more
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
-207
yac-2.0.4/storage/allocator/yac_allocator.c less more
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
-97
yac-2.0.4/storage/allocator/yac_allocator.h less more
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
-629
yac-2.0.4/storage/yac_storage.c less more
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 uint64_t 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 uint64_t yac_inline_hash_func2(char *key, uint32_t len) {
142 register uint64_t 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 uint64_t 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 uint32_t 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 uint64_t 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 uint32_t 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 uint64_t 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 = (uint64_t)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 uint32_t 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 uint32_t i;
473 uint64_t 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
-129
yac-2.0.4/storage/yac_storage.h less more
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
-21
yac-2.0.4/tests/001.phpt less more
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
-92
yac-2.0.4/tests/002.phpt less more
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
-48
yac-2.0.4/tests/003.phpt less more
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
-38
yac-2.0.4/tests/004.phpt less more
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
-45
yac-2.0.4/tests/005.phpt less more
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 %s error:%sObject of class stdClass could not be converted to string in %s005.php%A
+0
-32
yac-2.0.4/tests/006.phpt less more
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
-41
yac-2.0.4/tests/007.phpt less more
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
-39
yac-2.0.4/tests/008.phpt less more
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
-39
yac-2.0.4/tests/009.phpt less more
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
-35
yac-2.0.4/tests/010.phpt less more
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
-38
yac-2.0.4/tests/011.phpt less more
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
-33
yac-2.0.4/tests/012.phpt less more
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
-16
yac-2.0.4/tests/013.phpt less more
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
-26
yac-2.0.4/tests/014.phpt less more
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
-22
yac-2.0.4/tests/015.phpt less more
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
-24
yac-2.0.4/tests/issue012.phpt less more
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
-1064
yac-2.0.4/yac.c less more
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 "zend_smart_str.h"
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_setter, 0, 0, 2)
58 ZEND_ARG_INFO(0, key)
59 ZEND_ARG_INFO(0, value)
60 ZEND_END_ARG_INFO()
61
62 ZEND_BEGIN_ARG_INFO_EX(arginfo_yac_get, 0, 0, 1)
63 ZEND_ARG_INFO(0, keys)
64 ZEND_END_ARG_INFO()
65
66 ZEND_BEGIN_ARG_INFO_EX(arginfo_yac_getter, 0, 0, 1)
67 ZEND_ARG_INFO(0, key)
68 ZEND_END_ARG_INFO()
69
70 ZEND_BEGIN_ARG_INFO_EX(arginfo_yac_delete, 0, 0, 1)
71 ZEND_ARG_INFO(0, keys)
72 ZEND_ARG_INFO(0, ttl)
73 ZEND_END_ARG_INFO()
74
75 ZEND_BEGIN_ARG_INFO_EX(arginfo_yac_void, 0, 0, 0)
76 ZEND_END_ARG_INFO()
77 /* }}} */
78
79 static PHP_INI_MH(OnChangeKeysMemoryLimit) /* {{{ */ {
80 if (new_value) {
81 YAC_G(k_msize) = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
82 }
83 return SUCCESS;
84 }
85 /* }}} */
86
87 static PHP_INI_MH(OnChangeValsMemoryLimit) /* {{{ */ {
88 if (new_value) {
89 YAC_G(v_msize) = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
90 }
91 return SUCCESS;
92 }
93 /* }}} */
94
95 static PHP_INI_MH(OnChangeCompressThreshold) /* {{{ */ {
96 if (new_value) {
97 YAC_G(compress_threshold) = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
98 if (YAC_G(compress_threshold) < YAC_MIN_COMPRESS_THRESHOLD) {
99 YAC_G(compress_threshold) = YAC_MIN_COMPRESS_THRESHOLD;
100 }
101 }
102 return SUCCESS;
103 }
104 /* }}} */
105
106 /* {{{ PHP_INI
107 */
108 PHP_INI_BEGIN()
109 STD_PHP_INI_BOOLEAN("yac.enable", "1", PHP_INI_SYSTEM, OnUpdateBool, enable, zend_yac_globals, yac_globals)
110 STD_PHP_INI_BOOLEAN("yac.debug", "0", PHP_INI_ALL, OnUpdateBool, debug, zend_yac_globals, yac_globals)
111 STD_PHP_INI_ENTRY("yac.keys_memory_size", "4M", PHP_INI_SYSTEM, OnChangeKeysMemoryLimit, k_msize, zend_yac_globals, yac_globals)
112 STD_PHP_INI_ENTRY("yac.values_memory_size", "64M", PHP_INI_SYSTEM, OnChangeValsMemoryLimit, v_msize, zend_yac_globals, yac_globals)
113 STD_PHP_INI_ENTRY("yac.compress_threshold", "-1", PHP_INI_SYSTEM, OnChangeCompressThreshold, compress_threshold, zend_yac_globals, yac_globals)
114 STD_PHP_INI_ENTRY("yac.enable_cli", "0", PHP_INI_SYSTEM, OnUpdateBool, enable_cli, zend_yac_globals, yac_globals)
115 PHP_INI_END()
116 /* }}} */
117
118 static int yac_add_impl(zend_string *prefix, zend_string *key, zval *value, int ttl, int add) /* {{{ */ {
119 int ret = 0, flag = Z_TYPE_P(value);
120 char *msg;
121 time_t tv;
122 zend_string *prefix_key;
123
124 if ((ZSTR_LEN(key) + prefix->len) > YAC_STORAGE_MAX_KEY_LEN) {
125 php_error_docref(NULL, E_WARNING, "Key%s can not be longer than %d bytes",
126 prefix->len? "(include prefix)" : "", YAC_STORAGE_MAX_KEY_LEN);
127 return ret;
128 }
129
130 if (prefix->len) {
131 prefix_key = strpprintf(YAC_STORAGE_MAX_KEY_LEN, "%s%s", ZSTR_VAL(prefix), ZSTR_VAL(key));
132 key = prefix_key;
133 }
134
135 tv = time(NULL);
136 switch (Z_TYPE_P(value)) {
137 case IS_NULL:
138 case IS_TRUE:
139 case IS_FALSE:
140 ret = yac_storage_update(ZSTR_VAL(key), ZSTR_LEN(key), (char *)&flag, sizeof(int), flag, ttl, add, tv);
141 break;
142 case IS_LONG:
143 ret = yac_storage_update(ZSTR_VAL(key), ZSTR_LEN(key), (char *)&Z_LVAL_P(value), sizeof(long), flag, ttl, add, tv);
144 break;
145 case IS_DOUBLE:
146 ret = yac_storage_update(ZSTR_VAL(key), ZSTR_LEN(key), (char *)&Z_DVAL_P(value), sizeof(double), flag, ttl, add, tv);
147 break;
148 case IS_STRING:
149 #ifdef IS_CONSTANT
150 case IS_CONSTANT:
151 #endif
152 {
153 if (Z_STRLEN_P(value) > YAC_G(compress_threshold) || Z_STRLEN_P(value) > YAC_STORAGE_MAX_ENTRY_LEN) {
154 int compressed_len;
155 char *compressed;
156
157 /* if longer than this, then we can not stored the length in flag */
158 if (Z_STRLEN_P(value) > YAC_ENTRY_MAX_ORIG_LEN) {
159 php_error_docref(NULL, E_WARNING, "Value is too long(%ld bytes) to be stored", Z_STRLEN_P(value));
160 if (prefix->len) {
161 zend_string_release(prefix_key);
162 }
163 return ret;
164 }
165
166 compressed = emalloc(Z_STRLEN_P(value) * 1.05);
167 compressed_len = fastlz_compress(Z_STRVAL_P(value), Z_STRLEN_P(value), compressed);
168 if (!compressed_len || compressed_len > Z_STRLEN_P(value)) {
169 php_error_docref(NULL, E_WARNING, "Compression failed");
170 efree(compressed);
171 if (prefix->len) {
172 zend_string_release(prefix_key);
173 }
174 return ret;
175 }
176
177 if (compressed_len > YAC_STORAGE_MAX_ENTRY_LEN) {
178 php_error_docref(NULL, E_WARNING, "Value is too long(%ld bytes) to be stored", Z_STRLEN_P(value));
179 efree(compressed);
180 if (prefix->len) {
181 zend_string_release(prefix_key);
182 }
183 return ret;
184 }
185
186 flag |= YAC_ENTRY_COMPRESSED;
187 flag |= (Z_STRLEN_P(value) << YAC_ENTRY_ORIG_LEN_SHIT);
188 ret = yac_storage_update(ZSTR_VAL(key), ZSTR_LEN(key), compressed, compressed_len, flag, ttl, add, tv);
189 efree(compressed);
190 } else {
191 ret = yac_storage_update(ZSTR_VAL(key), ZSTR_LEN(key), Z_STRVAL_P(value), Z_STRLEN_P(value), flag, ttl, add, tv);
192 }
193 }
194 break;
195 case IS_ARRAY:
196 #ifdef IS_CONSTANT_ARRAY
197 case IS_CONSTANT_ARRAY:
198 #endif
199 case IS_OBJECT:
200 {
201 smart_str buf = {0};
202 #if ENABLE_MSGPACK
203 if (yac_serializer_msgpack_pack(value, &buf, &msg))
204 #else
205
206 if (yac_serializer_php_pack(value, &buf, &msg))
207 #endif
208 {
209 if (buf.s->len > YAC_G(compress_threshold) || buf.s->len > YAC_STORAGE_MAX_ENTRY_LEN) {
210 int compressed_len;
211 char *compressed;
212
213 if (buf.s->len > YAC_ENTRY_MAX_ORIG_LEN) {
214 php_error_docref(NULL, E_WARNING, "Value is too big to be stored");
215 if (prefix->len) {
216 zend_string_release(prefix_key);
217 }
218 return ret;
219 }
220
221 compressed = emalloc(buf.s->len * 1.05);
222 compressed_len = fastlz_compress(ZSTR_VAL(buf.s), ZSTR_LEN(buf.s), compressed);
223 if (!compressed_len || compressed_len > buf.s->len) {
224 php_error_docref(NULL, E_WARNING, "Compression failed");
225 efree(compressed);
226 if (prefix->len) {
227 zend_string_release(prefix_key);
228 }
229 return ret;
230 }
231
232 if (compressed_len > YAC_STORAGE_MAX_ENTRY_LEN) {
233 php_error_docref(NULL, E_WARNING, "Value is too big to be stored");
234 efree(compressed);
235 if (prefix->len) {
236 zend_string_release(prefix_key);
237 }
238 return ret;
239 }
240
241 flag |= YAC_ENTRY_COMPRESSED;
242 flag |= (buf.s->len << YAC_ENTRY_ORIG_LEN_SHIT);
243 ret = yac_storage_update(ZSTR_VAL(key), ZSTR_LEN(key), compressed, compressed_len, flag, ttl, add, tv);
244 efree(compressed);
245 } else {
246 ret = yac_storage_update(ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(buf.s), ZSTR_LEN(buf.s), flag, ttl, add, tv);
247 }
248 smart_str_free(&buf);
249 } else {
250 php_error_docref(NULL, E_WARNING, "Serialization failed");
251 smart_str_free(&buf);
252 }
253 }
254 break;
255 case IS_RESOURCE:
256 php_error_docref(NULL, E_WARNING, "Type 'IS_RESOURCE' cannot be stored");
257 break;
258 default:
259 php_error_docref(NULL, E_WARNING, "Unsupported valued type to be stored '%d'", flag);
260 break;
261 }
262
263 if (prefix->len) {
264 zend_string_release(prefix_key);
265 }
266
267 return ret;
268 }
269 /* }}} */
270
271 static int yac_add_multi_impl(zend_string *prefix, zval *kvs, int ttl, int add) /* {{{ */ {
272 HashTable *ht = Z_ARRVAL_P(kvs);
273 zend_string *key;
274 zend_ulong idx;
275 zval *value;
276
277 ZEND_HASH_FOREACH_KEY_VAL(ht, idx, key, value) {
278 uint32_t should_free = 0;
279 if (!key) {
280 key = strpprintf(0, "%lu", idx);
281 should_free = 1;
282 }
283 if (yac_add_impl(prefix, key, value, ttl, add)) {
284 if (should_free) {
285 zend_string_release(key);
286 }
287 continue;
288 } else {
289 if (should_free) {
290 zend_string_release(key);
291 }
292 return 0;
293 }
294 } ZEND_HASH_FOREACH_END();
295
296 return 1;
297 }
298 /* }}} */
299
300 static zval * yac_get_impl(zend_string *prefix, zend_string *key, uint32_t *cas, zval *rv) /* {{{ */ {
301 uint32_t flag, size = 0;
302 char *data, *msg;
303 time_t tv;
304 zend_string *prefix_key;
305
306 if ((ZSTR_LEN(key) + prefix->len) > YAC_STORAGE_MAX_KEY_LEN) {
307 php_error_docref(NULL, E_WARNING, "Key%s can not be longer than %d bytes",
308 prefix->len? "(include prefix)" : "", YAC_STORAGE_MAX_KEY_LEN);
309 return NULL;
310 }
311
312 if (prefix->len) {
313 prefix_key = strpprintf(YAC_STORAGE_MAX_KEY_LEN, "%s%s", ZSTR_VAL(prefix), ZSTR_VAL(key));
314 key = prefix_key;
315 }
316
317 tv = time(NULL);
318 if (yac_storage_find(ZSTR_VAL(key), ZSTR_LEN(key), &data, &size, &flag, (int *)cas, tv)) {
319 switch ((flag & YAC_ENTRY_TYPE_MASK)) {
320 case IS_NULL:
321 if (size == sizeof(int)) {
322 ZVAL_NULL(rv);
323 }
324 efree(data);
325 break;
326 case IS_TRUE:
327 if (size == sizeof(int)) {
328 ZVAL_TRUE(rv);
329 }
330 efree(data);
331 break;
332 case IS_FALSE:
333 if (size == sizeof(int)) {
334 ZVAL_FALSE(rv);
335 }
336 efree(data);
337 break;
338 case IS_LONG:
339 if (size == sizeof(long)) {
340 ZVAL_LONG(rv, *(long*)data);
341 }
342 efree(data);
343 break;
344 case IS_DOUBLE:
345 if (size == sizeof(double)) {
346 ZVAL_DOUBLE(rv, *(double*)data);
347 }
348 efree(data);
349 break;
350 case IS_STRING:
351 #ifdef IS_CONSTANT
352 case IS_CONSTANT:
353 #endif
354 {
355 if ((flag & YAC_ENTRY_COMPRESSED)) {
356 size_t orig_len = ((uint32_t)flag >> YAC_ENTRY_ORIG_LEN_SHIT);
357 char *origin = emalloc(orig_len + 1);
358 uint32_t length;
359 length = fastlz_decompress(data, size, origin, orig_len);
360 if (!length) {
361 php_error_docref(NULL, E_WARNING, "Decompression failed");
362 efree(data);
363 efree(origin);
364 if (prefix->len) {
365 zend_string_release(prefix_key);
366 }
367 return NULL;
368 }
369 ZVAL_STRINGL(rv, origin, length);
370 efree(origin);
371 efree(data);
372 } else {
373 ZVAL_STRINGL(rv, data, size);
374 efree(data);
375 }
376 }
377 break;
378 case IS_ARRAY:
379 #ifdef IS_CONSTANT_ARRAY
380 case IS_CONSTANT_ARRAY:
381 #endif
382 case IS_OBJECT:
383 {
384 if ((flag & YAC_ENTRY_COMPRESSED)) {
385 size_t length, orig_len = ((uint32_t)flag >> YAC_ENTRY_ORIG_LEN_SHIT);
386 char *origin = emalloc(orig_len + 1);
387 length = fastlz_decompress(data, size, origin, orig_len);
388 if (!length) {
389 php_error_docref(NULL, E_WARNING, "Decompression failed");
390 efree(data);
391 efree(origin);
392 if (prefix->len) {
393 zend_string_release(prefix_key);
394 }
395 return NULL;
396 }
397 efree(data);
398 data = origin;
399 size = length;
400 }
401 #if ENABLE_MSGPACK
402 rv = yac_serializer_msgpack_unpack(data, size, &msg, rv);
403 #else
404 rv = yac_serializer_php_unpack(data, size, &msg, rv);
405 #endif
406 if (!rv) {
407 php_error_docref(NULL, E_WARNING, "Unserialization failed");
408 }
409 efree(data);
410 }
411 break;
412 default:
413 php_error_docref(NULL, E_WARNING, "Unexpected valued type '%d'", flag);
414 rv = NULL;
415 break;
416 }
417 } else {
418 rv = NULL;
419 }
420
421 if (prefix->len) {
422 zend_string_release(prefix_key);
423 }
424
425 return rv;
426 }
427 /* }}} */
428
429 static zval * yac_get_multi_impl(zend_string *prefix, zval *keys, zval *cas, zval *rv) /* {{{ */ {
430 zval *value;
431 HashTable *ht = Z_ARRVAL_P(keys);
432
433 array_init(rv);
434
435 ZEND_HASH_FOREACH_VAL(ht, value) {
436 uint32_t lcas = 0;
437 zval *v, tmp_rv;
438
439 ZVAL_UNDEF(&tmp_rv);
440
441 switch (Z_TYPE_P(value)) {
442 case IS_STRING:
443 if ((v = yac_get_impl(prefix, Z_STR_P(value), &lcas, &tmp_rv)) && !Z_ISUNDEF(tmp_rv)) {
444 zend_symtable_update(Z_ARRVAL_P(rv), Z_STR_P(value), v);
445 } else {
446 ZVAL_FALSE(&tmp_rv);
447 zend_symtable_update(Z_ARRVAL_P(rv), Z_STR_P(value), &tmp_rv);
448 }
449 continue;
450 default:
451 {
452 zend_string *key = zval_get_string(value);
453 if ((v = yac_get_impl(prefix, key, &lcas, &tmp_rv)) && !Z_ISUNDEF(tmp_rv)) {
454 zend_symtable_update(Z_ARRVAL_P(rv), key, v);
455 } else {
456 ZVAL_FALSE(&tmp_rv);
457 zend_symtable_update(Z_ARRVAL_P(rv), key, &tmp_rv);
458 }
459 zend_string_release(key);
460 }
461 continue;
462 }
463 } ZEND_HASH_FOREACH_END();
464
465 return rv;
466 }
467 /* }}} */
468
469 void yac_delete_impl(char *prefix, uint32_t prefix_len, char *key, uint32_t len, int ttl) /* {{{ */ {
470 char buf[YAC_STORAGE_MAX_KEY_LEN];
471 time_t tv = 0;
472
473 if ((len + prefix_len) > YAC_STORAGE_MAX_KEY_LEN) {
474 php_error_docref(NULL, E_WARNING, "Key%s can not be longer than %d bytes",
475 prefix_len? "(include prefix)" : "", YAC_STORAGE_MAX_KEY_LEN);
476 return;
477 }
478
479 if (prefix_len) {
480 len = snprintf(buf, sizeof(buf), "%s%s", prefix, key);
481 key = (char *)buf;
482 }
483
484 if (ttl) {
485 tv = (zend_ulong)time(NULL);
486 }
487
488 yac_storage_delete(key, len, ttl, tv);
489 }
490 /* }}} */
491
492 static void yac_delete_multi_impl(char *prefix, uint32_t prefix_len, zval *keys, int ttl) /* {{{ */ {
493 HashTable *ht = Z_ARRVAL_P(keys);
494 zval *value;
495
496 ZEND_HASH_FOREACH_VAL(ht, value) {
497 switch (Z_TYPE_P(value)) {
498 case IS_STRING:
499 yac_delete_impl(prefix, prefix_len, Z_STRVAL_P(value), Z_STRLEN_P(value), ttl);
500 continue;
501 default:
502 {
503 zval copy;
504 zend_make_printable_zval(value, &copy);
505 yac_delete_impl(prefix, prefix_len, Z_STRVAL(copy), Z_STRLEN(copy), ttl);
506 zval_dtor(&copy);
507 }
508 continue;
509 }
510 } ZEND_HASH_FOREACH_END();
511 }
512 /* }}} */
513
514 /** {{{ proto public Yac::__construct([string $prefix])
515 */
516 PHP_METHOD(yac, __construct) {
517 zend_string *prefix = NULL;
518
519 if (!YAC_G(enable)) {
520 return;
521 }
522
523 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S", &prefix) == FAILURE) {
524 return;
525 }
526
527 if (!prefix) {
528 return;
529 }
530
531 zend_update_property_str(yac_class_ce, getThis(), ZEND_STRL(YAC_CLASS_PROPERTY_PREFIX), prefix);
532
533 }
534 /* }}} */
535
536 /** {{{ proto public Yac::add(mixed $keys, mixed $value[, int $ttl])
537 */
538 PHP_METHOD(yac, add) {
539 long ttl = 0;
540 zval rv, *keys, *prefix, *value = NULL;
541 uint32_t ret;
542
543 if (!YAC_G(enable)) {
544 RETURN_FALSE;
545 }
546
547 switch (ZEND_NUM_ARGS()) {
548 case 1:
549 if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &keys) == FAILURE) {
550 return;
551 }
552 break;
553 case 2:
554 if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &keys, &value) == FAILURE) {
555 return;
556 }
557 if (Z_TYPE_P(keys) == IS_ARRAY) {
558 if (Z_TYPE_P(value) == IS_LONG) {
559 ttl = Z_LVAL_P(value);
560 value = NULL;
561 } else {
562 php_error_docref(NULL, E_WARNING, "ttl parameter must be an integer");
563 return;
564 }
565 }
566 break;
567 case 3:
568 if (zend_parse_parameters(ZEND_NUM_ARGS(), "zzl", &keys, &value, &ttl) == FAILURE) {
569 return;
570 }
571 break;
572 default:
573 WRONG_PARAM_COUNT;
574 }
575
576 prefix = zend_read_property(yac_class_ce, getThis(), ZEND_STRL(YAC_CLASS_PROPERTY_PREFIX), 0, &rv);
577
578 if (Z_TYPE_P(keys) == IS_ARRAY) {
579 ret = yac_add_multi_impl(Z_STR_P(prefix), keys, ttl, 1);
580 } else if (Z_TYPE_P(keys) == IS_STRING) {
581 ret = yac_add_impl(Z_STR_P(prefix), Z_STR_P(keys), value, ttl, 1);
582 } else {
583 zval copy;
584 zend_make_printable_zval(keys, &copy);
585 ret = yac_add_impl(Z_STR_P(prefix), Z_STR(copy), value, ttl, 1);
586 zval_dtor(&copy);
587 }
588
589 RETURN_BOOL(ret);
590 }
591 /* }}} */
592
593 /** {{{ proto public Yac::set(mixed $keys, mixed $value[, int $ttl])
594 */
595 PHP_METHOD(yac, set) {
596 long ttl = 0;
597 zval rv, *keys, *prefix, *value = NULL;
598 uint32_t ret;
599
600 if (!YAC_G(enable)) {
601 RETURN_FALSE;
602 }
603
604 switch (ZEND_NUM_ARGS()) {
605 case 1:
606 if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &keys) == FAILURE) {
607 return;
608 }
609 break;
610 case 2:
611 if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &keys, &value) == FAILURE) {
612 return;
613 }
614 if (Z_TYPE_P(keys) == IS_ARRAY) {
615 if (Z_TYPE_P(value) == IS_LONG) {
616 ttl = Z_LVAL_P(value);
617 value = NULL;
618 } else {
619 php_error_docref(NULL, E_WARNING, "ttl parameter must be an integer");
620 return;
621 }
622 }
623 break;
624 case 3:
625 if (zend_parse_parameters(ZEND_NUM_ARGS(), "zzl", &keys, &value, &ttl) == FAILURE) {
626 return;
627 }
628 break;
629 default:
630 WRONG_PARAM_COUNT;
631 }
632
633 prefix = zend_read_property(yac_class_ce, getThis(), ZEND_STRL(YAC_CLASS_PROPERTY_PREFIX), 0, &rv);
634
635 if (Z_TYPE_P(keys) == IS_ARRAY) {
636 ret = yac_add_multi_impl(Z_STR_P(prefix), keys, ttl, 0);
637 } else if (Z_TYPE_P(keys) == IS_STRING) {
638 ret = yac_add_impl(Z_STR_P(prefix), Z_STR_P(keys), value, ttl, 0);
639 } else {
640 zval copy;
641 zend_make_printable_zval(keys, &copy);
642 ret = yac_add_impl(Z_STR_P(prefix), Z_STR(copy), value, ttl, 0);
643 zval_dtor(&copy);
644 }
645
646 RETURN_BOOL(ret);
647 }
648 /* }}} */
649
650 /** {{{ proto public Yac::__set(string $name, mixed $value)
651 */
652 PHP_METHOD(yac, __set) {
653 zend_string *key;
654 zval *prefix, *value, rv;
655
656 if (!YAC_G(enable)) {
657 RETURN_FALSE;
658 }
659
660 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz", &key, &value) == FAILURE) {
661 return;
662 }
663
664 prefix = zend_read_property(yac_class_ce, getThis(), ZEND_STRL(YAC_CLASS_PROPERTY_PREFIX), 0, &rv);
665
666 yac_add_impl(Z_STR_P(prefix), key, value, 0, 0);
667 }
668 /* }}} */
669
670 /** {{{ proto public Yac::get(mixed $keys[, int &$cas])
671 */
672 PHP_METHOD(yac, get) {
673 uint32_t lcas = 0;
674 zval rv, *ret, *keys, *prefix, *cas = NULL;
675
676 if (!YAC_G(enable)) {
677 RETURN_FALSE;
678 }
679
680 if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|z", &keys, &cas) == FAILURE) {
681 return;
682 }
683
684 prefix = zend_read_property(yac_class_ce, getThis(), ZEND_STRL(YAC_CLASS_PROPERTY_PREFIX), 0, &rv);
685
686 if (Z_TYPE_P(keys) == IS_ARRAY) {
687 ret = yac_get_multi_impl(Z_STR_P(prefix), keys, cas, return_value);
688 } else if (Z_TYPE_P(keys) == IS_STRING) {
689 ret = yac_get_impl(Z_STR_P(prefix), Z_STR_P(keys), &lcas, return_value);
690 } else {
691 zval copy;
692 zend_make_printable_zval(keys, &copy);
693 ret = yac_get_impl(Z_STR_P(prefix), Z_STR(copy), &lcas, return_value);
694 zval_dtor(&copy);
695 }
696
697 if (ret == NULL) {
698 RETURN_FALSE;
699 }
700 }
701 /* }}} */
702
703 /** {{{ proto public Yac::__get(string $name)
704 */
705 PHP_METHOD(yac, __get) {
706 zval *prefix, rv;
707 zend_string *key;
708 uint32_t lcas = 0;
709
710 if (!YAC_G(enable)) {
711 RETURN_FALSE;
712 }
713
714 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &key) == FAILURE) {
715 return;
716 }
717
718 prefix = zend_read_property(yac_class_ce, getThis(), ZEND_STRL(YAC_CLASS_PROPERTY_PREFIX), 0, &rv);
719
720 if (yac_get_impl(Z_STR_P(prefix), key, &lcas, return_value) == NULL) {
721 RETURN_FALSE;
722 }
723 }
724 /* }}} */
725
726 /** {{{ proto public Yac::delete(mixed $key[, int $delay = 0])
727 */
728 PHP_METHOD(yac, delete) {
729 long time = 0;
730 zval *keys, *prefix, rv;
731 char *sprefix = NULL;
732 uint32_t prefix_len = 0;
733
734 if (!YAC_G(enable)) {
735 RETURN_FALSE;
736 }
737
738 if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|l", &keys, &time) == FAILURE) {
739 return;
740 }
741
742 prefix = zend_read_property(yac_class_ce, getThis(), ZEND_STRL(YAC_CLASS_PROPERTY_PREFIX), 0, &rv);
743 sprefix = Z_STRVAL_P(prefix);
744 prefix_len = Z_STRLEN_P(prefix);
745
746 if (Z_TYPE_P(keys) == IS_ARRAY) {
747 yac_delete_multi_impl(sprefix, prefix_len, keys, time);
748 } else if (Z_TYPE_P(keys) == IS_STRING) {
749 yac_delete_impl(sprefix, prefix_len, Z_STRVAL_P(keys), Z_STRLEN_P(keys), time);
750 } else {
751 zval copy;
752 zend_make_printable_zval(keys, &copy);
753 yac_delete_impl(sprefix, prefix_len, Z_STRVAL(copy), Z_STRLEN(copy), time);
754 zval_dtor(&copy);
755 }
756
757 RETURN_TRUE;
758 }
759 /* }}} */
760
761 /** {{{ proto public Yac::flush(void)
762 */
763 PHP_METHOD(yac, flush) {
764
765 if (!YAC_G(enable)) {
766 RETURN_FALSE;
767 }
768
769 yac_storage_flush();
770
771 RETURN_TRUE;
772 }
773 /* }}} */
774
775 /** {{{ proto public Yac::info(void)
776 */
777 PHP_METHOD(yac, info) {
778 yac_storage_info *inf;
779
780 if (!YAC_G(enable)) {
781 RETURN_FALSE;
782 }
783
784 inf = yac_storage_get_info();
785
786 array_init(return_value);
787
788 add_assoc_long(return_value, "memory_size", inf->k_msize + inf->v_msize);
789 add_assoc_long(return_value, "slots_memory_size", inf->k_msize);
790 add_assoc_long(return_value, "values_memory_size", inf->v_msize);
791 add_assoc_long(return_value, "segment_size", inf->segment_size);
792 add_assoc_long(return_value, "segment_num", inf->segments_num);
793 add_assoc_long(return_value, "miss", inf->miss);
794 add_assoc_long(return_value, "hits", inf->hits);
795 add_assoc_long(return_value, "fails", inf->fails);
796 add_assoc_long(return_value, "kicks", inf->kicks);
797 add_assoc_long(return_value, "recycles", inf->recycles);
798 add_assoc_long(return_value, "slots_size", inf->slots_size);
799 add_assoc_long(return_value, "slots_used", inf->slots_num);
800
801 yac_storage_free_info(inf);
802 }
803 /* }}} */
804
805 /** {{{ proto public Yac::dump(int $limit)
806 */
807 PHP_METHOD(yac, dump) {
808 long limit = 100;
809 yac_item_list *list, *l;
810
811 if (!YAC_G(enable)) {
812 RETURN_FALSE;
813 }
814
815 array_init(return_value);
816
817 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &limit) == FAILURE) {
818 return;
819 }
820
821 list = l = yac_storage_dump(limit);
822 for (; l; l = l->next) {
823 zval item;
824 array_init(&item);
825 add_assoc_long(&item, "index", l->index);
826 add_assoc_long(&item, "hash", l->h);
827 add_assoc_long(&item, "crc", l->crc);
828 add_assoc_long(&item, "ttl", l->ttl);
829 add_assoc_long(&item, "k_len", l->k_len);
830 add_assoc_long(&item, "v_len", l->v_len);
831 add_assoc_long(&item, "size", l->size);
832 add_assoc_string(&item, "key", (char*)l->key);
833 add_next_index_zval(return_value, &item);
834 }
835
836 yac_storage_free_list(list);
837 return;
838 }
839 /* }}} */
840
841 #if 0
842 only OO-style APIs is supported now
843 /* {{{{ proto bool yac_add(mixed $keys, mixed $value[, int $ttl])
844 */
845 PHP_FUNCTION(yac_add)
846 {
847 PHP_MN(yac_add)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
848 }
849 /* }}} */
850
851 /* {{{ proto bool yac_set(mixed $keys, mixed $value[, int $ttl])
852 */
853 PHP_FUNCTION(yac_set)
854 {
855 PHP_MN(yac_set)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
856 }
857 /* }}} */
858
859 /* {{{ proto bool yac_get(mixed $keys[, int &$cas])
860 */
861 PHP_FUNCTION(yac_get)
862 {
863 PHP_MN(yac_get)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
864 }
865 /* }}} */
866
867 /* {{{ proto bool yac_delete(mixed $keys[, int $delay = 0])
868 */
869 PHP_FUNCTION(yac_delete)
870 {
871 PHP_MN(yac_delete)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
872 }
873 /* }}} */
874
875 /* {{{ proto bool yac_flush(void)
876 */
877 PHP_FUNCTION(yac_flush)
878 {
879 PHP_MN(yac_flush)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
880 }
881 /* }}} */
882
883 /* {{{ proto bool yac_info(void)
884 */
885 PHP_FUNCTION(yac_info)
886 {
887 PHP_MN(yac_info)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
888 }
889 /* }}} */
890
891 /* {{{ yac_functions[] */
892 zend_function_entry yac_functions[] = {
893 PHP_FE(yac_add, arginfo_yac_add)
894 PHP_FE(yac_set, arginfo_yac_add)
895 PHP_FE(yac_get, arginfo_yac_get)
896 PHP_FE(yac_delete, arginfo_yac_delete)
897 PHP_FE(yac_flush, arginfo_yac_void)
898 PHP_FE(yac_info, arginfo_yac_void)
899 {NULL, NULL}
900 };
901 /* }}} */
902 #endif
903
904 /** {{{ yac_methods
905 */
906 zend_function_entry yac_methods[] = {
907 PHP_ME(yac, __construct, arginfo_yac_constructor, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
908 PHP_ME(yac, add, arginfo_yac_add, ZEND_ACC_PUBLIC)
909 PHP_ME(yac, set, arginfo_yac_add, ZEND_ACC_PUBLIC)
910 PHP_ME(yac, __set, arginfo_yac_setter, ZEND_ACC_PUBLIC)
911 PHP_ME(yac, get, arginfo_yac_get, ZEND_ACC_PUBLIC)
912 PHP_ME(yac, __get, arginfo_yac_getter, ZEND_ACC_PUBLIC)
913 PHP_ME(yac, delete, arginfo_yac_delete, ZEND_ACC_PUBLIC)
914 PHP_ME(yac, flush, arginfo_yac_void, ZEND_ACC_PUBLIC)
915 PHP_ME(yac, info, arginfo_yac_void, ZEND_ACC_PUBLIC)
916 PHP_ME(yac, dump, arginfo_yac_void, ZEND_ACC_PUBLIC)
917 {NULL, NULL, NULL}
918 };
919 /* }}} */
920
921 /* {{{ PHP_GINIT_FUNCTION
922 */
923 PHP_GINIT_FUNCTION(yac)
924 {
925 yac_globals->enable = 1;
926 yac_globals->k_msize = (4 * 1024 * 1024);
927 yac_globals->v_msize = (64 * 1024 * 1024);
928 yac_globals->debug = 0;
929 yac_globals->compress_threshold = -1;
930 yac_globals->enable_cli = 0;
931 #ifdef PHP_WIN32
932 yac_globals->mmap_base = NULL;
933 #endif
934 }
935 /* }}} */
936
937 /* {{{ PHP_MINIT_FUNCTION
938 */
939 PHP_MINIT_FUNCTION(yac)
940 {
941 char *msg;
942 zend_class_entry ce;
943
944 REGISTER_INI_ENTRIES();
945
946 if(!YAC_G(enable_cli) && !strcmp(sapi_module.name, "cli")) {
947 YAC_G(enable) = 0;
948 }
949
950 if (YAC_G(enable)) {
951 if (!yac_storage_startup(YAC_G(k_msize), YAC_G(v_msize), &msg)) {
952 php_error(E_ERROR, "Shared memory allocator startup failed at '%s': %s", msg, strerror(errno));
953 return FAILURE;
954 }
955 }
956
957 REGISTER_STRINGL_CONSTANT("YAC_VERSION", PHP_YAC_VERSION, sizeof(PHP_YAC_VERSION) - 1, CONST_PERSISTENT | CONST_CS);
958 REGISTER_LONG_CONSTANT("YAC_MAX_KEY_LEN", YAC_STORAGE_MAX_KEY_LEN, CONST_PERSISTENT | CONST_CS);
959 REGISTER_LONG_CONSTANT("YAC_MAX_VALUE_RAW_LEN", YAC_ENTRY_MAX_ORIG_LEN, CONST_PERSISTENT | CONST_CS);
960 REGISTER_LONG_CONSTANT("YAC_MAX_RAW_COMPRESSED_LEN", YAC_STORAGE_MAX_ENTRY_LEN, CONST_PERSISTENT | CONST_CS);
961 #if ENABLE_MSGPACK
962 REGISTER_STRINGL_CONSTANT("YAC_SERIALIZER", "MSGPACK", sizeof("MSGPACK") -1, CONST_PERSISTENT | CONST_CS);
963 #else
964 REGISTER_STRINGL_CONSTANT("YAC_SERIALIZER", "PHP", sizeof("PHP") -1, CONST_PERSISTENT | CONST_CS);
965 #endif
966
967 INIT_CLASS_ENTRY(ce, "Yac", yac_methods);
968 yac_class_ce = zend_register_internal_class(&ce);
969 zend_declare_property_stringl(yac_class_ce, ZEND_STRS(YAC_CLASS_PROPERTY_PREFIX) - 1, "", 0, ZEND_ACC_PROTECTED);
970
971 return SUCCESS;
972 }
973 /* }}} */
974
975 /* {{{ PHP_MSHUTDOWN_FUNCTION
976 */
977 PHP_MSHUTDOWN_FUNCTION(yac)
978 {
979 UNREGISTER_INI_ENTRIES();
980 if (YAC_G(enable)) {
981 yac_storage_shutdown();
982 }
983 return SUCCESS;
984 }
985 /* }}} */
986
987 /* {{{ PHP_MINFO_FUNCTION
988 */
989 PHP_MINFO_FUNCTION(yac)
990 {
991 php_info_print_table_start();
992 php_info_print_table_header(2, "yac support", "enabled");
993 php_info_print_table_row(2, "Version", PHP_YAC_VERSION);
994 php_info_print_table_row(2, "Shared Memory", yac_storage_shared_memory_name());
995 #if ENABLE_MSGPACK
996 php_info_print_table_row(2, "Serializer", "msgpack");
997 #else
998 php_info_print_table_row(2, "Serializer", "php");
999 #endif
1000 php_info_print_table_end();
1001
1002 DISPLAY_INI_ENTRIES();
1003
1004 if (YAC_G(enable)) {
1005 char buf[64];
1006 yac_storage_info *inf;
1007 inf = yac_storage_get_info();
1008
1009 php_info_print_table_start();
1010 php_info_print_table_colspan_header(2, "Cache info");
1011 snprintf(buf, sizeof(buf), "%ld", inf->k_msize + inf->v_msize);
1012 php_info_print_table_row(2, "Total Shared Memory Usage(memory_size)", buf);
1013 snprintf(buf, sizeof(buf), "%ld", inf->k_msize);
1014 php_info_print_table_row(2, "Total Shared Memory Usage for keys(keys_memory_size)", buf);
1015 snprintf(buf, sizeof(buf), "%ld", inf->v_msize);
1016 php_info_print_table_row(2, "Total Shared Memory Usage for values(values_memory_size)", buf);
1017 snprintf(buf, sizeof(buf), "%d", inf->segment_size);
1018 php_info_print_table_row(2, "Size of Shared Memory Segment(segment_size)", buf);
1019 snprintf(buf, sizeof(buf), "%ld", inf->segments_num);
1020 php_info_print_table_row(2, "Number of Segments (segment_num)", buf);
1021 snprintf(buf, sizeof(buf), "%ld", inf->slots_size);
1022 php_info_print_table_row(2, "Total Slots Number(slots_size)", buf);
1023 snprintf(buf, sizeof(buf), "%ld", inf->slots_num);
1024 php_info_print_table_row(2, "Total Used Slots(slots_num)", buf);
1025 php_info_print_table_end();
1026
1027 yac_storage_free_info(inf);
1028 }
1029 }
1030 /* }}} */
1031
1032 #ifdef COMPILE_DL_YAC
1033 ZEND_GET_MODULE(yac)
1034 #endif
1035
1036 /* {{{ yac_module_entry
1037 */
1038 zend_module_entry yac_module_entry = {
1039 STANDARD_MODULE_HEADER,
1040 "yac",
1041 NULL, /* yac_functions, */
1042 PHP_MINIT(yac),
1043 PHP_MSHUTDOWN(yac),
1044 NULL,
1045 NULL,
1046 PHP_MINFO(yac),
1047 PHP_YAC_VERSION,
1048 PHP_MODULE_GLOBALS(yac),
1049 PHP_GINIT(yac),
1050 NULL,
1051 NULL,
1052 STANDARD_MODULE_PROPERTIES_EX
1053 };
1054 /* }}} */
1055
1056 /*
1057 * Local variables:
1058 * tab-width: 4
1059 * c-basic-offset: 4
1060 * End:
1061 * vim600: noet sw=4 ts=4 fdm=marker
1062 * vim<600: noet sw=4 ts=4
1063 */
0 yac
1
2 Xinchen Hui
3 Wei Dai
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://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, whether to use system FastLZ library,
7 [ --with-system-fastlz Use system FastLZ library], no, no)
8
9 PHP_ARG_ENABLE(json, whether to use igbinary as serializer,
10 [ --enable-json Use igbinary as serializer], no, no)
11
12 PHP_ARG_ENABLE(msgpack, whether to use msgpack as serializer,
13 [ --enable-msgpack Use Messagepack as serializer], no, no)
14
15 PHP_ARG_ENABLE(igbinary, whether to use igbinary as serializer,
16 [ --enable-igbinary Use igbinary as serializer], no, no)
17
18 dnl copied from Zend Optimizer Plus
19 AC_MSG_CHECKING(for sysvipc shared memory support)
20 AC_TRY_RUN([
21 #include <sys/types.h>
22 #include <sys/wait.h>
23 #include <sys/ipc.h>
24 #include <sys/shm.h>
25 #include <unistd.h>
26 #include <string.h>
27
28 int main() {
29 pid_t pid;
30 int status;
31 int ipc_id;
32 char *shm;
33 struct shmid_ds shmbuf;
34
35 ipc_id = shmget(IPC_PRIVATE, 4096, (IPC_CREAT | SHM_R | SHM_W));
36 if (ipc_id == -1) {
37 return 1;
38 }
39
40 shm = shmat(ipc_id, NULL, 0);
41 if (shm == (void *)-1) {
42 shmctl(ipc_id, IPC_RMID, NULL);
43 return 2;
44 }
45
46 if (shmctl(ipc_id, IPC_STAT, &shmbuf) != 0) {
47 shmdt(shm);
48 shmctl(ipc_id, IPC_RMID, NULL);
49 return 3;
50 }
51
52 shmbuf.shm_perm.uid = getuid();
53 shmbuf.shm_perm.gid = getgid();
54 shmbuf.shm_perm.mode = 0600;
55
56 if (shmctl(ipc_id, IPC_SET, &shmbuf) != 0) {
57 shmdt(shm);
58 shmctl(ipc_id, IPC_RMID, NULL);
59 return 4;
60 }
61
62 shmctl(ipc_id, IPC_RMID, NULL);
63
64 strcpy(shm, "hello");
65
66 pid = fork();
67 if (pid < 0) {
68 return 5;
69 } else if (pid == 0) {
70 strcpy(shm, "bye");
71 return 6;
72 }
73 if (wait(&status) != pid) {
74 return 7;
75 }
76 if (!WIFEXITED(status) || WEXITSTATUS(status) != 6) {
77 return 8;
78 }
79 if (strcmp(shm, "bye") != 0) {
80 return 9;
81 }
82 return 0;
83 }
84 ],dnl
85 AC_DEFINE(HAVE_SHM_IPC, 1, [Define if you have SysV IPC SHM support])
86 msg=yes,msg=no,msg=no)
87 AC_MSG_RESULT([$msg])
88
89 AC_MSG_CHECKING(for mmap() using MAP_ANON shared memory support)
90 AC_TRY_RUN([
91 #include <sys/types.h>
92 #include <sys/wait.h>
93 #include <sys/mman.h>
94 #include <unistd.h>
95 #include <string.h>
96
97 #ifndef MAP_ANON
98 # ifdef MAP_ANONYMOUS
99 # define MAP_ANON MAP_ANONYMOUS
100 # endif
101 #endif
102 #ifndef MAP_FAILED
103 # define MAP_FAILED ((void*)-1)
104 #endif
105
106 int main() {
107 pid_t pid;
108 int status;
109 char *shm;
110
111 shm = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
112 if (shm == MAP_FAILED) {
113 return 1;
114 }
115
116 strcpy(shm, "hello");
117
118 pid = fork();
119 if (pid < 0) {
120 return 5;
121 } else if (pid == 0) {
122 strcpy(shm, "bye");
123 return 6;
124 }
125 if (wait(&status) != pid) {
126 return 7;
127 }
128 if (!WIFEXITED(status) || WEXITSTATUS(status) != 6) {
129 return 8;
130 }
131 if (strcmp(shm, "bye") != 0) {
132 return 9;
133 }
134 return 0;
135 }
136 ],dnl
137 AC_DEFINE(HAVE_SHM_MMAP_ANON, 1, [Define if you have mmap(MAP_ANON) SHM support])
138 msg=yes,msg=no,msg=no)
139 AC_MSG_RESULT([$msg])
140
141 AC_MSG_CHECKING(for mmap() using /dev/zero shared memory support)
142 AC_TRY_RUN([
143 #include <sys/types.h>
144 #include <sys/wait.h>
145 #include <sys/mman.h>
146 #include <sys/stat.h>
147 #include <fcntl.h>
148 #include <unistd.h>
149 #include <string.h>
150
151 #ifndef MAP_FAILED
152 # define MAP_FAILED ((void*)-1)
153 #endif
154
155 int main() {
156 pid_t pid;
157 int status;
158 int fd;
159 char *shm;
160
161 fd = open("/dev/zero", O_RDWR, S_IRUSR | S_IWUSR);
162 if (fd == -1) {
163 return 1;
164 }
165
166 shm = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
167 if (shm == MAP_FAILED) {
168 return 2;
169 }
170
171 strcpy(shm, "hello");
172
173 pid = fork();
174 if (pid < 0) {
175 return 5;
176 } else if (pid == 0) {
177 strcpy(shm, "bye");
178 return 6;
179 }
180 if (wait(&status) != pid) {
181 return 7;
182 }
183 if (!WIFEXITED(status) || WEXITSTATUS(status) != 6) {
184 return 8;
185 }
186 if (strcmp(shm, "bye") != 0) {
187 return 9;
188 }
189 return 0;
190 }
191 ],dnl
192 AC_DEFINE(HAVE_SHM_MMAP_ZERO, 1, [Define if you have mmap("/dev/zero") SHM support])
193 msg=yes,msg=no,msg=no)
194 AC_MSG_RESULT([$msg])
195
196 if test "$PHP_MSGPACK" != "no"; then
197 AC_DEFINE(YAC_ENABLE_MSGPACK, 1, [enable msgpack packager])
198 ifdef([PHP_ADD_EXTENSION_DEP],
199 [
200 PHP_ADD_EXTENSION_DEP(yac, msgpack, true)
201 ])
202 fi
203
204 if test "$PHP_IGBINARY" != "no"; then
205 AC_DEFINE(YAC_ENABLE_IGBINARY, 1, [enable igbinary packager])
206 ifdef([PHP_ADD_EXTENSION_DEP],
207 [
208 PHP_ADD_EXTENSION_DEP(yac, igbinary, true)
209 ])
210 fi
211
212 if test "$PHP_JSON" != "no"; then
213 AC_DEFINE(YAC_ENABLE_JSON, 1, [enable json packager])
214 ifdef([PHP_ADD_EXTENSION_DEP],
215 [
216 PHP_ADD_EXTENSION_DEP(yac, json, true)
217 ])
218 fi
219
220 ifdef([PHP_CHECK_CPU_SUPPORTS],
221 [
222 if test -x "$PHP_CONFIG"; then
223 php_vernum=`$PHP_CONFIG --vernum`
224 if test $php_vernum -ge 70300; then
225 AC_CHECK_HEADERS([nmmintrin.h])
226 PHP_CHECK_CPU_SUPPORTS([sse4.2])
227 dnl Tricky way to remove unintentionally defines
228 if test -e "confdefs.h"; then
229 sed -i "/PHP_HAVE_/d" confdefs.h
230 fi
231 AC_MSG_CHECKING([for crc32 instruction supports])
232 if test $have_ext_instructions -eq 1; then
233 AC_DEFINE([HAVE_SSE_CRC32], 1, [define if you have sse4.2 crc32 instruction support])
234 CFLAGS="$CFLAGS -msse4.2"
235 AC_MSG_RESULT([yes])
236 else
237 AC_MSG_RESULT([no])
238 fi
239 fi
240 fi
241 ], [])
242
243 AC_DEFUN([YAC_BUILTIN_ATOMIC],
244 [
245 AC_MSG_CHECKING([for __sync_bool_compare_and_swap supports])
246 AC_LINK_IFELSE([AC_LANG_PROGRAM([], [[
247 int variable = 1;
248 return (__sync_bool_compare_and_swap(&variable, 1, 2)
249 && __sync_add_and_fetch(&variable, 1)) ? 1 : 0;
250 ]])], [
251 AC_MSG_RESULT([yes])
252 AC_DEFINE(HAVE_BUILTIN_ATOMIC, 1, [Define to 1 if gcc supports __sync_bool_compare_and_swap() a.o.])
253 ], [
254 AC_MSG_RESULT([no])
255 ])
256 ])
257
258 YAC_BUILTIN_ATOMIC
259
260 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 serializer/igbinary.c serializer/json.c"
261 if test "$PHP_SYSTEM_FASTLZ" != "no"; then
262 AC_CHECK_HEADERS([fastlz.h])
263 PHP_CHECK_LIBRARY(fastlz, fastlz_compress,
264 [PHP_ADD_LIBRARY(fastlz, 1, YAC_SHARED_LIBADD)],
265 [AC_MSG_ERROR(FastLZ library not found)])
266 else
267 YAC_FILES="${YAC_FILES} compressor/fastlz/fastlz.c"
268 fi
269
270 if test "$PHP_YAC" != "no"; then
271 PHP_SUBST(YAC_SHARED_LIBADD)
272 PHP_NEW_EXTENSION(yac, ${YAC_FILES}, $ext_shared)
273 PHP_ADD_BUILD_DIR([$ext_builddir/storage])
274 PHP_ADD_BUILD_DIR([$ext_builddir/storage/allocator])
275 PHP_ADD_BUILD_DIR([$ext_builddir/storage/allocator/allocators])
276 PHP_ADD_BUILD_DIR([$ext_builddir/serializer])
277 PHP_ADD_BUILD_DIR([$ext_builddir/compressor])
278 PHP_ADD_BUILD_DIR([$ext_builddir/compressor/fastlz])
279 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 "2.2.1"
37
38 #if PHP_VERSION_ID < 70400
39 #define YAC_WHANDLER void
40 #define YAC_WHANDLER_RET(zv) return
41 #else
42 #define YAC_WHANDLER zval *
43 #define YAC_WHANDLER_RET(zv) return zv
44 #endif
45
46 #define YAC_CLASS_PROPERTY_PREFIX "_prefix"
47 #define YAC_ENTRY_COMPRESSED 0x0020
48 #define YAC_ENTRY_TYPE_MASK 0x1f
49 #define YAC_ENTRY_ORIG_LEN_SHIT 6
50 #define YAC_ENTRY_MAX_ORIG_LEN ((1U << ((sizeof(int)*8 - YAC_ENTRY_ORIG_LEN_SHIT))) - 1)
51 #define YAC_MIN_COMPRESS_THRESHOLD 1024
52
53 #define YAC_SERIALIZER_PHP 0
54 #define YAC_SERIALIZER_JSON 1
55 #define YAC_SERIALIZER_MSGPACK 2
56 #define YAC_SERIALIZER_IGBINARY 3
57
58 ZEND_BEGIN_MODULE_GLOBALS(yac)
59 zend_bool enable;
60 zend_bool debug;
61 size_t k_msize;
62 size_t v_msize;
63 zend_ulong compress_threshold;
64 zend_bool enable_cli;
65 char *serializer;
66 #ifdef PHP_WIN32
67 char *mmap_base;
68 #endif
69 ZEND_END_MODULE_GLOBALS(yac)
70
71 PHP_MINIT_FUNCTION(yac);
72 PHP_MSHUTDOWN_FUNCTION(yac);
73 PHP_RINIT_FUNCTION(yac);
74 PHP_RSHUTDOWN_FUNCTION(yac);
75 PHP_MINFO_FUNCTION(yac);
76
77 ZEND_EXTERN_MODULE_GLOBALS(yac);
78 #define YAC_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(yac, v)
79
80 #endif /* PHP_YAC_H */
81 /*
82 * Local variables:
83 * tab-width: 4
84 * c-basic-offset: 4
85 * End:
86 * vim600: noet sw=4 ts=4 fdm=marker
87 * vim<600: noet sw=4 ts=4
88 */
0 /*
1 +----------------------------------------------------------------------+
2 | Yet Another Cache |
3 +----------------------------------------------------------------------+
4 | Copyright (c) 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 | Remi Collet <remi@php.net> |
16 +----------------------------------------------------------------------+
17 */
18
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #ifdef YAC_ENABLE_IGBINARY
24
25 #include "php.h"
26 #include "ext/igbinary/igbinary.h"
27 #include "zend_smart_str.h" /* for smart_str */
28
29 #include "yac_serializer.h"
30
31 int yac_serializer_igbinary_pack(zval *pzval, smart_str *buf, char **msg) /* {{{ */ {
32 uint8_t *ret;
33 size_t ret_len;
34
35 if (igbinary_serialize(&ret, &ret_len, pzval) == 0) {
36 smart_str_appendl(buf, (const char *)ret, ret_len);
37 efree(ret);
38 return 1;
39 }
40 return 0;
41 } /* }}} */
42
43 zval * yac_serializer_igbinary_unpack(char *content, size_t len, char **msg, zval *rv) /* {{{ */ {
44
45 ZVAL_NULL(rv);
46 igbinary_unserialize((uint8_t *)content, len, rv);
47 return rv;
48 } /* }}} */
49
50 #endif
51
52 /*
53 * Local variables:
54 * tab-width: 4
55 * c-basic-offset: 4
56 * End:
57 * vim600: noet sw=4 ts=4 fdm=marker
58 * vim<600: noet sw=4 ts=4
59 */
0 /*
1 +----------------------------------------------------------------------+
2 | Yet Another Cache |
3 +----------------------------------------------------------------------+
4 | Copyright (c) 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 YAC_ENABLE_JSON
25
26 #include "php.h"
27 #include "ext/json/php_json.h"
28 #include "zend_smart_str.h" /* for smart_str */
29
30 #include "yac_serializer.h"
31
32 int yac_serializer_json_pack(zval *pzval, smart_str *buf, char **msg) /* {{{ */ {
33 #if ((PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION < 3))
34 php_json_encode(buf, pzval);
35 #else
36 php_json_encode(buf, pzval, 0); /* options */
37 #endif
38
39 return 1;
40 } /* }}} */
41
42 zval* yac_serializer_json_unpack(char *content, size_t len, char **msg, zval *rv) /* {{{ */ {
43 ZVAL_NULL(rv);
44 php_json_decode(rv, content, len, 1, 512);
45
46 return rv;
47 } /* }}} */
48
49 #endif
50
51 /*
52 * Local variables:
53 * tab-width: 4
54 * c-basic-offset: 4
55 * End:
56 * vim600: noet sw=4 ts=4 fdm=marker
57 * vim<600: noet sw=4 ts=4
58 */
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 YAC_ENABLE_MSGPACK
26
27 #include "php.h"
28 #include "ext/msgpack/php_msgpack.h"
29 #include "zend_smart_str.h" /* for smart_str */
30
31 #include "yac_serializer.h"
32
33 int yac_serializer_msgpack_pack(zval *pzval, smart_str *buf, char **msg) /* {{{ */ {
34 php_msgpack_serialize(buf, pzval);
35 return 1;
36 } /* }}} */
37
38 zval * yac_serializer_msgpack_unpack(char *content, size_t len, char **msg, zval *rv) /* {{{ */ {
39 ZVAL_NULL(rv);
40 php_msgpack_unserialize(rv, content, len);
41 return rv;
42 } /* }}} */
43
44 #endif
45
46 /*
47 * Local variables:
48 * tab-width: 4
49 * c-basic-offset: 4
50 * End:
51 * vim600: noet sw=4 ts=4 fdm=marker
52 * vim<600: noet sw=4 ts=4
53 */
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 "php.h"
25 #include "ext/standard/php_var.h" /* for serialize */
26 #include "zend_smart_str.h"
27
28 #include "yac_serializer.h"
29
30 int yac_serializer_php_pack(zval *pzval, smart_str *buf, char **msg) /* {{{ */ {
31 php_serialize_data_t var_hash;
32
33 PHP_VAR_SERIALIZE_INIT(var_hash);
34 php_var_serialize(buf, pzval, &var_hash);
35 PHP_VAR_SERIALIZE_DESTROY(var_hash);
36
37 return 1;
38 } /* }}} */
39
40 zval * yac_serializer_php_unpack(char *content, size_t len, char **msg, zval *rv) /* {{{ */ {
41 const unsigned char *p;
42 php_unserialize_data_t var_hash;
43 p = (const unsigned char*)content;
44
45 ZVAL_FALSE(rv);
46 PHP_VAR_UNSERIALIZE_INIT(var_hash);
47 if (!php_var_unserialize(rv, &p, p + len, &var_hash)) {
48 zval_ptr_dtor(rv);
49 PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
50 /* spprintf(msg, 0, "unpack error at offset %ld of %ld bytes", (long)((char*)p - content), len); */
51 return NULL;
52 }
53 PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
54
55 return rv;
56 } /* }}} */
57
58 /*
59 * Local variables:
60 * tab-width: 4
61 * c-basic-offset: 4
62 * End:
63 * vim600: noet sw=4 ts=4 fdm=marker
64 * vim<600: noet sw=4 ts=4
65 */
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 typedef int (*yac_serializer_t)(zval*, smart_str*, char**);
24 typedef zval* (*yac_unserializer_t)(char *, size_t, char**, zval*);
25
26 #ifdef YAC_ENABLE_MSGPACK
27 int yac_serializer_msgpack_pack(zval *pzval, smart_str *buf, char **msg);
28 zval * yac_serializer_msgpack_unpack(char *content, size_t len, char **msg, zval *rv);
29 #endif
30
31 int yac_serializer_php_pack(zval *pzval, smart_str *buf, char **msg);
32 zval * yac_serializer_php_unpack(char *content, size_t len, char **msg, zval *rv);
33
34 #ifdef YAC_ENABLE_IGBINARY
35 int yac_serializer_igbinary_pack(zval *pzval, smart_str *buf, char **msg);
36 zval * yac_serializer_igbinary_unpack(char *content, size_t len, char **msg, zval *rv);
37 #endif
38
39 #ifdef YAC_ENABLE_JSON
40 int yac_serializer_json_pack(zval *pzval, smart_str *buf, char **msg);
41 zval * yac_serializer_json_unpack(char *content, size_t len, char **msg, zval *rv);
42 #endif
43
44 #endif /* YAC_SERIALIZER_H */
45
46 /*
47 * Local variables:
48 * tab-width: 4
49 * c-basic-offset: 4
50 * End:
51 * vim600: noet sw=4 ts=4 fdm=marker
52 * vim<600: noet sw=4 ts=4
53 */
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 <demon@php.net> |
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 static char newname[MAXPATHLEN + UNLEN + 4];
45 char uname[UNLEN + 1];
46 DWORD unsize = UNLEN;
47
48 GetUserName(uname, &unsize);
49 snprintf(newname, sizeof(newname) - 1, "%s@%s", name, uname);
50 return newname;
51 }
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
68 static int yac_shared_alloc_reattach(size_t requested_size, char **error_in) /* {{{ */ {
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
112 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) /* {{{ */ {
113 int ret;
114 unsigned long allocate_size, occupied_size = 0;
115 unsigned int i, segment_size, segments_num = 1024, is_reattach = 0;
116 int map_retries = 0;
117 yac_shared_segment_create_file first_segment;
118 void *default_mapping_base_set[] = {0, 0};
119 /* TODO:
120 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
121 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
122 desired. Not done yet, @zend refused but did not remember the exact reason, pls add info here if one of you know why :)
123 */
124 #if defined(_WIN64)
125 void *vista_mapping_base_set[] = { (void *) 0x0000100000000000, (void *) 0x0000200000000000, (void *) 0x0000300000000000, (void *) 0x0000700000000000, 0 };
126 #else
127 void *vista_mapping_base_set[] = { (void *) 0x20000000, (void *) 0x21000000, (void *) 0x30000000, (void *) 0x31000000, (void *) 0x50000000, 0 };
128 #endif
129 void **wanted_mapping_base = default_mapping_base_set;
130
131
132 k_size = YAC_SMM_ALIGNED_SIZE(k_size);
133 v_size = YAC_SMM_ALIGNED_SIZE(v_size);
134 while ((v_size / segments_num) < YAC_SMM_SEGMENT_MIN_SIZE) {
135 segments_num >>= 1;
136 }
137
138 segment_size = v_size / segments_num;
139 ++segments_num;
140
141 allocate_size = k_size + v_size;
142
143 /* Mapping retries: When Apache2 restarts, the parent process startup routine
144 can be called before the child process is killed. In this case, the map will fail
145 and we have to sleep some time (until the child releases the mapping object) and retry.*/
146 do {
147 memfile = OpenFileMapping(FILE_MAP_WRITE, 0, create_name_with_username(ACCEL_FILEMAP_NAME));
148 if (memfile == NULL) {
149 break;
150 }
151
152 ret = yac_shared_alloc_reattach((size_t)k_size, error_in);
153 if (ret == ALLOC_FAIL_MAPPING) {
154 /* Mapping failed, wait for mapping object to get freed and retry */
155 CloseHandle(memfile);
156 memfile = NULL;
157 Sleep(1000 * (map_retries + 1));
158 } else if (ret == SUCCESSFULLY_REATTACHED) {
159 is_reattach = 1;
160 break;
161 } else {
162 return ret;
163 }
164 } while (++map_retries < MAX_MAP_RETRIES);
165
166 if (map_retries == MAX_MAP_RETRIES) {
167 *error_in = "OpenFileMapping";
168 return 0;
169 }
170
171 *shared_segments_p = (yac_shared_segment_create_file *)calloc(1, segments_num * sizeof(yac_shared_segment_create_file));
172 if(!*shared_segments_p) {
173 *error_in = "calloc";
174 return 0;
175 }
176 *shared_segments_count = segments_num;
177
178 /* Starting from windows Vista, heap randomization occurs which might cause our mapping base to
179 be taken (fail to map). So under Vista, we try to map into a hard coded predefined addresses
180 in high memory. */
181 if (!YAC_G(mmap_base) || !*YAC_G(mmap_base)) {
182 do {
183 OSVERSIONINFOEX osvi;
184 SYSTEM_INFO si;
185
186 ZeroMemory(&si, sizeof(SYSTEM_INFO));
187 ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
188
189 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
190
191 if (! GetVersionEx ((OSVERSIONINFO *) &osvi)) {
192 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
193 if (!GetVersionEx((OSVERSIONINFO *)&osvi)) {
194 break;
195 }
196 }
197
198 GetSystemInfo(&si);
199
200 /* Are we running Vista ? */
201 if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion == 6) {
202 wanted_mapping_base = vista_mapping_base_set;
203 }
204 } while (0);
205 } else {
206 char *s = YAC_G(mmap_base);
207
208 /* skip leading 0x, %p assumes hexdeciaml format anyway */
209 if (*s == '0' && *(s + 1) == 'x') {
210 s += 2;
211 }
212 if (sscanf(s, "%p", &default_mapping_base_set[0]) != 1) {
213 *error_in = "mapping";
214 return 0;
215 }
216 }
217
218 if (is_reattach == 0) {
219 memfile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, allocate_size, create_name_with_username(ACCEL_FILEMAP_NAME));
220 if (memfile == NULL) {
221 *error_in = "CreateFileMapping";
222 return 0;
223 }
224
225 do {
226 first_segment.common.p = mapping_base = MapViewOfFileEx(memfile, FILE_MAP_ALL_ACCESS, 0, 0, 0, *wanted_mapping_base);
227 if (wanted_mapping_base == NULL) {
228 break;
229 }
230 *wanted_mapping_base++;
231 } while (!mapping_base);
232 }
233
234 if(mapping_base == NULL) {
235 *error_in = "MapViewOfFileEx";
236 return 0;
237 } else {
238 char *mmap_base_file = get_mmap_base_file();
239 FILE *fp = fopen(mmap_base_file, "w");
240 if (!fp) {
241 *error_in = "get_mmap_base_file";
242 return 0;
243 }
244 fprintf(fp, "%p", mapping_base);
245 fclose(fp);
246 }
247
248 first_segment.common.p = mapping_base;
249 first_segment.size = allocate_size;
250 first_segment.common.size = k_size;
251 first_segment.common.pos = 0;
252
253 (*shared_segments_p)[0] = first_segment;
254
255 occupied_size = k_size;
256 for (i = 1; i < segments_num; i++) {
257 (*shared_segments_p)[i].size = 0;
258 (*shared_segments_p)[i].common.pos = 0;
259 (*shared_segments_p)[i].common.p = (void *)((char *)first_segment.common.p + occupied_size);
260 if ((allocate_size - occupied_size) >= YAC_SMM_ALIGNED_SIZE(segment_size)) {
261 (*shared_segments_p)[i].common.size = YAC_SMM_ALIGNED_SIZE(segment_size);
262 occupied_size += YAC_SMM_ALIGNED_SIZE(segment_size);
263 } else {
264 (*shared_segments_p)[i].common.size = (allocate_size - occupied_size);
265 break;
266 }
267 }
268
269 return 1;
270 }
271 /* }}} */
272
273 static int detach_segment(yac_shared_segment *shared_segment) /* {{{ */ {
274 if (!shared_segment->size && mapping_base) {
275 UnmapViewOfFile(mapping_base);
276 CloseHandle(memfile);
277 }
278 return 0;
279 }
280 /* }}} */
281
282 static unsigned long segment_type_size(void) /* {{{ */ {
283 return sizeof(yac_shared_segment_create_file);
284 }
285 /* }}} */
286
287 yac_shared_memory_handlers yac_alloc_create_file_handlers = /* {{{ */ {
288 (create_segments_t)create_segments,
289 detach_segment,
290 segment_type_size
291 };
292 /* }}} */
293 #endif /* USE_CREATE_FILE */
294
295 /*
296 * Local variables:
297 * tab-width: 4
298 * c-basic-offset: 4
299 * End:
300 * vim600: noet sw=4 ts=4 fdm=marker
301 * vim<600: noet sw=4 ts=4
302 */
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 unsigned long allocate_size, occupied_size = 0;
44 unsigned int i, segment_size, segments_num = 1024;
45 yac_shared_segment_mmap first_segment;
46
47 k_size = YAC_SMM_ALIGNED_SIZE(k_size);
48 v_size = YAC_SMM_ALIGNED_SIZE(v_size);
49 while ((v_size / segments_num) < YAC_SMM_SEGMENT_MIN_SIZE) {
50 segments_num >>= 1;
51 }
52
53 segment_size = v_size / segments_num;
54 ++segments_num;
55
56 allocate_size = k_size + v_size;
57
58 first_segment.common.p = mmap(0, allocate_size, PROT_READ | PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
59 if (first_segment.common.p == MAP_FAILED) {
60 *error_in = "mmap";
61 return 0;
62 }
63 first_segment.size = allocate_size;
64 first_segment.common.size = k_size;
65 first_segment.common.pos = 0;
66
67 *shared_segments_p = (yac_shared_segment_mmap *)calloc(1, segments_num * sizeof(yac_shared_segment_mmap));
68 if (!*shared_segments_p) {
69 munmap(first_segment.common.p, first_segment.size);
70 *error_in = "calloc";
71 return 0;
72 } else {
73 *shared_segments_p[0] = first_segment;
74 }
75 *shared_segments_count = segments_num;
76
77 occupied_size = k_size;
78 for (i = 1; i < segments_num; i++) {
79 (*shared_segments_p)[i].size = 0;
80 (*shared_segments_p)[i].common.pos = 0;
81 (*shared_segments_p)[i].common.p = first_segment.common.p + occupied_size;
82 if ((allocate_size - occupied_size) >= YAC_SMM_ALIGNED_SIZE(segment_size)) {
83 (*shared_segments_p)[i].common.size = YAC_SMM_ALIGNED_SIZE(segment_size);
84 occupied_size += YAC_SMM_ALIGNED_SIZE(segment_size);
85 } else {
86 (*shared_segments_p)[i].common.size = (allocate_size - occupied_size);
87 break;
88 }
89 }
90
91 return 1;
92 }
93 /* }}} */
94
95 static int detach_segment(yac_shared_segment *shared_segment) /* {{{ */ {
96 if (shared_segment->size) {
97 munmap(shared_segment->p, shared_segment->size);
98 }
99 return 0;
100 }
101 /* }}} */
102
103 static unsigned long segment_type_size(void) /* {{{ */ {
104 return sizeof(yac_shared_segment_mmap);
105 }
106 /* }}} */
107
108 yac_shared_memory_handlers yac_alloc_mmap_handlers = /* {{{ */ {
109 (create_segments_t)create_segments,
110 detach_segment,
111 segment_type_size
112 };
113 /* }}} */
114
115 #endif /* USE_MMAP */
116
117 /*
118 * Local variables:
119 * tab-width: 4
120 * c-basic-offset: 4
121 * End:
122 * vim600: noet sw=4 ts=4 fdm=marker
123 * vim<600: noet sw=4 ts=4
124 */
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 <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 int yac_allocator_startup(unsigned long k_size, unsigned long size, char **msg) /* {{{ */ {
27 char *p;
28 yac_shared_segment *segments = NULL;
29 int i, segments_num, segments_array_size, segment_size;
30 const yac_shared_memory_handlers *he;
31
32 if ((he = &yac_shared_memory_handler)) {
33 int ret = he->create_segments(k_size, size, &segments, &segments_num, msg);
34
35 if (!ret) {
36 if (segments) {
37 int i;
38 for (i = 0; i < segments_num; i++) {
39 if (segments[i].p && segments[i].p != (void *)-1) {
40 he->detach_segment(&segments[i]);
41 }
42 }
43 free(segments);
44 }
45 return 0;
46 }
47 } else {
48 return 0;
49 }
50
51 segment_size = he->segment_type_size();
52 segments_array_size = (segments_num - 1) * segment_size;
53
54 yac_storage = segments[0].p;
55 memcpy(&YAC_SG(first_seg), (char *)(&segments[0]), segment_size);
56
57 YAC_SG(segments_num) = segments_num - 1;
58 YAC_SG(segments_num_mask) = YAC_SG(segments_num) - 1;
59 YAC_SG(segments) = (yac_shared_segment **)((char *)yac_storage + YAC_SMM_ALIGNED_SIZE(sizeof(yac_storage_globals) + segment_size - sizeof(yac_shared_segment)));
60
61 p = (char *)YAC_SG(segments) + (sizeof(void *) * YAC_SG(segments_num));
62 memcpy(p, (char *)segments + segment_size, segments_array_size);
63 for (i = 0; i < YAC_SG(segments_num); i++) {
64 YAC_SG(segments)[i] = (yac_shared_segment *)p;
65 p += segment_size;
66 }
67 YAC_SG(slots) = (yac_kv_key *)((char *)YAC_SG(segments)
68 + (YAC_SG(segments_num) * sizeof(void *)) + YAC_SMM_ALIGNED_SIZE(segments_array_size));
69
70 free(segments);
71
72 return 1;
73 }
74 /* }}} */
75
76 void yac_allocator_shutdown(void) /* {{{ */ {
77 yac_shared_segment **segments;
78 const yac_shared_memory_handlers *he;
79
80 segments = YAC_SG(segments);
81 if (segments) {
82 if ((he = &yac_shared_memory_handler)) {
83 int i = 0;
84 for (i = 0; i < YAC_SG(segments_num); i++) {
85 he->detach_segment(segments[i]);
86 }
87 he->detach_segment(&YAC_SG(first_seg));
88 }
89 }
90 }
91 /* }}} */
92
93 static inline void *yac_allocator_alloc_algo2(unsigned long size, int hash) /* {{{ */ {
94 yac_shared_segment *segment;
95 unsigned int seg_size, retry, pos, current;
96
97 current = hash & YAC_SG(segments_num_mask);
98 /* do we really need lock here? it depends the real life exam */
99 retry = 3;
100 do_retry:
101 segment = YAC_SG(segments)[current];
102 seg_size = segment->size;
103 pos = segment->pos;
104 if ((seg_size - pos) >= size) {
105 do_alloc:
106 pos += size;
107 segment->pos = pos;
108 if (segment->pos == pos) {
109 return (void *)((char *)segment->p + (pos - size));
110 } else if (retry--) {
111 goto do_retry;
112 }
113 return NULL;
114 } else {
115 int i, max;
116 max = (YAC_SG(segments_num) > 4)? 4 : YAC_SG(segments_num);
117 for (i = 1; i < max; i++) {
118 segment = YAC_SG(segments)[(current + i) & YAC_SG(segments_num_mask)];
119 seg_size = segment->size;
120 pos = segment->pos;
121 if ((seg_size - pos) >= size) {
122 current = (current + i) & YAC_SG(segments_num_mask);
123 goto do_alloc;
124 }
125 }
126 segment->pos = 0;
127 pos = 0;
128 ++YAC_SG(recycles);
129 goto do_alloc;
130 }
131 }
132 /* }}} */
133
134 #if 0
135 static inline void *yac_allocator_alloc_algo1(unsigned long size) /* {{{ */ {
136 int i, j, picked_seg, atime;
137 picked_seg = (YAC_SG(current_seg) + 1) & YAC_SG(segments_num_mask);
138
139 atime = YAC_SG(segments)[picked_seg]->atime;
140 for (i = 0; i < 10; i++) {
141 j = (picked_seg + 1) & YAC_SG(segments_num_mask);
142 if (YAC_SG(segments)[j]->atime < atime) {
143 picked_seg = j;
144 atime = YAC_SG(segments)[j]->atime;
145 }
146 }
147
148 YAC_SG(current_seg) = picked_seg;
149 YAC_SG(segments)[picked_seg]->pos = 0;
150 return yac_allocator_alloc_algo2(size);
151 }
152 /* }}} */
153 #endif
154
155 unsigned long yac_allocator_real_size(unsigned long size) /* {{{ */ {
156 unsigned long real_size = YAC_SMM_TRUE_SIZE(size);
157
158 if (real_size > YAC_SG(segments)[0]->size) {
159 return 0;
160 }
161
162 return real_size;
163 }
164 /* }}} */
165
166 void * yac_allocator_raw_alloc(unsigned long real_size, int hash) /* {{{ */ {
167
168 return yac_allocator_alloc_algo2(real_size, hash);
169 /*
170 if (YAC_SG(exhausted)) {
171 return yac_allocator_alloc_algo1(real_size);
172 } else {
173 void *p;
174 if ((p = yac_allocator_alloc_algo2(real_size))) {
175 return p;
176 }
177 return yac_allocator_alloc_algo1(real_size);
178 }
179 */
180 }
181 /* }}} */
182
183 #if 0
184 void yac_allocator_touch(void *p, unsigned long atime) /* {{{ */ {
185 yac_shared_block_header h = *(yac_shared_block_header *)(p - sizeof(yac_shared_block_header));
186
187 if (h.seg >= YAC_SG(segments_num)) {
188 return;
189 }
190
191 YAC_SG(segments)[h.seg]->atime = atime;
192 }
193 /* }}} */
194 #endif
195
196 /*
197 * Local variables:
198 * tab-width: 4
199 * c-basic-offset: 4
200 * End:
201 * vim600: noet sw=4 ts=4 fdm=marker
202 * vim<600: noet sw=4 ts=4
203 */
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 | John Neo <nhf0424@gmail.com> |
16 +----------------------------------------------------------------------+
17 */
18
19 #ifndef YAC_ATOMIC_H
20 #define YAC_ATOMIC_H
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #if HAVE_BUILTIN_ATOMIC
27 #define YAC_CAS(lock, old, set) __sync_bool_compare_and_swap(lock, old, set)
28 #elif ( __amd64__ || __amd64 || __x86_64__ || __i386__ || __i386 )
29 static inline int __yac_cas(unsigned int *lock, unsigned int old, unsigned int set) {
30 unsigned char res;
31
32 __asm__ volatile ( "lock;" "cmpxchgl %3, %1;" "sete %0;" :
33 "=a" (res) : "m" (*lock), "a" (old), "r" (set) : "memory");
34
35 return res;
36 }
37 #define YAC_CAS(lock, old, set) __yac_cas(lock, old, set)
38 #elif ZEND_WIN32
39 #define YAC_CAS(lock, old, set) (InterlockedCompareExchange(lock, set, old) == old)
40 #else
41 #undef YAC_CAS
42 #warning No atomic CAS supports
43 #endif
44
45 #ifdef YAC_CAS
46
47 #define MUT_READ 0x0
48 #define MUT_WRITE 0x1
49 #define CAS_MAX_SPIN 100
50
51 static inline int yac_mutex_write(unsigned int *me) {
52 int retry = 0;
53 while (!YAC_CAS(me, MUT_READ, MUT_WRITE)) {
54 if (++retry == CAS_MAX_SPIN) {
55 return 0;
56 }
57 }
58 return 1;
59 }
60
61 static inline void yac_mutex_read(unsigned int *me) {
62 *me = MUT_READ;
63 }
64
65 #define WRITEP(P) yac_mutex_write(&(P->mutex))
66 #define READP(P) yac_mutex_read(&(P->mutex))
67 #else
68 #undef YAC_CAS
69 #define WRITEP(P) (1)
70 #define READP(P)
71 #endif
72
73 #endif
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 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21
22 #include "php.h"
23
24 #if HAVE_SSE_CRC32
25 #include "Zend/zend_cpuinfo.h"
26 #include <nmmintrin.h>
27 static uint32_t crc32c_sse42(const char *dagta, unsigned int size);
28 #endif
29
30 #include "yac_atomic.h"
31 #include "yac_storage.h"
32 #include "allocator/yac_allocator.h"
33
34 yac_storage_globals *yac_storage;
35
36 static uint32_t (*yac_crc)(const char *data, unsigned int size);
37 static uint32_t crc32(const char *dagta, unsigned int size);
38
39 static inline unsigned int yac_storage_align_size(unsigned int size) /* {{{ */ {
40 int bits = 0;
41 while ((size = size >> 1)) {
42 ++bits;
43 }
44 return (1 << bits);
45 }
46 /* }}} */
47
48 int yac_storage_startup(unsigned long fsize, unsigned long size, char **msg) /* {{{ */ {
49 unsigned long real_size;
50
51 if (!yac_allocator_startup(fsize, size, msg)) {
52 return 0;
53 }
54 #if HAVE_SSE_CRC32
55 if (zend_cpu_supports_sse42()) {
56 yac_crc = crc32c_sse42;
57 } else
58 #endif
59 {
60 yac_crc = crc32;
61 }
62 size = YAC_SG(first_seg).size - ((char *)YAC_SG(slots) - (char *)yac_storage);
63 real_size = yac_storage_align_size(size / sizeof(yac_kv_key));
64 if (!((size / sizeof(yac_kv_key)) & ~(real_size << 1))) {
65 real_size <<= 1;
66 }
67
68 YAC_SG(slots_size) = real_size;
69 YAC_SG(slots_mask) = real_size - 1;
70 YAC_SG(slots_num) = 0;
71 YAC_SG(fails) = 0;
72 YAC_SG(hits) = 0;
73 YAC_SG(miss) = 0;
74 YAC_SG(kicks) = 0;
75
76 memset((char *)YAC_SG(slots), 0, sizeof(yac_kv_key) * real_size);
77
78 return 1;
79 }
80 /* }}} */
81
82 void yac_storage_shutdown(void) /* {{{ */ {
83 yac_allocator_shutdown();
84 }
85 /* }}} */
86
87 /* {{{ MurmurHash2 (Austin Appleby)
88 */
89 static inline uint64_t yac_inline_hash_func1(const char *data, unsigned int len) {
90 unsigned int h, k;
91
92 h = 0 ^ len;
93
94 while (len >= 4) {
95 k = data[0];
96 k |= data[1] << 8;
97 k |= data[2] << 16;
98 k |= data[3] << 24;
99
100 k *= 0x5bd1e995;
101 k ^= k >> 24;
102 k *= 0x5bd1e995;
103
104 h *= 0x5bd1e995;
105 h ^= k;
106
107 data += 4;
108 len -= 4;
109 }
110
111 switch (len) {
112 case 3:
113 h ^= data[2] << 16;
114 case 2:
115 h ^= data[1] << 8;
116 case 1:
117 h ^= data[0];
118 h *= 0x5bd1e995;
119 }
120
121 h ^= h >> 13;
122 h *= 0x5bd1e995;
123 h ^= h >> 15;
124
125 return h;
126 }
127 /* }}} */
128
129 /* {{{ DJBX33A (Daniel J. Bernstein, Times 33 with Addition)
130 *
131 * This is Daniel J. Bernstein's popular `times 33' hash function as
132 * posted by him years ago on comp->lang.c. It basically uses a function
133 * like ``hash(i) = hash(i-1) * 33 + str[i]''. This is one of the best
134 * known hash functions for strings. Because it is both computed very
135 * fast and distributes very well.
136 *
137 * The magic of number 33, i.e. why it works better than many other
138 * constants, prime or not, has never been adequately explained by
139 * anyone. So I try an explanation: if one experimentally tests all
140 * multipliers between 1 and 256 (as RSE did now) one detects that even
141 * numbers are not useable at all. The remaining 128 odd numbers
142 * (except for the number 1) work more or less all equally well. They
143 * all distribute in an acceptable way and this way fill a hash table
144 * with an average percent of approx. 86%.
145 *
146 * If one compares the Chi^2 values of the variants, the number 33 not
147 * even has the best value. But the number 33 and a few other equally
148 * good numbers like 17, 31, 63, 127 and 129 have nevertheless a great
149 * advantage to the remaining numbers in the large set of possible
150 * multipliers: their multiply operation can be replaced by a faster
151 * operation based on just one shift plus either a single addition
152 * or subtraction operation. And because a hash function has to both
153 * distribute good _and_ has to be very fast to compute, those few
154 * numbers should be preferred and seems to be the reason why Daniel J.
155 * Bernstein also preferred it.
156 *
157 *
158 * -- Ralf S. Engelschall <rse@engelschall.com>
159 */
160
161 static inline uint64_t yac_inline_hash_func2(const char *key, uint32_t len) {
162 register uint64_t hash = 5381;
163
164 /* variant with the hash unrolled eight times */
165 for (; len >= 8; len -= 8) {
166 hash = ((hash << 5) + hash) + *key++;
167 hash = ((hash << 5) + hash) + *key++;
168 hash = ((hash << 5) + hash) + *key++;
169 hash = ((hash << 5) + hash) + *key++;
170 hash = ((hash << 5) + hash) + *key++;
171 hash = ((hash << 5) + hash) + *key++;
172 hash = ((hash << 5) + hash) + *key++;
173 hash = ((hash << 5) + hash) + *key++;
174 }
175 switch (len) {
176 case 7: hash = ((hash << 5) + hash) + *key++; /* fallthrough... */
177 case 6: hash = ((hash << 5) + hash) + *key++; /* fallthrough... */
178 case 5: hash = ((hash << 5) + hash) + *key++; /* fallthrough... */
179 case 4: hash = ((hash << 5) + hash) + *key++; /* fallthrough... */
180 case 3: hash = ((hash << 5) + hash) + *key++; /* fallthrough... */
181 case 2: hash = ((hash << 5) + hash) + *key++; /* fallthrough... */
182 case 1: hash = ((hash << 5) + hash) + *key++; break;
183 case 0: break;
184 default: break;
185 }
186 return hash;
187 }
188 /* }}} */
189
190 /* {{{ COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
191 * code or tables extracted from it, as desired without restriction.
192 *
193 * First, the polynomial itself and its table of feedback terms. The
194 * polynomial is
195 * 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
196 *
197 * Note that we take it "backwards" and put the highest-order term in
198 * the lowest-order bit. The X^32 term is "implied"; the LSB is the
199 * X^31 term, etc. The X^0 term (usually shown as "+1") results in
200 * the MSB being 1
201 *
202 * Note that the usual hardware shift register implementation, which
203 * is what we're using (we're merely optimizing it by doing eight-bit
204 * chunks at a time) shifts bits into the lowest-order term. In our
205 * implementation, that means shifting towards the right. Why do we
206 * do it this way? Because the calculated CRC must be transmitted in
207 * order from highest-order term to lowest-order term. UARTs transmit
208 * characters in order from LSB to MSB. By storing the CRC this way
209 * we hand it to the UART in the order low-byte to high-byte; the UART
210 * sends each low-bit to hight-bit; and the result is transmission bit
211 * by bit from highest- to lowest-order term without requiring any bit
212 * shuffling on our part. Reception works similarly
213 *
214 * The feedback terms table consists of 256, 32-bit entries. Notes
215 *
216 * The table can be generated at runtime if desired; code to do so
217 * is shown later. It might not be obvious, but the feedback
218 * terms simply represent the results of eight shift/xor opera
219 * tions for all combinations of data and CRC register values
220 *
221 * The values must be right-shifted by eight bits by the "updcrc
222 * logic; the shift must be unsigned (bring in zeroes). On some
223 * hardware you could probably optimize the shift in assembler by
224 * using byte-swap instructions
225 * polynomial $edb88320
226 *
227 *
228 * CRC32 code derived from work by Gary S. Brown.
229 */
230
231 static unsigned int crc32_tab[] = {
232 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
233 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
234 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
235 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
236 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
237 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
238 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
239 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
240 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
241 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
242 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
243 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
244 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
245 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
246 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
247 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
248 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
249 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
250 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
251 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
252 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
253 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
254 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
255 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
256 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
257 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
258 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
259 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
260 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
261 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
262 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
263 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
264 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
265 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
266 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
267 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
268 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
269 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
270 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
271 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
272 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
273 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
274 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
275 };
276
277 static uint32_t crc32(const char *buf, unsigned int size) {
278 const char *p;
279 uint32_t crc = 0 ^ 0xFFFFFFFF;
280
281 p = buf;
282 while (size--) {
283 crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
284 }
285
286 return crc ^ 0xFFFFFFFF;
287 }
288 /* }}} */
289
290 #if HAVE_SSE_CRC32
291 static uint32_t crc32c_sse42(const char *buf, unsigned int size) /* {{{ */ {
292 uint32_t crc = 0 ^ 0xFFFFFFFF;
293 #if __x86_64__
294 while (size >= sizeof(uint64_t)) {
295 crc = _mm_crc32_u64(crc, *(uint64_t*)buf);
296 buf += sizeof(uint64_t);
297 size -= sizeof(uint64_t);
298 }
299 #endif
300 while (size >= sizeof(uint32_t)) {
301 crc = _mm_crc32_u32(crc, *(uint32_t*)buf);
302 buf += sizeof(uint32_t);
303 size -= sizeof(uint32_t);
304 }
305 if (size >= sizeof(uint16_t)) {
306 crc = _mm_crc32_u16(crc, *(uint16_t*)buf);
307 buf += sizeof(uint16_t);
308 size -= sizeof(uint16_t);
309 }
310 if (size) {
311 crc = _mm_crc32_u8(crc, *buf);
312 }
313
314 return crc ^ 0xFFFFFFFF;
315 }
316 /* }}} */
317 #endif
318
319 static inline unsigned int yac_crc32(char *data, unsigned int size) /* {{{ */ {
320 if (size < YAC_FULL_CRC_THRESHOLD) {
321 return yac_crc(data, size);
322 } else {
323 int i = 0;
324 char crc_contents[YAC_FULL_CRC_THRESHOLD];
325 int head = YAC_FULL_CRC_THRESHOLD >> 2;
326 int tail = YAC_FULL_CRC_THRESHOLD >> 4;
327 int body = YAC_FULL_CRC_THRESHOLD - head - tail;
328 char *p = data + head;
329 char *q = crc_contents + head;
330 int step = (size - tail - head) / body;
331
332 memcpy(crc_contents, data, head);
333 for (; i < body; i++, q++, p+= step) {
334 *q = *p;
335 }
336 memcpy(q, p, tail);
337
338 return yac_crc(crc_contents, YAC_FULL_CRC_THRESHOLD);
339 }
340 }
341 /* }}} */
342
343 int yac_storage_find(const char *key, unsigned int len, char **data, unsigned int *size, unsigned int *flag, int *cas, unsigned long tv) /* {{{ */ {
344 uint64_t h, hash, seed;
345 yac_kv_key k, *p;
346 yac_kv_val v;
347
348 hash = h = yac_inline_hash_func1(key, len);
349 p = &(YAC_SG(slots)[h & YAC_SG(slots_mask)]);
350 if (!WRITEP(p)) {
351 ++YAC_SG(miss);
352 return 0;
353 }
354 k = *p;
355 READP(p);
356 if (k.val) {
357 char *s;
358 uint32_t i;
359 if (k.h == hash && YAC_KEY_KLEN(k) == len) {
360 v = *(k.val);
361 if (!memcmp(k.key, key, len)) {
362 s = USER_ALLOC(YAC_KEY_VLEN(k) + 1);
363 memcpy(s, (char *)k.val->data, YAC_KEY_VLEN(k));
364 do_verify:
365 if (k.len != v.len) {
366 USER_FREE(s);
367 ++YAC_SG(miss);
368 return 0;
369 }
370
371 if (k.ttl) {
372 if (k.ttl <= tv) {
373 ++YAC_SG(miss);
374 USER_FREE(s);
375 return 0;
376 }
377 }
378
379 if (k.crc != yac_crc32(s, YAC_KEY_VLEN(k))) {
380 USER_FREE(s);
381 ++YAC_SG(miss);
382 return 0;
383 }
384 s[YAC_KEY_VLEN(k)] = '\0';
385 k.val->atime = tv;
386 *data = s;
387 *size = YAC_KEY_VLEN(k);
388 *flag = k.flag;
389 ++YAC_SG(hits);
390 return 1;
391 }
392 }
393
394 seed = yac_inline_hash_func2(key, len);
395 for (i = 0; i < 3; i++) {
396 h += seed & YAC_SG(slots_mask);
397 p = &(YAC_SG(slots)[h & YAC_SG(slots_mask)]);
398 if (!WRITEP(p)) {
399 ++YAC_SG(miss);
400 return 0;
401 }
402 k = *p;
403 READP(p);
404 if (k.h == hash && YAC_KEY_KLEN(k) == len) {
405 v = *(k.val);
406 if (!memcmp(k.key, key, len)) {
407 s = USER_ALLOC(YAC_KEY_VLEN(k) + 1);
408 memcpy(s, (char *)k.val->data, YAC_KEY_VLEN(k));
409 goto do_verify;
410 }
411 }
412 }
413 }
414
415 ++YAC_SG(miss);
416
417 return 0;
418 }
419 /* }}} */
420
421 int yac_storage_delete(const char *key, unsigned int len, int ttl, unsigned long tv) /* {{{ */ {
422 uint64_t hash, h, seed;
423 yac_kv_key k, *p;
424
425 hash = h = yac_inline_hash_func1(key, len);
426 p = &(YAC_SG(slots)[h & YAC_SG(slots_mask)]);
427 if (!WRITEP(p)) {
428 return 0;
429 }
430 k = *p;
431 READP(p);
432 if (k.val) {
433 uint32_t i;
434 if (k.h == hash && YAC_KEY_KLEN(k) == len) {
435 if (!memcmp((char *)k.key, key, len)) {
436 if (ttl == 0) {
437 p->ttl = 1;
438 } else {
439 p->ttl = ttl + tv;
440 }
441 return 1;
442 }
443 }
444
445 seed = yac_inline_hash_func2(key, len);
446 for (i = 0; i < 3; i++) {
447 h += seed & YAC_SG(slots_mask);
448 p = &(YAC_SG(slots)[h & YAC_SG(slots_mask)]);
449 if (!WRITEP(p)) {
450 return 0;
451 }
452 k = *p;
453 READP(p);
454 if (k.val == NULL) {
455 return 1;
456 } else if (k.h == hash && YAC_KEY_KLEN(k) == len && !memcmp((char *)k.key, key, len)) {
457 p->ttl = 1;
458 return 1;
459 }
460 }
461 }
462
463 return 0;
464 }
465 /* }}} */
466
467 int yac_storage_update(const char *key, unsigned int len, char *data, unsigned int size, unsigned int flag, int ttl, int add, unsigned long tv) /* {{{ */ {
468 uint64_t hash, h;
469 int idx = 0, is_valid;
470 yac_kv_key *p, k, *paths[4];
471 yac_kv_val *val, *s;
472 unsigned long real_size;
473
474 hash = h = yac_inline_hash_func1(key, len);
475 paths[idx++] = p = &(YAC_SG(slots)[h & YAC_SG(slots_mask)]);
476 if (!WRITEP(p)) {
477 return 0;
478 }
479 k = *p;
480 READP(p);
481 if (k.val) {
482 /* Found the exact match */
483 if (k.h == hash && YAC_KEY_KLEN(k) == len && !memcmp((char *)k.key, key, len)) {
484 do_update:
485 is_valid = 0;
486 if (k.crc == yac_crc32(k.val->data, YAC_KEY_VLEN(k))) {
487 is_valid = 1;
488 }
489 if (add && (!k.ttl || k.ttl > tv) && is_valid) {
490 return 0;
491 }
492 if (k.size >= size && is_valid) {
493 s = USER_ALLOC(sizeof(yac_kv_val) + size - 1);
494 memcpy(s->data, data, size);
495 if (ttl) {
496 k.ttl = (uint64_t)tv + ttl;
497 } else {
498 k.ttl = 0;
499 }
500 s->atime = tv;
501 YAC_KEY_SET_LEN(*s, len, size);
502 memcpy((char *)k.val, (char *)s, sizeof(yac_kv_val) + size - 1);
503 k.crc = yac_crc32(s->data, size);
504 k.flag = flag;
505 memcpy(k.key, key, len);
506 YAC_KEY_SET_LEN(k, len, size);
507 if (!WRITEP(p)) {
508 USER_FREE(s);
509 return 0;
510 }
511 *p = k;
512 READP(p);
513 USER_FREE(s);
514 return 1;
515 } else {
516 uint32_t msize;
517 real_size = yac_allocator_real_size(sizeof(yac_kv_val) + (size * YAC_STORAGE_FACTOR) - 1);
518 if (!real_size) {
519 ++YAC_SG(fails);
520 return 0;
521 }
522 msize = sizeof(yac_kv_val) + size - 1;
523 s = USER_ALLOC(sizeof(yac_kv_val) + size - 1);
524 memcpy(s->data, data, size);
525 s->atime = tv;
526 YAC_KEY_SET_LEN(*s, len, size);
527 val = yac_allocator_raw_alloc(real_size, (int)hash);
528 if (val) {
529 memcpy((char *)val, (char *)s, msize);
530 if (ttl) {
531 k.ttl = tv + ttl;
532 } else {
533 k.ttl = 0;
534 }
535 k.crc = yac_crc32(s->data, size);
536 k.val = val;
537 k.flag = flag;
538 k.size = real_size;
539 memcpy(k.key, key, len);
540 YAC_KEY_SET_LEN(k, len, size);
541 if (!WRITEP(p)) {
542 USER_FREE(s);
543 return 0;
544 }
545 *p = k;
546 READP(p);
547 USER_FREE(s);
548 return 1;
549 }
550 ++YAC_SG(fails);
551 USER_FREE(s);
552 return 0;
553 }
554 } else {
555 uint32_t i;
556 uint64_t seed, max_atime;
557
558 seed = yac_inline_hash_func2(key, len);
559 for (i = 0; i < 3; i++) {
560 h += seed & YAC_SG(slots_mask);
561 paths[idx++] = p = &(YAC_SG(slots)[h & YAC_SG(slots_mask)]);
562 if (!WRITEP(p)) {
563 return 0;
564 }
565 k = *p;
566 READP(p);
567 if (k.val == NULL) {
568 goto do_add;
569 } else if (k.h == hash && YAC_KEY_KLEN(k) == len && !memcmp((char *)k.key, key, len)) {
570 /* Found the exact match */
571 goto do_update;
572 }
573 }
574
575 --idx;
576 max_atime = paths[idx]->val->atime;
577 for (i = 0; i < idx; i++) {
578 if ((paths[i]->ttl && paths[i]->ttl <= tv) || paths[i]->len != paths[i]->val->len) {
579 p = paths[i];
580 goto do_add;
581 } else if (paths[i]->val->atime < max_atime) {
582 max_atime = paths[i]->val->atime;
583 p = paths[i];
584 }
585 }
586 if (!WRITEP(p)) {
587 return 0;
588 }
589 k = *p;
590 READP(p);
591 ++YAC_SG(kicks);
592 k.h = hash;
593
594 goto do_update;
595 }
596 } else {
597 do_add:
598 real_size = yac_allocator_real_size(sizeof(yac_kv_val) + (size * YAC_STORAGE_FACTOR) - 1);
599 if (!real_size) {
600 ++YAC_SG(fails);
601 return 0;
602 }
603 s = USER_ALLOC(sizeof(yac_kv_val) + size - 1);
604 memcpy(s->data, data, size);
605 s->atime = tv;
606 YAC_KEY_SET_LEN(*s, len, size);
607 val = yac_allocator_raw_alloc(real_size, (int)hash);
608 if (val) {
609 memcpy((char *)val, (char *)s, sizeof(yac_kv_val) + size - 1);
610 if (p->val == NULL) {
611 ++YAC_SG(slots_num);
612 }
613 k.h = hash;
614 k.val = val;
615 k.flag = flag;
616 k.size = real_size;
617 k.crc = yac_crc32(s->data, size);
618 memcpy(k.key, key, len);
619 YAC_KEY_SET_LEN(k, len, size);
620 if (ttl) {
621 k.ttl = tv + ttl;
622 } else {
623 k.ttl = 0;
624 }
625 if (!WRITEP(p)) {
626 USER_FREE(s);
627 return 0;
628 }
629 *p = k;
630 READP(p);
631 USER_FREE(s);
632 return 1;
633 }
634 ++YAC_SG(fails);
635 USER_FREE(s);
636 }
637 return 0;
638 }
639 /* }}} */
640
641 void yac_storage_flush(void) /* {{{ */ {
642 YAC_SG(slots_num) = 0;
643
644 memset((char *)YAC_SG(slots), 0, sizeof(yac_kv_key) * YAC_SG(slots_size));
645 }
646 /* }}} */
647
648 yac_storage_info * yac_storage_get_info(void) /* {{{ */ {
649 yac_storage_info *info = USER_ALLOC(sizeof(yac_storage_info));
650
651 info->k_msize = (unsigned long)YAC_SG(first_seg).size;
652 info->v_msize = (unsigned long)YAC_SG(segments)[0]->size * (unsigned long)YAC_SG(segments_num);
653 info->segment_size = YAC_SG(segments)[0]->size;
654 info->segments_num = YAC_SG(segments_num);
655 info->hits = YAC_SG(hits);
656 info->miss = YAC_SG(miss);
657 info->fails = YAC_SG(fails);
658 info->kicks = YAC_SG(kicks);
659 info->recycles = YAC_SG(recycles);
660 info->slots_size = YAC_SG(slots_size);
661 info->slots_num = YAC_SG(slots_num);
662
663 return info;
664 }
665 /* }}} */
666
667 void yac_storage_free_info(yac_storage_info *info) /* {{{ */ {
668 USER_FREE(info);
669 }
670 /* }}} */
671
672 yac_item_list * yac_storage_dump(unsigned int limit) /* {{{ */ {
673 yac_kv_key k;
674 yac_item_list *item, *list = NULL;
675
676 if (YAC_SG(slots_num)) {
677 unsigned int i = 0, n = 0;
678 for (; i<YAC_SG(slots_size) && n < YAC_SG(slots_num) && n < limit; i++) {
679 k = YAC_SG(slots)[i];
680 if (k.val) {
681 item = USER_ALLOC(sizeof(yac_item_list));
682 item->index = i;
683 item->h = k.h;
684 item->crc = k.crc;
685 item->ttl = k.ttl;
686 item->k_len = YAC_KEY_KLEN(k);
687 item->v_len = YAC_KEY_VLEN(k);
688 item->flag = k.flag;
689 item->size = k.size;
690 memcpy(item->key, k.key, YAC_STORAGE_MAX_KEY_LEN);
691 item->next = list;
692 list = item;
693 ++n;
694 }
695 }
696 }
697
698 return list;
699 }
700 /* }}} */
701
702 void yac_storage_free_list(yac_item_list *list) /* {{{ */ {
703 yac_item_list *l;
704 while (list) {
705 l = list;
706 list = list->next;
707 USER_FREE(l);
708 }
709 }
710 /* }}} */
711
712 const char * yac_storage_shared_memory_name(void) /* {{{ */ {
713 return YAC_SHARED_MEMORY_HANDLER_NAME;
714 }
715 /* }}} */
716
717 /*
718 * Local variables:
719 * tab-width: 4
720 * c-basic-offset: 4
721 * End:
722 * vim600: noet sw=4 ts=4 fdm=marker
723 * vim<600: noet sw=4 ts=4
724 */
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 int crc;
45 unsigned int ttl;
46 unsigned int len;
47 unsigned int flag;
48 unsigned int size;
49 unsigned int mutex;
50 yac_kv_val *val;
51 unsigned char key[YAC_STORAGE_MAX_KEY_LEN];
52 } yac_kv_key;
53
54 typedef struct _yac_item_list {
55 unsigned int index;
56 unsigned long h;
57 unsigned long crc;
58 unsigned int ttl;
59 unsigned int k_len;
60 unsigned int v_len;
61 unsigned int flag;
62 unsigned int size;
63 unsigned char key[YAC_STORAGE_MAX_KEY_LEN];
64 struct _yac_item_list *next;
65 } yac_item_list;
66
67 typedef struct {
68 volatile unsigned int pos;
69 unsigned int size;
70 void *p;
71 } yac_shared_segment;
72
73 typedef struct {
74 unsigned long k_msize;
75 unsigned long v_msize;
76 unsigned int segments_num;
77 unsigned int segment_size;
78 unsigned int slots_num;
79 unsigned int slots_size;
80 unsigned int miss;
81 unsigned int fails;
82 unsigned int kicks;
83 unsigned int recycles;
84 unsigned long hits;
85 } yac_storage_info;
86
87 typedef struct {
88 yac_kv_key *slots;
89 unsigned int slots_mask;
90 unsigned int slots_num;
91 unsigned int slots_size;
92 unsigned int miss;
93 unsigned int fails;
94 unsigned int kicks;
95 unsigned int recycles;
96 unsigned long hits;
97 yac_shared_segment **segments;
98 unsigned int segments_num;
99 unsigned int segments_num_mask;
100 yac_shared_segment first_seg;
101 } yac_storage_globals;
102
103 extern yac_storage_globals *yac_storage;
104
105 #define YAC_SG(element) (yac_storage->element)
106
107 int yac_storage_startup(unsigned long first_size, unsigned long size, char **err);
108 void yac_storage_shutdown(void);
109 int yac_storage_find(const char *key, unsigned int len, char **data, unsigned int *size, unsigned int *flag, int *cas, unsigned long tv);
110 int yac_storage_update(const char *key, unsigned int len, char *data, unsigned int size, unsigned int falg, int ttl, int add, unsigned long tv);
111 int yac_storage_delete(const char *key, unsigned int len, int ttl, unsigned long tv);
112 void yac_storage_flush(void);
113 const char * yac_storage_shared_memory_name(void);
114 yac_storage_info * yac_storage_get_info(void);
115 void yac_storage_free_info(yac_storage_info *info);
116 yac_item_list * yac_storage_dump(unsigned int limit);
117 void yac_storage_free_list(yac_item_list *list);
118 #define yac_storage_exists(ht, key, len) yac_storage_find(ht, key, len, NULL)
119
120 #endif /* YAC_STORAGE_H */
121
122 /*
123 * Local variables:
124 * tab-width: 4
125 * c-basic-offset: 4
126 * End:
127 * vim600: noet sw=4 ts=4 fdm=marker
128 * vim<600: noet sw=4 ts=4
129 */
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 --INI--
5 yac.enable=1
6 yac.enable_cli=1
7 yac.keys_memory_size=4M
8 yac.values_memory_size=32M
9 yac.serializer=php
10 --FILE--
11 <?php
12 $yac = new Yac();
13
14 var_dump(YAC_SERIALIZER == YAC_SERIALIZER_PHP);
15
16 $key = "foo";
17 $value = "dummy";
18
19 var_dump($yac->set($key, $value));
20 var_dump($yac->get($key));
21
22 $value = NULL;
23 var_dump($yac->set($key, $value));
24 var_dump($yac->get($key));
25
26 $value = TRUE;
27 var_dump($yac->set($key, $value));
28 var_dump($yac->get($key));
29
30 $value = FALSE;
31 var_dump($yac->set($key, $value));
32 var_dump($yac->get($key));
33
34 $value = range(1, 5);
35 var_dump($yac->set($key, $value));
36 var_dump($yac->get($key));
37
38 $value = 9234324;
39 var_dump($yac->set($key, $value));
40 var_dump($yac->get($key));
41
42 $value = 9234324.123456;
43 var_dump($yac->set($key, $value));
44 var_dump($yac->get($key));
45
46 $value = new StdClass();;
47 var_dump($yac->set($key, $value));
48 var_dump($yac->get($key));
49
50 $value = fopen("php://input", "r");
51 var_dump($yac->set($key, $value));
52
53 $value = range(1, 5);
54 var_dump($yac->set($key, $value));
55 var_dump($yac->delete($key));
56 var_dump($yac->get($key));
57
58 ?>
59 --EXPECTF--
60 bool(true)
61 bool(true)
62 string(5) "dummy"
63 bool(true)
64 NULL
65 bool(true)
66 bool(true)
67 bool(true)
68 bool(false)
69 bool(true)
70 array(5) {
71 [0]=>
72 int(1)
73 [1]=>
74 int(2)
75 [2]=>
76 int(3)
77 [3]=>
78 int(4)
79 [4]=>
80 int(5)
81 }
82 bool(true)
83 int(9234324)
84 bool(true)
85 float(9234324.123456)
86 bool(true)
87 object(stdClass)#3 (0) {
88 }
89
90 Warning: Yac::set(): Type 'IS_RESOURCE' cannot be stored in %s002.php on line %d
91 bool(false)
92 bool(true)
93 bool(true)
94 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 'kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk' exceed max key length '48' bytes in %s003.php on line %d
38 bool(false)
39
40 Warning: Yac::get(): Key 'kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk' exceed max key length '48' bytes in %s003.php on line %d
41 bool(false)
42
43 Warning: Yac::set(): Key 'dummykkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk' exceed max key length '48' bytes in %s003.php on line %d
44 bool(false)
45
46 Warning: Yac::get(): Key 'dummykkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk' exceed max key length '48' bytes in %s003.php on line %d
47 bool(false)
48
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 %s error:%sObject of class stdClass could not be converted to string in %s005.php%A
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 --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 $yac->set('test', 1, 1);
13 sleep(2);
14 var_dump($yac->get('test'));
15 ?>
16 --EXPECTF--
17 bool(false)
0 --TEST--
1 Check for ttl bug
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 yac.compress_threshold=1024
10 --FILE--
11 <?php
12 error_reporting(E_ALL);
13 $yac = new Yac();
14
15 for($i = 0; $i<100; $i++) {
16 $value[] = ($i + 100000)."sdfsfsfsfs";
17 }
18
19 $yac->set('test', $value);
20
21 echo count($yac->get('test'));
22 ?>
23 --EXPECTF--
24 100
0 --TEST--
1 Check for Yac::dump
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 yac.compress_threshold=1024
10 --FILE--
11 <?php
12 $yac = new Yac();
13
14 for ($i = 0; $i<100; $i++) {
15 $yac->set("key". $i, "kjslkdfkldasjkf");
16 }
17 for ($i = 0; $i<100; $i++) {
18 $yac->set("key". $i, "kjslkdfkldasjkf");
19 }
20
21 var_dump(count($yac->dump(1000)));
22 --EXPECTF--
23 int(100)
0 --TEST--
1 Check for Yac setter/getter
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 yac.compress_threshold=1024
10 --FILE--
11 <?php
12 $yac = new Yac("prefix");
13
14 $yac->name = "test";
15
16 var_dump($yac->name);
17 var_dump($yac->get("name"));
18 ?>
19 --EXPECTF--
20 string(4) "test"
21 string(4) "test"
0 --TEST--
1 Check for mutiple process
2 --SKIPIF--
3 <?php if (!extension_loaded("yac")) print "skip"; ?>
4 <?php if (!extension_loaded("pcntl")) print "skip need pcntl"; ?>
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 $yac = new Yac();
14
15 if (($pid = pcntl_fork())) {
16 while(!$yac->set("parent", "FIN"));
17 while (!($msg = $yac->get("child")));
18 echo "MSG From Child:", $msg,"\n";
19 while(!($yac->set("parent", "BYE")));
20 pcntl_wait($status);
21 echo "Parent exiting\n";
22 } else {
23 while(!($msg = $yac->get("parent")));
24 echo "MSG From Parent:" , $msg, "\n";
25 while(!($yac->set("child", "ACK")));
26 while(($msg = $yac->get("parent")) != "BYE");
27 echo "Child exiting\n";
28 }
29 ?>
30 --EXPECT--
31 MSG From Parent:FIN
32 MSG From Child:ACK
33 Child exiting
34 Parent exiting
0 --TEST--
1 Check for yac with json serializer
2 --SKIPIF--
3 <?php if (!extension_loaded("yac")) print "skip"; ?>
4 <?php if (!defined("YAC_SERIALIZER_JSON")) die ("skip need --enable-json"); ?>
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.serializer=json
11 --FILE--
12 <?php
13 $yac = new Yac();
14
15 var_dump(YAC_SERIALIZER == YAC_SERIALIZER_JSON);
16 $key = "foo";
17 $value = "dummy";
18
19 var_dump($yac->set($key, $value));
20 var_dump($yac->get($key));
21
22 $value = NULL;
23 var_dump($yac->set($key, $value));
24 var_dump($yac->get($key));
25
26 $value = TRUE;
27 var_dump($yac->set($key, $value));
28 var_dump($yac->get($key));
29
30 $value = FALSE;
31 var_dump($yac->set($key, $value));
32 var_dump($yac->get($key));
33
34 $value = range(1, 5);
35 var_dump($yac->set($key, $value));
36 var_dump($yac->get($key));
37
38 $value = 9234324;
39 var_dump($yac->set($key, $value));
40 var_dump($yac->get($key));
41
42 $value = 9234324.123456;
43 var_dump($yac->set($key, $value));
44 var_dump($yac->get($key));
45
46 $value = new StdClass();;
47 var_dump($yac->set($key, $value));
48 var_dump($yac->get($key));
49
50 $value = fopen("php://input", "r");
51 var_dump($yac->set($key, $value));
52
53 $value = range(1, 5);
54 var_dump($yac->set($key, $value));
55 var_dump($yac->delete($key));
56 var_dump($yac->get($key));
57
58 ?>
59 --EXPECTF--
60 bool(true)
61 bool(true)
62 string(5) "dummy"
63 bool(true)
64 NULL
65 bool(true)
66 bool(true)
67 bool(true)
68 bool(false)
69 bool(true)
70 array(5) {
71 [0]=>
72 int(1)
73 [1]=>
74 int(2)
75 [2]=>
76 int(3)
77 [3]=>
78 int(4)
79 [4]=>
80 int(5)
81 }
82 bool(true)
83 int(9234324)
84 bool(true)
85 float(9234324.123456)
86 bool(true)
87 array(0) {
88 }
89
90 Warning: Yac::set(): Type 'IS_RESOURCE' cannot be stored in %s018.php on line %d
91 bool(false)
92 bool(true)
93 bool(true)
94 bool(false)
0 --TEST--
1 Check for yac with msgpack serializer
2 --SKIPIF--
3 <?php if (!extension_loaded("yac")) print "skip"; ?>
4 <?php if (!defined("YAC_SERIALIZER_MSGPACK")) die ("skip need --enable-msgpack"); ?>
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.serializer=msgpack
11 --FILE--
12 <?php
13 $yac = new Yac();
14
15 var_dump(YAC_SERIALIZER == YAC_SERIALIZER_MSGPACK);
16 $key = "foo";
17 $value = "dummy";
18
19 var_dump($yac->set($key, $value));
20 var_dump($yac->get($key));
21
22 $value = NULL;
23 var_dump($yac->set($key, $value));
24 var_dump($yac->get($key));
25
26 $value = TRUE;
27 var_dump($yac->set($key, $value));
28 var_dump($yac->get($key));
29
30 $value = FALSE;
31 var_dump($yac->set($key, $value));
32 var_dump($yac->get($key));
33
34 $value = range(1, 5);
35 var_dump($yac->set($key, $value));
36 var_dump($yac->get($key));
37
38 $value = 9234324;
39 var_dump($yac->set($key, $value));
40 var_dump($yac->get($key));
41
42 $value = 9234324.123456;
43 var_dump($yac->set($key, $value));
44 var_dump($yac->get($key));
45
46 $value = new StdClass();;
47 var_dump($yac->set($key, $value));
48 var_dump($yac->get($key));
49
50 $value = fopen("php://input", "r");
51 var_dump($yac->set($key, $value));
52
53 $value = range(1, 5);
54 var_dump($yac->set($key, $value));
55 var_dump($yac->delete($key));
56 var_dump($yac->get($key));
57
58 ?>
59 --EXPECTF--
60 bool(true)
61 bool(true)
62 string(5) "dummy"
63 bool(true)
64 NULL
65 bool(true)
66 bool(true)
67 bool(true)
68 bool(false)
69 bool(true)
70 array(5) {
71 [0]=>
72 int(1)
73 [1]=>
74 int(2)
75 [2]=>
76 int(3)
77 [3]=>
78 int(4)
79 [4]=>
80 int(5)
81 }
82 bool(true)
83 int(9234324)
84 bool(true)
85 float(9234324.123456)
86 bool(true)
87 object(stdClass)#%d (0) {
88 }
89
90 Warning: Yac::set(): Type 'IS_RESOURCE' cannot be stored in %s019.php on line %d
91 bool(false)
92 bool(true)
93 bool(true)
94 bool(false)
0 --TEST--
1 Check for yac with igbinary serializer
2 --SKIPIF--
3 <?php if (!extension_loaded("yac")) print "skip"; ?>
4 <?php if (!defined("YAC_SERIALIZER_IGBINARY")) die ("skip need --enable-igbinary"); ?>
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.serializer=igbinary
11 --FILE--
12 <?php
13 $yac = new Yac();
14
15 var_dump(YAC_SERIALIZER == YAC_SERIALIZER_IGBINARY);
16 $key = "foo";
17 $value = "dummy";
18
19 var_dump($yac->set($key, $value));
20 var_dump($yac->get($key));
21
22 $value = NULL;
23 var_dump($yac->set($key, $value));
24 var_dump($yac->get($key));
25
26 $value = TRUE;
27 var_dump($yac->set($key, $value));
28 var_dump($yac->get($key));
29
30 $value = FALSE;
31 var_dump($yac->set($key, $value));
32 var_dump($yac->get($key));
33
34 $value = range(1, 5);
35 var_dump($yac->set($key, $value));
36 var_dump($yac->get($key));
37
38 $value = 9234324;
39 var_dump($yac->set($key, $value));
40 var_dump($yac->get($key));
41
42 $value = 9234324.123456;
43 var_dump($yac->set($key, $value));
44 var_dump($yac->get($key));
45
46 $value = new StdClass();;
47 var_dump($yac->set($key, $value));
48 var_dump($yac->get($key));
49
50 $value = fopen("php://input", "r");
51 var_dump($yac->set($key, $value));
52
53 $value = range(1, 5);
54 var_dump($yac->set($key, $value));
55 var_dump($yac->delete($key));
56 var_dump($yac->get($key));
57
58 ?>
59 --EXPECTF--
60 bool(true)
61 bool(true)
62 string(5) "dummy"
63 bool(true)
64 NULL
65 bool(true)
66 bool(true)
67 bool(true)
68 bool(false)
69 bool(true)
70 array(5) {
71 [0]=>
72 int(1)
73 [1]=>
74 int(2)
75 [2]=>
76 int(3)
77 [3]=>
78 int(4)
79 [4]=>
80 int(5)
81 }
82 bool(true)
83 int(9234324)
84 bool(true)
85 float(9234324.123456)
86 bool(true)
87 object(stdClass)#%d (0) {
88 }
89
90 Warning: Yac::set(): Type 'IS_RESOURCE' cannot be stored in %s020.php on line %d
91 bool(false)
92 bool(true)
93 bool(true)
94 bool(false)
0 --TEST--
1 Check for yac read/write/unset property
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("prefix");
12
13 $yac->value = "value";
14
15 /* can not used in writen context */
16 $yac->foo->bar = "bar";
17
18 var_dump($yac->get("value"));
19 var_dump($yac->value);
20
21 var_dump($yac->get("foo"));
22 var_dump($yac->foo);
23
24 unset($yac->value);
25 var_dump($yac->get("value"));
26 var_dump($yac->value);
27 ?>
28 --EXPECT--
29 string(5) "value"
30 string(5) "value"
31 bool(false)
32 NULL
33 bool(false)
34 NULL
0 --TEST--
1 Check for yac::__construct with yac.enable=0
2 --SKIPIF--
3 <?php if (!extension_loaded("yac")) print "skip"; ?>
4 --INI--
5 yac.enable=0
6 --FILE--
7 <?php
8 try {
9 $yac = new Yac("prefix");
10 } catch (Exception $e) {
11 var_dump($e->getMessage());
12 }
13
14 var_dump($yac);
15 ?>
16 --EXPECTF--
17 string(18) "Yac is not enabled"
18
19 Notice: Undefined variable: yac in %s022.php on line %d
20 NULL
0 --TEST--
1 Check for inherit from Yac
2 --SKIPIF--
3 <?php if (!extension_loaded("yac")) print "skip"; ?>
4 --INI--
5 yac.enable=0
6 --FILE--
7 <?php
8 class Sub extends Yac {};
9 ?>
10 --EXPECTF--
11 Fatal error: Class Sub may not inherit from final class (Yac) in %s023.php on line %d
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 "SAPI.h"
29 #include "ext/standard/info.h"
30 #include "Zend/zend_smart_str.h"
31 #include "Zend/zend_exceptions.h"
32
33 #include "php_yac.h"
34 #include "storage/yac_storage.h"
35 #include "serializer/yac_serializer.h"
36 #ifdef HAVE_FASTLZ_H
37 #include <fastlz.h>
38 #else
39 #include "compressor/fastlz/fastlz.h"
40 #endif
41
42 zend_class_entry *yac_class_ce;
43
44 static zend_object_handlers yac_obj_handlers;
45
46 typedef struct {
47 unsigned char prefix[YAC_STORAGE_MAX_KEY_LEN];
48 uint16_t prefix_len;
49 zend_object std;
50 } yac_object;
51
52 ZEND_DECLARE_MODULE_GLOBALS(yac);
53
54 static yac_serializer_t yac_serializer;
55 static yac_unserializer_t yac_unserializer;
56
57 /** {{{ ARG_INFO
58 */
59 ZEND_BEGIN_ARG_INFO_EX(arginfo_yac_constructor, 0, 0, 0)
60 ZEND_ARG_INFO(0, prefix)
61 ZEND_END_ARG_INFO()
62
63 ZEND_BEGIN_ARG_INFO_EX(arginfo_yac_add, 0, 0, 1)
64 ZEND_ARG_INFO(0, keys)
65 ZEND_ARG_INFO(0, value)
66 ZEND_ARG_INFO(0, ttl)
67 ZEND_END_ARG_INFO()
68
69 ZEND_BEGIN_ARG_INFO_EX(arginfo_yac_get, 0, 0, 1)
70 ZEND_ARG_INFO(0, keys)
71 ZEND_END_ARG_INFO()
72
73 ZEND_BEGIN_ARG_INFO_EX(arginfo_yac_delete, 0, 0, 1)
74 ZEND_ARG_INFO(0, keys)
75 ZEND_ARG_INFO(0, ttl)
76 ZEND_END_ARG_INFO()
77
78 ZEND_BEGIN_ARG_INFO_EX(arginfo_yac_void, 0, 0, 0)
79 ZEND_END_ARG_INFO()
80 /* }}} */
81
82 static PHP_INI_MH(OnChangeKeysMemoryLimit) /* {{{ */ {
83 if (new_value) {
84 YAC_G(k_msize) = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
85 }
86 return SUCCESS;
87 }
88 /* }}} */
89
90 static PHP_INI_MH(OnChangeValsMemoryLimit) /* {{{ */ {
91 if (new_value) {
92 YAC_G(v_msize) = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
93 }
94 return SUCCESS;
95 }
96 /* }}} */
97
98 static PHP_INI_MH(OnChangeCompressThreshold) /* {{{ */ {
99 if (new_value) {
100 YAC_G(compress_threshold) = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
101 if (YAC_G(compress_threshold) < YAC_MIN_COMPRESS_THRESHOLD) {
102 YAC_G(compress_threshold) = YAC_MIN_COMPRESS_THRESHOLD;
103 }
104 }
105 return SUCCESS;
106 }
107 /* }}} */
108
109 /* {{{ PHP_INI
110 */
111 PHP_INI_BEGIN()
112 STD_PHP_INI_BOOLEAN("yac.enable", "1", PHP_INI_SYSTEM, OnUpdateBool, enable, zend_yac_globals, yac_globals)
113 STD_PHP_INI_BOOLEAN("yac.debug", "0", PHP_INI_ALL, OnUpdateBool, debug, zend_yac_globals, yac_globals)
114 STD_PHP_INI_ENTRY("yac.keys_memory_size", "4M", PHP_INI_SYSTEM, OnChangeKeysMemoryLimit, k_msize, zend_yac_globals, yac_globals)
115 STD_PHP_INI_ENTRY("yac.values_memory_size", "64M", PHP_INI_SYSTEM, OnChangeValsMemoryLimit, v_msize, zend_yac_globals, yac_globals)
116 STD_PHP_INI_ENTRY("yac.compress_threshold", "-1", PHP_INI_SYSTEM, OnChangeCompressThreshold, compress_threshold, zend_yac_globals, yac_globals)
117 STD_PHP_INI_ENTRY("yac.enable_cli", "0", PHP_INI_SYSTEM, OnUpdateBool, enable_cli, zend_yac_globals, yac_globals)
118 STD_PHP_INI_ENTRY("yac.serializer", "php", PHP_INI_SYSTEM, OnUpdateString, serializer, zend_yac_globals, yac_globals)
119 PHP_INI_END()
120 /* }}} */
121
122 #define Z_YACOBJ_P(zv) (php_yac_fetch_object(Z_OBJ_P(zv)))
123 static inline yac_object *php_yac_fetch_object(zend_object *obj) /* {{{ */ {
124 return (yac_object *)((char*)(obj) - XtOffsetOf(yac_object, std));
125 }
126 /* }}} */
127
128 static const char *yac_assemble_key(yac_object *yac, zend_string *name, size_t *len) /* {{{ */ {
129 const char *key;
130
131 if ((ZSTR_LEN(name) + yac->prefix_len) > YAC_STORAGE_MAX_KEY_LEN) {
132 php_error_docref(NULL, E_WARNING,
133 "Key '%.*s%s' exceed max key length '%d' bytes",
134 yac->prefix_len, yac->prefix, ZSTR_VAL(name), YAC_STORAGE_MAX_KEY_LEN);
135 return NULL;
136 }
137
138 if (yac->prefix_len) {
139 memcpy(yac->prefix + yac->prefix_len, ZSTR_VAL(name), ZSTR_LEN(name));
140 key = (const char*)yac->prefix;
141 *len = yac->prefix_len + ZSTR_LEN(name);
142 } else {
143 key = ZSTR_VAL(name);
144 *len = ZSTR_LEN(name);
145 }
146
147 return key;
148 }
149 /* }}} */
150
151 static int yac_add_impl(yac_object *yac, zend_string *name, zval *value, int ttl, int add) /* {{{ */ {
152 int ret = 0, flag = Z_TYPE_P(value);
153 char *msg;
154 time_t tv;
155 const char *key;
156 size_t key_len;
157
158 if ((key = yac_assemble_key(yac, name, &key_len)) == NULL) {
159 return ret;
160 }
161
162 tv = time(NULL);
163 switch (Z_TYPE_P(value)) {
164 case IS_NULL:
165 case IS_TRUE:
166 case IS_FALSE:
167 ret = yac_storage_update(key, key_len, (char *)&flag, sizeof(int), flag, ttl, add, tv);
168 break;
169 case IS_LONG:
170 ret = yac_storage_update(key, key_len, (char *)&Z_LVAL_P(value), sizeof(long), flag, ttl, add, tv);
171 break;
172 case IS_DOUBLE:
173 ret = yac_storage_update(key, key_len, (char *)&Z_DVAL_P(value), sizeof(double), flag, ttl, add, tv);
174 break;
175 case IS_STRING:
176 #ifdef IS_CONSTANT
177 case IS_CONSTANT:
178 #endif
179 {
180 if (Z_STRLEN_P(value) > YAC_G(compress_threshold) || Z_STRLEN_P(value) > YAC_STORAGE_MAX_ENTRY_LEN) {
181 int compressed_len;
182 char *compressed;
183
184 /* if longer than this, then we can not stored the length in flag */
185 if (Z_STRLEN_P(value) > YAC_ENTRY_MAX_ORIG_LEN) {
186 php_error_docref(NULL, E_WARNING, "Value is too long(%ld bytes) to be stored", Z_STRLEN_P(value));
187 return ret;
188 }
189
190 compressed = emalloc(Z_STRLEN_P(value) * 1.05);
191 compressed_len = fastlz_compress(Z_STRVAL_P(value), Z_STRLEN_P(value), compressed);
192 if (!compressed_len || compressed_len > Z_STRLEN_P(value)) {
193 php_error_docref(NULL, E_WARNING, "Compression failed");
194 efree(compressed);
195 return ret;
196 }
197
198 if (compressed_len > YAC_STORAGE_MAX_ENTRY_LEN) {
199 php_error_docref(NULL, E_WARNING, "Value is too long(%ld bytes) to be stored", Z_STRLEN_P(value));
200 efree(compressed);
201 return ret;
202 }
203
204 flag |= YAC_ENTRY_COMPRESSED;
205 flag |= (Z_STRLEN_P(value) << YAC_ENTRY_ORIG_LEN_SHIT);
206 ret = yac_storage_update(key, key_len, compressed, compressed_len, flag, ttl, add, tv);
207 efree(compressed);
208 } else {
209 ret = yac_storage_update(key, key_len, Z_STRVAL_P(value), Z_STRLEN_P(value), flag, ttl, add, tv);
210 }
211 }
212 break;
213 case IS_ARRAY:
214 #ifdef IS_CONSTANT_ARRAY
215 case IS_CONSTANT_ARRAY:
216 #endif
217 case IS_OBJECT:
218 {
219 smart_str buf = {0};
220
221 if (yac_serializer(value, &buf, &msg)) {
222 if (buf.s->len > YAC_G(compress_threshold) || buf.s->len > YAC_STORAGE_MAX_ENTRY_LEN) {
223 int compressed_len;
224 char *compressed;
225
226 if (buf.s->len > YAC_ENTRY_MAX_ORIG_LEN) {
227 php_error_docref(NULL, E_WARNING, "Value is too big to be stored");
228 return ret;
229 }
230
231 compressed = emalloc(buf.s->len * 1.05);
232 compressed_len = fastlz_compress(ZSTR_VAL(buf.s), ZSTR_LEN(buf.s), compressed);
233 if (!compressed_len || compressed_len > buf.s->len) {
234 php_error_docref(NULL, E_WARNING, "Compression failed");
235 efree(compressed);
236 return ret;
237 }
238
239 if (compressed_len > YAC_STORAGE_MAX_ENTRY_LEN) {
240 php_error_docref(NULL, E_WARNING, "Value is too big to be stored");
241 efree(compressed);
242 return ret;
243 }
244
245 flag |= YAC_ENTRY_COMPRESSED;
246 flag |= (buf.s->len << YAC_ENTRY_ORIG_LEN_SHIT);
247 ret = yac_storage_update(key, key_len, compressed, compressed_len, flag, ttl, add, tv);
248 efree(compressed);
249 } else {
250 ret = yac_storage_update(key, key_len, ZSTR_VAL(buf.s), ZSTR_LEN(buf.s), flag, ttl, add, tv);
251 }
252 smart_str_free(&buf);
253 } else {
254 php_error_docref(NULL, E_WARNING, "Serialization failed");
255 smart_str_free(&buf);
256 }
257 }
258 break;
259 case IS_RESOURCE:
260 php_error_docref(NULL, E_WARNING, "Type 'IS_RESOURCE' cannot be stored");
261 break;
262 default:
263 php_error_docref(NULL, E_WARNING, "Unsupported valued type to be stored '%d'", flag);
264 break;
265 }
266
267 return ret;
268 }
269 /* }}} */
270
271 static int yac_add_multi_impl(yac_object *yac, zval *kvs, int ttl, int add) /* {{{ */ {
272 HashTable *ht = Z_ARRVAL_P(kvs);
273 zend_string *key;
274 zend_ulong idx;
275 zval *value;
276
277 ZEND_HASH_FOREACH_KEY_VAL(ht, idx, key, value) {
278 uint32_t should_free = 0;
279 if (!key) {
280 key = strpprintf(0, "%lu", idx);
281 should_free = 1;
282 }
283 if (yac_add_impl(yac, key, value, ttl, add)) {
284 if (should_free) {
285 zend_string_release(key);
286 }
287 continue;
288 } else {
289 if (should_free) {
290 zend_string_release(key);
291 }
292 return 0;
293 }
294 } ZEND_HASH_FOREACH_END();
295
296 return 1;
297 }
298 /* }}} */
299
300 static zval* yac_get_impl(yac_object *yac, zend_string *name, uint32_t *cas, zval *rv) /* {{{ */ {
301 uint32_t flag, size = 0;
302 char *data, *msg;
303 time_t tv;
304 const char *key;
305 size_t key_len;
306
307 if ((key = yac_assemble_key(yac, name, &key_len)) == NULL) {
308 return NULL;
309 }
310
311 tv = time(NULL);
312 if (yac_storage_find(key, key_len, &data, &size, &flag, (int *)cas, tv)) {
313 switch ((flag & YAC_ENTRY_TYPE_MASK)) {
314 case IS_NULL:
315 if (size == sizeof(int)) {
316 ZVAL_NULL(rv);
317 }
318 efree(data);
319 break;
320 case IS_TRUE:
321 if (size == sizeof(int)) {
322 ZVAL_TRUE(rv);
323 }
324 efree(data);
325 break;
326 case IS_FALSE:
327 if (size == sizeof(int)) {
328 ZVAL_FALSE(rv);
329 }
330 efree(data);
331 break;
332 case IS_LONG:
333 if (size == sizeof(long)) {
334 ZVAL_LONG(rv, *(long*)data);
335 }
336 efree(data);
337 break;
338 case IS_DOUBLE:
339 if (size == sizeof(double)) {
340 ZVAL_DOUBLE(rv, *(double*)data);
341 }
342 efree(data);
343 break;
344 case IS_STRING:
345 #ifdef IS_CONSTANT
346 case IS_CONSTANT:
347 #endif
348 {
349 if ((flag & YAC_ENTRY_COMPRESSED)) {
350 size_t orig_len = ((uint32_t)flag >> YAC_ENTRY_ORIG_LEN_SHIT);
351 char *origin = emalloc(orig_len + 1);
352 uint32_t length;
353 length = fastlz_decompress(data, size, origin, orig_len);
354 if (!length) {
355 php_error_docref(NULL, E_WARNING, "Decompression failed");
356 efree(data);
357 efree(origin);
358 return NULL;
359 }
360 ZVAL_STRINGL(rv, origin, length);
361 efree(origin);
362 efree(data);
363 } else {
364 ZVAL_STRINGL(rv, data, size);
365 efree(data);
366 }
367 }
368 break;
369 case IS_ARRAY:
370 #ifdef IS_CONSTANT_ARRAY
371 case IS_CONSTANT_ARRAY:
372 #endif
373 case IS_OBJECT:
374 {
375 if ((flag & YAC_ENTRY_COMPRESSED)) {
376 size_t length, orig_len = ((uint32_t)flag >> YAC_ENTRY_ORIG_LEN_SHIT);
377 char *origin = emalloc(orig_len + 1);
378 length = fastlz_decompress(data, size, origin, orig_len);
379 if (!length) {
380 php_error_docref(NULL, E_WARNING, "Decompression failed");
381 efree(data);
382 efree(origin);
383 return NULL;
384 }
385 efree(data);
386 data = origin;
387 size = length;
388 }
389 rv = yac_unserializer(data, size, &msg, rv);
390 efree(data);
391 }
392 break;
393 default:
394 php_error_docref(NULL, E_WARNING, "Unexpected valued type '%d'", flag);
395 rv = NULL;
396 break;
397 }
398 } else {
399 rv = NULL;
400 }
401
402 return rv;
403 }
404 /* }}} */
405
406 static zval* yac_get_multi_impl(yac_object *yac, zval *keys, zval *cas, zval *rv) /* {{{ */ {
407 zval *value;
408 HashTable *ht = Z_ARRVAL_P(keys);
409
410 array_init(rv);
411
412 ZEND_HASH_FOREACH_VAL(ht, value) {
413 uint32_t lcas = 0;
414 zval *v, tmp;
415
416 switch (Z_TYPE_P(value)) {
417 case IS_STRING:
418 if ((v = yac_get_impl(yac, Z_STR_P(value), &lcas, &tmp))) {
419 zend_symtable_update(Z_ARRVAL_P(rv), Z_STR_P(value), v);
420 } else {
421 ZVAL_FALSE(&tmp);
422 zend_symtable_update(Z_ARRVAL_P(rv), Z_STR_P(value), &tmp);
423 }
424 continue;
425 default:
426 {
427 zend_string *key = zval_get_string(value);
428 if ((v = yac_get_impl(yac, key, &lcas, &tmp))) {
429 zend_symtable_update(Z_ARRVAL_P(rv), key, v);
430 } else {
431 ZVAL_FALSE(&tmp);
432 zend_symtable_update(Z_ARRVAL_P(rv), key, &tmp);
433 }
434 zend_string_release(key);
435 }
436 continue;
437 }
438 } ZEND_HASH_FOREACH_END();
439
440 return rv;
441 }
442 /* }}} */
443
444 static int yac_delete_impl(yac_object *yac, zend_string *name, int ttl) /* {{{ */ {
445 time_t tv = 0;
446 const char *key;
447 size_t key_len;
448
449 if ((key = yac_assemble_key(yac, name, &key_len)) == NULL) {
450 return 0;
451 }
452
453 if (ttl) {
454 tv = (zend_ulong)time(NULL);
455 }
456
457 return yac_storage_delete(key, key_len, ttl, tv);
458 }
459 /* }}} */
460
461 static int yac_delete_multi_impl(yac_object *yac, zval *keys, int ttl) /* {{{ */ {
462 HashTable *ht = Z_ARRVAL_P(keys);
463 int ret = 1;
464 zval *value;
465
466 ZEND_HASH_FOREACH_VAL(ht, value) {
467 switch (Z_TYPE_P(value)) {
468 case IS_STRING:
469 ret = ret & yac_delete_impl(yac, Z_STR_P(value), ttl);
470 continue;
471 default:
472 {
473 zend_string *key = zval_get_string(value);
474 ret = ret & yac_delete_impl(yac, key, ttl);
475 zend_string_release(key);
476 }
477 continue;
478 }
479 } ZEND_HASH_FOREACH_END();
480
481 return ret;
482 }
483 /* }}} */
484
485 static zend_object *yac_object_new(zend_class_entry *ce) /* {{{ */ {
486 yac_object *yac = emalloc(sizeof(yac_object) + zend_object_properties_size(ce));
487
488 if (!YAC_G(enable)) {
489 zend_throw_exception(NULL, "Yac is not enabled", 0);
490 }
491
492 zend_object_std_init(&yac->std, ce);
493 yac->std.handlers = &yac_obj_handlers;
494 yac->prefix_len = 0;
495
496
497 return &yac->std;
498 }
499 /* }}} */
500
501 static void yac_object_free(zend_object *object) /* {{{ */ {
502 zend_object_std_dtor(object);
503 }
504 /* }}} */
505
506 static zval* yac_read_property_ptr(zval *zobj, zval *name, int type, void **cache_slot) /* {{{ */ {
507 return &EG(error_zval);
508 }
509 /* }}} */
510
511 static zval* yac_read_property(zval *zobj, zval *name, int type, void **cache_slot, zval *rv) /* {{{ */ {
512 if (UNEXPECTED(type == BP_VAR_RW||type == BP_VAR_W)) {
513 return &EG(error_zval);
514 }
515
516 if (yac_get_impl(Z_YACOBJ_P(zobj), Z_STR_P(name), NULL, rv)) {
517 return rv;
518 }
519
520 return &EG(uninitialized_zval);
521 }
522 /* }}} */
523
524 static YAC_WHANDLER yac_write_property(zval *zobj, zval *name, zval *value, void **cache_slot) /* {{{ */ {
525 yac_add_impl(Z_YACOBJ_P(zobj), Z_STR_P(name), value, 0, 0);
526 Z_TRY_ADDREF_P(value);
527
528 YAC_WHANDLER_RET(value);
529 }
530 /* }}} */
531
532 static void yac_unset_property(zval *zobj, zval *name, void **cache_slot) /* {{{ */ {
533 yac_delete_impl(Z_YACOBJ_P(zobj), Z_STR_P(name), 0);
534 }
535 /* }}} */
536
537 /** {{{ proto public Yac::__construct([string $prefix])
538 */
539 PHP_METHOD(yac, __construct) {
540 zend_string *prefix = NULL;
541
542 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S", &prefix) == FAILURE) {
543 return;
544 }
545
546 if (prefix && ZSTR_LEN(prefix)) {
547 yac_object *yac;
548 if (ZSTR_LEN(prefix) > YAC_STORAGE_MAX_KEY_LEN) {
549 zend_throw_exception_ex(NULL, 0,
550 "Prefix '%s' exceed max key length '%d' bytes", ZSTR_VAL(prefix), YAC_STORAGE_MAX_KEY_LEN);
551 return;
552 }
553 yac = Z_YACOBJ_P(getThis());
554 yac->prefix_len = ZSTR_LEN(prefix);
555 memcpy(yac->prefix, ZSTR_VAL(prefix), ZSTR_LEN(prefix));
556 }
557 }
558 /* }}} */
559
560 /** {{{ proto public Yac::add(mixed $keys, mixed $value[, int $ttl])
561 */
562 PHP_METHOD(yac, add) {
563 zend_long ttl = 0;
564 zval *keys, *value = NULL;
565 int ret;
566
567 switch (ZEND_NUM_ARGS()) {
568 case 1:
569 if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &keys) == FAILURE) {
570 return;
571 }
572 break;
573 case 2:
574 if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &keys, &value) == FAILURE) {
575 return;
576 }
577 if (Z_TYPE_P(keys) == IS_ARRAY) {
578 if (Z_TYPE_P(value) == IS_LONG) {
579 ttl = Z_LVAL_P(value);
580 value = NULL;
581 } else {
582 php_error_docref(NULL, E_WARNING, "ttl parameter must be an integer");
583 return;
584 }
585 }
586 break;
587 case 3:
588 if (zend_parse_parameters(ZEND_NUM_ARGS(), "zzl", &keys, &value, &ttl) == FAILURE) {
589 return;
590 }
591 break;
592 default:
593 WRONG_PARAM_COUNT;
594 }
595
596 if (Z_TYPE_P(keys) == IS_ARRAY) {
597 ret = yac_add_multi_impl(Z_YACOBJ_P(getThis()), keys, ttl, 1);
598 } else if (Z_TYPE_P(keys) == IS_STRING) {
599 ret = yac_add_impl(Z_YACOBJ_P(getThis()), Z_STR_P(keys), value, ttl, 1);
600 } else {
601 zend_string *key = zval_get_string(keys);
602 ret = yac_add_impl(Z_YACOBJ_P(getThis()), key, value, ttl, 1);
603 zend_string_release(key);
604 }
605
606 RETURN_BOOL(ret);
607 }
608 /* }}} */
609
610 /** {{{ proto public Yac::set(mixed $keys, mixed $value[, int $ttl])
611 */
612 PHP_METHOD(yac, set) {
613 zend_long ttl = 0;
614 zval *keys, *value = NULL;
615 int ret;
616
617 switch (ZEND_NUM_ARGS()) {
618 case 1:
619 if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &keys) == FAILURE) {
620 return;
621 }
622 break;
623 case 2:
624 if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &keys, &value) == FAILURE) {
625 return;
626 }
627 if (Z_TYPE_P(keys) == IS_ARRAY) {
628 if (Z_TYPE_P(value) == IS_LONG) {
629 ttl = Z_LVAL_P(value);
630 value = NULL;
631 } else {
632 php_error_docref(NULL, E_WARNING, "ttl parameter must be an integer");
633 return;
634 }
635 }
636 break;
637 case 3:
638 if (zend_parse_parameters(ZEND_NUM_ARGS(), "zzl", &keys, &value, &ttl) == FAILURE) {
639 return;
640 }
641 break;
642 default:
643 WRONG_PARAM_COUNT;
644 }
645
646 if (Z_TYPE_P(keys) == IS_ARRAY) {
647 ret = yac_add_multi_impl(Z_YACOBJ_P(getThis()), keys, ttl, 0);
648 } else if (Z_TYPE_P(keys) == IS_STRING) {
649 ret = yac_add_impl(Z_YACOBJ_P(getThis()), Z_STR_P(keys), value, ttl, 0);
650 } else {
651 zend_string *key = zval_get_string(keys);
652 ret = yac_add_impl(Z_YACOBJ_P(getThis()), key, value, ttl, 0);
653 zend_string_release(key);
654 }
655
656 RETURN_BOOL(ret);
657 }
658 /* }}} */
659
660 /** {{{ proto public Yac::get(mixed $keys[, int &$cas])
661 */
662 PHP_METHOD(yac, get) {
663 uint32_t lcas = 0;
664 zval *ret, *keys, *cas = NULL;
665
666 if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|z", &keys, &cas) == FAILURE) {
667 return;
668 }
669
670 if (Z_TYPE_P(keys) == IS_ARRAY) {
671 ret = yac_get_multi_impl(Z_YACOBJ_P(getThis()), keys, cas, return_value);
672 } else if (Z_TYPE_P(keys) == IS_STRING) {
673 ret = yac_get_impl(Z_YACOBJ_P(getThis()), Z_STR_P(keys), &lcas, return_value);
674 } else {
675 zend_string *key = zval_get_string(keys);
676 ret = yac_get_impl(Z_YACOBJ_P(getThis()), key, &lcas, return_value);
677 zend_string_release(key);
678 }
679
680 if (ret == NULL) {
681 RETURN_FALSE;
682 }
683 }
684 /* }}} */
685
686 /** {{{ proto public Yac::delete(mixed $key[, int $delay = 0])
687 */
688 PHP_METHOD(yac, delete) {
689 zend_long time = 0;
690 zval *keys;
691 int ret;
692
693 if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|l", &keys, &time) == FAILURE) {
694 return;
695 }
696
697 if (Z_TYPE_P(keys) == IS_ARRAY) {
698 ret = yac_delete_multi_impl(Z_YACOBJ_P(getThis()), keys, time);
699 } else if (Z_TYPE_P(keys) == IS_STRING) {
700 ret = yac_delete_impl(Z_YACOBJ_P(getThis()), Z_STR_P(keys), time);
701 } else {
702 zend_string *key = zval_get_string(keys);
703 ret = yac_delete_impl(Z_YACOBJ_P(getThis()), key, time);
704 zend_string_release(key);
705 }
706
707 RETURN_BOOL(ret);
708 }
709 /* }}} */
710
711 /** {{{ proto public Yac::flush(void)
712 */
713 PHP_METHOD(yac, flush) {
714
715 yac_storage_flush();
716
717 RETURN_TRUE;
718 }
719 /* }}} */
720
721 /** {{{ proto public Yac::info(void)
722 */
723 PHP_METHOD(yac, info) {
724 yac_storage_info *inf;
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 return;
745 }
746 /* }}} */
747
748 /** {{{ proto public Yac::dump(int $limit)
749 */
750 PHP_METHOD(yac, dump) {
751 long limit = 100;
752 yac_item_list *list, *l;
753
754 array_init(return_value);
755
756 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &limit) == FAILURE) {
757 return;
758 }
759
760 list = l = yac_storage_dump(limit);
761 for (; l; l = l->next) {
762 zval item;
763 array_init(&item);
764 add_assoc_long(&item, "index", l->index);
765 add_assoc_long(&item, "hash", l->h);
766 add_assoc_long(&item, "crc", l->crc);
767 add_assoc_long(&item, "ttl", l->ttl);
768 add_assoc_long(&item, "k_len", l->k_len);
769 add_assoc_long(&item, "v_len", l->v_len);
770 add_assoc_long(&item, "size", l->size);
771 add_assoc_string(&item, "key", (char*)l->key);
772 add_next_index_zval(return_value, &item);
773 }
774
775 yac_storage_free_list(list);
776 return;
777 }
778 /* }}} */
779
780 #if 0
781 only OO-style APIs is supported now
782 /* {{{{ proto bool yac_add(mixed $keys, mixed $value[, int $ttl])
783 */
784 PHP_FUNCTION(yac_add)
785 {
786 PHP_MN(yac_add)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
787 }
788 /* }}} */
789
790 /* {{{ proto bool yac_set(mixed $keys, mixed $value[, int $ttl])
791 */
792 PHP_FUNCTION(yac_set)
793 {
794 PHP_MN(yac_set)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
795 }
796 /* }}} */
797
798 /* {{{ proto bool yac_get(mixed $keys[, int &$cas])
799 */
800 PHP_FUNCTION(yac_get)
801 {
802 PHP_MN(yac_get)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
803 }
804 /* }}} */
805
806 /* {{{ proto bool yac_delete(mixed $keys[, int $delay = 0])
807 */
808 PHP_FUNCTION(yac_delete)
809 {
810 PHP_MN(yac_delete)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
811 }
812 /* }}} */
813
814 /* {{{ proto bool yac_flush(void)
815 */
816 PHP_FUNCTION(yac_flush)
817 {
818 PHP_MN(yac_flush)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
819 }
820 /* }}} */
821
822 /* {{{ proto bool yac_info(void)
823 */
824 PHP_FUNCTION(yac_info)
825 {
826 PHP_MN(yac_info)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
827 }
828 /* }}} */
829
830 /* {{{ yac_functions[] */
831 zend_function_entry yac_functions[] = {
832 PHP_FE(yac_add, arginfo_yac_add)
833 PHP_FE(yac_set, arginfo_yac_add)
834 PHP_FE(yac_get, arginfo_yac_get)
835 PHP_FE(yac_delete, arginfo_yac_delete)
836 PHP_FE(yac_flush, arginfo_yac_void)
837 PHP_FE(yac_info, arginfo_yac_void)
838 {NULL, NULL}
839 };
840 /* }}} */
841 #endif
842
843 /** {{{ yac_methods
844 */
845 zend_function_entry yac_methods[] = {
846 PHP_ME(yac, __construct, arginfo_yac_constructor, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
847 PHP_ME(yac, add, arginfo_yac_add, ZEND_ACC_PUBLIC)
848 PHP_ME(yac, set, arginfo_yac_add, ZEND_ACC_PUBLIC)
849 PHP_ME(yac, get, arginfo_yac_get, ZEND_ACC_PUBLIC)
850 PHP_ME(yac, delete, arginfo_yac_delete, ZEND_ACC_PUBLIC)
851 PHP_ME(yac, flush, arginfo_yac_void, ZEND_ACC_PUBLIC)
852 PHP_ME(yac, info, arginfo_yac_void, ZEND_ACC_PUBLIC)
853 PHP_ME(yac, dump, arginfo_yac_void, ZEND_ACC_PUBLIC)
854 {NULL, NULL, NULL}
855 };
856 /* }}} */
857
858 /* {{{ PHP_GINIT_FUNCTION
859 */
860 PHP_GINIT_FUNCTION(yac)
861 {
862 yac_globals->enable = 1;
863 yac_globals->k_msize = (4 * 1024 * 1024);
864 yac_globals->v_msize = (64 * 1024 * 1024);
865 yac_globals->debug = 0;
866 yac_globals->compress_threshold = -1;
867 yac_globals->enable_cli = 0;
868 #ifdef PHP_WIN32
869 yac_globals->mmap_base = NULL;
870 #endif
871 }
872 /* }}} */
873
874 /* {{{ PHP_MINIT_FUNCTION
875 */
876 PHP_MINIT_FUNCTION(yac)
877 {
878 char *msg;
879 zend_class_entry ce;
880
881 REGISTER_INI_ENTRIES();
882
883 if (!YAC_G(enable_cli) && !strcmp(sapi_module.name, "cli")) {
884 YAC_G(enable) = 0;
885 }
886
887 if (YAC_G(enable)) {
888 if (!yac_storage_startup(YAC_G(k_msize), YAC_G(v_msize), &msg)) {
889 php_error(E_ERROR, "Shared memory allocator startup failed at '%s': %s", msg, strerror(errno));
890 return FAILURE;
891 }
892 }
893
894 REGISTER_STRINGL_CONSTANT("YAC_VERSION", PHP_YAC_VERSION, sizeof(PHP_YAC_VERSION) - 1, CONST_PERSISTENT | CONST_CS);
895 REGISTER_LONG_CONSTANT("YAC_MAX_KEY_LEN", YAC_STORAGE_MAX_KEY_LEN, CONST_PERSISTENT | CONST_CS);
896 REGISTER_LONG_CONSTANT("YAC_MAX_VALUE_RAW_LEN", YAC_ENTRY_MAX_ORIG_LEN, CONST_PERSISTENT | CONST_CS);
897 REGISTER_LONG_CONSTANT("YAC_MAX_RAW_COMPRESSED_LEN", YAC_STORAGE_MAX_ENTRY_LEN, CONST_PERSISTENT | CONST_CS);
898 REGISTER_LONG_CONSTANT("YAC_SERIALIZER_PHP", YAC_SERIALIZER_PHP, CONST_PERSISTENT | CONST_CS);
899 #if YAC_ENABLE_MSGPACK
900 REGISTER_LONG_CONSTANT("YAC_SERIALIZER_MSGPACK", YAC_SERIALIZER_MSGPACK, CONST_PERSISTENT | CONST_CS);
901 #endif
902 #if YAC_ENABLE_IGBINARY
903 REGISTER_LONG_CONSTANT("YAC_SERIALIZER_IGBINARY", YAC_SERIALIZER_IGBINARY, CONST_PERSISTENT | CONST_CS);
904 #endif
905 #if YAC_ENABLE_JSON
906 REGISTER_LONG_CONSTANT("YAC_SERIALIZER_JSON", YAC_SERIALIZER_JSON, CONST_PERSISTENT | CONST_CS);
907 #endif
908
909 #if YAC_ENABLE_MSGPACK
910 if (strcmp(YAC_G(serializer), "msgpack") == 0) {
911 yac_serializer = yac_serializer_msgpack_pack;
912 yac_unserializer = yac_serializer_msgpack_unpack;
913 REGISTER_LONG_CONSTANT("YAC_SERIALIZER", YAC_SERIALIZER_MSGPACK, CONST_PERSISTENT | CONST_CS);
914 } else
915 #endif
916 #if YAC_ENABLE_IGBINARY
917 if (strcmp(YAC_G(serializer), "igbinary") == 0) {
918 yac_serializer = yac_serializer_igbinary_pack;
919 yac_unserializer = yac_serializer_igbinary_unpack;
920 REGISTER_LONG_CONSTANT("YAC_SERIALIZER", YAC_SERIALIZER_IGBINARY, CONST_PERSISTENT | CONST_CS);
921 } else
922 #endif
923 #if YAC_ENABLE_JSON
924 if (strcmp(YAC_G(serializer), "json") == 0) {
925 yac_serializer = yac_serializer_json_pack;
926 yac_unserializer = yac_serializer_json_unpack;
927 REGISTER_LONG_CONSTANT("YAC_SERIALIZER", YAC_SERIALIZER_JSON, CONST_PERSISTENT | CONST_CS);
928 } else
929 #endif
930 {
931 yac_serializer = yac_serializer_php_pack;
932 yac_unserializer = yac_serializer_php_unpack;
933 REGISTER_LONG_CONSTANT("YAC_SERIALIZER", YAC_SERIALIZER_PHP, CONST_PERSISTENT | CONST_CS);
934 }
935
936 INIT_CLASS_ENTRY(ce, "Yac", yac_methods);
937 yac_class_ce = zend_register_internal_class(&ce);
938 yac_class_ce->ce_flags |= ZEND_ACC_FINAL;
939 yac_class_ce->create_object = yac_object_new;
940
941 memcpy(&yac_obj_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
942 yac_obj_handlers.offset = XtOffsetOf(yac_object, std);
943 yac_obj_handlers.free_obj = yac_object_free;
944 if (YAC_G(enable)) {
945 yac_obj_handlers.read_property = yac_read_property;
946 yac_obj_handlers.write_property = yac_write_property;
947 yac_obj_handlers.unset_property = yac_unset_property;
948 yac_obj_handlers.get_property_ptr_ptr = yac_read_property_ptr;
949 }
950
951 return SUCCESS;
952 }
953 /* }}} */
954
955 /* {{{ PHP_MSHUTDOWN_FUNCTION
956 */
957 PHP_MSHUTDOWN_FUNCTION(yac)
958 {
959 UNREGISTER_INI_ENTRIES();
960 if (YAC_G(enable)) {
961 yac_storage_shutdown();
962 }
963 return SUCCESS;
964 }
965 /* }}} */
966
967 /* {{{ PHP_MINFO_FUNCTION
968 */
969 PHP_MINFO_FUNCTION(yac)
970 {
971 smart_str names = {0,};
972
973 php_info_print_table_start();
974 php_info_print_table_header(2, "yac support", "enabled");
975 php_info_print_table_row(2, "Version", PHP_YAC_VERSION);
976 php_info_print_table_row(2, "Shared Memory", yac_storage_shared_memory_name());
977
978 smart_str_appends(&names, "php");
979 #if YAC_ENABLE_MSGPACK
980 smart_str_appends(&names, ", msgpack");
981 #endif
982 #if YAC_ENABLE_IGBINARY
983 smart_str_appends(&names, ", igbinary");
984 #endif
985 #if YAC_ENABLE_JSON
986 smart_str_appends(&names, ", json");
987 #endif
988 php_info_print_table_row(2, "Serializer", ZSTR_VAL(names.s));
989 smart_str_free(&names);
990
991 php_info_print_table_end();
992
993 DISPLAY_INI_ENTRIES();
994
995 if (YAC_G(enable)) {
996 char buf[64];
997 yac_storage_info *inf;
998 inf = yac_storage_get_info();
999
1000 php_info_print_table_start();
1001 php_info_print_table_colspan_header(2, "Cache info");
1002 snprintf(buf, sizeof(buf), "%ld", inf->k_msize + inf->v_msize);
1003 php_info_print_table_row(2, "Total Shared Memory Usage(memory_size)", buf);
1004 snprintf(buf, sizeof(buf), "%ld", inf->k_msize);
1005 php_info_print_table_row(2, "Total Shared Memory Usage for keys(keys_memory_size)", buf);
1006 snprintf(buf, sizeof(buf), "%ld", inf->v_msize);
1007 php_info_print_table_row(2, "Total Shared Memory Usage for values(values_memory_size)", buf);
1008 snprintf(buf, sizeof(buf), "%d", inf->segment_size);
1009 php_info_print_table_row(2, "Size of Shared Memory Segment(segment_size)", buf);
1010 snprintf(buf, sizeof(buf), "%d", inf->segments_num);
1011 php_info_print_table_row(2, "Number of Segments (segment_num)", buf);
1012 snprintf(buf, sizeof(buf), "%d", inf->slots_size);
1013 php_info_print_table_row(2, "Total Slots Number(slots_size)", buf);
1014 snprintf(buf, sizeof(buf), "%d", inf->slots_num);
1015 php_info_print_table_row(2, "Total Used Slots(slots_num)", buf);
1016 php_info_print_table_end();
1017
1018 yac_storage_free_info(inf);
1019 }
1020 }
1021 /* }}} */
1022
1023 #ifdef COMPILE_DL_YAC
1024 ZEND_GET_MODULE(yac)
1025 #endif
1026
1027 static zend_module_dep yac_module_deps[] = {
1028 #if YAC_ENABLE_MSGPACK
1029 ZEND_MOD_REQUIRED("msgpack")
1030 #endif
1031 #if YAC_ENABLE_IGBINARY
1032 ZEND_MOD_REQUIRED("igbinary")
1033 #endif
1034 #if YAC_ENABLE_JSON
1035 ZEND_MOD_REQUIRED("json")
1036 #endif
1037 {NULL, NULL, NULL, 0}
1038 };
1039
1040 /* {{{ yac_module_entry
1041 */
1042 zend_module_entry yac_module_entry = {
1043 STANDARD_MODULE_HEADER_EX,
1044 NULL,
1045 yac_module_deps,
1046 "yac",
1047 NULL, /* yac_functions, */
1048 PHP_MINIT(yac),
1049 PHP_MSHUTDOWN(yac),
1050 NULL,
1051 NULL,
1052 PHP_MINFO(yac),
1053 PHP_YAC_VERSION,
1054 PHP_MODULE_GLOBALS(yac),
1055 PHP_GINIT(yac),
1056 NULL,
1057 NULL,
1058 STANDARD_MODULE_PROPERTIES_EX
1059 };
1060 /* }}} */
1061
1062 /*
1063 * Local variables:
1064 * tab-width: 4
1065 * c-basic-offset: 4
1066 * End:
1067 * vim600: noet sw=4 ts=4 fdm=marker
1068 * vim<600: noet sw=4 ts=4
1069 */
1070