mirror of
https://github.com/syncthing/syncthing.git
synced 2025-12-24 06:28:10 -05:00
Compare commits
3174 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea5808d833 | ||
|
|
8b045a826a | ||
|
|
1a6e078510 | ||
|
|
daff8010cd | ||
|
|
4035930e0e | ||
|
|
fc63a384b2 | ||
|
|
2f3449b651 | ||
|
|
31c65a39e4 | ||
|
|
7ba20928c3 | ||
|
|
c482cbbe70 | ||
|
|
4042a3e406 | ||
|
|
392132dc3b | ||
|
|
e11302172e | ||
|
|
bf353a42cd | ||
|
|
d8e19b776e | ||
|
|
cf96bb464f | ||
|
|
3c7164846d | ||
|
|
4fa4668ed6 | ||
|
|
0ce21aea08 | ||
|
|
459a3dc58c | ||
|
|
194a8b0922 | ||
|
|
6f2de31146 | ||
|
|
e1ac740ac4 | ||
|
|
4feeaf1641 | ||
|
|
a08bbabd4d | ||
|
|
a7a9d7d85c | ||
|
|
e93c766c42 | ||
|
|
5d4bfdabd6 | ||
|
|
39c16d1cc4 | ||
|
|
eb55d19786 | ||
|
|
ae36fada6b | ||
|
|
60ca7784ba | ||
|
|
8a8336ae08 | ||
|
|
7e8db13854 | ||
|
|
3e7d0ec14f | ||
|
|
5971c00a4f | ||
|
|
8ff7531f89 | ||
|
|
f59e1ad854 | ||
|
|
1a0a8a1655 | ||
|
|
24023ff9e8 | ||
|
|
016f799983 | ||
|
|
fae68a5396 | ||
|
|
79680b1d5e | ||
|
|
0ce45c20b8 | ||
|
|
fed374fcb6 | ||
|
|
374202ac45 | ||
|
|
56db1d3dfa | ||
|
|
d4796261d7 | ||
|
|
452c5d5e91 | ||
|
|
458e0b3b8b | ||
|
|
9758dc6422 | ||
|
|
cc5f93e717 | ||
|
|
49601a63c8 | ||
|
|
6c33188af3 | ||
|
|
1353e3916f | ||
|
|
11d4986517 | ||
|
|
e267bf3e09 | ||
|
|
39c5c8c1d1 | ||
|
|
6cce073da5 | ||
|
|
99372c69e5 | ||
|
|
042b703fe4 | ||
|
|
1880284bde | ||
|
|
6c1faa4bdb | ||
|
|
e4a9fb8a27 | ||
|
|
33f97d7d8f | ||
|
|
82e033942e | ||
|
|
f0473fde17 | ||
|
|
e2980a5210 | ||
|
|
764da14440 | ||
|
|
7da6c627fe | ||
|
|
0a092b5b7f | ||
|
|
693e1c93f1 | ||
|
|
2919b76947 | ||
|
|
42b94561a2 | ||
|
|
acaf134dfe | ||
|
|
ab9109e0dc | ||
|
|
f88b2c11fe | ||
|
|
d5d330413b | ||
|
|
61d7e11001 | ||
|
|
c4c6df179b | ||
|
|
b04b7bf357 | ||
|
|
97b1c66d4a | ||
|
|
74a210f198 | ||
|
|
9f8af2327d | ||
|
|
345e24142e | ||
|
|
0fdd03ddee | ||
|
|
31861052e5 | ||
|
|
7c42b5cb17 | ||
|
|
df7fea4412 | ||
|
|
a0fa288cb6 | ||
|
|
70bac24832 | ||
|
|
1df40fbdeb | ||
|
|
5fa8b42fac | ||
|
|
d3fa67fe2e | ||
|
|
357089a438 | ||
|
|
8b3d75b339 | ||
|
|
f741066466 | ||
|
|
91e9ffff85 | ||
|
|
853df14e2f | ||
|
|
e17a772bb6 | ||
|
|
90e027d9a4 | ||
|
|
fdc9a5d8b0 | ||
|
|
543891a0a0 | ||
|
|
1e45111bde | ||
|
|
9595687bce | ||
|
|
7427b9de35 | ||
|
|
acdddc0b79 | ||
|
|
01c70caa8f | ||
|
|
ff4bab4c07 | ||
|
|
5c36029274 | ||
|
|
cd54186113 | ||
|
|
353689857e | ||
|
|
d74377350b | ||
|
|
06921443fc | ||
|
|
6c0a973ac3 | ||
|
|
3ca46c29c3 | ||
|
|
837fde70ae | ||
|
|
1e52cc474f | ||
|
|
76807006be | ||
|
|
0d35fe0f21 | ||
|
|
370b0fc5da | ||
|
|
25b3c09f6a | ||
|
|
576c365753 | ||
|
|
bc2ed60b92 | ||
|
|
a4385100c4 | ||
|
|
4c01709cdf | ||
|
|
1df924f4f8 | ||
|
|
400bfe9251 | ||
|
|
6e1d364d60 | ||
|
|
504ad86648 | ||
|
|
096b2d73cd | ||
|
|
5754d31d0f | ||
|
|
ed3ed1f90a | ||
|
|
adb1227b2e | ||
|
|
ac190b2e39 | ||
|
|
18ae87962d | ||
|
|
4673862981 | ||
|
|
212d7257e9 | ||
|
|
9df8d0848a | ||
|
|
ded7abb1f6 | ||
|
|
44d5a61cfe | ||
|
|
0db80710aa | ||
|
|
7c47eff112 | ||
|
|
d81849ab3b | ||
|
|
dbb3f80995 | ||
|
|
80b9a3e00b | ||
|
|
be5e5d837b | ||
|
|
ffc4a60bc6 | ||
|
|
1edfa4474f | ||
|
|
18e70f4e79 | ||
|
|
62a81cfdd1 | ||
|
|
6365a026c1 | ||
|
|
7c89193398 | ||
|
|
4a6f1718b8 | ||
|
|
7b3fa8da60 | ||
|
|
2fae7ccf5c | ||
|
|
f36f48c2cf | ||
|
|
8b726c7e8b | ||
|
|
8eb0687407 | ||
|
|
9b9912ba9e | ||
|
|
22d0ed8225 | ||
|
|
b7a58d2f87 | ||
|
|
219ece22fc | ||
|
|
4874301615 | ||
|
|
1827dda0c6 | ||
|
|
d088b01f75 | ||
|
|
00c5062eab | ||
|
|
84eacde63a | ||
|
|
d98290c17f | ||
|
|
6d94a3be05 | ||
|
|
a2833d18ed | ||
|
|
6f95afdc59 | ||
|
|
aaa75a32a5 | ||
|
|
c300015ac2 | ||
|
|
eb4f5e9faa | ||
|
|
c7aec839ae | ||
|
|
37aa89b19d | ||
|
|
3f94e70488 | ||
|
|
435afa0eea | ||
|
|
fb82a5e086 | ||
|
|
71d98c2f26 | ||
|
|
4a97aa12d6 | ||
|
|
c9e67fb460 | ||
|
|
cec87be4e3 | ||
|
|
eb1a234a77 | ||
|
|
394c2b67d6 | ||
|
|
aeb3af7105 | ||
|
|
e5cf99e31c | ||
|
|
8120535a35 | ||
|
|
ba01433381 | ||
|
|
6b99cdb83a | ||
|
|
e7b71f8743 | ||
|
|
03935b2d64 | ||
|
|
2b89f33765 | ||
|
|
9c82a4ca60 | ||
|
|
7eb9b9b1c6 | ||
|
|
69b35b2ede | ||
|
|
e8016abd97 | ||
|
|
e54036be25 | ||
|
|
1dc894087c | ||
|
|
b014967550 | ||
|
|
490962ccdb | ||
|
|
d10e81fb3d | ||
|
|
33a87f54bb | ||
|
|
2cdfa59fbe | ||
|
|
bebe74fa4a | ||
|
|
4098f97735 | ||
|
|
a0b7ac402d | ||
|
|
0ca4482977 | ||
|
|
5cf15db6e4 | ||
|
|
6379d50f07 | ||
|
|
5a2792ae24 | ||
|
|
9b26f3cd84 | ||
|
|
316be5ee34 | ||
|
|
f208e6f0b6 | ||
|
|
7c8c131e1a | ||
|
|
81e71d7275 | ||
|
|
fc6c4b8e16 | ||
|
|
2280566bca | ||
|
|
33173e76a0 | ||
|
|
cc0b9e5088 | ||
|
|
ecc72d7693 | ||
|
|
4ab4aeacb0 | ||
|
|
348d12bd60 | ||
|
|
7b686c1103 | ||
|
|
403583cfbb | ||
|
|
29bff06cd6 | ||
|
|
2b80057ac9 | ||
|
|
c3625e16d7 | ||
|
|
f4642e9e66 | ||
|
|
5bdf4c6143 | ||
|
|
80aaf6a065 | ||
|
|
3025caf932 | ||
|
|
95cfc50fbd | ||
|
|
ded0925155 | ||
|
|
931408037c | ||
|
|
3318651565 | ||
|
|
2ab07f3aac | ||
|
|
1340e54327 | ||
|
|
1b6e4645b1 | ||
|
|
a6a573f5dc | ||
|
|
415415b5b2 | ||
|
|
38e9b92c42 | ||
|
|
345d727936 | ||
|
|
86e8e5199e | ||
|
|
739979a116 | ||
|
|
7cbc81adca | ||
|
|
737d0fa23c | ||
|
|
ab1962934d | ||
|
|
192455702d | ||
|
|
cb0d739daf | ||
|
|
a937fcc477 | ||
|
|
9503e60444 | ||
|
|
9f2dc4554d | ||
|
|
3008dc76d3 | ||
|
|
596c4b77e8 | ||
|
|
05a31c2686 | ||
|
|
45535c0f5a | ||
|
|
4bd0dd2123 | ||
|
|
9b2a643626 | ||
|
|
1ebc9a9a88 | ||
|
|
f0c8b7ce40 | ||
|
|
ec54550f21 | ||
|
|
4474d200b0 | ||
|
|
f062e35641 | ||
|
|
321ef9816c | ||
|
|
be01e925c7 | ||
|
|
6d11006b54 | ||
|
|
ed792b97c0 | ||
|
|
a4b8c2298a | ||
|
|
e5b33ce9f6 | ||
|
|
30374d46c9 | ||
|
|
9edf8233f7 | ||
|
|
bd4a14519c | ||
|
|
f12bf8c09a | ||
|
|
53cc45a0d5 | ||
|
|
fa4b4dece1 | ||
|
|
02f044a2a1 | ||
|
|
431d51f5c4 | ||
|
|
45c1357bab | ||
|
|
5136675fae | ||
|
|
db4f23f377 | ||
|
|
6ff02761a9 | ||
|
|
d46f267663 | ||
|
|
6a98534d5d | ||
|
|
eeb5d99942 | ||
|
|
dcc5f333c1 | ||
|
|
ff8a66d22f | ||
|
|
f7ad97918a | ||
|
|
9047d56aa0 | ||
|
|
945ddc2403 | ||
|
|
92158b0611 | ||
|
|
bed6155c79 | ||
|
|
f2459e61dd | ||
|
|
69dcdafb3d | ||
|
|
6dbb072d11 | ||
|
|
dc96849718 | ||
|
|
d7a3cc505c | ||
|
|
c6936ced6c | ||
|
|
91048f655c | ||
|
|
66bf524394 | ||
|
|
ba9448bdd7 | ||
|
|
c5cb5cba18 | ||
|
|
aa853ac833 | ||
|
|
8b759d0e1e | ||
|
|
a8a2192cf9 | ||
|
|
37f866b47f | ||
|
|
9cf653d673 | ||
|
|
0167b4b4a3 | ||
|
|
dcb773e446 | ||
|
|
b1a86fbc98 | ||
|
|
cdd0cf7f18 | ||
|
|
9ae419201d | ||
|
|
e37cefdbee | ||
|
|
ad8c266f76 | ||
|
|
807c3bdcc7 | ||
|
|
62efbd17de | ||
|
|
d99350fd61 | ||
|
|
40c70a9a2a | ||
|
|
8fb7f40a6a | ||
|
|
2f12d41d9d | ||
|
|
9fbdb6b305 | ||
|
|
73285cadb6 | ||
|
|
56f1c295b6 | ||
|
|
7f76ed8413 | ||
|
|
f7edd36931 | ||
|
|
c39f2b7c05 | ||
|
|
342036408e | ||
|
|
f4904fce17 | ||
|
|
2abb2de753 | ||
|
|
ef0a0db07e | ||
|
|
a45795efec | ||
|
|
88ae353aef | ||
|
|
97b9690711 | ||
|
|
48ce356d5c | ||
|
|
92451f94bc | ||
|
|
593632045d | ||
|
|
e3c55ef307 | ||
|
|
edf1730fd2 | ||
|
|
34cd8e3f95 | ||
|
|
242cce022a | ||
|
|
19bf51cefb | ||
|
|
74a2e80142 | ||
|
|
b9b630e3b6 | ||
|
|
f0bdf833d1 | ||
|
|
81bc6bf34b | ||
|
|
7de736e8d0 | ||
|
|
cd097e0fce | ||
|
|
cc81a7ccfe | ||
|
|
58d320c270 | ||
|
|
59565fd1d1 | ||
|
|
55592137a2 | ||
|
|
58523060f0 | ||
|
|
07d53be9fc | ||
|
|
d4b0235a8b | ||
|
|
34aa41e17b | ||
|
|
36f6a9347c | ||
|
|
d49d386ef2 | ||
|
|
00c363829c | ||
|
|
a9691dbdf4 | ||
|
|
9df701906f | ||
|
|
283671fa9d | ||
|
|
435c29755d | ||
|
|
686f91777c | ||
|
|
2aa028facb | ||
|
|
b4bbd050c2 | ||
|
|
2a4fc28318 | ||
|
|
313485e406 | ||
|
|
faf4267c73 | ||
|
|
e6277d799f | ||
|
|
cdbc8004fb | ||
|
|
1fac2f686d | ||
|
|
08c8d679ac | ||
|
|
48c34b7234 | ||
|
|
28603f0d2c | ||
|
|
b2855f02fe | ||
|
|
bef3d88076 | ||
|
|
e1a8ea7dec | ||
|
|
c4ad97136f | ||
|
|
eab1d6782b | ||
|
|
fd7b8ec77e | ||
|
|
e28c991331 | ||
|
|
a52811dfa3 | ||
|
|
9e210d705d | ||
|
|
c42f1b53ab | ||
|
|
d171173e90 | ||
|
|
679f0f9363 | ||
|
|
724c1e297f | ||
|
|
83154569b1 | ||
|
|
e3c0fba34b | ||
|
|
2b6a6b91f3 | ||
|
|
09a555fdd2 | ||
|
|
dc32f7f0a3 | ||
|
|
1efd8d6c75 | ||
|
|
898fc72313 | ||
|
|
21c5806cbf | ||
|
|
464e6bec95 | ||
|
|
2ae832d919 | ||
|
|
5b03c2d949 | ||
|
|
f629a998a0 | ||
|
|
fe88781bc8 | ||
|
|
e725c97967 | ||
|
|
63caf22671 | ||
|
|
44790b1333 | ||
|
|
b40bb64612 | ||
|
|
7b5ab29a6d | ||
|
|
4fd614be09 | ||
|
|
73236e58c5 | ||
|
|
32414853c6 | ||
|
|
f3dc78d457 | ||
|
|
a32ac62208 | ||
|
|
d7a934cf0e | ||
|
|
503491392d | ||
|
|
b3a2bf367b | ||
|
|
c19eff4872 | ||
|
|
2941a813c2 | ||
|
|
0a022d38fa | ||
|
|
7ed3b3dd3a | ||
|
|
ce52963d2b | ||
|
|
9a1922fdc6 | ||
|
|
967424a538 | ||
|
|
83131103cf | ||
|
|
9f4a0d3216 | ||
|
|
c1591a5efd | ||
|
|
918ef4dff8 | ||
|
|
0d9a04c713 | ||
|
|
0c0c69f0cf | ||
|
|
943e80e26c | ||
|
|
058a327584 | ||
|
|
1eca4170f7 | ||
|
|
c268e4ad1b | ||
|
|
d4f81e8791 | ||
|
|
4f0680c3c8 | ||
|
|
8c26fe44c3 | ||
|
|
8c7d9f3dd2 | ||
|
|
f241b7e79a | ||
|
|
dc1f3503be | ||
|
|
c2a5e180b8 | ||
|
|
7351217489 | ||
|
|
aa42aafe33 | ||
|
|
b2da0120d6 | ||
|
|
9e84e09c26 | ||
|
|
32c1a9bc45 | ||
|
|
a7e95922c1 | ||
|
|
1392d0bc14 | ||
|
|
0f9fa9507e | ||
|
|
1087535d8f | ||
|
|
0e51f51979 | ||
|
|
90e0141ac5 | ||
|
|
8435a8678e | ||
|
|
bd2888fc3b | ||
|
|
6578ffe2c9 | ||
|
|
175340522f | ||
|
|
afc917b582 | ||
|
|
9f4cd7716e | ||
|
|
29b0017445 | ||
|
|
910a7c619a | ||
|
|
273fac2028 | ||
|
|
a323d85d32 | ||
|
|
491a33de0b | ||
|
|
d6a0a44432 | ||
|
|
752533489a | ||
|
|
e4e3c19e96 | ||
|
|
4ddb066728 | ||
|
|
958bbbc8cb | ||
|
|
e15be5c2bf | ||
|
|
cc436dc8cb | ||
|
|
abbcd1f436 | ||
|
|
db494f2afc | ||
|
|
985ea29940 | ||
|
|
76359da58e | ||
|
|
368cd44558 | ||
|
|
cc1387ec0c | ||
|
|
7c79985a29 | ||
|
|
2b56961b54 | ||
|
|
ff9920cbdc | ||
|
|
953a67bc3a | ||
|
|
29343aec3a | ||
|
|
2972472179 | ||
|
|
240e7b0835 | ||
|
|
baf5191433 | ||
|
|
2645e87766 | ||
|
|
ec8bc02d33 | ||
|
|
054bc970e2 | ||
|
|
c1c41242bb | ||
|
|
169ff73d26 | ||
|
|
d985ed553a | ||
|
|
dea1ef24d9 | ||
|
|
49f29a0453 | ||
|
|
76af9ba53d | ||
|
|
2de364414f | ||
|
|
5ae84970e7 | ||
|
|
141b0d38a6 | ||
|
|
44891b6924 | ||
|
|
f008588307 | ||
|
|
e481d03b5e | ||
|
|
a8a73b60c4 | ||
|
|
7e8b76e8ea | ||
|
|
36c746bd9f | ||
|
|
7476c583e7 | ||
|
|
89928ca8e4 | ||
|
|
38a3bf3ada | ||
|
|
96b3d31b42 | ||
|
|
362ae5c4bb | ||
|
|
dc303c2a71 | ||
|
|
be2ca0ea22 | ||
|
|
460cb19839 | ||
|
|
ddfebb17cf | ||
|
|
375c9dd116 | ||
|
|
15716a0772 | ||
|
|
6f6c1cd330 | ||
|
|
36ac757c3a | ||
|
|
b614cfffcb | ||
|
|
b58a52c7b4 | ||
|
|
a80fc1b062 | ||
|
|
90d18189da | ||
|
|
22a2e95126 | ||
|
|
11e1a99e14 | ||
|
|
3c6bfb880d | ||
|
|
ad2c05c3f5 | ||
|
|
fa75f54a05 | ||
|
|
6405fd4770 | ||
|
|
f42f20c70c | ||
|
|
209bc59e8c | ||
|
|
84ee86f6b3 | ||
|
|
ed7791d824 | ||
|
|
0580b10385 | ||
|
|
47c7351b16 | ||
|
|
b158072a15 | ||
|
|
b6486c26e6 | ||
|
|
da0ac96704 | ||
|
|
af1fbda892 | ||
|
|
2234c45c19 | ||
|
|
fd38fb684a | ||
|
|
e0a16e08dd | ||
|
|
43189dfe3a | ||
|
|
46d4f6037d | ||
|
|
e522811a52 | ||
|
|
6124bbb12a | ||
|
|
fbf911cf7e | ||
|
|
7fdfa81fb8 | ||
|
|
a4673f3007 | ||
|
|
24c499d282 | ||
|
|
4581c57478 | ||
|
|
f177924629 | ||
|
|
633e888ba7 | ||
|
|
4316992d95 | ||
|
|
5ecb8bdd8a | ||
|
|
3b81d4b8a5 | ||
|
|
6e3b3dc4e7 | ||
|
|
8d421a62d2 | ||
|
|
185b0690c8 | ||
|
|
bd0e97023e | ||
|
|
34ff0706a3 | ||
|
|
acba61babb | ||
|
|
f91191218b | ||
|
|
05c79ac8c2 | ||
|
|
24d2a93c0d | ||
|
|
de43080228 | ||
|
|
b0cd7be39b | ||
|
|
a7169a6348 | ||
|
|
6e126fb97e | ||
|
|
22783d8f6c | ||
|
|
1d710bdcd9 | ||
|
|
5feffba1ff | ||
|
|
6c56586a6b | ||
|
|
a32b66c7c3 | ||
|
|
7e3c06191e | ||
|
|
372c96c6b2 | ||
|
|
7073b8721a | ||
|
|
fccb9c0bf4 | ||
|
|
3d09090c4e | ||
|
|
596a49c112 | ||
|
|
95fc253d6b | ||
|
|
e6d5372029 | ||
|
|
8e5c692244 | ||
|
|
e694c664e5 | ||
|
|
8779f93746 | ||
|
|
1f0f5c1e23 | ||
|
|
f9f12131ae | ||
|
|
7e0106da0c | ||
|
|
aaf6bf3cd2 | ||
|
|
fa95c82daf | ||
|
|
0da7142a59 | ||
|
|
446a938b06 | ||
|
|
21c3994650 | ||
|
|
f90f3a5ca6 | ||
|
|
a34d2b72c0 | ||
|
|
9d617dcfec | ||
|
|
55506a0fc3 | ||
|
|
19c03f504f | ||
|
|
985a3436e2 | ||
|
|
9dae87c80c | ||
|
|
46364a38c6 | ||
|
|
148b2b9d02 | ||
|
|
64354b51c9 | ||
|
|
d180bc794b | ||
|
|
eab5fd5bdd | ||
|
|
e3ca797dad | ||
|
|
f2db1c8ab2 | ||
|
|
36b8a75ede | ||
|
|
11b2815b88 | ||
|
|
0a42b85c06 | ||
|
|
baf231e3b6 | ||
|
|
e26e85b6d6 | ||
|
|
b2193b23e5 | ||
|
|
2af3a92833 | ||
|
|
d2af6dcf38 | ||
|
|
dd6b66167e | ||
|
|
51a4a88a81 | ||
|
|
516efb21cf | ||
|
|
2d4397af53 | ||
|
|
06f319a380 | ||
|
|
37ed5a01e0 | ||
|
|
4a9997e449 | ||
|
|
54269553c8 | ||
|
|
541d05df1b | ||
|
|
3d6ea23511 | ||
|
|
c0554c9fbf | ||
|
|
61130ea191 | ||
|
|
2581e56503 | ||
|
|
fea0ae7f2f | ||
|
|
3299438cbd | ||
|
|
5c160048df | ||
|
|
e3e1036dda | ||
|
|
876d7ac85e | ||
|
|
70b37dc469 | ||
|
|
6393f69138 | ||
|
|
0ca39f6c65 | ||
|
|
02493251d5 | ||
|
|
ff04648112 | ||
|
|
55002d7adf | ||
|
|
0664c6b5b0 | ||
|
|
a4ebac147b | ||
|
|
cf802dc67e | ||
|
|
84365882de | ||
|
|
37fb6473b3 | ||
|
|
ba676f2810 | ||
|
|
b3d7c622c3 | ||
|
|
bc016e360e | ||
|
|
594918dd3c | ||
|
|
ec5feb41e8 | ||
|
|
94c52e3a77 | ||
|
|
875de4f637 | ||
|
|
72fa5a69f1 | ||
|
|
d63e54237b | ||
|
|
e256d93b43 | ||
|
|
4d12df5424 | ||
|
|
cae120fd4d | ||
|
|
be332a6223 | ||
|
|
bda0bb6f13 | ||
|
|
68c5dcd83d | ||
|
|
9bdcadf634 | ||
|
|
037be433f8 | ||
|
|
2bed62dd9e | ||
|
|
a27bc4ebea | ||
|
|
d6e34761dc | ||
|
|
98effcd8e3 | ||
|
|
baa87bc823 | ||
|
|
944d9c84a0 | ||
|
|
1e447741ee | ||
|
|
4405ac7386 | ||
|
|
e1190f0f0f | ||
|
|
a7f2416c0c | ||
|
|
40d0100132 | ||
|
|
37f7c48cfc | ||
|
|
21adf752c8 | ||
|
|
aec143b882 | ||
|
|
f691040936 | ||
|
|
42acf0ed60 | ||
|
|
ca4a3589e5 | ||
|
|
2eead17224 | ||
|
|
626b26a227 | ||
|
|
c46db0761e | ||
|
|
cfed06697d | ||
|
|
a0d9183b14 | ||
|
|
d3eb674b30 | ||
|
|
7fe1fdd8c7 | ||
|
|
37cbe68204 | ||
|
|
f76a66fc55 | ||
|
|
d7949aa58e | ||
|
|
f0c0c5483f | ||
|
|
7d444021bb | ||
|
|
388a29bbe2 | ||
|
|
a03dd1bd41 | ||
|
|
4b366f2857 | ||
|
|
c87faace6b | ||
|
|
e2be051558 | ||
|
|
1e8b185377 | ||
|
|
031804827f | ||
|
|
6cccd9b6fc | ||
|
|
687fbb0a7e | ||
|
|
8f2db99c86 | ||
|
|
2c0f8dc546 | ||
|
|
a388fb0bb7 | ||
|
|
27465353c1 | ||
|
|
c2ccab4361 | ||
|
|
bb876eac82 | ||
|
|
34c04babbe | ||
|
|
7c6a310179 | ||
|
|
50702eda94 | ||
|
|
59eeafbdfa | ||
|
|
abc606608c | ||
|
|
1487552b48 | ||
|
|
c7dbe18df6 | ||
|
|
c2bc3358cc | ||
|
|
47a1494d68 | ||
|
|
dbb388719e | ||
|
|
283c91548a | ||
|
|
38b93bd310 | ||
|
|
8dcc30ac83 | ||
|
|
0ee123375d | ||
|
|
be18cbef8b | ||
|
|
6a36ec63d7 | ||
|
|
9c8b907ff1 | ||
|
|
f769df16e8 | ||
|
|
c6f5075721 | ||
|
|
8eb494c13e | ||
|
|
b6b6375f70 | ||
|
|
8783688391 | ||
|
|
98afc3e99c | ||
|
|
50a1858367 | ||
|
|
f3f586773b | ||
|
|
61a182077f | ||
|
|
1c9513e770 | ||
|
|
5e5eb9bf8e | ||
|
|
7a9bb65e03 | ||
|
|
a5345ac71e | ||
|
|
ae5079f7b4 | ||
|
|
ea1ecfbc38 | ||
|
|
a84b6b4bcc | ||
|
|
93023128fd | ||
|
|
77157f16a1 | ||
|
|
99736e5066 | ||
|
|
681306b7a1 | ||
|
|
5f36c9d4de | ||
|
|
6cbc8791b1 | ||
|
|
c08de67b0d | ||
|
|
b21e18dfad | ||
|
|
1e497915be | ||
|
|
3704c41dda | ||
|
|
6ff31ac666 | ||
|
|
a2f73a7d35 | ||
|
|
1492e57676 | ||
|
|
7504fc53b6 | ||
|
|
daa2bcefad | ||
|
|
49aa9399be | ||
|
|
a71090df81 | ||
|
|
0bfcafc5c6 | ||
|
|
161d5c8379 | ||
|
|
5cfb578170 | ||
|
|
9b0d47e9eb | ||
|
|
13f4706067 | ||
|
|
7ebdb1736f | ||
|
|
2bcb57c994 | ||
|
|
a2df691c7d | ||
|
|
58f1191f2d | ||
|
|
dfaa999291 | ||
|
|
a693698279 | ||
|
|
6a58033f2b | ||
|
|
7705a6c1f1 | ||
|
|
0a803891a4 | ||
|
|
7d620a93b9 | ||
|
|
3f3b2f4c99 | ||
|
|
9eb4089710 | ||
|
|
257d1afdf8 | ||
|
|
dad1fb7805 | ||
|
|
e312fdd4f8 | ||
|
|
9b6681d543 | ||
|
|
bcc04623c1 | ||
|
|
d75d162058 | ||
|
|
8f2294bbd4 | ||
|
|
d1b91c7619 | ||
|
|
1b6b481fcc | ||
|
|
dd64ba1910 | ||
|
|
82a5d1cd79 | ||
|
|
c26c172d01 | ||
|
|
a7b7aaa7cb | ||
|
|
4e5c02c05c | ||
|
|
2baf61fda3 | ||
|
|
219a25fe80 | ||
|
|
b1dd704819 | ||
|
|
9513e91d66 | ||
|
|
26d52bedb3 | ||
|
|
19451e0654 | ||
|
|
fa922d7792 | ||
|
|
4949e3ba41 | ||
|
|
bbe1de3119 | ||
|
|
f87e9b596d | ||
|
|
917e12952e | ||
|
|
1977c526e4 | ||
|
|
b63351074c | ||
|
|
ebcdea63c0 | ||
|
|
d78eb1247e | ||
|
|
9b9fe0d65c | ||
|
|
5a2db802d9 | ||
|
|
d3972b88f2 | ||
|
|
e62cf13760 | ||
|
|
a5f6e3bba0 | ||
|
|
d170660c25 | ||
|
|
2202aaed51 | ||
|
|
cbefcd50cf | ||
|
|
1acfa291a0 | ||
|
|
21accd534c | ||
|
|
eb29989dff | ||
|
|
de89d7a976 | ||
|
|
78ef42daa1 | ||
|
|
319abebd70 | ||
|
|
76480adda5 | ||
|
|
e205f8afbb | ||
|
|
42dc51784e | ||
|
|
a4a46f480d | ||
|
|
e34be16237 | ||
|
|
dfcc166918 | ||
|
|
895d56ed04 | ||
|
|
12eab4a8ba | ||
|
|
3eb2b1f7a2 | ||
|
|
6ecc9bf93a | ||
|
|
22e24fc387 | ||
|
|
516d88b072 | ||
|
|
da4ebb6535 | ||
|
|
77457e91e9 | ||
|
|
6e4d33c741 | ||
|
|
d3387e2a28 | ||
|
|
491452a19d | ||
|
|
7d3257b222 | ||
|
|
1836ef2884 | ||
|
|
43d6322d0f | ||
|
|
f0684d83e9 | ||
|
|
3f3170818d | ||
|
|
7683096fe1 | ||
|
|
bb438bfb17 | ||
|
|
a11aa295de | ||
|
|
049d92b525 | ||
|
|
f9bd59f031 | ||
|
|
6d0d5bd566 | ||
|
|
35d20a19bc | ||
|
|
dab1c4cfc9 | ||
|
|
9a50f4ac1f | ||
|
|
59e829e595 | ||
|
|
f86946c6df | ||
|
|
e97f75cad5 | ||
|
|
2505f82ce5 | ||
|
|
78dca5fe8b | ||
|
|
8c816f64e4 | ||
|
|
22c525e3fe | ||
|
|
f3f6b03d85 | ||
|
|
00bebc317e | ||
|
|
8f38e83aaf | ||
|
|
8fab7ec5e3 | ||
|
|
50eb968109 | ||
|
|
569314be45 | ||
|
|
909d60464e | ||
|
|
d855abf8b0 | ||
|
|
b611f72e08 | ||
|
|
44e3bec42e | ||
|
|
a04b005e93 | ||
|
|
1b837116e6 | ||
|
|
d16b04b683 | ||
|
|
d2e7a8004d | ||
|
|
7996ef0d45 | ||
|
|
0c28216ee5 | ||
|
|
b05c1a5bb9 | ||
|
|
5bb8ea7449 | ||
|
|
b78c515724 | ||
|
|
cb1a7a7bdc | ||
|
|
b8dcb7c884 | ||
|
|
9dd6f848bd | ||
|
|
1ded554a15 | ||
|
|
bc0ce7b820 | ||
|
|
1da3a57fe7 | ||
|
|
8697982302 | ||
|
|
c4168cf855 | ||
|
|
7023d3ca2b | ||
|
|
57a5d13c47 | ||
|
|
500b96240b | ||
|
|
13d961d41d | ||
|
|
fddc4c2fc0 | ||
|
|
061ec7369f | ||
|
|
8366dbd8e0 | ||
|
|
b02047e4b5 | ||
|
|
e9545c4961 | ||
|
|
966a2b1df5 | ||
|
|
dec6540967 | ||
|
|
3fe1673ce9 | ||
|
|
e9e13474c9 | ||
|
|
aee9093848 | ||
|
|
76822c7c34 | ||
|
|
5c18d34d89 | ||
|
|
970a9c7552 | ||
|
|
37a42dc408 | ||
|
|
a03c9f9457 | ||
|
|
60004ebff1 | ||
|
|
2d9fcf6828 | ||
|
|
e1959afb6b | ||
|
|
c68c78d412 | ||
|
|
c8ac9721d7 | ||
|
|
b72d31f87f | ||
|
|
b1b68b58fe | ||
|
|
95e15c95f2 | ||
|
|
ca21db9481 | ||
|
|
93ad803073 | ||
|
|
6cc7f70a65 | ||
|
|
9f871a3726 | ||
|
|
e19e2c123e | ||
|
|
cbe44e1fff | ||
|
|
2b0c33f74d | ||
|
|
dae1d36a23 | ||
|
|
824fa8f17a | ||
|
|
31cd0b943c | ||
|
|
8e191c8e6b | ||
|
|
070eced2f6 | ||
|
|
986f8dfb2e | ||
|
|
19d742b9e4 | ||
|
|
8c0c03eb38 | ||
|
|
fd9bc20bc5 | ||
|
|
089fca2319 | ||
|
|
e936890927 | ||
|
|
0450d48f89 | ||
|
|
2463819a3d | ||
|
|
2b2cae2d50 | ||
|
|
0f1b40da71 | ||
|
|
f73d5a9ab2 | ||
|
|
4eb0e24c6e | ||
|
|
1d2235abe7 | ||
|
|
d347e54acb | ||
|
|
b5198d8119 | ||
|
|
b8b5c5ff34 | ||
|
|
a738490a3b | ||
|
|
54a8de2059 | ||
|
|
cb2c0e7ac5 | ||
|
|
510d309b8a | ||
|
|
a7ce2a7aa5 | ||
|
|
cfe24ecdd9 | ||
|
|
c5e9cb025c | ||
|
|
c3d07d60ca | ||
|
|
a0897a7456 | ||
|
|
c50ba9267c | ||
|
|
423e69916c | ||
|
|
b56c76f8ad | ||
|
|
cb2d2f000f | ||
|
|
69af77a3bd | ||
|
|
7767746d3e | ||
|
|
7219aaeb89 | ||
|
|
7af1863e81 | ||
|
|
4beb42bf45 | ||
|
|
12a3086a9e | ||
|
|
198725216f | ||
|
|
08647f1267 | ||
|
|
87811efc30 | ||
|
|
82c3e6f87f | ||
|
|
1ac40a3043 | ||
|
|
127b0c3332 | ||
|
|
a6d9150b14 | ||
|
|
7e5197c566 | ||
|
|
2d217e72bd | ||
|
|
12331cc62b | ||
|
|
2449f1e1b6 | ||
|
|
6a6593c656 | ||
|
|
ad220d61f9 | ||
|
|
1e35383b4d | ||
|
|
c8457ab005 | ||
|
|
070a308217 | ||
|
|
c1f4477376 | ||
|
|
d728320ece | ||
|
|
fee0d7168a | ||
|
|
7c23b32de3 | ||
|
|
1437952aee | ||
|
|
a162157301 | ||
|
|
6316bf3582 | ||
|
|
1d856b4723 | ||
|
|
7f56d5c23a | ||
|
|
a778763851 | ||
|
|
983d7ec265 | ||
|
|
297769ef57 | ||
|
|
885d050e5f | ||
|
|
8fb4ce6cad | ||
|
|
42738ab54d | ||
|
|
7d1250620e | ||
|
|
5c49b93c67 | ||
|
|
9a11f81fd3 | ||
|
|
cba2e972fd | ||
|
|
76ad925842 | ||
|
|
ef6f52f688 | ||
|
|
197bfa9f11 | ||
|
|
145f8c7435 | ||
|
|
a8b43ae598 | ||
|
|
567f19bf68 | ||
|
|
5cd4cd2271 | ||
|
|
4180569443 | ||
|
|
5f4a92c8e6 | ||
|
|
ccf3fed950 | ||
|
|
3626003f68 | ||
|
|
11cb040ad1 | ||
|
|
c1761cab49 | ||
|
|
25b25b5434 | ||
|
|
8bdf66d9c0 | ||
|
|
ccebdd142a | ||
|
|
e952da7f91 | ||
|
|
5bd1e4a167 | ||
|
|
6d3de41751 | ||
|
|
f11bac6705 | ||
|
|
c23a601cc6 | ||
|
|
36d4c69fd6 | ||
|
|
ca7e7fa0c4 | ||
|
|
1f6dd5dbb9 | ||
|
|
db52646655 | ||
|
|
8bb18fa988 | ||
|
|
f0edaf2f8c | ||
|
|
d632e3aa1b | ||
|
|
f0e58fa804 | ||
|
|
ceced09d02 | ||
|
|
7d48115b90 | ||
|
|
d2205228fb | ||
|
|
5417fb7287 | ||
|
|
3f59d6daff | ||
|
|
0d659933aa | ||
|
|
3e8eabe833 | ||
|
|
badfc77339 | ||
|
|
c51d3e59ea | ||
|
|
c0d02a65c3 | ||
|
|
3a203b8d83 | ||
|
|
feecdcc7a4 | ||
|
|
51ad533be6 | ||
|
|
29da0bc8f5 | ||
|
|
bccf7fc2a8 | ||
|
|
7b6b5981c4 | ||
|
|
9463192224 | ||
|
|
d1689f0012 | ||
|
|
8ed67fe349 | ||
|
|
90a1d99785 | ||
|
|
e215cf6fb8 | ||
|
|
e827c0bd94 | ||
|
|
8dd7e4e6b5 | ||
|
|
a2b94f4e06 | ||
|
|
8b0037ffab | ||
|
|
4ab03f3bef | ||
|
|
3c3db52f49 | ||
|
|
5b1e884659 | ||
|
|
7ec6740e26 | ||
|
|
f12b8c19be | ||
|
|
76174d31ce | ||
|
|
5042248260 | ||
|
|
1df6589533 | ||
|
|
12f76b448c | ||
|
|
f112ef34f6 | ||
|
|
e4b57a978f | ||
|
|
b51e09e0e8 | ||
|
|
a3ba3f895c | ||
|
|
947a129e12 | ||
|
|
f3fe6a6cbd | ||
|
|
9d150bef9f | ||
|
|
65be18cc93 | ||
|
|
e27ea63900 | ||
|
|
aa96f7b660 | ||
|
|
053690d885 | ||
|
|
b9fc6397a3 | ||
|
|
19b9f15da3 | ||
|
|
0b9441e1a4 | ||
|
|
2324d7420c | ||
|
|
c6b2ca8b19 | ||
|
|
83ea8dc577 | ||
|
|
d898277f62 | ||
|
|
a289cfb986 | ||
|
|
d603998617 | ||
|
|
8bf9f4f5ab | ||
|
|
2c4e6f2926 | ||
|
|
21fbbc50cd | ||
|
|
99512418da | ||
|
|
c2f2d8771f | ||
|
|
179c9ee8cc | ||
|
|
eb8a505287 | ||
|
|
a7482a3644 | ||
|
|
a692348336 | ||
|
|
285dcc30cf | ||
|
|
bcf51aed83 | ||
|
|
1a11ce6211 | ||
|
|
10021c97a6 | ||
|
|
e869e3c534 | ||
|
|
f6416285db | ||
|
|
7f0593cd2d | ||
|
|
e4c41718d8 | ||
|
|
7234553990 | ||
|
|
5761efdb73 | ||
|
|
1133192a86 | ||
|
|
af3288043a | ||
|
|
24a348f6a8 | ||
|
|
5528b6c231 | ||
|
|
245bd1eb17 | ||
|
|
03506db76c | ||
|
|
cb5ef26020 | ||
|
|
2493ae4c2c | ||
|
|
2bd88344ad | ||
|
|
4950980d69 | ||
|
|
2361a0dd6e | ||
|
|
152cdd1750 | ||
|
|
31797a5831 | ||
|
|
9308c42cff | ||
|
|
c096cd34b9 | ||
|
|
5fc0808f28 | ||
|
|
e6866ee980 | ||
|
|
45631d30b0 | ||
|
|
0f432a0844 | ||
|
|
df59bc7194 | ||
|
|
ff4706e450 | ||
|
|
fc013bd04c | ||
|
|
7e29a8b927 | ||
|
|
67ae7a0b6c | ||
|
|
bd5a64bac0 | ||
|
|
1bd85d8baf | ||
|
|
fe34b08ece | ||
|
|
33048f88b8 | ||
|
|
0ec01f4e78 | ||
|
|
d0ebf06ff8 | ||
|
|
687b249034 | ||
|
|
d1528dcff0 | ||
|
|
1c31cf6319 | ||
|
|
67f0c9bef0 | ||
|
|
d54c366150 | ||
|
|
4ff535f883 | ||
|
|
58b15f9452 | ||
|
|
dedca59ac9 | ||
|
|
3cbddfe545 | ||
|
|
e3cae69495 | ||
|
|
aee40316f8 | ||
|
|
d754f9ae89 | ||
|
|
3c50b3a9e0 | ||
|
|
fb312a71f7 | ||
|
|
136d79eaa3 | ||
|
|
834336499a | ||
|
|
c9da8237df | ||
|
|
9638dcda0a | ||
|
|
756c5a2604 | ||
|
|
a9c31652b6 | ||
|
|
32a76901a9 | ||
|
|
a5e11c7489 | ||
|
|
f2b12014e1 | ||
|
|
60fcaebfdb | ||
|
|
32fe2cb659 | ||
|
|
1207d54fdd | ||
|
|
3932884688 | ||
|
|
19a2042746 | ||
|
|
4c6eb137da | ||
|
|
57ec2ff915 | ||
|
|
77a161a087 | ||
|
|
0642402449 | ||
|
|
50d377d9fe | ||
|
|
f5211b0697 | ||
|
|
fd4ea46fd7 | ||
|
|
8d8546868d | ||
|
|
8ce547edeb | ||
|
|
a17c48aed6 | ||
|
|
d12db3e7b8 | ||
|
|
15b87ae297 | ||
|
|
02fdf59839 | ||
|
|
d9da02b7a8 | ||
|
|
8f2ad6418d | ||
|
|
ff984425a3 | ||
|
|
ac1058359f | ||
|
|
9afbca3001 | ||
|
|
ec3f17cb9c | ||
|
|
73b9d5c5f9 | ||
|
|
ecc8591c95 | ||
|
|
696b67e4b1 | ||
|
|
266a5116a1 | ||
|
|
131f2be857 | ||
|
|
be7b3a9952 | ||
|
|
bb31b1785b | ||
|
|
2a60f4b1e9 | ||
|
|
33a4fb5a1a | ||
|
|
aece6e8b6c | ||
|
|
7bf55dd14f | ||
|
|
e158f17c2b | ||
|
|
c5027d9478 | ||
|
|
36c1d82146 | ||
|
|
bd4f404d45 | ||
|
|
43d39844f7 | ||
|
|
e041a4d212 | ||
|
|
433b923ea7 | ||
|
|
f8f1c72b44 | ||
|
|
542716e216 | ||
|
|
b35958d024 | ||
|
|
9ee3541655 | ||
|
|
bf7d84c12a | ||
|
|
34c691087e | ||
|
|
08c383012f | ||
|
|
e2420495f3 | ||
|
|
d530c5eda7 | ||
|
|
ef7420ecf6 | ||
|
|
c905a41e2a | ||
|
|
42ff4b5bf0 | ||
|
|
4fb74a32cc | ||
|
|
c741465328 | ||
|
|
fbca537a40 | ||
|
|
83420b0199 | ||
|
|
33d3ba1b45 | ||
|
|
497f85a236 | ||
|
|
a624c302ab | ||
|
|
cebe21a3af | ||
|
|
9eb679d70a | ||
|
|
6d84443db8 | ||
|
|
da8a1f242c | ||
|
|
946d98b71f | ||
|
|
dff51fc707 | ||
|
|
7d954dd5d1 | ||
|
|
c6300a5da8 | ||
|
|
9359daa0d9 | ||
|
|
2322e9cff7 | ||
|
|
a876e1e348 | ||
|
|
6a863c8f71 | ||
|
|
392b006b06 | ||
|
|
96289f42b7 | ||
|
|
1b69c2441c | ||
|
|
8ca85a4918 | ||
|
|
2a31031cbc | ||
|
|
d148cd8ccc | ||
|
|
d1cc1828b8 | ||
|
|
069e8cf122 | ||
|
|
45cbcaca6d | ||
|
|
102a2db1f3 | ||
|
|
9f81c85ca7 | ||
|
|
ba4a6fc0c5 | ||
|
|
aa803ce2ff | ||
|
|
a027a60f5d | ||
|
|
270649535e | ||
|
|
cf80ba71f4 | ||
|
|
b74df18a4a | ||
|
|
5cd2906a39 | ||
|
|
bc37b69d17 | ||
|
|
94f6e400ad | ||
|
|
b95a6ccf80 | ||
|
|
7df9c1b6e4 | ||
|
|
75348c0158 | ||
|
|
75fb14acaf | ||
|
|
5350315b68 | ||
|
|
658e39c270 | ||
|
|
ef7ce6c7e1 | ||
|
|
509e2411bf | ||
|
|
65c906f951 | ||
|
|
1f159e8233 | ||
|
|
936c76119d | ||
|
|
f45865606a | ||
|
|
cfc9776bae | ||
|
|
e7db264803 | ||
|
|
0cb7ed9e4e | ||
|
|
4b07609458 | ||
|
|
e41e58e781 | ||
|
|
f5030f1c2c | ||
|
|
2a48fb8e87 | ||
|
|
3d8a71fdb2 | ||
|
|
df6dbc5fa4 | ||
|
|
4b1d2839e8 | ||
|
|
a892f80e86 | ||
|
|
b2a79855ae | ||
|
|
ff4974178a | ||
|
|
d7100fd9bc | ||
|
|
0bfb40ae51 | ||
|
|
11c83670d6 | ||
|
|
68ff4f3842 | ||
|
|
ab25cd09ed | ||
|
|
8f05b8f982 | ||
|
|
63ae2f64cf | ||
|
|
105103fae0 | ||
|
|
70f4792ab1 | ||
|
|
defd9fa322 | ||
|
|
e884d0fda6 | ||
|
|
5f6a8fdc20 | ||
|
|
196a9ddbb0 | ||
|
|
746140bd11 | ||
|
|
7b99a5fbac | ||
|
|
b74c31e520 | ||
|
|
221f43e4bd | ||
|
|
a17333d73e | ||
|
|
207b43499c | ||
|
|
0c0de17b38 | ||
|
|
77882e6086 | ||
|
|
19a9834843 | ||
|
|
23dab30ca5 | ||
|
|
b5d7ce8ebe | ||
|
|
bf4eb4b269 | ||
|
|
a5edb6807e | ||
|
|
ecadf30fe7 | ||
|
|
515f0db5b4 | ||
|
|
c2f367cf70 | ||
|
|
f21dfea965 | ||
|
|
b84cad4db0 | ||
|
|
16ae019c8c | ||
|
|
bd2051febd | ||
|
|
6fb1e03ed4 | ||
|
|
8d41a762b6 | ||
|
|
6d3003716c | ||
|
|
2c87c3bac3 | ||
|
|
739c525a98 | ||
|
|
ab287ebf40 | ||
|
|
ab6bcab78a | ||
|
|
6e317896e9 | ||
|
|
b08ee3ff81 | ||
|
|
17fd09102e | ||
|
|
a598cd2b18 | ||
|
|
55e434d67a | ||
|
|
04d4b5d8a0 | ||
|
|
7ea00bcb78 | ||
|
|
0ab56ffde8 | ||
|
|
e7e945533e | ||
|
|
7fd1047832 | ||
|
|
19dfa88258 | ||
|
|
65923b5c20 | ||
|
|
ac731aa50c | ||
|
|
2aa3182476 | ||
|
|
529c386943 | ||
|
|
b659da8a4b | ||
|
|
eba98717c9 | ||
|
|
e4dba99cc0 | ||
|
|
454e688c3d | ||
|
|
54752deaa1 | ||
|
|
a3cf37cb2e | ||
|
|
6459d11d32 | ||
|
|
15f2fabaaf | ||
|
|
d6030b8d68 | ||
|
|
e1757ee726 | ||
|
|
9fed75d59c | ||
|
|
5fe15475a4 | ||
|
|
c7f6f4f48d | ||
|
|
747c6c2714 | ||
|
|
2951f128f6 | ||
|
|
53cb66eeaf | ||
|
|
bcf8f798e2 | ||
|
|
7406176fad | ||
|
|
34ba5678c3 | ||
|
|
da0b78c67a | ||
|
|
47e64ae503 | ||
|
|
520bb74626 | ||
|
|
4beef5cc66 | ||
|
|
ba575f55ec | ||
|
|
2012ce02e8 | ||
|
|
c67e2c2a5a | ||
|
|
4b1ce250c1 | ||
|
|
0401a07507 | ||
|
|
c12265499a | ||
|
|
0e341832e0 | ||
|
|
489e2e6ad5 | ||
|
|
941f637bca | ||
|
|
6277c0595c | ||
|
|
aa9eda1979 | ||
|
|
1d76efcbcd | ||
|
|
34c2c1ec16 | ||
|
|
bf7fea9a0a | ||
|
|
fdf15f3ca3 | ||
|
|
1cb5875b20 | ||
|
|
1a59a5478f | ||
|
|
fc0cb704f2 | ||
|
|
960c0cbddf | ||
|
|
5750443371 | ||
|
|
9f67d86b30 | ||
|
|
66f7d83baa | ||
|
|
b44e87c6e8 | ||
|
|
6da7f17c4a | ||
|
|
b4f45d1e79 | ||
|
|
7d766bf7c7 | ||
|
|
f9132cae85 | ||
|
|
75dc7e6671 | ||
|
|
3fd887fc57 | ||
|
|
128447a681 | ||
|
|
17149741a7 | ||
|
|
23bae932c7 | ||
|
|
d2ec40bb67 | ||
|
|
9701998f82 | ||
|
|
0289c50ad9 | ||
|
|
50490f5b26 | ||
|
|
d12f802027 | ||
|
|
ac7097b4d0 | ||
|
|
66087e4332 | ||
|
|
3706f9bcb8 | ||
|
|
c505218896 | ||
|
|
6186a746e0 | ||
|
|
3e98bae5ec | ||
|
|
2e1e8f764e | ||
|
|
a7492f8612 | ||
|
|
123b1f01e4 | ||
|
|
865f62e3eb | ||
|
|
3ea93f52ee | ||
|
|
b53e545ebc | ||
|
|
157a4c891c | ||
|
|
ad9ea07309 | ||
|
|
fc483cdfc6 | ||
|
|
9033838cf2 | ||
|
|
8e5d2d5905 | ||
|
|
18aa66dabb | ||
|
|
a2f7b78453 | ||
|
|
5c026cbe1d | ||
|
|
dc51476897 | ||
|
|
39eaa577e0 | ||
|
|
1f006481ee | ||
|
|
60faabcbe2 | ||
|
|
d3f1eaf1a3 | ||
|
|
f568e76fd4 | ||
|
|
e947223aaa | ||
|
|
8311162be3 | ||
|
|
75523556e8 | ||
|
|
c82b5d4982 | ||
|
|
1c3158099c | ||
|
|
bdbca75dfa | ||
|
|
124b189cc0 | ||
|
|
de38b46392 | ||
|
|
e1975644d6 | ||
|
|
d9fd27a9e8 | ||
|
|
32425c5561 | ||
|
|
8d20923881 | ||
|
|
3a35b8b26c | ||
|
|
36c93b755a | ||
|
|
ea8c3debea | ||
|
|
b2425b2a25 | ||
|
|
49bc74e7a0 | ||
|
|
51c932164f | ||
|
|
19e82e93b1 | ||
|
|
3f785eaecf | ||
|
|
e59c0f38d9 | ||
|
|
64004c6bc0 | ||
|
|
422332de7e | ||
|
|
5a15ba7451 | ||
|
|
d3686bb1e2 | ||
|
|
3a6eeef580 | ||
|
|
1dc5c6b8a8 | ||
|
|
3532a560d8 | ||
|
|
d2d894d808 | ||
|
|
2aa38bfc4b | ||
|
|
9c3cee9ae4 | ||
|
|
fc521b5f9d | ||
|
|
1a4398cc55 | ||
|
|
5253368acc | ||
|
|
51cfc3d4be | ||
|
|
80bffd93e7 | ||
|
|
df4f22e899 | ||
|
|
529d91fb9d | ||
|
|
8cc70843a5 | ||
|
|
70c841f23a | ||
|
|
108b4e2e10 | ||
|
|
7b22e09805 | ||
|
|
c5838c143c | ||
|
|
eaf71db7c9 | ||
|
|
b322b527b3 | ||
|
|
cc4b231875 | ||
|
|
05642a3e17 | ||
|
|
7dcc6bb579 | ||
|
|
f15c416e59 | ||
|
|
6fa97eeec7 | ||
|
|
03bbf273b3 | ||
|
|
cd0cce4195 | ||
|
|
9f1a72ec88 | ||
|
|
1e376cd3a6 | ||
|
|
49cf939c04 | ||
|
|
338394f8c3 | ||
|
|
575b62d77b | ||
|
|
57fc0eb5b1 | ||
|
|
3a19fe3663 | ||
|
|
a10c621e33 | ||
|
|
0c049179b4 | ||
|
|
e22c873ec4 | ||
|
|
d644ebab09 | ||
|
|
2fdc578a88 | ||
|
|
aeb3a3f7b5 | ||
|
|
044b7ce070 | ||
|
|
815e538f10 | ||
|
|
758233f001 | ||
|
|
f4f4fda520 | ||
|
|
1d77aeb69c | ||
|
|
29dbfc647d | ||
|
|
55d9514e83 | ||
|
|
46bd7956a3 | ||
|
|
e1ee394c26 | ||
|
|
19884ade99 | ||
|
|
f0a88061db | ||
|
|
6057138466 | ||
|
|
aaaa6556f3 | ||
|
|
4745431cda | ||
|
|
0455a948a9 | ||
|
|
bf3e249237 | ||
|
|
fb649e9525 | ||
|
|
9d1e2d9f46 | ||
|
|
9876d93b60 | ||
|
|
b3dd05580b | ||
|
|
32847f33fd | ||
|
|
bff9723fe3 | ||
|
|
d114648c16 | ||
|
|
44d0da02d0 | ||
|
|
c25107eff3 | ||
|
|
af5c36d2a8 | ||
|
|
0828a67145 | ||
|
|
617fb84983 | ||
|
|
6f8ac2b61c | ||
|
|
6f2b4b96cf | ||
|
|
3cc288a169 | ||
|
|
0bbbf3eb3b | ||
|
|
4b1b56fee8 | ||
|
|
154fc59e93 | ||
|
|
218c4c128c | ||
|
|
53f1af0cab | ||
|
|
f9577a38dc | ||
|
|
fadc7d9ba5 | ||
|
|
1e4b2133f6 | ||
|
|
bfefa6d016 | ||
|
|
8b66472949 | ||
|
|
3b3aa94c4e | ||
|
|
dc05275670 | ||
|
|
7921082ece | ||
|
|
efd6a29909 | ||
|
|
88c44b303d | ||
|
|
e7dbb8ccdc | ||
|
|
fe2a743c8d | ||
|
|
2e2d479103 | ||
|
|
1f5c124ac4 | ||
|
|
64a5bc038a | ||
|
|
5d9396334c | ||
|
|
35f0e355bf | ||
|
|
ec160f1f0a | ||
|
|
bbaeca96eb | ||
|
|
3ab779895f | ||
|
|
203c7360e7 | ||
|
|
a831f174ef | ||
|
|
153091f52f | ||
|
|
35d3af5039 | ||
|
|
57e8cd6eab | ||
|
|
fc123a71af | ||
|
|
f14836cf02 | ||
|
|
4178feb65f | ||
|
|
2edaf22590 | ||
|
|
acd3dab957 | ||
|
|
6bbd74adcd | ||
|
|
9bb928bb38 | ||
|
|
c87a6c5969 | ||
|
|
c482c13dcb | ||
|
|
b87ed97402 | ||
|
|
ee000dabfd | ||
|
|
4395711d26 | ||
|
|
a73a011ee0 | ||
|
|
2a8e5e2c14 | ||
|
|
5d9a41f712 | ||
|
|
ebcf4b60f6 | ||
|
|
f976b78917 | ||
|
|
078790bd0f | ||
|
|
b88c5a89a8 | ||
|
|
57028e3acc | ||
|
|
c586a17926 | ||
|
|
9d078bac54 | ||
|
|
38eaefcabd | ||
|
|
ba8cadc2f1 | ||
|
|
380d5dfa6d | ||
|
|
32af626630 | ||
|
|
8358fedaf4 | ||
|
|
aba915037f | ||
|
|
ec82b0c648 | ||
|
|
81a87f873f | ||
|
|
d91b8ac444 | ||
|
|
952e51ac75 | ||
|
|
11267cd44f | ||
|
|
0e59e0aebd | ||
|
|
ae1d3b3dd3 | ||
|
|
1a91dbee5f | ||
|
|
fd507e3e41 | ||
|
|
9c1a67cf47 | ||
|
|
69e3824840 | ||
|
|
fcb1a98129 | ||
|
|
6d942635af | ||
|
|
cda2c5d459 | ||
|
|
969bb5a742 | ||
|
|
4bccc611c3 | ||
|
|
d18c4ece0c | ||
|
|
25c664b13a | ||
|
|
7c680c955f | ||
|
|
442e93d3fc | ||
|
|
f037d1b6ca | ||
|
|
2c8b627008 | ||
|
|
221e3eddd5 | ||
|
|
74c39c677b | ||
|
|
e6558832bf | ||
|
|
9c50625c55 | ||
|
|
d372435e92 | ||
|
|
a53facf709 | ||
|
|
ffc39dfbcb | ||
|
|
cba38b15a9 | ||
|
|
3450b5f80c | ||
|
|
5ac7564bfe | ||
|
|
53cd289b90 | ||
|
|
8dc13bcf1a | ||
|
|
261825a89b | ||
|
|
f47a5a309d | ||
|
|
a40f2b9fa0 | ||
|
|
cfcd3892f7 | ||
|
|
703987f61c | ||
|
|
e50a8917ec | ||
|
|
74d7c8e625 | ||
|
|
a5d1383fe8 | ||
|
|
bf2bcf515c | ||
|
|
4c5e94c64b | ||
|
|
b4043216b6 | ||
|
|
4371014667 | ||
|
|
fbb3222d29 | ||
|
|
f76b5d8002 | ||
|
|
7e54868206 | ||
|
|
4ca3889bed | ||
|
|
d84a8e6404 | ||
|
|
eef1aebe8c | ||
|
|
4833b6085c | ||
|
|
2ceaca8828 | ||
|
|
48382c4b59 | ||
|
|
d02158c0ef | ||
|
|
9a45f0b31c | ||
|
|
25c26e2f81 | ||
|
|
6213c4f2cd | ||
|
|
e4837f14b1 | ||
|
|
ce86131d12 | ||
|
|
e6c9baf6ef | ||
|
|
8d6db7be31 | ||
|
|
a2548b1fd0 | ||
|
|
e4658bb99d | ||
|
|
bf2e4a561a | ||
|
|
1816320124 | ||
|
|
f09bfe293d | ||
|
|
7b4e8fda4b | ||
|
|
c95812353f | ||
|
|
cd34eea017 | ||
|
|
b622ec7a28 | ||
|
|
7a0a702ec0 | ||
|
|
d8fbe7b77f | ||
|
|
dbcac37d91 | ||
|
|
d4d391b34f | ||
|
|
571cf7d490 | ||
|
|
e18b19ca5a | ||
|
|
48651bf482 | ||
|
|
5034a41c08 | ||
|
|
6795173e77 | ||
|
|
219ef996f5 | ||
|
|
00af1db275 | ||
|
|
5935ea896f | ||
|
|
459983c05e | ||
|
|
ebf4f029ac | ||
|
|
0eec945df1 | ||
|
|
8824b9d68f | ||
|
|
d2862814c5 | ||
|
|
25fece2d50 | ||
|
|
beb4239d1b | ||
|
|
2b78e37d92 | ||
|
|
a2070d9ce4 | ||
|
|
5827a686b8 | ||
|
|
dec479532e | ||
|
|
5d173168cc | ||
|
|
2aac1cde04 | ||
|
|
3676f0268f | ||
|
|
a7b75a54bb | ||
|
|
961a87b743 | ||
|
|
e03d59e381 | ||
|
|
d46ce5003c | ||
|
|
d9ed8e125e | ||
|
|
4c4143d9be | ||
|
|
36708a5067 | ||
|
|
8bc7d259f4 | ||
|
|
2d047fa428 | ||
|
|
735d420d40 | ||
|
|
8c32955da1 | ||
|
|
bc9fc1aece | ||
|
|
c111ed4b20 | ||
|
|
b88e3c99c1 | ||
|
|
a3ea9427d1 | ||
|
|
ce3e6e084c | ||
|
|
2a58ca7697 | ||
|
|
af96f7a0cd | ||
|
|
7d39d1a925 | ||
|
|
1b6c700e18 | ||
|
|
6304bd60ee | ||
|
|
4ad4417740 | ||
|
|
6a4c259a73 | ||
|
|
12eabb220d | ||
|
|
d68ce2d68c | ||
|
|
8e02c040eb | ||
|
|
a7a317c284 | ||
|
|
9d6ef24660 | ||
|
|
14014408fb | ||
|
|
b933e9666a | ||
|
|
7aff59bcce | ||
|
|
8e2760cb3d | ||
|
|
7a9fc6dbd3 | ||
|
|
75d0dc251e | ||
|
|
9a50c4d93f | ||
|
|
010d5a0192 | ||
|
|
cf1594829a | ||
|
|
854d720ce0 | ||
|
|
2f43c74ece | ||
|
|
b9817ac6b4 | ||
|
|
1e8da0d494 | ||
|
|
c47be7b415 | ||
|
|
d3f6cb860f | ||
|
|
83d25f09a3 | ||
|
|
ed747a2d3d | ||
|
|
3a8ee4ce2e | ||
|
|
5ac01a3af4 | ||
|
|
46343f2f9e | ||
|
|
56ccb5b2ab | ||
|
|
9a946eed80 | ||
|
|
9c6cb0f630 | ||
|
|
1b066d6965 | ||
|
|
54c3caad53 | ||
|
|
9b5e8aaf83 | ||
|
|
5143c09bcf | ||
|
|
09b534b8a3 | ||
|
|
2496185629 | ||
|
|
34deb82aea | ||
|
|
8f72ae9da2 | ||
|
|
b753f01ac1 | ||
|
|
fd0a147ae6 | ||
|
|
e94bd90782 | ||
|
|
ce4b897d0e | ||
|
|
a7694029e2 | ||
|
|
1e9110b763 | ||
|
|
6f3fbbbe49 | ||
|
|
d346ec7bfe | ||
|
|
26a3613397 | ||
|
|
e6318bddf3 | ||
|
|
514bb0beda | ||
|
|
41b1bd2f05 | ||
|
|
bf40dadf04 | ||
|
|
cb1678ebec | ||
|
|
0c1ac568b5 | ||
|
|
0f9550c747 | ||
|
|
b13ae17a47 | ||
|
|
f762a12d18 | ||
|
|
20d30a80be | ||
|
|
229b218203 | ||
|
|
4b668aaca8 | ||
|
|
8c7f1421c6 | ||
|
|
d90b2c1d52 | ||
|
|
22f39be197 | ||
|
|
2fa45436c2 | ||
|
|
cadbb6bbce | ||
|
|
2c89f04be7 | ||
|
|
597011e3a9 | ||
|
|
0d433b58ba | ||
|
|
cde8ef56e5 | ||
|
|
110816c7aa | ||
|
|
fbb1e168f7 | ||
|
|
23085eb5ae | ||
|
|
7344a6205f | ||
|
|
4b76ec40c0 | ||
|
|
90101d0269 | ||
|
|
7ac84c0660 | ||
|
|
2090530bbb | ||
|
|
b6cb7ddbaf | ||
|
|
3422d9335c | ||
|
|
e91f9a944e | ||
|
|
e7ddc7cf0f | ||
|
|
40dfa48756 | ||
|
|
579f92cf5f | ||
|
|
4565125da9 | ||
|
|
ce13a01e65 | ||
|
|
618a8682b7 | ||
|
|
963077f918 | ||
|
|
3704d2d86b | ||
|
|
fc6a029311 | ||
|
|
7c7b1e6c2d | ||
|
|
892920039d | ||
|
|
51cdd38c3e | ||
|
|
80977bd4c0 | ||
|
|
d8022f94ef | ||
|
|
1c43587d7d | ||
|
|
b2ed32b118 | ||
|
|
0cc815d816 | ||
|
|
d452b7593f | ||
|
|
5346bdc683 | ||
|
|
dc5c1e2002 | ||
|
|
2e48e298a2 | ||
|
|
7a1aaaf5c4 | ||
|
|
bde92d5cfe | ||
|
|
691f0f4845 | ||
|
|
fdd458d2fe | ||
|
|
d2c0b8374a | ||
|
|
c96c78892d | ||
|
|
957643f523 | ||
|
|
749bbec566 | ||
|
|
25e363c5fb | ||
|
|
febeed3277 | ||
|
|
9d07aa006d | ||
|
|
12d69e25dd | ||
|
|
0c9f1efc75 | ||
|
|
665b4506e7 | ||
|
|
cb5548ceb8 | ||
|
|
c9492e54f7 | ||
|
|
12490eafff | ||
|
|
6e83d11d5f | ||
|
|
9c6aedc91b | ||
|
|
a9339d0627 | ||
|
|
4d9aa10532 | ||
|
|
b00264b594 | ||
|
|
e329c7015e | ||
|
|
1392cfc72d | ||
|
|
c6688d8f89 | ||
|
|
87abea0ba3 | ||
|
|
f9fcb44f3c | ||
|
|
996cbbca38 | ||
|
|
581f4b89bd | ||
|
|
88a347dce0 | ||
|
|
3e7b197a1d | ||
|
|
94ab06e92f | ||
|
|
d38c81fcff | ||
|
|
3e26fdfb67 | ||
|
|
e1be73232d | ||
|
|
190c61ba2f | ||
|
|
06fd2268d9 | ||
|
|
15251dfae1 | ||
|
|
f62812a8dc | ||
|
|
c6041d2590 | ||
|
|
c7e779107c | ||
|
|
7cd25c919f | ||
|
|
47d67d3985 | ||
|
|
1a7921b46c | ||
|
|
43d569741b | ||
|
|
52c6869eab | ||
|
|
6dff9097a2 | ||
|
|
4ff211662a | ||
|
|
05eab51a0d | ||
|
|
604a4e7dbc | ||
|
|
80dca96ee8 | ||
|
|
7f97037190 | ||
|
|
b658afd857 | ||
|
|
992ad97ad5 | ||
|
|
5af6cbae2c | ||
|
|
2abe792f36 | ||
|
|
1ff9bb8fdc | ||
|
|
5cb1039daf | ||
|
|
591c5dabf4 | ||
|
|
770fff287e | ||
|
|
cea7a179ae | ||
|
|
d80c40cfbf | ||
|
|
12e83374e9 | ||
|
|
98344d2e5e | ||
|
|
99dc1eec50 | ||
|
|
2a886576a6 | ||
|
|
919d005550 | ||
|
|
97abdaca5a | ||
|
|
9cc8b7c858 | ||
|
|
0726472b91 | ||
|
|
3cbe92d797 | ||
|
|
72a278c9ed | ||
|
|
e567c8adce | ||
|
|
dde8045109 | ||
|
|
c922c4c383 | ||
|
|
bc8907e90d | ||
|
|
a8ba7786ae | ||
|
|
c734e48ad0 | ||
|
|
d30d0b29a9 | ||
|
|
2912defb97 | ||
|
|
69f8ac6b56 | ||
|
|
e7441ff6e8 | ||
|
|
8a34158fa4 | ||
|
|
8d2a6d96f2 | ||
|
|
bb50b677c7 | ||
|
|
0fde4b3b2e | ||
|
|
ee9c109f07 | ||
|
|
1219423091 | ||
|
|
cf00ab854f | ||
|
|
c417dcb7e2 | ||
|
|
7ad711f554 | ||
|
|
2d7b0cf94d | ||
|
|
d669c07e8a | ||
|
|
8bd52946b4 | ||
|
|
27e81637be | ||
|
|
5c67e27a30 | ||
|
|
59af9809fe | ||
|
|
a564510c49 | ||
|
|
285b614927 | ||
|
|
fd2d2c035e | ||
|
|
dc71ec734d | ||
|
|
78981862be | ||
|
|
7f1253ff83 | ||
|
|
e0265aed05 | ||
|
|
9d36d88a65 | ||
|
|
5dd5602229 | ||
|
|
126c4e9a06 | ||
|
|
5dbaf6ceb0 | ||
|
|
90de5659ea | ||
|
|
367e50edab | ||
|
|
42b8dafafe | ||
|
|
577aaf8ad6 | ||
|
|
07cdf0364c | ||
|
|
7f829f0159 | ||
|
|
a918aa97d9 | ||
|
|
4fdecc9b85 | ||
|
|
7af25c785d | ||
|
|
4de39b205d | ||
|
|
2748a2e97f | ||
|
|
2926bbfe15 | ||
|
|
254c63763a | ||
|
|
2de834f1f4 | ||
|
|
7273eab80e | ||
|
|
13e79c777a | ||
|
|
8aa7d4b463 | ||
|
|
5251f1c9db | ||
|
|
82e923dfc8 | ||
|
|
decf16b92c | ||
|
|
b84d960a81 | ||
|
|
34cb305755 | ||
|
|
ed85bfa915 | ||
|
|
06ef33ff5e | ||
|
|
57f121178c | ||
|
|
3b88ee623b | ||
|
|
8588625937 | ||
|
|
3417839726 | ||
|
|
c1069052ae | ||
|
|
ea17542e4b | ||
|
|
c7d779fe88 | ||
|
|
a70f3f12c5 | ||
|
|
90a31589bb | ||
|
|
b48d9a3a82 | ||
|
|
0255311bbe | ||
|
|
bd91519df9 | ||
|
|
58fe8b0cf1 | ||
|
|
064aa64f20 | ||
|
|
d9f79853fb | ||
|
|
2e68ee5c8b | ||
|
|
a9544ca890 | ||
|
|
9a549a853b | ||
|
|
2dad769a00 | ||
|
|
0ceb14dbf6 | ||
|
|
bab1e26d9b | ||
|
|
9a91cc232c | ||
|
|
5a46cf1d48 | ||
|
|
f1e241940b | ||
|
|
47b344ba12 | ||
|
|
afbb06a72f | ||
|
|
e336cd463f | ||
|
|
3a8315971e | ||
|
|
4ccfa98771 | ||
|
|
1db120bf06 | ||
|
|
262cf63956 | ||
|
|
fe2ae4c6c3 | ||
|
|
16d9944dbb | ||
|
|
e9956cc71e | ||
|
|
3af96e50bd | ||
|
|
59a85c1d75 | ||
|
|
4427149a38 | ||
|
|
20dee618ea | ||
|
|
37ebbb53be | ||
|
|
ba019efaf1 | ||
|
|
ce948fc512 | ||
|
|
2cd9e7fb55 | ||
|
|
1e2d151684 | ||
|
|
ce5651f5fa | ||
|
|
20ba0bf4ed | ||
|
|
ddc56c8a0d | ||
|
|
c325ffd0f8 | ||
|
|
e0da2764c9 | ||
|
|
6e88d9688b | ||
|
|
bf898f10fb | ||
|
|
c891999e1d | ||
|
|
938e287501 | ||
|
|
edcfc32b1a | ||
|
|
904b211d98 | ||
|
|
af08567f24 | ||
|
|
75ef658962 | ||
|
|
fe2dd79838 | ||
|
|
bbe7e6525d | ||
|
|
ef20df719c | ||
|
|
68399601ce | ||
|
|
aa637fd942 | ||
|
|
601c97c015 | ||
|
|
6b47052491 | ||
|
|
297da94319 | ||
|
|
64f101f534 | ||
|
|
45917f278a | ||
|
|
ddd2759cec | ||
|
|
70d8903d3c | ||
|
|
f66c7dc09c | ||
|
|
ad29093ac1 | ||
|
|
82c6caef85 | ||
|
|
46ec72412a | ||
|
|
ead09395d9 | ||
|
|
7106fc5304 | ||
|
|
d16dcb9f19 | ||
|
|
1aaf34b0ed | ||
|
|
39a3b8922d | ||
|
|
9b78582475 | ||
|
|
3a84224b93 | ||
|
|
2592ba7399 | ||
|
|
1795e0a290 | ||
|
|
c959f59581 | ||
|
|
2449723a1c | ||
|
|
ae0e56e98d | ||
|
|
6efe521e44 | ||
|
|
bccd21ac14 | ||
|
|
8449a65cdf | ||
|
|
fc47562983 | ||
|
|
76900ae291 | ||
|
|
ec55559ff1 | ||
|
|
3daa26e1f7 | ||
|
|
9ea8b6f659 | ||
|
|
387f2f0a94 | ||
|
|
b0d95d02be | ||
|
|
3a98f01d31 | ||
|
|
d305752749 | ||
|
|
2ba4b235fc | ||
|
|
6820c0a5d7 | ||
|
|
048883ad27 | ||
|
|
08e7ada242 | ||
|
|
d3ddfa31f7 | ||
|
|
4b899a813e | ||
|
|
28610a9a42 | ||
|
|
15ee9a5cac | ||
|
|
58945a429f | ||
|
|
9f4111015e | ||
|
|
04b960b415 | ||
|
|
33267f2178 | ||
|
|
970e50d1f1 | ||
|
|
d4199c2d08 | ||
|
|
cf4ca7b6a8 | ||
|
|
d8b335ce65 | ||
|
|
39a2934b05 | ||
|
|
7d1c720b84 | ||
|
|
51743461ee | ||
|
|
53cf5ca762 | ||
|
|
b5ef42b0a1 | ||
|
|
0521ddd858 | ||
|
|
b7bb3bfee2 | ||
|
|
4183044e96 | ||
|
|
27448bde20 | ||
|
|
87b9e8fbaf | ||
|
|
9d79859ba6 | ||
|
|
25bb55491a | ||
|
|
198cbacc3e | ||
|
|
3f842221f7 | ||
|
|
5d0183a9ed | ||
|
|
99df4d660b | ||
|
|
65eb528e2d | ||
|
|
f2adfde1a8 | ||
|
|
1e915a2903 | ||
|
|
e2dc3e9ff3 | ||
|
|
f1bb8daaab | ||
|
|
ec9d68960f | ||
|
|
b0fcbebdae | ||
|
|
34f72ecf8f | ||
|
|
9d348319fd | ||
|
|
c55fee69de | ||
|
|
ce31cb072b | ||
|
|
6b91fc9c91 | ||
|
|
e34f77ba0e | ||
|
|
bc3b7401a1 | ||
|
|
85677eaf1a | ||
|
|
75d5e74059 | ||
|
|
c4d15b3b95 | ||
|
|
aa168ec2d6 | ||
|
|
4ae0efe887 | ||
|
|
86a57d8b56 | ||
|
|
9dda7485eb | ||
|
|
8b9670add9 | ||
|
|
978aebd79c | ||
|
|
ac079f0f83 | ||
|
|
e82e912151 | ||
|
|
5488ae5b89 | ||
|
|
15b875b116 | ||
|
|
dedf835aa6 | ||
|
|
e62b9c6009 | ||
|
|
53da778506 | ||
|
|
4360b2c815 | ||
|
|
1e15b1e0be | ||
|
|
c618eba9a9 | ||
|
|
0bc50f7284 | ||
|
|
435f9113e8 | ||
|
|
8818c4785b | ||
|
|
2e003e5404 | ||
|
|
e791a8ea07 | ||
|
|
2fb8eb755b | ||
|
|
1ef8378a30 | ||
|
|
d031f958a9 | ||
|
|
9bbadac9dc | ||
|
|
b012f77475 | ||
|
|
3cf36b1773 | ||
|
|
8f93c046a9 | ||
|
|
90af68901a | ||
|
|
c17507b216 | ||
|
|
b110b7c3f7 | ||
|
|
36431b3dcd | ||
|
|
609294deee | ||
|
|
fffae9a741 | ||
|
|
598ce4bb5f | ||
|
|
212f6dc9e0 | ||
|
|
cd05f1c3d7 | ||
|
|
d7a0691c99 | ||
|
|
86346aa332 | ||
|
|
b162b1fa34 | ||
|
|
ea9f8b0ceb | ||
|
|
6210b9e746 | ||
|
|
a778b410b9 | ||
|
|
8a674c8bc3 | ||
|
|
aaf625c624 | ||
|
|
d4079a3273 | ||
|
|
8d94fe3346 | ||
|
|
ce510e55ae | ||
|
|
5419ff9a71 | ||
|
|
ade437d625 | ||
|
|
87780a5b7e | ||
|
|
f6f6f261ed | ||
|
|
65acc7c9ad | ||
|
|
31d95ac9e6 | ||
|
|
964d17d05a | ||
|
|
665c5992f0 | ||
|
|
5f52e0581d | ||
|
|
870e3a45ef | ||
|
|
a5fe4a3694 | ||
|
|
838670ccbc | ||
|
|
baf4cc225e | ||
|
|
93ac1605bd | ||
|
|
c8a68001c1 | ||
|
|
244a22755c | ||
|
|
79c3ea82c7 | ||
|
|
4b92960975 | ||
|
|
ef616ff25b | ||
|
|
7fb1a470ce | ||
|
|
fc6b2d9193 | ||
|
|
e5dc66e7e5 | ||
|
|
bb01b76582 | ||
|
|
f1aff0fd96 | ||
|
|
5656be5206 | ||
|
|
484ce8e488 | ||
|
|
dcadefd133 | ||
|
|
28366677b0 | ||
|
|
d65302742c | ||
|
|
b2cf28efdd | ||
|
|
41e20bb6b7 | ||
|
|
6e670a2499 | ||
|
|
481b2186cb | ||
|
|
1bc1c0b14f | ||
|
|
e9d27b9d2b | ||
|
|
828bbc407f | ||
|
|
e50469d84e | ||
|
|
d3a9b126a6 | ||
|
|
9eb185ec39 | ||
|
|
fcf60e7f7c | ||
|
|
0ebee92f7d | ||
|
|
64b42bba2e | ||
|
|
d297f9e032 | ||
|
|
30aabf1da9 | ||
|
|
eebdaa2f27 | ||
|
|
c3c9c4cde5 | ||
|
|
640d5135df | ||
|
|
cbbd20a687 | ||
|
|
1a2a27b988 | ||
|
|
d819151020 | ||
|
|
d089436546 | ||
|
|
289d604690 | ||
|
|
2979e0e964 | ||
|
|
5338f1cfbd | ||
|
|
214f18cbfd | ||
|
|
9b11609b63 | ||
|
|
d476c2b613 | ||
|
|
590afebc0a | ||
|
|
02bd1af293 | ||
|
|
2fde82528d | ||
|
|
6c383e279f | ||
|
|
5c07477de4 | ||
|
|
146a284315 | ||
|
|
a8faeeac73 | ||
|
|
69e385e4cd | ||
|
|
41b8dd2863 | ||
|
|
493dc8fcd5 | ||
|
|
87764445e8 | ||
|
|
0bb31e16c9 | ||
|
|
72c90abe36 | ||
|
|
c4d8d33a60 | ||
|
|
a267bca8fb | ||
|
|
32d2e78e3c | ||
|
|
555e70ebec | ||
|
|
cd1b2aab46 | ||
|
|
43289103cb | ||
|
|
9edce23e76 | ||
|
|
756a8a35e3 | ||
|
|
f3057c61a7 | ||
|
|
25345f08e7 | ||
|
|
2091e12e82 | ||
|
|
3eb000fa60 | ||
|
|
3059b36118 | ||
|
|
35b1887e17 | ||
|
|
8f9b8a8550 | ||
|
|
174befe729 | ||
|
|
e212b64823 | ||
|
|
991dc32a0b | ||
|
|
a76efd4166 | ||
|
|
8a768baaaa | ||
|
|
997692b494 | ||
|
|
59ffec4e39 | ||
|
|
56d0ecc253 | ||
|
|
e863746bd7 | ||
|
|
d4dc7911eb | ||
|
|
f561d3261a | ||
|
|
1bc5632771 | ||
|
|
fdf8ee7015 | ||
|
|
5ec95086f2 | ||
|
|
26e4669316 | ||
|
|
4b488a2d28 | ||
|
|
6c352dca74 | ||
|
|
9d816694ba | ||
|
|
39ef35db0c | ||
|
|
b8ed135183 | ||
|
|
6f750582dd | ||
|
|
5f93fbd471 | ||
|
|
0e2653b7dd | ||
|
|
47554b562d | ||
|
|
99427d649e | ||
|
|
7bc4589d4d | ||
|
|
9af586d4ac | ||
|
|
87e68cac6c | ||
|
|
7d5a98409b | ||
|
|
f28367bcfc | ||
|
|
14817e31f6 | ||
|
|
fbdbd722b1 | ||
|
|
b34102cd11 | ||
|
|
3c51cd6626 | ||
|
|
b0b34236e3 | ||
|
|
a502836002 | ||
|
|
09417d4b83 | ||
|
|
83ef2fa84c | ||
|
|
e596a45e9f | ||
|
|
24e5000c37 | ||
|
|
e3bcfa17f8 | ||
|
|
3b512676b7 | ||
|
|
928198bbfe | ||
|
|
1fb56f0ad2 | ||
|
|
9797f62cb8 | ||
|
|
4ddd87e773 | ||
|
|
7fd2e4d2db | ||
|
|
55c7d86205 | ||
|
|
737a28050c | ||
|
|
434ecdac6b | ||
|
|
709570afcc | ||
|
|
b084b4faaf | ||
|
|
d96ce23451 | ||
|
|
760a9d6d35 | ||
|
|
8e624cedb1 | ||
|
|
39cf269d6b | ||
|
|
6a00b5a79e | ||
|
|
2ce674e3fd | ||
|
|
0fcc25d7c9 | ||
|
|
63bd0136fb | ||
|
|
80a2a934dd | ||
|
|
e13976a3b3 | ||
|
|
5144330807 | ||
|
|
bb29639183 | ||
|
|
4667cb9de9 | ||
|
|
c34f3defe1 | ||
|
|
eb0d742672 | ||
|
|
d9b0a73787 | ||
|
|
4810879b2f | ||
|
|
f4b6704aad | ||
|
|
b1a31d3b30 | ||
|
|
bf909db3f9 | ||
|
|
9c68be4d5e | ||
|
|
d7956dd495 | ||
|
|
37a473e7d6 | ||
|
|
5a1c885e8f | ||
|
|
0b1136ad82 | ||
|
|
45af549897 | ||
|
|
97844603fc | ||
|
|
c07b39e58b | ||
|
|
384c543ab9 | ||
|
|
592b13d7db | ||
|
|
6fdba3c02e | ||
|
|
cbf758ead9 | ||
|
|
d1ad778a64 | ||
|
|
ce5ad296ae | ||
|
|
797e105786 | ||
|
|
d17d80747e | ||
|
|
55ea207a55 | ||
|
|
6384d1e5a3 | ||
|
|
aba01cdace | ||
|
|
517b7a14b4 | ||
|
|
2927de7cf9 | ||
|
|
6471ba70e4 | ||
|
|
9f9de01c51 | ||
|
|
3662decb8b | ||
|
|
583bcfb3c7 | ||
|
|
c45e3fa4d5 | ||
|
|
24cbcef620 | ||
|
|
e2a520ff49 | ||
|
|
a5e3317e28 | ||
|
|
5638c4ba87 | ||
|
|
bf7a128142 | ||
|
|
c5243cd4d5 | ||
|
|
db868ed29d | ||
|
|
450c7d80f8 | ||
|
|
abbb001975 | ||
|
|
f35d83ae48 | ||
|
|
a2315dc95e | ||
|
|
4e2feb6fbc | ||
|
|
13602b6769 | ||
|
|
85dba25246 | ||
|
|
66432672b3 | ||
|
|
e6d96e4c18 | ||
|
|
9812305bb9 | ||
|
|
f680a63a1f | ||
|
|
781d63cb2a | ||
|
|
9ff04ee3d8 | ||
|
|
5d85a24977 | ||
|
|
1e51fca0b0 | ||
|
|
5537d53f9a | ||
|
|
50a4170541 | ||
|
|
3a8255bda1 | ||
|
|
a617846f0f | ||
|
|
5772588c29 | ||
|
|
9d0dc45f74 | ||
|
|
c6aefbc9a0 | ||
|
|
dbbafb0cc9 | ||
|
|
6e8272f78f | ||
|
|
baf8a63121 | ||
|
|
fc4a76ee50 | ||
|
|
2117d1d035 | ||
|
|
0a70e0b7b6 | ||
|
|
64ffac5671 | ||
|
|
ac384e8a9c | ||
|
|
f97c8222c7 | ||
|
|
728289ee3a | ||
|
|
5faa16f9ee | ||
|
|
4e608b116a | ||
|
|
521b49166e | ||
|
|
8f32decf2d | ||
|
|
0d51f83d2d | ||
|
|
78c6a68db9 | ||
|
|
2949ab73e2 | ||
|
|
223741820d | ||
|
|
4b57821f52 | ||
|
|
74271a479f | ||
|
|
c377177108 | ||
|
|
84eb729bd4 | ||
|
|
14aea365c5 | ||
|
|
97cb3fa5a5 | ||
|
|
b5368db704 | ||
|
|
8c442b72f3 | ||
|
|
f8f6791d39 | ||
|
|
0c09f077aa | ||
|
|
af2831d7b6 | ||
|
|
64d5d4aec7 | ||
|
|
619a6b2adb | ||
|
|
33a26bc0cf | ||
|
|
b445a7c4d3 | ||
|
|
e6892d0c3e | ||
|
|
33e9a88b56 | ||
|
|
df00a2251e | ||
|
|
92c44c8abe | ||
|
|
8e4f7bbd3e | ||
|
|
a40217cf07 | ||
|
|
e586fda5f2 | ||
|
|
a58564ff88 | ||
|
|
89885b9fb9 | ||
|
|
5c7d977ae0 | ||
|
|
2cd3ee9698 | ||
|
|
dd3080e018 | ||
|
|
5915e8e86a | ||
|
|
3c67c06654 | ||
|
|
76232ca573 | ||
|
|
5235e82bda | ||
|
|
10f0713257 | ||
|
|
e9c7970ea4 | ||
|
|
1a6ac4aeb1 | ||
|
|
f633bdddf0 | ||
|
|
de0b91d157 | ||
|
|
2e77e498f5 | ||
|
|
4ac67eb1f9 | ||
|
|
2b536de37f | ||
|
|
2ffa92ba1b | ||
|
|
6ecddd8388 | ||
|
|
bd2772ea4c | ||
|
|
92bf79d53b | ||
|
|
eebe0eeb71 | ||
|
|
1068eaa0b9 | ||
|
|
faac3e7d7c | ||
|
|
dab4340207 | ||
|
|
fd2567748f | ||
|
|
c2daedbd11 | ||
|
|
7c604beb73 | ||
|
|
8c42aea827 | ||
|
|
cf1bfdfb61 | ||
|
|
75b26513e1 | ||
|
|
6c09a77a97 | ||
|
|
67389c39fb | ||
|
|
c326103e6e | ||
|
|
c2120a16da | ||
|
|
258ad4352e | ||
|
|
435d3958f4 | ||
|
|
b0408ef5c6 | ||
|
|
1c41b0bc2f | ||
|
|
aa827f3042 | ||
|
|
f44f5964bb | ||
|
|
91ba93bd7a | ||
|
|
0abe4cefb4 | ||
|
|
bccd460f3b | ||
|
|
d1023004e1 | ||
|
|
04a5f9cb04 | ||
|
|
9818e2b550 | ||
|
|
fe43e3b89d | ||
|
|
e1f1ae041f | ||
|
|
5bcf26e324 | ||
|
|
5f47a8149f | ||
|
|
00b662b53a | ||
|
|
faf519ab1b | ||
|
|
fce73f6f17 | ||
|
|
887890baf5 | ||
|
|
c66b24feeb | ||
|
|
84c6f147ad | ||
|
|
0cdb0daa8c | ||
|
|
eee702f299 | ||
|
|
df65247325 | ||
|
|
1a174e75d3 | ||
|
|
9e1fd3454f | ||
|
|
3b1603cadf | ||
|
|
8803bac708 | ||
|
|
3a01eaa4a6 | ||
|
|
9f84c1c448 | ||
|
|
dda0390156 | ||
|
|
c74509dd5f | ||
|
|
f61bbb2ff4 | ||
|
|
e7f60161a3 | ||
|
|
ebec4fbc24 | ||
|
|
1d4105ae3d | ||
|
|
586d49f0c3 | ||
|
|
5b0fab0697 | ||
|
|
2b3359dff3 | ||
|
|
63203aa14c | ||
|
|
716a8329c2 | ||
|
|
dab0aec85e | ||
|
|
1f1ab017c0 | ||
|
|
b6912ef95e | ||
|
|
db54dca694 | ||
|
|
0e751b983c | ||
|
|
997b20a975 | ||
|
|
386f9c42c2 | ||
|
|
cfae06db65 | ||
|
|
44260b7b5c | ||
|
|
13063b957f | ||
|
|
ee05e12480 | ||
|
|
5538545fb0 | ||
|
|
bc1167c2c5 | ||
|
|
c57656e4c3 | ||
|
|
264400a984 | ||
|
|
408db4eb1d | ||
|
|
9347f223ef | ||
|
|
518aa30c9c | ||
|
|
6bbf1f9355 | ||
|
|
b221e4d445 | ||
|
|
580fccbfca | ||
|
|
045916efcc | ||
|
|
4f92482294 | ||
|
|
2f055a75a0 | ||
|
|
f0621207e3 | ||
|
|
d657bc4e3d | ||
|
|
a1fd07b27c | ||
|
|
52219c5f3f | ||
|
|
1a66461e07 | ||
|
|
d20df12168 | ||
|
|
668b429615 | ||
|
|
7db528be39 | ||
|
|
60f760ee49 | ||
|
|
884aaab751 | ||
|
|
e968560ea4 | ||
|
|
07caaa96e4 | ||
|
|
e8a679c280 | ||
|
|
bc885f1d08 | ||
|
|
f2f051d6de | ||
|
|
49a0bfccba | ||
|
|
0c1e60894f | ||
|
|
ace87ad7bb | ||
|
|
50f0097843 | ||
|
|
32a9466277 | ||
|
|
1ee3407946 | ||
|
|
f1120d7aa9 | ||
|
|
2e7d6b2f99 | ||
|
|
dfef929187 | ||
|
|
e78d9ad592 | ||
|
|
9f2948f595 | ||
|
|
198da910ed | ||
|
|
5f1bf9d9d6 | ||
|
|
798c4aef9a | ||
|
|
f80f5b3bda | ||
|
|
cbb07b0d67 | ||
|
|
7cc9921615 | ||
|
|
7555fe065e | ||
|
|
d977f4278e | ||
|
|
870e3ca893 | ||
|
|
213acaee3b | ||
|
|
58381496a2 | ||
|
|
5981e42aed | ||
|
|
3c9165d295 | ||
|
|
60d0ef93ac | ||
|
|
f45d5b0066 | ||
|
|
b71306480f | ||
|
|
0c7771ccc5 | ||
|
|
dc9df0a79a | ||
|
|
17cd49fbdc | ||
|
|
ad273adb78 | ||
|
|
150e7daf2d | ||
|
|
b004155e8f | ||
|
|
92eed3b33b | ||
|
|
fe7b77198c | ||
|
|
f51b775698 | ||
|
|
939dd5cb31 | ||
|
|
adcbe13ecd | ||
|
|
8976e53998 | ||
|
|
97dda6a4bb | ||
|
|
9e395eb883 | ||
|
|
60da59623e | ||
|
|
9752ea9ac3 | ||
|
|
279693078a | ||
|
|
19b93045a4 | ||
|
|
5231a09820 | ||
|
|
ab952e6103 | ||
|
|
a418771c04 | ||
|
|
b41590ce38 | ||
|
|
c7dde9499f | ||
|
|
528cbf62ec | ||
|
|
1be4b8bb5d | ||
|
|
c832fc9917 | ||
|
|
4797a94689 | ||
|
|
6948903084 | ||
|
|
94164611ae | ||
|
|
ae298e8902 | ||
|
|
3d8771ecb0 | ||
|
|
28db264e90 | ||
|
|
6af9fa4b81 | ||
|
|
60b4d05860 | ||
|
|
7b93839ed1 | ||
|
|
fdb11d7c06 | ||
|
|
5651847877 | ||
|
|
e1442290b6 | ||
|
|
c45b18cc75 | ||
|
|
bb2ad77987 | ||
|
|
68b1ffec19 | ||
|
|
bc2bb22673 | ||
|
|
83d707fc4b | ||
|
|
175b32e56c | ||
|
|
97b4a6553b | ||
|
|
4ade30e681 | ||
|
|
4e03b4f191 | ||
|
|
bfe1d1d4ca | ||
|
|
8918de85fd | ||
|
|
5e237aecae | ||
|
|
13291ad481 | ||
|
|
a47ee86bee | ||
|
|
62d703f967 | ||
|
|
b2c196e5c7 | ||
|
|
4be6a54bc0 | ||
|
|
8ce8476547 | ||
|
|
d82caf6bd4 | ||
|
|
8ea1e302c3 | ||
|
|
a8799efa94 | ||
|
|
0cfac4e021 | ||
|
|
f6c9642d72 | ||
|
|
5a07f9ddee | ||
|
|
9db75e91ac | ||
|
|
f288e00c37 | ||
|
|
c9edd31993 | ||
|
|
5a7780ab5f | ||
|
|
ac0fba99ad | ||
|
|
6f724a113c | ||
|
|
327cd4cb87 | ||
|
|
25de3a2590 | ||
|
|
06208a703a | ||
|
|
56afba6606 | ||
|
|
d65bbf2113 | ||
|
|
b8bfc9b732 | ||
|
|
cec3bad373 | ||
|
|
9312e3c7de | ||
|
|
43e7435c41 | ||
|
|
f34f5e41a4 | ||
|
|
47a70a536b | ||
|
|
bbeddfe522 | ||
|
|
28220310a5 | ||
|
|
3e82a0a259 | ||
|
|
c860ad23a0 | ||
|
|
4e36dd2943 | ||
|
|
13d77f1557 | ||
|
|
cc619f6b53 | ||
|
|
d425794665 | ||
|
|
32da1c8d58 | ||
|
|
830be1035b | ||
|
|
e9e45d0e29 | ||
|
|
d3ca265a25 | ||
|
|
244f0ffaf1 | ||
|
|
73f5c47fe2 | ||
|
|
e8b9600ddb | ||
|
|
d2c813ffac | ||
|
|
8e699f8243 | ||
|
|
3f6cdc829b | ||
|
|
c5c9ee92ac | ||
|
|
7f1fcc9cfc | ||
|
|
9de45c3be4 | ||
|
|
144a881ae5 | ||
|
|
4566690617 | ||
|
|
e8fe1590b6 | ||
|
|
25f4fd5a19 | ||
|
|
7b8c126aa1 | ||
|
|
86b3ff3099 | ||
|
|
fa9df4dc5e | ||
|
|
fbd22e7b94 | ||
|
|
e35411d90f | ||
|
|
be15e48074 | ||
|
|
2be1218aa3 | ||
|
|
c47aebdd2a | ||
|
|
f4d1632506 | ||
|
|
8bfe4374de | ||
|
|
4afe02cb21 | ||
|
|
115b967e5b | ||
|
|
ea4524024a | ||
|
|
4ff6cd9105 | ||
|
|
96c17d8292 | ||
|
|
bc6faaffc4 | ||
|
|
51e9839237 | ||
|
|
6115631746 | ||
|
|
ee005fbc8e | ||
|
|
e27d42935c | ||
|
|
9c99d65716 | ||
|
|
5b9469eed3 | ||
|
|
6805ac915b | ||
|
|
7148cf99f7 | ||
|
|
67a3fb8bf2 | ||
|
|
933b61f99f | ||
|
|
6c5c14f35f | ||
|
|
6a441d5013 | ||
|
|
6b46465c77 | ||
|
|
75388caeed | ||
|
|
2546930a1a | ||
|
|
135e29a3bb | ||
|
|
3b65a58f59 | ||
|
|
49cb931572 | ||
|
|
b7176d2204 | ||
|
|
5bf7d372f6 | ||
|
|
073775e461 | ||
|
|
fbf8f3dc68 | ||
|
|
e8c8cc550b | ||
|
|
87c3790fa8 | ||
|
|
0d9dcb2f4f | ||
|
|
6188185b22 | ||
|
|
f762bd5e25 | ||
|
|
b676264fca | ||
|
|
3640c3b66a | ||
|
|
5087d02fba | ||
|
|
2aa4340551 | ||
|
|
3b34895ae6 | ||
|
|
91cc84c4e6 | ||
|
|
797e53c5ba | ||
|
|
c714a12ad7 | ||
|
|
08ce9b09ec | ||
|
|
3152152ed9 | ||
|
|
544fea51b0 | ||
|
|
08ca9f9378 | ||
|
|
978f68b744 | ||
|
|
680896e4c4 | ||
|
|
975627af2e | ||
|
|
b208102b98 | ||
|
|
88a063434c | ||
|
|
bc0a8fcc1d | ||
|
|
3b4fe19dfb | ||
|
|
58cc108c0c | ||
|
|
d3085a4127 | ||
|
|
0fcc193197 | ||
|
|
75d4d2df8b | ||
|
|
28f2e8f24d | ||
|
|
f692e3ac73 | ||
|
|
bcb5f6f472 | ||
|
|
74fd4a3722 | ||
|
|
884bb638bc | ||
|
|
3388d5b49c | ||
|
|
4fe2992924 | ||
|
|
0a804e39a8 | ||
|
|
f88a7a8e6a | ||
|
|
ec212f73eb | ||
|
|
91cc0cd05e | ||
|
|
7943902d73 | ||
|
|
32a5e83612 | ||
|
|
8b349945de | ||
|
|
fccdd85cc1 | ||
|
|
bd2b5db8f3 | ||
|
|
44bc5fd784 | ||
|
|
45dfd616cb | ||
|
|
39a691a7e6 | ||
|
|
35b5999cba | ||
|
|
d812f559ef | ||
|
|
54a1f37bf5 | ||
|
|
b0f46beffb | ||
|
|
c844991cba | ||
|
|
b7cf8a471f | ||
|
|
864bb8bc34 | ||
|
|
2d4b89a8e9 | ||
|
|
a6d67d30f5 | ||
|
|
0a633c526f | ||
|
|
655acb4cb2 | ||
|
|
91b35118d9 | ||
|
|
c64321df47 | ||
|
|
3f791b57ce | ||
|
|
8de2a7f4c8 | ||
|
|
dbb4b67205 | ||
|
|
f510f5f205 | ||
|
|
620eeae4a7 | ||
|
|
50b37f1366 | ||
|
|
a7b6e35467 | ||
|
|
4cf04a3e0d | ||
|
|
27cd6e60f4 | ||
|
|
2b9fc0fd43 | ||
|
|
d6c058c407 | ||
|
|
8fe5438b59 | ||
|
|
e937e51476 | ||
|
|
b7ea695caf | ||
|
|
31350b4352 | ||
|
|
37d83a4e2e | ||
|
|
4a88d1244d | ||
|
|
439049f672 | ||
|
|
ee10295d04 | ||
|
|
2d272a3cac | ||
|
|
2b26891062 | ||
|
|
3d7d4d845a | ||
|
|
c488179783 | ||
|
|
cfb33321b0 | ||
|
|
193cea95ce | ||
|
|
3c4002e149 | ||
|
|
a720f90a70 | ||
|
|
4a6b43bcae | ||
|
|
2f5a822ca4 | ||
|
|
bc1d04f0b9 | ||
|
|
381795d6d0 | ||
|
|
6ade27641d | ||
|
|
53898d2c60 | ||
|
|
91c4ff6009 | ||
|
|
0aa067a726 | ||
|
|
67445a6dda | ||
|
|
5353659f9f | ||
|
|
7ac00e189b | ||
|
|
071f4c0769 | ||
|
|
b57f4ed97e | ||
|
|
7633b9672f | ||
|
|
4f6ee7c8eb | ||
|
|
d7cc48eab2 | ||
|
|
8f3effed32 | ||
|
|
fee8289c0a | ||
|
|
a2da31056b | ||
|
|
f97dd9d8d3 | ||
|
|
2383579a64 | ||
|
|
68750211ef | ||
|
|
db3e3ade80 | ||
|
|
e6f04ed238 | ||
|
|
a6eb690e31 | ||
|
|
21518adfc8 | ||
|
|
77fe8449ba | ||
|
|
33e9a35f08 | ||
|
|
4ab4816556 | ||
|
|
8e8a579bb2 | ||
|
|
efbdf72d20 | ||
|
|
0e59b5678a | ||
|
|
de75550415 | ||
|
|
4dbce32738 | ||
|
|
b05fcbc9d7 | ||
|
|
d09c71b688 | ||
|
|
874d6760d4 | ||
|
|
26ebbee877 | ||
|
|
12eda0449a | ||
|
|
5a98f4e47c | ||
|
|
964c903a68 | ||
|
|
21b699826d | ||
|
|
5fa8f8e50c | ||
|
|
9ca87f5314 | ||
|
|
537c6b3b69 | ||
|
|
48a3fac2da | ||
|
|
fd73682806 | ||
|
|
34bd5b9dcf | ||
|
|
58c5e46206 | ||
|
|
4c61ab0f18 | ||
|
|
f241b63e0e | ||
|
|
2ffdb5a82a | ||
|
|
46e963443d | ||
|
|
66d4e9e5d7 | ||
|
|
de382e33a3 | ||
|
|
3c6738da73 | ||
|
|
18e5cb6793 | ||
|
|
9cd6b85c09 | ||
|
|
f40f3b3b7b | ||
|
|
7454670b0a | ||
|
|
e63596681d | ||
|
|
3dbaa76dcb | ||
|
|
8752003b50 | ||
|
|
8716ed5aa4 | ||
|
|
38ac4e8f79 | ||
|
|
70fc8a3064 | ||
|
|
7626c5d526 | ||
|
|
7e04c9d048 | ||
|
|
9eda8f2c7e | ||
|
|
456d9e870d | ||
|
|
a1533696a5 | ||
|
|
92499af323 | ||
|
|
b2988cdd35 | ||
|
|
82cfd37263 | ||
|
|
df381fd03f | ||
|
|
5a2328d9a5 | ||
|
|
b2f66cfb60 | ||
|
|
6d24e4f122 | ||
|
|
2e2185165c | ||
|
|
f0612e57c2 | ||
|
|
e5d16ed08a | ||
|
|
1cff9ccc63 | ||
|
|
20a018db2e | ||
|
|
80c2b32b92 | ||
|
|
028e9bc17a | ||
|
|
afc2d6fda4 | ||
|
|
bec5c76631 | ||
|
|
d87051ca99 | ||
|
|
3798cebad0 | ||
|
|
a477989950 | ||
|
|
5065d1d0b4 | ||
|
|
829990c9ef | ||
|
|
ac037e0fa3 | ||
|
|
da42d51008 | ||
|
|
99027813ef | ||
|
|
9112ba8f0b | ||
|
|
843fd9bdbd | ||
|
|
26c33c4a69 | ||
|
|
2db76ae786 | ||
|
|
a0b15d006d | ||
|
|
23b27fa24a | ||
|
|
b6f580cbc2 | ||
|
|
f2459ef331 | ||
|
|
0a37fac794 | ||
|
|
2d9a822ed7 | ||
|
|
98622ca4d0 | ||
|
|
f7a25adcbd | ||
|
|
9bf13b253c | ||
|
|
2e8b639a34 | ||
|
|
672f7a010f | ||
|
|
37e15c4368 | ||
|
|
4d7837ba96 | ||
|
|
a6c8423905 | ||
|
|
832ed556d9 | ||
|
|
7c6fb018ca | ||
|
|
9c5c06bf31 | ||
|
|
61e3daaead | ||
|
|
9c0fde795e | ||
|
|
ce4f565e2f | ||
|
|
5369a62fd5 | ||
|
|
b44016ff70 | ||
|
|
9f76c87880 | ||
|
|
42ae2898e1 | ||
|
|
dd649a6be4 | ||
|
|
593f098276 | ||
|
|
4a87221f16 | ||
|
|
7745ed34d3 | ||
|
|
8fe546c4a2 | ||
|
|
381f6aeaf6 | ||
|
|
9154bacced | ||
|
|
dc0dc8efb4 | ||
|
|
b062d5dd7f | ||
|
|
c519e582b5 | ||
|
|
6b9dce36bf | ||
|
|
8e0520887a | ||
|
|
cfd1fdb38e | ||
|
|
c6ba0208d0 | ||
|
|
3d055bbb79 | ||
|
|
dd971b56e5 | ||
|
|
4031f5e24b | ||
|
|
1cd7cc6869 | ||
|
|
9de2864db3 | ||
|
|
c27861cbaf | ||
|
|
c2f75d3689 | ||
|
|
5454ca1cf7 | ||
|
|
8644bf30a9 | ||
|
|
db3341a178 | ||
|
|
e2cb0219c7 | ||
|
|
217f29de76 | ||
|
|
8661afcb4f | ||
|
|
ed07fc0f2c | ||
|
|
4af3f77a9a | ||
|
|
8c4f07ef1b | ||
|
|
1a231d39a5 | ||
|
|
17e3d14272 | ||
|
|
03182c7714 | ||
|
|
963078f6ac | ||
|
|
8356b58b1d | ||
|
|
303ce02271 | ||
|
|
bcdc3ecdae | ||
|
|
b60d648e22 | ||
|
|
7bc36cbbd1 | ||
|
|
04130fcb15 | ||
|
|
52d8e4c691 | ||
|
|
ae0193b724 | ||
|
|
2e1c33206f | ||
|
|
0c642ec7cf | ||
|
|
b3ca96eeba | ||
|
|
ae0e033178 | ||
|
|
a97985b428 | ||
|
|
63c0f11458 | ||
|
|
5b0dd9d3b2 | ||
|
|
8bba82a08d | ||
|
|
51bf15728a | ||
|
|
b336b2c336 | ||
|
|
2331089854 | ||
|
|
8a5a573851 | ||
|
|
6fb05fc82a | ||
|
|
358862c7ad | ||
|
|
4235175966 | ||
|
|
cd433a4f52 | ||
|
|
f3b550744f | ||
|
|
f31e5eaba2 | ||
|
|
7c8652b600 | ||
|
|
30837a7d95 | ||
|
|
3c25a74f3b | ||
|
|
da3177dbe0 | ||
|
|
3ca8dce98b | ||
|
|
e17fa7b14e | ||
|
|
230f149b4b | ||
|
|
dd3d8a6c98 | ||
|
|
36bdd9cb4d | ||
|
|
95f5e5fa9a | ||
|
|
1aef03288a | ||
|
|
a8c510cc72 | ||
|
|
e359b146aa | ||
|
|
dba40eefb1 | ||
|
|
23b55f68b7 | ||
|
|
5c65e10875 | ||
|
|
d7df11e724 | ||
|
|
c08ce5c571 | ||
|
|
12a6682eaf | ||
|
|
bbefcef53b | ||
|
|
729b0143e1 | ||
|
|
84c4298cd5 | ||
|
|
7d672fd989 | ||
|
|
1442d6f4c2 | ||
|
|
13022817d4 | ||
|
|
e788a99c3e | ||
|
|
09d4b3f71e | ||
|
|
78f0f2b131 | ||
|
|
40c750141a | ||
|
|
b60251b960 | ||
|
|
958c39ef5f | ||
|
|
e22ddae3a8 | ||
|
|
68afc897d6 | ||
|
|
ba58e95f6b | ||
|
|
adbd0b1834 | ||
|
|
3e34fc66e6 | ||
|
|
f8e34c083e | ||
|
|
cba554d0fa | ||
|
|
8903825e02 | ||
|
|
81cd84add2 | ||
|
|
8229d47da5 | ||
|
|
8f14d11d66 | ||
|
|
76f82cbd1f | ||
|
|
dc2f83e522 | ||
|
|
8b4282fe28 | ||
|
|
c6416b235b | ||
|
|
79f2b3bd7e | ||
|
|
1f996afa21 | ||
|
|
21335d65c4 | ||
|
|
870ce57005 | ||
|
|
0d3caa2183 | ||
|
|
602d7e8d18 | ||
|
|
a2309f3119 | ||
|
|
9a51be8548 | ||
|
|
5ed319ea42 | ||
|
|
eb7a70a3c9 | ||
|
|
b61f418bf2 | ||
|
|
1338b0a2f8 | ||
|
|
587e1a4f4c | ||
|
|
85d5449b3c | ||
|
|
532b576fd5 | ||
|
|
dd1197236d | ||
|
|
e8a9abaf40 | ||
|
|
1bf07d6b58 | ||
|
|
30ea9cb37e | ||
|
|
bae9247d84 | ||
|
|
a105ad1391 | ||
|
|
abbb40abd2 | ||
|
|
20b23338f7 | ||
|
|
0fcbee6478 | ||
|
|
1d602b9efa | ||
|
|
b783169c72 | ||
|
|
e4f266883a | ||
|
|
7a41362d90 | ||
|
|
3ed783983f | ||
|
|
837f3a68ab | ||
|
|
59e45c5c68 | ||
|
|
94761d0472 | ||
|
|
a91eb701bf | ||
|
|
1a1f118f1a | ||
|
|
b115fca8a9 | ||
|
|
dfd239ac06 | ||
|
|
2ae218d069 | ||
|
|
1401d2ee9b | ||
|
|
f39e105101 | ||
|
|
482795bab0 | ||
|
|
10e8861f14 | ||
|
|
ecc6476308 | ||
|
|
28e347002a | ||
|
|
b3d19bd5cc | ||
|
|
647165ab89 | ||
|
|
6807d9bd4c | ||
|
|
699ecc7140 | ||
|
|
b374ec9355 | ||
|
|
9659d021cb | ||
|
|
a4ad9eb134 | ||
|
|
a455258a62 | ||
|
|
0ae342673a | ||
|
|
33d75a264d | ||
|
|
89dc5bb951 | ||
|
|
45403917de | ||
|
|
ed476271a6 | ||
|
|
1e92c47960 | ||
|
|
4f2fe07ae4 | ||
|
|
aff3cd01c5 | ||
|
|
ac74ee1468 | ||
|
|
0d55cf4be5 | ||
|
|
5399a25532 | ||
|
|
ae882c93c9 | ||
|
|
f398ca77c1 | ||
|
|
dcd7d278aa | ||
|
|
89f5f3bf9a | ||
|
|
76ef42ee07 | ||
|
|
92c1ce57a6 | ||
|
|
116f232f5a | ||
|
|
ef81a36654 | ||
|
|
9fd2724d73 | ||
|
|
07d49b61d0 | ||
|
|
0c4e6ae7de | ||
|
|
65ec129dfb | ||
|
|
3e4d628f54 | ||
|
|
71684bfa45 | ||
|
|
e73b7e0398 | ||
|
|
35ebdc76ff | ||
|
|
90d0896848 | ||
|
|
5528db9693 | ||
|
|
aa78fbb09d | ||
|
|
d53b193e09 | ||
|
|
e0e16c371f | ||
|
|
53cd877899 | ||
|
|
1207223f3d | ||
|
|
39be6932b5 | ||
|
|
44a194d226 | ||
|
|
9349eb77cd | ||
|
|
c64549471a | ||
|
|
264bcbc78c | ||
|
|
f76fe1ac7a | ||
|
|
6364c4ff3f | ||
|
|
292a50de04 | ||
|
|
a08cba9c85 | ||
|
|
9fb60d6935 | ||
|
|
f2ed2d98d8 | ||
|
|
b802cb1e36 | ||
|
|
31bfd8c039 | ||
|
|
f72ee7a69e | ||
|
|
a98d75edaa | ||
|
|
622568c327 | ||
|
|
1ca7e47fd6 | ||
|
|
116203aef8 | ||
|
|
1bf128612d | ||
|
|
935a8eb9a7 | ||
|
|
7e5b350096 | ||
|
|
5c75869e85 | ||
|
|
fbd5ddea72 | ||
|
|
bc8e033eb5 | ||
|
|
70fa5ffa06 | ||
|
|
fb162ff529 | ||
|
|
9d535b13cf | ||
|
|
48bfc2d9ed | ||
|
|
5064f846fc | ||
|
|
41c228cb56 | ||
|
|
e974c8f33e | ||
|
|
94f5d5b59e | ||
|
|
433a0cb9cc | ||
|
|
c42a6b511c | ||
|
|
346b6f4f11 | ||
|
|
07eb4020bd | ||
|
|
c2f0c2225a | ||
|
|
711587492c | ||
|
|
536613f008 | ||
|
|
c832fc7d1b | ||
|
|
0b654581b6 | ||
|
|
cbae64fc06 | ||
|
|
1443a1388e | ||
|
|
a203d99182 | ||
|
|
bc5ff6e1b6 | ||
|
|
3b3c0c5950 | ||
|
|
ee0ee0e39d | ||
|
|
8dee10ba9c | ||
|
|
d3915b8dbf | ||
|
|
671d5cace6 | ||
|
|
aa3d73d322 | ||
|
|
d30a286f38 | ||
|
|
15699a39cf | ||
|
|
a1f32095df | ||
|
|
76e0960a51 | ||
|
|
8e33288156 | ||
|
|
f4d3a9980f | ||
|
|
fc8ce7c6e0 | ||
|
|
aaf0604601 | ||
|
|
dddf563105 | ||
|
|
dbe12cca4b | ||
|
|
ddf0ddbd05 | ||
|
|
5eb5a056bf | ||
|
|
2a5c0646c0 | ||
|
|
7d3c51df9e | ||
|
|
a67bb5e720 | ||
|
|
6d314cdc04 | ||
|
|
1139ea2c81 | ||
|
|
f87b1520e8 | ||
|
|
3700eb1e61 | ||
|
|
17a21102b3 | ||
|
|
e37441627f | ||
|
|
f4c6cd1676 | ||
|
|
bcd3fd40e4 | ||
|
|
d3d1a79996 | ||
|
|
fb4a2c9b5a | ||
|
|
ff18a2c3e2 | ||
|
|
589244f39e | ||
|
|
804cce7ba0 | ||
|
|
6d7b001b0b | ||
|
|
75cfa4c33e | ||
|
|
145c8e4063 | ||
|
|
52cad94e86 | ||
|
|
89399092b9 | ||
|
|
168b23556a | ||
|
|
513100bb92 | ||
|
|
68d9454bc4 | ||
|
|
a4e56caf78 | ||
|
|
a84ea70387 | ||
|
|
25acc0e445 | ||
|
|
16e1a4397a | ||
|
|
8db1bf9732 | ||
|
|
58fd379e35 | ||
|
|
222272b75c | ||
|
|
ef8cf3bc30 | ||
|
|
a48bf50608 | ||
|
|
60ae665c0f | ||
|
|
2df78a9313 | ||
|
|
d2d32f26c7 | ||
|
|
473df1bd19 | ||
|
|
880f417ae3 | ||
|
|
043fa7f489 | ||
|
|
9b0768a71b | ||
|
|
446b21c568 | ||
|
|
b3c2ffc96a | ||
|
|
b5f652a815 | ||
|
|
9ec7de643e | ||
|
|
2553ba0463 | ||
|
|
52ee7d5724 | ||
|
|
d4ef6a6285 | ||
|
|
56b7d3c28d | ||
|
|
ae94b726a7 | ||
|
|
a88e4db1ee | ||
|
|
0ebd4a6ba1 | ||
|
|
1448cfe66a | ||
|
|
d6c9afd07f | ||
|
|
799f55e7ae | ||
|
|
04a3db132f | ||
|
|
d06204959e | ||
|
|
2d0600de38 | ||
|
|
6a1c055288 | ||
|
|
b9ec30ebdb | ||
|
|
428164f395 | ||
|
|
ba59e0d3f0 | ||
|
|
5d8f0f835e | ||
|
|
b4a1aadd1b | ||
|
|
8f41d90ab1 | ||
|
|
9743386166 | ||
|
|
0afcb5b7e7 | ||
|
|
043dea760f | ||
|
|
0618e2b9b4 | ||
|
|
3c171d281c | ||
|
|
c217b7cd22 | ||
|
|
23593c3d20 | ||
|
|
192117dc11 | ||
|
|
24b8f9211a | ||
|
|
51788d6f0e | ||
|
|
ea0bed2238 | ||
|
|
e2fe57c440 | ||
|
|
434a0ccf2a | ||
|
|
e7bf3ac108 | ||
|
|
c5bdaebf2b |
9
.gitattributes
vendored
Normal file
9
.gitattributes
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
# Text files use LF line endings in this repository
|
||||
* text=auto
|
||||
|
||||
# Except the dependencies, which we leave alone
|
||||
Godeps/** -text=auto
|
||||
|
||||
# Diffs on these files are meaningless
|
||||
gui.files.go -diff
|
||||
*.svg -diff
|
||||
15
.gitignore
vendored
15
.gitignore
vendored
@@ -1,3 +1,16 @@
|
||||
syncthing
|
||||
!gui/syncthing
|
||||
!Godeps/_workspace/src/github.com/syncthing
|
||||
syncthing.exe
|
||||
*.tar.gz
|
||||
dist
|
||||
*.zip
|
||||
*.asc
|
||||
.jshintrc
|
||||
coverage.out
|
||||
files/pidx
|
||||
bin
|
||||
perfstats*.csv
|
||||
coverage.xml
|
||||
syncthing.sig
|
||||
RELEASE
|
||||
deb
|
||||
|
||||
84
AUTHORS
Normal file
84
AUTHORS
Normal file
@@ -0,0 +1,84 @@
|
||||
# This is the official list of Syncthing authors for copyright purposes.
|
||||
|
||||
Aaron Bieber <qbit@deftly.net>
|
||||
Adam Piggott <aD@simplypeachy.co.uk> <simplypeachy@users.noreply.github.com>
|
||||
Alessandro G. <alessandro.g89@gmail.com>
|
||||
Alexander Graf <register-github@alex-graf.de>
|
||||
Anderson Mesquita <andersonvom@gmail.com>
|
||||
Andrew Dunham <andrew@du.nham.ca>
|
||||
Antony Male <antony.male@gmail.com>
|
||||
Arthur Axel fREW Schmidt <frew@afoolishmanifesto.com> <frioux@gmail.com>
|
||||
Audrius Butkevicius <audrius.butkevicius@gmail.com>
|
||||
Bart De Vries <devriesb@gmail.com>
|
||||
Ben Curthoys <ben@bencurthoys.com>
|
||||
Ben Schulz <ueomkail@gmail.com> <uok@users.noreply.github.com>
|
||||
Ben Sidhom <bsidhom@gmail.com>
|
||||
Benny Ng <benny.tpng@gmail.com>
|
||||
Brandon Philips <brandon@ifup.org>
|
||||
Brendan Long <self@brendanlong.com>
|
||||
Brian R. Becker <brbecker@gmail.com>
|
||||
Caleb Callaway <enlightened.despot@gmail.com>
|
||||
Carsten Hagemann <moter8@gmail.com>
|
||||
Cathryne Linenweaver <cathryne.linenweaver@gmail.com> <Cathryne@users.noreply.github.com>
|
||||
Chris Howie <me@chrishowie.com>
|
||||
Chris Joel <chris@scriptolo.gy>
|
||||
Colin Kennedy <moshen.colin@gmail.com>
|
||||
Daniel Bergmann <dan.arne.bergmann@gmail.com> <brgmnn@users.noreply.github.com>
|
||||
Daniel Martí <mvdan@mvdan.cc>
|
||||
Denis A. <denisva@gmail.com>
|
||||
Dennis Wilson <dw@risu.io>
|
||||
Dominik Heidler <dominik@heidler.eu>
|
||||
Elias Jarlebring <jarlebring@gmail.com>
|
||||
Emil Hessman <emil@hessman.se>
|
||||
Erik Meitner <e.meitner@willystreet.coop>
|
||||
Federico Castagnini <federico.castagnini@gmail.com>
|
||||
Felix Ableitner <me@nutomic.com>
|
||||
Felix Unterpaintner <bigbear2nd@gmail.com>
|
||||
Francois-Xavier Gsell <fxgsell@gmail.com>
|
||||
Frank Isemann <frank@isemann.name>
|
||||
Gilli Sigurdsson <gilli@vx.is>
|
||||
Jaakko Hannikainen <jgke@jgke.fi>
|
||||
Jacek Szafarkiewicz <szafar@linux.pl>
|
||||
Jake Peterson <jake@acogdev.com>
|
||||
Jakob Borg <jakob@nym.se>
|
||||
James Patterson <jamespatterson@operamail.com> <jpjp@users.noreply.github.com>
|
||||
Jaroslav Malec <dzardacz@gmail.com>
|
||||
Jens Diemer <github.com@jensdiemer.de> <git@jensdiemer.de>
|
||||
Jochen Voss <voss@seehuhn.de>
|
||||
Johan Vromans <jvromans@squirrel.nl>
|
||||
Karol Różycki <rozycki.karol@gmail.com>
|
||||
Ken'ichi Kamada <kamada@nanohz.org>
|
||||
Kevin Allen <kma1660@gmail.com>
|
||||
Laurent Etiemble <laurent.etiemble@gmail.com> <laurent.etiemble@monobjc.net>
|
||||
Lode Hoste <zillode@zillode.be>
|
||||
Lord Landon Agahnim <lordlandon@gmail.com>
|
||||
Marc Laporte <marc@marclaporte.com> <marc@laporte.name>
|
||||
Marc Pujol <kilburn@la3.org>
|
||||
Marcin Dziadus <dziadus.marcin@gmail.com>
|
||||
Mateusz Naściszewski <matin1111@wp.pl>
|
||||
Matt Burke <mburke@amplify.com> <burkemw3@gmail.com>
|
||||
Max Schulze <max.schulze@online.de> <kralo@users.noreply.github.com>
|
||||
Michael Jephcote <rewt0r@gmx.com> <Rewt0r@users.noreply.github.com>
|
||||
Michael Ploujnikov <ploujj@gmail.com>
|
||||
Michael Tilli <pyfisch@gmail.com>
|
||||
Nate Morrison <natemorrison@gmail.com>
|
||||
Pascal Jungblut <github@pascalj.com> <mail@pascal-jungblut.com>
|
||||
Peter Hoeg <peter@speartail.com>
|
||||
Philippe Schommers <philippe@schommers.be>
|
||||
Phill Luby <phill.luby@newredo.com>
|
||||
Piotr Bejda <piotrb10@gmail.com>
|
||||
Ryan Sullivan <kayoticsully@gmail.com>
|
||||
Scott Klupfel <kluppy@going2blue.com>
|
||||
Sergey Mishin <ralder@yandex.ru>
|
||||
Stefan Kuntz <stefan.github@gmail.com> <Stefan.github@gmail.com>
|
||||
Stefan Tatschner <stefan@sevenbyte.org> <rumpelsepp@sevenbyte.org>
|
||||
Tim Abell <tim@timwise.co.uk>
|
||||
Tobias Nygren <tnn@nygren.pp.se>
|
||||
Tomas Cerveny <kozec@kozec.com>
|
||||
Tully Robinson <tully@tojr.org>
|
||||
Tyler Brazier <tyler@tylerbrazier.com>
|
||||
Veeti Paananen <veeti.paananen@rojekti.fi>
|
||||
Victor Buinsky <vix_booja@tut.by>
|
||||
Vil Brekin <vilbrekin@gmail.com>
|
||||
William A. Kennington III <william@wkennington.com>
|
||||
Yannic A. <eipiminusone+github@gmail.com> <eipiminus1@users.noreply.github.com>
|
||||
92
CONDUCT.md
Normal file
92
CONDUCT.md
Normal file
@@ -0,0 +1,92 @@
|
||||
## Conduct
|
||||
|
||||
* We are committed to providing a friendly, safe and welcoming
|
||||
environment for all, regardless of gender, sexual orientation,
|
||||
disability, ethnicity, religion, or similar personal characteristic.
|
||||
|
||||
* On IRC, please avoid using overtly sexual nicknames or other nicknames
|
||||
that might detract from a friendly, safe and welcoming environment for
|
||||
all.
|
||||
|
||||
* Please be kind and courteous. There's no need to be mean or rude.
|
||||
|
||||
* Respect that people have differences of opinion and that every design
|
||||
or implementation choice carries a trade-off and numerous costs. There
|
||||
is seldom a right answer.
|
||||
|
||||
* Please keep unstructured critique to a minimum. If you have solid
|
||||
ideas you want to experiment with, make a fork and see how it works.
|
||||
|
||||
* We will exclude you from interaction if you insult, demean or harass
|
||||
anyone. That is not welcome behaviour. We interpret the term
|
||||
"harassment" as including the definition in the <a
|
||||
href="http://citizencodeofconduct.org/">Citizen Code of Conduct</a>;
|
||||
if you have any lack of clarity about what might be included in that
|
||||
concept, please read their definition. In particular, we don't
|
||||
tolerate behavior that excludes people in socially marginalized
|
||||
groups.
|
||||
|
||||
* Private harassment is also unacceptable. No matter who you are, if you
|
||||
feel you have been or are being harassed or made uncomfortable by a
|
||||
community member, please contact one of the channel ops or any of the
|
||||
Syncthing core team immediately. Whether you're a regular contributor
|
||||
or a newcomer, we care about making this community a safe place for
|
||||
you and we've got your back.
|
||||
|
||||
* Likewise any spamming, trolling, flaming, baiting or other
|
||||
attention-stealing behaviour is not welcome.
|
||||
|
||||
## Moderation
|
||||
|
||||
These are the policies for upholding our community's standards of
|
||||
conduct in our communication channels, most notably in Syncthing-related
|
||||
IRC channels and on the web forum.
|
||||
|
||||
1. Remarks that violate the Syncthing standards of conduct, including
|
||||
hateful, hurtful, oppressive, or exclusionary remarks, are not
|
||||
allowed. (Cursing is allowed, but never targeting another user, and
|
||||
never in a hateful manner.)
|
||||
|
||||
2. Remarks that moderators find inappropriate, whether listed in the
|
||||
code of conduct or not, are also not allowed.
|
||||
|
||||
3. Moderators will first respond to such remarks with a warning.
|
||||
|
||||
4. If the warning is unheeded, the user will be "kicked," i.e., kicked
|
||||
out of the communication channel to cool off.
|
||||
|
||||
5. If the user comes back and continues to make trouble, they will be
|
||||
banned, i.e., indefinitely excluded.
|
||||
|
||||
6. Moderators may choose at their discretion to un-ban the user if it
|
||||
was a first offense and they offer the offended party a genuine
|
||||
apology.
|
||||
|
||||
7. If a moderator bans someone and you think it was unjustified, please
|
||||
take it up with that moderator, or with a different moderator, **in
|
||||
private**. Complaints about bans in-channel are not allowed.
|
||||
|
||||
8. Moderators are held to a higher standard than other community
|
||||
members. If a moderator creates an inappropriate situation, they
|
||||
should expect less leeway than others.
|
||||
|
||||
In the Syncthing community we strive to go the extra step to look out
|
||||
for each other. Don't just aim to be technically unimpeachable, try to
|
||||
be your best self. In particular, avoid flirting with offensive or
|
||||
sensitive issues, particularly if they're off-topic; this all too
|
||||
often leads to unnecessary fights, hurt feelings, and damaged trust;
|
||||
worse, it can drive people away from the community entirely.
|
||||
|
||||
And if someone takes issue with something you said or did, resist the
|
||||
urge to be defensive. Just stop doing what it was they complained about
|
||||
and apologize. Even if you feel you were misinterpreted or unfairly
|
||||
accused, chances are good there was something you could've communicated
|
||||
better — remember that it's your responsibility to make your fellow
|
||||
community members comfortable. Everyone wants to get along and we are
|
||||
all here first and foremost because we want to talk about cool
|
||||
technology. You will find that people will be eager to assume good
|
||||
intent and forgive as long as you earn their trust.
|
||||
|
||||
*Adapted from the [Rust Code of Conduct](https://github.com/rust-lang/rust/wiki/Note-development-policy#conduct)*
|
||||
|
||||
*Adapted from the [Node.js Policy on Trolling](http://blog.izs.me/post/30036893703/policy-on-trolling)*
|
||||
@@ -1,22 +1,52 @@
|
||||
Please do contribute!
|
||||
## Reporting Bugs
|
||||
|
||||
## Building
|
||||
Please file bugs in the [Github Issue
|
||||
Tracker](https://github.com/syncthing/syncthing/issues). Include at
|
||||
least the following:
|
||||
|
||||
[See the wiki](https://github.com/calmh/syncthing/wiki/Building)
|
||||
- What happened
|
||||
|
||||
## Tests
|
||||
- What did you expect to happen instead of what *did* happen, if it's
|
||||
not crazy obvious
|
||||
|
||||
Yes please!
|
||||
- What operating system, operating system version and version of
|
||||
Syncthing you are running
|
||||
|
||||
## Style
|
||||
- The same for other connected devices, where relevant
|
||||
|
||||
`go fmt`
|
||||
- Screenshot if the issue concerns something visible in the GUI
|
||||
|
||||
## Documentation
|
||||
- Console log entries, where possible and relevant
|
||||
|
||||
[Hack it here](https://github.com/calmh/syncthing/wiki)
|
||||
If you're not sure whether something is relevant, erring on the side of
|
||||
too much information will never get you yelled at. :)
|
||||
|
||||
## License
|
||||
## Contributing Translations
|
||||
|
||||
MIT
|
||||
All translations are done via
|
||||
[Transifex](https://www.transifex.com/projects/p/syncthing/). If you
|
||||
wish to contribute to a translation, just head over there and sign up.
|
||||
Before every release, the language resources are updated from the
|
||||
latest info on Transifex.
|
||||
|
||||
## Contributing Code
|
||||
|
||||
Every contribution is welcome. If you want to contribute but are unsure
|
||||
where to start, any open issues are fair game! See the [Contribution
|
||||
Guidelines](http://docs.syncthing.net/dev/contributing.html) for the full
|
||||
story on committing code.
|
||||
|
||||
## Contributing Documentation
|
||||
|
||||
Updates to the [documentation site](http://docs.syncthing.net/) can be
|
||||
made as pull requests on the [documentation
|
||||
repository](https://github.com/syncthing/docs).
|
||||
|
||||
## Licensing
|
||||
|
||||
All contributions are made under the same MPLv2 license as the rest of
|
||||
the project, except documentation, user interface text and translation
|
||||
strings which are licensed under the Creative Commons Attribution 4.0
|
||||
International License. You retain the copyright to code you have
|
||||
written.
|
||||
|
||||
|
||||
90
Godeps/Godeps.json
generated
Normal file
90
Godeps/Godeps.json
generated
Normal file
@@ -0,0 +1,90 @@
|
||||
{
|
||||
"ImportPath": "github.com/syncthing/syncthing",
|
||||
"GoVersion": "go1.5.2",
|
||||
"Packages": [
|
||||
"./cmd/..."
|
||||
],
|
||||
"Deps": [
|
||||
{
|
||||
"ImportPath": "github.com/bkaradzic/go-lz4",
|
||||
"Rev": "74ddf82598bc4745b965729e9c6a463bedd33049"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/calmh/du",
|
||||
"Rev": "3c0690cca16228b97741327b1b6781397afbdb24"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/calmh/luhn",
|
||||
"Rev": "0c8388ff95fa92d4094011e5a04fc99dea3d1632"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/calmh/xdr",
|
||||
"Rev": "9eb3e1a622d9364deb39c831f7e5f164393d7e37"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/golang/snappy",
|
||||
"Rev": "723cc1e459b8eea2dea4583200fd60757d40097a"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/juju/ratelimit",
|
||||
"Rev": "772f5c38e468398c4511514f4f6aa9a4185bc0a0"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/kardianos/osext",
|
||||
"Rev": "29ae4ffbc9a6fe9fb2bc5029050ce6996ea1d3bc"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/rcrowley/go-metrics",
|
||||
"Rev": "1ce93efbc8f9c568886b2ef85ce305b2217b3de3"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/syndtr/goleveldb/leveldb",
|
||||
"Rev": "1a9d62f03ea92815b46fcaab357cfd4df264b1a0"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/thejerf/suture",
|
||||
"Comment": "v1.0.1",
|
||||
"Rev": "99c1f2d613756768fc4299acd9dc621e11ed3fd7"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/vitrun/qart/coding",
|
||||
"Rev": "ccb109cf25f0cd24474da73b9fee4e7a3e8a8ce0"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/vitrun/qart/gf256",
|
||||
"Rev": "ccb109cf25f0cd24474da73b9fee4e7a3e8a8ce0"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/vitrun/qart/qr",
|
||||
"Rev": "ccb109cf25f0cd24474da73b9fee4e7a3e8a8ce0"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/crypto/bcrypt",
|
||||
"Rev": "575fdbe86e5dd89229707ebec0575ce7d088a4a6"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/crypto/blowfish",
|
||||
"Rev": "575fdbe86e5dd89229707ebec0575ce7d088a4a6"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/net/internal/iana",
|
||||
"Rev": "042ba42fa6633b34205efc66ba5719cd3afd8d38"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/net/ipv6",
|
||||
"Rev": "042ba42fa6633b34205efc66ba5719cd3afd8d38"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/net/proxy",
|
||||
"Rev": "042ba42fa6633b34205efc66ba5719cd3afd8d38"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/text/transform",
|
||||
"Rev": "5eb8d4684c4796dd36c74f6452f2c0fa6c79597e"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/text/unicode/norm",
|
||||
"Rev": "5eb8d4684c4796dd36c74f6452f2c0fa6c79597e"
|
||||
}
|
||||
]
|
||||
}
|
||||
5
Godeps/Readme
generated
Normal file
5
Godeps/Readme
generated
Normal file
@@ -0,0 +1,5 @@
|
||||
This directory tree is generated automatically by godep.
|
||||
|
||||
Please do not edit.
|
||||
|
||||
See https://github.com/tools/godep for more information.
|
||||
2
Godeps/_workspace/.gitignore
generated
vendored
Normal file
2
Godeps/_workspace/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/pkg
|
||||
/bin
|
||||
1
Godeps/_workspace/src/github.com/bkaradzic/go-lz4/.gitignore
generated
vendored
Normal file
1
Godeps/_workspace/src/github.com/bkaradzic/go-lz4/.gitignore
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/lz4-example/lz4-example
|
||||
9
Godeps/_workspace/src/github.com/bkaradzic/go-lz4/.travis.yml
generated
vendored
Normal file
9
Godeps/_workspace/src/github.com/bkaradzic/go-lz4/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.1
|
||||
- 1.2
|
||||
- 1.3
|
||||
- 1.4
|
||||
- 1.5
|
||||
- tip
|
||||
24
Godeps/_workspace/src/github.com/bkaradzic/go-lz4/LICENSE
generated
vendored
Normal file
24
Godeps/_workspace/src/github.com/bkaradzic/go-lz4/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
Copyright 2011-2012 Branimir Karadzic. All rights reserved.
|
||||
Copyright 2013 Damian Gryski. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
71
Godeps/_workspace/src/github.com/bkaradzic/go-lz4/README.md
generated
vendored
Normal file
71
Godeps/_workspace/src/github.com/bkaradzic/go-lz4/README.md
generated
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
go-lz4
|
||||
======
|
||||
|
||||
go-lz4 is port of LZ4 lossless compression algorithm to Go. The original C code
|
||||
is located at:
|
||||
|
||||
https://github.com/Cyan4973/lz4
|
||||
|
||||
Status
|
||||
------
|
||||
[](http://travis-ci.org/bkaradzic/go-lz4)
|
||||
[](https://godoc.org/github.com/bkaradzic/go-lz4)
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
go get github.com/bkaradzic/go-lz4
|
||||
|
||||
import "github.com/bkaradzic/go-lz4"
|
||||
|
||||
The package name is `lz4`
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
||||
* go-lz4 saves a uint32 with the original uncompressed length at the beginning
|
||||
of the encoded buffer. They may get in the way of interoperability with
|
||||
other implementations.
|
||||
|
||||
Contributors
|
||||
------------
|
||||
|
||||
Damian Gryski ([@dgryski](https://github.com/dgryski))
|
||||
Dustin Sallings ([@dustin](https://github.com/dustin))
|
||||
|
||||
Contact
|
||||
-------
|
||||
|
||||
[@bkaradzic](https://twitter.com/bkaradzic)
|
||||
http://www.stuckingeometry.com
|
||||
|
||||
Project page
|
||||
https://github.com/bkaradzic/go-lz4
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
Copyright 2011-2012 Branimir Karadzic. All rights reserved.
|
||||
Copyright 2013 Damian Gryski. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
23
Godeps/_workspace/src/github.com/bkaradzic/go-lz4/fuzz.go
generated
vendored
Normal file
23
Godeps/_workspace/src/github.com/bkaradzic/go-lz4/fuzz.go
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
// +build gofuzz
|
||||
|
||||
package lz4
|
||||
|
||||
import "encoding/binary"
|
||||
|
||||
func Fuzz(data []byte) int {
|
||||
|
||||
if len(data) < 4 {
|
||||
return 0
|
||||
}
|
||||
|
||||
ln := binary.LittleEndian.Uint32(data)
|
||||
if ln > (1 << 21) {
|
||||
return 0
|
||||
}
|
||||
|
||||
if _, err := Decode(nil, data); err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
||||
74
Godeps/_workspace/src/github.com/bkaradzic/go-lz4/fuzzer/main.go
generated
vendored
Normal file
74
Godeps/_workspace/src/github.com/bkaradzic/go-lz4/fuzzer/main.go
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
|
||||
"github.com/bkaradzic/go-lz4"
|
||||
|
||||
// lz4's API matches snappy's, so we can easily see how it performs
|
||||
// lz4 "code.google.com/p/snappy-go/snappy"
|
||||
)
|
||||
|
||||
var input = `
|
||||
ADVENTURE I. A SCANDAL IN BOHEMIA
|
||||
|
||||
I.
|
||||
|
||||
To Sherlock Holmes she is always THE woman. I have seldom heard
|
||||
him mention her under any other name. In his eyes she eclipses
|
||||
and predominates the whole of her sex. It was not that he felt
|
||||
any emotion akin to love for Irene Adler. All emotions, and that
|
||||
one particularly, were abhorrent to his cold, precise but
|
||||
admirably balanced mind. He was, I take it, the most perfect
|
||||
reasoning and observing machine that the world has seen, but as a
|
||||
lover he would have placed himself in a false position. He never
|
||||
spoke of the softer passions, save with a gibe and a sneer. They
|
||||
were admirable things for the observer--excellent for drawing the
|
||||
veil from men's motives and actions. But for the trained reasoner
|
||||
to admit such intrusions into his own delicate and finely
|
||||
adjusted temperament was to introduce a distracting factor which
|
||||
might throw a doubt upon all his mental results. Grit in a
|
||||
sensitive instrument, or a crack in one of his own high-power
|
||||
lenses, would not be more disturbing than a strong emotion in a
|
||||
nature such as his. And yet there was but one woman to him, and
|
||||
that woman was the late Irene Adler, of dubious and questionable
|
||||
memory.
|
||||
|
||||
I had seen little of Holmes lately. My marriage had drifted us
|
||||
away from each other. My own complete happiness, and the
|
||||
home-centred interests which rise up around the man who first
|
||||
finds himself master of his own establishment, were sufficient to
|
||||
absorb all my attention, while Holmes, who loathed every form of
|
||||
society with his whole Bohemian soul, remained in our lodgings in
|
||||
Baker Street, buried among his old books, and alternating from
|
||||
week to week between cocaine and ambition, the drowsiness of the
|
||||
drug, and the fierce energy of his own keen nature. He was still,
|
||||
as ever, deeply attracted by the study of crime, and occupied his
|
||||
immense faculties and extraordinary powers of observation in
|
||||
following out those clues, and clearing up those mysteries which
|
||||
had been abandoned as hopeless by the official police. From time
|
||||
to time I heard some vague account of his doings: of his summons
|
||||
to Odessa in the case of the Trepoff murder, of his clearing up
|
||||
of the singular tragedy of the Atkinson brothers at Trincomalee,
|
||||
and finally of the mission which he had accomplished so
|
||||
delicately and successfully for the reigning family of Holland.
|
||||
Beyond these signs of his activity, however, which I merely
|
||||
shared with all the readers of the daily press, I knew little of
|
||||
my former friend and companion.
|
||||
`
|
||||
|
||||
func main() {
|
||||
|
||||
compressed, _ := lz4.Encode(nil, []byte(input))
|
||||
|
||||
modified := make([]byte, len(compressed))
|
||||
|
||||
for {
|
||||
copy(modified, compressed)
|
||||
for i := 0; i < 100; i++ {
|
||||
modified[rand.Intn(len(compressed)-4)+4] = byte(rand.Intn(256))
|
||||
}
|
||||
lz4.Decode(nil, modified)
|
||||
}
|
||||
|
||||
}
|
||||
94
Godeps/_workspace/src/github.com/bkaradzic/go-lz4/lz4-example/main.go
generated
vendored
Normal file
94
Godeps/_workspace/src/github.com/bkaradzic/go-lz4/lz4-example/main.go
generated
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 2011 Branimir Karadzic. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"runtime/pprof"
|
||||
|
||||
lz4 "github.com/bkaradzic/go-lz4"
|
||||
)
|
||||
|
||||
var (
|
||||
decompress = flag.Bool("d", false, "decompress")
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
var optCPUProfile = flag.String("cpuprofile", "", "profile")
|
||||
flag.Parse()
|
||||
|
||||
if *optCPUProfile != "" {
|
||||
f, err := os.Create(*optCPUProfile)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
pprof.StartCPUProfile(f)
|
||||
defer pprof.StopCPUProfile()
|
||||
}
|
||||
|
||||
args := flag.Args()
|
||||
|
||||
var data []byte
|
||||
|
||||
if len(args) < 2 {
|
||||
fmt.Print("Usage: lz4 [-d] <input> <output>\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
input, err := os.OpenFile(args[0], os.O_RDONLY, 0644)
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to open input file %s\n", args[0])
|
||||
os.Exit(1)
|
||||
}
|
||||
defer input.Close()
|
||||
|
||||
if *decompress {
|
||||
data, _ = ioutil.ReadAll(input)
|
||||
data, err = lz4.Decode(nil, data)
|
||||
if err != nil {
|
||||
fmt.Println("Failed to decode:", err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
data, _ = ioutil.ReadAll(input)
|
||||
data, err = lz4.Encode(nil, data)
|
||||
if err != nil {
|
||||
fmt.Println("Failed to encode:", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(args[1], data, 0644)
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to open output file %s\n", args[1])
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
199
Godeps/_workspace/src/github.com/bkaradzic/go-lz4/reader.go
generated
vendored
Normal file
199
Godeps/_workspace/src/github.com/bkaradzic/go-lz4/reader.go
generated
vendored
Normal file
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* Copyright 2011-2012 Branimir Karadzic. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package lz4
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"io"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrCorrupt indicates the input was corrupt
|
||||
ErrCorrupt = errors.New("corrupt input")
|
||||
)
|
||||
|
||||
const (
|
||||
mlBits = 4
|
||||
mlMask = (1 << mlBits) - 1
|
||||
runBits = 8 - mlBits
|
||||
runMask = (1 << runBits) - 1
|
||||
)
|
||||
|
||||
type decoder struct {
|
||||
src []byte
|
||||
dst []byte
|
||||
spos uint32
|
||||
dpos uint32
|
||||
ref uint32
|
||||
}
|
||||
|
||||
func (d *decoder) readByte() (uint8, error) {
|
||||
if int(d.spos) == len(d.src) {
|
||||
return 0, io.EOF
|
||||
}
|
||||
b := d.src[d.spos]
|
||||
d.spos++
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (d *decoder) getLen() (uint32, error) {
|
||||
|
||||
length := uint32(0)
|
||||
ln, err := d.readByte()
|
||||
if err != nil {
|
||||
return 0, ErrCorrupt
|
||||
}
|
||||
for ln == 255 {
|
||||
length += 255
|
||||
ln, err = d.readByte()
|
||||
if err != nil {
|
||||
return 0, ErrCorrupt
|
||||
}
|
||||
}
|
||||
length += uint32(ln)
|
||||
|
||||
return length, nil
|
||||
}
|
||||
|
||||
func (d *decoder) cp(length, decr uint32) {
|
||||
|
||||
if int(d.ref+length) < int(d.dpos) {
|
||||
copy(d.dst[d.dpos:], d.dst[d.ref:d.ref+length])
|
||||
} else {
|
||||
for ii := uint32(0); ii < length; ii++ {
|
||||
d.dst[d.dpos+ii] = d.dst[d.ref+ii]
|
||||
}
|
||||
}
|
||||
d.dpos += length
|
||||
d.ref += length - decr
|
||||
}
|
||||
|
||||
func (d *decoder) finish(err error) error {
|
||||
if err == io.EOF {
|
||||
return nil
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Decode returns the decoded form of src. The returned slice may be a
|
||||
// subslice of dst if it was large enough to hold the entire decoded block.
|
||||
func Decode(dst, src []byte) ([]byte, error) {
|
||||
|
||||
if len(src) < 4 {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
|
||||
uncompressedLen := binary.LittleEndian.Uint32(src)
|
||||
|
||||
if uncompressedLen == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if uncompressedLen > MaxInputSize {
|
||||
return nil, ErrTooLarge
|
||||
}
|
||||
|
||||
if dst == nil || len(dst) < int(uncompressedLen) {
|
||||
dst = make([]byte, uncompressedLen)
|
||||
}
|
||||
|
||||
d := decoder{src: src, dst: dst[:uncompressedLen], spos: 4}
|
||||
|
||||
decr := []uint32{0, 3, 2, 3}
|
||||
|
||||
for {
|
||||
code, err := d.readByte()
|
||||
if err != nil {
|
||||
return d.dst, d.finish(err)
|
||||
}
|
||||
|
||||
length := uint32(code >> mlBits)
|
||||
if length == runMask {
|
||||
ln, err := d.getLen()
|
||||
if err != nil {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
length += ln
|
||||
}
|
||||
|
||||
if int(d.spos+length) > len(d.src) || int(d.dpos+length) > len(d.dst) {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
|
||||
for ii := uint32(0); ii < length; ii++ {
|
||||
d.dst[d.dpos+ii] = d.src[d.spos+ii]
|
||||
}
|
||||
|
||||
d.spos += length
|
||||
d.dpos += length
|
||||
|
||||
if int(d.spos) == len(d.src) {
|
||||
return d.dst, nil
|
||||
}
|
||||
|
||||
if int(d.spos+2) >= len(d.src) {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
|
||||
back := uint32(d.src[d.spos]) | uint32(d.src[d.spos+1])<<8
|
||||
|
||||
if back > d.dpos {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
|
||||
d.spos += 2
|
||||
d.ref = d.dpos - back
|
||||
|
||||
length = uint32(code & mlMask)
|
||||
if length == mlMask {
|
||||
ln, err := d.getLen()
|
||||
if err != nil {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
length += ln
|
||||
}
|
||||
|
||||
literal := d.dpos - d.ref
|
||||
|
||||
if literal < 4 {
|
||||
if int(d.dpos+4) > len(d.dst) {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
|
||||
d.cp(4, decr[literal])
|
||||
} else {
|
||||
length += 4
|
||||
}
|
||||
|
||||
if d.dpos+length > uncompressedLen {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
|
||||
d.cp(length, 0)
|
||||
}
|
||||
}
|
||||
190
Godeps/_workspace/src/github.com/bkaradzic/go-lz4/writer.go
generated
vendored
Normal file
190
Godeps/_workspace/src/github.com/bkaradzic/go-lz4/writer.go
generated
vendored
Normal file
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright 2011-2012 Branimir Karadzic. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package lz4
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
)
|
||||
|
||||
const (
|
||||
minMatch = 4
|
||||
hashLog = 17
|
||||
hashTableSize = 1 << hashLog
|
||||
hashShift = (minMatch * 8) - hashLog
|
||||
incompressible uint32 = 128
|
||||
uninitHash = 0x88888888
|
||||
|
||||
// MaxInputSize is the largest buffer than can be compressed in a single block
|
||||
MaxInputSize = 0x7E000000
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrTooLarge indicates the input buffer was too large
|
||||
ErrTooLarge = errors.New("input too large")
|
||||
)
|
||||
|
||||
type encoder struct {
|
||||
src []byte
|
||||
dst []byte
|
||||
hashTable []uint32
|
||||
pos uint32
|
||||
anchor uint32
|
||||
dpos uint32
|
||||
}
|
||||
|
||||
// CompressBound returns the maximum length of a lz4 block, given it's uncompressed length
|
||||
func CompressBound(isize int) int {
|
||||
if isize > MaxInputSize {
|
||||
return 0
|
||||
}
|
||||
return isize + ((isize) / 255) + 16 + 4
|
||||
}
|
||||
|
||||
func (e *encoder) writeLiterals(length, mlLen, pos uint32) {
|
||||
|
||||
ln := length
|
||||
|
||||
var code byte
|
||||
if ln > runMask-1 {
|
||||
code = runMask
|
||||
} else {
|
||||
code = byte(ln)
|
||||
}
|
||||
|
||||
if mlLen > mlMask-1 {
|
||||
e.dst[e.dpos] = (code << mlBits) + byte(mlMask)
|
||||
} else {
|
||||
e.dst[e.dpos] = (code << mlBits) + byte(mlLen)
|
||||
}
|
||||
e.dpos++
|
||||
|
||||
if code == runMask {
|
||||
ln -= runMask
|
||||
for ; ln > 254; ln -= 255 {
|
||||
e.dst[e.dpos] = 255
|
||||
e.dpos++
|
||||
}
|
||||
|
||||
e.dst[e.dpos] = byte(ln)
|
||||
e.dpos++
|
||||
}
|
||||
|
||||
for ii := uint32(0); ii < length; ii++ {
|
||||
e.dst[e.dpos+ii] = e.src[pos+ii]
|
||||
}
|
||||
|
||||
e.dpos += length
|
||||
}
|
||||
|
||||
// Encode returns the encoded form of src. The returned array may be a
|
||||
// sub-slice of dst if it was large enough to hold the entire output.
|
||||
func Encode(dst, src []byte) ([]byte, error) {
|
||||
|
||||
if len(src) >= MaxInputSize {
|
||||
return nil, ErrTooLarge
|
||||
}
|
||||
|
||||
if n := CompressBound(len(src)); len(dst) < n {
|
||||
dst = make([]byte, n)
|
||||
}
|
||||
|
||||
e := encoder{src: src, dst: dst, hashTable: make([]uint32, hashTableSize)}
|
||||
|
||||
binary.LittleEndian.PutUint32(dst, uint32(len(src)))
|
||||
e.dpos = 4
|
||||
|
||||
var (
|
||||
step uint32 = 1
|
||||
limit = incompressible
|
||||
)
|
||||
|
||||
for {
|
||||
if int(e.pos)+12 >= len(e.src) {
|
||||
e.writeLiterals(uint32(len(e.src))-e.anchor, 0, e.anchor)
|
||||
return e.dst[:e.dpos], nil
|
||||
}
|
||||
|
||||
sequence := uint32(e.src[e.pos+3])<<24 | uint32(e.src[e.pos+2])<<16 | uint32(e.src[e.pos+1])<<8 | uint32(e.src[e.pos+0])
|
||||
|
||||
hash := (sequence * 2654435761) >> hashShift
|
||||
ref := e.hashTable[hash] + uninitHash
|
||||
e.hashTable[hash] = e.pos - uninitHash
|
||||
|
||||
if ((e.pos-ref)>>16) != 0 || uint32(e.src[ref+3])<<24|uint32(e.src[ref+2])<<16|uint32(e.src[ref+1])<<8|uint32(e.src[ref+0]) != sequence {
|
||||
if e.pos-e.anchor > limit {
|
||||
limit <<= 1
|
||||
step += 1 + (step >> 2)
|
||||
}
|
||||
e.pos += step
|
||||
continue
|
||||
}
|
||||
|
||||
if step > 1 {
|
||||
e.hashTable[hash] = ref - uninitHash
|
||||
e.pos -= step - 1
|
||||
step = 1
|
||||
continue
|
||||
}
|
||||
limit = incompressible
|
||||
|
||||
ln := e.pos - e.anchor
|
||||
back := e.pos - ref
|
||||
|
||||
anchor := e.anchor
|
||||
|
||||
e.pos += minMatch
|
||||
ref += minMatch
|
||||
e.anchor = e.pos
|
||||
|
||||
for int(e.pos) < len(e.src)-5 && e.src[e.pos] == e.src[ref] {
|
||||
e.pos++
|
||||
ref++
|
||||
}
|
||||
|
||||
mlLen := e.pos - e.anchor
|
||||
|
||||
e.writeLiterals(ln, mlLen, anchor)
|
||||
e.dst[e.dpos] = uint8(back)
|
||||
e.dst[e.dpos+1] = uint8(back >> 8)
|
||||
e.dpos += 2
|
||||
|
||||
if mlLen > mlMask-1 {
|
||||
mlLen -= mlMask
|
||||
for mlLen > 254 {
|
||||
mlLen -= 255
|
||||
|
||||
e.dst[e.dpos] = 255
|
||||
e.dpos++
|
||||
}
|
||||
|
||||
e.dst[e.dpos] = byte(mlLen)
|
||||
e.dpos++
|
||||
}
|
||||
|
||||
e.anchor = e.pos
|
||||
}
|
||||
}
|
||||
24
Godeps/_workspace/src/github.com/calmh/du/LICENSE
generated
vendored
Normal file
24
Godeps/_workspace/src/github.com/calmh/du/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org>
|
||||
14
Godeps/_workspace/src/github.com/calmh/du/README.md
generated
vendored
Normal file
14
Godeps/_workspace/src/github.com/calmh/du/README.md
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
du
|
||||
==
|
||||
|
||||
Get total and available disk space on a given volume.
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
http://godoc.org/github.com/calmh/du
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
Public Domain
|
||||
21
Godeps/_workspace/src/github.com/calmh/du/cmd/du/main.go
generated
vendored
Normal file
21
Godeps/_workspace/src/github.com/calmh/du/cmd/du/main.go
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/calmh/du"
|
||||
)
|
||||
|
||||
var KB = int64(1024)
|
||||
|
||||
func main() {
|
||||
usage, err := du.Get(os.Args[1])
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Println("Free:", usage.FreeBytes/(KB*KB), "MiB")
|
||||
fmt.Println("Available:", usage.AvailBytes/(KB*KB), "MiB")
|
||||
fmt.Println("Size:", usage.TotalBytes/(KB*KB), "MiB")
|
||||
}
|
||||
8
Godeps/_workspace/src/github.com/calmh/du/diskusage.go
generated
vendored
Normal file
8
Godeps/_workspace/src/github.com/calmh/du/diskusage.go
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
package du
|
||||
|
||||
// Usage holds information about total and available storage on a volume.
|
||||
type Usage struct {
|
||||
TotalBytes int64 // Size of volume
|
||||
FreeBytes int64 // Unused size
|
||||
AvailBytes int64 // Available to a non-privileged user
|
||||
}
|
||||
24
Godeps/_workspace/src/github.com/calmh/du/diskusage_posix.go
generated
vendored
Normal file
24
Godeps/_workspace/src/github.com/calmh/du/diskusage_posix.go
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
// +build !windows,!netbsd,!openbsd,!solaris
|
||||
|
||||
package du
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// Get returns the Usage of a given path, or an error if usage data is
|
||||
// unavailable.
|
||||
func Get(path string) (Usage, error) {
|
||||
var stat syscall.Statfs_t
|
||||
err := syscall.Statfs(filepath.Clean(path), &stat)
|
||||
if err != nil {
|
||||
return Usage{}, err
|
||||
}
|
||||
u := Usage{
|
||||
FreeBytes: int64(stat.Bfree) * int64(stat.Bsize),
|
||||
TotalBytes: int64(stat.Blocks) * int64(stat.Bsize),
|
||||
AvailBytes: int64(stat.Bavail) * int64(stat.Bsize),
|
||||
}
|
||||
return u, nil
|
||||
}
|
||||
13
Godeps/_workspace/src/github.com/calmh/du/diskusage_unsupported.go
generated
vendored
Normal file
13
Godeps/_workspace/src/github.com/calmh/du/diskusage_unsupported.go
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
// +build netbsd openbsd solaris
|
||||
|
||||
package du
|
||||
|
||||
import "errors"
|
||||
|
||||
var ErrUnsupported = errors.New("unsupported platform")
|
||||
|
||||
// Get returns the Usage of a given path, or an error if usage data is
|
||||
// unavailable.
|
||||
func Get(path string) (Usage, error) {
|
||||
return Usage{}, ErrUnsupported
|
||||
}
|
||||
27
Godeps/_workspace/src/github.com/calmh/du/diskusage_windows.go
generated
vendored
Normal file
27
Godeps/_workspace/src/github.com/calmh/du/diskusage_windows.go
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
package du
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Get returns the Usage of a given path, or an error if usage data is
|
||||
// unavailable.
|
||||
func Get(path string) (Usage, error) {
|
||||
h := syscall.MustLoadDLL("kernel32.dll")
|
||||
c := h.MustFindProc("GetDiskFreeSpaceExW")
|
||||
|
||||
var u Usage
|
||||
|
||||
ret, _, err := c.Call(
|
||||
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(path))),
|
||||
uintptr(unsafe.Pointer(&u.FreeBytes)),
|
||||
uintptr(unsafe.Pointer(&u.TotalBytes)),
|
||||
uintptr(unsafe.Pointer(&u.AvailBytes)))
|
||||
|
||||
if ret == 0 {
|
||||
return u, err
|
||||
}
|
||||
|
||||
return u, nil
|
||||
}
|
||||
19
Godeps/_workspace/src/github.com/calmh/luhn/LICENSE
generated
vendored
Normal file
19
Godeps/_workspace/src/github.com/calmh/luhn/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (C) 2014 Jakob Borg
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
- The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
70
Godeps/_workspace/src/github.com/calmh/luhn/luhn.go
generated
vendored
Normal file
70
Godeps/_workspace/src/github.com/calmh/luhn/luhn.go
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
// Copyright (C) 2014 Jakob Borg
|
||||
|
||||
// Package luhn generates and validates Luhn mod N check digits.
|
||||
package luhn
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// An alphabet is a string of N characters, representing the digits of a given
|
||||
// base N.
|
||||
type Alphabet string
|
||||
|
||||
var (
|
||||
Base32 Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
|
||||
)
|
||||
|
||||
// Generate returns a check digit for the string s, which should be composed
|
||||
// of characters from the Alphabet a.
|
||||
func (a Alphabet) Generate(s string) (rune, error) {
|
||||
if err := a.check(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
factor := 1
|
||||
sum := 0
|
||||
n := len(a)
|
||||
|
||||
for i := range s {
|
||||
codepoint := strings.IndexByte(string(a), s[i])
|
||||
if codepoint == -1 {
|
||||
return 0, fmt.Errorf("Digit %q not valid in alphabet %q", s[i], a)
|
||||
}
|
||||
addend := factor * codepoint
|
||||
if factor == 2 {
|
||||
factor = 1
|
||||
} else {
|
||||
factor = 2
|
||||
}
|
||||
addend = (addend / n) + (addend % n)
|
||||
sum += addend
|
||||
}
|
||||
remainder := sum % n
|
||||
checkCodepoint := (n - remainder) % n
|
||||
return rune(a[checkCodepoint]), nil
|
||||
}
|
||||
|
||||
// Validate returns true if the last character of the string s is correct, for
|
||||
// a string s composed of characters in the alphabet a.
|
||||
func (a Alphabet) Validate(s string) bool {
|
||||
t := s[:len(s)-1]
|
||||
c, err := a.Generate(t)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return rune(s[len(s)-1]) == c
|
||||
}
|
||||
|
||||
// check returns an error if the given alphabet does not consist of unique characters
|
||||
func (a Alphabet) check() error {
|
||||
cm := make(map[byte]bool, len(a))
|
||||
for i := range a {
|
||||
if cm[a[i]] {
|
||||
return fmt.Errorf("Digit %q non-unique in alphabet %q", a[i], a)
|
||||
}
|
||||
cm[a[i]] = true
|
||||
}
|
||||
return nil
|
||||
}
|
||||
1
Godeps/_workspace/src/github.com/calmh/xdr/.gitignore
generated
vendored
Normal file
1
Godeps/_workspace/src/github.com/calmh/xdr/.gitignore
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
coverage.out
|
||||
19
Godeps/_workspace/src/github.com/calmh/xdr/.travis.yml
generated
vendored
Normal file
19
Godeps/_workspace/src/github.com/calmh/xdr/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
language: go
|
||||
go:
|
||||
- tip
|
||||
|
||||
install:
|
||||
- export PATH=$PATH:$HOME/gopath/bin
|
||||
- go get golang.org/x/tools/cover
|
||||
- go get github.com/mattn/goveralls
|
||||
|
||||
script:
|
||||
- ./generate.sh
|
||||
- go test -coverprofile=coverage.out
|
||||
|
||||
after_success:
|
||||
- goveralls -coverprofile=coverage.out -service=travis-ci -package=calmh/xdr -repotoken="$COVERALLS_TOKEN"
|
||||
|
||||
env:
|
||||
global:
|
||||
secure: SmgnrGfp2zLrA44ChRMpjPeujubt9veZ8Fx/OseMWECmacyV5N/TuDhzIbwo6QwV4xB0sBacoPzvxQbJRVjNKsPiSu72UbcQmQ7flN4Tf7nW09tSh1iW8NgrpBCq/3UYLoBu2iPBEBKm93IK0aGNAKs6oEkB0fU27iTVBwiTXOY=
|
||||
19
Godeps/_workspace/src/github.com/calmh/xdr/LICENSE
generated
vendored
Normal file
19
Godeps/_workspace/src/github.com/calmh/xdr/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (C) 2014 Jakob Borg.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
- The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
12
Godeps/_workspace/src/github.com/calmh/xdr/README.md
generated
vendored
Normal file
12
Godeps/_workspace/src/github.com/calmh/xdr/README.md
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
xdr
|
||||
===
|
||||
|
||||
[](https://circleci.com/gh/calmh/xdr)
|
||||
[](https://coveralls.io/r/calmh/xdr?branch=master)
|
||||
[](http://godoc.org/github.com/calmh/xdr)
|
||||
[](http://opensource.org/licenses/MIT)
|
||||
|
||||
This is an XDR encoding/decoding library. It uses code generation and
|
||||
not reflection. It supports the IPDR bastardized XDR format when built
|
||||
with `-tags ipdr`.
|
||||
|
||||
3
Godeps/_workspace/src/github.com/calmh/xdr/circle.yml
generated
vendored
Normal file
3
Godeps/_workspace/src/github.com/calmh/xdr/circle.yml
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
dependencies:
|
||||
post:
|
||||
- ./generate.sh
|
||||
530
Godeps/_workspace/src/github.com/calmh/xdr/cmd/genxdr/main.go
generated
vendored
Normal file
530
Godeps/_workspace/src/github.com/calmh/xdr/cmd/genxdr/main.go
generated
vendored
Normal file
@@ -0,0 +1,530 @@
|
||||
// Copyright (C) 2014 Jakob Borg. All rights reserved. Use of this source code
|
||||
// is governed by an MIT-style license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/format"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
type fieldInfo struct {
|
||||
Name string
|
||||
IsBasic bool // handled by one the native Read/WriteUint64 etc functions
|
||||
IsSlice bool // field is a slice of FieldType
|
||||
FieldType string // original type of field, i.e. "int"
|
||||
Encoder string // the encoder name, i.e. "Uint64" for Read/WriteUint64
|
||||
Convert string // what to convert to when encoding, i.e. "uint64"
|
||||
Max int // max size for slices and strings
|
||||
Submax int // max size for strings inside slices
|
||||
}
|
||||
|
||||
type structInfo struct {
|
||||
Name string
|
||||
Fields []fieldInfo
|
||||
}
|
||||
|
||||
var headerTpl = template.Must(template.New("header").Parse(`// ************************************************************
|
||||
// This file is automatically generated by genxdr. Do not edit.
|
||||
// ************************************************************
|
||||
|
||||
package {{.Package}}
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"github.com/calmh/xdr"
|
||||
)
|
||||
`))
|
||||
|
||||
var encodeTpl = template.Must(template.New("encoder").Parse(`
|
||||
func (o {{.TypeName}}) EncodeXDR(w io.Writer) (int, error) {
|
||||
var xw = xdr.NewWriter(w)
|
||||
return o.EncodeXDRInto(xw)
|
||||
}//+n
|
||||
|
||||
func (o {{.TypeName}}) MarshalXDR() ([]byte, error) {
|
||||
return o.AppendXDR(make([]byte, 0, 128))
|
||||
}//+n
|
||||
|
||||
func (o {{.TypeName}}) MustMarshalXDR() []byte {
|
||||
bs, err := o.MarshalXDR()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return bs
|
||||
}//+n
|
||||
|
||||
func (o {{.TypeName}}) AppendXDR(bs []byte) ([]byte, error) {
|
||||
var aw = xdr.AppendWriter(bs)
|
||||
var xw = xdr.NewWriter(&aw)
|
||||
_, err := o.EncodeXDRInto(xw)
|
||||
return []byte(aw), err
|
||||
}//+n
|
||||
|
||||
func (o {{.TypeName}}) EncodeXDRInto(xw *xdr.Writer) (int, error) {
|
||||
{{range $fieldInfo := .Fields}}
|
||||
{{if not $fieldInfo.IsSlice}}
|
||||
{{if ne $fieldInfo.Convert ""}}
|
||||
xw.Write{{$fieldInfo.Encoder}}({{$fieldInfo.Convert}}(o.{{$fieldInfo.Name}}))
|
||||
{{else if $fieldInfo.IsBasic}}
|
||||
{{if ge $fieldInfo.Max 1}}
|
||||
if l := len(o.{{$fieldInfo.Name}}); l > {{$fieldInfo.Max}} {
|
||||
return xw.Tot(), xdr.ElementSizeExceeded("{{$fieldInfo.Name}}", l, {{$fieldInfo.Max}})
|
||||
}
|
||||
{{end}}
|
||||
xw.Write{{$fieldInfo.Encoder}}(o.{{$fieldInfo.Name}})
|
||||
{{else}}
|
||||
_, err := o.{{$fieldInfo.Name}}.EncodeXDRInto(xw)
|
||||
if err != nil {
|
||||
return xw.Tot(), err
|
||||
}
|
||||
{{end}}
|
||||
{{else}}
|
||||
{{if ge $fieldInfo.Max 1}}
|
||||
if l := len(o.{{$fieldInfo.Name}}); l > {{$fieldInfo.Max}} {
|
||||
return xw.Tot(), xdr.ElementSizeExceeded("{{$fieldInfo.Name}}", l, {{$fieldInfo.Max}})
|
||||
}
|
||||
{{end}}
|
||||
xw.WriteUint32(uint32(len(o.{{$fieldInfo.Name}})))
|
||||
for i := range o.{{$fieldInfo.Name}} {
|
||||
{{if ne $fieldInfo.Convert ""}}
|
||||
xw.Write{{$fieldInfo.Encoder}}({{$fieldInfo.Convert}}(o.{{$fieldInfo.Name}}[i]))
|
||||
{{else if $fieldInfo.IsBasic}}
|
||||
xw.Write{{$fieldInfo.Encoder}}(o.{{$fieldInfo.Name}}[i])
|
||||
{{else}}
|
||||
_, err := o.{{$fieldInfo.Name}}[i].EncodeXDRInto(xw)
|
||||
if err != nil {
|
||||
return xw.Tot(), err
|
||||
}
|
||||
{{end}}
|
||||
}
|
||||
{{end}}
|
||||
{{end}}
|
||||
return xw.Tot(), xw.Error()
|
||||
}//+n
|
||||
|
||||
func (o *{{.TypeName}}) DecodeXDR(r io.Reader) error {
|
||||
xr := xdr.NewReader(r)
|
||||
return o.DecodeXDRFrom(xr)
|
||||
}//+n
|
||||
|
||||
func (o *{{.TypeName}}) UnmarshalXDR(bs []byte) error {
|
||||
var br = bytes.NewReader(bs)
|
||||
var xr = xdr.NewReader(br)
|
||||
return o.DecodeXDRFrom(xr)
|
||||
}//+n
|
||||
|
||||
func (o *{{.TypeName}}) DecodeXDRFrom(xr *xdr.Reader) error {
|
||||
{{range $fieldInfo := .Fields}}
|
||||
{{if not $fieldInfo.IsSlice}}
|
||||
{{if ne $fieldInfo.Convert ""}}
|
||||
o.{{$fieldInfo.Name}} = {{$fieldInfo.FieldType}}(xr.Read{{$fieldInfo.Encoder}}())
|
||||
{{else if $fieldInfo.IsBasic}}
|
||||
{{if ge $fieldInfo.Max 1}}
|
||||
o.{{$fieldInfo.Name}} = xr.Read{{$fieldInfo.Encoder}}Max({{$fieldInfo.Max}})
|
||||
{{else}}
|
||||
o.{{$fieldInfo.Name}} = xr.Read{{$fieldInfo.Encoder}}()
|
||||
{{end}}
|
||||
{{else}}
|
||||
(&o.{{$fieldInfo.Name}}).DecodeXDRFrom(xr)
|
||||
{{end}}
|
||||
{{else}}
|
||||
_{{$fieldInfo.Name}}Size := int(xr.ReadUint32())
|
||||
if _{{$fieldInfo.Name}}Size < 0 {
|
||||
return xdr.ElementSizeExceeded("{{$fieldInfo.Name}}", _{{$fieldInfo.Name}}Size, {{$fieldInfo.Max}})
|
||||
}
|
||||
{{if ge $fieldInfo.Max 1}}
|
||||
if _{{$fieldInfo.Name}}Size > {{$fieldInfo.Max}} {
|
||||
return xdr.ElementSizeExceeded("{{$fieldInfo.Name}}", _{{$fieldInfo.Name}}Size, {{$fieldInfo.Max}})
|
||||
}
|
||||
{{end}}
|
||||
o.{{$fieldInfo.Name}} = make([]{{$fieldInfo.FieldType}}, _{{$fieldInfo.Name}}Size)
|
||||
for i := range o.{{$fieldInfo.Name}} {
|
||||
{{if ne $fieldInfo.Convert ""}}
|
||||
o.{{$fieldInfo.Name}}[i] = {{$fieldInfo.FieldType}}(xr.Read{{$fieldInfo.Encoder}}())
|
||||
{{else if $fieldInfo.IsBasic}}
|
||||
{{if ge $fieldInfo.Submax 1}}
|
||||
o.{{$fieldInfo.Name}}[i] = xr.Read{{$fieldInfo.Encoder}}Max({{$fieldInfo.Submax}})
|
||||
{{else}}
|
||||
o.{{$fieldInfo.Name}}[i] = xr.Read{{$fieldInfo.Encoder}}()
|
||||
{{end}}
|
||||
{{else}}
|
||||
(&o.{{$fieldInfo.Name}}[i]).DecodeXDRFrom(xr)
|
||||
{{end}}
|
||||
}
|
||||
{{end}}
|
||||
{{end}}
|
||||
return xr.Error()
|
||||
}`))
|
||||
|
||||
var emptyTypeTpl = template.Must(template.New("encoder").Parse(`
|
||||
func (o {{.TypeName}}) EncodeXDR(w io.Writer) (int, error) {
|
||||
return 0, nil
|
||||
}//+n
|
||||
|
||||
func (o {{.TypeName}}) MarshalXDR() ([]byte, error) {
|
||||
return nil, nil
|
||||
}//+n
|
||||
|
||||
func (o {{.TypeName}}) MustMarshalXDR() []byte {
|
||||
return nil
|
||||
}//+n
|
||||
|
||||
func (o {{.TypeName}}) AppendXDR(bs []byte) ([]byte, error) {
|
||||
return bs, nil
|
||||
}//+n
|
||||
|
||||
func (o {{.TypeName}}) EncodeXDRInto(xw *xdr.Writer) (int, error) {
|
||||
return xw.Tot(), xw.Error()
|
||||
}//+n
|
||||
|
||||
func (o *{{.TypeName}}) DecodeXDR(r io.Reader) error {
|
||||
return nil
|
||||
}//+n
|
||||
|
||||
func (o *{{.TypeName}}) UnmarshalXDR(bs []byte) error {
|
||||
return nil
|
||||
}//+n
|
||||
|
||||
func (o *{{.TypeName}}) DecodeXDRFrom(xr *xdr.Reader) error {
|
||||
return xr.Error()
|
||||
}`))
|
||||
|
||||
var maxRe = regexp.MustCompile(`(?:\Wmax:)(\d+)(?:\s*,\s*(\d+))?`)
|
||||
|
||||
type typeSet struct {
|
||||
Type string
|
||||
Encoder string
|
||||
}
|
||||
|
||||
var xdrEncoders = map[string]typeSet{
|
||||
"int8": typeSet{"uint8", "Uint8"},
|
||||
"uint8": typeSet{"", "Uint8"},
|
||||
"int16": typeSet{"uint16", "Uint16"},
|
||||
"uint16": typeSet{"", "Uint16"},
|
||||
"int32": typeSet{"uint32", "Uint32"},
|
||||
"uint32": typeSet{"", "Uint32"},
|
||||
"int64": typeSet{"uint64", "Uint64"},
|
||||
"uint64": typeSet{"", "Uint64"},
|
||||
"int": typeSet{"uint64", "Uint64"},
|
||||
"string": typeSet{"", "String"},
|
||||
"[]byte": typeSet{"", "Bytes"},
|
||||
"bool": typeSet{"", "Bool"},
|
||||
}
|
||||
|
||||
func handleStruct(t *ast.StructType) []fieldInfo {
|
||||
var fs []fieldInfo
|
||||
|
||||
for _, sf := range t.Fields.List {
|
||||
if len(sf.Names) == 0 {
|
||||
// We don't handle anonymous fields
|
||||
continue
|
||||
}
|
||||
|
||||
fn := sf.Names[0].Name
|
||||
var max1, max2 int
|
||||
if sf.Comment != nil {
|
||||
c := sf.Comment.List[0].Text
|
||||
m := maxRe.FindStringSubmatch(c)
|
||||
if len(m) >= 2 {
|
||||
max1, _ = strconv.Atoi(m[1])
|
||||
}
|
||||
if len(m) >= 3 {
|
||||
max2, _ = strconv.Atoi(m[2])
|
||||
}
|
||||
if strings.Contains(c, "noencode") {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
var f fieldInfo
|
||||
switch ft := sf.Type.(type) {
|
||||
case *ast.Ident:
|
||||
tn := ft.Name
|
||||
if enc, ok := xdrEncoders[tn]; ok {
|
||||
f = fieldInfo{
|
||||
Name: fn,
|
||||
IsBasic: true,
|
||||
FieldType: tn,
|
||||
Encoder: enc.Encoder,
|
||||
Convert: enc.Type,
|
||||
Max: max1,
|
||||
Submax: max2,
|
||||
}
|
||||
} else {
|
||||
f = fieldInfo{
|
||||
Name: fn,
|
||||
IsBasic: false,
|
||||
FieldType: tn,
|
||||
Max: max1,
|
||||
Submax: max2,
|
||||
}
|
||||
}
|
||||
|
||||
case *ast.ArrayType:
|
||||
if ft.Len != nil {
|
||||
// We don't handle arrays
|
||||
continue
|
||||
}
|
||||
|
||||
tn := ft.Elt.(*ast.Ident).Name
|
||||
if enc, ok := xdrEncoders["[]"+tn]; ok {
|
||||
f = fieldInfo{
|
||||
Name: fn,
|
||||
IsBasic: true,
|
||||
FieldType: tn,
|
||||
Encoder: enc.Encoder,
|
||||
Convert: enc.Type,
|
||||
Max: max1,
|
||||
Submax: max2,
|
||||
}
|
||||
} else if enc, ok := xdrEncoders[tn]; ok {
|
||||
f = fieldInfo{
|
||||
Name: fn,
|
||||
IsBasic: true,
|
||||
IsSlice: true,
|
||||
FieldType: tn,
|
||||
Encoder: enc.Encoder,
|
||||
Convert: enc.Type,
|
||||
Max: max1,
|
||||
Submax: max2,
|
||||
}
|
||||
} else {
|
||||
f = fieldInfo{
|
||||
Name: fn,
|
||||
IsSlice: true,
|
||||
FieldType: tn,
|
||||
Max: max1,
|
||||
Submax: max2,
|
||||
}
|
||||
}
|
||||
|
||||
case *ast.SelectorExpr:
|
||||
f = fieldInfo{
|
||||
Name: fn,
|
||||
FieldType: ft.Sel.Name,
|
||||
Max: max1,
|
||||
Submax: max2,
|
||||
}
|
||||
}
|
||||
|
||||
fs = append(fs, f)
|
||||
}
|
||||
|
||||
return fs
|
||||
}
|
||||
|
||||
func generateCode(output io.Writer, s structInfo) {
|
||||
name := s.Name
|
||||
fs := s.Fields
|
||||
|
||||
var buf bytes.Buffer
|
||||
var err error
|
||||
if len(fs) == 0 {
|
||||
// This is an empty type. We can create a quite simple codec for it.
|
||||
err = emptyTypeTpl.Execute(&buf, map[string]interface{}{"TypeName": name})
|
||||
} else {
|
||||
// Generate with the default template.
|
||||
err = encodeTpl.Execute(&buf, map[string]interface{}{"TypeName": name, "Fields": fs})
|
||||
}
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
bs := regexp.MustCompile(`(\s*\n)+`).ReplaceAll(buf.Bytes(), []byte("\n"))
|
||||
bs = bytes.Replace(bs, []byte("//+n"), []byte("\n"), -1)
|
||||
|
||||
bs, err = format.Source(bs)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Fprintln(output, string(bs))
|
||||
}
|
||||
|
||||
func uncamelize(s string) string {
|
||||
return regexp.MustCompile("[a-z][A-Z]").ReplaceAllStringFunc(s, func(camel string) string {
|
||||
return camel[:1] + " " + camel[1:]
|
||||
})
|
||||
}
|
||||
|
||||
func generateDiagram(output io.Writer, s structInfo) {
|
||||
sn := s.Name
|
||||
fs := s.Fields
|
||||
|
||||
fmt.Fprintln(output, sn+" Structure:")
|
||||
|
||||
if len(fs) == 0 {
|
||||
fmt.Fprintln(output, "(contains no fields)")
|
||||
fmt.Fprintln(output)
|
||||
fmt.Fprintln(output)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Fprintln(output)
|
||||
fmt.Fprintln(output, " 0 1 2 3")
|
||||
fmt.Fprintln(output, " 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1")
|
||||
line := "+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+"
|
||||
fmt.Fprintln(output, line)
|
||||
|
||||
for _, f := range fs {
|
||||
tn := f.FieldType
|
||||
name := uncamelize(f.Name)
|
||||
|
||||
if f.IsSlice {
|
||||
fmt.Fprintf(output, "| %s |\n", center("Number of "+name, 61))
|
||||
fmt.Fprintln(output, line)
|
||||
}
|
||||
switch tn {
|
||||
case "bool":
|
||||
fmt.Fprintf(output, "| %s |V|\n", center(name+" (V=0 or 1)", 59))
|
||||
fmt.Fprintln(output, line)
|
||||
case "int16", "uint16":
|
||||
fmt.Fprintf(output, "| %s | %s |\n", center("0x0000", 29), center(name, 29))
|
||||
fmt.Fprintln(output, line)
|
||||
case "int32", "uint32":
|
||||
fmt.Fprintf(output, "| %s |\n", center(name, 61))
|
||||
fmt.Fprintln(output, line)
|
||||
case "int64", "uint64":
|
||||
fmt.Fprintf(output, "| %-61s |\n", "")
|
||||
fmt.Fprintf(output, "+ %s +\n", center(name+" (64 bits)", 61))
|
||||
fmt.Fprintf(output, "| %-61s |\n", "")
|
||||
fmt.Fprintln(output, line)
|
||||
case "string", "byte": // XXX We assume slice of byte!
|
||||
fmt.Fprintf(output, "| %s |\n", center("Length of "+name, 61))
|
||||
fmt.Fprintln(output, line)
|
||||
fmt.Fprintf(output, "/ %61s /\n", "")
|
||||
fmt.Fprintf(output, "\\ %s \\\n", center(name+" (variable length)", 61))
|
||||
fmt.Fprintf(output, "/ %61s /\n", "")
|
||||
fmt.Fprintln(output, line)
|
||||
default:
|
||||
if f.IsSlice {
|
||||
tn = "Zero or more " + tn + " Structures"
|
||||
fmt.Fprintf(output, "/ %s /\n", center("", 61))
|
||||
fmt.Fprintf(output, "\\ %s \\\n", center(tn, 61))
|
||||
fmt.Fprintf(output, "/ %s /\n", center("", 61))
|
||||
} else {
|
||||
tn = tn + " Structure"
|
||||
fmt.Fprintf(output, "/ %s /\n", center("", 61))
|
||||
fmt.Fprintf(output, "\\ %s \\\n", center(tn, 61))
|
||||
fmt.Fprintf(output, "/ %s /\n", center("", 61))
|
||||
}
|
||||
fmt.Fprintln(output, line)
|
||||
}
|
||||
}
|
||||
fmt.Fprintln(output)
|
||||
fmt.Fprintln(output)
|
||||
}
|
||||
|
||||
func generateXdr(output io.Writer, s structInfo) {
|
||||
sn := s.Name
|
||||
fs := s.Fields
|
||||
|
||||
fmt.Fprintf(output, "struct %s {\n", sn)
|
||||
|
||||
for _, f := range fs {
|
||||
tn := f.FieldType
|
||||
fn := f.Name
|
||||
suf := ""
|
||||
l := ""
|
||||
if f.Max > 0 {
|
||||
l = strconv.Itoa(f.Max)
|
||||
}
|
||||
if f.IsSlice {
|
||||
suf = "<" + l + ">"
|
||||
}
|
||||
|
||||
switch tn {
|
||||
case "int16", "int32":
|
||||
fmt.Fprintf(output, "\tint %s%s;\n", fn, suf)
|
||||
case "uint16", "uint32":
|
||||
fmt.Fprintf(output, "\tunsigned int %s%s;\n", fn, suf)
|
||||
case "int64":
|
||||
fmt.Fprintf(output, "\thyper %s%s;\n", fn, suf)
|
||||
case "uint64":
|
||||
fmt.Fprintf(output, "\tunsigned hyper %s%s;\n", fn, suf)
|
||||
case "string":
|
||||
fmt.Fprintf(output, "\tstring %s<%s>;\n", fn, l)
|
||||
case "byte":
|
||||
fmt.Fprintf(output, "\topaque %s<%s>;\n", fn, l)
|
||||
default:
|
||||
fmt.Fprintf(output, "\t%s %s%s;\n", tn, fn, suf)
|
||||
}
|
||||
}
|
||||
fmt.Fprintln(output, "}")
|
||||
fmt.Fprintln(output)
|
||||
}
|
||||
|
||||
func center(s string, w int) string {
|
||||
w -= len(s)
|
||||
l := w / 2
|
||||
r := l
|
||||
if l+r < w {
|
||||
r++
|
||||
}
|
||||
return strings.Repeat(" ", l) + s + strings.Repeat(" ", r)
|
||||
}
|
||||
|
||||
func inspector(structs *[]structInfo) func(ast.Node) bool {
|
||||
return func(n ast.Node) bool {
|
||||
switch n := n.(type) {
|
||||
case *ast.TypeSpec:
|
||||
switch t := n.Type.(type) {
|
||||
case *ast.StructType:
|
||||
name := n.Name.Name
|
||||
fs := handleStruct(t)
|
||||
*structs = append(*structs, structInfo{name, fs})
|
||||
}
|
||||
return false
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
outputFile := flag.String("o", "", "Output file, blank for stdout")
|
||||
flag.Parse()
|
||||
fname := flag.Arg(0)
|
||||
|
||||
fset := token.NewFileSet()
|
||||
f, err := parser.ParseFile(fset, fname, nil, parser.ParseComments)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
var structs []structInfo
|
||||
i := inspector(&structs)
|
||||
ast.Inspect(f, i)
|
||||
|
||||
var output io.Writer = os.Stdout
|
||||
if *outputFile != "" {
|
||||
fd, err := os.Create(*outputFile)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
output = fd
|
||||
}
|
||||
|
||||
headerTpl.Execute(output, map[string]string{"Package": f.Name.Name})
|
||||
for _, s := range structs {
|
||||
fmt.Fprintf(output, "\n/*\n\n")
|
||||
generateDiagram(output, s)
|
||||
generateXdr(output, s)
|
||||
fmt.Fprintf(output, "*/\n")
|
||||
generateCode(output, s)
|
||||
}
|
||||
}
|
||||
16
Godeps/_workspace/src/github.com/calmh/xdr/debug.go
generated
vendored
Normal file
16
Godeps/_workspace/src/github.com/calmh/xdr/debug.go
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright (C) 2014 Jakob Borg. All rights reserved. Use of this source code
|
||||
// is governed by an MIT-style license that can be found in the LICENSE file.
|
||||
|
||||
package xdr
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
var (
|
||||
debug = len(os.Getenv("XDRTRACE")) > 0
|
||||
dl = log.New(os.Stdout, "xdr: ", log.Lshortfile|log.Ltime|log.Lmicroseconds)
|
||||
)
|
||||
|
||||
const maxDebugBytes = 32
|
||||
5
Godeps/_workspace/src/github.com/calmh/xdr/doc.go
generated
vendored
Normal file
5
Godeps/_workspace/src/github.com/calmh/xdr/doc.go
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
// Copyright (C) 2014 Jakob Borg. All rights reserved. Use of this source code
|
||||
// is governed by an MIT-style license that can be found in the LICENSE file.
|
||||
|
||||
// Package xdr implements an XDR (RFC 4506) encoder/decoder.
|
||||
package xdr
|
||||
4
Godeps/_workspace/src/github.com/calmh/xdr/generate.sh
generated
vendored
Normal file
4
Godeps/_workspace/src/github.com/calmh/xdr/generate.sh
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
go run cmd/genxdr/main.go -- bench_test.go > bench_xdr_test.go
|
||||
go run cmd/genxdr/main.go -- encdec_test.go > encdec_xdr_test.go
|
||||
10
Godeps/_workspace/src/github.com/calmh/xdr/pad_ipdr.go
generated
vendored
Normal file
10
Godeps/_workspace/src/github.com/calmh/xdr/pad_ipdr.go
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
// Copyright (C) 2014 Jakob Borg. All rights reserved. Use of this source code
|
||||
// is governed by an MIT-style license that can be found in the LICENSE file.
|
||||
|
||||
// +build ipdr
|
||||
|
||||
package xdr
|
||||
|
||||
func pad(l int) int {
|
||||
return 0
|
||||
}
|
||||
14
Godeps/_workspace/src/github.com/calmh/xdr/pad_xdr.go
generated
vendored
Normal file
14
Godeps/_workspace/src/github.com/calmh/xdr/pad_xdr.go
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
// Copyright (C) 2014 Jakob Borg. All rights reserved. Use of this source code
|
||||
// is governed by an MIT-style license that can be found in the LICENSE file.
|
||||
|
||||
// +build !ipdr
|
||||
|
||||
package xdr
|
||||
|
||||
func pad(l int) int {
|
||||
d := l % 4
|
||||
if d == 0 {
|
||||
return 0
|
||||
}
|
||||
return 4 - d
|
||||
}
|
||||
171
Godeps/_workspace/src/github.com/calmh/xdr/reader.go
generated
vendored
Normal file
171
Godeps/_workspace/src/github.com/calmh/xdr/reader.go
generated
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
// Copyright (C) 2014 Jakob Borg and Contributors (see the CONTRIBUTORS file).
|
||||
// All rights reserved. Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package xdr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type Reader struct {
|
||||
r io.Reader
|
||||
err error
|
||||
b [8]byte
|
||||
}
|
||||
|
||||
func NewReader(r io.Reader) *Reader {
|
||||
return &Reader{
|
||||
r: r,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Reader) ReadRaw(bs []byte) (int, error) {
|
||||
if r.err != nil {
|
||||
return 0, r.err
|
||||
}
|
||||
|
||||
var n int
|
||||
n, r.err = io.ReadFull(r.r, bs)
|
||||
return n, r.err
|
||||
}
|
||||
|
||||
func (r *Reader) ReadString() string {
|
||||
return r.ReadStringMax(0)
|
||||
}
|
||||
|
||||
func (r *Reader) ReadStringMax(max int) string {
|
||||
buf := r.ReadBytesMaxInto(max, nil)
|
||||
bh := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
|
||||
sh := reflect.StringHeader{
|
||||
Data: bh.Data,
|
||||
Len: bh.Len,
|
||||
}
|
||||
return *((*string)(unsafe.Pointer(&sh)))
|
||||
}
|
||||
|
||||
func (r *Reader) ReadBytes() []byte {
|
||||
return r.ReadBytesInto(nil)
|
||||
}
|
||||
|
||||
func (r *Reader) ReadBytesMax(max int) []byte {
|
||||
return r.ReadBytesMaxInto(max, nil)
|
||||
}
|
||||
|
||||
func (r *Reader) ReadBytesInto(dst []byte) []byte {
|
||||
return r.ReadBytesMaxInto(0, dst)
|
||||
}
|
||||
|
||||
func (r *Reader) ReadBytesMaxInto(max int, dst []byte) []byte {
|
||||
if r.err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
l := int(r.ReadUint32())
|
||||
if r.err != nil {
|
||||
return nil
|
||||
}
|
||||
if l < 0 || max > 0 && l > max {
|
||||
// l may be negative on 32 bit builds
|
||||
r.err = ElementSizeExceeded("bytes field", l, max)
|
||||
return nil
|
||||
}
|
||||
|
||||
if fullLen := l + pad(l); fullLen > len(dst) {
|
||||
dst = make([]byte, fullLen)
|
||||
} else {
|
||||
dst = dst[:fullLen]
|
||||
}
|
||||
|
||||
var n int
|
||||
n, r.err = io.ReadFull(r.r, dst)
|
||||
if r.err != nil {
|
||||
if debug {
|
||||
dl.Printf("rd bytes (%d): %v", len(dst), r.err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if debug {
|
||||
if n > maxDebugBytes {
|
||||
dl.Printf("rd bytes (%d): %x...", len(dst), dst[:maxDebugBytes])
|
||||
} else {
|
||||
dl.Printf("rd bytes (%d): %x", len(dst), dst)
|
||||
}
|
||||
}
|
||||
return dst[:l]
|
||||
}
|
||||
|
||||
func (r *Reader) ReadBool() bool {
|
||||
return r.ReadUint8() != 0
|
||||
}
|
||||
|
||||
func (r *Reader) ReadUint32() uint32 {
|
||||
if r.err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
_, r.err = io.ReadFull(r.r, r.b[:4])
|
||||
if r.err != nil {
|
||||
if debug {
|
||||
dl.Printf("rd uint32: %v", r.err)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
v := uint32(r.b[3]) | uint32(r.b[2])<<8 | uint32(r.b[1])<<16 | uint32(r.b[0])<<24
|
||||
|
||||
if debug {
|
||||
dl.Printf("rd uint32=%d (0x%08x)", v, v)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func (r *Reader) ReadUint64() uint64 {
|
||||
if r.err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
_, r.err = io.ReadFull(r.r, r.b[:8])
|
||||
if r.err != nil {
|
||||
if debug {
|
||||
dl.Printf("rd uint64: %v", r.err)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
v := uint64(r.b[7]) | uint64(r.b[6])<<8 | uint64(r.b[5])<<16 | uint64(r.b[4])<<24 |
|
||||
uint64(r.b[3])<<32 | uint64(r.b[2])<<40 | uint64(r.b[1])<<48 | uint64(r.b[0])<<56
|
||||
|
||||
if debug {
|
||||
dl.Printf("rd uint64=%d (0x%016x)", v, v)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
type XDRError struct {
|
||||
op string
|
||||
err error
|
||||
}
|
||||
|
||||
func (e XDRError) Error() string {
|
||||
return "xdr " + e.op + ": " + e.err.Error()
|
||||
}
|
||||
|
||||
func (e XDRError) IsEOF() bool {
|
||||
return e.err == io.EOF
|
||||
}
|
||||
|
||||
func (r *Reader) Error() error {
|
||||
if r.err == nil {
|
||||
return nil
|
||||
}
|
||||
return XDRError{"read", r.err}
|
||||
}
|
||||
|
||||
func ElementSizeExceeded(field string, size, limit int) error {
|
||||
return fmt.Errorf("%s exceeds size limit; %d > %d", field, size, limit)
|
||||
}
|
||||
49
Godeps/_workspace/src/github.com/calmh/xdr/reader_ipdr.go
generated
vendored
Normal file
49
Godeps/_workspace/src/github.com/calmh/xdr/reader_ipdr.go
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright (C) 2014 Jakob Borg and Contributors (see the CONTRIBUTORS file).
|
||||
// All rights reserved. Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ipdr
|
||||
|
||||
package xdr
|
||||
|
||||
import "io"
|
||||
|
||||
func (r *Reader) ReadUint8() uint8 {
|
||||
if r.err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
_, r.err = io.ReadFull(r.r, r.b[:1])
|
||||
if r.err != nil {
|
||||
if debug {
|
||||
dl.Printf("rd uint8: %v", r.err)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
if debug {
|
||||
dl.Printf("rd uint8=%d (0x%02x)", r.b[0], r.b[0])
|
||||
}
|
||||
return r.b[0]
|
||||
}
|
||||
|
||||
func (r *Reader) ReadUint16() uint16 {
|
||||
if r.err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
_, r.err = io.ReadFull(r.r, r.b[:2])
|
||||
if r.err != nil {
|
||||
if debug {
|
||||
dl.Printf("rd uint16: %v", r.err)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
v := uint16(r.b[1]) | uint16(r.b[0])<<8
|
||||
|
||||
if debug {
|
||||
dl.Printf("rd uint16=%d (0x%04x)", v, v)
|
||||
}
|
||||
return v
|
||||
}
|
||||
15
Godeps/_workspace/src/github.com/calmh/xdr/reader_xdr.go
generated
vendored
Normal file
15
Godeps/_workspace/src/github.com/calmh/xdr/reader_xdr.go
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
// Copyright (C) 2014 Jakob Borg and Contributors (see the CONTRIBUTORS file).
|
||||
// All rights reserved. Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !ipdr
|
||||
|
||||
package xdr
|
||||
|
||||
func (r *Reader) ReadUint8() uint8 {
|
||||
return uint8(r.ReadUint32())
|
||||
}
|
||||
|
||||
func (r *Reader) ReadUint16() uint16 {
|
||||
return uint16(r.ReadUint32())
|
||||
}
|
||||
82
xdr/writer.go → Godeps/_workspace/src/github.com/calmh/xdr/writer.go
generated
vendored
82
xdr/writer.go → Godeps/_workspace/src/github.com/calmh/xdr/writer.go
generated
vendored
@@ -1,14 +1,13 @@
|
||||
// Copyright (C) 2014 Jakob Borg. All rights reserved. Use of this source code
|
||||
// is governed by an MIT-style license that can be found in the LICENSE file.
|
||||
|
||||
package xdr
|
||||
|
||||
import "io"
|
||||
|
||||
func pad(l int) int {
|
||||
d := l % 4
|
||||
if d == 0 {
|
||||
return 0
|
||||
}
|
||||
return 4 - d
|
||||
}
|
||||
import (
|
||||
"io"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var padBytes = []byte{0, 0, 0}
|
||||
|
||||
@@ -19,14 +18,37 @@ type Writer struct {
|
||||
b [8]byte
|
||||
}
|
||||
|
||||
type AppendWriter []byte
|
||||
|
||||
func (w *AppendWriter) Write(bs []byte) (int, error) {
|
||||
*w = append(*w, bs...)
|
||||
return len(bs), nil
|
||||
}
|
||||
|
||||
func NewWriter(w io.Writer) *Writer {
|
||||
return &Writer{
|
||||
w: w,
|
||||
}
|
||||
}
|
||||
|
||||
func (w *Writer) WriteRaw(bs []byte) (int, error) {
|
||||
if w.err != nil {
|
||||
return 0, w.err
|
||||
}
|
||||
|
||||
var n int
|
||||
n, w.err = w.w.Write(bs)
|
||||
return n, w.err
|
||||
}
|
||||
|
||||
func (w *Writer) WriteString(s string) (int, error) {
|
||||
return w.WriteBytes([]byte(s))
|
||||
sh := *((*reflect.StringHeader)(unsafe.Pointer(&s)))
|
||||
bh := reflect.SliceHeader{
|
||||
Data: sh.Data,
|
||||
Len: sh.Len,
|
||||
Cap: sh.Len,
|
||||
}
|
||||
return w.WriteBytes(*(*[]byte)(unsafe.Pointer(&bh)))
|
||||
}
|
||||
|
||||
func (w *Writer) WriteBytes(bs []byte) (int, error) {
|
||||
@@ -39,6 +61,14 @@ func (w *Writer) WriteBytes(bs []byte) (int, error) {
|
||||
return 0, w.err
|
||||
}
|
||||
|
||||
if debug {
|
||||
if len(bs) > maxDebugBytes {
|
||||
dl.Printf("wr bytes (%d): %x...", len(bs), bs[:maxDebugBytes])
|
||||
} else {
|
||||
dl.Printf("wr bytes (%d): %x", len(bs), bs)
|
||||
}
|
||||
}
|
||||
|
||||
var l, n int
|
||||
n, w.err = w.w.Write(bs)
|
||||
l += n
|
||||
@@ -52,25 +82,23 @@ func (w *Writer) WriteBytes(bs []byte) (int, error) {
|
||||
return l, w.err
|
||||
}
|
||||
|
||||
func (w *Writer) WriteUint16(v uint16) (int, error) {
|
||||
if w.err != nil {
|
||||
return 0, w.err
|
||||
func (w *Writer) WriteBool(v bool) (int, error) {
|
||||
if v {
|
||||
return w.WriteUint8(1)
|
||||
} else {
|
||||
return w.WriteUint8(0)
|
||||
}
|
||||
w.b[0] = byte(v >> 8)
|
||||
w.b[1] = byte(v)
|
||||
w.b[2] = 0
|
||||
w.b[3] = 0
|
||||
|
||||
var l int
|
||||
l, w.err = w.w.Write(w.b[:4])
|
||||
w.tot += l
|
||||
return l, w.err
|
||||
}
|
||||
|
||||
func (w *Writer) WriteUint32(v uint32) (int, error) {
|
||||
if w.err != nil {
|
||||
return 0, w.err
|
||||
}
|
||||
|
||||
if debug {
|
||||
dl.Printf("wr uint32=%d", v)
|
||||
}
|
||||
|
||||
w.b[0] = byte(v >> 24)
|
||||
w.b[1] = byte(v >> 16)
|
||||
w.b[2] = byte(v >> 8)
|
||||
@@ -86,6 +114,11 @@ func (w *Writer) WriteUint64(v uint64) (int, error) {
|
||||
if w.err != nil {
|
||||
return 0, w.err
|
||||
}
|
||||
|
||||
if debug {
|
||||
dl.Printf("wr uint64=%d", v)
|
||||
}
|
||||
|
||||
w.b[0] = byte(v >> 56)
|
||||
w.b[1] = byte(v >> 48)
|
||||
w.b[2] = byte(v >> 40)
|
||||
@@ -106,5 +139,8 @@ func (w *Writer) Tot() int {
|
||||
}
|
||||
|
||||
func (w *Writer) Error() error {
|
||||
return w.err
|
||||
if w.err == nil {
|
||||
return nil
|
||||
}
|
||||
return XDRError{"write", w.err}
|
||||
}
|
||||
41
Godeps/_workspace/src/github.com/calmh/xdr/writer_ipdr.go
generated
vendored
Normal file
41
Godeps/_workspace/src/github.com/calmh/xdr/writer_ipdr.go
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
// Copyright (C) 2014 Jakob Borg. All rights reserved. Use of this source code
|
||||
// is governed by an MIT-style license that can be found in the LICENSE file.
|
||||
|
||||
// +build ipdr
|
||||
|
||||
package xdr
|
||||
|
||||
func (w *Writer) WriteUint8(v uint8) (int, error) {
|
||||
if w.err != nil {
|
||||
return 0, w.err
|
||||
}
|
||||
|
||||
if debug {
|
||||
dl.Printf("wr uint8=%d", v)
|
||||
}
|
||||
|
||||
w.b[0] = byte(v)
|
||||
|
||||
var l int
|
||||
l, w.err = w.w.Write(w.b[:1])
|
||||
w.tot += l
|
||||
return l, w.err
|
||||
}
|
||||
|
||||
func (w *Writer) WriteUint16(v uint16) (int, error) {
|
||||
if w.err != nil {
|
||||
return 0, w.err
|
||||
}
|
||||
|
||||
if debug {
|
||||
dl.Printf("wr uint8=%d", v)
|
||||
}
|
||||
|
||||
w.b[0] = byte(v >> 8)
|
||||
w.b[1] = byte(v)
|
||||
|
||||
var l int
|
||||
l, w.err = w.w.Write(w.b[:2])
|
||||
w.tot += l
|
||||
return l, w.err
|
||||
}
|
||||
14
Godeps/_workspace/src/github.com/calmh/xdr/writer_xdr.go
generated
vendored
Normal file
14
Godeps/_workspace/src/github.com/calmh/xdr/writer_xdr.go
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
// Copyright (C) 2014 Jakob Borg. All rights reserved. Use of this source code
|
||||
// is governed by an MIT-style license that can be found in the LICENSE file.
|
||||
|
||||
// +build !ipdr
|
||||
|
||||
package xdr
|
||||
|
||||
func (w *Writer) WriteUint8(v uint8) (int, error) {
|
||||
return w.WriteUint32(uint32(v))
|
||||
}
|
||||
|
||||
func (w *Writer) WriteUint16(v uint16) (int, error) {
|
||||
return w.WriteUint32(uint32(v))
|
||||
}
|
||||
14
Godeps/_workspace/src/github.com/golang/snappy/AUTHORS
generated
vendored
Normal file
14
Godeps/_workspace/src/github.com/golang/snappy/AUTHORS
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
# This is the official list of Snappy-Go authors for copyright purposes.
|
||||
# This file is distinct from the CONTRIBUTORS files.
|
||||
# See the latter for an explanation.
|
||||
|
||||
# Names should be added to this file as
|
||||
# Name or Organization <email address>
|
||||
# The email address is not required for organizations.
|
||||
|
||||
# Please keep the list sorted.
|
||||
|
||||
Damian Gryski <dgryski@gmail.com>
|
||||
Google Inc.
|
||||
Jan Mercl <0xjnml@gmail.com>
|
||||
Sebastien Binet <seb.binet@gmail.com>
|
||||
36
Godeps/_workspace/src/github.com/golang/snappy/CONTRIBUTORS
generated
vendored
Normal file
36
Godeps/_workspace/src/github.com/golang/snappy/CONTRIBUTORS
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
# This is the official list of people who can contribute
|
||||
# (and typically have contributed) code to the Snappy-Go repository.
|
||||
# The AUTHORS file lists the copyright holders; this file
|
||||
# lists people. For example, Google employees are listed here
|
||||
# but not in AUTHORS, because Google holds the copyright.
|
||||
#
|
||||
# The submission process automatically checks to make sure
|
||||
# that people submitting code are listed in this file (by email address).
|
||||
#
|
||||
# Names should be added to this file only after verifying that
|
||||
# the individual or the individual's organization has agreed to
|
||||
# the appropriate Contributor License Agreement, found here:
|
||||
#
|
||||
# http://code.google.com/legal/individual-cla-v1.0.html
|
||||
# http://code.google.com/legal/corporate-cla-v1.0.html
|
||||
#
|
||||
# The agreement for individuals can be filled out on the web.
|
||||
#
|
||||
# When adding J Random Contributor's name to this file,
|
||||
# either J's name or J's organization's name should be
|
||||
# added to the AUTHORS file, depending on whether the
|
||||
# individual or corporate CLA was used.
|
||||
|
||||
# Names should be added to this file like so:
|
||||
# Name <email address>
|
||||
|
||||
# Please keep the list sorted.
|
||||
|
||||
Damian Gryski <dgryski@gmail.com>
|
||||
Jan Mercl <0xjnml@gmail.com>
|
||||
Kai Backman <kaib@golang.org>
|
||||
Marc-Antoine Ruel <maruel@chromium.org>
|
||||
Nigel Tao <nigeltao@golang.org>
|
||||
Rob Pike <r@golang.org>
|
||||
Russ Cox <rsc@golang.org>
|
||||
Sebastien Binet <seb.binet@gmail.com>
|
||||
27
Godeps/_workspace/src/github.com/golang/snappy/LICENSE
generated
vendored
Normal file
27
Godeps/_workspace/src/github.com/golang/snappy/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
Copyright (c) 2011 The Snappy-Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
7
Godeps/_workspace/src/github.com/golang/snappy/README
generated
vendored
Normal file
7
Godeps/_workspace/src/github.com/golang/snappy/README
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
The Snappy compression format in the Go programming language.
|
||||
|
||||
To download and install from source:
|
||||
$ go get github.com/golang/snappy
|
||||
|
||||
Unless otherwise noted, the Snappy-Go source files are distributed
|
||||
under the BSD-style license found in the LICENSE file.
|
||||
294
Godeps/_workspace/src/github.com/golang/snappy/decode.go
generated
vendored
Normal file
294
Godeps/_workspace/src/github.com/golang/snappy/decode.go
generated
vendored
Normal file
@@ -0,0 +1,294 @@
|
||||
// Copyright 2011 The Snappy-Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package snappy
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"io"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrCorrupt reports that the input is invalid.
|
||||
ErrCorrupt = errors.New("snappy: corrupt input")
|
||||
// ErrTooLarge reports that the uncompressed length is too large.
|
||||
ErrTooLarge = errors.New("snappy: decoded block is too large")
|
||||
// ErrUnsupported reports that the input isn't supported.
|
||||
ErrUnsupported = errors.New("snappy: unsupported input")
|
||||
)
|
||||
|
||||
// DecodedLen returns the length of the decoded block.
|
||||
func DecodedLen(src []byte) (int, error) {
|
||||
v, _, err := decodedLen(src)
|
||||
return v, err
|
||||
}
|
||||
|
||||
// decodedLen returns the length of the decoded block and the number of bytes
|
||||
// that the length header occupied.
|
||||
func decodedLen(src []byte) (blockLen, headerLen int, err error) {
|
||||
v, n := binary.Uvarint(src)
|
||||
if n <= 0 || v > 0xffffffff {
|
||||
return 0, 0, ErrCorrupt
|
||||
}
|
||||
|
||||
const wordSize = 32 << (^uint(0) >> 32 & 1)
|
||||
if wordSize == 32 && v > 0x7fffffff {
|
||||
return 0, 0, ErrTooLarge
|
||||
}
|
||||
return int(v), n, nil
|
||||
}
|
||||
|
||||
// Decode returns the decoded form of src. The returned slice may be a sub-
|
||||
// slice of dst if dst was large enough to hold the entire decoded block.
|
||||
// Otherwise, a newly allocated slice will be returned.
|
||||
// It is valid to pass a nil dst.
|
||||
func Decode(dst, src []byte) ([]byte, error) {
|
||||
dLen, s, err := decodedLen(src)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(dst) < dLen {
|
||||
dst = make([]byte, dLen)
|
||||
}
|
||||
|
||||
var d, offset, length int
|
||||
for s < len(src) {
|
||||
switch src[s] & 0x03 {
|
||||
case tagLiteral:
|
||||
x := uint(src[s] >> 2)
|
||||
switch {
|
||||
case x < 60:
|
||||
s++
|
||||
case x == 60:
|
||||
s += 2
|
||||
if s > len(src) {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
x = uint(src[s-1])
|
||||
case x == 61:
|
||||
s += 3
|
||||
if s > len(src) {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
x = uint(src[s-2]) | uint(src[s-1])<<8
|
||||
case x == 62:
|
||||
s += 4
|
||||
if s > len(src) {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
x = uint(src[s-3]) | uint(src[s-2])<<8 | uint(src[s-1])<<16
|
||||
case x == 63:
|
||||
s += 5
|
||||
if s > len(src) {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
x = uint(src[s-4]) | uint(src[s-3])<<8 | uint(src[s-2])<<16 | uint(src[s-1])<<24
|
||||
}
|
||||
length = int(x + 1)
|
||||
if length <= 0 {
|
||||
return nil, errors.New("snappy: unsupported literal length")
|
||||
}
|
||||
if length > len(dst)-d || length > len(src)-s {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
copy(dst[d:], src[s:s+length])
|
||||
d += length
|
||||
s += length
|
||||
continue
|
||||
|
||||
case tagCopy1:
|
||||
s += 2
|
||||
if s > len(src) {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
length = 4 + int(src[s-2])>>2&0x7
|
||||
offset = int(src[s-2])&0xe0<<3 | int(src[s-1])
|
||||
|
||||
case tagCopy2:
|
||||
s += 3
|
||||
if s > len(src) {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
length = 1 + int(src[s-3])>>2
|
||||
offset = int(src[s-2]) | int(src[s-1])<<8
|
||||
|
||||
case tagCopy4:
|
||||
return nil, errors.New("snappy: unsupported COPY_4 tag")
|
||||
}
|
||||
|
||||
end := d + length
|
||||
if offset > d || end > len(dst) {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
for ; d < end; d++ {
|
||||
dst[d] = dst[d-offset]
|
||||
}
|
||||
}
|
||||
if d != dLen {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
return dst[:d], nil
|
||||
}
|
||||
|
||||
// NewReader returns a new Reader that decompresses from r, using the framing
|
||||
// format described at
|
||||
// https://github.com/google/snappy/blob/master/framing_format.txt
|
||||
func NewReader(r io.Reader) *Reader {
|
||||
return &Reader{
|
||||
r: r,
|
||||
decoded: make([]byte, maxUncompressedChunkLen),
|
||||
buf: make([]byte, MaxEncodedLen(maxUncompressedChunkLen)+checksumSize),
|
||||
}
|
||||
}
|
||||
|
||||
// Reader is an io.Reader than can read Snappy-compressed bytes.
|
||||
type Reader struct {
|
||||
r io.Reader
|
||||
err error
|
||||
decoded []byte
|
||||
buf []byte
|
||||
// decoded[i:j] contains decoded bytes that have not yet been passed on.
|
||||
i, j int
|
||||
readHeader bool
|
||||
}
|
||||
|
||||
// Reset discards any buffered data, resets all state, and switches the Snappy
|
||||
// reader to read from r. This permits reusing a Reader rather than allocating
|
||||
// a new one.
|
||||
func (r *Reader) Reset(reader io.Reader) {
|
||||
r.r = reader
|
||||
r.err = nil
|
||||
r.i = 0
|
||||
r.j = 0
|
||||
r.readHeader = false
|
||||
}
|
||||
|
||||
func (r *Reader) readFull(p []byte) (ok bool) {
|
||||
if _, r.err = io.ReadFull(r.r, p); r.err != nil {
|
||||
if r.err == io.ErrUnexpectedEOF {
|
||||
r.err = ErrCorrupt
|
||||
}
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Read satisfies the io.Reader interface.
|
||||
func (r *Reader) Read(p []byte) (int, error) {
|
||||
if r.err != nil {
|
||||
return 0, r.err
|
||||
}
|
||||
for {
|
||||
if r.i < r.j {
|
||||
n := copy(p, r.decoded[r.i:r.j])
|
||||
r.i += n
|
||||
return n, nil
|
||||
}
|
||||
if !r.readFull(r.buf[:4]) {
|
||||
return 0, r.err
|
||||
}
|
||||
chunkType := r.buf[0]
|
||||
if !r.readHeader {
|
||||
if chunkType != chunkTypeStreamIdentifier {
|
||||
r.err = ErrCorrupt
|
||||
return 0, r.err
|
||||
}
|
||||
r.readHeader = true
|
||||
}
|
||||
chunkLen := int(r.buf[1]) | int(r.buf[2])<<8 | int(r.buf[3])<<16
|
||||
if chunkLen > len(r.buf) {
|
||||
r.err = ErrUnsupported
|
||||
return 0, r.err
|
||||
}
|
||||
|
||||
// The chunk types are specified at
|
||||
// https://github.com/google/snappy/blob/master/framing_format.txt
|
||||
switch chunkType {
|
||||
case chunkTypeCompressedData:
|
||||
// Section 4.2. Compressed data (chunk type 0x00).
|
||||
if chunkLen < checksumSize {
|
||||
r.err = ErrCorrupt
|
||||
return 0, r.err
|
||||
}
|
||||
buf := r.buf[:chunkLen]
|
||||
if !r.readFull(buf) {
|
||||
return 0, r.err
|
||||
}
|
||||
checksum := uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24
|
||||
buf = buf[checksumSize:]
|
||||
|
||||
n, err := DecodedLen(buf)
|
||||
if err != nil {
|
||||
r.err = err
|
||||
return 0, r.err
|
||||
}
|
||||
if n > len(r.decoded) {
|
||||
r.err = ErrCorrupt
|
||||
return 0, r.err
|
||||
}
|
||||
if _, err := Decode(r.decoded, buf); err != nil {
|
||||
r.err = err
|
||||
return 0, r.err
|
||||
}
|
||||
if crc(r.decoded[:n]) != checksum {
|
||||
r.err = ErrCorrupt
|
||||
return 0, r.err
|
||||
}
|
||||
r.i, r.j = 0, n
|
||||
continue
|
||||
|
||||
case chunkTypeUncompressedData:
|
||||
// Section 4.3. Uncompressed data (chunk type 0x01).
|
||||
if chunkLen < checksumSize {
|
||||
r.err = ErrCorrupt
|
||||
return 0, r.err
|
||||
}
|
||||
buf := r.buf[:checksumSize]
|
||||
if !r.readFull(buf) {
|
||||
return 0, r.err
|
||||
}
|
||||
checksum := uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24
|
||||
// Read directly into r.decoded instead of via r.buf.
|
||||
n := chunkLen - checksumSize
|
||||
if !r.readFull(r.decoded[:n]) {
|
||||
return 0, r.err
|
||||
}
|
||||
if crc(r.decoded[:n]) != checksum {
|
||||
r.err = ErrCorrupt
|
||||
return 0, r.err
|
||||
}
|
||||
r.i, r.j = 0, n
|
||||
continue
|
||||
|
||||
case chunkTypeStreamIdentifier:
|
||||
// Section 4.1. Stream identifier (chunk type 0xff).
|
||||
if chunkLen != len(magicBody) {
|
||||
r.err = ErrCorrupt
|
||||
return 0, r.err
|
||||
}
|
||||
if !r.readFull(r.buf[:len(magicBody)]) {
|
||||
return 0, r.err
|
||||
}
|
||||
for i := 0; i < len(magicBody); i++ {
|
||||
if r.buf[i] != magicBody[i] {
|
||||
r.err = ErrCorrupt
|
||||
return 0, r.err
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if chunkType <= 0x7f {
|
||||
// Section 4.5. Reserved unskippable chunks (chunk types 0x02-0x7f).
|
||||
r.err = ErrUnsupported
|
||||
return 0, r.err
|
||||
}
|
||||
// Section 4.4 Padding (chunk type 0xfe).
|
||||
// Section 4.6. Reserved skippable chunks (chunk types 0x80-0xfd).
|
||||
if !r.readFull(r.buf[:chunkLen]) {
|
||||
return 0, r.err
|
||||
}
|
||||
}
|
||||
}
|
||||
254
Godeps/_workspace/src/github.com/golang/snappy/encode.go
generated
vendored
Normal file
254
Godeps/_workspace/src/github.com/golang/snappy/encode.go
generated
vendored
Normal file
@@ -0,0 +1,254 @@
|
||||
// Copyright 2011 The Snappy-Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package snappy
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"io"
|
||||
)
|
||||
|
||||
// We limit how far copy back-references can go, the same as the C++ code.
|
||||
const maxOffset = 1 << 15
|
||||
|
||||
// emitLiteral writes a literal chunk and returns the number of bytes written.
|
||||
func emitLiteral(dst, lit []byte) int {
|
||||
i, n := 0, uint(len(lit)-1)
|
||||
switch {
|
||||
case n < 60:
|
||||
dst[0] = uint8(n)<<2 | tagLiteral
|
||||
i = 1
|
||||
case n < 1<<8:
|
||||
dst[0] = 60<<2 | tagLiteral
|
||||
dst[1] = uint8(n)
|
||||
i = 2
|
||||
case n < 1<<16:
|
||||
dst[0] = 61<<2 | tagLiteral
|
||||
dst[1] = uint8(n)
|
||||
dst[2] = uint8(n >> 8)
|
||||
i = 3
|
||||
case n < 1<<24:
|
||||
dst[0] = 62<<2 | tagLiteral
|
||||
dst[1] = uint8(n)
|
||||
dst[2] = uint8(n >> 8)
|
||||
dst[3] = uint8(n >> 16)
|
||||
i = 4
|
||||
case int64(n) < 1<<32:
|
||||
dst[0] = 63<<2 | tagLiteral
|
||||
dst[1] = uint8(n)
|
||||
dst[2] = uint8(n >> 8)
|
||||
dst[3] = uint8(n >> 16)
|
||||
dst[4] = uint8(n >> 24)
|
||||
i = 5
|
||||
default:
|
||||
panic("snappy: source buffer is too long")
|
||||
}
|
||||
if copy(dst[i:], lit) != len(lit) {
|
||||
panic("snappy: destination buffer is too short")
|
||||
}
|
||||
return i + len(lit)
|
||||
}
|
||||
|
||||
// emitCopy writes a copy chunk and returns the number of bytes written.
|
||||
func emitCopy(dst []byte, offset, length int) int {
|
||||
i := 0
|
||||
for length > 0 {
|
||||
x := length - 4
|
||||
if 0 <= x && x < 1<<3 && offset < 1<<11 {
|
||||
dst[i+0] = uint8(offset>>8)&0x07<<5 | uint8(x)<<2 | tagCopy1
|
||||
dst[i+1] = uint8(offset)
|
||||
i += 2
|
||||
break
|
||||
}
|
||||
|
||||
x = length
|
||||
if x > 1<<6 {
|
||||
x = 1 << 6
|
||||
}
|
||||
dst[i+0] = uint8(x-1)<<2 | tagCopy2
|
||||
dst[i+1] = uint8(offset)
|
||||
dst[i+2] = uint8(offset >> 8)
|
||||
i += 3
|
||||
length -= x
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
// Encode returns the encoded form of src. The returned slice may be a sub-
|
||||
// slice of dst if dst was large enough to hold the entire encoded block.
|
||||
// Otherwise, a newly allocated slice will be returned.
|
||||
// It is valid to pass a nil dst.
|
||||
func Encode(dst, src []byte) []byte {
|
||||
if n := MaxEncodedLen(len(src)); len(dst) < n {
|
||||
dst = make([]byte, n)
|
||||
}
|
||||
|
||||
// The block starts with the varint-encoded length of the decompressed bytes.
|
||||
d := binary.PutUvarint(dst, uint64(len(src)))
|
||||
|
||||
// Return early if src is short.
|
||||
if len(src) <= 4 {
|
||||
if len(src) != 0 {
|
||||
d += emitLiteral(dst[d:], src)
|
||||
}
|
||||
return dst[:d]
|
||||
}
|
||||
|
||||
// Initialize the hash table. Its size ranges from 1<<8 to 1<<14 inclusive.
|
||||
const maxTableSize = 1 << 14
|
||||
shift, tableSize := uint(32-8), 1<<8
|
||||
for tableSize < maxTableSize && tableSize < len(src) {
|
||||
shift--
|
||||
tableSize *= 2
|
||||
}
|
||||
var table [maxTableSize]int
|
||||
|
||||
// Iterate over the source bytes.
|
||||
var (
|
||||
s int // The iterator position.
|
||||
t int // The last position with the same hash as s.
|
||||
lit int // The start position of any pending literal bytes.
|
||||
)
|
||||
for s+3 < len(src) {
|
||||
// Update the hash table.
|
||||
b0, b1, b2, b3 := src[s], src[s+1], src[s+2], src[s+3]
|
||||
h := uint32(b0) | uint32(b1)<<8 | uint32(b2)<<16 | uint32(b3)<<24
|
||||
p := &table[(h*0x1e35a7bd)>>shift]
|
||||
// We need to to store values in [-1, inf) in table. To save
|
||||
// some initialization time, (re)use the table's zero value
|
||||
// and shift the values against this zero: add 1 on writes,
|
||||
// subtract 1 on reads.
|
||||
t, *p = *p-1, s+1
|
||||
// If t is invalid or src[s:s+4] differs from src[t:t+4], accumulate a literal byte.
|
||||
if t < 0 || s-t >= maxOffset || b0 != src[t] || b1 != src[t+1] || b2 != src[t+2] || b3 != src[t+3] {
|
||||
s++
|
||||
continue
|
||||
}
|
||||
// Otherwise, we have a match. First, emit any pending literal bytes.
|
||||
if lit != s {
|
||||
d += emitLiteral(dst[d:], src[lit:s])
|
||||
}
|
||||
// Extend the match to be as long as possible.
|
||||
s0 := s
|
||||
s, t = s+4, t+4
|
||||
for s < len(src) && src[s] == src[t] {
|
||||
s++
|
||||
t++
|
||||
}
|
||||
// Emit the copied bytes.
|
||||
d += emitCopy(dst[d:], s-t, s-s0)
|
||||
lit = s
|
||||
}
|
||||
|
||||
// Emit any final pending literal bytes and return.
|
||||
if lit != len(src) {
|
||||
d += emitLiteral(dst[d:], src[lit:])
|
||||
}
|
||||
return dst[:d]
|
||||
}
|
||||
|
||||
// MaxEncodedLen returns the maximum length of a snappy block, given its
|
||||
// uncompressed length.
|
||||
func MaxEncodedLen(srcLen int) int {
|
||||
// Compressed data can be defined as:
|
||||
// compressed := item* literal*
|
||||
// item := literal* copy
|
||||
//
|
||||
// The trailing literal sequence has a space blowup of at most 62/60
|
||||
// since a literal of length 60 needs one tag byte + one extra byte
|
||||
// for length information.
|
||||
//
|
||||
// Item blowup is trickier to measure. Suppose the "copy" op copies
|
||||
// 4 bytes of data. Because of a special check in the encoding code,
|
||||
// we produce a 4-byte copy only if the offset is < 65536. Therefore
|
||||
// the copy op takes 3 bytes to encode, and this type of item leads
|
||||
// to at most the 62/60 blowup for representing literals.
|
||||
//
|
||||
// Suppose the "copy" op copies 5 bytes of data. If the offset is big
|
||||
// enough, it will take 5 bytes to encode the copy op. Therefore the
|
||||
// worst case here is a one-byte literal followed by a five-byte copy.
|
||||
// That is, 6 bytes of input turn into 7 bytes of "compressed" data.
|
||||
//
|
||||
// This last factor dominates the blowup, so the final estimate is:
|
||||
return 32 + srcLen + srcLen/6
|
||||
}
|
||||
|
||||
// NewWriter returns a new Writer that compresses to w, using the framing
|
||||
// format described at
|
||||
// https://github.com/google/snappy/blob/master/framing_format.txt
|
||||
func NewWriter(w io.Writer) *Writer {
|
||||
return &Writer{
|
||||
w: w,
|
||||
enc: make([]byte, MaxEncodedLen(maxUncompressedChunkLen)),
|
||||
}
|
||||
}
|
||||
|
||||
// Writer is an io.Writer than can write Snappy-compressed bytes.
|
||||
type Writer struct {
|
||||
w io.Writer
|
||||
err error
|
||||
enc []byte
|
||||
buf [checksumSize + chunkHeaderSize]byte
|
||||
wroteHeader bool
|
||||
}
|
||||
|
||||
// Reset discards the writer's state and switches the Snappy writer to write to
|
||||
// w. This permits reusing a Writer rather than allocating a new one.
|
||||
func (w *Writer) Reset(writer io.Writer) {
|
||||
w.w = writer
|
||||
w.err = nil
|
||||
w.wroteHeader = false
|
||||
}
|
||||
|
||||
// Write satisfies the io.Writer interface.
|
||||
func (w *Writer) Write(p []byte) (n int, errRet error) {
|
||||
if w.err != nil {
|
||||
return 0, w.err
|
||||
}
|
||||
if !w.wroteHeader {
|
||||
copy(w.enc, magicChunk)
|
||||
if _, err := w.w.Write(w.enc[:len(magicChunk)]); err != nil {
|
||||
w.err = err
|
||||
return n, err
|
||||
}
|
||||
w.wroteHeader = true
|
||||
}
|
||||
for len(p) > 0 {
|
||||
var uncompressed []byte
|
||||
if len(p) > maxUncompressedChunkLen {
|
||||
uncompressed, p = p[:maxUncompressedChunkLen], p[maxUncompressedChunkLen:]
|
||||
} else {
|
||||
uncompressed, p = p, nil
|
||||
}
|
||||
checksum := crc(uncompressed)
|
||||
|
||||
// Compress the buffer, discarding the result if the improvement
|
||||
// isn't at least 12.5%.
|
||||
chunkType := uint8(chunkTypeCompressedData)
|
||||
chunkBody := Encode(w.enc, uncompressed)
|
||||
if len(chunkBody) >= len(uncompressed)-len(uncompressed)/8 {
|
||||
chunkType, chunkBody = chunkTypeUncompressedData, uncompressed
|
||||
}
|
||||
|
||||
chunkLen := 4 + len(chunkBody)
|
||||
w.buf[0] = chunkType
|
||||
w.buf[1] = uint8(chunkLen >> 0)
|
||||
w.buf[2] = uint8(chunkLen >> 8)
|
||||
w.buf[3] = uint8(chunkLen >> 16)
|
||||
w.buf[4] = uint8(checksum >> 0)
|
||||
w.buf[5] = uint8(checksum >> 8)
|
||||
w.buf[6] = uint8(checksum >> 16)
|
||||
w.buf[7] = uint8(checksum >> 24)
|
||||
if _, err := w.w.Write(w.buf[:]); err != nil {
|
||||
w.err = err
|
||||
return n, err
|
||||
}
|
||||
if _, err := w.w.Write(chunkBody); err != nil {
|
||||
w.err = err
|
||||
return n, err
|
||||
}
|
||||
n += len(uncompressed)
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
68
Godeps/_workspace/src/github.com/golang/snappy/snappy.go
generated
vendored
Normal file
68
Godeps/_workspace/src/github.com/golang/snappy/snappy.go
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
// Copyright 2011 The Snappy-Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package snappy implements the snappy block-based compression format.
|
||||
// It aims for very high speeds and reasonable compression.
|
||||
//
|
||||
// The C++ snappy implementation is at https://github.com/google/snappy
|
||||
package snappy
|
||||
|
||||
import (
|
||||
"hash/crc32"
|
||||
)
|
||||
|
||||
/*
|
||||
Each encoded block begins with the varint-encoded length of the decoded data,
|
||||
followed by a sequence of chunks. Chunks begin and end on byte boundaries. The
|
||||
first byte of each chunk is broken into its 2 least and 6 most significant bits
|
||||
called l and m: l ranges in [0, 4) and m ranges in [0, 64). l is the chunk tag.
|
||||
Zero means a literal tag. All other values mean a copy tag.
|
||||
|
||||
For literal tags:
|
||||
- If m < 60, the next 1 + m bytes are literal bytes.
|
||||
- Otherwise, let n be the little-endian unsigned integer denoted by the next
|
||||
m - 59 bytes. The next 1 + n bytes after that are literal bytes.
|
||||
|
||||
For copy tags, length bytes are copied from offset bytes ago, in the style of
|
||||
Lempel-Ziv compression algorithms. In particular:
|
||||
- For l == 1, the offset ranges in [0, 1<<11) and the length in [4, 12).
|
||||
The length is 4 + the low 3 bits of m. The high 3 bits of m form bits 8-10
|
||||
of the offset. The next byte is bits 0-7 of the offset.
|
||||
- For l == 2, the offset ranges in [0, 1<<16) and the length in [1, 65).
|
||||
The length is 1 + m. The offset is the little-endian unsigned integer
|
||||
denoted by the next 2 bytes.
|
||||
- For l == 3, this tag is a legacy format that is no longer supported.
|
||||
*/
|
||||
const (
|
||||
tagLiteral = 0x00
|
||||
tagCopy1 = 0x01
|
||||
tagCopy2 = 0x02
|
||||
tagCopy4 = 0x03
|
||||
)
|
||||
|
||||
const (
|
||||
checksumSize = 4
|
||||
chunkHeaderSize = 4
|
||||
magicChunk = "\xff\x06\x00\x00" + magicBody
|
||||
magicBody = "sNaPpY"
|
||||
// https://github.com/google/snappy/blob/master/framing_format.txt says
|
||||
// that "the uncompressed data in a chunk must be no longer than 65536 bytes".
|
||||
maxUncompressedChunkLen = 65536
|
||||
)
|
||||
|
||||
const (
|
||||
chunkTypeCompressedData = 0x00
|
||||
chunkTypeUncompressedData = 0x01
|
||||
chunkTypePadding = 0xfe
|
||||
chunkTypeStreamIdentifier = 0xff
|
||||
)
|
||||
|
||||
var crcTable = crc32.MakeTable(crc32.Castagnoli)
|
||||
|
||||
// crc implements the checksum specified in section 3 of
|
||||
// https://github.com/google/snappy/blob/master/framing_format.txt
|
||||
func crc(b []byte) uint32 {
|
||||
c := crc32.Update(0, crcTable, b)
|
||||
return uint32(c>>15|c<<17) + 0xa282ead8
|
||||
}
|
||||
191
Godeps/_workspace/src/github.com/juju/ratelimit/LICENSE
generated
vendored
Normal file
191
Godeps/_workspace/src/github.com/juju/ratelimit/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,191 @@
|
||||
All files in this repository are licensed as follows. If you contribute
|
||||
to this repository, it is assumed that you license your contribution
|
||||
under the same license unless you state otherwise.
|
||||
|
||||
All files Copyright (C) 2015 Canonical Ltd. unless otherwise specified in the file.
|
||||
|
||||
This software is licensed under the LGPLv3, included below.
|
||||
|
||||
As a special exception to the GNU Lesser General Public License version 3
|
||||
("LGPL3"), the copyright holders of this Library give you permission to
|
||||
convey to a third party a Combined Work that links statically or dynamically
|
||||
to this Library without providing any Minimal Corresponding Source or
|
||||
Minimal Application Code as set out in 4d or providing the installation
|
||||
information set out in section 4e, provided that you comply with the other
|
||||
provisions of LGPL3 and provided that you meet, for the Application the
|
||||
terms and conditions of the license(s) which apply to the Application.
|
||||
|
||||
Except as stated in this special exception, the provisions of LGPL3 will
|
||||
continue to comply in full to this Library. If you modify this Library, you
|
||||
may apply this exception to your version of this Library, but you are not
|
||||
obliged to do so. If you do not wish to do so, delete this exception
|
||||
statement from your version. This exception does not (and cannot) modify any
|
||||
license terms which apply to the Application, with which you must still
|
||||
comply.
|
||||
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
117
Godeps/_workspace/src/github.com/juju/ratelimit/README.md
generated
vendored
Normal file
117
Godeps/_workspace/src/github.com/juju/ratelimit/README.md
generated
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
# ratelimit
|
||||
--
|
||||
import "github.com/juju/ratelimit"
|
||||
|
||||
The ratelimit package provides an efficient token bucket implementation. See
|
||||
http://en.wikipedia.org/wiki/Token_bucket.
|
||||
|
||||
## Usage
|
||||
|
||||
#### func Reader
|
||||
|
||||
```go
|
||||
func Reader(r io.Reader, bucket *Bucket) io.Reader
|
||||
```
|
||||
Reader returns a reader that is rate limited by the given token bucket. Each
|
||||
token in the bucket represents one byte.
|
||||
|
||||
#### func Writer
|
||||
|
||||
```go
|
||||
func Writer(w io.Writer, bucket *Bucket) io.Writer
|
||||
```
|
||||
Writer returns a writer that is rate limited by the given token bucket. Each
|
||||
token in the bucket represents one byte.
|
||||
|
||||
#### type Bucket
|
||||
|
||||
```go
|
||||
type Bucket struct {
|
||||
}
|
||||
```
|
||||
|
||||
Bucket represents a token bucket that fills at a predetermined rate. Methods on
|
||||
Bucket may be called concurrently.
|
||||
|
||||
#### func NewBucket
|
||||
|
||||
```go
|
||||
func NewBucket(fillInterval time.Duration, capacity int64) *Bucket
|
||||
```
|
||||
NewBucket returns a new token bucket that fills at the rate of one token every
|
||||
fillInterval, up to the given maximum capacity. Both arguments must be positive.
|
||||
The bucket is initially full.
|
||||
|
||||
#### func NewBucketWithQuantum
|
||||
|
||||
```go
|
||||
func NewBucketWithQuantum(fillInterval time.Duration, capacity, quantum int64) *Bucket
|
||||
```
|
||||
NewBucketWithQuantum is similar to NewBucket, but allows the specification of
|
||||
the quantum size - quantum tokens are added every fillInterval.
|
||||
|
||||
#### func NewBucketWithRate
|
||||
|
||||
```go
|
||||
func NewBucketWithRate(rate float64, capacity int64) *Bucket
|
||||
```
|
||||
NewBucketWithRate returns a token bucket that fills the bucket at the rate of
|
||||
rate tokens per second up to the given maximum capacity. Because of limited
|
||||
clock resolution, at high rates, the actual rate may be up to 1% different from
|
||||
the specified rate.
|
||||
|
||||
#### func (*Bucket) Rate
|
||||
|
||||
```go
|
||||
func (tb *Bucket) Rate() float64
|
||||
```
|
||||
Rate returns the fill rate of the bucket, in tokens per second.
|
||||
|
||||
#### func (*Bucket) Take
|
||||
|
||||
```go
|
||||
func (tb *Bucket) Take(count int64) time.Duration
|
||||
```
|
||||
Take takes count tokens from the bucket without blocking. It returns the time
|
||||
that the caller should wait until the tokens are actually available.
|
||||
|
||||
Note that if the request is irrevocable - there is no way to return tokens to
|
||||
the bucket once this method commits us to taking them.
|
||||
|
||||
#### func (*Bucket) TakeAvailable
|
||||
|
||||
```go
|
||||
func (tb *Bucket) TakeAvailable(count int64) int64
|
||||
```
|
||||
TakeAvailable takes up to count immediately available tokens from the bucket. It
|
||||
returns the number of tokens removed, or zero if there are no available tokens.
|
||||
It does not block.
|
||||
|
||||
#### func (*Bucket) TakeMaxDuration
|
||||
|
||||
```go
|
||||
func (tb *Bucket) TakeMaxDuration(count int64, maxWait time.Duration) (time.Duration, bool)
|
||||
```
|
||||
TakeMaxDuration is like Take, except that it will only take tokens from the
|
||||
bucket if the wait time for the tokens is no greater than maxWait.
|
||||
|
||||
If it would take longer than maxWait for the tokens to become available, it does
|
||||
nothing and reports false, otherwise it returns the time that the caller should
|
||||
wait until the tokens are actually available, and reports true.
|
||||
|
||||
#### func (*Bucket) Wait
|
||||
|
||||
```go
|
||||
func (tb *Bucket) Wait(count int64)
|
||||
```
|
||||
Wait takes count tokens from the bucket, waiting until they are available.
|
||||
|
||||
#### func (*Bucket) WaitMaxDuration
|
||||
|
||||
```go
|
||||
func (tb *Bucket) WaitMaxDuration(count int64, maxWait time.Duration) bool
|
||||
```
|
||||
WaitMaxDuration is like Wait except that it will only take tokens from the
|
||||
bucket if it needs to wait for no greater than maxWait. It reports whether any
|
||||
tokens have been removed from the bucket If no tokens have been removed, it
|
||||
returns immediately.
|
||||
221
Godeps/_workspace/src/github.com/juju/ratelimit/ratelimit.go
generated
vendored
Normal file
221
Godeps/_workspace/src/github.com/juju/ratelimit/ratelimit.go
generated
vendored
Normal file
@@ -0,0 +1,221 @@
|
||||
// Copyright 2014 Canonical Ltd.
|
||||
// Licensed under the LGPLv3 with static-linking exception.
|
||||
// See LICENCE file for details.
|
||||
|
||||
// The ratelimit package provides an efficient token bucket implementation
|
||||
// that can be used to limit the rate of arbitrary things.
|
||||
// See http://en.wikipedia.org/wiki/Token_bucket.
|
||||
package ratelimit
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
"math"
|
||||
)
|
||||
|
||||
// Bucket represents a token bucket that fills at a predetermined rate.
|
||||
// Methods on Bucket may be called concurrently.
|
||||
type Bucket struct {
|
||||
startTime time.Time
|
||||
capacity int64
|
||||
quantum int64
|
||||
fillInterval time.Duration
|
||||
|
||||
// The mutex guards the fields following it.
|
||||
mu sync.Mutex
|
||||
|
||||
// avail holds the number of available tokens
|
||||
// in the bucket, as of availTick ticks from startTime.
|
||||
// It will be negative when there are consumers
|
||||
// waiting for tokens.
|
||||
avail int64
|
||||
availTick int64
|
||||
}
|
||||
|
||||
// NewBucket returns a new token bucket that fills at the
|
||||
// rate of one token every fillInterval, up to the given
|
||||
// maximum capacity. Both arguments must be
|
||||
// positive. The bucket is initially full.
|
||||
func NewBucket(fillInterval time.Duration, capacity int64) *Bucket {
|
||||
return NewBucketWithQuantum(fillInterval, capacity, 1)
|
||||
}
|
||||
|
||||
// rateMargin specifes the allowed variance of actual
|
||||
// rate from specified rate. 1% seems reasonable.
|
||||
const rateMargin = 0.01
|
||||
|
||||
// NewBucketWithRate returns a token bucket that fills the bucket
|
||||
// at the rate of rate tokens per second up to the given
|
||||
// maximum capacity. Because of limited clock resolution,
|
||||
// at high rates, the actual rate may be up to 1% different from the
|
||||
// specified rate.
|
||||
func NewBucketWithRate(rate float64, capacity int64) *Bucket {
|
||||
for quantum := int64(1); quantum < 1<<50; quantum = nextQuantum(quantum) {
|
||||
fillInterval := time.Duration(1e9 * float64(quantum) / rate)
|
||||
if fillInterval <= 0 {
|
||||
continue
|
||||
}
|
||||
tb := NewBucketWithQuantum(fillInterval, capacity, quantum)
|
||||
if diff := math.Abs(tb.Rate() - rate); diff/rate <= rateMargin {
|
||||
return tb
|
||||
}
|
||||
}
|
||||
panic("cannot find suitable quantum for " + strconv.FormatFloat(rate, 'g', -1, 64))
|
||||
}
|
||||
|
||||
// nextQuantum returns the next quantum to try after q.
|
||||
// We grow the quantum exponentially, but slowly, so we
|
||||
// get a good fit in the lower numbers.
|
||||
func nextQuantum(q int64) int64 {
|
||||
q1 := q * 11 / 10
|
||||
if q1 == q {
|
||||
q1++
|
||||
}
|
||||
return q1
|
||||
}
|
||||
|
||||
// NewBucketWithQuantum is similar to NewBucket, but allows
|
||||
// the specification of the quantum size - quantum tokens
|
||||
// are added every fillInterval.
|
||||
func NewBucketWithQuantum(fillInterval time.Duration, capacity, quantum int64) *Bucket {
|
||||
if fillInterval <= 0 {
|
||||
panic("token bucket fill interval is not > 0")
|
||||
}
|
||||
if capacity <= 0 {
|
||||
panic("token bucket capacity is not > 0")
|
||||
}
|
||||
if quantum <= 0 {
|
||||
panic("token bucket quantum is not > 0")
|
||||
}
|
||||
return &Bucket{
|
||||
startTime: time.Now(),
|
||||
capacity: capacity,
|
||||
quantum: quantum,
|
||||
avail: capacity,
|
||||
fillInterval: fillInterval,
|
||||
}
|
||||
}
|
||||
|
||||
// Wait takes count tokens from the bucket, waiting until they are
|
||||
// available.
|
||||
func (tb *Bucket) Wait(count int64) {
|
||||
if d := tb.Take(count); d > 0 {
|
||||
time.Sleep(d)
|
||||
}
|
||||
}
|
||||
|
||||
// WaitMaxDuration is like Wait except that it will
|
||||
// only take tokens from the bucket if it needs to wait
|
||||
// for no greater than maxWait. It reports whether
|
||||
// any tokens have been removed from the bucket
|
||||
// If no tokens have been removed, it returns immediately.
|
||||
func (tb *Bucket) WaitMaxDuration(count int64, maxWait time.Duration) bool {
|
||||
d, ok := tb.TakeMaxDuration(count, maxWait)
|
||||
if d > 0 {
|
||||
time.Sleep(d)
|
||||
}
|
||||
return ok
|
||||
}
|
||||
|
||||
const infinityDuration time.Duration = 0x7fffffffffffffff
|
||||
|
||||
// Take takes count tokens from the bucket without blocking. It returns
|
||||
// the time that the caller should wait until the tokens are actually
|
||||
// available.
|
||||
//
|
||||
// Note that if the request is irrevocable - there is no way to return
|
||||
// tokens to the bucket once this method commits us to taking them.
|
||||
func (tb *Bucket) Take(count int64) time.Duration {
|
||||
d, _ := tb.take(time.Now(), count, infinityDuration)
|
||||
return d
|
||||
}
|
||||
|
||||
// TakeMaxDuration is like Take, except that
|
||||
// it will only take tokens from the bucket if the wait
|
||||
// time for the tokens is no greater than maxWait.
|
||||
//
|
||||
// If it would take longer than maxWait for the tokens
|
||||
// to become available, it does nothing and reports false,
|
||||
// otherwise it returns the time that the caller should
|
||||
// wait until the tokens are actually available, and reports
|
||||
// true.
|
||||
func (tb *Bucket) TakeMaxDuration(count int64, maxWait time.Duration) (time.Duration, bool) {
|
||||
return tb.take(time.Now(), count, maxWait)
|
||||
}
|
||||
|
||||
// TakeAvailable takes up to count immediately available tokens from the
|
||||
// bucket. It returns the number of tokens removed, or zero if there are
|
||||
// no available tokens. It does not block.
|
||||
func (tb *Bucket) TakeAvailable(count int64) int64 {
|
||||
return tb.takeAvailable(time.Now(), count)
|
||||
}
|
||||
|
||||
// takeAvailable is the internal version of TakeAvailable - it takes the
|
||||
// current time as an argument to enable easy testing.
|
||||
func (tb *Bucket) takeAvailable(now time.Time, count int64) int64 {
|
||||
if count <= 0 {
|
||||
return 0
|
||||
}
|
||||
tb.mu.Lock()
|
||||
defer tb.mu.Unlock()
|
||||
|
||||
tb.adjust(now)
|
||||
if tb.avail <= 0 {
|
||||
return 0
|
||||
}
|
||||
if count > tb.avail {
|
||||
count = tb.avail
|
||||
}
|
||||
tb.avail -= count
|
||||
return count
|
||||
}
|
||||
|
||||
// Rate returns the fill rate of the bucket, in tokens per second.
|
||||
func (tb *Bucket) Rate() float64 {
|
||||
return 1e9 * float64(tb.quantum) / float64(tb.fillInterval)
|
||||
}
|
||||
|
||||
// take is the internal version of Take - it takes the current time as
|
||||
// an argument to enable easy testing.
|
||||
func (tb *Bucket) take(now time.Time, count int64, maxWait time.Duration) (time.Duration, bool) {
|
||||
if count <= 0 {
|
||||
return 0, true
|
||||
}
|
||||
tb.mu.Lock()
|
||||
defer tb.mu.Unlock()
|
||||
|
||||
currentTick := tb.adjust(now)
|
||||
avail := tb.avail - count
|
||||
if avail >= 0 {
|
||||
tb.avail = avail
|
||||
return 0, true
|
||||
}
|
||||
// Round up the missing tokens to the nearest multiple
|
||||
// of quantum - the tokens won't be available until
|
||||
// that tick.
|
||||
endTick := currentTick + (-avail+tb.quantum-1)/tb.quantum
|
||||
endTime := tb.startTime.Add(time.Duration(endTick) * tb.fillInterval)
|
||||
waitTime := endTime.Sub(now)
|
||||
if waitTime > maxWait {
|
||||
return 0, false
|
||||
}
|
||||
tb.avail = avail
|
||||
return waitTime, true
|
||||
}
|
||||
|
||||
// adjust adjusts the current bucket capacity based on the current time.
|
||||
// It returns the current tick.
|
||||
func (tb *Bucket) adjust(now time.Time) (currentTick int64) {
|
||||
currentTick = int64(now.Sub(tb.startTime) / tb.fillInterval)
|
||||
|
||||
if tb.avail >= tb.capacity {
|
||||
return
|
||||
}
|
||||
tb.avail += (currentTick - tb.availTick) * tb.quantum
|
||||
if tb.avail > tb.capacity {
|
||||
tb.avail = tb.capacity
|
||||
}
|
||||
tb.availTick = currentTick
|
||||
return
|
||||
}
|
||||
51
Godeps/_workspace/src/github.com/juju/ratelimit/reader.go
generated
vendored
Normal file
51
Godeps/_workspace/src/github.com/juju/ratelimit/reader.go
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright 2014 Canonical Ltd.
|
||||
// Licensed under the LGPLv3 with static-linking exception.
|
||||
// See LICENCE file for details.
|
||||
|
||||
package ratelimit
|
||||
|
||||
import "io"
|
||||
|
||||
type reader struct {
|
||||
r io.Reader
|
||||
bucket *Bucket
|
||||
}
|
||||
|
||||
// Reader returns a reader that is rate limited by
|
||||
// the given token bucket. Each token in the bucket
|
||||
// represents one byte.
|
||||
func Reader(r io.Reader, bucket *Bucket) io.Reader {
|
||||
return &reader{
|
||||
r: r,
|
||||
bucket: bucket,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *reader) Read(buf []byte) (int, error) {
|
||||
n, err := r.r.Read(buf)
|
||||
if n <= 0 {
|
||||
return n, err
|
||||
}
|
||||
r.bucket.Wait(int64(n))
|
||||
return n, err
|
||||
}
|
||||
|
||||
type writer struct {
|
||||
w io.Writer
|
||||
bucket *Bucket
|
||||
}
|
||||
|
||||
// Writer returns a reader that is rate limited by
|
||||
// the given token bucket. Each token in the bucket
|
||||
// represents one byte.
|
||||
func Writer(w io.Writer, bucket *Bucket) io.Writer {
|
||||
return &writer{
|
||||
w: w,
|
||||
bucket: bucket,
|
||||
}
|
||||
}
|
||||
|
||||
func (w *writer) Write(buf []byte) (int, error) {
|
||||
w.bucket.Wait(int64(len(buf)))
|
||||
return w.w.Write(buf)
|
||||
}
|
||||
27
Godeps/_workspace/src/github.com/kardianos/osext/LICENSE
generated
vendored
Normal file
27
Godeps/_workspace/src/github.com/kardianos/osext/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
Copyright (c) 2012 The Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
16
Godeps/_workspace/src/github.com/kardianos/osext/README.md
generated
vendored
Normal file
16
Godeps/_workspace/src/github.com/kardianos/osext/README.md
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
### Extensions to the "os" package.
|
||||
|
||||
## Find the current Executable and ExecutableFolder.
|
||||
|
||||
There is sometimes utility in finding the current executable file
|
||||
that is running. This can be used for upgrading the current executable
|
||||
or finding resources located relative to the executable file. Both
|
||||
working directory and the os.Args[0] value are arbitrary and cannot
|
||||
be relied on; os.Args[0] can be "faked".
|
||||
|
||||
Multi-platform and supports:
|
||||
* Linux
|
||||
* OS X
|
||||
* Windows
|
||||
* Plan 9
|
||||
* BSDs.
|
||||
33
Godeps/_workspace/src/github.com/kardianos/osext/osext.go
generated
vendored
Normal file
33
Godeps/_workspace/src/github.com/kardianos/osext/osext.go
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Extensions to the standard "os" package.
|
||||
package osext
|
||||
|
||||
import "path/filepath"
|
||||
|
||||
var cx, ce = executableClean()
|
||||
|
||||
func executableClean() (string, error) {
|
||||
p, err := executable()
|
||||
return filepath.Clean(p), err
|
||||
}
|
||||
|
||||
// Executable returns an absolute path that can be used to
|
||||
// re-invoke the current program.
|
||||
// It may not be valid after the current program exits.
|
||||
func Executable() (string, error) {
|
||||
return cx, ce
|
||||
}
|
||||
|
||||
// Returns same path as Executable, returns just the folder
|
||||
// path. Excludes the executable name and any trailing slash.
|
||||
func ExecutableFolder() (string, error) {
|
||||
p, err := Executable()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return filepath.Dir(p), nil
|
||||
}
|
||||
20
Godeps/_workspace/src/github.com/kardianos/osext/osext_plan9.go
generated
vendored
Normal file
20
Godeps/_workspace/src/github.com/kardianos/osext/osext_plan9.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package osext
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func executable() (string, error) {
|
||||
f, err := os.Open("/proc/" + strconv.Itoa(os.Getpid()) + "/text")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer f.Close()
|
||||
return syscall.Fd2path(int(f.Fd()))
|
||||
}
|
||||
36
Godeps/_workspace/src/github.com/kardianos/osext/osext_procfs.go
generated
vendored
Normal file
36
Godeps/_workspace/src/github.com/kardianos/osext/osext_procfs.go
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build linux netbsd solaris dragonfly
|
||||
|
||||
package osext
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func executable() (string, error) {
|
||||
switch runtime.GOOS {
|
||||
case "linux":
|
||||
const deletedTag = " (deleted)"
|
||||
execpath, err := os.Readlink("/proc/self/exe")
|
||||
if err != nil {
|
||||
return execpath, err
|
||||
}
|
||||
execpath = strings.TrimSuffix(execpath, deletedTag)
|
||||
execpath = strings.TrimPrefix(execpath, deletedTag)
|
||||
return execpath, nil
|
||||
case "netbsd":
|
||||
return os.Readlink("/proc/curproc/exe")
|
||||
case "dragonfly":
|
||||
return os.Readlink("/proc/curproc/file")
|
||||
case "solaris":
|
||||
return os.Readlink(fmt.Sprintf("/proc/%d/path/a.out", os.Getpid()))
|
||||
}
|
||||
return "", errors.New("ExecPath not implemented for " + runtime.GOOS)
|
||||
}
|
||||
126
Godeps/_workspace/src/github.com/kardianos/osext/osext_sysctl.go
generated
vendored
Normal file
126
Godeps/_workspace/src/github.com/kardianos/osext/osext_sysctl.go
generated
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build darwin freebsd openbsd
|
||||
|
||||
package osext
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var initCwd, initCwdErr = os.Getwd()
|
||||
|
||||
func executable() (string, error) {
|
||||
var mib [4]int32
|
||||
switch runtime.GOOS {
|
||||
case "freebsd":
|
||||
mib = [4]int32{1 /* CTL_KERN */, 14 /* KERN_PROC */, 12 /* KERN_PROC_PATHNAME */, -1}
|
||||
case "darwin":
|
||||
mib = [4]int32{1 /* CTL_KERN */, 38 /* KERN_PROCARGS */, int32(os.Getpid()), -1}
|
||||
case "openbsd":
|
||||
mib = [4]int32{1 /* CTL_KERN */, 55 /* KERN_PROC_ARGS */, int32(os.Getpid()), 1 /* KERN_PROC_ARGV */}
|
||||
}
|
||||
|
||||
n := uintptr(0)
|
||||
// Get length.
|
||||
_, _, errNum := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, 0, uintptr(unsafe.Pointer(&n)), 0, 0)
|
||||
if errNum != 0 {
|
||||
return "", errNum
|
||||
}
|
||||
if n == 0 { // This shouldn't happen.
|
||||
return "", nil
|
||||
}
|
||||
buf := make([]byte, n)
|
||||
_, _, errNum = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&n)), 0, 0)
|
||||
if errNum != 0 {
|
||||
return "", errNum
|
||||
}
|
||||
if n == 0 { // This shouldn't happen.
|
||||
return "", nil
|
||||
}
|
||||
|
||||
var execPath string
|
||||
switch runtime.GOOS {
|
||||
case "openbsd":
|
||||
// buf now contains **argv, with pointers to each of the C-style
|
||||
// NULL terminated arguments.
|
||||
var args []string
|
||||
argv := uintptr(unsafe.Pointer(&buf[0]))
|
||||
Loop:
|
||||
for {
|
||||
argp := *(**[1 << 20]byte)(unsafe.Pointer(argv))
|
||||
if argp == nil {
|
||||
break
|
||||
}
|
||||
for i := 0; uintptr(i) < n; i++ {
|
||||
// we don't want the full arguments list
|
||||
if string(argp[i]) == " " {
|
||||
break Loop
|
||||
}
|
||||
if argp[i] != 0 {
|
||||
continue
|
||||
}
|
||||
args = append(args, string(argp[:i]))
|
||||
n -= uintptr(i)
|
||||
break
|
||||
}
|
||||
if n < unsafe.Sizeof(argv) {
|
||||
break
|
||||
}
|
||||
argv += unsafe.Sizeof(argv)
|
||||
n -= unsafe.Sizeof(argv)
|
||||
}
|
||||
execPath = args[0]
|
||||
// There is no canonical way to get an executable path on
|
||||
// OpenBSD, so check PATH in case we are called directly
|
||||
if execPath[0] != '/' && execPath[0] != '.' {
|
||||
execIsInPath, err := exec.LookPath(execPath)
|
||||
if err == nil {
|
||||
execPath = execIsInPath
|
||||
}
|
||||
}
|
||||
default:
|
||||
for i, v := range buf {
|
||||
if v == 0 {
|
||||
buf = buf[:i]
|
||||
break
|
||||
}
|
||||
}
|
||||
execPath = string(buf)
|
||||
}
|
||||
|
||||
var err error
|
||||
// execPath will not be empty due to above checks.
|
||||
// Try to get the absolute path if the execPath is not rooted.
|
||||
if execPath[0] != '/' {
|
||||
execPath, err = getAbs(execPath)
|
||||
if err != nil {
|
||||
return execPath, err
|
||||
}
|
||||
}
|
||||
// For darwin KERN_PROCARGS may return the path to a symlink rather than the
|
||||
// actual executable.
|
||||
if runtime.GOOS == "darwin" {
|
||||
if execPath, err = filepath.EvalSymlinks(execPath); err != nil {
|
||||
return execPath, err
|
||||
}
|
||||
}
|
||||
return execPath, nil
|
||||
}
|
||||
|
||||
func getAbs(execPath string) (string, error) {
|
||||
if initCwdErr != nil {
|
||||
return execPath, initCwdErr
|
||||
}
|
||||
// The execPath may begin with a "../" or a "./" so clean it first.
|
||||
// Join the two paths, trailing and starting slashes undetermined, so use
|
||||
// the generic Join function.
|
||||
return filepath.Join(initCwd, filepath.Clean(execPath)), nil
|
||||
}
|
||||
34
Godeps/_workspace/src/github.com/kardianos/osext/osext_windows.go
generated
vendored
Normal file
34
Godeps/_workspace/src/github.com/kardianos/osext/osext_windows.go
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package osext
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unicode/utf16"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
kernel = syscall.MustLoadDLL("kernel32.dll")
|
||||
getModuleFileNameProc = kernel.MustFindProc("GetModuleFileNameW")
|
||||
)
|
||||
|
||||
// GetModuleFileName() with hModule = NULL
|
||||
func executable() (exePath string, err error) {
|
||||
return getModuleFileName()
|
||||
}
|
||||
|
||||
func getModuleFileName() (string, error) {
|
||||
var n uint32
|
||||
b := make([]uint16, syscall.MAX_PATH)
|
||||
size := uint32(len(b))
|
||||
|
||||
r0, _, e1 := getModuleFileNameProc.Call(0, uintptr(unsafe.Pointer(&b[0])), uintptr(size))
|
||||
n = uint32(r0)
|
||||
if n == 0 {
|
||||
return "", e1
|
||||
}
|
||||
return string(utf16.Decode(b[0:n])), nil
|
||||
}
|
||||
9
Godeps/_workspace/src/github.com/rcrowley/go-metrics/.gitignore
generated
vendored
Normal file
9
Godeps/_workspace/src/github.com/rcrowley/go-metrics/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
*.[68]
|
||||
*.a
|
||||
*.out
|
||||
*.swp
|
||||
_obj
|
||||
_testmain.go
|
||||
cmd/metrics-bench/metrics-bench
|
||||
cmd/metrics-example/metrics-example
|
||||
cmd/never-read/never-read
|
||||
13
Godeps/_workspace/src/github.com/rcrowley/go-metrics/.travis.yml
generated
vendored
Normal file
13
Godeps/_workspace/src/github.com/rcrowley/go-metrics/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.2
|
||||
- 1.3
|
||||
- 1.4
|
||||
|
||||
script:
|
||||
- ./validate.sh
|
||||
|
||||
# this should give us faster builds according to
|
||||
# http://docs.travis-ci.com/user/migrating-from-legacy/
|
||||
sudo: false
|
||||
29
Godeps/_workspace/src/github.com/rcrowley/go-metrics/LICENSE
generated
vendored
Normal file
29
Godeps/_workspace/src/github.com/rcrowley/go-metrics/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
Copyright 2012 Richard Crowley. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY RICHARD CROWLEY ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RICHARD CROWLEY OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
The views and conclusions contained in the software and documentation
|
||||
are those of the authors and should not be interpreted as representing
|
||||
official policies, either expressed or implied, of Richard Crowley.
|
||||
126
Godeps/_workspace/src/github.com/rcrowley/go-metrics/README.md
generated
vendored
Normal file
126
Godeps/_workspace/src/github.com/rcrowley/go-metrics/README.md
generated
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
go-metrics
|
||||
==========
|
||||
|
||||

|
||||
|
||||
Go port of Coda Hale's Metrics library: <https://github.com/dropwizard/metrics>.
|
||||
|
||||
Documentation: <http://godoc.org/github.com/rcrowley/go-metrics>.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Create and update metrics:
|
||||
|
||||
```go
|
||||
c := metrics.NewCounter()
|
||||
metrics.Register("foo", c)
|
||||
c.Inc(47)
|
||||
|
||||
g := metrics.NewGauge()
|
||||
metrics.Register("bar", g)
|
||||
g.Update(47)
|
||||
|
||||
s := metrics.NewExpDecaySample(1028, 0.015) // or metrics.NewUniformSample(1028)
|
||||
h := metrics.NewHistogram(s)
|
||||
metrics.Register("baz", h)
|
||||
h.Update(47)
|
||||
|
||||
m := metrics.NewMeter()
|
||||
metrics.Register("quux", m)
|
||||
m.Mark(47)
|
||||
|
||||
t := metrics.NewTimer()
|
||||
metrics.Register("bang", t)
|
||||
t.Time(func() {})
|
||||
t.Update(47)
|
||||
```
|
||||
|
||||
Periodically log every metric in human-readable form to standard error:
|
||||
|
||||
```go
|
||||
go metrics.Log(metrics.DefaultRegistry, 60e9, log.New(os.Stderr, "metrics: ", log.Lmicroseconds))
|
||||
```
|
||||
|
||||
Periodically log every metric in slightly-more-parseable form to syslog:
|
||||
|
||||
```go
|
||||
w, _ := syslog.Dial("unixgram", "/dev/log", syslog.LOG_INFO, "metrics")
|
||||
go metrics.Syslog(metrics.DefaultRegistry, 60e9, w)
|
||||
```
|
||||
|
||||
Periodically emit every metric to Graphite using the [Graphite client](https://github.com/cyberdelia/go-metrics-graphite):
|
||||
|
||||
```go
|
||||
|
||||
import "github.com/cyberdelia/go-metrics-graphite"
|
||||
|
||||
addr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:2003")
|
||||
go graphite.Graphite(metrics.DefaultRegistry, 10e9, "metrics", addr)
|
||||
```
|
||||
|
||||
Periodically emit every metric into InfluxDB:
|
||||
|
||||
**NOTE:** this has been pulled out of the library due to constant fluctuations
|
||||
in the InfluxDB API. In fact, all client libraries are on their way out. see
|
||||
issues [#121](https://github.com/rcrowley/go-metrics/issues/121) and
|
||||
[#124](https://github.com/rcrowley/go-metrics/issues/124) for progress and details.
|
||||
|
||||
```go
|
||||
import "github.com/rcrowley/go-metrics/influxdb"
|
||||
|
||||
go influxdb.Influxdb(metrics.DefaultRegistry, 10e9, &influxdb.Config{
|
||||
Host: "127.0.0.1:8086",
|
||||
Database: "metrics",
|
||||
Username: "test",
|
||||
Password: "test",
|
||||
})
|
||||
```
|
||||
|
||||
Periodically upload every metric to Librato using the [Librato client](https://github.com/mihasya/go-metrics-librato):
|
||||
|
||||
**Note**: the client included with this repository under the `librato` package
|
||||
has been deprecated and moved to the repository linked above.
|
||||
|
||||
```go
|
||||
import "github.com/mihasya/go-metrics-librato"
|
||||
|
||||
go librato.Librato(metrics.DefaultRegistry,
|
||||
10e9, // interval
|
||||
"example@example.com", // account owner email address
|
||||
"token", // Librato API token
|
||||
"hostname", // source
|
||||
[]float64{0.95}, // percentiles to send
|
||||
time.Millisecond, // time unit
|
||||
)
|
||||
```
|
||||
|
||||
Periodically emit every metric to StatHat:
|
||||
|
||||
```go
|
||||
import "github.com/rcrowley/go-metrics/stathat"
|
||||
|
||||
go stathat.Stathat(metrics.DefaultRegistry, 10e9, "example@example.com")
|
||||
```
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
```sh
|
||||
go get github.com/rcrowley/go-metrics
|
||||
```
|
||||
|
||||
StatHat support additionally requires their Go client:
|
||||
|
||||
```sh
|
||||
go get github.com/stathat/go
|
||||
```
|
||||
|
||||
Publishing Metrics
|
||||
------------------
|
||||
|
||||
Clients are available for the following destinations:
|
||||
|
||||
* Librato - [https://github.com/mihasya/go-metrics-librato](https://github.com/mihasya/go-metrics-librato)
|
||||
* Graphite - [https://github.com/cyberdelia/go-metrics-graphite](https://github.com/cyberdelia/go-metrics-graphite)
|
||||
* InfluxDB - [https://github.com/vrischmann/go-metrics-influxdb](https://github.com/vrischmann/go-metrics-influxdb)
|
||||
20
Godeps/_workspace/src/github.com/rcrowley/go-metrics/cmd/metrics-bench/metrics-bench.go
generated
vendored
Normal file
20
Godeps/_workspace/src/github.com/rcrowley/go-metrics/cmd/metrics-bench/metrics-bench.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/rcrowley/go-metrics"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
r := metrics.NewRegistry()
|
||||
for i := 0; i < 10000; i++ {
|
||||
r.Register(fmt.Sprintf("counter-%d", i), metrics.NewCounter())
|
||||
r.Register(fmt.Sprintf("gauge-%d", i), metrics.NewGauge())
|
||||
r.Register(fmt.Sprintf("gaugefloat64-%d", i), metrics.NewGaugeFloat64())
|
||||
r.Register(fmt.Sprintf("histogram-uniform-%d", i), metrics.NewHistogram(metrics.NewUniformSample(1028)))
|
||||
r.Register(fmt.Sprintf("histogram-exp-%d", i), metrics.NewHistogram(metrics.NewExpDecaySample(1028, 0.015)))
|
||||
r.Register(fmt.Sprintf("meter-%d", i), metrics.NewMeter())
|
||||
}
|
||||
time.Sleep(600e9)
|
||||
}
|
||||
154
Godeps/_workspace/src/github.com/rcrowley/go-metrics/cmd/metrics-example/metrics-example.go
generated
vendored
Normal file
154
Godeps/_workspace/src/github.com/rcrowley/go-metrics/cmd/metrics-example/metrics-example.go
generated
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/rcrowley/go-metrics"
|
||||
// "github.com/rcrowley/go-metrics/stathat"
|
||||
"log"
|
||||
"math/rand"
|
||||
"os"
|
||||
// "syslog"
|
||||
"time"
|
||||
)
|
||||
|
||||
const fanout = 10
|
||||
|
||||
func main() {
|
||||
|
||||
r := metrics.NewRegistry()
|
||||
|
||||
c := metrics.NewCounter()
|
||||
r.Register("foo", c)
|
||||
for i := 0; i < fanout; i++ {
|
||||
go func() {
|
||||
for {
|
||||
c.Dec(19)
|
||||
time.Sleep(300e6)
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
for {
|
||||
c.Inc(47)
|
||||
time.Sleep(400e6)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
g := metrics.NewGauge()
|
||||
r.Register("bar", g)
|
||||
for i := 0; i < fanout; i++ {
|
||||
go func() {
|
||||
for {
|
||||
g.Update(19)
|
||||
time.Sleep(300e6)
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
for {
|
||||
g.Update(47)
|
||||
time.Sleep(400e6)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
gf := metrics.NewGaugeFloat64()
|
||||
r.Register("barfloat64", gf)
|
||||
for i := 0; i < fanout; i++ {
|
||||
go func() {
|
||||
for {
|
||||
g.Update(19.0)
|
||||
time.Sleep(300e6)
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
for {
|
||||
g.Update(47.0)
|
||||
time.Sleep(400e6)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
hc := metrics.NewHealthcheck(func(h metrics.Healthcheck) {
|
||||
if 0 < rand.Intn(2) {
|
||||
h.Healthy()
|
||||
} else {
|
||||
h.Unhealthy(errors.New("baz"))
|
||||
}
|
||||
})
|
||||
r.Register("baz", hc)
|
||||
|
||||
s := metrics.NewExpDecaySample(1028, 0.015)
|
||||
//s := metrics.NewUniformSample(1028)
|
||||
h := metrics.NewHistogram(s)
|
||||
r.Register("bang", h)
|
||||
for i := 0; i < fanout; i++ {
|
||||
go func() {
|
||||
for {
|
||||
h.Update(19)
|
||||
time.Sleep(300e6)
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
for {
|
||||
h.Update(47)
|
||||
time.Sleep(400e6)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
m := metrics.NewMeter()
|
||||
r.Register("quux", m)
|
||||
for i := 0; i < fanout; i++ {
|
||||
go func() {
|
||||
for {
|
||||
m.Mark(19)
|
||||
time.Sleep(300e6)
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
for {
|
||||
m.Mark(47)
|
||||
time.Sleep(400e6)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
t := metrics.NewTimer()
|
||||
r.Register("hooah", t)
|
||||
for i := 0; i < fanout; i++ {
|
||||
go func() {
|
||||
for {
|
||||
t.Time(func() { time.Sleep(300e6) })
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
for {
|
||||
t.Time(func() { time.Sleep(400e6) })
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
metrics.RegisterDebugGCStats(r)
|
||||
go metrics.CaptureDebugGCStats(r, 5e9)
|
||||
|
||||
metrics.RegisterRuntimeMemStats(r)
|
||||
go metrics.CaptureRuntimeMemStats(r, 5e9)
|
||||
|
||||
metrics.Log(r, 60e9, log.New(os.Stderr, "metrics: ", log.Lmicroseconds))
|
||||
|
||||
/*
|
||||
w, err := syslog.Dial("unixgram", "/dev/log", syslog.LOG_INFO, "metrics")
|
||||
if nil != err { log.Fatalln(err) }
|
||||
metrics.Syslog(r, 60e9, w)
|
||||
*/
|
||||
|
||||
/*
|
||||
addr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:2003")
|
||||
metrics.Graphite(r, 10e9, "metrics", addr)
|
||||
*/
|
||||
|
||||
/*
|
||||
stathat.Stathat(r, 10e9, "example@example.com")
|
||||
*/
|
||||
|
||||
}
|
||||
22
Godeps/_workspace/src/github.com/rcrowley/go-metrics/cmd/never-read/never-read.go
generated
vendored
Normal file
22
Godeps/_workspace/src/github.com/rcrowley/go-metrics/cmd/never-read/never-read.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net"
|
||||
)
|
||||
|
||||
func main() {
|
||||
addr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:2003")
|
||||
l, err := net.ListenTCP("tcp", addr)
|
||||
if nil != err {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
log.Println("listening", l.Addr())
|
||||
for {
|
||||
c, err := l.AcceptTCP()
|
||||
if nil != err {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
log.Println("accepted", c.RemoteAddr())
|
||||
}
|
||||
}
|
||||
112
Godeps/_workspace/src/github.com/rcrowley/go-metrics/counter.go
generated
vendored
Normal file
112
Godeps/_workspace/src/github.com/rcrowley/go-metrics/counter.go
generated
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
package metrics
|
||||
|
||||
import "sync/atomic"
|
||||
|
||||
// Counters hold an int64 value that can be incremented and decremented.
|
||||
type Counter interface {
|
||||
Clear()
|
||||
Count() int64
|
||||
Dec(int64)
|
||||
Inc(int64)
|
||||
Snapshot() Counter
|
||||
}
|
||||
|
||||
// GetOrRegisterCounter returns an existing Counter or constructs and registers
|
||||
// a new StandardCounter.
|
||||
func GetOrRegisterCounter(name string, r Registry) Counter {
|
||||
if nil == r {
|
||||
r = DefaultRegistry
|
||||
}
|
||||
return r.GetOrRegister(name, NewCounter).(Counter)
|
||||
}
|
||||
|
||||
// NewCounter constructs a new StandardCounter.
|
||||
func NewCounter() Counter {
|
||||
if UseNilMetrics {
|
||||
return NilCounter{}
|
||||
}
|
||||
return &StandardCounter{0}
|
||||
}
|
||||
|
||||
// NewRegisteredCounter constructs and registers a new StandardCounter.
|
||||
func NewRegisteredCounter(name string, r Registry) Counter {
|
||||
c := NewCounter()
|
||||
if nil == r {
|
||||
r = DefaultRegistry
|
||||
}
|
||||
r.Register(name, c)
|
||||
return c
|
||||
}
|
||||
|
||||
// CounterSnapshot is a read-only copy of another Counter.
|
||||
type CounterSnapshot int64
|
||||
|
||||
// Clear panics.
|
||||
func (CounterSnapshot) Clear() {
|
||||
panic("Clear called on a CounterSnapshot")
|
||||
}
|
||||
|
||||
// Count returns the count at the time the snapshot was taken.
|
||||
func (c CounterSnapshot) Count() int64 { return int64(c) }
|
||||
|
||||
// Dec panics.
|
||||
func (CounterSnapshot) Dec(int64) {
|
||||
panic("Dec called on a CounterSnapshot")
|
||||
}
|
||||
|
||||
// Inc panics.
|
||||
func (CounterSnapshot) Inc(int64) {
|
||||
panic("Inc called on a CounterSnapshot")
|
||||
}
|
||||
|
||||
// Snapshot returns the snapshot.
|
||||
func (c CounterSnapshot) Snapshot() Counter { return c }
|
||||
|
||||
// NilCounter is a no-op Counter.
|
||||
type NilCounter struct{}
|
||||
|
||||
// Clear is a no-op.
|
||||
func (NilCounter) Clear() {}
|
||||
|
||||
// Count is a no-op.
|
||||
func (NilCounter) Count() int64 { return 0 }
|
||||
|
||||
// Dec is a no-op.
|
||||
func (NilCounter) Dec(i int64) {}
|
||||
|
||||
// Inc is a no-op.
|
||||
func (NilCounter) Inc(i int64) {}
|
||||
|
||||
// Snapshot is a no-op.
|
||||
func (NilCounter) Snapshot() Counter { return NilCounter{} }
|
||||
|
||||
// StandardCounter is the standard implementation of a Counter and uses the
|
||||
// sync/atomic package to manage a single int64 value.
|
||||
type StandardCounter struct {
|
||||
count int64
|
||||
}
|
||||
|
||||
// Clear sets the counter to zero.
|
||||
func (c *StandardCounter) Clear() {
|
||||
atomic.StoreInt64(&c.count, 0)
|
||||
}
|
||||
|
||||
// Count returns the current count.
|
||||
func (c *StandardCounter) Count() int64 {
|
||||
return atomic.LoadInt64(&c.count)
|
||||
}
|
||||
|
||||
// Dec decrements the counter by the given amount.
|
||||
func (c *StandardCounter) Dec(i int64) {
|
||||
atomic.AddInt64(&c.count, -i)
|
||||
}
|
||||
|
||||
// Inc increments the counter by the given amount.
|
||||
func (c *StandardCounter) Inc(i int64) {
|
||||
atomic.AddInt64(&c.count, i)
|
||||
}
|
||||
|
||||
// Snapshot returns a read-only copy of the counter.
|
||||
func (c *StandardCounter) Snapshot() Counter {
|
||||
return CounterSnapshot(c.Count())
|
||||
}
|
||||
76
Godeps/_workspace/src/github.com/rcrowley/go-metrics/debug.go
generated
vendored
Normal file
76
Godeps/_workspace/src/github.com/rcrowley/go-metrics/debug.go
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"runtime/debug"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
debugMetrics struct {
|
||||
GCStats struct {
|
||||
LastGC Gauge
|
||||
NumGC Gauge
|
||||
Pause Histogram
|
||||
//PauseQuantiles Histogram
|
||||
PauseTotal Gauge
|
||||
}
|
||||
ReadGCStats Timer
|
||||
}
|
||||
gcStats debug.GCStats
|
||||
)
|
||||
|
||||
// Capture new values for the Go garbage collector statistics exported in
|
||||
// debug.GCStats. This is designed to be called as a goroutine.
|
||||
func CaptureDebugGCStats(r Registry, d time.Duration) {
|
||||
for _ = range time.Tick(d) {
|
||||
CaptureDebugGCStatsOnce(r)
|
||||
}
|
||||
}
|
||||
|
||||
// Capture new values for the Go garbage collector statistics exported in
|
||||
// debug.GCStats. This is designed to be called in a background goroutine.
|
||||
// Giving a registry which has not been given to RegisterDebugGCStats will
|
||||
// panic.
|
||||
//
|
||||
// Be careful (but much less so) with this because debug.ReadGCStats calls
|
||||
// the C function runtime·lock(runtime·mheap) which, while not a stop-the-world
|
||||
// operation, isn't something you want to be doing all the time.
|
||||
func CaptureDebugGCStatsOnce(r Registry) {
|
||||
lastGC := gcStats.LastGC
|
||||
t := time.Now()
|
||||
debug.ReadGCStats(&gcStats)
|
||||
debugMetrics.ReadGCStats.UpdateSince(t)
|
||||
|
||||
debugMetrics.GCStats.LastGC.Update(int64(gcStats.LastGC.UnixNano()))
|
||||
debugMetrics.GCStats.NumGC.Update(int64(gcStats.NumGC))
|
||||
if lastGC != gcStats.LastGC && 0 < len(gcStats.Pause) {
|
||||
debugMetrics.GCStats.Pause.Update(int64(gcStats.Pause[0]))
|
||||
}
|
||||
//debugMetrics.GCStats.PauseQuantiles.Update(gcStats.PauseQuantiles)
|
||||
debugMetrics.GCStats.PauseTotal.Update(int64(gcStats.PauseTotal))
|
||||
}
|
||||
|
||||
// Register metrics for the Go garbage collector statistics exported in
|
||||
// debug.GCStats. The metrics are named by their fully-qualified Go symbols,
|
||||
// i.e. debug.GCStats.PauseTotal.
|
||||
func RegisterDebugGCStats(r Registry) {
|
||||
debugMetrics.GCStats.LastGC = NewGauge()
|
||||
debugMetrics.GCStats.NumGC = NewGauge()
|
||||
debugMetrics.GCStats.Pause = NewHistogram(NewExpDecaySample(1028, 0.015))
|
||||
//debugMetrics.GCStats.PauseQuantiles = NewHistogram(NewExpDecaySample(1028, 0.015))
|
||||
debugMetrics.GCStats.PauseTotal = NewGauge()
|
||||
debugMetrics.ReadGCStats = NewTimer()
|
||||
|
||||
r.Register("debug.GCStats.LastGC", debugMetrics.GCStats.LastGC)
|
||||
r.Register("debug.GCStats.NumGC", debugMetrics.GCStats.NumGC)
|
||||
r.Register("debug.GCStats.Pause", debugMetrics.GCStats.Pause)
|
||||
//r.Register("debug.GCStats.PauseQuantiles", debugMetrics.GCStats.PauseQuantiles)
|
||||
r.Register("debug.GCStats.PauseTotal", debugMetrics.GCStats.PauseTotal)
|
||||
r.Register("debug.ReadGCStats", debugMetrics.ReadGCStats)
|
||||
}
|
||||
|
||||
// Allocate an initial slice for gcStats.Pause to avoid allocations during
|
||||
// normal operation.
|
||||
func init() {
|
||||
gcStats.Pause = make([]time.Duration, 11)
|
||||
}
|
||||
118
Godeps/_workspace/src/github.com/rcrowley/go-metrics/ewma.go
generated
vendored
Normal file
118
Godeps/_workspace/src/github.com/rcrowley/go-metrics/ewma.go
generated
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"math"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// EWMAs continuously calculate an exponentially-weighted moving average
|
||||
// based on an outside source of clock ticks.
|
||||
type EWMA interface {
|
||||
Rate() float64
|
||||
Snapshot() EWMA
|
||||
Tick()
|
||||
Update(int64)
|
||||
}
|
||||
|
||||
// NewEWMA constructs a new EWMA with the given alpha.
|
||||
func NewEWMA(alpha float64) EWMA {
|
||||
if UseNilMetrics {
|
||||
return NilEWMA{}
|
||||
}
|
||||
return &StandardEWMA{alpha: alpha}
|
||||
}
|
||||
|
||||
// NewEWMA1 constructs a new EWMA for a one-minute moving average.
|
||||
func NewEWMA1() EWMA {
|
||||
return NewEWMA(1 - math.Exp(-5.0/60.0/1))
|
||||
}
|
||||
|
||||
// NewEWMA5 constructs a new EWMA for a five-minute moving average.
|
||||
func NewEWMA5() EWMA {
|
||||
return NewEWMA(1 - math.Exp(-5.0/60.0/5))
|
||||
}
|
||||
|
||||
// NewEWMA15 constructs a new EWMA for a fifteen-minute moving average.
|
||||
func NewEWMA15() EWMA {
|
||||
return NewEWMA(1 - math.Exp(-5.0/60.0/15))
|
||||
}
|
||||
|
||||
// EWMASnapshot is a read-only copy of another EWMA.
|
||||
type EWMASnapshot float64
|
||||
|
||||
// Rate returns the rate of events per second at the time the snapshot was
|
||||
// taken.
|
||||
func (a EWMASnapshot) Rate() float64 { return float64(a) }
|
||||
|
||||
// Snapshot returns the snapshot.
|
||||
func (a EWMASnapshot) Snapshot() EWMA { return a }
|
||||
|
||||
// Tick panics.
|
||||
func (EWMASnapshot) Tick() {
|
||||
panic("Tick called on an EWMASnapshot")
|
||||
}
|
||||
|
||||
// Update panics.
|
||||
func (EWMASnapshot) Update(int64) {
|
||||
panic("Update called on an EWMASnapshot")
|
||||
}
|
||||
|
||||
// NilEWMA is a no-op EWMA.
|
||||
type NilEWMA struct{}
|
||||
|
||||
// Rate is a no-op.
|
||||
func (NilEWMA) Rate() float64 { return 0.0 }
|
||||
|
||||
// Snapshot is a no-op.
|
||||
func (NilEWMA) Snapshot() EWMA { return NilEWMA{} }
|
||||
|
||||
// Tick is a no-op.
|
||||
func (NilEWMA) Tick() {}
|
||||
|
||||
// Update is a no-op.
|
||||
func (NilEWMA) Update(n int64) {}
|
||||
|
||||
// StandardEWMA is the standard implementation of an EWMA and tracks the number
|
||||
// of uncounted events and processes them on each tick. It uses the
|
||||
// sync/atomic package to manage uncounted events.
|
||||
type StandardEWMA struct {
|
||||
uncounted int64 // /!\ this should be the first member to ensure 64-bit alignment
|
||||
alpha float64
|
||||
rate float64
|
||||
init bool
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
// Rate returns the moving average rate of events per second.
|
||||
func (a *StandardEWMA) Rate() float64 {
|
||||
a.mutex.Lock()
|
||||
defer a.mutex.Unlock()
|
||||
return a.rate * float64(1e9)
|
||||
}
|
||||
|
||||
// Snapshot returns a read-only copy of the EWMA.
|
||||
func (a *StandardEWMA) Snapshot() EWMA {
|
||||
return EWMASnapshot(a.Rate())
|
||||
}
|
||||
|
||||
// Tick ticks the clock to update the moving average. It assumes it is called
|
||||
// every five seconds.
|
||||
func (a *StandardEWMA) Tick() {
|
||||
count := atomic.LoadInt64(&a.uncounted)
|
||||
atomic.AddInt64(&a.uncounted, -count)
|
||||
instantRate := float64(count) / float64(5e9)
|
||||
a.mutex.Lock()
|
||||
defer a.mutex.Unlock()
|
||||
if a.init {
|
||||
a.rate += a.alpha * (instantRate - a.rate)
|
||||
} else {
|
||||
a.init = true
|
||||
a.rate = instantRate
|
||||
}
|
||||
}
|
||||
|
||||
// Update adds n uncounted events.
|
||||
func (a *StandardEWMA) Update(n int64) {
|
||||
atomic.AddInt64(&a.uncounted, n)
|
||||
}
|
||||
84
Godeps/_workspace/src/github.com/rcrowley/go-metrics/gauge.go
generated
vendored
Normal file
84
Godeps/_workspace/src/github.com/rcrowley/go-metrics/gauge.go
generated
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
package metrics
|
||||
|
||||
import "sync/atomic"
|
||||
|
||||
// Gauges hold an int64 value that can be set arbitrarily.
|
||||
type Gauge interface {
|
||||
Snapshot() Gauge
|
||||
Update(int64)
|
||||
Value() int64
|
||||
}
|
||||
|
||||
// GetOrRegisterGauge returns an existing Gauge or constructs and registers a
|
||||
// new StandardGauge.
|
||||
func GetOrRegisterGauge(name string, r Registry) Gauge {
|
||||
if nil == r {
|
||||
r = DefaultRegistry
|
||||
}
|
||||
return r.GetOrRegister(name, NewGauge).(Gauge)
|
||||
}
|
||||
|
||||
// NewGauge constructs a new StandardGauge.
|
||||
func NewGauge() Gauge {
|
||||
if UseNilMetrics {
|
||||
return NilGauge{}
|
||||
}
|
||||
return &StandardGauge{0}
|
||||
}
|
||||
|
||||
// NewRegisteredGauge constructs and registers a new StandardGauge.
|
||||
func NewRegisteredGauge(name string, r Registry) Gauge {
|
||||
c := NewGauge()
|
||||
if nil == r {
|
||||
r = DefaultRegistry
|
||||
}
|
||||
r.Register(name, c)
|
||||
return c
|
||||
}
|
||||
|
||||
// GaugeSnapshot is a read-only copy of another Gauge.
|
||||
type GaugeSnapshot int64
|
||||
|
||||
// Snapshot returns the snapshot.
|
||||
func (g GaugeSnapshot) Snapshot() Gauge { return g }
|
||||
|
||||
// Update panics.
|
||||
func (GaugeSnapshot) Update(int64) {
|
||||
panic("Update called on a GaugeSnapshot")
|
||||
}
|
||||
|
||||
// Value returns the value at the time the snapshot was taken.
|
||||
func (g GaugeSnapshot) Value() int64 { return int64(g) }
|
||||
|
||||
// NilGauge is a no-op Gauge.
|
||||
type NilGauge struct{}
|
||||
|
||||
// Snapshot is a no-op.
|
||||
func (NilGauge) Snapshot() Gauge { return NilGauge{} }
|
||||
|
||||
// Update is a no-op.
|
||||
func (NilGauge) Update(v int64) {}
|
||||
|
||||
// Value is a no-op.
|
||||
func (NilGauge) Value() int64 { return 0 }
|
||||
|
||||
// StandardGauge is the standard implementation of a Gauge and uses the
|
||||
// sync/atomic package to manage a single int64 value.
|
||||
type StandardGauge struct {
|
||||
value int64
|
||||
}
|
||||
|
||||
// Snapshot returns a read-only copy of the gauge.
|
||||
func (g *StandardGauge) Snapshot() Gauge {
|
||||
return GaugeSnapshot(g.Value())
|
||||
}
|
||||
|
||||
// Update updates the gauge's value.
|
||||
func (g *StandardGauge) Update(v int64) {
|
||||
atomic.StoreInt64(&g.value, v)
|
||||
}
|
||||
|
||||
// Value returns the gauge's current value.
|
||||
func (g *StandardGauge) Value() int64 {
|
||||
return atomic.LoadInt64(&g.value)
|
||||
}
|
||||
91
Godeps/_workspace/src/github.com/rcrowley/go-metrics/gauge_float64.go
generated
vendored
Normal file
91
Godeps/_workspace/src/github.com/rcrowley/go-metrics/gauge_float64.go
generated
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
package metrics
|
||||
|
||||
import "sync"
|
||||
|
||||
// GaugeFloat64s hold a float64 value that can be set arbitrarily.
|
||||
type GaugeFloat64 interface {
|
||||
Snapshot() GaugeFloat64
|
||||
Update(float64)
|
||||
Value() float64
|
||||
}
|
||||
|
||||
// GetOrRegisterGaugeFloat64 returns an existing GaugeFloat64 or constructs and registers a
|
||||
// new StandardGaugeFloat64.
|
||||
func GetOrRegisterGaugeFloat64(name string, r Registry) GaugeFloat64 {
|
||||
if nil == r {
|
||||
r = DefaultRegistry
|
||||
}
|
||||
return r.GetOrRegister(name, NewGaugeFloat64()).(GaugeFloat64)
|
||||
}
|
||||
|
||||
// NewGaugeFloat64 constructs a new StandardGaugeFloat64.
|
||||
func NewGaugeFloat64() GaugeFloat64 {
|
||||
if UseNilMetrics {
|
||||
return NilGaugeFloat64{}
|
||||
}
|
||||
return &StandardGaugeFloat64{
|
||||
value: 0.0,
|
||||
}
|
||||
}
|
||||
|
||||
// NewRegisteredGaugeFloat64 constructs and registers a new StandardGaugeFloat64.
|
||||
func NewRegisteredGaugeFloat64(name string, r Registry) GaugeFloat64 {
|
||||
c := NewGaugeFloat64()
|
||||
if nil == r {
|
||||
r = DefaultRegistry
|
||||
}
|
||||
r.Register(name, c)
|
||||
return c
|
||||
}
|
||||
|
||||
// GaugeFloat64Snapshot is a read-only copy of another GaugeFloat64.
|
||||
type GaugeFloat64Snapshot float64
|
||||
|
||||
// Snapshot returns the snapshot.
|
||||
func (g GaugeFloat64Snapshot) Snapshot() GaugeFloat64 { return g }
|
||||
|
||||
// Update panics.
|
||||
func (GaugeFloat64Snapshot) Update(float64) {
|
||||
panic("Update called on a GaugeFloat64Snapshot")
|
||||
}
|
||||
|
||||
// Value returns the value at the time the snapshot was taken.
|
||||
func (g GaugeFloat64Snapshot) Value() float64 { return float64(g) }
|
||||
|
||||
// NilGauge is a no-op Gauge.
|
||||
type NilGaugeFloat64 struct{}
|
||||
|
||||
// Snapshot is a no-op.
|
||||
func (NilGaugeFloat64) Snapshot() GaugeFloat64 { return NilGaugeFloat64{} }
|
||||
|
||||
// Update is a no-op.
|
||||
func (NilGaugeFloat64) Update(v float64) {}
|
||||
|
||||
// Value is a no-op.
|
||||
func (NilGaugeFloat64) Value() float64 { return 0.0 }
|
||||
|
||||
// StandardGaugeFloat64 is the standard implementation of a GaugeFloat64 and uses
|
||||
// sync.Mutex to manage a single float64 value.
|
||||
type StandardGaugeFloat64 struct {
|
||||
mutex sync.Mutex
|
||||
value float64
|
||||
}
|
||||
|
||||
// Snapshot returns a read-only copy of the gauge.
|
||||
func (g *StandardGaugeFloat64) Snapshot() GaugeFloat64 {
|
||||
return GaugeFloat64Snapshot(g.Value())
|
||||
}
|
||||
|
||||
// Update updates the gauge's value.
|
||||
func (g *StandardGaugeFloat64) Update(v float64) {
|
||||
g.mutex.Lock()
|
||||
defer g.mutex.Unlock()
|
||||
g.value = v
|
||||
}
|
||||
|
||||
// Value returns the gauge's current value.
|
||||
func (g *StandardGaugeFloat64) Value() float64 {
|
||||
g.mutex.Lock()
|
||||
defer g.mutex.Unlock()
|
||||
return g.value
|
||||
}
|
||||
113
Godeps/_workspace/src/github.com/rcrowley/go-metrics/graphite.go
generated
vendored
Normal file
113
Godeps/_workspace/src/github.com/rcrowley/go-metrics/graphite.go
generated
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// GraphiteConfig provides a container with configuration parameters for
|
||||
// the Graphite exporter
|
||||
type GraphiteConfig struct {
|
||||
Addr *net.TCPAddr // Network address to connect to
|
||||
Registry Registry // Registry to be exported
|
||||
FlushInterval time.Duration // Flush interval
|
||||
DurationUnit time.Duration // Time conversion unit for durations
|
||||
Prefix string // Prefix to be prepended to metric names
|
||||
Percentiles []float64 // Percentiles to export from timers and histograms
|
||||
}
|
||||
|
||||
// Graphite is a blocking exporter function which reports metrics in r
|
||||
// to a graphite server located at addr, flushing them every d duration
|
||||
// and prepending metric names with prefix.
|
||||
func Graphite(r Registry, d time.Duration, prefix string, addr *net.TCPAddr) {
|
||||
GraphiteWithConfig(GraphiteConfig{
|
||||
Addr: addr,
|
||||
Registry: r,
|
||||
FlushInterval: d,
|
||||
DurationUnit: time.Nanosecond,
|
||||
Prefix: prefix,
|
||||
Percentiles: []float64{0.5, 0.75, 0.95, 0.99, 0.999},
|
||||
})
|
||||
}
|
||||
|
||||
// GraphiteWithConfig is a blocking exporter function just like Graphite,
|
||||
// but it takes a GraphiteConfig instead.
|
||||
func GraphiteWithConfig(c GraphiteConfig) {
|
||||
log.Printf("WARNING: This go-metrics client has been DEPRECATED! It has been moved to https://github.com/cyberdelia/go-metrics-graphite and will be removed from rcrowley/go-metrics on August 12th 2015")
|
||||
for _ = range time.Tick(c.FlushInterval) {
|
||||
if err := graphite(&c); nil != err {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GraphiteOnce performs a single submission to Graphite, returning a
|
||||
// non-nil error on failed connections. This can be used in a loop
|
||||
// similar to GraphiteWithConfig for custom error handling.
|
||||
func GraphiteOnce(c GraphiteConfig) error {
|
||||
log.Printf("WARNING: This go-metrics client has been DEPRECATED! It has been moved to https://github.com/cyberdelia/go-metrics-graphite and will be removed from rcrowley/go-metrics on August 12th 2015")
|
||||
return graphite(&c)
|
||||
}
|
||||
|
||||
func graphite(c *GraphiteConfig) error {
|
||||
now := time.Now().Unix()
|
||||
du := float64(c.DurationUnit)
|
||||
conn, err := net.DialTCP("tcp", nil, c.Addr)
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
defer conn.Close()
|
||||
w := bufio.NewWriter(conn)
|
||||
c.Registry.Each(func(name string, i interface{}) {
|
||||
switch metric := i.(type) {
|
||||
case Counter:
|
||||
fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, metric.Count(), now)
|
||||
case Gauge:
|
||||
fmt.Fprintf(w, "%s.%s.value %d %d\n", c.Prefix, name, metric.Value(), now)
|
||||
case GaugeFloat64:
|
||||
fmt.Fprintf(w, "%s.%s.value %f %d\n", c.Prefix, name, metric.Value(), now)
|
||||
case Histogram:
|
||||
h := metric.Snapshot()
|
||||
ps := h.Percentiles(c.Percentiles)
|
||||
fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, h.Count(), now)
|
||||
fmt.Fprintf(w, "%s.%s.min %d %d\n", c.Prefix, name, h.Min(), now)
|
||||
fmt.Fprintf(w, "%s.%s.max %d %d\n", c.Prefix, name, h.Max(), now)
|
||||
fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, h.Mean(), now)
|
||||
fmt.Fprintf(w, "%s.%s.std-dev %.2f %d\n", c.Prefix, name, h.StdDev(), now)
|
||||
for psIdx, psKey := range c.Percentiles {
|
||||
key := strings.Replace(strconv.FormatFloat(psKey*100.0, 'f', -1, 64), ".", "", 1)
|
||||
fmt.Fprintf(w, "%s.%s.%s-percentile %.2f %d\n", c.Prefix, name, key, ps[psIdx], now)
|
||||
}
|
||||
case Meter:
|
||||
m := metric.Snapshot()
|
||||
fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, m.Count(), now)
|
||||
fmt.Fprintf(w, "%s.%s.one-minute %.2f %d\n", c.Prefix, name, m.Rate1(), now)
|
||||
fmt.Fprintf(w, "%s.%s.five-minute %.2f %d\n", c.Prefix, name, m.Rate5(), now)
|
||||
fmt.Fprintf(w, "%s.%s.fifteen-minute %.2f %d\n", c.Prefix, name, m.Rate15(), now)
|
||||
fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, m.RateMean(), now)
|
||||
case Timer:
|
||||
t := metric.Snapshot()
|
||||
ps := t.Percentiles(c.Percentiles)
|
||||
fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, t.Count(), now)
|
||||
fmt.Fprintf(w, "%s.%s.min %d %d\n", c.Prefix, name, t.Min()/int64(du), now)
|
||||
fmt.Fprintf(w, "%s.%s.max %d %d\n", c.Prefix, name, t.Max()/int64(du), now)
|
||||
fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, t.Mean()/du, now)
|
||||
fmt.Fprintf(w, "%s.%s.std-dev %.2f %d\n", c.Prefix, name, t.StdDev()/du, now)
|
||||
for psIdx, psKey := range c.Percentiles {
|
||||
key := strings.Replace(strconv.FormatFloat(psKey*100.0, 'f', -1, 64), ".", "", 1)
|
||||
fmt.Fprintf(w, "%s.%s.%s-percentile %.2f %d\n", c.Prefix, name, key, ps[psIdx], now)
|
||||
}
|
||||
fmt.Fprintf(w, "%s.%s.one-minute %.2f %d\n", c.Prefix, name, t.Rate1(), now)
|
||||
fmt.Fprintf(w, "%s.%s.five-minute %.2f %d\n", c.Prefix, name, t.Rate5(), now)
|
||||
fmt.Fprintf(w, "%s.%s.fifteen-minute %.2f %d\n", c.Prefix, name, t.Rate15(), now)
|
||||
fmt.Fprintf(w, "%s.%s.mean-rate %.2f %d\n", c.Prefix, name, t.RateMean(), now)
|
||||
}
|
||||
w.Flush()
|
||||
})
|
||||
return nil
|
||||
}
|
||||
61
Godeps/_workspace/src/github.com/rcrowley/go-metrics/healthcheck.go
generated
vendored
Normal file
61
Godeps/_workspace/src/github.com/rcrowley/go-metrics/healthcheck.go
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
package metrics
|
||||
|
||||
// Healthchecks hold an error value describing an arbitrary up/down status.
|
||||
type Healthcheck interface {
|
||||
Check()
|
||||
Error() error
|
||||
Healthy()
|
||||
Unhealthy(error)
|
||||
}
|
||||
|
||||
// NewHealthcheck constructs a new Healthcheck which will use the given
|
||||
// function to update its status.
|
||||
func NewHealthcheck(f func(Healthcheck)) Healthcheck {
|
||||
if UseNilMetrics {
|
||||
return NilHealthcheck{}
|
||||
}
|
||||
return &StandardHealthcheck{nil, f}
|
||||
}
|
||||
|
||||
// NilHealthcheck is a no-op.
|
||||
type NilHealthcheck struct{}
|
||||
|
||||
// Check is a no-op.
|
||||
func (NilHealthcheck) Check() {}
|
||||
|
||||
// Error is a no-op.
|
||||
func (NilHealthcheck) Error() error { return nil }
|
||||
|
||||
// Healthy is a no-op.
|
||||
func (NilHealthcheck) Healthy() {}
|
||||
|
||||
// Unhealthy is a no-op.
|
||||
func (NilHealthcheck) Unhealthy(error) {}
|
||||
|
||||
// StandardHealthcheck is the standard implementation of a Healthcheck and
|
||||
// stores the status and a function to call to update the status.
|
||||
type StandardHealthcheck struct {
|
||||
err error
|
||||
f func(Healthcheck)
|
||||
}
|
||||
|
||||
// Check runs the healthcheck function to update the healthcheck's status.
|
||||
func (h *StandardHealthcheck) Check() {
|
||||
h.f(h)
|
||||
}
|
||||
|
||||
// Error returns the healthcheck's status, which will be nil if it is healthy.
|
||||
func (h *StandardHealthcheck) Error() error {
|
||||
return h.err
|
||||
}
|
||||
|
||||
// Healthy marks the healthcheck as healthy.
|
||||
func (h *StandardHealthcheck) Healthy() {
|
||||
h.err = nil
|
||||
}
|
||||
|
||||
// Unhealthy marks the healthcheck as unhealthy. The error is stored and
|
||||
// may be retrieved by the Error method.
|
||||
func (h *StandardHealthcheck) Unhealthy(err error) {
|
||||
h.err = err
|
||||
}
|
||||
202
Godeps/_workspace/src/github.com/rcrowley/go-metrics/histogram.go
generated
vendored
Normal file
202
Godeps/_workspace/src/github.com/rcrowley/go-metrics/histogram.go
generated
vendored
Normal file
@@ -0,0 +1,202 @@
|
||||
package metrics
|
||||
|
||||
// Histograms calculate distribution statistics from a series of int64 values.
|
||||
type Histogram interface {
|
||||
Clear()
|
||||
Count() int64
|
||||
Max() int64
|
||||
Mean() float64
|
||||
Min() int64
|
||||
Percentile(float64) float64
|
||||
Percentiles([]float64) []float64
|
||||
Sample() Sample
|
||||
Snapshot() Histogram
|
||||
StdDev() float64
|
||||
Sum() int64
|
||||
Update(int64)
|
||||
Variance() float64
|
||||
}
|
||||
|
||||
// GetOrRegisterHistogram returns an existing Histogram or constructs and
|
||||
// registers a new StandardHistogram.
|
||||
func GetOrRegisterHistogram(name string, r Registry, s Sample) Histogram {
|
||||
if nil == r {
|
||||
r = DefaultRegistry
|
||||
}
|
||||
return r.GetOrRegister(name, func() Histogram { return NewHistogram(s) }).(Histogram)
|
||||
}
|
||||
|
||||
// NewHistogram constructs a new StandardHistogram from a Sample.
|
||||
func NewHistogram(s Sample) Histogram {
|
||||
if UseNilMetrics {
|
||||
return NilHistogram{}
|
||||
}
|
||||
return &StandardHistogram{sample: s}
|
||||
}
|
||||
|
||||
// NewRegisteredHistogram constructs and registers a new StandardHistogram from
|
||||
// a Sample.
|
||||
func NewRegisteredHistogram(name string, r Registry, s Sample) Histogram {
|
||||
c := NewHistogram(s)
|
||||
if nil == r {
|
||||
r = DefaultRegistry
|
||||
}
|
||||
r.Register(name, c)
|
||||
return c
|
||||
}
|
||||
|
||||
// HistogramSnapshot is a read-only copy of another Histogram.
|
||||
type HistogramSnapshot struct {
|
||||
sample *SampleSnapshot
|
||||
}
|
||||
|
||||
// Clear panics.
|
||||
func (*HistogramSnapshot) Clear() {
|
||||
panic("Clear called on a HistogramSnapshot")
|
||||
}
|
||||
|
||||
// Count returns the number of samples recorded at the time the snapshot was
|
||||
// taken.
|
||||
func (h *HistogramSnapshot) Count() int64 { return h.sample.Count() }
|
||||
|
||||
// Max returns the maximum value in the sample at the time the snapshot was
|
||||
// taken.
|
||||
func (h *HistogramSnapshot) Max() int64 { return h.sample.Max() }
|
||||
|
||||
// Mean returns the mean of the values in the sample at the time the snapshot
|
||||
// was taken.
|
||||
func (h *HistogramSnapshot) Mean() float64 { return h.sample.Mean() }
|
||||
|
||||
// Min returns the minimum value in the sample at the time the snapshot was
|
||||
// taken.
|
||||
func (h *HistogramSnapshot) Min() int64 { return h.sample.Min() }
|
||||
|
||||
// Percentile returns an arbitrary percentile of values in the sample at the
|
||||
// time the snapshot was taken.
|
||||
func (h *HistogramSnapshot) Percentile(p float64) float64 {
|
||||
return h.sample.Percentile(p)
|
||||
}
|
||||
|
||||
// Percentiles returns a slice of arbitrary percentiles of values in the sample
|
||||
// at the time the snapshot was taken.
|
||||
func (h *HistogramSnapshot) Percentiles(ps []float64) []float64 {
|
||||
return h.sample.Percentiles(ps)
|
||||
}
|
||||
|
||||
// Sample returns the Sample underlying the histogram.
|
||||
func (h *HistogramSnapshot) Sample() Sample { return h.sample }
|
||||
|
||||
// Snapshot returns the snapshot.
|
||||
func (h *HistogramSnapshot) Snapshot() Histogram { return h }
|
||||
|
||||
// StdDev returns the standard deviation of the values in the sample at the
|
||||
// time the snapshot was taken.
|
||||
func (h *HistogramSnapshot) StdDev() float64 { return h.sample.StdDev() }
|
||||
|
||||
// Sum returns the sum in the sample at the time the snapshot was taken.
|
||||
func (h *HistogramSnapshot) Sum() int64 { return h.sample.Sum() }
|
||||
|
||||
// Update panics.
|
||||
func (*HistogramSnapshot) Update(int64) {
|
||||
panic("Update called on a HistogramSnapshot")
|
||||
}
|
||||
|
||||
// Variance returns the variance of inputs at the time the snapshot was taken.
|
||||
func (h *HistogramSnapshot) Variance() float64 { return h.sample.Variance() }
|
||||
|
||||
// NilHistogram is a no-op Histogram.
|
||||
type NilHistogram struct{}
|
||||
|
||||
// Clear is a no-op.
|
||||
func (NilHistogram) Clear() {}
|
||||
|
||||
// Count is a no-op.
|
||||
func (NilHistogram) Count() int64 { return 0 }
|
||||
|
||||
// Max is a no-op.
|
||||
func (NilHistogram) Max() int64 { return 0 }
|
||||
|
||||
// Mean is a no-op.
|
||||
func (NilHistogram) Mean() float64 { return 0.0 }
|
||||
|
||||
// Min is a no-op.
|
||||
func (NilHistogram) Min() int64 { return 0 }
|
||||
|
||||
// Percentile is a no-op.
|
||||
func (NilHistogram) Percentile(p float64) float64 { return 0.0 }
|
||||
|
||||
// Percentiles is a no-op.
|
||||
func (NilHistogram) Percentiles(ps []float64) []float64 {
|
||||
return make([]float64, len(ps))
|
||||
}
|
||||
|
||||
// Sample is a no-op.
|
||||
func (NilHistogram) Sample() Sample { return NilSample{} }
|
||||
|
||||
// Snapshot is a no-op.
|
||||
func (NilHistogram) Snapshot() Histogram { return NilHistogram{} }
|
||||
|
||||
// StdDev is a no-op.
|
||||
func (NilHistogram) StdDev() float64 { return 0.0 }
|
||||
|
||||
// Sum is a no-op.
|
||||
func (NilHistogram) Sum() int64 { return 0 }
|
||||
|
||||
// Update is a no-op.
|
||||
func (NilHistogram) Update(v int64) {}
|
||||
|
||||
// Variance is a no-op.
|
||||
func (NilHistogram) Variance() float64 { return 0.0 }
|
||||
|
||||
// StandardHistogram is the standard implementation of a Histogram and uses a
|
||||
// Sample to bound its memory use.
|
||||
type StandardHistogram struct {
|
||||
sample Sample
|
||||
}
|
||||
|
||||
// Clear clears the histogram and its sample.
|
||||
func (h *StandardHistogram) Clear() { h.sample.Clear() }
|
||||
|
||||
// Count returns the number of samples recorded since the histogram was last
|
||||
// cleared.
|
||||
func (h *StandardHistogram) Count() int64 { return h.sample.Count() }
|
||||
|
||||
// Max returns the maximum value in the sample.
|
||||
func (h *StandardHistogram) Max() int64 { return h.sample.Max() }
|
||||
|
||||
// Mean returns the mean of the values in the sample.
|
||||
func (h *StandardHistogram) Mean() float64 { return h.sample.Mean() }
|
||||
|
||||
// Min returns the minimum value in the sample.
|
||||
func (h *StandardHistogram) Min() int64 { return h.sample.Min() }
|
||||
|
||||
// Percentile returns an arbitrary percentile of the values in the sample.
|
||||
func (h *StandardHistogram) Percentile(p float64) float64 {
|
||||
return h.sample.Percentile(p)
|
||||
}
|
||||
|
||||
// Percentiles returns a slice of arbitrary percentiles of the values in the
|
||||
// sample.
|
||||
func (h *StandardHistogram) Percentiles(ps []float64) []float64 {
|
||||
return h.sample.Percentiles(ps)
|
||||
}
|
||||
|
||||
// Sample returns the Sample underlying the histogram.
|
||||
func (h *StandardHistogram) Sample() Sample { return h.sample }
|
||||
|
||||
// Snapshot returns a read-only copy of the histogram.
|
||||
func (h *StandardHistogram) Snapshot() Histogram {
|
||||
return &HistogramSnapshot{sample: h.sample.Snapshot().(*SampleSnapshot)}
|
||||
}
|
||||
|
||||
// StdDev returns the standard deviation of the values in the sample.
|
||||
func (h *StandardHistogram) StdDev() float64 { return h.sample.StdDev() }
|
||||
|
||||
// Sum returns the sum in the sample.
|
||||
func (h *StandardHistogram) Sum() int64 { return h.sample.Sum() }
|
||||
|
||||
// Update samples a new value.
|
||||
func (h *StandardHistogram) Update(v int64) { h.sample.Update(v) }
|
||||
|
||||
// Variance returns the variance of the values in the sample.
|
||||
func (h *StandardHistogram) Variance() float64 { return h.sample.Variance() }
|
||||
83
Godeps/_workspace/src/github.com/rcrowley/go-metrics/json.go
generated
vendored
Normal file
83
Godeps/_workspace/src/github.com/rcrowley/go-metrics/json.go
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"time"
|
||||
)
|
||||
|
||||
// MarshalJSON returns a byte slice containing a JSON representation of all
|
||||
// the metrics in the Registry.
|
||||
func (r *StandardRegistry) MarshalJSON() ([]byte, error) {
|
||||
data := make(map[string]map[string]interface{})
|
||||
r.Each(func(name string, i interface{}) {
|
||||
values := make(map[string]interface{})
|
||||
switch metric := i.(type) {
|
||||
case Counter:
|
||||
values["count"] = metric.Count()
|
||||
case Gauge:
|
||||
values["value"] = metric.Value()
|
||||
case GaugeFloat64:
|
||||
values["value"] = metric.Value()
|
||||
case Healthcheck:
|
||||
values["error"] = nil
|
||||
metric.Check()
|
||||
if err := metric.Error(); nil != err {
|
||||
values["error"] = metric.Error().Error()
|
||||
}
|
||||
case Histogram:
|
||||
h := metric.Snapshot()
|
||||
ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
|
||||
values["count"] = h.Count()
|
||||
values["min"] = h.Min()
|
||||
values["max"] = h.Max()
|
||||
values["mean"] = h.Mean()
|
||||
values["stddev"] = h.StdDev()
|
||||
values["median"] = ps[0]
|
||||
values["75%"] = ps[1]
|
||||
values["95%"] = ps[2]
|
||||
values["99%"] = ps[3]
|
||||
values["99.9%"] = ps[4]
|
||||
case Meter:
|
||||
m := metric.Snapshot()
|
||||
values["count"] = m.Count()
|
||||
values["1m.rate"] = m.Rate1()
|
||||
values["5m.rate"] = m.Rate5()
|
||||
values["15m.rate"] = m.Rate15()
|
||||
values["mean.rate"] = m.RateMean()
|
||||
case Timer:
|
||||
t := metric.Snapshot()
|
||||
ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
|
||||
values["count"] = t.Count()
|
||||
values["min"] = t.Min()
|
||||
values["max"] = t.Max()
|
||||
values["mean"] = t.Mean()
|
||||
values["stddev"] = t.StdDev()
|
||||
values["median"] = ps[0]
|
||||
values["75%"] = ps[1]
|
||||
values["95%"] = ps[2]
|
||||
values["99%"] = ps[3]
|
||||
values["99.9%"] = ps[4]
|
||||
values["1m.rate"] = t.Rate1()
|
||||
values["5m.rate"] = t.Rate5()
|
||||
values["15m.rate"] = t.Rate15()
|
||||
values["mean.rate"] = t.RateMean()
|
||||
}
|
||||
data[name] = values
|
||||
})
|
||||
return json.Marshal(data)
|
||||
}
|
||||
|
||||
// WriteJSON writes metrics from the given registry periodically to the
|
||||
// specified io.Writer as JSON.
|
||||
func WriteJSON(r Registry, d time.Duration, w io.Writer) {
|
||||
for _ = range time.Tick(d) {
|
||||
WriteJSONOnce(r, w)
|
||||
}
|
||||
}
|
||||
|
||||
// WriteJSONOnce writes metrics from the given registry to the specified
|
||||
// io.Writer as JSON.
|
||||
func WriteJSONOnce(r Registry, w io.Writer) {
|
||||
json.NewEncoder(w).Encode(r)
|
||||
}
|
||||
102
Godeps/_workspace/src/github.com/rcrowley/go-metrics/librato/client.go
generated
vendored
Normal file
102
Godeps/_workspace/src/github.com/rcrowley/go-metrics/librato/client.go
generated
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
package librato
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
const Operations = "operations"
|
||||
const OperationsShort = "ops"
|
||||
|
||||
type LibratoClient struct {
|
||||
Email, Token string
|
||||
}
|
||||
|
||||
// property strings
|
||||
const (
|
||||
// display attributes
|
||||
Color = "color"
|
||||
DisplayMax = "display_max"
|
||||
DisplayMin = "display_min"
|
||||
DisplayUnitsLong = "display_units_long"
|
||||
DisplayUnitsShort = "display_units_short"
|
||||
DisplayStacked = "display_stacked"
|
||||
DisplayTransform = "display_transform"
|
||||
// special gauge display attributes
|
||||
SummarizeFunction = "summarize_function"
|
||||
Aggregate = "aggregate"
|
||||
|
||||
// metric keys
|
||||
Name = "name"
|
||||
Period = "period"
|
||||
Description = "description"
|
||||
DisplayName = "display_name"
|
||||
Attributes = "attributes"
|
||||
|
||||
// measurement keys
|
||||
MeasureTime = "measure_time"
|
||||
Source = "source"
|
||||
Value = "value"
|
||||
|
||||
// special gauge keys
|
||||
Count = "count"
|
||||
Sum = "sum"
|
||||
Max = "max"
|
||||
Min = "min"
|
||||
SumSquares = "sum_squares"
|
||||
|
||||
// batch keys
|
||||
Counters = "counters"
|
||||
Gauges = "gauges"
|
||||
|
||||
MetricsPostUrl = "https://metrics-api.librato.com/v1/metrics"
|
||||
)
|
||||
|
||||
type Measurement map[string]interface{}
|
||||
type Metric map[string]interface{}
|
||||
|
||||
type Batch struct {
|
||||
Gauges []Measurement `json:"gauges,omitempty"`
|
||||
Counters []Measurement `json:"counters,omitempty"`
|
||||
MeasureTime int64 `json:"measure_time"`
|
||||
Source string `json:"source"`
|
||||
}
|
||||
|
||||
func (self *LibratoClient) PostMetrics(batch Batch) (err error) {
|
||||
var (
|
||||
js []byte
|
||||
req *http.Request
|
||||
resp *http.Response
|
||||
)
|
||||
|
||||
if len(batch.Counters) == 0 && len(batch.Gauges) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if js, err = json.Marshal(batch); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if req, err = http.NewRequest("POST", MetricsPostUrl, bytes.NewBuffer(js)); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.SetBasicAuth(self.Email, self.Token)
|
||||
|
||||
if resp, err = http.DefaultClient.Do(req); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
var body []byte
|
||||
if body, err = ioutil.ReadAll(resp.Body); err != nil {
|
||||
body = []byte(fmt.Sprintf("(could not fetch response body for error: %s)", err))
|
||||
}
|
||||
err = fmt.Errorf("Unable to post to Librato: %d %s %s", resp.StatusCode, resp.Status, string(body))
|
||||
}
|
||||
return
|
||||
}
|
||||
231
Godeps/_workspace/src/github.com/rcrowley/go-metrics/librato/librato.go
generated
vendored
Normal file
231
Godeps/_workspace/src/github.com/rcrowley/go-metrics/librato/librato.go
generated
vendored
Normal file
@@ -0,0 +1,231 @@
|
||||
package librato
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"math"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"github.com/rcrowley/go-metrics"
|
||||
)
|
||||
|
||||
// a regexp for extracting the unit from time.Duration.String
|
||||
var unitRegexp = regexp.MustCompile("[^\\d]+$")
|
||||
|
||||
// a helper that turns a time.Duration into librato display attributes for timer metrics
|
||||
func translateTimerAttributes(d time.Duration) (attrs map[string]interface{}) {
|
||||
attrs = make(map[string]interface{})
|
||||
attrs[DisplayTransform] = fmt.Sprintf("x/%d", int64(d))
|
||||
attrs[DisplayUnitsShort] = string(unitRegexp.Find([]byte(d.String())))
|
||||
return
|
||||
}
|
||||
|
||||
type Reporter struct {
|
||||
Email, Token string
|
||||
Source string
|
||||
Interval time.Duration
|
||||
Registry metrics.Registry
|
||||
Percentiles []float64 // percentiles to report on histogram metrics
|
||||
TimerAttributes map[string]interface{} // units in which timers will be displayed
|
||||
intervalSec int64
|
||||
}
|
||||
|
||||
func NewReporter(r metrics.Registry, d time.Duration, e string, t string, s string, p []float64, u time.Duration) *Reporter {
|
||||
return &Reporter{e, t, s, d, r, p, translateTimerAttributes(u), int64(d / time.Second)}
|
||||
}
|
||||
|
||||
func Librato(r metrics.Registry, d time.Duration, e string, t string, s string, p []float64, u time.Duration) {
|
||||
NewReporter(r, d, e, t, s, p, u).Run()
|
||||
}
|
||||
|
||||
func (self *Reporter) Run() {
|
||||
log.Printf("WARNING: This client has been DEPRECATED! It has been moved to https://github.com/mihasya/go-metrics-librato and will be removed from rcrowley/go-metrics on August 5th 2015")
|
||||
ticker := time.Tick(self.Interval)
|
||||
metricsApi := &LibratoClient{self.Email, self.Token}
|
||||
for now := range ticker {
|
||||
var metrics Batch
|
||||
var err error
|
||||
if metrics, err = self.BuildRequest(now, self.Registry); err != nil {
|
||||
log.Printf("ERROR constructing librato request body %s", err)
|
||||
continue
|
||||
}
|
||||
if err := metricsApi.PostMetrics(metrics); err != nil {
|
||||
log.Printf("ERROR sending metrics to librato %s", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// calculate sum of squares from data provided by metrics.Histogram
|
||||
// see http://en.wikipedia.org/wiki/Standard_deviation#Rapid_calculation_methods
|
||||
func sumSquares(s metrics.Sample) float64 {
|
||||
count := float64(s.Count())
|
||||
sumSquared := math.Pow(count*s.Mean(), 2)
|
||||
sumSquares := math.Pow(count*s.StdDev(), 2) + sumSquared/count
|
||||
if math.IsNaN(sumSquares) {
|
||||
return 0.0
|
||||
}
|
||||
return sumSquares
|
||||
}
|
||||
func sumSquaresTimer(t metrics.Timer) float64 {
|
||||
count := float64(t.Count())
|
||||
sumSquared := math.Pow(count*t.Mean(), 2)
|
||||
sumSquares := math.Pow(count*t.StdDev(), 2) + sumSquared/count
|
||||
if math.IsNaN(sumSquares) {
|
||||
return 0.0
|
||||
}
|
||||
return sumSquares
|
||||
}
|
||||
|
||||
func (self *Reporter) BuildRequest(now time.Time, r metrics.Registry) (snapshot Batch, err error) {
|
||||
snapshot = Batch{
|
||||
// coerce timestamps to a stepping fn so that they line up in Librato graphs
|
||||
MeasureTime: (now.Unix() / self.intervalSec) * self.intervalSec,
|
||||
Source: self.Source,
|
||||
}
|
||||
snapshot.Gauges = make([]Measurement, 0)
|
||||
snapshot.Counters = make([]Measurement, 0)
|
||||
histogramGaugeCount := 1 + len(self.Percentiles)
|
||||
r.Each(func(name string, metric interface{}) {
|
||||
measurement := Measurement{}
|
||||
measurement[Period] = self.Interval.Seconds()
|
||||
switch m := metric.(type) {
|
||||
case metrics.Counter:
|
||||
if m.Count() > 0 {
|
||||
measurement[Name] = fmt.Sprintf("%s.%s", name, "count")
|
||||
measurement[Value] = float64(m.Count())
|
||||
measurement[Attributes] = map[string]interface{}{
|
||||
DisplayUnitsLong: Operations,
|
||||
DisplayUnitsShort: OperationsShort,
|
||||
DisplayMin: "0",
|
||||
}
|
||||
snapshot.Counters = append(snapshot.Counters, measurement)
|
||||
}
|
||||
case metrics.Gauge:
|
||||
measurement[Name] = name
|
||||
measurement[Value] = float64(m.Value())
|
||||
snapshot.Gauges = append(snapshot.Gauges, measurement)
|
||||
case metrics.GaugeFloat64:
|
||||
measurement[Name] = name
|
||||
measurement[Value] = float64(m.Value())
|
||||
snapshot.Gauges = append(snapshot.Gauges, measurement)
|
||||
case metrics.Histogram:
|
||||
if m.Count() > 0 {
|
||||
gauges := make([]Measurement, histogramGaugeCount, histogramGaugeCount)
|
||||
s := m.Sample()
|
||||
measurement[Name] = fmt.Sprintf("%s.%s", name, "hist")
|
||||
measurement[Count] = uint64(s.Count())
|
||||
measurement[Max] = float64(s.Max())
|
||||
measurement[Min] = float64(s.Min())
|
||||
measurement[Sum] = float64(s.Sum())
|
||||
measurement[SumSquares] = sumSquares(s)
|
||||
gauges[0] = measurement
|
||||
for i, p := range self.Percentiles {
|
||||
gauges[i+1] = Measurement{
|
||||
Name: fmt.Sprintf("%s.%.2f", measurement[Name], p),
|
||||
Value: s.Percentile(p),
|
||||
Period: measurement[Period],
|
||||
}
|
||||
}
|
||||
snapshot.Gauges = append(snapshot.Gauges, gauges...)
|
||||
}
|
||||
case metrics.Meter:
|
||||
measurement[Name] = name
|
||||
measurement[Value] = float64(m.Count())
|
||||
snapshot.Counters = append(snapshot.Counters, measurement)
|
||||
snapshot.Gauges = append(snapshot.Gauges,
|
||||
Measurement{
|
||||
Name: fmt.Sprintf("%s.%s", name, "1min"),
|
||||
Value: m.Rate1(),
|
||||
Period: int64(self.Interval.Seconds()),
|
||||
Attributes: map[string]interface{}{
|
||||
DisplayUnitsLong: Operations,
|
||||
DisplayUnitsShort: OperationsShort,
|
||||
DisplayMin: "0",
|
||||
},
|
||||
},
|
||||
Measurement{
|
||||
Name: fmt.Sprintf("%s.%s", name, "5min"),
|
||||
Value: m.Rate5(),
|
||||
Period: int64(self.Interval.Seconds()),
|
||||
Attributes: map[string]interface{}{
|
||||
DisplayUnitsLong: Operations,
|
||||
DisplayUnitsShort: OperationsShort,
|
||||
DisplayMin: "0",
|
||||
},
|
||||
},
|
||||
Measurement{
|
||||
Name: fmt.Sprintf("%s.%s", name, "15min"),
|
||||
Value: m.Rate15(),
|
||||
Period: int64(self.Interval.Seconds()),
|
||||
Attributes: map[string]interface{}{
|
||||
DisplayUnitsLong: Operations,
|
||||
DisplayUnitsShort: OperationsShort,
|
||||
DisplayMin: "0",
|
||||
},
|
||||
},
|
||||
)
|
||||
case metrics.Timer:
|
||||
measurement[Name] = name
|
||||
measurement[Value] = float64(m.Count())
|
||||
snapshot.Counters = append(snapshot.Counters, measurement)
|
||||
if m.Count() > 0 {
|
||||
libratoName := fmt.Sprintf("%s.%s", name, "timer.mean")
|
||||
gauges := make([]Measurement, histogramGaugeCount, histogramGaugeCount)
|
||||
gauges[0] = Measurement{
|
||||
Name: libratoName,
|
||||
Count: uint64(m.Count()),
|
||||
Sum: m.Mean() * float64(m.Count()),
|
||||
Max: float64(m.Max()),
|
||||
Min: float64(m.Min()),
|
||||
SumSquares: sumSquaresTimer(m),
|
||||
Period: int64(self.Interval.Seconds()),
|
||||
Attributes: self.TimerAttributes,
|
||||
}
|
||||
for i, p := range self.Percentiles {
|
||||
gauges[i+1] = Measurement{
|
||||
Name: fmt.Sprintf("%s.timer.%2.0f", name, p*100),
|
||||
Value: m.Percentile(p),
|
||||
Period: int64(self.Interval.Seconds()),
|
||||
Attributes: self.TimerAttributes,
|
||||
}
|
||||
}
|
||||
snapshot.Gauges = append(snapshot.Gauges, gauges...)
|
||||
snapshot.Gauges = append(snapshot.Gauges,
|
||||
Measurement{
|
||||
Name: fmt.Sprintf("%s.%s", name, "rate.1min"),
|
||||
Value: m.Rate1(),
|
||||
Period: int64(self.Interval.Seconds()),
|
||||
Attributes: map[string]interface{}{
|
||||
DisplayUnitsLong: Operations,
|
||||
DisplayUnitsShort: OperationsShort,
|
||||
DisplayMin: "0",
|
||||
},
|
||||
},
|
||||
Measurement{
|
||||
Name: fmt.Sprintf("%s.%s", name, "rate.5min"),
|
||||
Value: m.Rate5(),
|
||||
Period: int64(self.Interval.Seconds()),
|
||||
Attributes: map[string]interface{}{
|
||||
DisplayUnitsLong: Operations,
|
||||
DisplayUnitsShort: OperationsShort,
|
||||
DisplayMin: "0",
|
||||
},
|
||||
},
|
||||
Measurement{
|
||||
Name: fmt.Sprintf("%s.%s", name, "rate.15min"),
|
||||
Value: m.Rate15(),
|
||||
Period: int64(self.Interval.Seconds()),
|
||||
Attributes: map[string]interface{}{
|
||||
DisplayUnitsLong: Operations,
|
||||
DisplayUnitsShort: OperationsShort,
|
||||
DisplayMin: "0",
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
70
Godeps/_workspace/src/github.com/rcrowley/go-metrics/log.go
generated
vendored
Normal file
70
Godeps/_workspace/src/github.com/rcrowley/go-metrics/log.go
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"log"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Output each metric in the given registry periodically using the given
|
||||
// logger.
|
||||
func Log(r Registry, d time.Duration, l *log.Logger) {
|
||||
for _ = range time.Tick(d) {
|
||||
r.Each(func(name string, i interface{}) {
|
||||
switch metric := i.(type) {
|
||||
case Counter:
|
||||
l.Printf("counter %s\n", name)
|
||||
l.Printf(" count: %9d\n", metric.Count())
|
||||
case Gauge:
|
||||
l.Printf("gauge %s\n", name)
|
||||
l.Printf(" value: %9d\n", metric.Value())
|
||||
case GaugeFloat64:
|
||||
l.Printf("gauge %s\n", name)
|
||||
l.Printf(" value: %f\n", metric.Value())
|
||||
case Healthcheck:
|
||||
metric.Check()
|
||||
l.Printf("healthcheck %s\n", name)
|
||||
l.Printf(" error: %v\n", metric.Error())
|
||||
case Histogram:
|
||||
h := metric.Snapshot()
|
||||
ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
|
||||
l.Printf("histogram %s\n", name)
|
||||
l.Printf(" count: %9d\n", h.Count())
|
||||
l.Printf(" min: %9d\n", h.Min())
|
||||
l.Printf(" max: %9d\n", h.Max())
|
||||
l.Printf(" mean: %12.2f\n", h.Mean())
|
||||
l.Printf(" stddev: %12.2f\n", h.StdDev())
|
||||
l.Printf(" median: %12.2f\n", ps[0])
|
||||
l.Printf(" 75%%: %12.2f\n", ps[1])
|
||||
l.Printf(" 95%%: %12.2f\n", ps[2])
|
||||
l.Printf(" 99%%: %12.2f\n", ps[3])
|
||||
l.Printf(" 99.9%%: %12.2f\n", ps[4])
|
||||
case Meter:
|
||||
m := metric.Snapshot()
|
||||
l.Printf("meter %s\n", name)
|
||||
l.Printf(" count: %9d\n", m.Count())
|
||||
l.Printf(" 1-min rate: %12.2f\n", m.Rate1())
|
||||
l.Printf(" 5-min rate: %12.2f\n", m.Rate5())
|
||||
l.Printf(" 15-min rate: %12.2f\n", m.Rate15())
|
||||
l.Printf(" mean rate: %12.2f\n", m.RateMean())
|
||||
case Timer:
|
||||
t := metric.Snapshot()
|
||||
ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
|
||||
l.Printf("timer %s\n", name)
|
||||
l.Printf(" count: %9d\n", t.Count())
|
||||
l.Printf(" min: %9d\n", t.Min())
|
||||
l.Printf(" max: %9d\n", t.Max())
|
||||
l.Printf(" mean: %12.2f\n", t.Mean())
|
||||
l.Printf(" stddev: %12.2f\n", t.StdDev())
|
||||
l.Printf(" median: %12.2f\n", ps[0])
|
||||
l.Printf(" 75%%: %12.2f\n", ps[1])
|
||||
l.Printf(" 95%%: %12.2f\n", ps[2])
|
||||
l.Printf(" 99%%: %12.2f\n", ps[3])
|
||||
l.Printf(" 99.9%%: %12.2f\n", ps[4])
|
||||
l.Printf(" 1-min rate: %12.2f\n", t.Rate1())
|
||||
l.Printf(" 5-min rate: %12.2f\n", t.Rate5())
|
||||
l.Printf(" 15-min rate: %12.2f\n", t.Rate15())
|
||||
l.Printf(" mean rate: %12.2f\n", t.RateMean())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
285
Godeps/_workspace/src/github.com/rcrowley/go-metrics/memory.md
generated
vendored
Normal file
285
Godeps/_workspace/src/github.com/rcrowley/go-metrics/memory.md
generated
vendored
Normal file
@@ -0,0 +1,285 @@
|
||||
Memory usage
|
||||
============
|
||||
|
||||
(Highly unscientific.)
|
||||
|
||||
Command used to gather static memory usage:
|
||||
|
||||
```sh
|
||||
grep ^Vm "/proc/$(ps fax | grep [m]etrics-bench | awk '{print $1}')/status"
|
||||
```
|
||||
|
||||
Program used to gather baseline memory usage:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import "time"
|
||||
|
||||
func main() {
|
||||
time.Sleep(600e9)
|
||||
}
|
||||
```
|
||||
|
||||
Baseline
|
||||
--------
|
||||
|
||||
```
|
||||
VmPeak: 42604 kB
|
||||
VmSize: 42604 kB
|
||||
VmLck: 0 kB
|
||||
VmHWM: 1120 kB
|
||||
VmRSS: 1120 kB
|
||||
VmData: 35460 kB
|
||||
VmStk: 136 kB
|
||||
VmExe: 1020 kB
|
||||
VmLib: 1848 kB
|
||||
VmPTE: 36 kB
|
||||
VmSwap: 0 kB
|
||||
```
|
||||
|
||||
Program used to gather metric memory usage (with other metrics being similar):
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"metrics"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Sprintf("foo")
|
||||
metrics.NewRegistry()
|
||||
time.Sleep(600e9)
|
||||
}
|
||||
```
|
||||
|
||||
1000 counters registered
|
||||
------------------------
|
||||
|
||||
```
|
||||
VmPeak: 44016 kB
|
||||
VmSize: 44016 kB
|
||||
VmLck: 0 kB
|
||||
VmHWM: 1928 kB
|
||||
VmRSS: 1928 kB
|
||||
VmData: 36868 kB
|
||||
VmStk: 136 kB
|
||||
VmExe: 1024 kB
|
||||
VmLib: 1848 kB
|
||||
VmPTE: 40 kB
|
||||
VmSwap: 0 kB
|
||||
```
|
||||
|
||||
**1.412 kB virtual, TODO 0.808 kB resident per counter.**
|
||||
|
||||
100000 counters registered
|
||||
--------------------------
|
||||
|
||||
```
|
||||
VmPeak: 55024 kB
|
||||
VmSize: 55024 kB
|
||||
VmLck: 0 kB
|
||||
VmHWM: 12440 kB
|
||||
VmRSS: 12440 kB
|
||||
VmData: 47876 kB
|
||||
VmStk: 136 kB
|
||||
VmExe: 1024 kB
|
||||
VmLib: 1848 kB
|
||||
VmPTE: 64 kB
|
||||
VmSwap: 0 kB
|
||||
```
|
||||
|
||||
**0.1242 kB virtual, 0.1132 kB resident per counter.**
|
||||
|
||||
1000 gauges registered
|
||||
----------------------
|
||||
|
||||
```
|
||||
VmPeak: 44012 kB
|
||||
VmSize: 44012 kB
|
||||
VmLck: 0 kB
|
||||
VmHWM: 1928 kB
|
||||
VmRSS: 1928 kB
|
||||
VmData: 36868 kB
|
||||
VmStk: 136 kB
|
||||
VmExe: 1020 kB
|
||||
VmLib: 1848 kB
|
||||
VmPTE: 40 kB
|
||||
VmSwap: 0 kB
|
||||
```
|
||||
|
||||
**1.408 kB virtual, 0.808 kB resident per counter.**
|
||||
|
||||
100000 gauges registered
|
||||
------------------------
|
||||
|
||||
```
|
||||
VmPeak: 55020 kB
|
||||
VmSize: 55020 kB
|
||||
VmLck: 0 kB
|
||||
VmHWM: 12432 kB
|
||||
VmRSS: 12432 kB
|
||||
VmData: 47876 kB
|
||||
VmStk: 136 kB
|
||||
VmExe: 1020 kB
|
||||
VmLib: 1848 kB
|
||||
VmPTE: 60 kB
|
||||
VmSwap: 0 kB
|
||||
```
|
||||
|
||||
**0.12416 kB virtual, 0.11312 resident per gauge.**
|
||||
|
||||
1000 histograms with a uniform sample size of 1028
|
||||
--------------------------------------------------
|
||||
|
||||
```
|
||||
VmPeak: 72272 kB
|
||||
VmSize: 72272 kB
|
||||
VmLck: 0 kB
|
||||
VmHWM: 16204 kB
|
||||
VmRSS: 16204 kB
|
||||
VmData: 65100 kB
|
||||
VmStk: 136 kB
|
||||
VmExe: 1048 kB
|
||||
VmLib: 1848 kB
|
||||
VmPTE: 80 kB
|
||||
VmSwap: 0 kB
|
||||
```
|
||||
|
||||
**29.668 kB virtual, TODO 15.084 resident per histogram.**
|
||||
|
||||
10000 histograms with a uniform sample size of 1028
|
||||
---------------------------------------------------
|
||||
|
||||
```
|
||||
VmPeak: 256912 kB
|
||||
VmSize: 256912 kB
|
||||
VmLck: 0 kB
|
||||
VmHWM: 146204 kB
|
||||
VmRSS: 146204 kB
|
||||
VmData: 249740 kB
|
||||
VmStk: 136 kB
|
||||
VmExe: 1048 kB
|
||||
VmLib: 1848 kB
|
||||
VmPTE: 448 kB
|
||||
VmSwap: 0 kB
|
||||
```
|
||||
|
||||
**21.4308 kB virtual, 14.5084 kB resident per histogram.**
|
||||
|
||||
50000 histograms with a uniform sample size of 1028
|
||||
---------------------------------------------------
|
||||
|
||||
```
|
||||
VmPeak: 908112 kB
|
||||
VmSize: 908112 kB
|
||||
VmLck: 0 kB
|
||||
VmHWM: 645832 kB
|
||||
VmRSS: 645588 kB
|
||||
VmData: 900940 kB
|
||||
VmStk: 136 kB
|
||||
VmExe: 1048 kB
|
||||
VmLib: 1848 kB
|
||||
VmPTE: 1716 kB
|
||||
VmSwap: 1544 kB
|
||||
```
|
||||
|
||||
**17.31016 kB virtual, 12.88936 kB resident per histogram.**
|
||||
|
||||
1000 histograms with an exponentially-decaying sample size of 1028 and alpha of 0.015
|
||||
-------------------------------------------------------------------------------------
|
||||
|
||||
```
|
||||
VmPeak: 62480 kB
|
||||
VmSize: 62480 kB
|
||||
VmLck: 0 kB
|
||||
VmHWM: 11572 kB
|
||||
VmRSS: 11572 kB
|
||||
VmData: 55308 kB
|
||||
VmStk: 136 kB
|
||||
VmExe: 1048 kB
|
||||
VmLib: 1848 kB
|
||||
VmPTE: 64 kB
|
||||
VmSwap: 0 kB
|
||||
```
|
||||
|
||||
**19.876 kB virtual, 10.452 kB resident per histogram.**
|
||||
|
||||
10000 histograms with an exponentially-decaying sample size of 1028 and alpha of 0.015
|
||||
--------------------------------------------------------------------------------------
|
||||
|
||||
```
|
||||
VmPeak: 153296 kB
|
||||
VmSize: 153296 kB
|
||||
VmLck: 0 kB
|
||||
VmHWM: 101176 kB
|
||||
VmRSS: 101176 kB
|
||||
VmData: 146124 kB
|
||||
VmStk: 136 kB
|
||||
VmExe: 1048 kB
|
||||
VmLib: 1848 kB
|
||||
VmPTE: 240 kB
|
||||
VmSwap: 0 kB
|
||||
```
|
||||
|
||||
**11.0692 kB virtual, 10.0056 kB resident per histogram.**
|
||||
|
||||
50000 histograms with an exponentially-decaying sample size of 1028 and alpha of 0.015
|
||||
--------------------------------------------------------------------------------------
|
||||
|
||||
```
|
||||
VmPeak: 557264 kB
|
||||
VmSize: 557264 kB
|
||||
VmLck: 0 kB
|
||||
VmHWM: 501056 kB
|
||||
VmRSS: 501056 kB
|
||||
VmData: 550092 kB
|
||||
VmStk: 136 kB
|
||||
VmExe: 1048 kB
|
||||
VmLib: 1848 kB
|
||||
VmPTE: 1032 kB
|
||||
VmSwap: 0 kB
|
||||
```
|
||||
|
||||
**10.2932 kB virtual, 9.99872 kB resident per histogram.**
|
||||
|
||||
1000 meters
|
||||
-----------
|
||||
|
||||
```
|
||||
VmPeak: 74504 kB
|
||||
VmSize: 74504 kB
|
||||
VmLck: 0 kB
|
||||
VmHWM: 24124 kB
|
||||
VmRSS: 24124 kB
|
||||
VmData: 67340 kB
|
||||
VmStk: 136 kB
|
||||
VmExe: 1040 kB
|
||||
VmLib: 1848 kB
|
||||
VmPTE: 92 kB
|
||||
VmSwap: 0 kB
|
||||
```
|
||||
|
||||
**31.9 kB virtual, 23.004 kB resident per meter.**
|
||||
|
||||
10000 meters
|
||||
------------
|
||||
|
||||
```
|
||||
VmPeak: 278920 kB
|
||||
VmSize: 278920 kB
|
||||
VmLck: 0 kB
|
||||
VmHWM: 227300 kB
|
||||
VmRSS: 227300 kB
|
||||
VmData: 271756 kB
|
||||
VmStk: 136 kB
|
||||
VmExe: 1040 kB
|
||||
VmLib: 1848 kB
|
||||
VmPTE: 488 kB
|
||||
VmSwap: 0 kB
|
||||
```
|
||||
|
||||
**23.6316 kB virtual, 22.618 kB resident per meter.**
|
||||
233
Godeps/_workspace/src/github.com/rcrowley/go-metrics/meter.go
generated
vendored
Normal file
233
Godeps/_workspace/src/github.com/rcrowley/go-metrics/meter.go
generated
vendored
Normal file
@@ -0,0 +1,233 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Meters count events to produce exponentially-weighted moving average rates
|
||||
// at one-, five-, and fifteen-minutes and a mean rate.
|
||||
type Meter interface {
|
||||
Count() int64
|
||||
Mark(int64)
|
||||
Rate1() float64
|
||||
Rate5() float64
|
||||
Rate15() float64
|
||||
RateMean() float64
|
||||
Snapshot() Meter
|
||||
}
|
||||
|
||||
// GetOrRegisterMeter returns an existing Meter or constructs and registers a
|
||||
// new StandardMeter.
|
||||
func GetOrRegisterMeter(name string, r Registry) Meter {
|
||||
if nil == r {
|
||||
r = DefaultRegistry
|
||||
}
|
||||
return r.GetOrRegister(name, NewMeter).(Meter)
|
||||
}
|
||||
|
||||
// NewMeter constructs a new StandardMeter and launches a goroutine.
|
||||
func NewMeter() Meter {
|
||||
if UseNilMetrics {
|
||||
return NilMeter{}
|
||||
}
|
||||
m := newStandardMeter()
|
||||
arbiter.Lock()
|
||||
defer arbiter.Unlock()
|
||||
arbiter.meters = append(arbiter.meters, m)
|
||||
if !arbiter.started {
|
||||
arbiter.started = true
|
||||
go arbiter.tick()
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// NewMeter constructs and registers a new StandardMeter and launches a
|
||||
// goroutine.
|
||||
func NewRegisteredMeter(name string, r Registry) Meter {
|
||||
c := NewMeter()
|
||||
if nil == r {
|
||||
r = DefaultRegistry
|
||||
}
|
||||
r.Register(name, c)
|
||||
return c
|
||||
}
|
||||
|
||||
// MeterSnapshot is a read-only copy of another Meter.
|
||||
type MeterSnapshot struct {
|
||||
count int64
|
||||
rate1, rate5, rate15, rateMean float64
|
||||
}
|
||||
|
||||
// Count returns the count of events at the time the snapshot was taken.
|
||||
func (m *MeterSnapshot) Count() int64 { return m.count }
|
||||
|
||||
// Mark panics.
|
||||
func (*MeterSnapshot) Mark(n int64) {
|
||||
panic("Mark called on a MeterSnapshot")
|
||||
}
|
||||
|
||||
// Rate1 returns the one-minute moving average rate of events per second at the
|
||||
// time the snapshot was taken.
|
||||
func (m *MeterSnapshot) Rate1() float64 { return m.rate1 }
|
||||
|
||||
// Rate5 returns the five-minute moving average rate of events per second at
|
||||
// the time the snapshot was taken.
|
||||
func (m *MeterSnapshot) Rate5() float64 { return m.rate5 }
|
||||
|
||||
// Rate15 returns the fifteen-minute moving average rate of events per second
|
||||
// at the time the snapshot was taken.
|
||||
func (m *MeterSnapshot) Rate15() float64 { return m.rate15 }
|
||||
|
||||
// RateMean returns the meter's mean rate of events per second at the time the
|
||||
// snapshot was taken.
|
||||
func (m *MeterSnapshot) RateMean() float64 { return m.rateMean }
|
||||
|
||||
// Snapshot returns the snapshot.
|
||||
func (m *MeterSnapshot) Snapshot() Meter { return m }
|
||||
|
||||
// NilMeter is a no-op Meter.
|
||||
type NilMeter struct{}
|
||||
|
||||
// Count is a no-op.
|
||||
func (NilMeter) Count() int64 { return 0 }
|
||||
|
||||
// Mark is a no-op.
|
||||
func (NilMeter) Mark(n int64) {}
|
||||
|
||||
// Rate1 is a no-op.
|
||||
func (NilMeter) Rate1() float64 { return 0.0 }
|
||||
|
||||
// Rate5 is a no-op.
|
||||
func (NilMeter) Rate5() float64 { return 0.0 }
|
||||
|
||||
// Rate15is a no-op.
|
||||
func (NilMeter) Rate15() float64 { return 0.0 }
|
||||
|
||||
// RateMean is a no-op.
|
||||
func (NilMeter) RateMean() float64 { return 0.0 }
|
||||
|
||||
// Snapshot is a no-op.
|
||||
func (NilMeter) Snapshot() Meter { return NilMeter{} }
|
||||
|
||||
// StandardMeter is the standard implementation of a Meter.
|
||||
type StandardMeter struct {
|
||||
lock sync.RWMutex
|
||||
snapshot *MeterSnapshot
|
||||
a1, a5, a15 EWMA
|
||||
startTime time.Time
|
||||
}
|
||||
|
||||
func newStandardMeter() *StandardMeter {
|
||||
return &StandardMeter{
|
||||
snapshot: &MeterSnapshot{},
|
||||
a1: NewEWMA1(),
|
||||
a5: NewEWMA5(),
|
||||
a15: NewEWMA15(),
|
||||
startTime: time.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
// Count returns the number of events recorded.
|
||||
func (m *StandardMeter) Count() int64 {
|
||||
m.lock.RLock()
|
||||
count := m.snapshot.count
|
||||
m.lock.RUnlock()
|
||||
return count
|
||||
}
|
||||
|
||||
// Mark records the occurance of n events.
|
||||
func (m *StandardMeter) Mark(n int64) {
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
m.snapshot.count += n
|
||||
m.a1.Update(n)
|
||||
m.a5.Update(n)
|
||||
m.a15.Update(n)
|
||||
m.updateSnapshot()
|
||||
}
|
||||
|
||||
// Rate1 returns the one-minute moving average rate of events per second.
|
||||
func (m *StandardMeter) Rate1() float64 {
|
||||
m.lock.RLock()
|
||||
rate1 := m.snapshot.rate1
|
||||
m.lock.RUnlock()
|
||||
return rate1
|
||||
}
|
||||
|
||||
// Rate5 returns the five-minute moving average rate of events per second.
|
||||
func (m *StandardMeter) Rate5() float64 {
|
||||
m.lock.RLock()
|
||||
rate5 := m.snapshot.rate5
|
||||
m.lock.RUnlock()
|
||||
return rate5
|
||||
}
|
||||
|
||||
// Rate15 returns the fifteen-minute moving average rate of events per second.
|
||||
func (m *StandardMeter) Rate15() float64 {
|
||||
m.lock.RLock()
|
||||
rate15 := m.snapshot.rate15
|
||||
m.lock.RUnlock()
|
||||
return rate15
|
||||
}
|
||||
|
||||
// RateMean returns the meter's mean rate of events per second.
|
||||
func (m *StandardMeter) RateMean() float64 {
|
||||
m.lock.RLock()
|
||||
rateMean := m.snapshot.rateMean
|
||||
m.lock.RUnlock()
|
||||
return rateMean
|
||||
}
|
||||
|
||||
// Snapshot returns a read-only copy of the meter.
|
||||
func (m *StandardMeter) Snapshot() Meter {
|
||||
m.lock.RLock()
|
||||
snapshot := *m.snapshot
|
||||
m.lock.RUnlock()
|
||||
return &snapshot
|
||||
}
|
||||
|
||||
func (m *StandardMeter) updateSnapshot() {
|
||||
// should run with write lock held on m.lock
|
||||
snapshot := m.snapshot
|
||||
snapshot.rate1 = m.a1.Rate()
|
||||
snapshot.rate5 = m.a5.Rate()
|
||||
snapshot.rate15 = m.a15.Rate()
|
||||
snapshot.rateMean = float64(snapshot.count) / time.Since(m.startTime).Seconds()
|
||||
}
|
||||
|
||||
func (m *StandardMeter) tick() {
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
m.a1.Tick()
|
||||
m.a5.Tick()
|
||||
m.a15.Tick()
|
||||
m.updateSnapshot()
|
||||
}
|
||||
|
||||
type meterArbiter struct {
|
||||
sync.RWMutex
|
||||
started bool
|
||||
meters []*StandardMeter
|
||||
ticker *time.Ticker
|
||||
}
|
||||
|
||||
var arbiter = meterArbiter{ticker: time.NewTicker(5e9)}
|
||||
|
||||
// Ticks meters on the scheduled interval
|
||||
func (ma *meterArbiter) tick() {
|
||||
for {
|
||||
select {
|
||||
case <-ma.ticker.C:
|
||||
ma.tickMeters()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ma *meterArbiter) tickMeters() {
|
||||
ma.RLock()
|
||||
defer ma.RUnlock()
|
||||
for _, meter := range ma.meters {
|
||||
meter.tick()
|
||||
}
|
||||
}
|
||||
13
Godeps/_workspace/src/github.com/rcrowley/go-metrics/metrics.go
generated
vendored
Normal file
13
Godeps/_workspace/src/github.com/rcrowley/go-metrics/metrics.go
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
// Go port of Coda Hale's Metrics library
|
||||
//
|
||||
// <https://github.com/rcrowley/go-metrics>
|
||||
//
|
||||
// Coda Hale's original work: <https://github.com/codahale/metrics>
|
||||
package metrics
|
||||
|
||||
// UseNilMetrics is checked by the constructor functions for all of the
|
||||
// standard metrics. If it is true, the metric returned is a stub.
|
||||
//
|
||||
// This global kill-switch helps quantify the observer effect and makes
|
||||
// for less cluttered pprof profiles.
|
||||
var UseNilMetrics bool = false
|
||||
119
Godeps/_workspace/src/github.com/rcrowley/go-metrics/opentsdb.go
generated
vendored
Normal file
119
Godeps/_workspace/src/github.com/rcrowley/go-metrics/opentsdb.go
generated
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var shortHostName string = ""
|
||||
|
||||
// OpenTSDBConfig provides a container with configuration parameters for
|
||||
// the OpenTSDB exporter
|
||||
type OpenTSDBConfig struct {
|
||||
Addr *net.TCPAddr // Network address to connect to
|
||||
Registry Registry // Registry to be exported
|
||||
FlushInterval time.Duration // Flush interval
|
||||
DurationUnit time.Duration // Time conversion unit for durations
|
||||
Prefix string // Prefix to be prepended to metric names
|
||||
}
|
||||
|
||||
// OpenTSDB is a blocking exporter function which reports metrics in r
|
||||
// to a TSDB server located at addr, flushing them every d duration
|
||||
// and prepending metric names with prefix.
|
||||
func OpenTSDB(r Registry, d time.Duration, prefix string, addr *net.TCPAddr) {
|
||||
OpenTSDBWithConfig(OpenTSDBConfig{
|
||||
Addr: addr,
|
||||
Registry: r,
|
||||
FlushInterval: d,
|
||||
DurationUnit: time.Nanosecond,
|
||||
Prefix: prefix,
|
||||
})
|
||||
}
|
||||
|
||||
// OpenTSDBWithConfig is a blocking exporter function just like OpenTSDB,
|
||||
// but it takes a OpenTSDBConfig instead.
|
||||
func OpenTSDBWithConfig(c OpenTSDBConfig) {
|
||||
for _ = range time.Tick(c.FlushInterval) {
|
||||
if err := openTSDB(&c); nil != err {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getShortHostname() string {
|
||||
if shortHostName == "" {
|
||||
host, _ := os.Hostname()
|
||||
if index := strings.Index(host, "."); index > 0 {
|
||||
shortHostName = host[:index]
|
||||
} else {
|
||||
shortHostName = host
|
||||
}
|
||||
}
|
||||
return shortHostName
|
||||
}
|
||||
|
||||
func openTSDB(c *OpenTSDBConfig) error {
|
||||
shortHostname := getShortHostname()
|
||||
now := time.Now().Unix()
|
||||
du := float64(c.DurationUnit)
|
||||
conn, err := net.DialTCP("tcp", nil, c.Addr)
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
defer conn.Close()
|
||||
w := bufio.NewWriter(conn)
|
||||
c.Registry.Each(func(name string, i interface{}) {
|
||||
switch metric := i.(type) {
|
||||
case Counter:
|
||||
fmt.Fprintf(w, "put %s.%s.count %d %d host=%s\n", c.Prefix, name, now, metric.Count(), shortHostname)
|
||||
case Gauge:
|
||||
fmt.Fprintf(w, "put %s.%s.value %d %d host=%s\n", c.Prefix, name, now, metric.Value(), shortHostname)
|
||||
case GaugeFloat64:
|
||||
fmt.Fprintf(w, "put %s.%s.value %d %f host=%s\n", c.Prefix, name, now, metric.Value(), shortHostname)
|
||||
case Histogram:
|
||||
h := metric.Snapshot()
|
||||
ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
|
||||
fmt.Fprintf(w, "put %s.%s.count %d %d host=%s\n", c.Prefix, name, now, h.Count(), shortHostname)
|
||||
fmt.Fprintf(w, "put %s.%s.min %d %d host=%s\n", c.Prefix, name, now, h.Min(), shortHostname)
|
||||
fmt.Fprintf(w, "put %s.%s.max %d %d host=%s\n", c.Prefix, name, now, h.Max(), shortHostname)
|
||||
fmt.Fprintf(w, "put %s.%s.mean %d %.2f host=%s\n", c.Prefix, name, now, h.Mean(), shortHostname)
|
||||
fmt.Fprintf(w, "put %s.%s.std-dev %d %.2f host=%s\n", c.Prefix, name, now, h.StdDev(), shortHostname)
|
||||
fmt.Fprintf(w, "put %s.%s.50-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[0], shortHostname)
|
||||
fmt.Fprintf(w, "put %s.%s.75-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[1], shortHostname)
|
||||
fmt.Fprintf(w, "put %s.%s.95-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[2], shortHostname)
|
||||
fmt.Fprintf(w, "put %s.%s.99-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[3], shortHostname)
|
||||
fmt.Fprintf(w, "put %s.%s.999-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[4], shortHostname)
|
||||
case Meter:
|
||||
m := metric.Snapshot()
|
||||
fmt.Fprintf(w, "put %s.%s.count %d %d host=%s\n", c.Prefix, name, now, m.Count(), shortHostname)
|
||||
fmt.Fprintf(w, "put %s.%s.one-minute %d %.2f host=%s\n", c.Prefix, name, now, m.Rate1(), shortHostname)
|
||||
fmt.Fprintf(w, "put %s.%s.five-minute %d %.2f host=%s\n", c.Prefix, name, now, m.Rate5(), shortHostname)
|
||||
fmt.Fprintf(w, "put %s.%s.fifteen-minute %d %.2f host=%s\n", c.Prefix, name, now, m.Rate15(), shortHostname)
|
||||
fmt.Fprintf(w, "put %s.%s.mean %d %.2f host=%s\n", c.Prefix, name, now, m.RateMean(), shortHostname)
|
||||
case Timer:
|
||||
t := metric.Snapshot()
|
||||
ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
|
||||
fmt.Fprintf(w, "put %s.%s.count %d %d host=%s\n", c.Prefix, name, now, t.Count(), shortHostname)
|
||||
fmt.Fprintf(w, "put %s.%s.min %d %d host=%s\n", c.Prefix, name, now, t.Min()/int64(du), shortHostname)
|
||||
fmt.Fprintf(w, "put %s.%s.max %d %d host=%s\n", c.Prefix, name, now, t.Max()/int64(du), shortHostname)
|
||||
fmt.Fprintf(w, "put %s.%s.mean %d %.2f host=%s\n", c.Prefix, name, now, t.Mean()/du, shortHostname)
|
||||
fmt.Fprintf(w, "put %s.%s.std-dev %d %.2f host=%s\n", c.Prefix, name, now, t.StdDev()/du, shortHostname)
|
||||
fmt.Fprintf(w, "put %s.%s.50-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[0]/du, shortHostname)
|
||||
fmt.Fprintf(w, "put %s.%s.75-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[1]/du, shortHostname)
|
||||
fmt.Fprintf(w, "put %s.%s.95-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[2]/du, shortHostname)
|
||||
fmt.Fprintf(w, "put %s.%s.99-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[3]/du, shortHostname)
|
||||
fmt.Fprintf(w, "put %s.%s.999-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[4]/du, shortHostname)
|
||||
fmt.Fprintf(w, "put %s.%s.one-minute %d %.2f host=%s\n", c.Prefix, name, now, t.Rate1(), shortHostname)
|
||||
fmt.Fprintf(w, "put %s.%s.five-minute %d %.2f host=%s\n", c.Prefix, name, now, t.Rate5(), shortHostname)
|
||||
fmt.Fprintf(w, "put %s.%s.fifteen-minute %d %.2f host=%s\n", c.Prefix, name, now, t.Rate15(), shortHostname)
|
||||
fmt.Fprintf(w, "put %s.%s.mean-rate %d %.2f host=%s\n", c.Prefix, name, now, t.RateMean(), shortHostname)
|
||||
}
|
||||
w.Flush()
|
||||
})
|
||||
return nil
|
||||
}
|
||||
240
Godeps/_workspace/src/github.com/rcrowley/go-metrics/registry.go
generated
vendored
Normal file
240
Godeps/_workspace/src/github.com/rcrowley/go-metrics/registry.go
generated
vendored
Normal file
@@ -0,0 +1,240 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// DuplicateMetric is the error returned by Registry.Register when a metric
|
||||
// already exists. If you mean to Register that metric you must first
|
||||
// Unregister the existing metric.
|
||||
type DuplicateMetric string
|
||||
|
||||
func (err DuplicateMetric) Error() string {
|
||||
return fmt.Sprintf("duplicate metric: %s", string(err))
|
||||
}
|
||||
|
||||
// A Registry holds references to a set of metrics by name and can iterate
|
||||
// over them, calling callback functions provided by the user.
|
||||
//
|
||||
// This is an interface so as to encourage other structs to implement
|
||||
// the Registry API as appropriate.
|
||||
type Registry interface {
|
||||
|
||||
// Call the given function for each registered metric.
|
||||
Each(func(string, interface{}))
|
||||
|
||||
// Get the metric by the given name or nil if none is registered.
|
||||
Get(string) interface{}
|
||||
|
||||
// Gets an existing metric or registers the given one.
|
||||
// The interface can be the metric to register if not found in registry,
|
||||
// or a function returning the metric for lazy instantiation.
|
||||
GetOrRegister(string, interface{}) interface{}
|
||||
|
||||
// Register the given metric under the given name.
|
||||
Register(string, interface{}) error
|
||||
|
||||
// Run all registered healthchecks.
|
||||
RunHealthchecks()
|
||||
|
||||
// Unregister the metric with the given name.
|
||||
Unregister(string)
|
||||
|
||||
// Unregister all metrics. (Mostly for testing.)
|
||||
UnregisterAll()
|
||||
}
|
||||
|
||||
// The standard implementation of a Registry is a mutex-protected map
|
||||
// of names to metrics.
|
||||
type StandardRegistry struct {
|
||||
metrics map[string]interface{}
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
// Create a new registry.
|
||||
func NewRegistry() Registry {
|
||||
return &StandardRegistry{metrics: make(map[string]interface{})}
|
||||
}
|
||||
|
||||
// Call the given function for each registered metric.
|
||||
func (r *StandardRegistry) Each(f func(string, interface{})) {
|
||||
for name, i := range r.registered() {
|
||||
f(name, i)
|
||||
}
|
||||
}
|
||||
|
||||
// Get the metric by the given name or nil if none is registered.
|
||||
func (r *StandardRegistry) Get(name string) interface{} {
|
||||
r.mutex.Lock()
|
||||
defer r.mutex.Unlock()
|
||||
return r.metrics[name]
|
||||
}
|
||||
|
||||
// Gets an existing metric or creates and registers a new one. Threadsafe
|
||||
// alternative to calling Get and Register on failure.
|
||||
// The interface can be the metric to register if not found in registry,
|
||||
// or a function returning the metric for lazy instantiation.
|
||||
func (r *StandardRegistry) GetOrRegister(name string, i interface{}) interface{} {
|
||||
r.mutex.Lock()
|
||||
defer r.mutex.Unlock()
|
||||
if metric, ok := r.metrics[name]; ok {
|
||||
return metric
|
||||
}
|
||||
if v := reflect.ValueOf(i); v.Kind() == reflect.Func {
|
||||
i = v.Call(nil)[0].Interface()
|
||||
}
|
||||
r.register(name, i)
|
||||
return i
|
||||
}
|
||||
|
||||
// Register the given metric under the given name. Returns a DuplicateMetric
|
||||
// if a metric by the given name is already registered.
|
||||
func (r *StandardRegistry) Register(name string, i interface{}) error {
|
||||
r.mutex.Lock()
|
||||
defer r.mutex.Unlock()
|
||||
return r.register(name, i)
|
||||
}
|
||||
|
||||
// Run all registered healthchecks.
|
||||
func (r *StandardRegistry) RunHealthchecks() {
|
||||
r.mutex.Lock()
|
||||
defer r.mutex.Unlock()
|
||||
for _, i := range r.metrics {
|
||||
if h, ok := i.(Healthcheck); ok {
|
||||
h.Check()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Unregister the metric with the given name.
|
||||
func (r *StandardRegistry) Unregister(name string) {
|
||||
r.mutex.Lock()
|
||||
defer r.mutex.Unlock()
|
||||
delete(r.metrics, name)
|
||||
}
|
||||
|
||||
// Unregister all metrics. (Mostly for testing.)
|
||||
func (r *StandardRegistry) UnregisterAll() {
|
||||
r.mutex.Lock()
|
||||
defer r.mutex.Unlock()
|
||||
for name, _ := range r.metrics {
|
||||
delete(r.metrics, name)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *StandardRegistry) register(name string, i interface{}) error {
|
||||
if _, ok := r.metrics[name]; ok {
|
||||
return DuplicateMetric(name)
|
||||
}
|
||||
switch i.(type) {
|
||||
case Counter, Gauge, GaugeFloat64, Healthcheck, Histogram, Meter, Timer:
|
||||
r.metrics[name] = i
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *StandardRegistry) registered() map[string]interface{} {
|
||||
r.mutex.Lock()
|
||||
defer r.mutex.Unlock()
|
||||
metrics := make(map[string]interface{}, len(r.metrics))
|
||||
for name, i := range r.metrics {
|
||||
metrics[name] = i
|
||||
}
|
||||
return metrics
|
||||
}
|
||||
|
||||
type PrefixedRegistry struct {
|
||||
underlying Registry
|
||||
prefix string
|
||||
}
|
||||
|
||||
func NewPrefixedRegistry(prefix string) Registry {
|
||||
return &PrefixedRegistry{
|
||||
underlying: NewRegistry(),
|
||||
prefix: prefix,
|
||||
}
|
||||
}
|
||||
|
||||
// Call the given function for each registered metric.
|
||||
func (r *PrefixedRegistry) Each(fn func(string, interface{})) {
|
||||
r.underlying.Each(fn)
|
||||
}
|
||||
|
||||
// Get the metric by the given name or nil if none is registered.
|
||||
func (r *PrefixedRegistry) Get(name string) interface{} {
|
||||
return r.underlying.Get(name)
|
||||
}
|
||||
|
||||
// Gets an existing metric or registers the given one.
|
||||
// The interface can be the metric to register if not found in registry,
|
||||
// or a function returning the metric for lazy instantiation.
|
||||
func (r *PrefixedRegistry) GetOrRegister(name string, metric interface{}) interface{} {
|
||||
realName := r.prefix + name
|
||||
return r.underlying.GetOrRegister(realName, metric)
|
||||
}
|
||||
|
||||
// Register the given metric under the given name. The name will be prefixed.
|
||||
func (r *PrefixedRegistry) Register(name string, metric interface{}) error {
|
||||
realName := r.prefix + name
|
||||
return r.underlying.Register(realName, metric)
|
||||
}
|
||||
|
||||
// Run all registered healthchecks.
|
||||
func (r *PrefixedRegistry) RunHealthchecks() {
|
||||
r.underlying.RunHealthchecks()
|
||||
}
|
||||
|
||||
// Unregister the metric with the given name. The name will be prefixed.
|
||||
func (r *PrefixedRegistry) Unregister(name string) {
|
||||
realName := r.prefix + name
|
||||
r.underlying.Unregister(realName)
|
||||
}
|
||||
|
||||
// Unregister all metrics. (Mostly for testing.)
|
||||
func (r *PrefixedRegistry) UnregisterAll() {
|
||||
r.underlying.UnregisterAll()
|
||||
}
|
||||
|
||||
var DefaultRegistry Registry = NewRegistry()
|
||||
|
||||
// Call the given function for each registered metric.
|
||||
func Each(f func(string, interface{})) {
|
||||
DefaultRegistry.Each(f)
|
||||
}
|
||||
|
||||
// Get the metric by the given name or nil if none is registered.
|
||||
func Get(name string) interface{} {
|
||||
return DefaultRegistry.Get(name)
|
||||
}
|
||||
|
||||
// Gets an existing metric or creates and registers a new one. Threadsafe
|
||||
// alternative to calling Get and Register on failure.
|
||||
func GetOrRegister(name string, i interface{}) interface{} {
|
||||
return DefaultRegistry.GetOrRegister(name, i)
|
||||
}
|
||||
|
||||
// Register the given metric under the given name. Returns a DuplicateMetric
|
||||
// if a metric by the given name is already registered.
|
||||
func Register(name string, i interface{}) error {
|
||||
return DefaultRegistry.Register(name, i)
|
||||
}
|
||||
|
||||
// Register the given metric under the given name. Panics if a metric by the
|
||||
// given name is already registered.
|
||||
func MustRegister(name string, i interface{}) {
|
||||
if err := Register(name, i); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Run all registered healthchecks.
|
||||
func RunHealthchecks() {
|
||||
DefaultRegistry.RunHealthchecks()
|
||||
}
|
||||
|
||||
// Unregister the metric with the given name.
|
||||
func Unregister(name string) {
|
||||
DefaultRegistry.Unregister(name)
|
||||
}
|
||||
200
Godeps/_workspace/src/github.com/rcrowley/go-metrics/runtime.go
generated
vendored
Normal file
200
Godeps/_workspace/src/github.com/rcrowley/go-metrics/runtime.go
generated
vendored
Normal file
@@ -0,0 +1,200 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
memStats runtime.MemStats
|
||||
runtimeMetrics struct {
|
||||
MemStats struct {
|
||||
Alloc Gauge
|
||||
BuckHashSys Gauge
|
||||
DebugGC Gauge
|
||||
EnableGC Gauge
|
||||
Frees Gauge
|
||||
HeapAlloc Gauge
|
||||
HeapIdle Gauge
|
||||
HeapInuse Gauge
|
||||
HeapObjects Gauge
|
||||
HeapReleased Gauge
|
||||
HeapSys Gauge
|
||||
LastGC Gauge
|
||||
Lookups Gauge
|
||||
Mallocs Gauge
|
||||
MCacheInuse Gauge
|
||||
MCacheSys Gauge
|
||||
MSpanInuse Gauge
|
||||
MSpanSys Gauge
|
||||
NextGC Gauge
|
||||
NumGC Gauge
|
||||
PauseNs Histogram
|
||||
PauseTotalNs Gauge
|
||||
StackInuse Gauge
|
||||
StackSys Gauge
|
||||
Sys Gauge
|
||||
TotalAlloc Gauge
|
||||
}
|
||||
NumCgoCall Gauge
|
||||
NumGoroutine Gauge
|
||||
ReadMemStats Timer
|
||||
}
|
||||
frees uint64
|
||||
lookups uint64
|
||||
mallocs uint64
|
||||
numGC uint32
|
||||
numCgoCalls int64
|
||||
)
|
||||
|
||||
// Capture new values for the Go runtime statistics exported in
|
||||
// runtime.MemStats. This is designed to be called as a goroutine.
|
||||
func CaptureRuntimeMemStats(r Registry, d time.Duration) {
|
||||
for _ = range time.Tick(d) {
|
||||
CaptureRuntimeMemStatsOnce(r)
|
||||
}
|
||||
}
|
||||
|
||||
// Capture new values for the Go runtime statistics exported in
|
||||
// runtime.MemStats. This is designed to be called in a background
|
||||
// goroutine. Giving a registry which has not been given to
|
||||
// RegisterRuntimeMemStats will panic.
|
||||
//
|
||||
// Be very careful with this because runtime.ReadMemStats calls the C
|
||||
// functions runtime·semacquire(&runtime·worldsema) and runtime·stoptheworld()
|
||||
// and that last one does what it says on the tin.
|
||||
func CaptureRuntimeMemStatsOnce(r Registry) {
|
||||
t := time.Now()
|
||||
runtime.ReadMemStats(&memStats) // This takes 50-200us.
|
||||
runtimeMetrics.ReadMemStats.UpdateSince(t)
|
||||
|
||||
runtimeMetrics.MemStats.Alloc.Update(int64(memStats.Alloc))
|
||||
runtimeMetrics.MemStats.BuckHashSys.Update(int64(memStats.BuckHashSys))
|
||||
if memStats.DebugGC {
|
||||
runtimeMetrics.MemStats.DebugGC.Update(1)
|
||||
} else {
|
||||
runtimeMetrics.MemStats.DebugGC.Update(0)
|
||||
}
|
||||
if memStats.EnableGC {
|
||||
runtimeMetrics.MemStats.EnableGC.Update(1)
|
||||
} else {
|
||||
runtimeMetrics.MemStats.EnableGC.Update(0)
|
||||
}
|
||||
|
||||
runtimeMetrics.MemStats.Frees.Update(int64(memStats.Frees - frees))
|
||||
runtimeMetrics.MemStats.HeapAlloc.Update(int64(memStats.HeapAlloc))
|
||||
runtimeMetrics.MemStats.HeapIdle.Update(int64(memStats.HeapIdle))
|
||||
runtimeMetrics.MemStats.HeapInuse.Update(int64(memStats.HeapInuse))
|
||||
runtimeMetrics.MemStats.HeapObjects.Update(int64(memStats.HeapObjects))
|
||||
runtimeMetrics.MemStats.HeapReleased.Update(int64(memStats.HeapReleased))
|
||||
runtimeMetrics.MemStats.HeapSys.Update(int64(memStats.HeapSys))
|
||||
runtimeMetrics.MemStats.LastGC.Update(int64(memStats.LastGC))
|
||||
runtimeMetrics.MemStats.Lookups.Update(int64(memStats.Lookups - lookups))
|
||||
runtimeMetrics.MemStats.Mallocs.Update(int64(memStats.Mallocs - mallocs))
|
||||
runtimeMetrics.MemStats.MCacheInuse.Update(int64(memStats.MCacheInuse))
|
||||
runtimeMetrics.MemStats.MCacheSys.Update(int64(memStats.MCacheSys))
|
||||
runtimeMetrics.MemStats.MSpanInuse.Update(int64(memStats.MSpanInuse))
|
||||
runtimeMetrics.MemStats.MSpanSys.Update(int64(memStats.MSpanSys))
|
||||
runtimeMetrics.MemStats.NextGC.Update(int64(memStats.NextGC))
|
||||
runtimeMetrics.MemStats.NumGC.Update(int64(memStats.NumGC - numGC))
|
||||
|
||||
// <https://code.google.com/p/go/source/browse/src/pkg/runtime/mgc0.c>
|
||||
i := numGC % uint32(len(memStats.PauseNs))
|
||||
ii := memStats.NumGC % uint32(len(memStats.PauseNs))
|
||||
if memStats.NumGC-numGC >= uint32(len(memStats.PauseNs)) {
|
||||
for i = 0; i < uint32(len(memStats.PauseNs)); i++ {
|
||||
runtimeMetrics.MemStats.PauseNs.Update(int64(memStats.PauseNs[i]))
|
||||
}
|
||||
} else {
|
||||
if i > ii {
|
||||
for ; i < uint32(len(memStats.PauseNs)); i++ {
|
||||
runtimeMetrics.MemStats.PauseNs.Update(int64(memStats.PauseNs[i]))
|
||||
}
|
||||
i = 0
|
||||
}
|
||||
for ; i < ii; i++ {
|
||||
runtimeMetrics.MemStats.PauseNs.Update(int64(memStats.PauseNs[i]))
|
||||
}
|
||||
}
|
||||
frees = memStats.Frees
|
||||
lookups = memStats.Lookups
|
||||
mallocs = memStats.Mallocs
|
||||
numGC = memStats.NumGC
|
||||
|
||||
runtimeMetrics.MemStats.PauseTotalNs.Update(int64(memStats.PauseTotalNs))
|
||||
runtimeMetrics.MemStats.StackInuse.Update(int64(memStats.StackInuse))
|
||||
runtimeMetrics.MemStats.StackSys.Update(int64(memStats.StackSys))
|
||||
runtimeMetrics.MemStats.Sys.Update(int64(memStats.Sys))
|
||||
runtimeMetrics.MemStats.TotalAlloc.Update(int64(memStats.TotalAlloc))
|
||||
|
||||
currentNumCgoCalls := numCgoCall()
|
||||
runtimeMetrics.NumCgoCall.Update(currentNumCgoCalls - numCgoCalls)
|
||||
numCgoCalls = currentNumCgoCalls
|
||||
|
||||
runtimeMetrics.NumGoroutine.Update(int64(runtime.NumGoroutine()))
|
||||
}
|
||||
|
||||
// Register runtimeMetrics for the Go runtime statistics exported in runtime and
|
||||
// specifically runtime.MemStats. The runtimeMetrics are named by their
|
||||
// fully-qualified Go symbols, i.e. runtime.MemStats.Alloc.
|
||||
func RegisterRuntimeMemStats(r Registry) {
|
||||
runtimeMetrics.MemStats.Alloc = NewGauge()
|
||||
runtimeMetrics.MemStats.BuckHashSys = NewGauge()
|
||||
runtimeMetrics.MemStats.DebugGC = NewGauge()
|
||||
runtimeMetrics.MemStats.EnableGC = NewGauge()
|
||||
runtimeMetrics.MemStats.Frees = NewGauge()
|
||||
runtimeMetrics.MemStats.HeapAlloc = NewGauge()
|
||||
runtimeMetrics.MemStats.HeapIdle = NewGauge()
|
||||
runtimeMetrics.MemStats.HeapInuse = NewGauge()
|
||||
runtimeMetrics.MemStats.HeapObjects = NewGauge()
|
||||
runtimeMetrics.MemStats.HeapReleased = NewGauge()
|
||||
runtimeMetrics.MemStats.HeapSys = NewGauge()
|
||||
runtimeMetrics.MemStats.LastGC = NewGauge()
|
||||
runtimeMetrics.MemStats.Lookups = NewGauge()
|
||||
runtimeMetrics.MemStats.Mallocs = NewGauge()
|
||||
runtimeMetrics.MemStats.MCacheInuse = NewGauge()
|
||||
runtimeMetrics.MemStats.MCacheSys = NewGauge()
|
||||
runtimeMetrics.MemStats.MSpanInuse = NewGauge()
|
||||
runtimeMetrics.MemStats.MSpanSys = NewGauge()
|
||||
runtimeMetrics.MemStats.NextGC = NewGauge()
|
||||
runtimeMetrics.MemStats.NumGC = NewGauge()
|
||||
runtimeMetrics.MemStats.PauseNs = NewHistogram(NewExpDecaySample(1028, 0.015))
|
||||
runtimeMetrics.MemStats.PauseTotalNs = NewGauge()
|
||||
runtimeMetrics.MemStats.StackInuse = NewGauge()
|
||||
runtimeMetrics.MemStats.StackSys = NewGauge()
|
||||
runtimeMetrics.MemStats.Sys = NewGauge()
|
||||
runtimeMetrics.MemStats.TotalAlloc = NewGauge()
|
||||
runtimeMetrics.NumCgoCall = NewGauge()
|
||||
runtimeMetrics.NumGoroutine = NewGauge()
|
||||
runtimeMetrics.ReadMemStats = NewTimer()
|
||||
|
||||
r.Register("runtime.MemStats.Alloc", runtimeMetrics.MemStats.Alloc)
|
||||
r.Register("runtime.MemStats.BuckHashSys", runtimeMetrics.MemStats.BuckHashSys)
|
||||
r.Register("runtime.MemStats.DebugGC", runtimeMetrics.MemStats.DebugGC)
|
||||
r.Register("runtime.MemStats.EnableGC", runtimeMetrics.MemStats.EnableGC)
|
||||
r.Register("runtime.MemStats.Frees", runtimeMetrics.MemStats.Frees)
|
||||
r.Register("runtime.MemStats.HeapAlloc", runtimeMetrics.MemStats.HeapAlloc)
|
||||
r.Register("runtime.MemStats.HeapIdle", runtimeMetrics.MemStats.HeapIdle)
|
||||
r.Register("runtime.MemStats.HeapInuse", runtimeMetrics.MemStats.HeapInuse)
|
||||
r.Register("runtime.MemStats.HeapObjects", runtimeMetrics.MemStats.HeapObjects)
|
||||
r.Register("runtime.MemStats.HeapReleased", runtimeMetrics.MemStats.HeapReleased)
|
||||
r.Register("runtime.MemStats.HeapSys", runtimeMetrics.MemStats.HeapSys)
|
||||
r.Register("runtime.MemStats.LastGC", runtimeMetrics.MemStats.LastGC)
|
||||
r.Register("runtime.MemStats.Lookups", runtimeMetrics.MemStats.Lookups)
|
||||
r.Register("runtime.MemStats.Mallocs", runtimeMetrics.MemStats.Mallocs)
|
||||
r.Register("runtime.MemStats.MCacheInuse", runtimeMetrics.MemStats.MCacheInuse)
|
||||
r.Register("runtime.MemStats.MCacheSys", runtimeMetrics.MemStats.MCacheSys)
|
||||
r.Register("runtime.MemStats.MSpanInuse", runtimeMetrics.MemStats.MSpanInuse)
|
||||
r.Register("runtime.MemStats.MSpanSys", runtimeMetrics.MemStats.MSpanSys)
|
||||
r.Register("runtime.MemStats.NextGC", runtimeMetrics.MemStats.NextGC)
|
||||
r.Register("runtime.MemStats.NumGC", runtimeMetrics.MemStats.NumGC)
|
||||
r.Register("runtime.MemStats.PauseNs", runtimeMetrics.MemStats.PauseNs)
|
||||
r.Register("runtime.MemStats.PauseTotalNs", runtimeMetrics.MemStats.PauseTotalNs)
|
||||
r.Register("runtime.MemStats.StackInuse", runtimeMetrics.MemStats.StackInuse)
|
||||
r.Register("runtime.MemStats.StackSys", runtimeMetrics.MemStats.StackSys)
|
||||
r.Register("runtime.MemStats.Sys", runtimeMetrics.MemStats.Sys)
|
||||
r.Register("runtime.MemStats.TotalAlloc", runtimeMetrics.MemStats.TotalAlloc)
|
||||
r.Register("runtime.NumCgoCall", runtimeMetrics.NumCgoCall)
|
||||
r.Register("runtime.NumGoroutine", runtimeMetrics.NumGoroutine)
|
||||
r.Register("runtime.ReadMemStats", runtimeMetrics.ReadMemStats)
|
||||
}
|
||||
10
Godeps/_workspace/src/github.com/rcrowley/go-metrics/runtime_cgo.go
generated
vendored
Normal file
10
Godeps/_workspace/src/github.com/rcrowley/go-metrics/runtime_cgo.go
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
// +build cgo
|
||||
// +build !appengine
|
||||
|
||||
package metrics
|
||||
|
||||
import "runtime"
|
||||
|
||||
func numCgoCall() int64 {
|
||||
return runtime.NumCgoCall()
|
||||
}
|
||||
7
Godeps/_workspace/src/github.com/rcrowley/go-metrics/runtime_no_cgo.go
generated
vendored
Normal file
7
Godeps/_workspace/src/github.com/rcrowley/go-metrics/runtime_no_cgo.go
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
// +build !cgo appengine
|
||||
|
||||
package metrics
|
||||
|
||||
func numCgoCall() int64 {
|
||||
return 0
|
||||
}
|
||||
609
Godeps/_workspace/src/github.com/rcrowley/go-metrics/sample.go
generated
vendored
Normal file
609
Godeps/_workspace/src/github.com/rcrowley/go-metrics/sample.go
generated
vendored
Normal file
@@ -0,0 +1,609 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/rand"
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const rescaleThreshold = time.Hour
|
||||
|
||||
// Samples maintain a statistically-significant selection of values from
|
||||
// a stream.
|
||||
type Sample interface {
|
||||
Clear()
|
||||
Count() int64
|
||||
Max() int64
|
||||
Mean() float64
|
||||
Min() int64
|
||||
Percentile(float64) float64
|
||||
Percentiles([]float64) []float64
|
||||
Size() int
|
||||
Snapshot() Sample
|
||||
StdDev() float64
|
||||
Sum() int64
|
||||
Update(int64)
|
||||
Values() []int64
|
||||
Variance() float64
|
||||
}
|
||||
|
||||
// ExpDecaySample is an exponentially-decaying sample using a forward-decaying
|
||||
// priority reservoir. See Cormode et al's "Forward Decay: A Practical Time
|
||||
// Decay Model for Streaming Systems".
|
||||
//
|
||||
// <http://www.research.att.com/people/Cormode_Graham/library/publications/CormodeShkapenyukSrivastavaXu09.pdf>
|
||||
type ExpDecaySample struct {
|
||||
alpha float64
|
||||
count int64
|
||||
mutex sync.Mutex
|
||||
reservoirSize int
|
||||
t0, t1 time.Time
|
||||
values *expDecaySampleHeap
|
||||
}
|
||||
|
||||
// NewExpDecaySample constructs a new exponentially-decaying sample with the
|
||||
// given reservoir size and alpha.
|
||||
func NewExpDecaySample(reservoirSize int, alpha float64) Sample {
|
||||
if UseNilMetrics {
|
||||
return NilSample{}
|
||||
}
|
||||
s := &ExpDecaySample{
|
||||
alpha: alpha,
|
||||
reservoirSize: reservoirSize,
|
||||
t0: time.Now(),
|
||||
values: newExpDecaySampleHeap(reservoirSize),
|
||||
}
|
||||
s.t1 = s.t0.Add(rescaleThreshold)
|
||||
return s
|
||||
}
|
||||
|
||||
// Clear clears all samples.
|
||||
func (s *ExpDecaySample) Clear() {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
s.count = 0
|
||||
s.t0 = time.Now()
|
||||
s.t1 = s.t0.Add(rescaleThreshold)
|
||||
s.values.Clear()
|
||||
}
|
||||
|
||||
// Count returns the number of samples recorded, which may exceed the
|
||||
// reservoir size.
|
||||
func (s *ExpDecaySample) Count() int64 {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
return s.count
|
||||
}
|
||||
|
||||
// Max returns the maximum value in the sample, which may not be the maximum
|
||||
// value ever to be part of the sample.
|
||||
func (s *ExpDecaySample) Max() int64 {
|
||||
return SampleMax(s.Values())
|
||||
}
|
||||
|
||||
// Mean returns the mean of the values in the sample.
|
||||
func (s *ExpDecaySample) Mean() float64 {
|
||||
return SampleMean(s.Values())
|
||||
}
|
||||
|
||||
// Min returns the minimum value in the sample, which may not be the minimum
|
||||
// value ever to be part of the sample.
|
||||
func (s *ExpDecaySample) Min() int64 {
|
||||
return SampleMin(s.Values())
|
||||
}
|
||||
|
||||
// Percentile returns an arbitrary percentile of values in the sample.
|
||||
func (s *ExpDecaySample) Percentile(p float64) float64 {
|
||||
return SamplePercentile(s.Values(), p)
|
||||
}
|
||||
|
||||
// Percentiles returns a slice of arbitrary percentiles of values in the
|
||||
// sample.
|
||||
func (s *ExpDecaySample) Percentiles(ps []float64) []float64 {
|
||||
return SamplePercentiles(s.Values(), ps)
|
||||
}
|
||||
|
||||
// Size returns the size of the sample, which is at most the reservoir size.
|
||||
func (s *ExpDecaySample) Size() int {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
return s.values.Size()
|
||||
}
|
||||
|
||||
// Snapshot returns a read-only copy of the sample.
|
||||
func (s *ExpDecaySample) Snapshot() Sample {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
vals := s.values.Values()
|
||||
values := make([]int64, len(vals))
|
||||
for i, v := range vals {
|
||||
values[i] = v.v
|
||||
}
|
||||
return &SampleSnapshot{
|
||||
count: s.count,
|
||||
values: values,
|
||||
}
|
||||
}
|
||||
|
||||
// StdDev returns the standard deviation of the values in the sample.
|
||||
func (s *ExpDecaySample) StdDev() float64 {
|
||||
return SampleStdDev(s.Values())
|
||||
}
|
||||
|
||||
// Sum returns the sum of the values in the sample.
|
||||
func (s *ExpDecaySample) Sum() int64 {
|
||||
return SampleSum(s.Values())
|
||||
}
|
||||
|
||||
// Update samples a new value.
|
||||
func (s *ExpDecaySample) Update(v int64) {
|
||||
s.update(time.Now(), v)
|
||||
}
|
||||
|
||||
// Values returns a copy of the values in the sample.
|
||||
func (s *ExpDecaySample) Values() []int64 {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
vals := s.values.Values()
|
||||
values := make([]int64, len(vals))
|
||||
for i, v := range vals {
|
||||
values[i] = v.v
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
||||
// Variance returns the variance of the values in the sample.
|
||||
func (s *ExpDecaySample) Variance() float64 {
|
||||
return SampleVariance(s.Values())
|
||||
}
|
||||
|
||||
// update samples a new value at a particular timestamp. This is a method all
|
||||
// its own to facilitate testing.
|
||||
func (s *ExpDecaySample) update(t time.Time, v int64) {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
s.count++
|
||||
if s.values.Size() == s.reservoirSize {
|
||||
s.values.Pop()
|
||||
}
|
||||
s.values.Push(expDecaySample{
|
||||
k: math.Exp(t.Sub(s.t0).Seconds()*s.alpha) / rand.Float64(),
|
||||
v: v,
|
||||
})
|
||||
if t.After(s.t1) {
|
||||
values := s.values.Values()
|
||||
t0 := s.t0
|
||||
s.values.Clear()
|
||||
s.t0 = t
|
||||
s.t1 = s.t0.Add(rescaleThreshold)
|
||||
for _, v := range values {
|
||||
v.k = v.k * math.Exp(-s.alpha*s.t0.Sub(t0).Seconds())
|
||||
s.values.Push(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NilSample is a no-op Sample.
|
||||
type NilSample struct{}
|
||||
|
||||
// Clear is a no-op.
|
||||
func (NilSample) Clear() {}
|
||||
|
||||
// Count is a no-op.
|
||||
func (NilSample) Count() int64 { return 0 }
|
||||
|
||||
// Max is a no-op.
|
||||
func (NilSample) Max() int64 { return 0 }
|
||||
|
||||
// Mean is a no-op.
|
||||
func (NilSample) Mean() float64 { return 0.0 }
|
||||
|
||||
// Min is a no-op.
|
||||
func (NilSample) Min() int64 { return 0 }
|
||||
|
||||
// Percentile is a no-op.
|
||||
func (NilSample) Percentile(p float64) float64 { return 0.0 }
|
||||
|
||||
// Percentiles is a no-op.
|
||||
func (NilSample) Percentiles(ps []float64) []float64 {
|
||||
return make([]float64, len(ps))
|
||||
}
|
||||
|
||||
// Size is a no-op.
|
||||
func (NilSample) Size() int { return 0 }
|
||||
|
||||
// Sample is a no-op.
|
||||
func (NilSample) Snapshot() Sample { return NilSample{} }
|
||||
|
||||
// StdDev is a no-op.
|
||||
func (NilSample) StdDev() float64 { return 0.0 }
|
||||
|
||||
// Sum is a no-op.
|
||||
func (NilSample) Sum() int64 { return 0 }
|
||||
|
||||
// Update is a no-op.
|
||||
func (NilSample) Update(v int64) {}
|
||||
|
||||
// Values is a no-op.
|
||||
func (NilSample) Values() []int64 { return []int64{} }
|
||||
|
||||
// Variance is a no-op.
|
||||
func (NilSample) Variance() float64 { return 0.0 }
|
||||
|
||||
// SampleMax returns the maximum value of the slice of int64.
|
||||
func SampleMax(values []int64) int64 {
|
||||
if 0 == len(values) {
|
||||
return 0
|
||||
}
|
||||
var max int64 = math.MinInt64
|
||||
for _, v := range values {
|
||||
if max < v {
|
||||
max = v
|
||||
}
|
||||
}
|
||||
return max
|
||||
}
|
||||
|
||||
// SampleMean returns the mean value of the slice of int64.
|
||||
func SampleMean(values []int64) float64 {
|
||||
if 0 == len(values) {
|
||||
return 0.0
|
||||
}
|
||||
return float64(SampleSum(values)) / float64(len(values))
|
||||
}
|
||||
|
||||
// SampleMin returns the minimum value of the slice of int64.
|
||||
func SampleMin(values []int64) int64 {
|
||||
if 0 == len(values) {
|
||||
return 0
|
||||
}
|
||||
var min int64 = math.MaxInt64
|
||||
for _, v := range values {
|
||||
if min > v {
|
||||
min = v
|
||||
}
|
||||
}
|
||||
return min
|
||||
}
|
||||
|
||||
// SamplePercentiles returns an arbitrary percentile of the slice of int64.
|
||||
func SamplePercentile(values int64Slice, p float64) float64 {
|
||||
return SamplePercentiles(values, []float64{p})[0]
|
||||
}
|
||||
|
||||
// SamplePercentiles returns a slice of arbitrary percentiles of the slice of
|
||||
// int64.
|
||||
func SamplePercentiles(values int64Slice, ps []float64) []float64 {
|
||||
scores := make([]float64, len(ps))
|
||||
size := len(values)
|
||||
if size > 0 {
|
||||
sort.Sort(values)
|
||||
for i, p := range ps {
|
||||
pos := p * float64(size+1)
|
||||
if pos < 1.0 {
|
||||
scores[i] = float64(values[0])
|
||||
} else if pos >= float64(size) {
|
||||
scores[i] = float64(values[size-1])
|
||||
} else {
|
||||
lower := float64(values[int(pos)-1])
|
||||
upper := float64(values[int(pos)])
|
||||
scores[i] = lower + (pos-math.Floor(pos))*(upper-lower)
|
||||
}
|
||||
}
|
||||
}
|
||||
return scores
|
||||
}
|
||||
|
||||
// SampleSnapshot is a read-only copy of another Sample.
|
||||
type SampleSnapshot struct {
|
||||
count int64
|
||||
values []int64
|
||||
}
|
||||
|
||||
// Clear panics.
|
||||
func (*SampleSnapshot) Clear() {
|
||||
panic("Clear called on a SampleSnapshot")
|
||||
}
|
||||
|
||||
// Count returns the count of inputs at the time the snapshot was taken.
|
||||
func (s *SampleSnapshot) Count() int64 { return s.count }
|
||||
|
||||
// Max returns the maximal value at the time the snapshot was taken.
|
||||
func (s *SampleSnapshot) Max() int64 { return SampleMax(s.values) }
|
||||
|
||||
// Mean returns the mean value at the time the snapshot was taken.
|
||||
func (s *SampleSnapshot) Mean() float64 { return SampleMean(s.values) }
|
||||
|
||||
// Min returns the minimal value at the time the snapshot was taken.
|
||||
func (s *SampleSnapshot) Min() int64 { return SampleMin(s.values) }
|
||||
|
||||
// Percentile returns an arbitrary percentile of values at the time the
|
||||
// snapshot was taken.
|
||||
func (s *SampleSnapshot) Percentile(p float64) float64 {
|
||||
return SamplePercentile(s.values, p)
|
||||
}
|
||||
|
||||
// Percentiles returns a slice of arbitrary percentiles of values at the time
|
||||
// the snapshot was taken.
|
||||
func (s *SampleSnapshot) Percentiles(ps []float64) []float64 {
|
||||
return SamplePercentiles(s.values, ps)
|
||||
}
|
||||
|
||||
// Size returns the size of the sample at the time the snapshot was taken.
|
||||
func (s *SampleSnapshot) Size() int { return len(s.values) }
|
||||
|
||||
// Snapshot returns the snapshot.
|
||||
func (s *SampleSnapshot) Snapshot() Sample { return s }
|
||||
|
||||
// StdDev returns the standard deviation of values at the time the snapshot was
|
||||
// taken.
|
||||
func (s *SampleSnapshot) StdDev() float64 { return SampleStdDev(s.values) }
|
||||
|
||||
// Sum returns the sum of values at the time the snapshot was taken.
|
||||
func (s *SampleSnapshot) Sum() int64 { return SampleSum(s.values) }
|
||||
|
||||
// Update panics.
|
||||
func (*SampleSnapshot) Update(int64) {
|
||||
panic("Update called on a SampleSnapshot")
|
||||
}
|
||||
|
||||
// Values returns a copy of the values in the sample.
|
||||
func (s *SampleSnapshot) Values() []int64 {
|
||||
values := make([]int64, len(s.values))
|
||||
copy(values, s.values)
|
||||
return values
|
||||
}
|
||||
|
||||
// Variance returns the variance of values at the time the snapshot was taken.
|
||||
func (s *SampleSnapshot) Variance() float64 { return SampleVariance(s.values) }
|
||||
|
||||
// SampleStdDev returns the standard deviation of the slice of int64.
|
||||
func SampleStdDev(values []int64) float64 {
|
||||
return math.Sqrt(SampleVariance(values))
|
||||
}
|
||||
|
||||
// SampleSum returns the sum of the slice of int64.
|
||||
func SampleSum(values []int64) int64 {
|
||||
var sum int64
|
||||
for _, v := range values {
|
||||
sum += v
|
||||
}
|
||||
return sum
|
||||
}
|
||||
|
||||
// SampleVariance returns the variance of the slice of int64.
|
||||
func SampleVariance(values []int64) float64 {
|
||||
if 0 == len(values) {
|
||||
return 0.0
|
||||
}
|
||||
m := SampleMean(values)
|
||||
var sum float64
|
||||
for _, v := range values {
|
||||
d := float64(v) - m
|
||||
sum += d * d
|
||||
}
|
||||
return sum / float64(len(values))
|
||||
}
|
||||
|
||||
// A uniform sample using Vitter's Algorithm R.
|
||||
//
|
||||
// <http://www.cs.umd.edu/~samir/498/vitter.pdf>
|
||||
type UniformSample struct {
|
||||
count int64
|
||||
mutex sync.Mutex
|
||||
reservoirSize int
|
||||
values []int64
|
||||
}
|
||||
|
||||
// NewUniformSample constructs a new uniform sample with the given reservoir
|
||||
// size.
|
||||
func NewUniformSample(reservoirSize int) Sample {
|
||||
if UseNilMetrics {
|
||||
return NilSample{}
|
||||
}
|
||||
return &UniformSample{
|
||||
reservoirSize: reservoirSize,
|
||||
values: make([]int64, 0, reservoirSize),
|
||||
}
|
||||
}
|
||||
|
||||
// Clear clears all samples.
|
||||
func (s *UniformSample) Clear() {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
s.count = 0
|
||||
s.values = make([]int64, 0, s.reservoirSize)
|
||||
}
|
||||
|
||||
// Count returns the number of samples recorded, which may exceed the
|
||||
// reservoir size.
|
||||
func (s *UniformSample) Count() int64 {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
return s.count
|
||||
}
|
||||
|
||||
// Max returns the maximum value in the sample, which may not be the maximum
|
||||
// value ever to be part of the sample.
|
||||
func (s *UniformSample) Max() int64 {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
return SampleMax(s.values)
|
||||
}
|
||||
|
||||
// Mean returns the mean of the values in the sample.
|
||||
func (s *UniformSample) Mean() float64 {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
return SampleMean(s.values)
|
||||
}
|
||||
|
||||
// Min returns the minimum value in the sample, which may not be the minimum
|
||||
// value ever to be part of the sample.
|
||||
func (s *UniformSample) Min() int64 {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
return SampleMin(s.values)
|
||||
}
|
||||
|
||||
// Percentile returns an arbitrary percentile of values in the sample.
|
||||
func (s *UniformSample) Percentile(p float64) float64 {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
return SamplePercentile(s.values, p)
|
||||
}
|
||||
|
||||
// Percentiles returns a slice of arbitrary percentiles of values in the
|
||||
// sample.
|
||||
func (s *UniformSample) Percentiles(ps []float64) []float64 {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
return SamplePercentiles(s.values, ps)
|
||||
}
|
||||
|
||||
// Size returns the size of the sample, which is at most the reservoir size.
|
||||
func (s *UniformSample) Size() int {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
return len(s.values)
|
||||
}
|
||||
|
||||
// Snapshot returns a read-only copy of the sample.
|
||||
func (s *UniformSample) Snapshot() Sample {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
values := make([]int64, len(s.values))
|
||||
copy(values, s.values)
|
||||
return &SampleSnapshot{
|
||||
count: s.count,
|
||||
values: values,
|
||||
}
|
||||
}
|
||||
|
||||
// StdDev returns the standard deviation of the values in the sample.
|
||||
func (s *UniformSample) StdDev() float64 {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
return SampleStdDev(s.values)
|
||||
}
|
||||
|
||||
// Sum returns the sum of the values in the sample.
|
||||
func (s *UniformSample) Sum() int64 {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
return SampleSum(s.values)
|
||||
}
|
||||
|
||||
// Update samples a new value.
|
||||
func (s *UniformSample) Update(v int64) {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
s.count++
|
||||
if len(s.values) < s.reservoirSize {
|
||||
s.values = append(s.values, v)
|
||||
} else {
|
||||
r := rand.Int63n(s.count)
|
||||
if r < int64(len(s.values)) {
|
||||
s.values[int(r)] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Values returns a copy of the values in the sample.
|
||||
func (s *UniformSample) Values() []int64 {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
values := make([]int64, len(s.values))
|
||||
copy(values, s.values)
|
||||
return values
|
||||
}
|
||||
|
||||
// Variance returns the variance of the values in the sample.
|
||||
func (s *UniformSample) Variance() float64 {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
return SampleVariance(s.values)
|
||||
}
|
||||
|
||||
// expDecaySample represents an individual sample in a heap.
|
||||
type expDecaySample struct {
|
||||
k float64
|
||||
v int64
|
||||
}
|
||||
|
||||
func newExpDecaySampleHeap(reservoirSize int) *expDecaySampleHeap {
|
||||
return &expDecaySampleHeap{make([]expDecaySample, 0, reservoirSize)}
|
||||
}
|
||||
|
||||
// expDecaySampleHeap is a min-heap of expDecaySamples.
|
||||
// The internal implementation is copied from the standard library's container/heap
|
||||
type expDecaySampleHeap struct {
|
||||
s []expDecaySample
|
||||
}
|
||||
|
||||
func (h *expDecaySampleHeap) Clear() {
|
||||
h.s = h.s[:0]
|
||||
}
|
||||
|
||||
func (h *expDecaySampleHeap) Push(s expDecaySample) {
|
||||
n := len(h.s)
|
||||
h.s = h.s[0 : n+1]
|
||||
h.s[n] = s
|
||||
h.up(n)
|
||||
}
|
||||
|
||||
func (h *expDecaySampleHeap) Pop() expDecaySample {
|
||||
n := len(h.s) - 1
|
||||
h.s[0], h.s[n] = h.s[n], h.s[0]
|
||||
h.down(0, n)
|
||||
|
||||
n = len(h.s)
|
||||
s := h.s[n-1]
|
||||
h.s = h.s[0 : n-1]
|
||||
return s
|
||||
}
|
||||
|
||||
func (h *expDecaySampleHeap) Size() int {
|
||||
return len(h.s)
|
||||
}
|
||||
|
||||
func (h *expDecaySampleHeap) Values() []expDecaySample {
|
||||
return h.s
|
||||
}
|
||||
|
||||
func (h *expDecaySampleHeap) up(j int) {
|
||||
for {
|
||||
i := (j - 1) / 2 // parent
|
||||
if i == j || !(h.s[j].k < h.s[i].k) {
|
||||
break
|
||||
}
|
||||
h.s[i], h.s[j] = h.s[j], h.s[i]
|
||||
j = i
|
||||
}
|
||||
}
|
||||
|
||||
func (h *expDecaySampleHeap) down(i, n int) {
|
||||
for {
|
||||
j1 := 2*i + 1
|
||||
if j1 >= n || j1 < 0 { // j1 < 0 after int overflow
|
||||
break
|
||||
}
|
||||
j := j1 // left child
|
||||
if j2 := j1 + 1; j2 < n && !(h.s[j1].k < h.s[j2].k) {
|
||||
j = j2 // = 2*i + 2 // right child
|
||||
}
|
||||
if !(h.s[j].k < h.s[i].k) {
|
||||
break
|
||||
}
|
||||
h.s[i], h.s[j] = h.s[j], h.s[i]
|
||||
i = j
|
||||
}
|
||||
}
|
||||
|
||||
type int64Slice []int64
|
||||
|
||||
func (p int64Slice) Len() int { return len(p) }
|
||||
func (p int64Slice) Less(i, j int) bool { return p[i] < p[j] }
|
||||
func (p int64Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
||||
69
Godeps/_workspace/src/github.com/rcrowley/go-metrics/stathat/stathat.go
generated
vendored
Normal file
69
Godeps/_workspace/src/github.com/rcrowley/go-metrics/stathat/stathat.go
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
// Metrics output to StatHat.
|
||||
package stathat
|
||||
|
||||
import (
|
||||
"github.com/rcrowley/go-metrics"
|
||||
"github.com/stathat/go"
|
||||
"log"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Stathat(r metrics.Registry, d time.Duration, userkey string) {
|
||||
for {
|
||||
if err := sh(r, userkey); nil != err {
|
||||
log.Println(err)
|
||||
}
|
||||
time.Sleep(d)
|
||||
}
|
||||
}
|
||||
|
||||
func sh(r metrics.Registry, userkey string) error {
|
||||
r.Each(func(name string, i interface{}) {
|
||||
switch metric := i.(type) {
|
||||
case metrics.Counter:
|
||||
stathat.PostEZCount(name, userkey, int(metric.Count()))
|
||||
case metrics.Gauge:
|
||||
stathat.PostEZValue(name, userkey, float64(metric.Value()))
|
||||
case metrics.GaugeFloat64:
|
||||
stathat.PostEZValue(name, userkey, float64(metric.Value()))
|
||||
case metrics.Histogram:
|
||||
h := metric.Snapshot()
|
||||
ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
|
||||
stathat.PostEZCount(name+".count", userkey, int(h.Count()))
|
||||
stathat.PostEZValue(name+".min", userkey, float64(h.Min()))
|
||||
stathat.PostEZValue(name+".max", userkey, float64(h.Max()))
|
||||
stathat.PostEZValue(name+".mean", userkey, float64(h.Mean()))
|
||||
stathat.PostEZValue(name+".std-dev", userkey, float64(h.StdDev()))
|
||||
stathat.PostEZValue(name+".50-percentile", userkey, float64(ps[0]))
|
||||
stathat.PostEZValue(name+".75-percentile", userkey, float64(ps[1]))
|
||||
stathat.PostEZValue(name+".95-percentile", userkey, float64(ps[2]))
|
||||
stathat.PostEZValue(name+".99-percentile", userkey, float64(ps[3]))
|
||||
stathat.PostEZValue(name+".999-percentile", userkey, float64(ps[4]))
|
||||
case metrics.Meter:
|
||||
m := metric.Snapshot()
|
||||
stathat.PostEZCount(name+".count", userkey, int(m.Count()))
|
||||
stathat.PostEZValue(name+".one-minute", userkey, float64(m.Rate1()))
|
||||
stathat.PostEZValue(name+".five-minute", userkey, float64(m.Rate5()))
|
||||
stathat.PostEZValue(name+".fifteen-minute", userkey, float64(m.Rate15()))
|
||||
stathat.PostEZValue(name+".mean", userkey, float64(m.RateMean()))
|
||||
case metrics.Timer:
|
||||
t := metric.Snapshot()
|
||||
ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
|
||||
stathat.PostEZCount(name+".count", userkey, int(t.Count()))
|
||||
stathat.PostEZValue(name+".min", userkey, float64(t.Min()))
|
||||
stathat.PostEZValue(name+".max", userkey, float64(t.Max()))
|
||||
stathat.PostEZValue(name+".mean", userkey, float64(t.Mean()))
|
||||
stathat.PostEZValue(name+".std-dev", userkey, float64(t.StdDev()))
|
||||
stathat.PostEZValue(name+".50-percentile", userkey, float64(ps[0]))
|
||||
stathat.PostEZValue(name+".75-percentile", userkey, float64(ps[1]))
|
||||
stathat.PostEZValue(name+".95-percentile", userkey, float64(ps[2]))
|
||||
stathat.PostEZValue(name+".99-percentile", userkey, float64(ps[3]))
|
||||
stathat.PostEZValue(name+".999-percentile", userkey, float64(ps[4]))
|
||||
stathat.PostEZValue(name+".one-minute", userkey, float64(t.Rate1()))
|
||||
stathat.PostEZValue(name+".five-minute", userkey, float64(t.Rate5()))
|
||||
stathat.PostEZValue(name+".fifteen-minute", userkey, float64(t.Rate15()))
|
||||
stathat.PostEZValue(name+".mean-rate", userkey, float64(t.RateMean()))
|
||||
}
|
||||
})
|
||||
return nil
|
||||
}
|
||||
78
Godeps/_workspace/src/github.com/rcrowley/go-metrics/syslog.go
generated
vendored
Normal file
78
Godeps/_workspace/src/github.com/rcrowley/go-metrics/syslog.go
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
// +build !windows
|
||||
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/syslog"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Output each metric in the given registry to syslog periodically using
|
||||
// the given syslogger.
|
||||
func Syslog(r Registry, d time.Duration, w *syslog.Writer) {
|
||||
for _ = range time.Tick(d) {
|
||||
r.Each(func(name string, i interface{}) {
|
||||
switch metric := i.(type) {
|
||||
case Counter:
|
||||
w.Info(fmt.Sprintf("counter %s: count: %d", name, metric.Count()))
|
||||
case Gauge:
|
||||
w.Info(fmt.Sprintf("gauge %s: value: %d", name, metric.Value()))
|
||||
case GaugeFloat64:
|
||||
w.Info(fmt.Sprintf("gauge %s: value: %f", name, metric.Value()))
|
||||
case Healthcheck:
|
||||
metric.Check()
|
||||
w.Info(fmt.Sprintf("healthcheck %s: error: %v", name, metric.Error()))
|
||||
case Histogram:
|
||||
h := metric.Snapshot()
|
||||
ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
|
||||
w.Info(fmt.Sprintf(
|
||||
"histogram %s: count: %d min: %d max: %d mean: %.2f stddev: %.2f median: %.2f 75%%: %.2f 95%%: %.2f 99%%: %.2f 99.9%%: %.2f",
|
||||
name,
|
||||
h.Count(),
|
||||
h.Min(),
|
||||
h.Max(),
|
||||
h.Mean(),
|
||||
h.StdDev(),
|
||||
ps[0],
|
||||
ps[1],
|
||||
ps[2],
|
||||
ps[3],
|
||||
ps[4],
|
||||
))
|
||||
case Meter:
|
||||
m := metric.Snapshot()
|
||||
w.Info(fmt.Sprintf(
|
||||
"meter %s: count: %d 1-min: %.2f 5-min: %.2f 15-min: %.2f mean: %.2f",
|
||||
name,
|
||||
m.Count(),
|
||||
m.Rate1(),
|
||||
m.Rate5(),
|
||||
m.Rate15(),
|
||||
m.RateMean(),
|
||||
))
|
||||
case Timer:
|
||||
t := metric.Snapshot()
|
||||
ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
|
||||
w.Info(fmt.Sprintf(
|
||||
"timer %s: count: %d min: %d max: %d mean: %.2f stddev: %.2f median: %.2f 75%%: %.2f 95%%: %.2f 99%%: %.2f 99.9%%: %.2f 1-min: %.2f 5-min: %.2f 15-min: %.2f mean-rate: %.2f",
|
||||
name,
|
||||
t.Count(),
|
||||
t.Min(),
|
||||
t.Max(),
|
||||
t.Mean(),
|
||||
t.StdDev(),
|
||||
ps[0],
|
||||
ps[1],
|
||||
ps[2],
|
||||
ps[3],
|
||||
ps[4],
|
||||
t.Rate1(),
|
||||
t.Rate5(),
|
||||
t.Rate15(),
|
||||
t.RateMean(),
|
||||
))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
311
Godeps/_workspace/src/github.com/rcrowley/go-metrics/timer.go
generated
vendored
Normal file
311
Godeps/_workspace/src/github.com/rcrowley/go-metrics/timer.go
generated
vendored
Normal file
@@ -0,0 +1,311 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Timers capture the duration and rate of events.
|
||||
type Timer interface {
|
||||
Count() int64
|
||||
Max() int64
|
||||
Mean() float64
|
||||
Min() int64
|
||||
Percentile(float64) float64
|
||||
Percentiles([]float64) []float64
|
||||
Rate1() float64
|
||||
Rate5() float64
|
||||
Rate15() float64
|
||||
RateMean() float64
|
||||
Snapshot() Timer
|
||||
StdDev() float64
|
||||
Sum() int64
|
||||
Time(func())
|
||||
Update(time.Duration)
|
||||
UpdateSince(time.Time)
|
||||
Variance() float64
|
||||
}
|
||||
|
||||
// GetOrRegisterTimer returns an existing Timer or constructs and registers a
|
||||
// new StandardTimer.
|
||||
func GetOrRegisterTimer(name string, r Registry) Timer {
|
||||
if nil == r {
|
||||
r = DefaultRegistry
|
||||
}
|
||||
return r.GetOrRegister(name, NewTimer).(Timer)
|
||||
}
|
||||
|
||||
// NewCustomTimer constructs a new StandardTimer from a Histogram and a Meter.
|
||||
func NewCustomTimer(h Histogram, m Meter) Timer {
|
||||
if UseNilMetrics {
|
||||
return NilTimer{}
|
||||
}
|
||||
return &StandardTimer{
|
||||
histogram: h,
|
||||
meter: m,
|
||||
}
|
||||
}
|
||||
|
||||
// NewRegisteredTimer constructs and registers a new StandardTimer.
|
||||
func NewRegisteredTimer(name string, r Registry) Timer {
|
||||
c := NewTimer()
|
||||
if nil == r {
|
||||
r = DefaultRegistry
|
||||
}
|
||||
r.Register(name, c)
|
||||
return c
|
||||
}
|
||||
|
||||
// NewTimer constructs a new StandardTimer using an exponentially-decaying
|
||||
// sample with the same reservoir size and alpha as UNIX load averages.
|
||||
func NewTimer() Timer {
|
||||
if UseNilMetrics {
|
||||
return NilTimer{}
|
||||
}
|
||||
return &StandardTimer{
|
||||
histogram: NewHistogram(NewExpDecaySample(1028, 0.015)),
|
||||
meter: NewMeter(),
|
||||
}
|
||||
}
|
||||
|
||||
// NilTimer is a no-op Timer.
|
||||
type NilTimer struct {
|
||||
h Histogram
|
||||
m Meter
|
||||
}
|
||||
|
||||
// Count is a no-op.
|
||||
func (NilTimer) Count() int64 { return 0 }
|
||||
|
||||
// Max is a no-op.
|
||||
func (NilTimer) Max() int64 { return 0 }
|
||||
|
||||
// Mean is a no-op.
|
||||
func (NilTimer) Mean() float64 { return 0.0 }
|
||||
|
||||
// Min is a no-op.
|
||||
func (NilTimer) Min() int64 { return 0 }
|
||||
|
||||
// Percentile is a no-op.
|
||||
func (NilTimer) Percentile(p float64) float64 { return 0.0 }
|
||||
|
||||
// Percentiles is a no-op.
|
||||
func (NilTimer) Percentiles(ps []float64) []float64 {
|
||||
return make([]float64, len(ps))
|
||||
}
|
||||
|
||||
// Rate1 is a no-op.
|
||||
func (NilTimer) Rate1() float64 { return 0.0 }
|
||||
|
||||
// Rate5 is a no-op.
|
||||
func (NilTimer) Rate5() float64 { return 0.0 }
|
||||
|
||||
// Rate15 is a no-op.
|
||||
func (NilTimer) Rate15() float64 { return 0.0 }
|
||||
|
||||
// RateMean is a no-op.
|
||||
func (NilTimer) RateMean() float64 { return 0.0 }
|
||||
|
||||
// Snapshot is a no-op.
|
||||
func (NilTimer) Snapshot() Timer { return NilTimer{} }
|
||||
|
||||
// StdDev is a no-op.
|
||||
func (NilTimer) StdDev() float64 { return 0.0 }
|
||||
|
||||
// Sum is a no-op.
|
||||
func (NilTimer) Sum() int64 { return 0 }
|
||||
|
||||
// Time is a no-op.
|
||||
func (NilTimer) Time(func()) {}
|
||||
|
||||
// Update is a no-op.
|
||||
func (NilTimer) Update(time.Duration) {}
|
||||
|
||||
// UpdateSince is a no-op.
|
||||
func (NilTimer) UpdateSince(time.Time) {}
|
||||
|
||||
// Variance is a no-op.
|
||||
func (NilTimer) Variance() float64 { return 0.0 }
|
||||
|
||||
// StandardTimer is the standard implementation of a Timer and uses a Histogram
|
||||
// and Meter.
|
||||
type StandardTimer struct {
|
||||
histogram Histogram
|
||||
meter Meter
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
// Count returns the number of events recorded.
|
||||
func (t *StandardTimer) Count() int64 {
|
||||
return t.histogram.Count()
|
||||
}
|
||||
|
||||
// Max returns the maximum value in the sample.
|
||||
func (t *StandardTimer) Max() int64 {
|
||||
return t.histogram.Max()
|
||||
}
|
||||
|
||||
// Mean returns the mean of the values in the sample.
|
||||
func (t *StandardTimer) Mean() float64 {
|
||||
return t.histogram.Mean()
|
||||
}
|
||||
|
||||
// Min returns the minimum value in the sample.
|
||||
func (t *StandardTimer) Min() int64 {
|
||||
return t.histogram.Min()
|
||||
}
|
||||
|
||||
// Percentile returns an arbitrary percentile of the values in the sample.
|
||||
func (t *StandardTimer) Percentile(p float64) float64 {
|
||||
return t.histogram.Percentile(p)
|
||||
}
|
||||
|
||||
// Percentiles returns a slice of arbitrary percentiles of the values in the
|
||||
// sample.
|
||||
func (t *StandardTimer) Percentiles(ps []float64) []float64 {
|
||||
return t.histogram.Percentiles(ps)
|
||||
}
|
||||
|
||||
// Rate1 returns the one-minute moving average rate of events per second.
|
||||
func (t *StandardTimer) Rate1() float64 {
|
||||
return t.meter.Rate1()
|
||||
}
|
||||
|
||||
// Rate5 returns the five-minute moving average rate of events per second.
|
||||
func (t *StandardTimer) Rate5() float64 {
|
||||
return t.meter.Rate5()
|
||||
}
|
||||
|
||||
// Rate15 returns the fifteen-minute moving average rate of events per second.
|
||||
func (t *StandardTimer) Rate15() float64 {
|
||||
return t.meter.Rate15()
|
||||
}
|
||||
|
||||
// RateMean returns the meter's mean rate of events per second.
|
||||
func (t *StandardTimer) RateMean() float64 {
|
||||
return t.meter.RateMean()
|
||||
}
|
||||
|
||||
// Snapshot returns a read-only copy of the timer.
|
||||
func (t *StandardTimer) Snapshot() Timer {
|
||||
t.mutex.Lock()
|
||||
defer t.mutex.Unlock()
|
||||
return &TimerSnapshot{
|
||||
histogram: t.histogram.Snapshot().(*HistogramSnapshot),
|
||||
meter: t.meter.Snapshot().(*MeterSnapshot),
|
||||
}
|
||||
}
|
||||
|
||||
// StdDev returns the standard deviation of the values in the sample.
|
||||
func (t *StandardTimer) StdDev() float64 {
|
||||
return t.histogram.StdDev()
|
||||
}
|
||||
|
||||
// Sum returns the sum in the sample.
|
||||
func (t *StandardTimer) Sum() int64 {
|
||||
return t.histogram.Sum()
|
||||
}
|
||||
|
||||
// Record the duration of the execution of the given function.
|
||||
func (t *StandardTimer) Time(f func()) {
|
||||
ts := time.Now()
|
||||
f()
|
||||
t.Update(time.Since(ts))
|
||||
}
|
||||
|
||||
// Record the duration of an event.
|
||||
func (t *StandardTimer) Update(d time.Duration) {
|
||||
t.mutex.Lock()
|
||||
defer t.mutex.Unlock()
|
||||
t.histogram.Update(int64(d))
|
||||
t.meter.Mark(1)
|
||||
}
|
||||
|
||||
// Record the duration of an event that started at a time and ends now.
|
||||
func (t *StandardTimer) UpdateSince(ts time.Time) {
|
||||
t.mutex.Lock()
|
||||
defer t.mutex.Unlock()
|
||||
t.histogram.Update(int64(time.Since(ts)))
|
||||
t.meter.Mark(1)
|
||||
}
|
||||
|
||||
// Variance returns the variance of the values in the sample.
|
||||
func (t *StandardTimer) Variance() float64 {
|
||||
return t.histogram.Variance()
|
||||
}
|
||||
|
||||
// TimerSnapshot is a read-only copy of another Timer.
|
||||
type TimerSnapshot struct {
|
||||
histogram *HistogramSnapshot
|
||||
meter *MeterSnapshot
|
||||
}
|
||||
|
||||
// Count returns the number of events recorded at the time the snapshot was
|
||||
// taken.
|
||||
func (t *TimerSnapshot) Count() int64 { return t.histogram.Count() }
|
||||
|
||||
// Max returns the maximum value at the time the snapshot was taken.
|
||||
func (t *TimerSnapshot) Max() int64 { return t.histogram.Max() }
|
||||
|
||||
// Mean returns the mean value at the time the snapshot was taken.
|
||||
func (t *TimerSnapshot) Mean() float64 { return t.histogram.Mean() }
|
||||
|
||||
// Min returns the minimum value at the time the snapshot was taken.
|
||||
func (t *TimerSnapshot) Min() int64 { return t.histogram.Min() }
|
||||
|
||||
// Percentile returns an arbitrary percentile of sampled values at the time the
|
||||
// snapshot was taken.
|
||||
func (t *TimerSnapshot) Percentile(p float64) float64 {
|
||||
return t.histogram.Percentile(p)
|
||||
}
|
||||
|
||||
// Percentiles returns a slice of arbitrary percentiles of sampled values at
|
||||
// the time the snapshot was taken.
|
||||
func (t *TimerSnapshot) Percentiles(ps []float64) []float64 {
|
||||
return t.histogram.Percentiles(ps)
|
||||
}
|
||||
|
||||
// Rate1 returns the one-minute moving average rate of events per second at the
|
||||
// time the snapshot was taken.
|
||||
func (t *TimerSnapshot) Rate1() float64 { return t.meter.Rate1() }
|
||||
|
||||
// Rate5 returns the five-minute moving average rate of events per second at
|
||||
// the time the snapshot was taken.
|
||||
func (t *TimerSnapshot) Rate5() float64 { return t.meter.Rate5() }
|
||||
|
||||
// Rate15 returns the fifteen-minute moving average rate of events per second
|
||||
// at the time the snapshot was taken.
|
||||
func (t *TimerSnapshot) Rate15() float64 { return t.meter.Rate15() }
|
||||
|
||||
// RateMean returns the meter's mean rate of events per second at the time the
|
||||
// snapshot was taken.
|
||||
func (t *TimerSnapshot) RateMean() float64 { return t.meter.RateMean() }
|
||||
|
||||
// Snapshot returns the snapshot.
|
||||
func (t *TimerSnapshot) Snapshot() Timer { return t }
|
||||
|
||||
// StdDev returns the standard deviation of the values at the time the snapshot
|
||||
// was taken.
|
||||
func (t *TimerSnapshot) StdDev() float64 { return t.histogram.StdDev() }
|
||||
|
||||
// Sum returns the sum at the time the snapshot was taken.
|
||||
func (t *TimerSnapshot) Sum() int64 { return t.histogram.Sum() }
|
||||
|
||||
// Time panics.
|
||||
func (*TimerSnapshot) Time(func()) {
|
||||
panic("Time called on a TimerSnapshot")
|
||||
}
|
||||
|
||||
// Update panics.
|
||||
func (*TimerSnapshot) Update(time.Duration) {
|
||||
panic("Update called on a TimerSnapshot")
|
||||
}
|
||||
|
||||
// UpdateSince panics.
|
||||
func (*TimerSnapshot) UpdateSince(time.Time) {
|
||||
panic("UpdateSince called on a TimerSnapshot")
|
||||
}
|
||||
|
||||
// Variance returns the variance of the values at the time the snapshot was
|
||||
// taken.
|
||||
func (t *TimerSnapshot) Variance() float64 { return t.histogram.Variance() }
|
||||
10
Godeps/_workspace/src/github.com/rcrowley/go-metrics/validate.sh
generated
vendored
Normal file
10
Godeps/_workspace/src/github.com/rcrowley/go-metrics/validate.sh
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
# check there are no formatting issues
|
||||
GOFMT_LINES=`gofmt -l . | wc -l | xargs`
|
||||
test $GOFMT_LINES -eq 0 || echo "gofmt needs to be run, ${GOFMT_LINES} files have issues"
|
||||
|
||||
# run the tests for the root package
|
||||
go test .
|
||||
100
Godeps/_workspace/src/github.com/rcrowley/go-metrics/writer.go
generated
vendored
Normal file
100
Godeps/_workspace/src/github.com/rcrowley/go-metrics/writer.go
generated
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"sort"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Write sorts writes each metric in the given registry periodically to the
|
||||
// given io.Writer.
|
||||
func Write(r Registry, d time.Duration, w io.Writer) {
|
||||
for _ = range time.Tick(d) {
|
||||
WriteOnce(r, w)
|
||||
}
|
||||
}
|
||||
|
||||
// WriteOnce sorts and writes metrics in the given registry to the given
|
||||
// io.Writer.
|
||||
func WriteOnce(r Registry, w io.Writer) {
|
||||
var namedMetrics namedMetricSlice
|
||||
r.Each(func(name string, i interface{}) {
|
||||
namedMetrics = append(namedMetrics, namedMetric{name, i})
|
||||
})
|
||||
|
||||
sort.Sort(namedMetrics)
|
||||
for _, namedMetric := range namedMetrics {
|
||||
switch metric := namedMetric.m.(type) {
|
||||
case Counter:
|
||||
fmt.Fprintf(w, "counter %s\n", namedMetric.name)
|
||||
fmt.Fprintf(w, " count: %9d\n", metric.Count())
|
||||
case Gauge:
|
||||
fmt.Fprintf(w, "gauge %s\n", namedMetric.name)
|
||||
fmt.Fprintf(w, " value: %9d\n", metric.Value())
|
||||
case GaugeFloat64:
|
||||
fmt.Fprintf(w, "gauge %s\n", namedMetric.name)
|
||||
fmt.Fprintf(w, " value: %f\n", metric.Value())
|
||||
case Healthcheck:
|
||||
metric.Check()
|
||||
fmt.Fprintf(w, "healthcheck %s\n", namedMetric.name)
|
||||
fmt.Fprintf(w, " error: %v\n", metric.Error())
|
||||
case Histogram:
|
||||
h := metric.Snapshot()
|
||||
ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
|
||||
fmt.Fprintf(w, "histogram %s\n", namedMetric.name)
|
||||
fmt.Fprintf(w, " count: %9d\n", h.Count())
|
||||
fmt.Fprintf(w, " min: %9d\n", h.Min())
|
||||
fmt.Fprintf(w, " max: %9d\n", h.Max())
|
||||
fmt.Fprintf(w, " mean: %12.2f\n", h.Mean())
|
||||
fmt.Fprintf(w, " stddev: %12.2f\n", h.StdDev())
|
||||
fmt.Fprintf(w, " median: %12.2f\n", ps[0])
|
||||
fmt.Fprintf(w, " 75%%: %12.2f\n", ps[1])
|
||||
fmt.Fprintf(w, " 95%%: %12.2f\n", ps[2])
|
||||
fmt.Fprintf(w, " 99%%: %12.2f\n", ps[3])
|
||||
fmt.Fprintf(w, " 99.9%%: %12.2f\n", ps[4])
|
||||
case Meter:
|
||||
m := metric.Snapshot()
|
||||
fmt.Fprintf(w, "meter %s\n", namedMetric.name)
|
||||
fmt.Fprintf(w, " count: %9d\n", m.Count())
|
||||
fmt.Fprintf(w, " 1-min rate: %12.2f\n", m.Rate1())
|
||||
fmt.Fprintf(w, " 5-min rate: %12.2f\n", m.Rate5())
|
||||
fmt.Fprintf(w, " 15-min rate: %12.2f\n", m.Rate15())
|
||||
fmt.Fprintf(w, " mean rate: %12.2f\n", m.RateMean())
|
||||
case Timer:
|
||||
t := metric.Snapshot()
|
||||
ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
|
||||
fmt.Fprintf(w, "timer %s\n", namedMetric.name)
|
||||
fmt.Fprintf(w, " count: %9d\n", t.Count())
|
||||
fmt.Fprintf(w, " min: %9d\n", t.Min())
|
||||
fmt.Fprintf(w, " max: %9d\n", t.Max())
|
||||
fmt.Fprintf(w, " mean: %12.2f\n", t.Mean())
|
||||
fmt.Fprintf(w, " stddev: %12.2f\n", t.StdDev())
|
||||
fmt.Fprintf(w, " median: %12.2f\n", ps[0])
|
||||
fmt.Fprintf(w, " 75%%: %12.2f\n", ps[1])
|
||||
fmt.Fprintf(w, " 95%%: %12.2f\n", ps[2])
|
||||
fmt.Fprintf(w, " 99%%: %12.2f\n", ps[3])
|
||||
fmt.Fprintf(w, " 99.9%%: %12.2f\n", ps[4])
|
||||
fmt.Fprintf(w, " 1-min rate: %12.2f\n", t.Rate1())
|
||||
fmt.Fprintf(w, " 5-min rate: %12.2f\n", t.Rate5())
|
||||
fmt.Fprintf(w, " 15-min rate: %12.2f\n", t.Rate15())
|
||||
fmt.Fprintf(w, " mean rate: %12.2f\n", t.RateMean())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type namedMetric struct {
|
||||
name string
|
||||
m interface{}
|
||||
}
|
||||
|
||||
// namedMetricSlice is a slice of namedMetrics that implements sort.Interface.
|
||||
type namedMetricSlice []namedMetric
|
||||
|
||||
func (nms namedMetricSlice) Len() int { return len(nms) }
|
||||
|
||||
func (nms namedMetricSlice) Swap(i, j int) { nms[i], nms[j] = nms[j], nms[i] }
|
||||
|
||||
func (nms namedMetricSlice) Less(i, j int) bool {
|
||||
return nms[i].name < nms[j].name
|
||||
}
|
||||
252
Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/batch.go
generated
vendored
Normal file
252
Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/batch.go
generated
vendored
Normal file
@@ -0,0 +1,252 @@
|
||||
// Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com>
|
||||
// All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package leveldb
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
"github.com/syndtr/goleveldb/leveldb/errors"
|
||||
"github.com/syndtr/goleveldb/leveldb/memdb"
|
||||
)
|
||||
|
||||
type ErrBatchCorrupted struct {
|
||||
Reason string
|
||||
}
|
||||
|
||||
func (e *ErrBatchCorrupted) Error() string {
|
||||
return fmt.Sprintf("leveldb: batch corrupted: %s", e.Reason)
|
||||
}
|
||||
|
||||
func newErrBatchCorrupted(reason string) error {
|
||||
return errors.NewErrCorrupted(nil, &ErrBatchCorrupted{reason})
|
||||
}
|
||||
|
||||
const (
|
||||
batchHdrLen = 8 + 4
|
||||
batchGrowRec = 3000
|
||||
)
|
||||
|
||||
type BatchReplay interface {
|
||||
Put(key, value []byte)
|
||||
Delete(key []byte)
|
||||
}
|
||||
|
||||
// Batch is a write batch.
|
||||
type Batch struct {
|
||||
data []byte
|
||||
rLen, bLen int
|
||||
seq uint64
|
||||
sync bool
|
||||
}
|
||||
|
||||
func (b *Batch) grow(n int) {
|
||||
off := len(b.data)
|
||||
if off == 0 {
|
||||
off = batchHdrLen
|
||||
if b.data != nil {
|
||||
b.data = b.data[:off]
|
||||
}
|
||||
}
|
||||
if cap(b.data)-off < n {
|
||||
if b.data == nil {
|
||||
b.data = make([]byte, off, off+n)
|
||||
} else {
|
||||
odata := b.data
|
||||
div := 1
|
||||
if b.rLen > batchGrowRec {
|
||||
div = b.rLen / batchGrowRec
|
||||
}
|
||||
b.data = make([]byte, off, off+n+(off-batchHdrLen)/div)
|
||||
copy(b.data, odata)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Batch) appendRec(kt kType, key, value []byte) {
|
||||
n := 1 + binary.MaxVarintLen32 + len(key)
|
||||
if kt == ktVal {
|
||||
n += binary.MaxVarintLen32 + len(value)
|
||||
}
|
||||
b.grow(n)
|
||||
off := len(b.data)
|
||||
data := b.data[:off+n]
|
||||
data[off] = byte(kt)
|
||||
off += 1
|
||||
off += binary.PutUvarint(data[off:], uint64(len(key)))
|
||||
copy(data[off:], key)
|
||||
off += len(key)
|
||||
if kt == ktVal {
|
||||
off += binary.PutUvarint(data[off:], uint64(len(value)))
|
||||
copy(data[off:], value)
|
||||
off += len(value)
|
||||
}
|
||||
b.data = data[:off]
|
||||
b.rLen++
|
||||
// Include 8-byte ikey header
|
||||
b.bLen += len(key) + len(value) + 8
|
||||
}
|
||||
|
||||
// Put appends 'put operation' of the given key/value pair to the batch.
|
||||
// It is safe to modify the contents of the argument after Put returns.
|
||||
func (b *Batch) Put(key, value []byte) {
|
||||
b.appendRec(ktVal, key, value)
|
||||
}
|
||||
|
||||
// Delete appends 'delete operation' of the given key to the batch.
|
||||
// It is safe to modify the contents of the argument after Delete returns.
|
||||
func (b *Batch) Delete(key []byte) {
|
||||
b.appendRec(ktDel, key, nil)
|
||||
}
|
||||
|
||||
// Dump dumps batch contents. The returned slice can be loaded into the
|
||||
// batch using Load method.
|
||||
// The returned slice is not its own copy, so the contents should not be
|
||||
// modified.
|
||||
func (b *Batch) Dump() []byte {
|
||||
return b.encode()
|
||||
}
|
||||
|
||||
// Load loads given slice into the batch. Previous contents of the batch
|
||||
// will be discarded.
|
||||
// The given slice will not be copied and will be used as batch buffer, so
|
||||
// it is not safe to modify the contents of the slice.
|
||||
func (b *Batch) Load(data []byte) error {
|
||||
return b.decode(0, data)
|
||||
}
|
||||
|
||||
// Replay replays batch contents.
|
||||
func (b *Batch) Replay(r BatchReplay) error {
|
||||
return b.decodeRec(func(i int, kt kType, key, value []byte) {
|
||||
switch kt {
|
||||
case ktVal:
|
||||
r.Put(key, value)
|
||||
case ktDel:
|
||||
r.Delete(key)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Len returns number of records in the batch.
|
||||
func (b *Batch) Len() int {
|
||||
return b.rLen
|
||||
}
|
||||
|
||||
// Reset resets the batch.
|
||||
func (b *Batch) Reset() {
|
||||
b.data = b.data[:0]
|
||||
b.seq = 0
|
||||
b.rLen = 0
|
||||
b.bLen = 0
|
||||
b.sync = false
|
||||
}
|
||||
|
||||
func (b *Batch) init(sync bool) {
|
||||
b.sync = sync
|
||||
}
|
||||
|
||||
func (b *Batch) append(p *Batch) {
|
||||
if p.rLen > 0 {
|
||||
b.grow(len(p.data) - batchHdrLen)
|
||||
b.data = append(b.data, p.data[batchHdrLen:]...)
|
||||
b.rLen += p.rLen
|
||||
}
|
||||
if p.sync {
|
||||
b.sync = true
|
||||
}
|
||||
}
|
||||
|
||||
// size returns sums of key/value pair length plus 8-bytes ikey.
|
||||
func (b *Batch) size() int {
|
||||
return b.bLen
|
||||
}
|
||||
|
||||
func (b *Batch) encode() []byte {
|
||||
b.grow(0)
|
||||
binary.LittleEndian.PutUint64(b.data, b.seq)
|
||||
binary.LittleEndian.PutUint32(b.data[8:], uint32(b.rLen))
|
||||
|
||||
return b.data
|
||||
}
|
||||
|
||||
func (b *Batch) decode(prevSeq uint64, data []byte) error {
|
||||
if len(data) < batchHdrLen {
|
||||
return newErrBatchCorrupted("too short")
|
||||
}
|
||||
|
||||
b.seq = binary.LittleEndian.Uint64(data)
|
||||
if b.seq < prevSeq {
|
||||
return newErrBatchCorrupted("invalid sequence number")
|
||||
}
|
||||
b.rLen = int(binary.LittleEndian.Uint32(data[8:]))
|
||||
if b.rLen < 0 {
|
||||
return newErrBatchCorrupted("invalid records length")
|
||||
}
|
||||
// No need to be precise at this point, it won't be used anyway
|
||||
b.bLen = len(data) - batchHdrLen
|
||||
b.data = data
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Batch) decodeRec(f func(i int, kt kType, key, value []byte)) (err error) {
|
||||
off := batchHdrLen
|
||||
for i := 0; i < b.rLen; i++ {
|
||||
if off >= len(b.data) {
|
||||
return newErrBatchCorrupted("invalid records length")
|
||||
}
|
||||
|
||||
kt := kType(b.data[off])
|
||||
if kt > ktVal {
|
||||
return newErrBatchCorrupted("bad record: invalid type")
|
||||
}
|
||||
off += 1
|
||||
|
||||
x, n := binary.Uvarint(b.data[off:])
|
||||
off += n
|
||||
if n <= 0 || off+int(x) > len(b.data) {
|
||||
return newErrBatchCorrupted("bad record: invalid key length")
|
||||
}
|
||||
key := b.data[off : off+int(x)]
|
||||
off += int(x)
|
||||
var value []byte
|
||||
if kt == ktVal {
|
||||
x, n := binary.Uvarint(b.data[off:])
|
||||
off += n
|
||||
if n <= 0 || off+int(x) > len(b.data) {
|
||||
return newErrBatchCorrupted("bad record: invalid value length")
|
||||
}
|
||||
value = b.data[off : off+int(x)]
|
||||
off += int(x)
|
||||
}
|
||||
|
||||
f(i, kt, key, value)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Batch) memReplay(to *memdb.DB) error {
|
||||
return b.decodeRec(func(i int, kt kType, key, value []byte) {
|
||||
ikey := newIkey(key, b.seq+uint64(i), kt)
|
||||
to.Put(ikey, value)
|
||||
})
|
||||
}
|
||||
|
||||
func (b *Batch) memDecodeAndReplay(prevSeq uint64, data []byte, to *memdb.DB) error {
|
||||
if err := b.decode(prevSeq, data); err != nil {
|
||||
return err
|
||||
}
|
||||
return b.memReplay(to)
|
||||
}
|
||||
|
||||
func (b *Batch) revertMemReplay(to *memdb.DB) error {
|
||||
return b.decodeRec(func(i int, kt kType, key, value []byte) {
|
||||
ikey := newIkey(key, b.seq+uint64(i), kt)
|
||||
to.Delete(ikey)
|
||||
})
|
||||
}
|
||||
676
Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/cache/cache.go
generated
vendored
Normal file
676
Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/cache/cache.go
generated
vendored
Normal file
@@ -0,0 +1,676 @@
|
||||
// Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com>
|
||||
// All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Package cache provides interface and implementation of a cache algorithms.
|
||||
package cache
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"unsafe"
|
||||
|
||||
"github.com/syndtr/goleveldb/leveldb/util"
|
||||
)
|
||||
|
||||
// Cacher provides interface to implements a caching functionality.
|
||||
// An implementation must be goroutine-safe.
|
||||
type Cacher interface {
|
||||
// Capacity returns cache capacity.
|
||||
Capacity() int
|
||||
|
||||
// SetCapacity sets cache capacity.
|
||||
SetCapacity(capacity int)
|
||||
|
||||
// Promote promotes the 'cache node'.
|
||||
Promote(n *Node)
|
||||
|
||||
// Ban evicts the 'cache node' and prevent subsequent 'promote'.
|
||||
Ban(n *Node)
|
||||
|
||||
// Evict evicts the 'cache node'.
|
||||
Evict(n *Node)
|
||||
|
||||
// EvictNS evicts 'cache node' with the given namespace.
|
||||
EvictNS(ns uint64)
|
||||
|
||||
// EvictAll evicts all 'cache node'.
|
||||
EvictAll()
|
||||
|
||||
// Close closes the 'cache tree'
|
||||
Close() error
|
||||
}
|
||||
|
||||
// Value is a 'cacheable object'. It may implements util.Releaser, if
|
||||
// so the the Release method will be called once object is released.
|
||||
type Value interface{}
|
||||
|
||||
type CacheGetter struct {
|
||||
Cache *Cache
|
||||
NS uint64
|
||||
}
|
||||
|
||||
func (g *CacheGetter) Get(key uint64, setFunc func() (size int, value Value)) *Handle {
|
||||
return g.Cache.Get(g.NS, key, setFunc)
|
||||
}
|
||||
|
||||
// The hash tables implementation is based on:
|
||||
// "Dynamic-Sized Nonblocking Hash Tables", by Yujie Liu, Kunlong Zhang, and Michael Spear. ACM Symposium on Principles of Distributed Computing, Jul 2014.
|
||||
|
||||
const (
|
||||
mInitialSize = 1 << 4
|
||||
mOverflowThreshold = 1 << 5
|
||||
mOverflowGrowThreshold = 1 << 7
|
||||
)
|
||||
|
||||
type mBucket struct {
|
||||
mu sync.Mutex
|
||||
node []*Node
|
||||
frozen bool
|
||||
}
|
||||
|
||||
func (b *mBucket) freeze() []*Node {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
if !b.frozen {
|
||||
b.frozen = true
|
||||
}
|
||||
return b.node
|
||||
}
|
||||
|
||||
func (b *mBucket) get(r *Cache, h *mNode, hash uint32, ns, key uint64, noset bool) (done, added bool, n *Node) {
|
||||
b.mu.Lock()
|
||||
|
||||
if b.frozen {
|
||||
b.mu.Unlock()
|
||||
return
|
||||
}
|
||||
|
||||
// Scan the node.
|
||||
for _, n := range b.node {
|
||||
if n.hash == hash && n.ns == ns && n.key == key {
|
||||
atomic.AddInt32(&n.ref, 1)
|
||||
b.mu.Unlock()
|
||||
return true, false, n
|
||||
}
|
||||
}
|
||||
|
||||
// Get only.
|
||||
if noset {
|
||||
b.mu.Unlock()
|
||||
return true, false, nil
|
||||
}
|
||||
|
||||
// Create node.
|
||||
n = &Node{
|
||||
r: r,
|
||||
hash: hash,
|
||||
ns: ns,
|
||||
key: key,
|
||||
ref: 1,
|
||||
}
|
||||
// Add node to bucket.
|
||||
b.node = append(b.node, n)
|
||||
bLen := len(b.node)
|
||||
b.mu.Unlock()
|
||||
|
||||
// Update counter.
|
||||
grow := atomic.AddInt32(&r.nodes, 1) >= h.growThreshold
|
||||
if bLen > mOverflowThreshold {
|
||||
grow = grow || atomic.AddInt32(&h.overflow, 1) >= mOverflowGrowThreshold
|
||||
}
|
||||
|
||||
// Grow.
|
||||
if grow && atomic.CompareAndSwapInt32(&h.resizeInProgess, 0, 1) {
|
||||
nhLen := len(h.buckets) << 1
|
||||
nh := &mNode{
|
||||
buckets: make([]unsafe.Pointer, nhLen),
|
||||
mask: uint32(nhLen) - 1,
|
||||
pred: unsafe.Pointer(h),
|
||||
growThreshold: int32(nhLen * mOverflowThreshold),
|
||||
shrinkThreshold: int32(nhLen >> 1),
|
||||
}
|
||||
ok := atomic.CompareAndSwapPointer(&r.mHead, unsafe.Pointer(h), unsafe.Pointer(nh))
|
||||
if !ok {
|
||||
panic("BUG: failed swapping head")
|
||||
}
|
||||
go nh.initBuckets()
|
||||
}
|
||||
|
||||
return true, true, n
|
||||
}
|
||||
|
||||
func (b *mBucket) delete(r *Cache, h *mNode, hash uint32, ns, key uint64) (done, deleted bool) {
|
||||
b.mu.Lock()
|
||||
|
||||
if b.frozen {
|
||||
b.mu.Unlock()
|
||||
return
|
||||
}
|
||||
|
||||
// Scan the node.
|
||||
var (
|
||||
n *Node
|
||||
bLen int
|
||||
)
|
||||
for i := range b.node {
|
||||
n = b.node[i]
|
||||
if n.ns == ns && n.key == key {
|
||||
if atomic.LoadInt32(&n.ref) == 0 {
|
||||
deleted = true
|
||||
|
||||
// Call releaser.
|
||||
if n.value != nil {
|
||||
if r, ok := n.value.(util.Releaser); ok {
|
||||
r.Release()
|
||||
}
|
||||
n.value = nil
|
||||
}
|
||||
|
||||
// Remove node from bucket.
|
||||
b.node = append(b.node[:i], b.node[i+1:]...)
|
||||
bLen = len(b.node)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
b.mu.Unlock()
|
||||
|
||||
if deleted {
|
||||
// Call OnDel.
|
||||
for _, f := range n.onDel {
|
||||
f()
|
||||
}
|
||||
|
||||
// Update counter.
|
||||
atomic.AddInt32(&r.size, int32(n.size)*-1)
|
||||
shrink := atomic.AddInt32(&r.nodes, -1) < h.shrinkThreshold
|
||||
if bLen >= mOverflowThreshold {
|
||||
atomic.AddInt32(&h.overflow, -1)
|
||||
}
|
||||
|
||||
// Shrink.
|
||||
if shrink && len(h.buckets) > mInitialSize && atomic.CompareAndSwapInt32(&h.resizeInProgess, 0, 1) {
|
||||
nhLen := len(h.buckets) >> 1
|
||||
nh := &mNode{
|
||||
buckets: make([]unsafe.Pointer, nhLen),
|
||||
mask: uint32(nhLen) - 1,
|
||||
pred: unsafe.Pointer(h),
|
||||
growThreshold: int32(nhLen * mOverflowThreshold),
|
||||
shrinkThreshold: int32(nhLen >> 1),
|
||||
}
|
||||
ok := atomic.CompareAndSwapPointer(&r.mHead, unsafe.Pointer(h), unsafe.Pointer(nh))
|
||||
if !ok {
|
||||
panic("BUG: failed swapping head")
|
||||
}
|
||||
go nh.initBuckets()
|
||||
}
|
||||
}
|
||||
|
||||
return true, deleted
|
||||
}
|
||||
|
||||
type mNode struct {
|
||||
buckets []unsafe.Pointer // []*mBucket
|
||||
mask uint32
|
||||
pred unsafe.Pointer // *mNode
|
||||
resizeInProgess int32
|
||||
|
||||
overflow int32
|
||||
growThreshold int32
|
||||
shrinkThreshold int32
|
||||
}
|
||||
|
||||
func (n *mNode) initBucket(i uint32) *mBucket {
|
||||
if b := (*mBucket)(atomic.LoadPointer(&n.buckets[i])); b != nil {
|
||||
return b
|
||||
}
|
||||
|
||||
p := (*mNode)(atomic.LoadPointer(&n.pred))
|
||||
if p != nil {
|
||||
var node []*Node
|
||||
if n.mask > p.mask {
|
||||
// Grow.
|
||||
pb := (*mBucket)(atomic.LoadPointer(&p.buckets[i&p.mask]))
|
||||
if pb == nil {
|
||||
pb = p.initBucket(i & p.mask)
|
||||
}
|
||||
m := pb.freeze()
|
||||
// Split nodes.
|
||||
for _, x := range m {
|
||||
if x.hash&n.mask == i {
|
||||
node = append(node, x)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Shrink.
|
||||
pb0 := (*mBucket)(atomic.LoadPointer(&p.buckets[i]))
|
||||
if pb0 == nil {
|
||||
pb0 = p.initBucket(i)
|
||||
}
|
||||
pb1 := (*mBucket)(atomic.LoadPointer(&p.buckets[i+uint32(len(n.buckets))]))
|
||||
if pb1 == nil {
|
||||
pb1 = p.initBucket(i + uint32(len(n.buckets)))
|
||||
}
|
||||
m0 := pb0.freeze()
|
||||
m1 := pb1.freeze()
|
||||
// Merge nodes.
|
||||
node = make([]*Node, 0, len(m0)+len(m1))
|
||||
node = append(node, m0...)
|
||||
node = append(node, m1...)
|
||||
}
|
||||
b := &mBucket{node: node}
|
||||
if atomic.CompareAndSwapPointer(&n.buckets[i], nil, unsafe.Pointer(b)) {
|
||||
if len(node) > mOverflowThreshold {
|
||||
atomic.AddInt32(&n.overflow, int32(len(node)-mOverflowThreshold))
|
||||
}
|
||||
return b
|
||||
}
|
||||
}
|
||||
|
||||
return (*mBucket)(atomic.LoadPointer(&n.buckets[i]))
|
||||
}
|
||||
|
||||
func (n *mNode) initBuckets() {
|
||||
for i := range n.buckets {
|
||||
n.initBucket(uint32(i))
|
||||
}
|
||||
atomic.StorePointer(&n.pred, nil)
|
||||
}
|
||||
|
||||
// Cache is a 'cache map'.
|
||||
type Cache struct {
|
||||
mu sync.RWMutex
|
||||
mHead unsafe.Pointer // *mNode
|
||||
nodes int32
|
||||
size int32
|
||||
cacher Cacher
|
||||
closed bool
|
||||
}
|
||||
|
||||
// NewCache creates a new 'cache map'. The cacher is optional and
|
||||
// may be nil.
|
||||
func NewCache(cacher Cacher) *Cache {
|
||||
h := &mNode{
|
||||
buckets: make([]unsafe.Pointer, mInitialSize),
|
||||
mask: mInitialSize - 1,
|
||||
growThreshold: int32(mInitialSize * mOverflowThreshold),
|
||||
shrinkThreshold: 0,
|
||||
}
|
||||
for i := range h.buckets {
|
||||
h.buckets[i] = unsafe.Pointer(&mBucket{})
|
||||
}
|
||||
r := &Cache{
|
||||
mHead: unsafe.Pointer(h),
|
||||
cacher: cacher,
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *Cache) getBucket(hash uint32) (*mNode, *mBucket) {
|
||||
h := (*mNode)(atomic.LoadPointer(&r.mHead))
|
||||
i := hash & h.mask
|
||||
b := (*mBucket)(atomic.LoadPointer(&h.buckets[i]))
|
||||
if b == nil {
|
||||
b = h.initBucket(i)
|
||||
}
|
||||
return h, b
|
||||
}
|
||||
|
||||
func (r *Cache) delete(n *Node) bool {
|
||||
for {
|
||||
h, b := r.getBucket(n.hash)
|
||||
done, deleted := b.delete(r, h, n.hash, n.ns, n.key)
|
||||
if done {
|
||||
return deleted
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Nodes returns number of 'cache node' in the map.
|
||||
func (r *Cache) Nodes() int {
|
||||
return int(atomic.LoadInt32(&r.nodes))
|
||||
}
|
||||
|
||||
// Size returns sums of 'cache node' size in the map.
|
||||
func (r *Cache) Size() int {
|
||||
return int(atomic.LoadInt32(&r.size))
|
||||
}
|
||||
|
||||
// Capacity returns cache capacity.
|
||||
func (r *Cache) Capacity() int {
|
||||
if r.cacher == nil {
|
||||
return 0
|
||||
}
|
||||
return r.cacher.Capacity()
|
||||
}
|
||||
|
||||
// SetCapacity sets cache capacity.
|
||||
func (r *Cache) SetCapacity(capacity int) {
|
||||
if r.cacher != nil {
|
||||
r.cacher.SetCapacity(capacity)
|
||||
}
|
||||
}
|
||||
|
||||
// Get gets 'cache node' with the given namespace and key.
|
||||
// If cache node is not found and setFunc is not nil, Get will atomically creates
|
||||
// the 'cache node' by calling setFunc. Otherwise Get will returns nil.
|
||||
//
|
||||
// The returned 'cache handle' should be released after use by calling Release
|
||||
// method.
|
||||
func (r *Cache) Get(ns, key uint64, setFunc func() (size int, value Value)) *Handle {
|
||||
r.mu.RLock()
|
||||
defer r.mu.RUnlock()
|
||||
if r.closed {
|
||||
return nil
|
||||
}
|
||||
|
||||
hash := murmur32(ns, key, 0xf00)
|
||||
for {
|
||||
h, b := r.getBucket(hash)
|
||||
done, _, n := b.get(r, h, hash, ns, key, setFunc == nil)
|
||||
if done {
|
||||
if n != nil {
|
||||
n.mu.Lock()
|
||||
if n.value == nil {
|
||||
if setFunc == nil {
|
||||
n.mu.Unlock()
|
||||
n.unref()
|
||||
return nil
|
||||
}
|
||||
|
||||
n.size, n.value = setFunc()
|
||||
if n.value == nil {
|
||||
n.size = 0
|
||||
n.mu.Unlock()
|
||||
n.unref()
|
||||
return nil
|
||||
}
|
||||
atomic.AddInt32(&r.size, int32(n.size))
|
||||
}
|
||||
n.mu.Unlock()
|
||||
if r.cacher != nil {
|
||||
r.cacher.Promote(n)
|
||||
}
|
||||
return &Handle{unsafe.Pointer(n)}
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Delete removes and ban 'cache node' with the given namespace and key.
|
||||
// A banned 'cache node' will never inserted into the 'cache tree'. Ban
|
||||
// only attributed to the particular 'cache node', so when a 'cache node'
|
||||
// is recreated it will not be banned.
|
||||
//
|
||||
// If onDel is not nil, then it will be executed if such 'cache node'
|
||||
// doesn't exist or once the 'cache node' is released.
|
||||
//
|
||||
// Delete return true is such 'cache node' exist.
|
||||
func (r *Cache) Delete(ns, key uint64, onDel func()) bool {
|
||||
r.mu.RLock()
|
||||
defer r.mu.RUnlock()
|
||||
if r.closed {
|
||||
return false
|
||||
}
|
||||
|
||||
hash := murmur32(ns, key, 0xf00)
|
||||
for {
|
||||
h, b := r.getBucket(hash)
|
||||
done, _, n := b.get(r, h, hash, ns, key, true)
|
||||
if done {
|
||||
if n != nil {
|
||||
if onDel != nil {
|
||||
n.mu.Lock()
|
||||
n.onDel = append(n.onDel, onDel)
|
||||
n.mu.Unlock()
|
||||
}
|
||||
if r.cacher != nil {
|
||||
r.cacher.Ban(n)
|
||||
}
|
||||
n.unref()
|
||||
return true
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if onDel != nil {
|
||||
onDel()
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// Evict evicts 'cache node' with the given namespace and key. This will
|
||||
// simply call Cacher.Evict.
|
||||
//
|
||||
// Evict return true is such 'cache node' exist.
|
||||
func (r *Cache) Evict(ns, key uint64) bool {
|
||||
r.mu.RLock()
|
||||
defer r.mu.RUnlock()
|
||||
if r.closed {
|
||||
return false
|
||||
}
|
||||
|
||||
hash := murmur32(ns, key, 0xf00)
|
||||
for {
|
||||
h, b := r.getBucket(hash)
|
||||
done, _, n := b.get(r, h, hash, ns, key, true)
|
||||
if done {
|
||||
if n != nil {
|
||||
if r.cacher != nil {
|
||||
r.cacher.Evict(n)
|
||||
}
|
||||
n.unref()
|
||||
return true
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// EvictNS evicts 'cache node' with the given namespace. This will
|
||||
// simply call Cacher.EvictNS.
|
||||
func (r *Cache) EvictNS(ns uint64) {
|
||||
r.mu.RLock()
|
||||
defer r.mu.RUnlock()
|
||||
if r.closed {
|
||||
return
|
||||
}
|
||||
|
||||
if r.cacher != nil {
|
||||
r.cacher.EvictNS(ns)
|
||||
}
|
||||
}
|
||||
|
||||
// EvictAll evicts all 'cache node'. This will simply call Cacher.EvictAll.
|
||||
func (r *Cache) EvictAll() {
|
||||
r.mu.RLock()
|
||||
defer r.mu.RUnlock()
|
||||
if r.closed {
|
||||
return
|
||||
}
|
||||
|
||||
if r.cacher != nil {
|
||||
r.cacher.EvictAll()
|
||||
}
|
||||
}
|
||||
|
||||
// Close closes the 'cache map' and releases all 'cache node'.
|
||||
func (r *Cache) Close() error {
|
||||
r.mu.Lock()
|
||||
if !r.closed {
|
||||
r.closed = true
|
||||
|
||||
if r.cacher != nil {
|
||||
if err := r.cacher.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
h := (*mNode)(r.mHead)
|
||||
h.initBuckets()
|
||||
|
||||
for i := range h.buckets {
|
||||
b := (*mBucket)(h.buckets[i])
|
||||
for _, n := range b.node {
|
||||
// Call releaser.
|
||||
if n.value != nil {
|
||||
if r, ok := n.value.(util.Releaser); ok {
|
||||
r.Release()
|
||||
}
|
||||
n.value = nil
|
||||
}
|
||||
|
||||
// Call OnDel.
|
||||
for _, f := range n.onDel {
|
||||
f()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
r.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Node is a 'cache node'.
|
||||
type Node struct {
|
||||
r *Cache
|
||||
|
||||
hash uint32
|
||||
ns, key uint64
|
||||
|
||||
mu sync.Mutex
|
||||
size int
|
||||
value Value
|
||||
|
||||
ref int32
|
||||
onDel []func()
|
||||
|
||||
CacheData unsafe.Pointer
|
||||
}
|
||||
|
||||
// NS returns this 'cache node' namespace.
|
||||
func (n *Node) NS() uint64 {
|
||||
return n.ns
|
||||
}
|
||||
|
||||
// Key returns this 'cache node' key.
|
||||
func (n *Node) Key() uint64 {
|
||||
return n.key
|
||||
}
|
||||
|
||||
// Size returns this 'cache node' size.
|
||||
func (n *Node) Size() int {
|
||||
return n.size
|
||||
}
|
||||
|
||||
// Value returns this 'cache node' value.
|
||||
func (n *Node) Value() Value {
|
||||
return n.value
|
||||
}
|
||||
|
||||
// Ref returns this 'cache node' ref counter.
|
||||
func (n *Node) Ref() int32 {
|
||||
return atomic.LoadInt32(&n.ref)
|
||||
}
|
||||
|
||||
// GetHandle returns an handle for this 'cache node'.
|
||||
func (n *Node) GetHandle() *Handle {
|
||||
if atomic.AddInt32(&n.ref, 1) <= 1 {
|
||||
panic("BUG: Node.GetHandle on zero ref")
|
||||
}
|
||||
return &Handle{unsafe.Pointer(n)}
|
||||
}
|
||||
|
||||
func (n *Node) unref() {
|
||||
if atomic.AddInt32(&n.ref, -1) == 0 {
|
||||
n.r.delete(n)
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Node) unrefLocked() {
|
||||
if atomic.AddInt32(&n.ref, -1) == 0 {
|
||||
n.r.mu.RLock()
|
||||
if !n.r.closed {
|
||||
n.r.delete(n)
|
||||
}
|
||||
n.r.mu.RUnlock()
|
||||
}
|
||||
}
|
||||
|
||||
type Handle struct {
|
||||
n unsafe.Pointer // *Node
|
||||
}
|
||||
|
||||
func (h *Handle) Value() Value {
|
||||
n := (*Node)(atomic.LoadPointer(&h.n))
|
||||
if n != nil {
|
||||
return n.value
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *Handle) Release() {
|
||||
nPtr := atomic.LoadPointer(&h.n)
|
||||
if nPtr != nil && atomic.CompareAndSwapPointer(&h.n, nPtr, nil) {
|
||||
n := (*Node)(nPtr)
|
||||
n.unrefLocked()
|
||||
}
|
||||
}
|
||||
|
||||
func murmur32(ns, key uint64, seed uint32) uint32 {
|
||||
const (
|
||||
m = uint32(0x5bd1e995)
|
||||
r = 24
|
||||
)
|
||||
|
||||
k1 := uint32(ns >> 32)
|
||||
k2 := uint32(ns)
|
||||
k3 := uint32(key >> 32)
|
||||
k4 := uint32(key)
|
||||
|
||||
k1 *= m
|
||||
k1 ^= k1 >> r
|
||||
k1 *= m
|
||||
|
||||
k2 *= m
|
||||
k2 ^= k2 >> r
|
||||
k2 *= m
|
||||
|
||||
k3 *= m
|
||||
k3 ^= k3 >> r
|
||||
k3 *= m
|
||||
|
||||
k4 *= m
|
||||
k4 ^= k4 >> r
|
||||
k4 *= m
|
||||
|
||||
h := seed
|
||||
|
||||
h *= m
|
||||
h ^= k1
|
||||
h *= m
|
||||
h ^= k2
|
||||
h *= m
|
||||
h ^= k3
|
||||
h *= m
|
||||
h ^= k4
|
||||
|
||||
h ^= h >> 13
|
||||
h *= m
|
||||
h ^= h >> 15
|
||||
|
||||
return h
|
||||
}
|
||||
195
Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/cache/lru.go
generated
vendored
Normal file
195
Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/cache/lru.go
generated
vendored
Normal file
@@ -0,0 +1,195 @@
|
||||
// Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com>
|
||||
// All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package cache
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type lruNode struct {
|
||||
n *Node
|
||||
h *Handle
|
||||
ban bool
|
||||
|
||||
next, prev *lruNode
|
||||
}
|
||||
|
||||
func (n *lruNode) insert(at *lruNode) {
|
||||
x := at.next
|
||||
at.next = n
|
||||
n.prev = at
|
||||
n.next = x
|
||||
x.prev = n
|
||||
}
|
||||
|
||||
func (n *lruNode) remove() {
|
||||
if n.prev != nil {
|
||||
n.prev.next = n.next
|
||||
n.next.prev = n.prev
|
||||
n.prev = nil
|
||||
n.next = nil
|
||||
} else {
|
||||
panic("BUG: removing removed node")
|
||||
}
|
||||
}
|
||||
|
||||
type lru struct {
|
||||
mu sync.Mutex
|
||||
capacity int
|
||||
used int
|
||||
recent lruNode
|
||||
}
|
||||
|
||||
func (r *lru) reset() {
|
||||
r.recent.next = &r.recent
|
||||
r.recent.prev = &r.recent
|
||||
r.used = 0
|
||||
}
|
||||
|
||||
func (r *lru) Capacity() int {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
return r.capacity
|
||||
}
|
||||
|
||||
func (r *lru) SetCapacity(capacity int) {
|
||||
var evicted []*lruNode
|
||||
|
||||
r.mu.Lock()
|
||||
r.capacity = capacity
|
||||
for r.used > r.capacity {
|
||||
rn := r.recent.prev
|
||||
if rn == nil {
|
||||
panic("BUG: invalid LRU used or capacity counter")
|
||||
}
|
||||
rn.remove()
|
||||
rn.n.CacheData = nil
|
||||
r.used -= rn.n.Size()
|
||||
evicted = append(evicted, rn)
|
||||
}
|
||||
r.mu.Unlock()
|
||||
|
||||
for _, rn := range evicted {
|
||||
rn.h.Release()
|
||||
}
|
||||
}
|
||||
|
||||
func (r *lru) Promote(n *Node) {
|
||||
var evicted []*lruNode
|
||||
|
||||
r.mu.Lock()
|
||||
if n.CacheData == nil {
|
||||
if n.Size() <= r.capacity {
|
||||
rn := &lruNode{n: n, h: n.GetHandle()}
|
||||
rn.insert(&r.recent)
|
||||
n.CacheData = unsafe.Pointer(rn)
|
||||
r.used += n.Size()
|
||||
|
||||
for r.used > r.capacity {
|
||||
rn := r.recent.prev
|
||||
if rn == nil {
|
||||
panic("BUG: invalid LRU used or capacity counter")
|
||||
}
|
||||
rn.remove()
|
||||
rn.n.CacheData = nil
|
||||
r.used -= rn.n.Size()
|
||||
evicted = append(evicted, rn)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
rn := (*lruNode)(n.CacheData)
|
||||
if !rn.ban {
|
||||
rn.remove()
|
||||
rn.insert(&r.recent)
|
||||
}
|
||||
}
|
||||
r.mu.Unlock()
|
||||
|
||||
for _, rn := range evicted {
|
||||
rn.h.Release()
|
||||
}
|
||||
}
|
||||
|
||||
func (r *lru) Ban(n *Node) {
|
||||
r.mu.Lock()
|
||||
if n.CacheData == nil {
|
||||
n.CacheData = unsafe.Pointer(&lruNode{n: n, ban: true})
|
||||
} else {
|
||||
rn := (*lruNode)(n.CacheData)
|
||||
if !rn.ban {
|
||||
rn.remove()
|
||||
rn.ban = true
|
||||
r.used -= rn.n.Size()
|
||||
r.mu.Unlock()
|
||||
|
||||
rn.h.Release()
|
||||
rn.h = nil
|
||||
return
|
||||
}
|
||||
}
|
||||
r.mu.Unlock()
|
||||
}
|
||||
|
||||
func (r *lru) Evict(n *Node) {
|
||||
r.mu.Lock()
|
||||
rn := (*lruNode)(n.CacheData)
|
||||
if rn == nil || rn.ban {
|
||||
r.mu.Unlock()
|
||||
return
|
||||
}
|
||||
n.CacheData = nil
|
||||
r.mu.Unlock()
|
||||
|
||||
rn.h.Release()
|
||||
}
|
||||
|
||||
func (r *lru) EvictNS(ns uint64) {
|
||||
var evicted []*lruNode
|
||||
|
||||
r.mu.Lock()
|
||||
for e := r.recent.prev; e != &r.recent; {
|
||||
rn := e
|
||||
e = e.prev
|
||||
if rn.n.NS() == ns {
|
||||
rn.remove()
|
||||
rn.n.CacheData = nil
|
||||
r.used -= rn.n.Size()
|
||||
evicted = append(evicted, rn)
|
||||
}
|
||||
}
|
||||
r.mu.Unlock()
|
||||
|
||||
for _, rn := range evicted {
|
||||
rn.h.Release()
|
||||
}
|
||||
}
|
||||
|
||||
func (r *lru) EvictAll() {
|
||||
r.mu.Lock()
|
||||
back := r.recent.prev
|
||||
for rn := back; rn != &r.recent; rn = rn.prev {
|
||||
rn.n.CacheData = nil
|
||||
}
|
||||
r.reset()
|
||||
r.mu.Unlock()
|
||||
|
||||
for rn := back; rn != &r.recent; rn = rn.prev {
|
||||
rn.h.Release()
|
||||
}
|
||||
}
|
||||
|
||||
func (r *lru) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewLRU create a new LRU-cache.
|
||||
func NewLRU(capacity int) Cacher {
|
||||
r := &lru{capacity: capacity}
|
||||
r.reset()
|
||||
return r
|
||||
}
|
||||
75
Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer.go
generated
vendored
Normal file
75
Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer.go
generated
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
// Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com>
|
||||
// All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package leveldb
|
||||
|
||||
import "github.com/syndtr/goleveldb/leveldb/comparer"
|
||||
|
||||
type iComparer struct {
|
||||
ucmp comparer.Comparer
|
||||
}
|
||||
|
||||
func (icmp *iComparer) uName() string {
|
||||
return icmp.ucmp.Name()
|
||||
}
|
||||
|
||||
func (icmp *iComparer) uCompare(a, b []byte) int {
|
||||
return icmp.ucmp.Compare(a, b)
|
||||
}
|
||||
|
||||
func (icmp *iComparer) uSeparator(dst, a, b []byte) []byte {
|
||||
return icmp.ucmp.Separator(dst, a, b)
|
||||
}
|
||||
|
||||
func (icmp *iComparer) uSuccessor(dst, b []byte) []byte {
|
||||
return icmp.ucmp.Successor(dst, b)
|
||||
}
|
||||
|
||||
func (icmp *iComparer) Name() string {
|
||||
return icmp.uName()
|
||||
}
|
||||
|
||||
func (icmp *iComparer) Compare(a, b []byte) int {
|
||||
x := icmp.ucmp.Compare(iKey(a).ukey(), iKey(b).ukey())
|
||||
if x == 0 {
|
||||
if m, n := iKey(a).num(), iKey(b).num(); m > n {
|
||||
x = -1
|
||||
} else if m < n {
|
||||
x = 1
|
||||
}
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
func (icmp *iComparer) Separator(dst, a, b []byte) []byte {
|
||||
ua, ub := iKey(a).ukey(), iKey(b).ukey()
|
||||
dst = icmp.ucmp.Separator(dst, ua, ub)
|
||||
if dst == nil {
|
||||
return nil
|
||||
}
|
||||
if len(dst) < len(ua) && icmp.uCompare(ua, dst) < 0 {
|
||||
dst = append(dst, kMaxNumBytes...)
|
||||
} else {
|
||||
// Did not close possibilities that n maybe longer than len(ub).
|
||||
dst = append(dst, a[len(a)-8:]...)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
func (icmp *iComparer) Successor(dst, b []byte) []byte {
|
||||
ub := iKey(b).ukey()
|
||||
dst = icmp.ucmp.Successor(dst, ub)
|
||||
if dst == nil {
|
||||
return nil
|
||||
}
|
||||
if len(dst) < len(ub) && icmp.uCompare(ub, dst) < 0 {
|
||||
dst = append(dst, kMaxNumBytes...)
|
||||
} else {
|
||||
// Did not close possibilities that n maybe longer than len(ub).
|
||||
dst = append(dst, b[len(b)-8:]...)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
51
Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer/bytes_comparer.go
generated
vendored
Normal file
51
Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer/bytes_comparer.go
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com>
|
||||
// All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package comparer
|
||||
|
||||
import "bytes"
|
||||
|
||||
type bytesComparer struct{}
|
||||
|
||||
func (bytesComparer) Compare(a, b []byte) int {
|
||||
return bytes.Compare(a, b)
|
||||
}
|
||||
|
||||
func (bytesComparer) Name() string {
|
||||
return "leveldb.BytewiseComparator"
|
||||
}
|
||||
|
||||
func (bytesComparer) Separator(dst, a, b []byte) []byte {
|
||||
i, n := 0, len(a)
|
||||
if n > len(b) {
|
||||
n = len(b)
|
||||
}
|
||||
for ; i < n && a[i] == b[i]; i++ {
|
||||
}
|
||||
if i >= n {
|
||||
// Do not shorten if one string is a prefix of the other
|
||||
} else if c := a[i]; c < 0xff && c+1 < b[i] {
|
||||
dst = append(dst, a[:i+1]...)
|
||||
dst[i]++
|
||||
return dst
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (bytesComparer) Successor(dst, b []byte) []byte {
|
||||
for i, c := range b {
|
||||
if c != 0xff {
|
||||
dst = append(dst, b[:i+1]...)
|
||||
dst[i]++
|
||||
return dst
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DefaultComparer are default implementation of the Comparer interface.
|
||||
// It uses the natural ordering, consistent with bytes.Compare.
|
||||
var DefaultComparer = bytesComparer{}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user