Compare commits
955 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a9f9b0da9d | ||
|
|
a0c99a7dcc | ||
|
|
13556cf129 | ||
|
|
70f89ae65b | ||
|
|
51c7fb1969 | ||
|
|
beb9d966f9 | ||
|
|
416bbe9583 | ||
|
|
66a7dc3a0d | ||
|
|
832c35d4d5 | ||
|
|
689cf2d367 | ||
|
|
bcb8605f84 | ||
|
|
3d9b73c47a | ||
|
|
1f39a763a5 | ||
|
|
a6af561660 | ||
|
|
4a81465b91 | ||
|
|
a3e1b278a1 | ||
|
|
43940f6562 | ||
|
|
e384ff604e | ||
|
|
56d1d67a34 | ||
|
|
a3dd7db4a3 | ||
|
|
589b1a2eaf | ||
|
|
ea3f024b8a | ||
|
|
079cd4e94f | ||
|
|
2fa42f24fd | ||
|
|
49b7cbda72 | ||
|
|
ef63abe9b1 | ||
|
|
a90a5f52dd | ||
|
|
3585b0a139 | ||
|
|
85a9cb260a | ||
|
|
d75f00cc2d | ||
|
|
b3052c425e | ||
|
|
f5dbfe99b1 | ||
|
|
d38d5ecbac | ||
|
|
77d418a36d | ||
|
|
217c8deae5 | ||
|
|
1f1736a79f | ||
|
|
14ae89dbe7 | ||
|
|
f5d3145bea | ||
|
|
fbab898f74 | ||
|
|
1624522761 | ||
|
|
7d268912f1 | ||
|
|
7c916ab91c | ||
|
|
3ddb7438d7 | ||
|
|
3f8d79024b | ||
|
|
2231fcf5b4 | ||
|
|
5011c657b5 | ||
|
|
104626d732 | ||
|
|
73e3ca670d | ||
|
|
60cc9e9a3c | ||
|
|
e8b1e91a1d | ||
|
|
7c3b71d294 | ||
|
|
93dffe1777 | ||
|
|
0d5680e971 | ||
|
|
2c67aa0f41 | ||
|
|
225cf0d010 | ||
|
|
fd519748e9 | ||
|
|
97c514daa5 | ||
|
|
3a62f39044 | ||
|
|
2146b20169 | ||
|
|
0feb5da31e | ||
|
|
5933f9448d | ||
|
|
e311f902ff | ||
|
|
a90351cd2c | ||
|
|
4f8c691f8c | ||
|
|
c49ea491a3 | ||
|
|
2c31fe4614 | ||
|
|
377fe63c60 | ||
|
|
f3edc0d8b7 | ||
|
|
de6ad380f6 | ||
|
|
e5b1688913 | ||
|
|
b64d3ecaed | ||
|
|
216f5afe54 | ||
|
|
23ca1f859e | ||
|
|
bfdcdbb2f3 | ||
|
|
aec7019728 | ||
|
|
97bcb59bee | ||
|
|
6fcbf219da | ||
|
|
2cdcf62b48 | ||
|
|
7e01213bf2 | ||
|
|
99bce9d877 | ||
|
|
b1c26a56b3 | ||
|
|
6410a25cef | ||
|
|
9fc97cbbf7 | ||
|
|
d9bd6e6b5b | ||
|
|
c67c55e0fc | ||
|
|
50c163ae6c | ||
|
|
4e86674a3a | ||
|
|
99a4a91488 | ||
|
|
ce1361f2fe | ||
|
|
64216b34a4 | ||
|
|
43da879ea2 | ||
|
|
e4da8d74d8 | ||
|
|
638c3d25b0 | ||
|
|
b10710d4a5 | ||
|
|
a33a1ac958 | ||
|
|
dbd773e89e | ||
|
|
6b9a65972c | ||
|
|
3194ffdab8 | ||
|
|
d6d5d4ebd0 | ||
|
|
4c2f6de8e4 | ||
|
|
ac198068ab | ||
|
|
4581bdd929 | ||
|
|
9bcf072795 | ||
|
|
f9dc5815c4 | ||
|
|
139dcf1246 | ||
|
|
76e778fe2c | ||
|
|
160659f683 | ||
|
|
2d3ac2b1ec | ||
|
|
946b370966 | ||
|
|
24dcf3cf6a | ||
|
|
b8612e005a | ||
|
|
151a8ca0cc | ||
|
|
7f0d9ad644 | ||
|
|
03698121ed | ||
|
|
976514d39a | ||
|
|
76bd3de2fd | ||
|
|
05012bb0df | ||
|
|
5b4b349776 | ||
|
|
09cb2a37dd | ||
|
|
dcfeb95e98 | ||
|
|
b857353fc9 | ||
|
|
847c01f406 | ||
|
|
fdfc951744 | ||
|
|
5198df3aa0 | ||
|
|
4ff3757f86 | ||
|
|
54b1071556 | ||
|
|
5bdfd55ace | ||
|
|
24df15dab7 | ||
|
|
5bcccfc305 | ||
|
|
87ee0c395e | ||
|
|
07e4958b19 | ||
|
|
d4c506e453 | ||
|
|
c9695a0a59 | ||
|
|
7a5d11f8a7 | ||
|
|
68b98a8003 | ||
|
|
7b9a50721d | ||
|
|
216e785ca9 | ||
|
|
0c4c084bed | ||
|
|
932c382737 | ||
|
|
59b461ac0e | ||
|
|
9f05a7ac7b | ||
|
|
1299592405 | ||
|
|
d82126b651 | ||
|
|
48ee440983 | ||
|
|
64f2dc778a | ||
|
|
ac2ad9690d | ||
|
|
87fcff9fc3 | ||
|
|
3c540f0d33 | ||
|
|
e4ecbc2b10 | ||
|
|
fd050fca7c | ||
|
|
590a8b0315 | ||
|
|
2b54199271 | ||
|
|
0d189165a8 | ||
|
|
6ad577d32b | ||
|
|
5a7784a0e6 | ||
|
|
1416c90932 | ||
|
|
8004e6f31c | ||
|
|
8efe4bfc2e | ||
|
|
7eee9eb312 | ||
|
|
1b94de8e58 | ||
|
|
1d4bf06fe7 | ||
|
|
33b54807a1 | ||
|
|
468ddd2373 | ||
|
|
c442ef346e | ||
|
|
698b2135ee | ||
|
|
63f6c8f27c | ||
|
|
7b0b5c9d97 | ||
|
|
6be614ba84 | ||
|
|
170a6f0563 | ||
|
|
8dff05a897 | ||
|
|
9cbbb7eddf | ||
|
|
18eca40af3 | ||
|
|
69975763d2 | ||
|
|
1572e91b5f | ||
|
|
3dac92f345 | ||
|
|
85428c49bb | ||
|
|
428916a64d | ||
|
|
ba9daf849e | ||
|
|
840be97e40 | ||
|
|
c245365484 | ||
|
|
056a6ee765 | ||
|
|
9038a503eb | ||
|
|
d27cc62458 | ||
|
|
ad2ebd2f3d | ||
|
|
a08f01fa83 | ||
|
|
dd2c211e62 | ||
|
|
d5367a219d | ||
|
|
878ce1e6b2 | ||
|
|
4cd03d8c31 | ||
|
|
72ed49af5f | ||
|
|
1fabdcc43c | ||
|
|
20b989e048 | ||
|
|
cac37e298c | ||
|
|
f0320f5652 | ||
|
|
46d017b197 | ||
|
|
4e5c7bdeb3 | ||
|
|
e6a0f6e428 | ||
|
|
14530b2607 | ||
|
|
c0433d5e4c | ||
|
|
879cbb4575 | ||
|
|
261512606d | ||
|
|
d7984ef775 | ||
|
|
aaee63af82 | ||
|
|
3891a8946b | ||
|
|
aae29c0ee2 | ||
|
|
9ab78d412c | ||
|
|
00d4a26eef | ||
|
|
665fb66686 | ||
|
|
e103e34f1d | ||
|
|
d8a6eb5641 | ||
|
|
feef9d64a4 | ||
|
|
fa2653c8e1 | ||
|
|
9a4a513b5e | ||
|
|
516062ae1f | ||
|
|
901bdfed40 | ||
|
|
744276dd50 | ||
|
|
42e52f544d | ||
|
|
7c1eb86c7d | ||
|
|
76e46d0158 | ||
|
|
aec8d1e6be | ||
|
|
f499b328c4 | ||
|
|
75686e0e49 | ||
|
|
b14156aa63 | ||
|
|
aec8852af7 | ||
|
|
401c2e2f2e | ||
|
|
af9deed135 | ||
|
|
90528c23d9 | ||
|
|
a57a472ab8 | ||
|
|
9fb9da1b6c | ||
|
|
60732c96ef | ||
|
|
8396f1bd42 | ||
|
|
bf517899a7 | ||
|
|
e6b6af62dd | ||
|
|
44543ebe63 | ||
|
|
89857378ce | ||
|
|
c45659863d | ||
|
|
5f7b2ea81b | ||
|
|
7b187deb19 | ||
|
|
84d0699761 | ||
|
|
b44f0e1a00 | ||
|
|
d0d654e218 | ||
|
|
acb7b4a09a | ||
|
|
b4c3a791aa | ||
|
|
13a4a80b38 | ||
|
|
803632f8f3 | ||
|
|
df63bfafef | ||
|
|
f81e289a1b | ||
|
|
99a727600b | ||
|
|
8d18ad2f6f | ||
|
|
116a449d89 | ||
|
|
b5ab0698d6 | ||
|
|
032c637c10 | ||
|
|
3919c80505 | ||
|
|
d5a1779465 | ||
|
|
174105ad02 | ||
|
|
18d5d8f5dd | ||
|
|
edafea6ae6 | ||
|
|
3a6acbcc14 | ||
|
|
866de53978 | ||
|
|
61eda1f441 | ||
|
|
e5c677779b | ||
|
|
5a2d4d888c | ||
|
|
66048e1a70 | ||
|
|
3a476bf60c | ||
|
|
98d47ea428 | ||
|
|
63c42d6602 | ||
|
|
9041f4a056 | ||
|
|
c1705236c7 | ||
|
|
1d65b0d802 | ||
|
|
edef7472d1 | ||
|
|
b5062ae7ee | ||
|
|
d9d995914c | ||
|
|
71b1511db5 | ||
|
|
a22a4db5ce | ||
|
|
552b85d33d | ||
|
|
ad198a714c | ||
|
|
9e35b069a4 | ||
|
|
ae997fffee | ||
|
|
6572847518 | ||
|
|
077be8b496 | ||
|
|
6293614074 | ||
|
|
49b3b7ee83 | ||
|
|
fa2370b32e | ||
|
|
f64f07e7c5 | ||
|
|
fda91d93da | ||
|
|
7127891957 | ||
|
|
5495df7443 | ||
|
|
52dc7b2a96 | ||
|
|
519dba9a69 | ||
|
|
5c54eb30ed | ||
|
|
5232ab0496 | ||
|
|
5f95f4d78e | ||
|
|
1d3deda10c | ||
|
|
af792bc7f2 | ||
|
|
f4317dc26d | ||
|
|
0f5b616fb0 | ||
|
|
2b8de2c404 | ||
|
|
e46459ef21 | ||
|
|
2c8bf4aaa6 | ||
|
|
894554faf6 | ||
|
|
9432f3c94d | ||
|
|
5f27aaa6dd | ||
|
|
8bad56cb46 | ||
|
|
d4720bd721 | ||
|
|
9f129938c9 | ||
|
|
9f578cf0c8 | ||
|
|
0419852598 | ||
|
|
a006caabbc | ||
|
|
99a600753e | ||
|
|
3fbd2c54bc | ||
|
|
cbc3576ee2 | ||
|
|
50b8ab60f2 | ||
|
|
21a09ad3ad | ||
|
|
e0f0b88dec | ||
|
|
6da50d34df | ||
|
|
5a01ffa515 | ||
|
|
6dd454240f | ||
|
|
70aa77f520 | ||
|
|
42e2a0d66e | ||
|
|
e8e073aa97 | ||
|
|
eb14e5a175 | ||
|
|
1b7b664c86 | ||
|
|
68fbf7eebb | ||
|
|
687c1a420a | ||
|
|
b060ce96d9 | ||
|
|
864f15ce4d | ||
|
|
fbb01bd280 | ||
|
|
ac73e70293 | ||
|
|
60325f81d8 | ||
|
|
d48946f9ef | ||
|
|
af02231a7b | ||
|
|
b0140383da | ||
|
|
e33ac50388 | ||
|
|
5939529036 | ||
|
|
c8dcb8474d | ||
|
|
98f59ffed5 | ||
|
|
c61ff917ef | ||
|
|
f3b3e21dea | ||
|
|
fcb0349d56 | ||
|
|
e4f741f006 | ||
|
|
a2ee887c6d | ||
|
|
b4f1b9acf6 | ||
|
|
931eb892d9 | ||
|
|
4d93870fe5 | ||
|
|
5a1d6727e1 | ||
|
|
bc405a6a34 | ||
|
|
6825377380 | ||
|
|
3a26e366d2 | ||
|
|
ff4ad60207 | ||
|
|
ccee2959f7 | ||
|
|
a412b1d682 | ||
|
|
cd64a70c79 | ||
|
|
d06c85ea77 | ||
|
|
b4cb644a05 | ||
|
|
3d118fb580 | ||
|
|
fa02f28dbf | ||
|
|
3d700bb42c | ||
|
|
29f6ae199e | ||
|
|
65239b059f | ||
|
|
1909ee70f8 | ||
|
|
83d1680057 | ||
|
|
ba8f9c9d0a | ||
|
|
7c2e4786ce | ||
|
|
e15a15688b | ||
|
|
f57f49eede | ||
|
|
44e9849ed1 | ||
|
|
ee51a9f9c9 | ||
|
|
51d106cff8 | ||
|
|
c4f1ec1fd6 | ||
|
|
ea371a6f54 | ||
|
|
604967b31e | ||
|
|
3b48b6a792 | ||
|
|
0120e858b7 | ||
|
|
9173130fde | ||
|
|
fe5da43d15 | ||
|
|
bdaeb02863 | ||
|
|
864a86983e | ||
|
|
1b265b213b | ||
|
|
59d19f038a | ||
|
|
38e6da5522 | ||
|
|
bb6fb65392 | ||
|
|
cec8e6d0f7 | ||
|
|
095066b1ce | ||
|
|
d0dfb744b2 | ||
|
|
67e500383e | ||
|
|
2c761cef19 | ||
|
|
065f8f56a2 | ||
|
|
33eea62606 | ||
|
|
fad4241e4e | ||
|
|
76b2b20f7e | ||
|
|
5f58b9b552 | ||
|
|
83da14008f | ||
|
|
af9b17c545 | ||
|
|
2025dd25f6 | ||
|
|
047ef9c2a5 | ||
|
|
eccec4f8f6 | ||
|
|
8be59829d1 | ||
|
|
013710168b | ||
|
|
dc54581700 | ||
|
|
b2d4b8b1da | ||
|
|
c3db595944 | ||
|
|
e19defde36 | ||
|
|
a38c2abae4 | ||
|
|
c66a9a08e4 | ||
|
|
1e72e1b258 | ||
|
|
bbb9af363d | ||
|
|
bbc40fab62 | ||
|
|
6026759406 | ||
|
|
70d24a654b | ||
|
|
1286677352 | ||
|
|
803e5498b0 | ||
|
|
71e26555bd | ||
|
|
391633c072 | ||
|
|
1dd3a0bc57 | ||
|
|
9b75d75724 | ||
|
|
93fd5e4036 | ||
|
|
b29a09ab8e | ||
|
|
d838f15d97 | ||
|
|
a65cec3986 | ||
|
|
97698ae311 | ||
|
|
03268d85c4 | ||
|
|
5f97c6f8f0 | ||
|
|
c358d5d168 | ||
|
|
2f6ee8aee2 | ||
|
|
98de67d573 | ||
|
|
ccceb6d6d2 | ||
|
|
55ac8c83c7 | ||
|
|
a44ad01492 | ||
|
|
67407024a2 | ||
|
|
5dbdd5f8b4 | ||
|
|
dd15f95499 | ||
|
|
ca26583e6b | ||
|
|
c4506cf4f3 | ||
|
|
8265a88c4a | ||
|
|
f2f33b7577 | ||
|
|
d80936bbbb | ||
|
|
da3aa44138 | ||
|
|
33ddb6c246 | ||
|
|
c95a23863a | ||
|
|
38a04ff993 | ||
|
|
d997c49e47 | ||
|
|
ca380ec039 | ||
|
|
93ee515d9d | ||
|
|
fdafc2a16c | ||
|
|
bf214122cd | ||
|
|
15d0bc0900 | ||
|
|
ec9ffbb89a | ||
|
|
c61becc62b | ||
|
|
0cc0a2485c | ||
|
|
ae42c93f9a | ||
|
|
98a2fa8e35 | ||
|
|
068a3afad9 | ||
|
|
16f40c1a15 | ||
|
|
5eb78aad96 | ||
|
|
80f4a008eb | ||
|
|
27cdfb7b84 | ||
|
|
25889b2d7e | ||
|
|
119f84fe11 | ||
|
|
06dba1fa62 | ||
|
|
4d24bf75fd | ||
|
|
d01b8e163d | ||
|
|
316e8f9239 | ||
|
|
9725b829d5 | ||
|
|
2c05caec7f | ||
|
|
626940ceb8 | ||
|
|
e984bfb4c6 | ||
|
|
ccca005969 | ||
|
|
635704b7ef | ||
|
|
8eb86c9ec9 | ||
|
|
c24c99f4ba | ||
|
|
9d5ae75950 | ||
|
|
425d2a2a97 | ||
|
|
23516717e4 | ||
|
|
2f4a729d40 | ||
|
|
e377abcc35 | ||
|
|
c738368846 | ||
|
|
1e97972f78 | ||
|
|
d7775d1e11 | ||
|
|
1fc873d09f | ||
|
|
74e7fac13f | ||
|
|
20f2cf8769 | ||
|
|
c462e0a51c | ||
|
|
8fa5d12fcb | ||
|
|
0c97021565 | ||
|
|
ff47cf77ab | ||
|
|
00093a305d | ||
|
|
3a634c56e3 | ||
|
|
371085546d | ||
|
|
eed15703ed | ||
|
|
4406f07a84 | ||
|
|
4cb4c9fb25 | ||
|
|
cbb5122729 | ||
|
|
e26e8b8829 | ||
|
|
dc0455e217 | ||
|
|
f6ce87c96d | ||
|
|
529633d970 | ||
|
|
d47fc48b32 | ||
|
|
c1b8f83dd4 | ||
|
|
149487ea0f | ||
|
|
f7d09b898a | ||
|
|
f78d2ef166 | ||
|
|
ce9b1320d2 | ||
|
|
4b00203fa5 | ||
|
|
936700bda3 | ||
|
|
4bf1afe300 | ||
|
|
edb11a7eca | ||
|
|
6c7e33fe47 | ||
|
|
ca3ce6da73 | ||
|
|
4778d67005 | ||
|
|
74539659f6 | ||
|
|
a5de4f692b | ||
|
|
bbeff4b8ca | ||
|
|
a33b6eed6d | ||
|
|
085a87060a | ||
|
|
05790ba1cf | ||
|
|
5b1a9f84fd | ||
|
|
d97333255d | ||
|
|
3370e19205 | ||
|
|
086fd70a5f | ||
|
|
84af1cab9b | ||
|
|
8a86e29579 | ||
|
|
1a72f62d7b | ||
|
|
3fe5e9057f | ||
|
|
dda44e31e3 | ||
|
|
9501a583cb | ||
|
|
768e8e363b | ||
|
|
0767523834 | ||
|
|
a1e32b8437 | ||
|
|
b7c9dee033 | ||
|
|
c0a00cd7fd | ||
|
|
713a14a6b5 | ||
|
|
b9dac1f8df | ||
|
|
865d46ae1e | ||
|
|
2c9bb0f973 | ||
|
|
0d2fd0d914 | ||
|
|
694c4bcbb6 | ||
|
|
e6cb7b4764 | ||
|
|
42b0c68eab | ||
|
|
9c530d725f | ||
|
|
ecfc6a3f4a | ||
|
|
720806b661 | ||
|
|
da3724a904 | ||
|
|
f074739e33 | ||
|
|
fc89bde044 | ||
|
|
db9d9d83eb | ||
|
|
d412c1b0eb | ||
|
|
d7f3d7efd2 | ||
|
|
b2c8d5eec7 | ||
|
|
b271217084 | ||
|
|
7c00ccb548 | ||
|
|
6b8e94864a | ||
|
|
7759b05dcb | ||
|
|
3357300362 | ||
|
|
824a4b4808 | ||
|
|
ef5be42c86 | ||
|
|
47b6e78790 | ||
|
|
7a17c3720b | ||
|
|
9fec0faade | ||
|
|
3cb65f0d31 | ||
|
|
9f8a8f3719 | ||
|
|
90097de6c3 | ||
|
|
7556a0f699 | ||
|
|
135e10ba09 | ||
|
|
d8da83b4ff | ||
|
|
a0fed03e10 | ||
|
|
b33db917f5 | ||
|
|
26b66c730e | ||
|
|
d47a18fd09 | ||
|
|
ed950e6c74 | ||
|
|
ba84074468 | ||
|
|
9d9b9d4938 | ||
|
|
b242ead6df | ||
|
|
1c7fbb86c2 | ||
|
|
a949556c4e | ||
|
|
7af97f88b7 | ||
|
|
32d1e50565 | ||
|
|
a2f1cd87f8 | ||
|
|
82e3b9a6e0 | ||
|
|
795acaa6aa | ||
|
|
57141e34bf | ||
|
|
7de0912a97 | ||
|
|
e741e5ebce | ||
|
|
4e2e69bd25 | ||
|
|
d00770d56b | ||
|
|
75e4af9d39 | ||
|
|
34d40e46a5 | ||
|
|
1cb1245d84 | ||
|
|
1387224821 | ||
|
|
6aa54a8e16 | ||
|
|
07cc16ff9c | ||
|
|
3a722ef81b | ||
|
|
75631e0267 | ||
|
|
7c0bfca7a0 | ||
|
|
454499ff60 | ||
|
|
346eda27cc | ||
|
|
f2a4d9b99c | ||
|
|
a74e65200c | ||
|
|
045c26f626 | ||
|
|
664c6191ed | ||
|
|
ac9c37f31b | ||
|
|
06012f8675 | ||
|
|
25fa647a74 | ||
|
|
2ebf70d719 | ||
|
|
a3210d1cf8 | ||
|
|
81ad9255b5 | ||
|
|
e1d98c9e4c | ||
|
|
26cd59cd6f | ||
|
|
e53b62304f | ||
|
|
a7dbafb0e3 | ||
|
|
e449950030 | ||
|
|
cd64da8746 | ||
|
|
47ffa12078 | ||
|
|
f41fc4eb25 | ||
|
|
10572b78f8 | ||
|
|
b4f472c4fa | ||
|
|
b5d0ac4c42 | ||
|
|
0c971d148c | ||
|
|
43d804b998 | ||
|
|
07058b044b | ||
|
|
d7fa9f671e | ||
|
|
ba2f13db63 | ||
|
|
217c7d1140 | ||
|
|
921ad8704e | ||
|
|
00c1586ff8 | ||
|
|
bf03523323 | ||
|
|
5b3a443125 | ||
|
|
924a5df25f | ||
|
|
e85c70223a | ||
|
|
4d32ca19bf | ||
|
|
48a175eff7 | ||
|
|
439f11cc3c | ||
|
|
3aa2fb9928 | ||
|
|
46335b103e | ||
|
|
328883700a | ||
|
|
6b88a665d3 | ||
|
|
12a3b85561 | ||
|
|
8f9a726465 | ||
|
|
cc7aa88b26 | ||
|
|
f9ee9efb97 | ||
|
|
4898f18f89 | ||
|
|
233b9ec4d7 | ||
|
|
7e1c7f54c7 | ||
|
|
ae0d6ab28a | ||
|
|
7c3a46ccea | ||
|
|
0c35d28933 | ||
|
|
533bbf033d | ||
|
|
1821372634 | ||
|
|
5f1f5ea5ab | ||
|
|
4979940def | ||
|
|
81a6c39781 | ||
|
|
a087dbed7f | ||
|
|
bb0ea25090 | ||
|
|
681fbda4b6 | ||
|
|
440905ad14 | ||
|
|
21a3a81c7a | ||
|
|
0cdea5c2f3 | ||
|
|
eb2bd9d203 | ||
|
|
02fe05f346 | ||
|
|
e597a7d94e | ||
|
|
9b56f99326 | ||
|
|
d90d8e9999 | ||
|
|
c5549d2730 | ||
|
|
0d5566e879 | ||
|
|
28548ab347 | ||
|
|
0e002e3693 | ||
|
|
29b3b44fab | ||
|
|
5efce21abc | ||
|
|
f490522082 | ||
|
|
ffc9b3dda7 | ||
|
|
61cdf9390d | ||
|
|
7d38f4940c | ||
|
|
6596a1de80 | ||
|
|
10097f13aa | ||
|
|
2fd8819a04 | ||
|
|
9de3979f5b | ||
|
|
ece7b33a96 | ||
|
|
06ab168897 | ||
|
|
ba6a6b2d40 | ||
|
|
434c3cf83b | ||
|
|
5c8d38d6cf | ||
|
|
6edecd5d94 | ||
|
|
c47de9878d | ||
|
|
6ae426c96b | ||
|
|
10e4fb2ce2 | ||
|
|
26904cc5a1 | ||
|
|
e65d1e459e | ||
|
|
477bee6468 | ||
|
|
fa8f5bafb2 | ||
|
|
214bae1479 | ||
|
|
ec818a506b | ||
|
|
61f4ab6674 | ||
|
|
3bc8cf65a4 | ||
|
|
d214e2d0c4 | ||
|
|
bd31821792 | ||
|
|
46eb8465a0 | ||
|
|
71a5cc2041 | ||
|
|
12289c4fd1 | ||
|
|
a4290cdbb3 | ||
|
|
177a53fbcf | ||
|
|
23ebae1828 | ||
|
|
df2a0fec5f | ||
|
|
ce979552fd | ||
|
|
e9847a4dbd | ||
|
|
f8bb90d963 | ||
|
|
91091c3e54 | ||
|
|
03fddb301b | ||
|
|
b135f1d58a | ||
|
|
645da54f25 | ||
|
|
66c328f51b | ||
|
|
f32a21d967 | ||
|
|
c86e828dbf | ||
|
|
15360cbb6b | ||
|
|
45f37e11ad | ||
|
|
4194d935ec | ||
|
|
af1fa95875 | ||
|
|
25fea82049 | ||
|
|
a4431381fa | ||
|
|
ab4d530462 | ||
|
|
48f8b884c3 | ||
|
|
55c9bc15e5 | ||
|
|
81d8deb1a8 | ||
|
|
a42bb799cc | ||
|
|
a1031772eb | ||
|
|
ff0332730d | ||
|
|
292a6037ad | ||
|
|
0e6ad94829 | ||
|
|
9978f36d9f | ||
|
|
b4a6f2195d | ||
|
|
3290cd09d3 | ||
|
|
2cb2f1d7e3 | ||
|
|
2b0b9f3e6c | ||
|
|
641c636790 | ||
|
|
182ea00cb3 | ||
|
|
543d1fe70b | ||
|
|
33aaa40bee | ||
|
|
601aa91163 | ||
|
|
6f5222e863 | ||
|
|
e92c05ebbd | ||
|
|
ac6dcd35fb | ||
|
|
f247ae1a75 | ||
|
|
ddd97cb78e | ||
|
|
84118c5735 | ||
|
|
1c6b8293d7 | ||
|
|
5d5edde429 | ||
|
|
4c83b5e719 | ||
|
|
93e1986d69 | ||
|
|
045aaa838a | ||
|
|
bf31896983 | ||
|
|
f9fb1484aa | ||
|
|
90f03ccd42 | ||
|
|
a81ddf3d70 | ||
|
|
ad00466483 | ||
|
|
1ffa69f691 | ||
|
|
5d25bb3084 | ||
|
|
5d93c99e8c | ||
|
|
7ca42d5711 | ||
|
|
304c5d4a8b | ||
|
|
4042c82a72 | ||
|
|
d9c3947824 | ||
|
|
a9480aed85 | ||
|
|
4cb73192a7 | ||
|
|
ed46b42fea | ||
|
|
0378baed35 | ||
|
|
04f76af22c | ||
|
|
e3d9d5566a | ||
|
|
386d67ec61 | ||
|
|
854dcd1abd | ||
|
|
c6d50cd431 | ||
|
|
b26276c8c4 | ||
|
|
fca4e4ec7c | ||
|
|
81a90e30c6 | ||
|
|
8d3250cee4 | ||
|
|
206fb306a7 | ||
|
|
ac135c649c | ||
|
|
46ae84cfba | ||
|
|
7cdb07b386 | ||
|
|
d322625f90 | ||
|
|
15a3f80e2e | ||
|
|
3ce198165c | ||
|
|
537b243360 | ||
|
|
67789201c3 | ||
|
|
0beccf23c0 | ||
|
|
a7cbb9edc9 | ||
|
|
12054aaa9f | ||
|
|
92ee288d66 | ||
|
|
ad1787770e | ||
|
|
21ec434688 | ||
|
|
f2d408829b | ||
|
|
2da8e60b6d | ||
|
|
e5582939fd | ||
|
|
890cb6a293 | ||
|
|
3ff7391495 | ||
|
|
a517e597f5 | ||
|
|
a49c5291dc | ||
|
|
222f530411 | ||
|
|
90a6891a7d | ||
|
|
f675d465b2 | ||
|
|
12599c34e2 | ||
|
|
cbb3bb62da | ||
|
|
ef08ab68a7 | ||
|
|
2262b13048 | ||
|
|
0e162511cf | ||
|
|
03c9d8ae4f | ||
|
|
5d0a8ff391 | ||
|
|
3bc8017464 | ||
|
|
c10405330d | ||
|
|
0e22021c65 | ||
|
|
ec4f981f1d | ||
|
|
5cd77a460c | ||
|
|
6f3c905744 | ||
|
|
1593d795ea | ||
|
|
1868680848 | ||
|
|
70081a40a4 | ||
|
|
c22a2ab7d2 | ||
|
|
e324f6f3f0 | ||
|
|
522ab85045 | ||
|
|
ed22014646 | ||
|
|
115e0aaf83 | ||
|
|
e1ac683154 | ||
|
|
293a024c14 | ||
|
|
6ddc39a676 | ||
|
|
46e4ecadc8 | ||
|
|
69f07fdb34 | ||
|
|
855c88a9c0 | ||
|
|
f40abc493a | ||
|
|
233f761779 | ||
|
|
258804cc04 | ||
|
|
9ae24cac2f | ||
|
|
06829c4082 | ||
|
|
d5419f0a46 | ||
|
|
7c839f176f | ||
|
|
53122fad40 | ||
|
|
ce043c5141 | ||
|
|
d4fa2c69ed | ||
|
|
c5de9840b0 | ||
|
|
5f2cbfc0fd | ||
|
|
b53713cdda | ||
|
|
9cc41d5118 | ||
|
|
59135c9a31 | ||
|
|
17fd075f39 | ||
|
|
148e46563f | ||
|
|
29e28f4b84 | ||
|
|
e20b0d5695 | ||
|
|
06068444e2 | ||
|
|
659c741ff5 | ||
|
|
8690a08881 | ||
|
|
aab2b032aa | ||
|
|
8e04c752fc | ||
|
|
4d2203ff52 | ||
|
|
f68b963596 | ||
|
|
99f39836a1 | ||
|
|
a7a1b8b7e9 | ||
|
|
fe16dc09da | ||
|
|
c7cd077e55 | ||
|
|
7f070236f7 | ||
|
|
0f008d5f7d | ||
|
|
d2367968e4 | ||
|
|
f064075a85 | ||
|
|
f281a994e8 | ||
|
|
831e4c3850 | ||
|
|
94d44142e3 | ||
|
|
7bf1986e91 | ||
|
|
97f0c9da84 | ||
|
|
c0319daa40 | ||
|
|
3332af4060 | ||
|
|
a3c723ee30 | ||
|
|
68c8633ba1 | ||
|
|
17aef1c883 | ||
|
|
ebc1209fc9 | ||
|
|
2bfe60e2fb | ||
|
|
69bc37acd6 | ||
|
|
0dce496499 | ||
|
|
600087ab49 | ||
|
|
4153cfbf14 | ||
|
|
84eb25da23 | ||
|
|
933ac60746 | ||
|
|
7d50015a74 | ||
|
|
75b8cf428e | ||
|
|
747ece59d2 | ||
|
|
2c581cae2a | ||
|
|
9b83e53b28 | ||
|
|
9fee431cc8 | ||
|
|
f8785b5f47 | ||
|
|
76629289f0 | ||
|
|
cbc9ae898c | ||
|
|
023faa227e | ||
|
|
23ae4c0a4d | ||
|
|
e89bcf4f77 | ||
|
|
4dfffa1df3 | ||
|
|
d87ddf50fc | ||
|
|
285bd3abc8 | ||
|
|
c92654fb43 | ||
|
|
2b142f2f9e | ||
|
|
feffc8081d | ||
|
|
03e421bf3d | ||
|
|
4ad9b27530 | ||
|
|
3b377f16b2 | ||
|
|
e97567e227 | ||
|
|
c2093ccce1 | ||
|
|
6a9630d2bd | ||
|
|
3f9b274180 | ||
|
|
9ca54d00d8 | ||
|
|
afd0d6af07 | ||
|
|
d9c049fd9f | ||
|
|
b05ed4ffa6 | ||
|
|
506d5e41bf | ||
|
|
617637c788 | ||
|
|
b5b01e5bb5 | ||
|
|
876d0d310f | ||
|
|
f32027f3b5 | ||
|
|
cfb20f09a9 | ||
|
|
dd7d7683c9 | ||
|
|
da5dbaf1d0 | ||
|
|
3072f257f5 | ||
|
|
abde0d4efb | ||
|
|
13170ca627 | ||
|
|
3f0f313a76 | ||
|
|
e82fab34d7 | ||
|
|
5f4c4df227 | ||
|
|
285dc554ec | ||
|
|
c96a6f1de6 | ||
|
|
953090fd62 | ||
|
|
f783b9169f | ||
|
|
128c72a234 | ||
|
|
01636ca900 | ||
|
|
93206ef0fa | ||
|
|
c4d9a23f26 | ||
|
|
1f17ef6d3c | ||
|
|
7471bc7775 | ||
|
|
476a7d3eee | ||
|
|
e23a0dcc5d | ||
|
|
46c833810c | ||
|
|
4de530af45 | ||
|
|
b1cd1d917e | ||
|
|
16af5b87f8 | ||
|
|
36651bed71 | ||
|
|
8de933ab07 | ||
|
|
c0ff5635ba | ||
|
|
3cb1c23554 | ||
|
|
9151b9d233 | ||
|
|
90b9121e66 | ||
|
|
3648164219 | ||
|
|
c2e4f8aed5 | ||
|
|
1dd2d432f1 | ||
|
|
8360223fed | ||
|
|
8510f57ad4 | ||
|
|
397379cd3f | ||
|
|
55ab6f015a | ||
|
|
5e1f651e21 | ||
|
|
0635d9d174 | ||
|
|
e4a70b9f9a | ||
|
|
d07943c262 | ||
|
|
fcecfc81bb | ||
|
|
3611d33b00 | ||
|
|
a7a9a8a614 |
@@ -58,13 +58,14 @@ where we are today.
|
||||
|
||||
|
||||
= Additional OpenSim Contributors =
|
||||
These folks have contributed code patches to OpenSim to help make it
|
||||
These folks have contributed code patches or content to OpenSimulator to help make it
|
||||
what it is today.
|
||||
|
||||
* aduffy70
|
||||
* A_Biondi
|
||||
* alex_carnell
|
||||
* Alan Webb (IBM)
|
||||
* Aleric
|
||||
* Allen Kerensky
|
||||
* BigFootAg
|
||||
* BlueWall Slade
|
||||
@@ -75,11 +76,12 @@ what it is today.
|
||||
* controlbreak
|
||||
* coyled
|
||||
* Daedius
|
||||
* Dong Jun Lan (IBM)
|
||||
* DoranZemlja
|
||||
* daTwitch
|
||||
* devalnor-#708
|
||||
* dmiles (Daxtron Labs)
|
||||
* Dong Jun Lan (IBM)
|
||||
* DoranZemlja
|
||||
* dr0b3rts
|
||||
* dslake (Intel)
|
||||
* FredoChaplin
|
||||
* Garmin Kawaguichi
|
||||
@@ -101,6 +103,7 @@ what it is today.
|
||||
* jhurliman
|
||||
* John R Sohn (XenReborn)
|
||||
* jonc
|
||||
* Jon Cundill
|
||||
* Junta Kohime
|
||||
* Kayne
|
||||
* Kevin Cozens
|
||||
@@ -161,6 +164,7 @@ what it is today.
|
||||
* webmage (IBM)
|
||||
* Xantor
|
||||
* Y. Nitta
|
||||
* YoshikoFazuku
|
||||
* YZh
|
||||
* Zackary Geers aka Kunnis Basiat
|
||||
* Zha Ewry
|
||||
@@ -213,5 +217,3 @@ In addition, we would like to thank:
|
||||
* The Mono Project
|
||||
* The NANT Developers
|
||||
* Microsoft (.NET, MSSQL-Adapters)
|
||||
*x
|
||||
|
||||
|
||||
@@ -504,6 +504,30 @@ namespace OpenSim.Groups
|
||||
|
||||
return notice;
|
||||
}
|
||||
|
||||
public static Dictionary<string, object> DirGroupsReplyData(DirGroupsReplyData g)
|
||||
{
|
||||
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||
|
||||
dict["GroupID"] = g.groupID;
|
||||
dict["Name"] = g.groupName;
|
||||
dict["NMembers"] = g.members;
|
||||
dict["SearchOrder"] = g.searchOrder;
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
public static DirGroupsReplyData DirGroupsReplyData(Dictionary<string, object> dict)
|
||||
{
|
||||
DirGroupsReplyData g;
|
||||
|
||||
g.groupID = new UUID(dict["GroupID"].ToString());
|
||||
g.groupName = dict["Name"].ToString();
|
||||
Int32.TryParse(dict["NMembers"].ToString(), out g.members);
|
||||
float.TryParse(dict["SearchOrder"].ToString(), out g.searchOrder);
|
||||
|
||||
return g;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenSim.Services.Interfaces;
|
||||
using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
|
||||
using GridRegion = OpenSim.Services.Interfaces.GridRegion;
|
||||
|
||||
namespace OpenSim.Groups
|
||||
{
|
||||
@@ -51,7 +52,7 @@ namespace OpenSim.Groups
|
||||
private IPresenceService m_presenceService;
|
||||
|
||||
private IMessageTransferModule m_msgTransferModule = null;
|
||||
|
||||
private IUserManagement m_UserManagement = null;
|
||||
private IGroupsServicesConnector m_groupData = null;
|
||||
|
||||
// Config Options
|
||||
@@ -79,6 +80,10 @@ namespace OpenSim.Groups
|
||||
|
||||
private int m_usersOnlineCacheExpirySeconds = 20;
|
||||
|
||||
private Dictionary<UUID, List<string>> m_groupsAgentsDroppedFromChatSession = new Dictionary<UUID, List<string>>();
|
||||
private Dictionary<UUID, List<string>> m_groupsAgentsInvitedToChatSession = new Dictionary<UUID, List<string>>();
|
||||
|
||||
|
||||
#region Region Module interfaceBase Members
|
||||
|
||||
public void Initialise(IConfigSource config)
|
||||
@@ -124,10 +129,12 @@ namespace OpenSim.Groups
|
||||
m_sceneList.Add(scene);
|
||||
|
||||
scene.EventManager.OnNewClient += OnNewClient;
|
||||
scene.EventManager.OnMakeRootAgent += OnMakeRootAgent;
|
||||
scene.EventManager.OnMakeChildAgent += OnMakeChildAgent;
|
||||
scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage;
|
||||
scene.EventManager.OnClientLogin += OnClientLogin;
|
||||
}
|
||||
|
||||
|
||||
public void RegionLoaded(Scene scene)
|
||||
{
|
||||
if (!m_groupMessagingEnabled)
|
||||
@@ -155,6 +162,17 @@ namespace OpenSim.Groups
|
||||
return;
|
||||
}
|
||||
|
||||
m_UserManagement = scene.RequestModuleInterface<IUserManagement>();
|
||||
|
||||
// No groups module, no groups messaging
|
||||
if (m_UserManagement == null)
|
||||
{
|
||||
m_log.Error("[Groups.Messaging]: Could not get IUserManagement, GroupsMessagingModule is now disabled.");
|
||||
RemoveRegion(scene);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (m_presenceService == null)
|
||||
m_presenceService = scene.PresenceService;
|
||||
|
||||
@@ -227,87 +245,107 @@ namespace OpenSim.Groups
|
||||
|
||||
public void SendMessageToGroup(GridInstantMessage im, UUID groupID)
|
||||
{
|
||||
List<GroupMembersData> groupMembers = m_groupData.GetGroupMembers(new UUID(im.fromAgentID).ToString(), groupID);
|
||||
UUID fromAgentID = new UUID(im.fromAgentID);
|
||||
List<GroupMembersData> groupMembers = m_groupData.GetGroupMembers(UUID.Zero.ToString(), groupID);
|
||||
int groupMembersCount = groupMembers.Count;
|
||||
PresenceInfo[] onlineAgents = null;
|
||||
|
||||
if (m_messageOnlineAgentsOnly)
|
||||
// In V2 we always only send to online members.
|
||||
// Sending to offline members is not an option.
|
||||
string[] t1 = groupMembers.ConvertAll<string>(gmd => gmd.AgentID.ToString()).ToArray();
|
||||
|
||||
// We cache in order not to overwhlem the presence service on large grids with many groups. This does
|
||||
// mean that members coming online will not see all group members until after m_usersOnlineCacheExpirySeconds has elapsed.
|
||||
// (assuming this is the same across all grid simulators).
|
||||
if (!m_usersOnlineCache.TryGetValue(groupID, out onlineAgents))
|
||||
{
|
||||
string[] t1 = groupMembers.ConvertAll<string>(gmd => gmd.AgentID.ToString()).ToArray();
|
||||
onlineAgents = m_presenceService.GetAgents(t1);
|
||||
m_usersOnlineCache.Add(groupID, onlineAgents, m_usersOnlineCacheExpirySeconds);
|
||||
}
|
||||
|
||||
// We cache in order not to overwhlem the presence service on large grids with many groups. This does
|
||||
// mean that members coming online will not see all group members until after m_usersOnlineCacheExpirySeconds has elapsed.
|
||||
// (assuming this is the same across all grid simulators).
|
||||
PresenceInfo[] onlineAgents;
|
||||
if (!m_usersOnlineCache.TryGetValue(groupID, out onlineAgents))
|
||||
{
|
||||
onlineAgents = m_presenceService.GetAgents(t1);
|
||||
m_usersOnlineCache.Add(groupID, onlineAgents, m_usersOnlineCacheExpirySeconds);
|
||||
}
|
||||
HashSet<string> onlineAgentsUuidSet = new HashSet<string>();
|
||||
Array.ForEach<PresenceInfo>(onlineAgents, pi => onlineAgentsUuidSet.Add(pi.UserID));
|
||||
|
||||
HashSet<string> onlineAgentsUuidSet = new HashSet<string>();
|
||||
Array.ForEach<PresenceInfo>(onlineAgents, pi => onlineAgentsUuidSet.Add(pi.UserID));
|
||||
groupMembers = groupMembers.Where(gmd => onlineAgentsUuidSet.Contains(gmd.AgentID.ToString())).ToList();
|
||||
|
||||
groupMembers = groupMembers.Where(gmd => onlineAgentsUuidSet.Contains(gmd.AgentID.ToString())).ToList();
|
||||
|
||||
// if (m_debugEnabled)
|
||||
// if (m_debugEnabled)
|
||||
// m_log.DebugFormat(
|
||||
// "[Groups.Messaging]: SendMessageToGroup called for group {0} with {1} visible members, {2} online",
|
||||
// groupID, groupMembersCount, groupMembers.Count());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_debugEnabled)
|
||||
m_log.DebugFormat(
|
||||
"[Groups.Messaging]: SendMessageToGroup called for group {0} with {1} visible members",
|
||||
groupID, groupMembers.Count);
|
||||
}
|
||||
|
||||
int requestStartTick = Environment.TickCount;
|
||||
|
||||
im.imSessionID = groupID.Guid;
|
||||
im.fromGroup = true;
|
||||
IClientAPI thisClient = GetActiveClient(fromAgentID);
|
||||
if (thisClient != null)
|
||||
{
|
||||
im.RegionID = thisClient.Scene.RegionInfo.RegionID.Guid;
|
||||
}
|
||||
|
||||
// Send to self first of all
|
||||
im.toAgentID = im.fromAgentID;
|
||||
im.fromGroup = true;
|
||||
ProcessMessageFromGroupSession(im);
|
||||
|
||||
List<UUID> regions = new List<UUID>();
|
||||
List<UUID> clientsAlreadySent = new List<UUID>();
|
||||
|
||||
// Then send to everybody else
|
||||
foreach (GroupMembersData member in groupMembers)
|
||||
{
|
||||
if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID.ToString(), groupID))
|
||||
if (member.AgentID.Guid == im.fromAgentID)
|
||||
continue;
|
||||
|
||||
if (clientsAlreadySent.Contains(member.AgentID))
|
||||
continue;
|
||||
clientsAlreadySent.Add(member.AgentID);
|
||||
|
||||
if (hasAgentDroppedGroupChatSession(member.AgentID.ToString(), groupID))
|
||||
{
|
||||
// Don't deliver messages to people who have dropped this session
|
||||
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: {0} has dropped session, not delivering to them", member.AgentID);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Copy Message
|
||||
GridInstantMessage msg = new GridInstantMessage();
|
||||
msg.imSessionID = groupID.Guid;
|
||||
msg.fromAgentName = im.fromAgentName;
|
||||
msg.message = im.message;
|
||||
msg.dialog = im.dialog;
|
||||
msg.offline = im.offline;
|
||||
msg.ParentEstateID = im.ParentEstateID;
|
||||
msg.Position = im.Position;
|
||||
msg.RegionID = im.RegionID;
|
||||
msg.binaryBucket = im.binaryBucket;
|
||||
msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
|
||||
|
||||
msg.fromAgentID = im.fromAgentID;
|
||||
msg.fromGroup = true;
|
||||
|
||||
msg.toAgentID = member.AgentID.Guid;
|
||||
im.toAgentID = member.AgentID.Guid;
|
||||
|
||||
IClientAPI client = GetActiveClient(member.AgentID);
|
||||
if (client == null)
|
||||
{
|
||||
// If they're not local, forward across the grid
|
||||
// BUT do it only once per region, please! Sim would be even better!
|
||||
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Delivering to {0} via Grid", member.AgentID);
|
||||
m_msgTransferModule.SendInstantMessage(msg, delegate(bool success) { });
|
||||
|
||||
bool reallySend = true;
|
||||
if (onlineAgents != null)
|
||||
{
|
||||
PresenceInfo presence = onlineAgents.First(p => p.UserID == member.AgentID.ToString());
|
||||
if (regions.Contains(presence.RegionID))
|
||||
reallySend = false;
|
||||
else
|
||||
regions.Add(presence.RegionID);
|
||||
}
|
||||
|
||||
if (reallySend)
|
||||
{
|
||||
// We have to create a new IM structure because the transfer module
|
||||
// uses async send
|
||||
GridInstantMessage msg = new GridInstantMessage(im, true);
|
||||
m_msgTransferModule.SendInstantMessage(msg, delegate(bool success) { });
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Deliver locally, directly
|
||||
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Passing to ProcessMessageFromGroupSession to deliver to {0} locally", client.Name);
|
||||
ProcessMessageFromGroupSession(msg);
|
||||
|
||||
ProcessMessageFromGroupSession(im);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Temporary for assessing how long it still takes to send messages to large online groups.
|
||||
if (m_messageOnlineAgentsOnly)
|
||||
if (m_debugEnabled)
|
||||
m_log.DebugFormat(
|
||||
"[Groups.Messaging]: SendMessageToGroup for group {0} with {1} visible members, {2} online took {3}ms",
|
||||
groupID, groupMembersCount, groupMembers.Count(), Environment.TickCount - requestStartTick);
|
||||
@@ -324,9 +362,20 @@ namespace OpenSim.Groups
|
||||
{
|
||||
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: OnInstantMessage registered for {0}", client.Name);
|
||||
|
||||
client.OnInstantMessage += OnInstantMessage;
|
||||
ResetAgentGroupChatSessions(client.AgentId.ToString());
|
||||
}
|
||||
|
||||
void OnMakeRootAgent(ScenePresence sp)
|
||||
{
|
||||
sp.ControllingClient.OnInstantMessage += OnInstantMessage;
|
||||
}
|
||||
|
||||
void OnMakeChildAgent(ScenePresence sp)
|
||||
{
|
||||
sp.ControllingClient.OnInstantMessage -= OnInstantMessage;
|
||||
}
|
||||
|
||||
|
||||
private void OnGridInstantMessage(GridInstantMessage msg)
|
||||
{
|
||||
// The instant message module will only deliver messages of dialog types:
|
||||
@@ -335,21 +384,91 @@ namespace OpenSim.Groups
|
||||
// Any other message type will not be delivered to a client by the
|
||||
// Instant Message Module
|
||||
|
||||
|
||||
UUID regionID = new UUID(msg.RegionID);
|
||||
if (m_debugEnabled)
|
||||
{
|
||||
m_log.DebugFormat("[Groups.Messaging]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||
m_log.DebugFormat("[Groups.Messaging]: {0} called, IM from region {1}",
|
||||
System.Reflection.MethodBase.GetCurrentMethod().Name, regionID);
|
||||
|
||||
DebugGridInstantMessage(msg);
|
||||
}
|
||||
|
||||
// Incoming message from a group
|
||||
if ((msg.fromGroup == true) &&
|
||||
((msg.dialog == (byte)InstantMessageDialog.SessionSend)
|
||||
|| (msg.dialog == (byte)InstantMessageDialog.SessionAdd)
|
||||
|| (msg.dialog == (byte)InstantMessageDialog.SessionDrop)))
|
||||
if ((msg.fromGroup == true) && (msg.dialog == (byte)InstantMessageDialog.SessionSend))
|
||||
{
|
||||
ProcessMessageFromGroupSession(msg);
|
||||
// We have to redistribute the message across all members of the group who are here
|
||||
// on this sim
|
||||
|
||||
UUID GroupID = new UUID(msg.imSessionID);
|
||||
|
||||
Scene aScene = m_sceneList[0];
|
||||
GridRegion regionOfOrigin = aScene.GridService.GetRegionByUUID(aScene.RegionInfo.ScopeID, regionID);
|
||||
|
||||
List<GroupMembersData> groupMembers = m_groupData.GetGroupMembers(UUID.Zero.ToString(), GroupID);
|
||||
|
||||
//if (m_debugEnabled)
|
||||
// foreach (GroupMembersData m in groupMembers)
|
||||
// m_log.DebugFormat("[Groups.Messaging]: member {0}", m.AgentID);
|
||||
|
||||
foreach (Scene s in m_sceneList)
|
||||
{
|
||||
s.ForEachScenePresence(sp =>
|
||||
{
|
||||
// If we got this via grid messaging, it's because the caller thinks
|
||||
// that the root agent is here. We should only send the IM to root agents.
|
||||
if (sp.IsChildAgent)
|
||||
return;
|
||||
|
||||
GroupMembersData m = groupMembers.Find(gmd =>
|
||||
{
|
||||
return gmd.AgentID == sp.UUID;
|
||||
});
|
||||
if (m.AgentID == UUID.Zero)
|
||||
{
|
||||
if (m_debugEnabled)
|
||||
m_log.DebugFormat("[Groups.Messaging]: skipping agent {0} because he is not a member of the group", sp.UUID);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the user has an agent in the region where
|
||||
// the IM came from, and if so, skip it, because the IM
|
||||
// was already sent via that agent
|
||||
if (regionOfOrigin != null)
|
||||
{
|
||||
AgentCircuitData aCircuit = s.AuthenticateHandler.GetAgentCircuitData(sp.UUID);
|
||||
if (aCircuit != null)
|
||||
{
|
||||
if (aCircuit.ChildrenCapSeeds.Keys.Contains(regionOfOrigin.RegionHandle))
|
||||
{
|
||||
if (m_debugEnabled)
|
||||
m_log.DebugFormat("[Groups.Messaging]: skipping agent {0} because he has an agent in region of origin", sp.UUID);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_debugEnabled)
|
||||
m_log.DebugFormat("[Groups.Messaging]: not skipping agent {0}", sp.UUID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UUID AgentID = sp.UUID;
|
||||
msg.toAgentID = AgentID.Guid;
|
||||
|
||||
if (!hasAgentDroppedGroupChatSession(AgentID.ToString(), GroupID))
|
||||
{
|
||||
if (!hasAgentBeenInvitedToGroupChatSession(AgentID.ToString(), GroupID))
|
||||
AddAgentToSession(AgentID, GroupID, msg);
|
||||
else
|
||||
{
|
||||
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Passing to ProcessMessageFromGroupSession to deliver to {0} locally", sp.Name);
|
||||
|
||||
ProcessMessageFromGroupSession(msg);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -359,82 +478,40 @@ namespace OpenSim.Groups
|
||||
|
||||
UUID AgentID = new UUID(msg.fromAgentID);
|
||||
UUID GroupID = new UUID(msg.imSessionID);
|
||||
UUID toAgentID = new UUID(msg.toAgentID);
|
||||
|
||||
switch (msg.dialog)
|
||||
{
|
||||
case (byte)InstantMessageDialog.SessionAdd:
|
||||
m_groupData.AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID);
|
||||
AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID);
|
||||
break;
|
||||
|
||||
case (byte)InstantMessageDialog.SessionDrop:
|
||||
m_groupData.AgentDroppedFromGroupChatSession(AgentID.ToString(), GroupID);
|
||||
AgentDroppedFromGroupChatSession(AgentID.ToString(), GroupID);
|
||||
break;
|
||||
|
||||
case (byte)InstantMessageDialog.SessionSend:
|
||||
if (!m_groupData.hasAgentDroppedGroupChatSession(AgentID.ToString(), GroupID)
|
||||
&& !m_groupData.hasAgentBeenInvitedToGroupChatSession(AgentID.ToString(), GroupID)
|
||||
)
|
||||
// User hasn't dropped, so they're in the session,
|
||||
// maybe we should deliver it.
|
||||
IClientAPI client = GetActiveClient(new UUID(msg.toAgentID));
|
||||
if (client != null)
|
||||
{
|
||||
// Agent not in session and hasn't dropped from session
|
||||
// Add them to the session for now, and Invite them
|
||||
m_groupData.AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID);
|
||||
// Deliver locally, directly
|
||||
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Delivering to {0} locally", client.Name);
|
||||
|
||||
UUID toAgentID = new UUID(msg.toAgentID);
|
||||
IClientAPI activeClient = GetActiveClient(toAgentID);
|
||||
if (activeClient != null)
|
||||
if (!hasAgentDroppedGroupChatSession(toAgentID.ToString(), GroupID))
|
||||
{
|
||||
GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero.ToString(), GroupID, null);
|
||||
if (groupInfo != null)
|
||||
{
|
||||
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Sending chatterbox invite instant message");
|
||||
|
||||
// Force? open the group session dialog???
|
||||
// and simultanously deliver the message, so we don't need to do a seperate client.SendInstantMessage(msg);
|
||||
IEventQueue eq = activeClient.Scene.RequestModuleInterface<IEventQueue>();
|
||||
eq.ChatterboxInvitation(
|
||||
GroupID
|
||||
, groupInfo.GroupName
|
||||
, new UUID(msg.fromAgentID)
|
||||
, msg.message
|
||||
, new UUID(msg.toAgentID)
|
||||
, msg.fromAgentName
|
||||
, msg.dialog
|
||||
, msg.timestamp
|
||||
, msg.offline == 1
|
||||
, (int)msg.ParentEstateID
|
||||
, msg.Position
|
||||
, 1
|
||||
, new UUID(msg.imSessionID)
|
||||
, msg.fromGroup
|
||||
, OpenMetaverse.Utils.StringToBytes(groupInfo.GroupName)
|
||||
);
|
||||
|
||||
eq.ChatterBoxSessionAgentListUpdates(
|
||||
new UUID(GroupID)
|
||||
, new UUID(msg.fromAgentID)
|
||||
, new UUID(msg.toAgentID)
|
||||
, false //canVoiceChat
|
||||
, false //isModerator
|
||||
, false //text mute
|
||||
);
|
||||
}
|
||||
if (!hasAgentBeenInvitedToGroupChatSession(toAgentID.ToString(), GroupID))
|
||||
// This actually sends the message too, so no need to resend it
|
||||
// with client.SendInstantMessage
|
||||
AddAgentToSession(toAgentID, GroupID, msg);
|
||||
else
|
||||
client.SendInstantMessage(msg);
|
||||
}
|
||||
}
|
||||
else if (!m_groupData.hasAgentDroppedGroupChatSession(AgentID.ToString(), GroupID))
|
||||
else
|
||||
{
|
||||
// User hasn't dropped, so they're in the session,
|
||||
// maybe we should deliver it.
|
||||
IClientAPI client = GetActiveClient(new UUID(msg.toAgentID));
|
||||
if (client != null)
|
||||
{
|
||||
// Deliver locally, directly
|
||||
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Delivering to {0} locally", client.Name);
|
||||
client.SendInstantMessage(msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.WarnFormat("[Groups.Messaging]: Received a message over the grid for a client that isn't here: {0}", msg.toAgentID);
|
||||
}
|
||||
m_log.WarnFormat("[Groups.Messaging]: Received a message over the grid for a client that isn't here: {0}", msg.toAgentID);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -444,6 +521,53 @@ namespace OpenSim.Groups
|
||||
}
|
||||
}
|
||||
|
||||
private void AddAgentToSession(UUID AgentID, UUID GroupID, GridInstantMessage msg)
|
||||
{
|
||||
// Agent not in session and hasn't dropped from session
|
||||
// Add them to the session for now, and Invite them
|
||||
AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID);
|
||||
|
||||
IClientAPI activeClient = GetActiveClient(AgentID);
|
||||
if (activeClient != null)
|
||||
{
|
||||
GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero.ToString(), GroupID, null);
|
||||
if (groupInfo != null)
|
||||
{
|
||||
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Sending chatterbox invite instant message");
|
||||
|
||||
// Force? open the group session dialog???
|
||||
// and simultanously deliver the message, so we don't need to do a seperate client.SendInstantMessage(msg);
|
||||
IEventQueue eq = activeClient.Scene.RequestModuleInterface<IEventQueue>();
|
||||
eq.ChatterboxInvitation(
|
||||
GroupID
|
||||
, groupInfo.GroupName
|
||||
, new UUID(msg.fromAgentID)
|
||||
, msg.message
|
||||
, AgentID
|
||||
, msg.fromAgentName
|
||||
, msg.dialog
|
||||
, msg.timestamp
|
||||
, msg.offline == 1
|
||||
, (int)msg.ParentEstateID
|
||||
, msg.Position
|
||||
, 1
|
||||
, new UUID(msg.imSessionID)
|
||||
, msg.fromGroup
|
||||
, OpenMetaverse.Utils.StringToBytes(groupInfo.GroupName)
|
||||
);
|
||||
|
||||
eq.ChatterBoxSessionAgentListUpdates(
|
||||
new UUID(GroupID)
|
||||
, AgentID
|
||||
, new UUID(msg.toAgentID)
|
||||
, false //canVoiceChat
|
||||
, false //isModerator
|
||||
, false //text mute
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -469,7 +593,7 @@ namespace OpenSim.Groups
|
||||
|
||||
if (groupInfo != null)
|
||||
{
|
||||
m_groupData.AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID);
|
||||
AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID);
|
||||
|
||||
ChatterBoxSessionStartReplyViaCaps(remoteClient, groupInfo.GroupName, GroupID);
|
||||
|
||||
@@ -495,7 +619,7 @@ namespace OpenSim.Groups
|
||||
m_log.DebugFormat("[Groups.Messaging]: Send message to session for group {0} with session ID {1}", GroupID, im.imSessionID.ToString());
|
||||
|
||||
//If this agent is sending a message, then they want to be in the session
|
||||
m_groupData.AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID);
|
||||
AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID);
|
||||
|
||||
SendMessageToGroup(im, GroupID);
|
||||
}
|
||||
@@ -566,12 +690,12 @@ namespace OpenSim.Groups
|
||||
{
|
||||
if (!sp.IsChildAgent)
|
||||
{
|
||||
if (m_debugEnabled) m_log.WarnFormat("[Groups.Messaging]: Found root agent for client : {0}", sp.ControllingClient.Name);
|
||||
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Found root agent for client : {0}", sp.ControllingClient.Name);
|
||||
return sp.ControllingClient;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_debugEnabled) m_log.WarnFormat("[Groups.Messaging]: Found child agent for client : {0}", sp.ControllingClient.Name);
|
||||
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Found child agent for client : {0}", sp.ControllingClient.Name);
|
||||
child = sp.ControllingClient;
|
||||
}
|
||||
}
|
||||
@@ -590,5 +714,71 @@ namespace OpenSim.Groups
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GroupSessionTracking
|
||||
|
||||
public void ResetAgentGroupChatSessions(string agentID)
|
||||
{
|
||||
foreach (List<string> agentList in m_groupsAgentsDroppedFromChatSession.Values)
|
||||
agentList.Remove(agentID);
|
||||
|
||||
foreach (List<string> agentList in m_groupsAgentsInvitedToChatSession.Values)
|
||||
agentList.Remove(agentID);
|
||||
}
|
||||
|
||||
public bool hasAgentBeenInvitedToGroupChatSession(string agentID, UUID groupID)
|
||||
{
|
||||
// If we're tracking this group, and we can find them in the tracking, then they've been invited
|
||||
return m_groupsAgentsInvitedToChatSession.ContainsKey(groupID)
|
||||
&& m_groupsAgentsInvitedToChatSession[groupID].Contains(agentID);
|
||||
}
|
||||
|
||||
public bool hasAgentDroppedGroupChatSession(string agentID, UUID groupID)
|
||||
{
|
||||
// If we're tracking drops for this group,
|
||||
// and we find them, well... then they've dropped
|
||||
return m_groupsAgentsDroppedFromChatSession.ContainsKey(groupID)
|
||||
&& m_groupsAgentsDroppedFromChatSession[groupID].Contains(agentID);
|
||||
}
|
||||
|
||||
public void AgentDroppedFromGroupChatSession(string agentID, UUID groupID)
|
||||
{
|
||||
if (m_groupsAgentsDroppedFromChatSession.ContainsKey(groupID))
|
||||
{
|
||||
// If not in dropped list, add
|
||||
if (!m_groupsAgentsDroppedFromChatSession[groupID].Contains(agentID))
|
||||
{
|
||||
m_groupsAgentsDroppedFromChatSession[groupID].Add(agentID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void AgentInvitedToGroupChatSession(string agentID, UUID groupID)
|
||||
{
|
||||
// Add Session Status if it doesn't exist for this session
|
||||
CreateGroupChatSessionTracking(groupID);
|
||||
|
||||
// If nessesary, remove from dropped list
|
||||
if (m_groupsAgentsDroppedFromChatSession[groupID].Contains(agentID))
|
||||
{
|
||||
m_groupsAgentsDroppedFromChatSession[groupID].Remove(agentID);
|
||||
}
|
||||
|
||||
// Add to invited
|
||||
if (!m_groupsAgentsInvitedToChatSession[groupID].Contains(agentID))
|
||||
m_groupsAgentsInvitedToChatSession[groupID].Add(agentID);
|
||||
}
|
||||
|
||||
private void CreateGroupChatSessionTracking(UUID groupID)
|
||||
{
|
||||
if (!m_groupsAgentsDroppedFromChatSession.ContainsKey(groupID))
|
||||
{
|
||||
m_groupsAgentsDroppedFromChatSession.Add(groupID, new List<string>());
|
||||
m_groupsAgentsInvitedToChatSession.Add(groupID, new List<string>());
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,6 +141,8 @@ namespace OpenSim.Groups
|
||||
if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||
|
||||
scene.EventManager.OnNewClient += OnNewClient;
|
||||
scene.EventManager.OnMakeRootAgent += OnMakeRoot;
|
||||
scene.EventManager.OnMakeChildAgent += OnMakeChild;
|
||||
scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage;
|
||||
// The InstantMessageModule itself doesn't do this,
|
||||
// so lets see if things explode if we don't do it
|
||||
@@ -194,6 +196,8 @@ namespace OpenSim.Groups
|
||||
if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||
|
||||
scene.EventManager.OnNewClient -= OnNewClient;
|
||||
scene.EventManager.OnMakeRootAgent -= OnMakeRoot;
|
||||
scene.EventManager.OnMakeChildAgent -= OnMakeChild;
|
||||
scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage;
|
||||
|
||||
lock (m_sceneList)
|
||||
@@ -232,16 +236,29 @@ namespace OpenSim.Groups
|
||||
{
|
||||
if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||
|
||||
client.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest;
|
||||
client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest;
|
||||
client.OnDirFindQuery += OnDirFindQuery;
|
||||
client.OnRequestAvatarProperties += OnRequestAvatarProperties;
|
||||
}
|
||||
|
||||
private void OnMakeRoot(ScenePresence sp)
|
||||
{
|
||||
if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||
|
||||
sp.ControllingClient.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest;
|
||||
// Used for Notices and Group Invites/Accept/Reject
|
||||
client.OnInstantMessage += OnInstantMessage;
|
||||
sp.ControllingClient.OnInstantMessage += OnInstantMessage;
|
||||
|
||||
// Send client their groups information.
|
||||
SendAgentGroupDataUpdate(client, client.AgentId);
|
||||
SendAgentGroupDataUpdate(sp.ControllingClient, sp.UUID);
|
||||
}
|
||||
|
||||
private void OnMakeChild(ScenePresence sp)
|
||||
{
|
||||
if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||
|
||||
sp.ControllingClient.OnUUIDGroupNameRequest -= HandleUUIDGroupNameRequest;
|
||||
// Used for Notices and Group Invites/Accept/Reject
|
||||
sp.ControllingClient.OnInstantMessage -= OnInstantMessage;
|
||||
}
|
||||
|
||||
private void OnRequestAvatarProperties(IClientAPI remoteClient, UUID avatarID)
|
||||
@@ -287,21 +304,6 @@ namespace OpenSim.Groups
|
||||
}
|
||||
*/
|
||||
|
||||
void OnDirFindQuery(IClientAPI remoteClient, UUID queryID, string queryText, uint queryFlags, int queryStart)
|
||||
{
|
||||
if (((DirFindFlags)queryFlags & DirFindFlags.Groups) == DirFindFlags.Groups)
|
||||
{
|
||||
if (m_debugEnabled)
|
||||
m_log.DebugFormat(
|
||||
"[Groups]: {0} called with queryText({1}) queryFlags({2}) queryStart({3})",
|
||||
System.Reflection.MethodBase.GetCurrentMethod().Name, queryText, (DirFindFlags)queryFlags, queryStart);
|
||||
|
||||
// TODO: This currently ignores pretty much all the query flags including Mature and sort order
|
||||
remoteClient.SendDirGroupsReply(queryID, m_groupData.FindGroups(GetRequestingAgentIDStr(remoteClient), queryText).ToArray());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void OnAgentDataUpdateRequest(IClientAPI remoteClient, UUID dataForAgentID, UUID sessionID)
|
||||
{
|
||||
if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||
@@ -347,7 +349,7 @@ namespace OpenSim.Groups
|
||||
{
|
||||
if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||
|
||||
m_log.DebugFormat("[Groups]: IM From {0} to {1} msg {2} type {3}", im.fromAgentID, im.toAgentID, im.message, (InstantMessageDialog)im.dialog);
|
||||
//m_log.DebugFormat("[Groups]: IM From {0} to {1} msg {2} type {3}", im.fromAgentID, im.toAgentID, im.message, (InstantMessageDialog)im.dialog);
|
||||
// Group invitations
|
||||
if ((im.dialog == (byte)InstantMessageDialog.GroupInvitationAccept) || (im.dialog == (byte)InstantMessageDialog.GroupInvitationDecline))
|
||||
{
|
||||
@@ -465,12 +467,12 @@ namespace OpenSim.Groups
|
||||
}
|
||||
|
||||
// Send notice out to everyone that wants notices
|
||||
// Build notice IIM
|
||||
GridInstantMessage msg = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice);
|
||||
foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetRequestingAgentIDStr(remoteClient), GroupID))
|
||||
{
|
||||
if (member.AcceptNotices)
|
||||
{
|
||||
// Build notice IIM, one of reach, because the sending may be async
|
||||
GridInstantMessage msg = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice);
|
||||
msg.toAgentID = member.AgentID.Guid;
|
||||
OutgoingInstantMessage(msg, member.AgentID);
|
||||
}
|
||||
@@ -485,7 +487,7 @@ namespace OpenSim.Groups
|
||||
return;
|
||||
|
||||
//// 16 bytes are the UUID. Maybe.
|
||||
UUID folderID = new UUID(im.binaryBucket, 0);
|
||||
// UUID folderID = new UUID(im.binaryBucket, 0);
|
||||
UUID noticeID = new UUID(im.imSessionID);
|
||||
|
||||
GroupNoticeInfo notice = m_groupData.GetGroupNotice(remoteClient.AgentId.ToString(), noticeID);
|
||||
@@ -766,14 +768,17 @@ namespace OpenSim.Groups
|
||||
remoteClient.SendCreateGroupReply(UUID.Zero, false, "Insufficient funds to create a group.");
|
||||
return UUID.Zero;
|
||||
}
|
||||
money.ApplyCharge(remoteClient.AgentId, money.GroupCreationCharge, "Group Creation");
|
||||
}
|
||||
|
||||
string reason = string.Empty;
|
||||
UUID groupID = m_groupData.CreateGroup(remoteClient.AgentId, name, charter, showInList, insigniaID, membershipFee, openEnrollment,
|
||||
allowPublish, maturePublish, remoteClient.AgentId, out reason);
|
||||
|
||||
if (groupID != UUID.Zero)
|
||||
{
|
||||
if (money != null)
|
||||
money.ApplyCharge(remoteClient.AgentId, money.GroupCreationCharge, MoneyTransactionType.GroupCreate);
|
||||
|
||||
remoteClient.SendCreateGroupReply(groupID, true, "Group created successfullly");
|
||||
|
||||
// Update the founder with new group information.
|
||||
@@ -904,23 +909,7 @@ namespace OpenSim.Groups
|
||||
{
|
||||
if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called for notice {1}", System.Reflection.MethodBase.GetCurrentMethod().Name, groupNoticeID);
|
||||
|
||||
//GroupRecord groupInfo = m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), data.GroupID, null);
|
||||
|
||||
GridInstantMessage msg = CreateGroupNoticeIM(remoteClient.AgentId, groupNoticeID, (byte)InstantMessageDialog.GroupNoticeRequested);
|
||||
//GridInstantMessage msg = new GridInstantMessage();
|
||||
//msg.imSessionID = UUID.Zero.Guid;
|
||||
//msg.fromAgentID = data.GroupID.Guid;
|
||||
//msg.toAgentID = GetRequestingAgentID(remoteClient).Guid;
|
||||
//msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
|
||||
//msg.fromAgentName = "Group Notice : " + groupInfo == null ? "Unknown" : groupInfo.GroupName;
|
||||
//msg.message = data.noticeData.Subject + "|" + data.Message;
|
||||
//msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.GroupNoticeRequested;
|
||||
//msg.fromGroup = true;
|
||||
//msg.offline = (byte)0;
|
||||
//msg.ParentEstateID = 0;
|
||||
//msg.Position = Vector3.Zero;
|
||||
//msg.RegionID = UUID.Zero.Guid;
|
||||
//msg.binaryBucket = data.BinaryBucket;
|
||||
|
||||
OutgoingInstantMessage(msg, GetRequestingAgentID(remoteClient));
|
||||
}
|
||||
@@ -1002,6 +991,10 @@ namespace OpenSim.Groups
|
||||
|
||||
// Should this send updates to everyone in the group?
|
||||
SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient));
|
||||
|
||||
if (reason != string.Empty)
|
||||
// A warning
|
||||
remoteClient.SendAlertMessage("Warning: " + reason);
|
||||
}
|
||||
else
|
||||
remoteClient.SendJoinGroupReply(groupID, false);
|
||||
@@ -1186,6 +1179,11 @@ namespace OpenSim.Groups
|
||||
}
|
||||
}
|
||||
|
||||
public List<DirGroupsReplyData> FindGroups(IClientAPI remoteClient, string query)
|
||||
{
|
||||
return m_groupData.FindGroups(GetRequestingAgentIDStr(remoteClient), query);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Client/Update Tools
|
||||
@@ -1225,12 +1223,16 @@ namespace OpenSim.Groups
|
||||
{
|
||||
if (m_debugEnabled) m_log.InfoFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||
|
||||
// NPCs currently don't have a CAPs structure or event queues. There is a strong argument for conveying this information
|
||||
// to them anyway since it makes writing server-side bots a lot easier, but for now we don't do anything.
|
||||
if (remoteClient.SceneAgent.PresenceType == PresenceType.Npc)
|
||||
return;
|
||||
|
||||
OSDArray AgentData = new OSDArray(1);
|
||||
OSDMap AgentDataMap = new OSDMap(1);
|
||||
AgentDataMap.Add("AgentID", OSD.FromUUID(dataForAgentID));
|
||||
AgentData.Add(AgentDataMap);
|
||||
|
||||
|
||||
OSDArray GroupData = new OSDArray(data.Length);
|
||||
OSDArray NewGroupData = new OSDArray(data.Length);
|
||||
|
||||
@@ -1276,8 +1278,7 @@ namespace OpenSim.Groups
|
||||
if (queue != null)
|
||||
{
|
||||
queue.Enqueue(queue.BuildEvent("AgentGroupDataUpdate", llDataStruct), GetRequestingAgentID(remoteClient));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void SendScenePresenceUpdate(UUID AgentID, string Title)
|
||||
@@ -1339,6 +1340,7 @@ namespace OpenSim.Groups
|
||||
|
||||
GroupMembershipData[] membershipArray = GetProfileListedGroupMemberships(remoteClient, dataForAgentID);
|
||||
SendGroupMembershipInfoViaCaps(remoteClient, dataForAgentID, membershipArray);
|
||||
|
||||
//remoteClient.SendAvatarGroupsReply(dataForAgentID, membershipArray);
|
||||
if (remoteClient.AgentId == dataForAgentID)
|
||||
remoteClient.RefreshGroupMembership();
|
||||
@@ -1399,19 +1401,18 @@ namespace OpenSim.Groups
|
||||
if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||
|
||||
// TODO: All the client update functions need to be reexamined because most do too much and send too much stuff
|
||||
UserAccount account = m_sceneList[0].UserAccountService.GetUserAccount(remoteClient.Scene.RegionInfo.ScopeID, dataForAgentID);
|
||||
string firstname, lastname;
|
||||
if (account != null)
|
||||
string firstname = "Unknown", lastname = "Unknown";
|
||||
string name = m_UserManagement.GetUserName(dataForAgentID);
|
||||
if (!string.IsNullOrEmpty(name))
|
||||
{
|
||||
firstname = account.FirstName;
|
||||
lastname = account.LastName;
|
||||
string[] parts = name.Split(new char[] { ' ' });
|
||||
if (parts.Length >= 2)
|
||||
{
|
||||
firstname = parts[0];
|
||||
lastname = parts[1];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
firstname = "Unknown";
|
||||
lastname = "Unknown";
|
||||
}
|
||||
|
||||
|
||||
remoteClient.SendAgentDataUpdate(dataForAgentID, activeGroupID, firstname,
|
||||
lastname, activeGroupPowers, activeGroupName,
|
||||
activeGroupTitle);
|
||||
|
||||
@@ -186,7 +186,6 @@ namespace OpenSim.Groups
|
||||
public UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment,
|
||||
bool allowPublish, bool maturePublish, UUID founderID, out string reason)
|
||||
{
|
||||
m_log.DebugFormat("[Groups]: Creating group {0}", name);
|
||||
reason = string.Empty;
|
||||
if (m_UserManagement.IsLocalGridUser(RequestingAgentID))
|
||||
return m_LocalGroupsConnector.CreateGroup(RequestingAgentID, name, charter, showInList, insigniaID,
|
||||
@@ -255,7 +254,10 @@ namespace OpenSim.Groups
|
||||
{
|
||||
string url = string.Empty, gname = string.Empty;
|
||||
if (IsLocal(GroupID, out url, out gname))
|
||||
return m_LocalGroupsConnector.GetGroupMembers(AgentUUI(RequestingAgentID), GroupID);
|
||||
{
|
||||
string agentID = AgentUUI(RequestingAgentID);
|
||||
return m_LocalGroupsConnector.GetGroupMembers(agentID, GroupID);
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(url))
|
||||
{
|
||||
ExtendedGroupMembershipData membership = m_LocalGroupsConnector.GetAgentGroupMembership(RequestingAgentID, RequestingAgentID, GroupID);
|
||||
@@ -397,17 +399,21 @@ namespace OpenSim.Groups
|
||||
|
||||
if (success)
|
||||
{
|
||||
// Here we always return true. The user has been added to the local group,
|
||||
// independent of whether the remote operation succeeds or not
|
||||
url = m_UserManagement.GetUserServerURL(uid, "GroupsServerURI");
|
||||
if (url == string.Empty)
|
||||
{
|
||||
reason = "User doesn't have a groups server";
|
||||
return false;
|
||||
reason = "You don't have an accessible groups server in your home world. You membership to this group in only within this grid.";
|
||||
return true;
|
||||
}
|
||||
|
||||
GroupsServiceHGConnector c = GetConnector(url);
|
||||
if (c != null)
|
||||
return c.CreateProxy(AgentUUI(RequestingAgentID), AgentID, token, GroupID, m_LocalGroupsServiceLocation, name, out reason);
|
||||
c.CreateProxy(AgentUUI(RequestingAgentID), AgentID, token, GroupID, m_LocalGroupsServiceLocation, name, out reason);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (m_UserManagement.IsLocalGridUser(uid)) // local user
|
||||
@@ -544,7 +550,6 @@ namespace OpenSim.Groups
|
||||
List<string> urls = new List<string>();
|
||||
foreach (GroupMembersData m in members)
|
||||
{
|
||||
UUID userID = UUID.Zero;
|
||||
if (!m_UserManagement.IsLocalGridUser(m.AgentID))
|
||||
{
|
||||
string gURL = m_UserManagement.GetUserServerURL(m.AgentID, "GroupsServerURI");
|
||||
@@ -592,28 +597,6 @@ namespace OpenSim.Groups
|
||||
return m_LocalGroupsConnector.GetGroupNotices(AgentUUI(RequestingAgentID), GroupID);
|
||||
}
|
||||
|
||||
public void ResetAgentGroupChatSessions(string agentID)
|
||||
{
|
||||
}
|
||||
|
||||
public bool hasAgentBeenInvitedToGroupChatSession(string agentID, UUID groupID)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool hasAgentDroppedGroupChatSession(string agentID, UUID groupID)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public void AgentDroppedFromGroupChatSession(string agentID, UUID groupID)
|
||||
{
|
||||
}
|
||||
|
||||
public void AgentInvitedToGroupChatSession(string agentID, UUID groupID)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region hypergrid groups
|
||||
@@ -685,6 +668,9 @@ namespace OpenSim.Groups
|
||||
{
|
||||
serviceLocation = string.Empty;
|
||||
name = string.Empty;
|
||||
if (groupID.Equals(UUID.Zero))
|
||||
return true;
|
||||
|
||||
ExtendedGroupRecord group = m_LocalGroupsConnector.GetGroupRecord(UUID.Zero.ToString(), groupID, string.Empty);
|
||||
if (group == null)
|
||||
{
|
||||
|
||||
@@ -47,7 +47,6 @@ namespace OpenSim.Groups
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private HGGroupsService m_GroupsService;
|
||||
private string m_HomeURI = string.Empty;
|
||||
private string m_ConfigName = "Groups";
|
||||
|
||||
// Called by Robust shell
|
||||
@@ -113,7 +112,7 @@ namespace OpenSim.Groups
|
||||
m_GroupsService = service;
|
||||
}
|
||||
|
||||
public override byte[] Handle(string path, Stream requestData,
|
||||
protected override byte[] ProcessRequest(string path, Stream requestData,
|
||||
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||
{
|
||||
StreamReader sr = new StreamReader(requestData);
|
||||
@@ -209,7 +208,6 @@ namespace OpenSim.Groups
|
||||
UUID groupID = new UUID(request["GroupID"].ToString());
|
||||
string agentID = request["AgentID"].ToString();
|
||||
string token = request["AccessToken"].ToString();
|
||||
string reason = string.Empty;
|
||||
|
||||
m_GroupsService.RemoveAgentFromGroup(agentID, agentID, groupID, token);
|
||||
}
|
||||
|
||||
@@ -92,12 +92,6 @@ namespace OpenSim.Groups
|
||||
GroupNoticeInfo GetGroupNotice(string RequestingAgentID, UUID noticeID);
|
||||
List<ExtendedGroupNoticeData> GetGroupNotices(string RequestingAgentID, UUID GroupID);
|
||||
|
||||
void ResetAgentGroupChatSessions(string agentID);
|
||||
bool hasAgentBeenInvitedToGroupChatSession(string agentID, UUID groupID);
|
||||
bool hasAgentDroppedGroupChatSession(string agentID, UUID groupID);
|
||||
void AgentDroppedFromGroupChatSession(string agentID, UUID groupID);
|
||||
void AgentInvitedToGroupChatSession(string agentID, UUID groupID);
|
||||
|
||||
}
|
||||
|
||||
public class GroupInviteInfo
|
||||
|
||||
@@ -320,28 +320,6 @@ namespace OpenSim.Groups
|
||||
return m_GroupsService.GetGroupNotices(RequestingAgentID, GroupID);
|
||||
}
|
||||
|
||||
public void ResetAgentGroupChatSessions(string agentID)
|
||||
{
|
||||
}
|
||||
|
||||
public bool hasAgentBeenInvitedToGroupChatSession(string agentID, UUID groupID)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool hasAgentDroppedGroupChatSession(string agentID, UUID groupID)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public void AgentDroppedFromGroupChatSession(string agentID, UUID groupID)
|
||||
{
|
||||
}
|
||||
|
||||
public void AgentInvitedToGroupChatSession(string agentID, UUID groupID)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,6 +133,36 @@ namespace OpenSim.Groups
|
||||
return GroupsDataUtils.GroupRecord((Dictionary<string, object>)ret["RESULT"]);
|
||||
}
|
||||
|
||||
public List<DirGroupsReplyData> FindGroups(string RequestingAgentID, string query)
|
||||
{
|
||||
List<DirGroupsReplyData> hits = new List<DirGroupsReplyData>();
|
||||
if (string.IsNullOrEmpty(query))
|
||||
return hits;
|
||||
|
||||
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||
sendData["Query"] = query;
|
||||
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||
|
||||
Dictionary<string, object> ret = MakeRequest("FINDGROUPS", sendData);
|
||||
|
||||
if (ret == null)
|
||||
return hits;
|
||||
|
||||
if (!ret.ContainsKey("RESULT"))
|
||||
return hits;
|
||||
|
||||
if (ret["RESULT"].ToString() == "NULL")
|
||||
return hits;
|
||||
|
||||
foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
|
||||
{
|
||||
DirGroupsReplyData m = GroupsDataUtils.DirGroupsReplyData((Dictionary<string, object>)v);
|
||||
hits.Add(m);
|
||||
}
|
||||
|
||||
return hits;
|
||||
}
|
||||
|
||||
public GroupMembershipData AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string token, out string reason)
|
||||
{
|
||||
reason = string.Empty;
|
||||
@@ -226,6 +256,7 @@ namespace OpenSim.Groups
|
||||
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||
sendData["GroupID"] = GroupID.ToString();
|
||||
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||
|
||||
Dictionary<string, object> ret = MakeRequest("GETGROUPMEMBERS", sendData);
|
||||
|
||||
if (ret == null)
|
||||
|
||||
@@ -199,7 +199,7 @@ namespace OpenSim.Groups
|
||||
public List<DirGroupsReplyData> FindGroups(string RequestingAgentID, string search)
|
||||
{
|
||||
// TODO!
|
||||
return new List<DirGroupsReplyData>();
|
||||
return m_GroupsService.FindGroups(RequestingAgentID, search);
|
||||
}
|
||||
|
||||
public bool AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string token, out string reason)
|
||||
@@ -406,28 +406,6 @@ namespace OpenSim.Groups
|
||||
});
|
||||
}
|
||||
|
||||
public void ResetAgentGroupChatSessions(string agentID)
|
||||
{
|
||||
}
|
||||
|
||||
public bool hasAgentBeenInvitedToGroupChatSession(string agentID, UUID groupID)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool hasAgentDroppedGroupChatSession(string agentID, UUID groupID)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public void AgentDroppedFromGroupChatSession(string agentID, UUID groupID)
|
||||
{
|
||||
}
|
||||
|
||||
public void AgentInvitedToGroupChatSession(string agentID, UUID groupID)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace OpenSim.Groups
|
||||
m_GroupsService = service;
|
||||
}
|
||||
|
||||
public override byte[] Handle(string path, Stream requestData,
|
||||
protected override byte[] ProcessRequest(string path, Stream requestData,
|
||||
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||
{
|
||||
StreamReader sr = new StreamReader(requestData);
|
||||
@@ -133,6 +133,8 @@ namespace OpenSim.Groups
|
||||
return HandleAddNotice(request);
|
||||
case "GETNOTICES":
|
||||
return HandleGetNotices(request);
|
||||
case "FINDGROUPS":
|
||||
return HandleFindGroups(request);
|
||||
}
|
||||
m_log.DebugFormat("[GROUPS HANDLER]: unknown method request: {0}", method);
|
||||
}
|
||||
@@ -170,11 +172,16 @@ namespace OpenSim.Groups
|
||||
|
||||
}
|
||||
|
||||
grec = m_GroupsService.GetGroupRecord(RequestingAgentID, grec.GroupID);
|
||||
if (grec == null)
|
||||
NullResult(result, "Internal Error");
|
||||
if (grec.GroupID != UUID.Zero)
|
||||
{
|
||||
grec = m_GroupsService.GetGroupRecord(RequestingAgentID, grec.GroupID);
|
||||
if (grec == null)
|
||||
NullResult(result, "Internal Error");
|
||||
else
|
||||
result["RESULT"] = GroupsDataUtils.GroupRecord(grec);
|
||||
}
|
||||
else
|
||||
result["RESULT"] = GroupsDataUtils.GroupRecord(grec);
|
||||
NullResult(result, reason);
|
||||
}
|
||||
|
||||
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||
@@ -264,7 +271,6 @@ namespace OpenSim.Groups
|
||||
UUID groupID = new UUID(request["GroupID"].ToString());
|
||||
string agentID = request["AgentID"].ToString();
|
||||
string requestingAgentID = request["RequestingAgentID"].ToString();
|
||||
string reason = string.Empty;
|
||||
|
||||
m_GroupsService.RemoveAgentFromGroup(requestingAgentID, agentID, groupID);
|
||||
}
|
||||
@@ -495,7 +501,6 @@ namespace OpenSim.Groups
|
||||
else
|
||||
{
|
||||
string op = request["OP"].ToString();
|
||||
string reason = string.Empty;
|
||||
|
||||
bool success = false;
|
||||
if (op == "ADD")
|
||||
@@ -563,7 +568,6 @@ namespace OpenSim.Groups
|
||||
else
|
||||
{
|
||||
string op = request["OP"].ToString();
|
||||
string reason = string.Empty;
|
||||
|
||||
if (op == "GROUP")
|
||||
{
|
||||
@@ -626,7 +630,6 @@ namespace OpenSim.Groups
|
||||
else
|
||||
{
|
||||
string op = request["OP"].ToString();
|
||||
string reason = string.Empty;
|
||||
|
||||
if (op == "ADD" && request.ContainsKey("GroupID") && request.ContainsKey("RoleID") && request.ContainsKey("AgentID"))
|
||||
{
|
||||
@@ -739,6 +742,32 @@ namespace OpenSim.Groups
|
||||
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||
}
|
||||
|
||||
byte[] HandleFindGroups(Dictionary<string, object> request)
|
||||
{
|
||||
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||
|
||||
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("Query"))
|
||||
NullResult(result, "Bad network data");
|
||||
|
||||
List<DirGroupsReplyData> hits = m_GroupsService.FindGroups(request["RequestingAgentID"].ToString(), request["Query"].ToString());
|
||||
|
||||
if (hits == null || (hits != null && hits.Count == 0))
|
||||
NullResult(result, "No hits");
|
||||
else
|
||||
{
|
||||
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||
int i = 0;
|
||||
foreach (DirGroupsReplyData n in hits)
|
||||
dict["n-" + i++] = GroupsDataUtils.DirGroupsReplyData(n);
|
||||
|
||||
result["RESULT"] = dict;
|
||||
}
|
||||
|
||||
|
||||
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||
}
|
||||
|
||||
|
||||
#region Helpers
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace OpenSim.Groups
|
||||
private ForeignImporter m_ForeignImporter;
|
||||
|
||||
private Dictionary<string, bool> m_ActiveRequests = new Dictionary<string, bool>();
|
||||
private const int GROUPS_CACHE_TIMEOUT = 5 * 60; // 5 minutes
|
||||
private const int GROUPS_CACHE_TIMEOUT = 1 * 60; // 1 minutes
|
||||
|
||||
// This all important cache cahces objects of different types:
|
||||
// group-<GroupID> or group-<Name> => ExtendedGroupRecord
|
||||
@@ -209,13 +209,10 @@ namespace OpenSim.Groups
|
||||
public void SetAgentActiveGroup(string AgentID, GroupMembershipDelegate d)
|
||||
{
|
||||
GroupMembershipData activeGroup = d();
|
||||
if (activeGroup != null)
|
||||
{
|
||||
string cacheKey = "active-" + AgentID.ToString();
|
||||
lock (m_Cache)
|
||||
if (m_Cache.Contains(cacheKey))
|
||||
m_Cache.AddOrUpdate(cacheKey, activeGroup, GROUPS_CACHE_TIMEOUT);
|
||||
}
|
||||
string cacheKey = "active-" + AgentID.ToString();
|
||||
lock (m_Cache)
|
||||
if (m_Cache.Contains(cacheKey))
|
||||
m_Cache.AddOrUpdate(cacheKey, activeGroup, GROUPS_CACHE_TIMEOUT);
|
||||
}
|
||||
|
||||
public ExtendedGroupMembershipData GetAgentActiveMembership(string AgentID, GroupMembershipDelegate d)
|
||||
|
||||
@@ -130,6 +130,13 @@ namespace OpenSim.Groups
|
||||
{
|
||||
reason = string.Empty;
|
||||
|
||||
// Check if the group already exists
|
||||
if (m_Database.RetrieveGroup(name) != null)
|
||||
{
|
||||
reason = "A group with that name already exists";
|
||||
return UUID.Zero;
|
||||
}
|
||||
|
||||
// Create the group
|
||||
GroupData data = new GroupData();
|
||||
data.GroupID = UUID.Random();
|
||||
@@ -248,13 +255,20 @@ namespace OpenSim.Groups
|
||||
return members;
|
||||
List<RoleData> rolesList = new List<RoleData>(roles);
|
||||
|
||||
// Is the requester a member of the group?
|
||||
bool isInGroup = false;
|
||||
if (m_Database.RetrieveMember(GroupID, RequestingAgentID) != null)
|
||||
isInGroup = true;
|
||||
// Check visibility?
|
||||
// When we don't want to check visibility, we pass it "all" as the requestingAgentID
|
||||
bool checkVisibility = !RequestingAgentID.Equals(UUID.Zero.ToString());
|
||||
|
||||
if (!isInGroup) // reduce the roles to the visible ones
|
||||
rolesList = rolesList.FindAll(r => (UInt64.Parse(r.Data["Powers"]) & (ulong)GroupPowers.MemberVisible) != 0);
|
||||
if (checkVisibility)
|
||||
{
|
||||
// Is the requester a member of the group?
|
||||
bool isInGroup = false;
|
||||
if (m_Database.RetrieveMember(GroupID, RequestingAgentID) != null)
|
||||
isInGroup = true;
|
||||
|
||||
if (!isInGroup) // reduce the roles to the visible ones
|
||||
rolesList = rolesList.FindAll(r => (UInt64.Parse(r.Data["Powers"]) & (ulong)GroupPowers.MemberVisible) != 0);
|
||||
}
|
||||
|
||||
MembershipData[] datas = m_Database.RetrieveMembers(GroupID);
|
||||
if (datas == null || (datas != null && datas.Length == 0))
|
||||
@@ -723,12 +737,12 @@ namespace OpenSim.Groups
|
||||
|
||||
#region Actions without permission checks
|
||||
|
||||
private void _AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
|
||||
protected void _AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
|
||||
{
|
||||
_AddAgentToGroup(RequestingAgentID, AgentID, GroupID, RoleID, string.Empty);
|
||||
}
|
||||
|
||||
public void _RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||
protected void _RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||
{
|
||||
// 1. Delete membership
|
||||
m_Database.DeleteMember(GroupID, AgentID);
|
||||
@@ -780,7 +794,7 @@ namespace OpenSim.Groups
|
||||
|
||||
}
|
||||
|
||||
private bool _AddOrUpdateGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, bool add)
|
||||
protected bool _AddOrUpdateGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, bool add)
|
||||
{
|
||||
RoleData data = m_Database.RetrieveRole(groupID, roleID);
|
||||
|
||||
@@ -810,12 +824,12 @@ namespace OpenSim.Groups
|
||||
return m_Database.StoreRole(data);
|
||||
}
|
||||
|
||||
private void _RemoveGroupRole(UUID groupID, UUID roleID)
|
||||
protected void _RemoveGroupRole(UUID groupID, UUID roleID)
|
||||
{
|
||||
m_Database.DeleteRole(groupID, roleID);
|
||||
}
|
||||
|
||||
private void _AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
|
||||
protected void _AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
|
||||
{
|
||||
RoleMembershipData data = m_Database.RetrieveRoleMember(GroupID, RoleID, AgentID);
|
||||
if (data != null)
|
||||
@@ -840,7 +854,7 @@ namespace OpenSim.Groups
|
||||
|
||||
}
|
||||
|
||||
private List<GroupRolesData> _GetGroupRoles(UUID groupID)
|
||||
protected List<GroupRolesData> _GetGroupRoles(UUID groupID)
|
||||
{
|
||||
List<GroupRolesData> roles = new List<GroupRolesData>();
|
||||
|
||||
@@ -865,7 +879,7 @@ namespace OpenSim.Groups
|
||||
return roles;
|
||||
}
|
||||
|
||||
private List<ExtendedGroupRoleMembersData> _GetGroupRoleMembers(UUID GroupID, bool isInGroup)
|
||||
protected List<ExtendedGroupRoleMembersData> _GetGroupRoleMembers(UUID GroupID, bool isInGroup)
|
||||
{
|
||||
List<ExtendedGroupRoleMembersData> rmembers = new List<ExtendedGroupRoleMembersData>();
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace OpenSim.OfflineIM
|
||||
m_OfflineIMService = service;
|
||||
}
|
||||
|
||||
public override byte[] Handle(string path, Stream requestData,
|
||||
protected override byte[] ProcessRequest(string path, Stream requestData,
|
||||
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||
{
|
||||
StreamReader sr = new StreamReader(requestData);
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace OpenSim.OfflineIM
|
||||
{
|
||||
public class OfflineIMService : OfflineIMServiceBase, IOfflineIMService
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private const int MAX_IM = 25;
|
||||
|
||||
private XmlSerializer m_serializer;
|
||||
|
||||
@@ -115,6 +115,8 @@ namespace OpenSim.ApplicationPlugins.LoadRegions
|
||||
Environment.Exit(1);
|
||||
}
|
||||
|
||||
List<IScene> createdScenes = new List<IScene>();
|
||||
|
||||
for (int i = 0; i < regionsToLoad.Length; i++)
|
||||
{
|
||||
IScene scene;
|
||||
@@ -123,17 +125,22 @@ namespace OpenSim.ApplicationPlugins.LoadRegions
|
||||
")");
|
||||
|
||||
bool changed = m_openSim.PopulateRegionEstateInfo(regionsToLoad[i]);
|
||||
|
||||
m_openSim.CreateRegion(regionsToLoad[i], true, out scene);
|
||||
createdScenes.Add(scene);
|
||||
|
||||
if (changed)
|
||||
regionsToLoad[i].EstateSettings.Save();
|
||||
|
||||
if (scene != null)
|
||||
regionsToLoad[i].EstateSettings.Save();
|
||||
}
|
||||
|
||||
foreach (IScene scene in createdScenes)
|
||||
{
|
||||
scene.Start();
|
||||
|
||||
m_newRegionCreatedHandler = OnNewRegionCreated;
|
||||
if (m_newRegionCreatedHandler != null)
|
||||
{
|
||||
m_newRegionCreatedHandler = OnNewRegionCreated;
|
||||
if (m_newRegionCreatedHandler != null)
|
||||
{
|
||||
m_newRegionCreatedHandler(scene);
|
||||
}
|
||||
m_newRegionCreatedHandler(scene);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ using OpenSim.Region.Framework.Scenes;
|
||||
using OpenSim.Services.Interfaces;
|
||||
using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
|
||||
using GridRegion = OpenSim.Services.Interfaces.GridRegion;
|
||||
using PermissionMask = OpenSim.Framework.PermissionMask;
|
||||
|
||||
namespace OpenSim.ApplicationPlugins.RemoteController
|
||||
{
|
||||
@@ -136,6 +137,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
||||
availableMethods["admin_save_heightmap"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcSaveHeightmapMethod);
|
||||
|
||||
// Agent management
|
||||
availableMethods["admin_get_agents"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcGetAgentsMethod);
|
||||
availableMethods["admin_teleport_agent"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcTeleportAgentMethod);
|
||||
|
||||
// User management
|
||||
@@ -155,6 +157,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
||||
availableMethods["admin_acl_add"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcAccessListAdd);
|
||||
availableMethods["admin_acl_remove"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcAccessListRemove);
|
||||
availableMethods["admin_acl_list"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcAccessListList);
|
||||
availableMethods["admin_estate_reload"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcEstateReload);
|
||||
|
||||
// Either enable full remote functionality or just selected features
|
||||
string enabledMethods = m_config.GetString("enabled_methods", "all");
|
||||
@@ -324,18 +327,26 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
||||
// k, (string)requestData[k], ((string)requestData[k]).Length);
|
||||
// }
|
||||
|
||||
CheckStringParameters(requestData, responseData, new string[] {"filename", "regionid"});
|
||||
CheckStringParameters(requestData, responseData, new string[] { "filename" });
|
||||
CheckRegionParams(requestData, responseData);
|
||||
|
||||
Scene scene = null;
|
||||
GetSceneFromRegionParams(requestData, responseData, out scene);
|
||||
string file = (string)requestData["filename"];
|
||||
|
||||
responseData["accepted"] = true;
|
||||
if (scene != null)
|
||||
{
|
||||
string file = (string)requestData["filename"];
|
||||
|
||||
LoadHeightmap(file, scene.RegionInfo.RegionID);
|
||||
responseData["accepted"] = true;
|
||||
|
||||
responseData["success"] = true;
|
||||
LoadHeightmap(file, scene.RegionInfo.RegionID);
|
||||
|
||||
responseData["success"] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
responseData["success"] = false;
|
||||
}
|
||||
|
||||
m_log.Info("[RADMIN]: Load height maps request complete");
|
||||
}
|
||||
@@ -349,23 +360,30 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
||||
|
||||
// m_log.DebugFormat("[RADMIN]: Save Terrain: XmlRpc {0}", request.ToString());
|
||||
|
||||
CheckStringParameters(requestData, responseData, new string[] { "filename", "regionid" });
|
||||
CheckStringParameters(requestData, responseData, new string[] { "filename" });
|
||||
CheckRegionParams(requestData, responseData);
|
||||
|
||||
Scene region = null;
|
||||
GetSceneFromRegionParams(requestData, responseData, out region);
|
||||
Scene scene = null;
|
||||
GetSceneFromRegionParams(requestData, responseData, out scene);
|
||||
|
||||
string file = (string)requestData["filename"];
|
||||
m_log.InfoFormat("[RADMIN]: Terrain Saving: {0}", file);
|
||||
if (scene != null)
|
||||
{
|
||||
string file = (string)requestData["filename"];
|
||||
m_log.InfoFormat("[RADMIN]: Terrain Saving: {0}", file);
|
||||
|
||||
responseData["accepted"] = true;
|
||||
responseData["accepted"] = true;
|
||||
|
||||
ITerrainModule terrainModule = region.RequestModuleInterface<ITerrainModule>();
|
||||
if (null == terrainModule) throw new Exception("terrain module not available");
|
||||
ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>();
|
||||
if (null == terrainModule) throw new Exception("terrain module not available");
|
||||
|
||||
terrainModule.SaveToFile(file);
|
||||
terrainModule.SaveToFile(file);
|
||||
|
||||
responseData["success"] = true;
|
||||
responseData["success"] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
responseData["success"] = false;
|
||||
}
|
||||
|
||||
m_log.Info("[RADMIN]: Save height maps request complete");
|
||||
}
|
||||
@@ -698,6 +716,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
||||
|
||||
IScene newScene;
|
||||
m_application.CreateRegion(region, out newScene);
|
||||
newScene.Start();
|
||||
|
||||
// If an access specification was provided, use it.
|
||||
// Otherwise accept the default.
|
||||
@@ -1092,7 +1111,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
||||
{
|
||||
GridUserInfo userInfo = m_application.SceneManager.CurrentOrFirstScene.GridUserService.GetGridUserInfo(account.PrincipalID.ToString());
|
||||
if (userInfo != null)
|
||||
responseData["lastlogin"] = userInfo.Login;
|
||||
responseData["lastlogin"] = Util.ToUnixTime(userInfo.Login);
|
||||
else
|
||||
responseData["lastlogin"] = 0;
|
||||
|
||||
@@ -1759,6 +1778,87 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
||||
m_log.Info("[RADMIN]: Access List List Request complete");
|
||||
}
|
||||
|
||||
private void XmlRpcEstateReload(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient)
|
||||
{
|
||||
m_log.Info("[RADMIN]: Received Estate Reload Request");
|
||||
|
||||
Hashtable responseData = (Hashtable)response.Value;
|
||||
// Hashtable requestData = (Hashtable)request.Params[0];
|
||||
|
||||
m_application.SceneManager.ForEachScene(s =>
|
||||
s.RegionInfo.EstateSettings = m_application.EstateDataService.LoadEstateSettings(s.RegionInfo.RegionID, false)
|
||||
);
|
||||
|
||||
responseData["success"] = true;
|
||||
|
||||
m_log.Info("[RADMIN]: Estate Reload Request complete");
|
||||
}
|
||||
|
||||
private void XmlRpcGetAgentsMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient)
|
||||
{
|
||||
Hashtable responseData = (Hashtable)response.Value;
|
||||
Hashtable requestData = (Hashtable)request.Params[0];
|
||||
|
||||
bool includeChildren = false;
|
||||
|
||||
if (requestData.Contains("include_children"))
|
||||
bool.TryParse((string)requestData["include_children"], out includeChildren);
|
||||
|
||||
Scene scene;
|
||||
GetSceneFromRegionParams(requestData, responseData, out scene);
|
||||
|
||||
ArrayList xmlRpcRegions = new ArrayList();
|
||||
responseData["regions"] = xmlRpcRegions;
|
||||
|
||||
Hashtable xmlRpcRegion = new Hashtable();
|
||||
xmlRpcRegions.Add(xmlRpcRegion);
|
||||
|
||||
xmlRpcRegion["name"] = scene.Name;
|
||||
xmlRpcRegion["id"] = scene.RegionInfo.RegionID.ToString();
|
||||
|
||||
List<ScenePresence> agents = scene.GetScenePresences();
|
||||
ArrayList xmlrpcAgents = new ArrayList();
|
||||
|
||||
foreach (ScenePresence agent in agents)
|
||||
{
|
||||
if (agent.IsChildAgent && !includeChildren)
|
||||
continue;
|
||||
|
||||
Hashtable xmlRpcAgent = new Hashtable();
|
||||
xmlRpcAgent.Add("name", agent.Name);
|
||||
xmlRpcAgent.Add("id", agent.UUID.ToString());
|
||||
xmlRpcAgent.Add("type", agent.PresenceType.ToString());
|
||||
xmlRpcAgent.Add("current_parcel_id", agent.currentParcelUUID.ToString());
|
||||
|
||||
Vector3 pos = agent.AbsolutePosition;
|
||||
xmlRpcAgent.Add("pos_x", pos.X.ToString());
|
||||
xmlRpcAgent.Add("pos_y", pos.Y.ToString());
|
||||
xmlRpcAgent.Add("pos_z", pos.Z.ToString());
|
||||
|
||||
Vector3 lookAt = agent.Lookat;
|
||||
xmlRpcAgent.Add("lookat_x", lookAt.X.ToString());
|
||||
xmlRpcAgent.Add("lookat_y", lookAt.Y.ToString());
|
||||
xmlRpcAgent.Add("lookat_z", lookAt.Z.ToString());
|
||||
|
||||
Vector3 vel = agent.Velocity;
|
||||
xmlRpcAgent.Add("vel_x", vel.X.ToString());
|
||||
xmlRpcAgent.Add("vel_y", vel.Y.ToString());
|
||||
xmlRpcAgent.Add("vel_z", vel.Z.ToString());
|
||||
|
||||
xmlRpcAgent.Add("is_flying", agent.Flying.ToString());
|
||||
xmlRpcAgent.Add("is_sat_on_ground", agent.SitGround.ToString());
|
||||
xmlRpcAgent.Add("is_sat_on_object", agent.IsSatOnObject.ToString());
|
||||
|
||||
xmlrpcAgents.Add(xmlRpcAgent);
|
||||
}
|
||||
|
||||
m_log.DebugFormat(
|
||||
"[REMOTE ADMIN]: XmlRpcGetAgents found {0} agents in {1}", xmlrpcAgents.Count, scene.Name);
|
||||
|
||||
xmlRpcRegion["agents"] = xmlrpcAgents;
|
||||
responseData["success"] = true;
|
||||
}
|
||||
|
||||
private void XmlRpcTeleportAgentMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient)
|
||||
{
|
||||
Hashtable responseData = (Hashtable)response.Value;
|
||||
|
||||
@@ -63,7 +63,11 @@ namespace OpenSim.Framework.Capabilities
|
||||
public string CapsObjectPath { get { return m_capsObjectPath; } }
|
||||
|
||||
private CapsHandlers m_capsHandlers;
|
||||
private Dictionary<string, string> m_externalCapsHandlers;
|
||||
|
||||
private Dictionary<string, PollServiceEventArgs> m_pollServiceHandlers
|
||||
= new Dictionary<string, PollServiceEventArgs>();
|
||||
|
||||
private Dictionary<string, string> m_externalCapsHandlers = new Dictionary<string, string>();
|
||||
|
||||
private IHttpServer m_httpListener;
|
||||
private UUID m_agentID;
|
||||
@@ -132,7 +136,6 @@ namespace OpenSim.Framework.Capabilities
|
||||
|
||||
m_agentID = agent;
|
||||
m_capsHandlers = new CapsHandlers(httpServer, httpListen, httpPort, (httpServer == null) ? false : httpServer.UseSSL);
|
||||
m_externalCapsHandlers = new Dictionary<string, string>();
|
||||
m_regionName = regionName;
|
||||
}
|
||||
|
||||
@@ -143,8 +146,29 @@ namespace OpenSim.Framework.Capabilities
|
||||
/// <param name="handler"></param>
|
||||
public void RegisterHandler(string capName, IRequestHandler handler)
|
||||
{
|
||||
m_capsHandlers[capName] = handler;
|
||||
//m_log.DebugFormat("[CAPS]: Registering handler for \"{0}\": path {1}", capName, handler.Path);
|
||||
m_capsHandlers[capName] = handler;
|
||||
}
|
||||
|
||||
public void RegisterPollHandler(string capName, PollServiceEventArgs pollServiceHandler)
|
||||
{
|
||||
m_pollServiceHandlers.Add(capName, pollServiceHandler);
|
||||
|
||||
m_httpListener.AddPollServiceHTTPHandler(pollServiceHandler.Url, pollServiceHandler);
|
||||
|
||||
// uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
|
||||
// string protocol = "http";
|
||||
// string hostName = m_httpListenerHostName;
|
||||
//
|
||||
// if (MainServer.Instance.UseSSL)
|
||||
// {
|
||||
// hostName = MainServer.Instance.SSLCommonName;
|
||||
// port = MainServer.Instance.SSLPort;
|
||||
// protocol = "https";
|
||||
// }
|
||||
|
||||
// RegisterHandler(
|
||||
// capName, String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, pollServiceHandler.Url));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -163,13 +187,70 @@ namespace OpenSim.Framework.Capabilities
|
||||
/// </summary>
|
||||
public void DeregisterHandlers()
|
||||
{
|
||||
if (m_capsHandlers != null)
|
||||
foreach (string capsName in m_capsHandlers.Caps)
|
||||
{
|
||||
foreach (string capsName in m_capsHandlers.Caps)
|
||||
{
|
||||
m_capsHandlers.Remove(capsName);
|
||||
}
|
||||
m_capsHandlers.Remove(capsName);
|
||||
}
|
||||
|
||||
foreach (PollServiceEventArgs handler in m_pollServiceHandlers.Values)
|
||||
{
|
||||
m_httpListener.RemovePollServiceHTTPHandler("", handler.Url);
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryGetPollHandler(string name, out PollServiceEventArgs pollHandler)
|
||||
{
|
||||
return m_pollServiceHandlers.TryGetValue(name, out pollHandler);
|
||||
}
|
||||
|
||||
public Dictionary<string, PollServiceEventArgs> GetPollHandlers()
|
||||
{
|
||||
return new Dictionary<string, PollServiceEventArgs>(m_pollServiceHandlers);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return an LLSD-serializable Hashtable describing the
|
||||
/// capabilities and their handler details.
|
||||
/// </summary>
|
||||
/// <param name="excludeSeed">If true, then exclude the seed cap.</param>
|
||||
public Hashtable GetCapsDetails(bool excludeSeed, List<string> requestedCaps)
|
||||
{
|
||||
Hashtable caps = CapsHandlers.GetCapsDetails(excludeSeed, requestedCaps);
|
||||
|
||||
lock (m_pollServiceHandlers)
|
||||
{
|
||||
foreach (KeyValuePair <string, PollServiceEventArgs> kvp in m_pollServiceHandlers)
|
||||
{
|
||||
if (!requestedCaps.Contains(kvp.Key))
|
||||
continue;
|
||||
|
||||
string hostName = m_httpListenerHostName;
|
||||
uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
|
||||
string protocol = "http";
|
||||
|
||||
if (MainServer.Instance.UseSSL)
|
||||
{
|
||||
hostName = MainServer.Instance.SSLCommonName;
|
||||
port = MainServer.Instance.SSLPort;
|
||||
protocol = "https";
|
||||
}
|
||||
//
|
||||
// caps.RegisterHandler("FetchInventoryDescendents2", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
|
||||
|
||||
caps[kvp.Key] = string.Format("{0}://{1}:{2}{3}", protocol, hostName, port, kvp.Value.Url);
|
||||
}
|
||||
}
|
||||
|
||||
// Add the external too
|
||||
foreach (KeyValuePair<string, string> kvp in ExternalCapsHandlers)
|
||||
{
|
||||
if (!requestedCaps.Contains(kvp.Key))
|
||||
continue;
|
||||
|
||||
caps[kvp.Key] = kvp.Value;
|
||||
}
|
||||
|
||||
return caps;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,7 @@ namespace OpenSim.Framework.Capabilities
|
||||
/// </summary>
|
||||
public class CapsHandlers
|
||||
{
|
||||
private Dictionary <string, IRequestHandler> m_capsHandlers = new Dictionary<string, IRequestHandler>();
|
||||
private Dictionary<string, IRequestHandler> m_capsHandlers = new Dictionary<string, IRequestHandler>();
|
||||
private IHttpServer m_httpListener;
|
||||
private string m_httpListenerHostName;
|
||||
private uint m_httpListenerPort;
|
||||
@@ -158,7 +158,7 @@ namespace OpenSim.Framework.Capabilities
|
||||
/// capabilities and their handler details.
|
||||
/// </summary>
|
||||
/// <param name="excludeSeed">If true, then exclude the seed cap.</param>
|
||||
public Hashtable GetCapsDetails(bool excludeSeed)
|
||||
public Hashtable GetCapsDetails(bool excludeSeed, List<string> requestedCaps)
|
||||
{
|
||||
Hashtable caps = new Hashtable();
|
||||
string protocol = "http://";
|
||||
@@ -175,11 +175,26 @@ namespace OpenSim.Framework.Capabilities
|
||||
if (excludeSeed && "SEED" == capsName)
|
||||
continue;
|
||||
|
||||
if (requestedCaps != null && !requestedCaps.Contains(capsName))
|
||||
continue;
|
||||
|
||||
caps[capsName] = baseUrl + m_capsHandlers[capsName].Path;
|
||||
}
|
||||
}
|
||||
|
||||
return caps;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a copy of the dictionary of all the HTTP cap handlers
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The dictionary copy. The key is the capability name, the value is the HTTP handler.
|
||||
/// </returns>
|
||||
public Dictionary<string, IRequestHandler> GetCapsHandlers()
|
||||
{
|
||||
lock (m_capsHandlers)
|
||||
return new Dictionary<string, IRequestHandler>(m_capsHandlers);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* 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 the OpenSimulator Project 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 DEVELOPERS ``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 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Web;
|
||||
using log4net;
|
||||
using Nini.Config;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Capabilities;
|
||||
using OpenSim.Framework.Servers;
|
||||
using OpenSim.Framework.Servers.HttpServer;
|
||||
//using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Services.Interfaces;
|
||||
using Caps = OpenSim.Framework.Capabilities.Caps;
|
||||
|
||||
namespace OpenSim.Capabilities.Handlers
|
||||
{
|
||||
public class AvatarPickerSearchHandler : BaseStreamHandler
|
||||
{
|
||||
private static readonly ILog m_log =
|
||||
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private IPeople m_PeopleService;
|
||||
|
||||
public AvatarPickerSearchHandler(string path, IPeople peopleService, string name, string description)
|
||||
: base("GET", path, name, description)
|
||||
{
|
||||
m_PeopleService = peopleService;
|
||||
}
|
||||
|
||||
protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||
{
|
||||
// Try to parse the texture ID from the request URL
|
||||
NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query);
|
||||
string names = query.GetOne("names");
|
||||
string psize = query.GetOne("page_size");
|
||||
string pnumber = query.GetOne("page");
|
||||
|
||||
if (m_PeopleService == null)
|
||||
return FailureResponse(names, (int)System.Net.HttpStatusCode.InternalServerError, httpResponse);
|
||||
|
||||
if (string.IsNullOrEmpty(names) || names.Length < 3)
|
||||
return FailureResponse(names, (int)System.Net.HttpStatusCode.BadRequest, httpResponse);
|
||||
|
||||
m_log.DebugFormat("[AVATAR PICKER SEARCH]: search for {0}", names);
|
||||
|
||||
int page_size = (string.IsNullOrEmpty(psize) ? 500 : Int32.Parse(psize));
|
||||
int page_number = (string.IsNullOrEmpty(pnumber) ? 1 : Int32.Parse(pnumber));
|
||||
|
||||
// Full content request
|
||||
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.OK;
|
||||
//httpResponse.ContentLength = ??;
|
||||
httpResponse.ContentType = "application/llsd+xml";
|
||||
|
||||
List<UserData> users = m_PeopleService.GetUserData(names, page_size, page_number);
|
||||
|
||||
LLSDAvatarPicker osdReply = new LLSDAvatarPicker();
|
||||
osdReply.next_page_url = httpRequest.RawUrl;
|
||||
foreach (UserData u in users)
|
||||
osdReply.agents.Array.Add(ConvertUserData(u));
|
||||
|
||||
string reply = LLSDHelpers.SerialiseLLSDReply(osdReply);
|
||||
return System.Text.Encoding.UTF8.GetBytes(reply);
|
||||
}
|
||||
|
||||
private LLSDPerson ConvertUserData(UserData user)
|
||||
{
|
||||
LLSDPerson p = new LLSDPerson();
|
||||
p.legacy_first_name = user.FirstName;
|
||||
p.legacy_last_name = user.LastName;
|
||||
p.display_name = user.FirstName + " " + user.LastName;
|
||||
if (user.LastName.StartsWith("@"))
|
||||
p.username = user.FirstName.ToLower() + user.LastName.ToLower();
|
||||
else
|
||||
p.username = user.FirstName.ToLower() + "." + user.LastName.ToLower();
|
||||
p.id = user.Id;
|
||||
p.is_display_name_default = false;
|
||||
return p;
|
||||
}
|
||||
|
||||
private byte[] FailureResponse(string names, int statuscode, IOSHttpResponse httpResponse)
|
||||
{
|
||||
m_log.Error("[AVATAR PICKER SEARCH]: Error searching for " + names);
|
||||
httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
|
||||
return System.Text.Encoding.UTF8.GetBytes(string.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,7 @@ namespace OpenSim.Capabilities.Handlers
|
||||
{
|
||||
public class FetchInventory2Handler
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private IInventoryService m_inventoryService;
|
||||
|
||||
@@ -121,4 +121,4 @@ namespace OpenSim.Capabilities.Handlers
|
||||
return llsdItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -64,7 +64,7 @@ namespace OpenSim.Capabilities.Handlers
|
||||
m_assetService = assService;
|
||||
}
|
||||
|
||||
public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||
protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||
{
|
||||
// Try to parse the texture ID from the request URL
|
||||
NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query);
|
||||
@@ -189,6 +189,7 @@ namespace OpenSim.Capabilities.Handlers
|
||||
|
||||
newTexture.Flags = AssetFlags.Collectable;
|
||||
newTexture.Temporary = true;
|
||||
newTexture.Local = true;
|
||||
m_assetService.Store(newTexture);
|
||||
WriteTextureData(httpRequest, httpResponse, newTexture, format);
|
||||
return true;
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* 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 the OpenSimulator Project 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 DEVELOPERS ``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 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using Nini.Config;
|
||||
using OpenSim.Server.Base;
|
||||
using OpenSim.Services.Interfaces;
|
||||
using OpenSim.Framework.Servers.HttpServer;
|
||||
using OpenSim.Server.Handlers.Base;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Capabilities.Handlers
|
||||
{
|
||||
public class UploadBakedTextureServerConnector : ServiceConnector
|
||||
{
|
||||
private IAssetService m_AssetService;
|
||||
private string m_ConfigName = "CapsService";
|
||||
|
||||
public UploadBakedTextureServerConnector(IConfigSource config, IHttpServer server, string configName) :
|
||||
base(config, server, configName)
|
||||
{
|
||||
if (configName != String.Empty)
|
||||
m_ConfigName = configName;
|
||||
|
||||
IConfig serverConfig = config.Configs[m_ConfigName];
|
||||
if (serverConfig == null)
|
||||
throw new Exception(String.Format("No section '{0}' in config file", m_ConfigName));
|
||||
|
||||
string assetService = serverConfig.GetString("AssetService", String.Empty);
|
||||
|
||||
if (assetService == String.Empty)
|
||||
throw new Exception("No AssetService in config file");
|
||||
|
||||
Object[] args = new Object[] { config };
|
||||
m_AssetService =
|
||||
ServerUtils.LoadPlugin<IAssetService>(assetService, args);
|
||||
|
||||
if (m_AssetService == null)
|
||||
throw new Exception(String.Format("Failed to load AssetService from {0}; config is {1}", assetService, m_ConfigName));
|
||||
|
||||
// NEED TO FIX THIS
|
||||
OpenSim.Framework.Capabilities.Caps caps = new OpenSim.Framework.Capabilities.Caps(server, "", server.Port, "", UUID.Zero, "");
|
||||
server.AddStreamHandler(new RestStreamHandler(
|
||||
"POST",
|
||||
"/CAPS/UploadBakedTexture/",
|
||||
new UploadBakedTextureHandler(caps, m_AssetService, true).UploadBakedTexture,
|
||||
"UploadBakedTexture",
|
||||
"Upload Baked Texture Capability"));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
51
OpenSim/Capabilities/LLSDAvatarPicker.cs
Normal file
51
OpenSim/Capabilities/LLSDAvatarPicker.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* 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 the OpenSimulator Project 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 DEVELOPERS ``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 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.
|
||||
*/
|
||||
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Framework.Capabilities
|
||||
{
|
||||
[OSDMap]
|
||||
public class LLSDAvatarPicker
|
||||
{
|
||||
public string next_page_url;
|
||||
// an array of LLSDPerson
|
||||
public OSDArray agents = new OSDArray();
|
||||
}
|
||||
|
||||
[OSDMap]
|
||||
public class LLSDPerson
|
||||
{
|
||||
public string username;
|
||||
public string display_name;
|
||||
//'display_name_next_update':d"1970-01-01T00:00:00Z"
|
||||
public string legacy_first_name;
|
||||
public string legacy_last_name;
|
||||
public UUID id;
|
||||
public bool is_display_name_default;
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,7 @@ namespace OpenSim.Framework.Capabilities
|
||||
m_method = method;
|
||||
}
|
||||
|
||||
public override byte[] Handle(string path, Stream request,
|
||||
protected override byte[] ProcessRequest(string path, Stream request,
|
||||
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||
{
|
||||
//Encoding encoding = Util.UTF8;
|
||||
|
||||
@@ -50,6 +50,7 @@ namespace OpenSim.Data
|
||||
public interface IGridUserData
|
||||
{
|
||||
GridUserData Get(string userID);
|
||||
GridUserData[] GetAll(string query);
|
||||
bool Store(GridUserData data);
|
||||
}
|
||||
}
|
||||
59
OpenSim/Data/IHGTravelingData.cs
Normal file
59
OpenSim/Data/IHGTravelingData.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* 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 the OpenSimulator Project 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 DEVELOPERS ``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 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
|
||||
namespace OpenSim.Data
|
||||
{
|
||||
// This MUST be a ref type!
|
||||
public class HGTravelingData
|
||||
{
|
||||
public UUID SessionID;
|
||||
public UUID UserID;
|
||||
public Dictionary<string, string> Data;
|
||||
|
||||
public HGTravelingData()
|
||||
{
|
||||
Data = new Dictionary<string, string>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An interface for connecting to the user grid datastore
|
||||
/// </summary>
|
||||
public interface IHGTravelingData
|
||||
{
|
||||
HGTravelingData Get(UUID sessionID);
|
||||
HGTravelingData[] GetSessions(UUID userID);
|
||||
bool Store(HGTravelingData data);
|
||||
bool Delete(UUID sessionID);
|
||||
void DeleteOld();
|
||||
}
|
||||
}
|
||||
56
OpenSim/Data/IProfilesData.cs
Normal file
56
OpenSim/Data/IProfilesData.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* 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 the OpenSimulator Project 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 DEVELOPERS ``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 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.StructuredData;
|
||||
using OpenSim.Framework;
|
||||
|
||||
namespace OpenSim.Data
|
||||
{
|
||||
|
||||
public interface IProfilesData
|
||||
{
|
||||
OSDArray GetClassifiedRecords(UUID creatorId);
|
||||
bool UpdateClassifiedRecord(UserClassifiedAdd ad, ref string result);
|
||||
bool DeleteClassifiedRecord(UUID recordId);
|
||||
OSDArray GetAvatarPicks(UUID avatarId);
|
||||
UserProfilePick GetPickInfo(UUID avatarId, UUID pickId);
|
||||
bool UpdatePicksRecord(UserProfilePick pick);
|
||||
bool DeletePicksRecord(UUID pickId);
|
||||
bool GetAvatarNotes(ref UserProfileNotes note);
|
||||
bool UpdateAvatarNotes(ref UserProfileNotes note, ref string result);
|
||||
bool GetAvatarProperties(ref UserProfileProperties props, ref string result);
|
||||
bool UpdateAvatarProperties(ref UserProfileProperties props, ref string result);
|
||||
bool UpdateAvatarInterests(UserProfileProperties up, ref string result);
|
||||
bool GetClassifiedInfo(ref UserClassifiedAdd ad, ref string result);
|
||||
bool GetUserAppData(ref UserAppData props, ref string result);
|
||||
bool SetUserAppData(UserAppData props, ref string result);
|
||||
OSDArray GetUserImageAssets(UUID avatarId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace OpenSim.Data.MSSQL
|
||||
{
|
||||
}
|
||||
|
||||
public GridUserData Get(string userID)
|
||||
public new GridUserData Get(string userID)
|
||||
{
|
||||
GridUserData[] ret = Get("UserID", userID);
|
||||
|
||||
@@ -60,5 +60,10 @@ namespace OpenSim.Data.MSSQL
|
||||
return ret[0];
|
||||
}
|
||||
|
||||
public GridUserData[] GetAll(string userID)
|
||||
{
|
||||
return base.Get(String.Format("UserID LIKE '{0}%'", userID));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2100,7 +2100,7 @@ VALUES
|
||||
parameters.Add(_Database.CreateParameter("LinkNumber", prim.LinkNum));
|
||||
parameters.Add(_Database.CreateParameter("MediaURL", prim.MediaUrl));
|
||||
|
||||
if (prim.DynAttrs.Count > 0)
|
||||
if (prim.DynAttrs.CountNamespaces > 0)
|
||||
parameters.Add(_Database.CreateParameter("DynAttrs", prim.DynAttrs.ToXml()));
|
||||
else
|
||||
parameters.Add(_Database.CreateParameter("DynAttrs", null));
|
||||
|
||||
@@ -1153,7 +1153,7 @@ COMMIT
|
||||
|
||||
BEGIN TRANSACTION
|
||||
|
||||
ALTER TABLE prims ADD COLUMN DynAttrs TEXT;
|
||||
ALTER TABLE prims ADD DynAttrs TEXT;
|
||||
|
||||
COMMIT
|
||||
|
||||
@@ -1161,10 +1161,10 @@ COMMIT
|
||||
|
||||
BEGIN TRANSACTION
|
||||
|
||||
ALTER TABLE prims ADD COLUMN `PhysicsShapeType` tinyint(4) NOT NULL default '0';
|
||||
ALTER TABLE prims ADD COLUMN `Density` double NOT NULL default '1000';
|
||||
ALTER TABLE prims ADD COLUMN `GravityModifier` double NOT NULL default '1';
|
||||
ALTER TABLE prims ADD COLUMN `Friction` double NOT NULL default '0.6';
|
||||
ALTER TABLE prims ADD COLUMN `Restitution` double NOT NULL default '0.5';
|
||||
ALTER TABLE prims ADD `PhysicsShapeType` tinyint(4) NOT NULL default '0';
|
||||
ALTER TABLE prims ADD `Density` double NOT NULL default '1000';
|
||||
ALTER TABLE prims ADD `GravityModifier` double NOT NULL default '1';
|
||||
ALTER TABLE prims ADD `Friction` double NOT NULL default '0.6';
|
||||
ALTER TABLE prims ADD `Restitution` double NOT NULL default '0.5';
|
||||
|
||||
COMMIT
|
||||
|
||||
@@ -142,7 +142,8 @@ namespace OpenSim.Data.MySQL
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error("[ASSETS DB]: MySql failure fetching asset " + assetID + ": " + e.Message);
|
||||
m_log.Error(
|
||||
string.Format("[ASSETS DB]: MySql failure fetching asset {0}. Exception ", assetID), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -209,8 +210,11 @@ namespace OpenSim.Data.MySQL
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("[ASSET DB]: MySQL failure creating asset {0} with name \"{1}\". Error: {2}",
|
||||
asset.FullID, asset.Name, e.Message);
|
||||
m_log.Error(
|
||||
string.Format(
|
||||
"[ASSET DB]: MySQL failure creating asset {0} with name {1}. Exception ",
|
||||
asset.FullID, asset.Name)
|
||||
, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -241,10 +245,11 @@ namespace OpenSim.Data.MySQL
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat(
|
||||
"[ASSETS DB]: " +
|
||||
"MySql failure updating access_time for asset {0} with name {1}" + Environment.NewLine + e.ToString()
|
||||
+ Environment.NewLine + "Attempting reconnection", asset.FullID, asset.Name);
|
||||
m_log.Error(
|
||||
string.Format(
|
||||
"[ASSETS DB]: Failure updating access_time for asset {0} with name {1}. Exception ",
|
||||
asset.FullID, asset.Name),
|
||||
e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -284,8 +289,8 @@ namespace OpenSim.Data.MySQL
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat(
|
||||
"[ASSETS DB]: MySql failure fetching asset {0}" + Environment.NewLine + e.ToString(), uuid);
|
||||
m_log.Error(
|
||||
string.Format("[ASSETS DB]: MySql failure fetching asset {0}. Exception ", uuid), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -344,7 +349,11 @@ namespace OpenSim.Data.MySQL
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error("[ASSETS DB]: MySql failure fetching asset set" + Environment.NewLine + e.ToString());
|
||||
m_log.Error(
|
||||
string.Format(
|
||||
"[ASSETS DB]: MySql failure fetching asset set from {0}, count {1}. Exception ",
|
||||
start, count),
|
||||
e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace OpenSim.Data.MySQL
|
||||
|
||||
public MySQLGridUserData(string connectionString, string realm) : base(connectionString, realm, "GridUserStore") {}
|
||||
|
||||
public GridUserData Get(string userID)
|
||||
public new GridUserData Get(string userID)
|
||||
{
|
||||
GridUserData[] ret = Get("UserID", userID);
|
||||
|
||||
@@ -56,6 +56,9 @@ namespace OpenSim.Data.MySQL
|
||||
return ret[0];
|
||||
}
|
||||
|
||||
|
||||
public GridUserData[] GetAll(string userID)
|
||||
{
|
||||
return base.Get(String.Format("UserID LIKE '{0}%'", userID));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -88,7 +88,7 @@ namespace OpenSim.Data.MySQL
|
||||
if (string.IsNullOrEmpty(pattern))
|
||||
pattern = "1 ORDER BY Name LIMIT 100";
|
||||
else
|
||||
pattern = string.Format("Name LIKE %{0}% ORDER BY Name LIMIT 100", pattern);
|
||||
pattern = string.Format("Name LIKE '%{0}%' ORDER BY Name LIMIT 100", pattern);
|
||||
|
||||
return m_Groups.Get(pattern);
|
||||
}
|
||||
|
||||
80
OpenSim/Data/MySQL/MySQLHGTravelData.cs
Normal file
80
OpenSim/Data/MySQL/MySQLHGTravelData.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* 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 the OpenSimulator Project 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 DEVELOPERS ``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 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using log4net;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
namespace OpenSim.Data.MySQL
|
||||
{
|
||||
/// <summary>
|
||||
/// A MySQL Interface for user grid data
|
||||
/// </summary>
|
||||
public class MySQLHGTravelData : MySQLGenericTableHandler<HGTravelingData>, IHGTravelingData
|
||||
{
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
public MySQLHGTravelData(string connectionString, string realm) : base(connectionString, realm, "HGTravelStore") { }
|
||||
|
||||
public HGTravelingData Get(UUID sessionID)
|
||||
{
|
||||
HGTravelingData[] ret = Get("SessionID", sessionID.ToString());
|
||||
|
||||
if (ret.Length == 0)
|
||||
return null;
|
||||
|
||||
return ret[0];
|
||||
}
|
||||
|
||||
public HGTravelingData[] GetSessions(UUID userID)
|
||||
{
|
||||
return base.Get("UserID", userID.ToString());
|
||||
}
|
||||
|
||||
public bool Delete(UUID sessionID)
|
||||
{
|
||||
return Delete("SessionID", sessionID.ToString());
|
||||
}
|
||||
|
||||
public void DeleteOld()
|
||||
{
|
||||
using (MySqlCommand cmd = new MySqlCommand())
|
||||
{
|
||||
cmd.CommandText = String.Format("delete from {0} where TMStamp < NOW() - INTERVAL 2 DAY", m_Realm);
|
||||
|
||||
ExecuteNonQuery(cmd);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -47,13 +47,10 @@ namespace OpenSim.Data.MySQL
|
||||
|
||||
public void DeleteOld()
|
||||
{
|
||||
uint now = (uint)Util.UnixTimeSinceEpoch();
|
||||
|
||||
using (MySqlCommand cmd = new MySqlCommand())
|
||||
{
|
||||
cmd.CommandText = String.Format("delete from {0} where TMStamp < ?tstamp", m_Realm);
|
||||
cmd.Parameters.AddWithValue("?tstamp", now - 14 * 24 * 60 * 60); // > 2 weeks old
|
||||
|
||||
cmd.CommandText = String.Format("delete from {0} where TMStamp < NOW() - INTERVAL 2 WEEK", m_Realm);
|
||||
|
||||
ExecuteNonQuery(cmd);
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace OpenSim.Data.MySQL
|
||||
private string m_connectionString;
|
||||
private object m_dbLock = new object();
|
||||
|
||||
protected Assembly Assembly
|
||||
protected virtual Assembly Assembly
|
||||
{
|
||||
get { return GetType().Assembly; }
|
||||
}
|
||||
@@ -173,9 +173,9 @@ namespace OpenSim.Data.MySQL
|
||||
"ParticleSystem, ClickAction, Material, " +
|
||||
"CollisionSound, CollisionSoundVolume, " +
|
||||
"PassTouches, " +
|
||||
"LinkNumber, MediaURL, DynAttrs, " +
|
||||
"LinkNumber, MediaURL, KeyframeMotion, " +
|
||||
"PhysicsShapeType, Density, GravityModifier, " +
|
||||
"Friction, Restitution " +
|
||||
"Friction, Restitution, DynAttrs " +
|
||||
") values (" + "?UUID, " +
|
||||
"?CreationDate, ?Name, ?Text, " +
|
||||
"?Description, ?SitName, ?TouchName, " +
|
||||
@@ -208,9 +208,9 @@ namespace OpenSim.Data.MySQL
|
||||
"?ColorB, ?ColorA, ?ParticleSystem, " +
|
||||
"?ClickAction, ?Material, ?CollisionSound, " +
|
||||
"?CollisionSoundVolume, ?PassTouches, " +
|
||||
"?LinkNumber, ?MediaURL, ?DynAttrs, " +
|
||||
"?LinkNumber, ?MediaURL, ?KeyframeMotion, " +
|
||||
"?PhysicsShapeType, ?Density, ?GravityModifier, " +
|
||||
"?Friction, ?Restitution)";
|
||||
"?Friction, ?Restitution, ?DynAttrs)";
|
||||
|
||||
FillPrimCommand(cmd, prim, obj.UUID, regionUUID);
|
||||
|
||||
@@ -455,7 +455,9 @@ namespace OpenSim.Data.MySQL
|
||||
foreach (SceneObjectPart prim in prims.Values)
|
||||
{
|
||||
if (prim.ParentUUID == UUID.Zero)
|
||||
{
|
||||
objects[prim.UUID] = new SceneObjectGroup(prim);
|
||||
}
|
||||
}
|
||||
|
||||
// Add all of the children objects to the SOGs
|
||||
@@ -1307,6 +1309,19 @@ namespace OpenSim.Data.MySQL
|
||||
else
|
||||
prim.DynAttrs = new DAMap();
|
||||
|
||||
if (!(row["KeyframeMotion"] is DBNull))
|
||||
{
|
||||
Byte[] data = (byte[])row["KeyframeMotion"];
|
||||
if (data.Length > 0)
|
||||
prim.KeyframeMotion = KeyframeMotion.FromData(null, data);
|
||||
else
|
||||
prim.KeyframeMotion = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
prim.KeyframeMotion = null;
|
||||
}
|
||||
|
||||
prim.PhysicsShapeType = (byte)Convert.ToInt32(row["PhysicsShapeType"].ToString());
|
||||
prim.Density = (float)(double)row["Density"];
|
||||
prim.GravityModifier = (float)(double)row["GravityModifier"];
|
||||
@@ -1659,8 +1674,12 @@ namespace OpenSim.Data.MySQL
|
||||
cmd.Parameters.AddWithValue("LinkNumber", prim.LinkNum);
|
||||
cmd.Parameters.AddWithValue("MediaURL", prim.MediaUrl);
|
||||
|
||||
if (prim.KeyframeMotion != null)
|
||||
cmd.Parameters.AddWithValue("KeyframeMotion", prim.KeyframeMotion.Serialize());
|
||||
else
|
||||
cmd.Parameters.AddWithValue("KeyframeMotion", new Byte[0]);
|
||||
|
||||
if (prim.DynAttrs.Count > 0)
|
||||
if (prim.DynAttrs.CountNamespaces > 0)
|
||||
cmd.Parameters.AddWithValue("DynAttrs", prim.DynAttrs.ToXml());
|
||||
else
|
||||
cmd.Parameters.AddWithValue("DynAttrs", null);
|
||||
|
||||
1096
OpenSim/Data/MySQL/MySQLUserProfilesData.cs
Normal file
1096
OpenSim/Data/MySQL/MySQLUserProfilesData.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -199,6 +199,8 @@ namespace OpenSim.Data.MySQL
|
||||
/// <remarks>On failure : Throw an exception and attempt to reconnect to database</remarks>
|
||||
public void StoreAsset(AssetBase asset)
|
||||
{
|
||||
// m_log.DebugFormat("[XASSETS DB]: Storing asset {0} {1}", asset.Name, asset.ID);
|
||||
|
||||
lock (m_dbLock)
|
||||
{
|
||||
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
|
||||
|
||||
@@ -77,5 +77,11 @@ BEGIN;
|
||||
ALTER TABLE estate_settings AUTO_INCREMENT = 100;
|
||||
COMMIT;
|
||||
|
||||
:VERSION 33 #---------------------
|
||||
|
||||
BEGIN;
|
||||
ALTER TABLE estate_settings ADD COLUMN `AllowLandmark` tinyint(4) NOT NULL default '1';
|
||||
ALTER TABLE estate_settings ADD COLUMN `AllowParcelChanges` tinyint(4) NOT NULL default '1';
|
||||
ALTER TABLE estate_settings ADD COLUMN `AllowSetHome` tinyint(4) NOT NULL default '1';
|
||||
COMMIT;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ CREATE TABLE `Friends` (
|
||||
`Offered` VARCHAR(32) NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY(`PrincipalID`, `Friend`),
|
||||
KEY(`PrincipalID`)
|
||||
);
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
||||
18
OpenSim/Data/MySQL/Resources/HGTravelStore.migrations
Normal file
18
OpenSim/Data/MySQL/Resources/HGTravelStore.migrations
Normal file
@@ -0,0 +1,18 @@
|
||||
:VERSION 1 # --------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
CREATE TABLE `hg_traveling_data` (
|
||||
`SessionID` VARCHAR(36) NOT NULL,
|
||||
`UserID` VARCHAR(36) NOT NULL,
|
||||
`GridExternalName` VARCHAR(255) NOT NULL DEFAULT '',
|
||||
`ServiceToken` VARCHAR(255) NOT NULL DEFAULT '',
|
||||
`ClientIPAddress` VARCHAR(16) NOT NULL DEFAULT '',
|
||||
`MyIPAddress` VARCHAR(16) NOT NULL DEFAULT '',
|
||||
`TMStamp` timestamp NOT NULL,
|
||||
PRIMARY KEY (`SessionID`),
|
||||
KEY (`UserID`)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
COMMIT;
|
||||
|
||||
@@ -923,3 +923,10 @@ ALTER TABLE prims ADD COLUMN `Restitution` double NOT NULL default '0.5';
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 48 #---------------- Keyframes
|
||||
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE prims ADD COLUMN `KeyframeMotion` blob;
|
||||
|
||||
COMMIT;
|
||||
|
||||
83
OpenSim/Data/MySQL/Resources/UserProfiles.migrations
Normal file
83
OpenSim/Data/MySQL/Resources/UserProfiles.migrations
Normal file
@@ -0,0 +1,83 @@
|
||||
:VERSION 1 # -------------------------------
|
||||
|
||||
begin;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `classifieds` (
|
||||
`classifieduuid` char(36) NOT NULL,
|
||||
`creatoruuid` char(36) NOT NULL,
|
||||
`creationdate` int(20) NOT NULL,
|
||||
`expirationdate` int(20) NOT NULL,
|
||||
`category` varchar(20) NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`description` text NOT NULL,
|
||||
`parceluuid` char(36) NOT NULL,
|
||||
`parentestate` int(11) NOT NULL,
|
||||
`snapshotuuid` char(36) NOT NULL,
|
||||
`simname` varchar(255) NOT NULL,
|
||||
`posglobal` varchar(255) NOT NULL,
|
||||
`parcelname` varchar(255) NOT NULL,
|
||||
`classifiedflags` int(8) NOT NULL,
|
||||
`priceforlisting` int(5) NOT NULL,
|
||||
PRIMARY KEY (`classifieduuid`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `usernotes` (
|
||||
`useruuid` varchar(36) NOT NULL,
|
||||
`targetuuid` varchar(36) NOT NULL,
|
||||
`notes` text NOT NULL,
|
||||
UNIQUE KEY `useruuid` (`useruuid`,`targetuuid`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `userpicks` (
|
||||
`pickuuid` varchar(36) NOT NULL,
|
||||
`creatoruuid` varchar(36) NOT NULL,
|
||||
`toppick` enum('true','false') NOT NULL,
|
||||
`parceluuid` varchar(36) NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`description` text NOT NULL,
|
||||
`snapshotuuid` varchar(36) NOT NULL,
|
||||
`user` varchar(255) NOT NULL,
|
||||
`originalname` varchar(255) NOT NULL,
|
||||
`simname` varchar(255) NOT NULL,
|
||||
`posglobal` varchar(255) NOT NULL,
|
||||
`sortorder` int(2) NOT NULL,
|
||||
`enabled` enum('true','false') NOT NULL,
|
||||
PRIMARY KEY (`pickuuid`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `userprofile` (
|
||||
`useruuid` varchar(36) NOT NULL,
|
||||
`profilePartner` varchar(36) NOT NULL,
|
||||
`profileAllowPublish` binary(1) NOT NULL,
|
||||
`profileMaturePublish` binary(1) NOT NULL,
|
||||
`profileURL` varchar(255) NOT NULL,
|
||||
`profileWantToMask` int(3) NOT NULL,
|
||||
`profileWantToText` text NOT NULL,
|
||||
`profileSkillsMask` int(3) NOT NULL,
|
||||
`profileSkillsText` text NOT NULL,
|
||||
`profileLanguages` text NOT NULL,
|
||||
`profileImage` varchar(36) NOT NULL,
|
||||
`profileAboutText` text NOT NULL,
|
||||
`profileFirstImage` varchar(36) NOT NULL,
|
||||
`profileFirstText` text NOT NULL,
|
||||
PRIMARY KEY (`useruuid`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
commit;
|
||||
|
||||
:VERSION 2 # -------------------------------
|
||||
|
||||
begin;
|
||||
CREATE TABLE IF NOT EXISTS `userdata` (
|
||||
`UserId` char(36) NOT NULL,
|
||||
`TagId` varchar(64) NOT NULL,
|
||||
`DataKey` varchar(255),
|
||||
`DataVal` varchar(255),
|
||||
PRIMARY KEY (`UserId`,`TagId`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
commit;
|
||||
|
||||
@@ -42,6 +42,22 @@ namespace OpenSim.Data.Null
|
||||
|
||||
// private string m_connectionString;
|
||||
|
||||
private Dictionary<uint, EstateSettings> m_knownEstates = new Dictionary<uint, EstateSettings>();
|
||||
private EstateSettings m_estate = null;
|
||||
|
||||
private EstateSettings GetEstate()
|
||||
{
|
||||
if (m_estate == null)
|
||||
{
|
||||
// This fools the initialization caller into thinking an estate was fetched (a check in OpenSimBase).
|
||||
// The estate info is pretty empty so don't try banning anyone.
|
||||
m_estate = new EstateSettings();
|
||||
m_estate.EstateID = 1;
|
||||
m_estate.OnSave += StoreEstateSettings;
|
||||
}
|
||||
return m_estate;
|
||||
}
|
||||
|
||||
protected virtual Assembly Assembly
|
||||
{
|
||||
get { return GetType().Assembly; }
|
||||
@@ -68,21 +84,18 @@ namespace OpenSim.Data.Null
|
||||
|
||||
public EstateSettings LoadEstateSettings(UUID regionID, bool create)
|
||||
{
|
||||
// This fools the initialization caller into thinking an estate was fetched (a check in OpenSimBase).
|
||||
// The estate info is pretty empty so don't try banning anyone.
|
||||
EstateSettings oneEstate = new EstateSettings();
|
||||
oneEstate.EstateID = 1;
|
||||
return oneEstate;
|
||||
return GetEstate();
|
||||
}
|
||||
|
||||
public void StoreEstateSettings(EstateSettings es)
|
||||
{
|
||||
m_estate = es;
|
||||
return;
|
||||
}
|
||||
|
||||
public EstateSettings LoadEstateSettings(int estateID)
|
||||
{
|
||||
return new EstateSettings();
|
||||
return GetEstate();
|
||||
}
|
||||
|
||||
public EstateSettings CreateNewEstate()
|
||||
@@ -93,13 +106,14 @@ namespace OpenSim.Data.Null
|
||||
public List<EstateSettings> LoadEstateSettingsAll()
|
||||
{
|
||||
List<EstateSettings> allEstateSettings = new List<EstateSettings>();
|
||||
allEstateSettings.Add(new EstateSettings());
|
||||
allEstateSettings.Add(GetEstate());
|
||||
return allEstateSettings;
|
||||
}
|
||||
|
||||
public List<int> GetEstatesAll()
|
||||
{
|
||||
List<int> result = new List<int>();
|
||||
result.Add((int)GetEstate().EstateID);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -77,20 +77,34 @@ namespace OpenSim.Data.Null
|
||||
}
|
||||
|
||||
#region Environment Settings
|
||||
|
||||
private Dictionary<UUID, string> EnvironmentSettings = new Dictionary<UUID, string>();
|
||||
|
||||
public string LoadRegionEnvironmentSettings(UUID regionUUID)
|
||||
{
|
||||
//This connector doesn't support the Environment module yet
|
||||
lock (EnvironmentSettings)
|
||||
{
|
||||
if (EnvironmentSettings.ContainsKey(regionUUID))
|
||||
return EnvironmentSettings[regionUUID];
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings)
|
||||
{
|
||||
//This connector doesn't support the Environment module yet
|
||||
lock (EnvironmentSettings)
|
||||
{
|
||||
EnvironmentSettings[regionUUID] = settings;
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveRegionEnvironmentSettings(UUID regionUUID)
|
||||
{
|
||||
//This connector doesn't support the Environment module yet
|
||||
lock (EnvironmentSettings)
|
||||
{
|
||||
if (EnvironmentSettings.ContainsKey(regionUUID))
|
||||
EnvironmentSettings.Remove(regionUUID);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -86,3 +86,12 @@ begin;
|
||||
alter table estate_settings add column DenyMinors tinyint not null default 0;
|
||||
|
||||
commit;
|
||||
|
||||
:VERSION 9
|
||||
|
||||
begin;
|
||||
alter table estate_settings add column AllowLandmark tinyint not null default '1';
|
||||
alter table estate_settings add column AllowParcelChanges tinyint not null default '1';
|
||||
alter table estate_settings add column AllowSetHome tinyint not null default '1';
|
||||
commit;
|
||||
|
||||
|
||||
18
OpenSim/Data/SQLite/Resources/HGTravelStore.migrations
Normal file
18
OpenSim/Data/SQLite/Resources/HGTravelStore.migrations
Normal file
@@ -0,0 +1,18 @@
|
||||
:VERSION 2 # --------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
CREATE TABLE hg_traveling_data(
|
||||
SessionID VARCHAR(36) NOT NULL,
|
||||
UserID VARCHAR(36) NOT NULL,
|
||||
GridExternalName VARCHAR(255) NOT NULL DEFAULT "",
|
||||
ServiceToken VARCHAR(255) NOT NULL DEFAULT "",
|
||||
ClientIPAddress VARCHAR(16) NOT NULL DEFAULT "",
|
||||
MyIPAddress VARCHAR(16) NOT NULL DEFAULT "",
|
||||
TMStamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY(SessionID),
|
||||
UNIQUE(UserID)
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
@@ -592,3 +592,11 @@ ALTER TABLE prims ADD COLUMN `Friction` double NOT NULL default '0.6';
|
||||
ALTER TABLE prims ADD COLUMN `Restitution` double NOT NULL default '0.5';
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 29 #---------------- Keyframes
|
||||
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE prims ADD COLUMN `KeyframeMotion` blob;
|
||||
|
||||
COMMIT;
|
||||
|
||||
90
OpenSim/Data/SQLite/Resources/UserProfiles.migrations
Normal file
90
OpenSim/Data/SQLite/Resources/UserProfiles.migrations
Normal file
@@ -0,0 +1,90 @@
|
||||
:VERSION 1 # -------------------------------
|
||||
|
||||
begin;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS classifieds (
|
||||
classifieduuid char(36) NOT NULL PRIMARY KEY,
|
||||
creatoruuid char(36) NOT NULL,
|
||||
creationdate int(20) NOT NULL,
|
||||
expirationdate int(20) NOT NULL,
|
||||
category varchar(20) NOT NULL,
|
||||
name varchar(255) NOT NULL,
|
||||
description text NOT NULL,
|
||||
parceluuid char(36) NOT NULL,
|
||||
parentestate int(11) NOT NULL,
|
||||
snapshotuuid char(36) NOT NULL,
|
||||
simname varchar(255) NOT NULL,
|
||||
posglobal varchar(255) NOT NULL,
|
||||
parcelname varchar(255) NOT NULL,
|
||||
classifiedflags int(8) NOT NULL,
|
||||
priceforlisting int(5) NOT NULL
|
||||
);
|
||||
|
||||
commit;
|
||||
|
||||
begin;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS usernotes (
|
||||
useruuid varchar(36) NOT NULL,
|
||||
targetuuid varchar(36) NOT NULL,
|
||||
notes text NOT NULL,
|
||||
UNIQUE (useruuid,targetuuid) ON CONFLICT REPLACE
|
||||
);
|
||||
|
||||
commit;
|
||||
|
||||
begin;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS userpicks (
|
||||
pickuuid varchar(36) NOT NULL PRIMARY KEY,
|
||||
creatoruuid varchar(36) NOT NULL,
|
||||
toppick int NOT NULL,
|
||||
parceluuid varchar(36) NOT NULL,
|
||||
name varchar(255) NOT NULL,
|
||||
description text NOT NULL,
|
||||
snapshotuuid varchar(36) NOT NULL,
|
||||
user varchar(255) NOT NULL,
|
||||
originalname varchar(255) NOT NULL,
|
||||
simname varchar(255) NOT NULL,
|
||||
posglobal varchar(255) NOT NULL,
|
||||
sortorder int(2) NOT NULL,
|
||||
enabled int NOT NULL
|
||||
);
|
||||
|
||||
commit;
|
||||
|
||||
begin;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS userprofile (
|
||||
useruuid varchar(36) NOT NULL PRIMARY KEY,
|
||||
profilePartner varchar(36) NOT NULL,
|
||||
profileAllowPublish binary(1) NOT NULL,
|
||||
profileMaturePublish binary(1) NOT NULL,
|
||||
profileURL varchar(255) NOT NULL,
|
||||
profileWantToMask int(3) NOT NULL,
|
||||
profileWantToText text NOT NULL,
|
||||
profileSkillsMask int(3) NOT NULL,
|
||||
profileSkillsText text NOT NULL,
|
||||
profileLanguages text NOT NULL,
|
||||
profileImage varchar(36) NOT NULL,
|
||||
profileAboutText text NOT NULL,
|
||||
profileFirstImage varchar(36) NOT NULL,
|
||||
profileFirstText text NOT NULL
|
||||
);
|
||||
|
||||
commit;
|
||||
|
||||
:VERSION 2 # -------------------------------
|
||||
|
||||
begin;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS userdata (
|
||||
UserId char(36) NOT NULL,
|
||||
TagId varchar(64) NOT NULL,
|
||||
DataKey varchar(255),
|
||||
DataVal varchar(255),
|
||||
PRIMARY KEY (UserId,TagId)
|
||||
);
|
||||
|
||||
commit;
|
||||
|
||||
@@ -56,6 +56,10 @@ namespace OpenSim.Data.SQLite
|
||||
return ret[0];
|
||||
}
|
||||
|
||||
public GridUserData[] GetAll(string userID)
|
||||
{
|
||||
return base.Get(String.Format("UserID LIKE '{0}%'", userID));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
82
OpenSim/Data/SQLite/SQLiteHGTravelData.cs
Normal file
82
OpenSim/Data/SQLite/SQLiteHGTravelData.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* 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 the OpenSimulator Project 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 DEVELOPERS ``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 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using log4net;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using Mono.Data.Sqlite;
|
||||
|
||||
namespace OpenSim.Data.SQLite
|
||||
{
|
||||
/// <summary>
|
||||
/// A SQL Interface for user grid data
|
||||
/// </summary>
|
||||
public class SQLiteHGTravelData : SQLiteGenericTableHandler<HGTravelingData>, IHGTravelingData
|
||||
{
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
public SQLiteHGTravelData(string connectionString, string realm)
|
||||
: base(connectionString, realm, "HGTravelStore") {}
|
||||
|
||||
public HGTravelingData Get(UUID sessionID)
|
||||
{
|
||||
HGTravelingData[] ret = Get("SessionID", sessionID.ToString());
|
||||
|
||||
if (ret.Length == 0)
|
||||
return null;
|
||||
|
||||
return ret[0];
|
||||
}
|
||||
|
||||
public HGTravelingData[] GetSessions(UUID userID)
|
||||
{
|
||||
return base.Get("UserID", userID.ToString());
|
||||
}
|
||||
|
||||
public bool Delete(UUID sessionID)
|
||||
{
|
||||
return Delete("SessionID", sessionID.ToString());
|
||||
}
|
||||
|
||||
public void DeleteOld()
|
||||
{
|
||||
using (SqliteCommand cmd = new SqliteCommand())
|
||||
{
|
||||
cmd.CommandText = String.Format("delete from {0} where TMStamp < datetime('now', '-2 day') ", m_Realm);
|
||||
|
||||
DoQuery(cmd);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -732,9 +732,12 @@ namespace OpenSim.Data.SQLite
|
||||
}
|
||||
|
||||
SceneObjectGroup group = new SceneObjectGroup(prim);
|
||||
|
||||
createdObjects.Add(group.UUID, group);
|
||||
retvals.Add(group);
|
||||
LoadItems(prim);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -1241,6 +1244,7 @@ namespace OpenSim.Data.SQLite
|
||||
createCol(prims, "Friction", typeof(Double));
|
||||
createCol(prims, "Restitution", typeof(Double));
|
||||
|
||||
createCol(prims, "KeyframeMotion", typeof(Byte[]));
|
||||
// Add in contraints
|
||||
prims.PrimaryKey = new DataColumn[] { prims.Columns["UUID"] };
|
||||
|
||||
@@ -1736,6 +1740,20 @@ namespace OpenSim.Data.SQLite
|
||||
prim.Friction = Convert.ToSingle(row["Friction"]);
|
||||
prim.Restitution = Convert.ToSingle(row["Restitution"]);
|
||||
|
||||
|
||||
if (!(row["KeyframeMotion"] is DBNull))
|
||||
{
|
||||
Byte[] data = (byte[])row["KeyframeMotion"];
|
||||
if (data.Length > 0)
|
||||
prim.KeyframeMotion = KeyframeMotion.FromData(null, data);
|
||||
else
|
||||
prim.KeyframeMotion = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
prim.KeyframeMotion = null;
|
||||
}
|
||||
|
||||
return prim;
|
||||
}
|
||||
|
||||
@@ -2158,7 +2176,7 @@ namespace OpenSim.Data.SQLite
|
||||
|
||||
row["MediaURL"] = prim.MediaUrl;
|
||||
|
||||
if (prim.DynAttrs.Count > 0)
|
||||
if (prim.DynAttrs.CountNamespaces > 0)
|
||||
row["DynAttrs"] = prim.DynAttrs.ToXml();
|
||||
else
|
||||
row["DynAttrs"] = null;
|
||||
@@ -2168,6 +2186,13 @@ namespace OpenSim.Data.SQLite
|
||||
row["GravityModifier"] = (double)prim.GravityModifier;
|
||||
row["Friction"] = (double)prim.Friction;
|
||||
row["Restitution"] = (double)prim.Restitution;
|
||||
|
||||
if (prim.KeyframeMotion != null)
|
||||
row["KeyframeMotion"] = prim.KeyframeMotion.Serialize();
|
||||
else
|
||||
row["KeyframeMotion"] = new Byte[0];
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
904
OpenSim/Data/SQLite/SQLiteUserProfilesData.cs
Normal file
904
OpenSim/Data/SQLite/SQLiteUserProfilesData.cs
Normal file
@@ -0,0 +1,904 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* 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 the OpenSimulator Project 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 DEVELOPERS ``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 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Reflection;
|
||||
using log4net;
|
||||
#if CSharpSqlite
|
||||
using Community.CsharpSqlite.Sqlite;
|
||||
#else
|
||||
using Mono.Data.Sqlite;
|
||||
#endif
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.StructuredData;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
|
||||
namespace OpenSim.Data.SQLite
|
||||
{
|
||||
public class SQLiteUserProfilesData: IProfilesData
|
||||
{
|
||||
private static readonly ILog m_log =
|
||||
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private SqliteConnection m_connection;
|
||||
private string m_connectionString;
|
||||
|
||||
private FieldInfo[] m_Fields;
|
||||
private Dictionary<string, FieldInfo> m_FieldMap =
|
||||
new Dictionary<string, FieldInfo>();
|
||||
|
||||
protected virtual Assembly Assembly
|
||||
{
|
||||
get { return GetType().Assembly; }
|
||||
}
|
||||
|
||||
public SQLiteUserProfilesData()
|
||||
{
|
||||
}
|
||||
|
||||
public SQLiteUserProfilesData(string connectionString)
|
||||
{
|
||||
Initialise(connectionString);
|
||||
}
|
||||
|
||||
public void Initialise(string connectionString)
|
||||
{
|
||||
if (Util.IsWindows())
|
||||
Util.LoadArchSpecificWindowsDll("sqlite3.dll");
|
||||
|
||||
m_connectionString = connectionString;
|
||||
|
||||
m_log.Info("[PROFILES_DATA]: Sqlite - connecting: "+m_connectionString);
|
||||
|
||||
m_connection = new SqliteConnection(m_connectionString);
|
||||
m_connection.Open();
|
||||
|
||||
Migration m = new Migration(m_connection, Assembly, "UserProfiles");
|
||||
m.Update();
|
||||
}
|
||||
|
||||
private string[] FieldList
|
||||
{
|
||||
get { return new List<string>(m_FieldMap.Keys).ToArray(); }
|
||||
}
|
||||
|
||||
#region IProfilesData implementation
|
||||
public OSDArray GetClassifiedRecords(UUID creatorId)
|
||||
{
|
||||
OSDArray data = new OSDArray();
|
||||
string query = "SELECT classifieduuid, name FROM classifieds WHERE creatoruuid = :Id";
|
||||
IDataReader reader = null;
|
||||
|
||||
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = query;
|
||||
cmd.Parameters.AddWithValue(":Id", creatorId);
|
||||
reader = cmd.ExecuteReader();
|
||||
}
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
OSDMap n = new OSDMap();
|
||||
UUID Id = UUID.Zero;
|
||||
string Name = null;
|
||||
try
|
||||
{
|
||||
UUID.TryParse(Convert.ToString( reader["classifieduuid"]), out Id);
|
||||
Name = Convert.ToString(reader["name"]);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.DebugFormat("[PROFILES_DATA]" +
|
||||
": UserAccount exception {0}", e.Message);
|
||||
}
|
||||
n.Add("classifieduuid", OSD.FromUUID(Id));
|
||||
n.Add("name", OSD.FromString(Name));
|
||||
data.Add(n);
|
||||
}
|
||||
|
||||
reader.Close();
|
||||
|
||||
return data;
|
||||
}
|
||||
public bool UpdateClassifiedRecord(UserClassifiedAdd ad, ref string result)
|
||||
{
|
||||
string query = string.Empty;
|
||||
|
||||
query += "INSERT OR REPLACE INTO classifieds (";
|
||||
query += "`classifieduuid`,";
|
||||
query += "`creatoruuid`,";
|
||||
query += "`creationdate`,";
|
||||
query += "`expirationdate`,";
|
||||
query += "`category`,";
|
||||
query += "`name`,";
|
||||
query += "`description`,";
|
||||
query += "`parceluuid`,";
|
||||
query += "`parentestate`,";
|
||||
query += "`snapshotuuid`,";
|
||||
query += "`simname`,";
|
||||
query += "`posglobal`,";
|
||||
query += "`parcelname`,";
|
||||
query += "`classifiedflags`,";
|
||||
query += "`priceforlisting`) ";
|
||||
query += "VALUES (";
|
||||
query += ":ClassifiedId,";
|
||||
query += ":CreatorId,";
|
||||
query += ":CreatedDate,";
|
||||
query += ":ExpirationDate,";
|
||||
query += ":Category,";
|
||||
query += ":Name,";
|
||||
query += ":Description,";
|
||||
query += ":ParcelId,";
|
||||
query += ":ParentEstate,";
|
||||
query += ":SnapshotId,";
|
||||
query += ":SimName,";
|
||||
query += ":GlobalPos,";
|
||||
query += ":ParcelName,";
|
||||
query += ":Flags,";
|
||||
query += ":ListingPrice ) ";
|
||||
|
||||
if(string.IsNullOrEmpty(ad.ParcelName))
|
||||
ad.ParcelName = "Unknown";
|
||||
if(ad.ParcelId == null)
|
||||
ad.ParcelId = UUID.Zero;
|
||||
if(string.IsNullOrEmpty(ad.Description))
|
||||
ad.Description = "No Description";
|
||||
|
||||
DateTime epoch = new DateTime(1970, 1, 1);
|
||||
DateTime now = DateTime.Now;
|
||||
TimeSpan epochnow = now - epoch;
|
||||
TimeSpan duration;
|
||||
DateTime expiration;
|
||||
TimeSpan epochexp;
|
||||
|
||||
if(ad.Flags == 2)
|
||||
{
|
||||
duration = new TimeSpan(7,0,0,0);
|
||||
expiration = now.Add(duration);
|
||||
epochexp = expiration - epoch;
|
||||
}
|
||||
else
|
||||
{
|
||||
duration = new TimeSpan(365,0,0,0);
|
||||
expiration = now.Add(duration);
|
||||
epochexp = expiration - epoch;
|
||||
}
|
||||
ad.CreationDate = (int)epochnow.TotalSeconds;
|
||||
ad.ExpirationDate = (int)epochexp.TotalSeconds;
|
||||
|
||||
try {
|
||||
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = query;
|
||||
cmd.Parameters.AddWithValue(":ClassifiedId", ad.ClassifiedId.ToString());
|
||||
cmd.Parameters.AddWithValue(":CreatorId", ad.CreatorId.ToString());
|
||||
cmd.Parameters.AddWithValue(":CreatedDate", ad.CreationDate.ToString());
|
||||
cmd.Parameters.AddWithValue(":ExpirationDate", ad.ExpirationDate.ToString());
|
||||
cmd.Parameters.AddWithValue(":Category", ad.Category.ToString());
|
||||
cmd.Parameters.AddWithValue(":Name", ad.Name.ToString());
|
||||
cmd.Parameters.AddWithValue(":Description", ad.Description.ToString());
|
||||
cmd.Parameters.AddWithValue(":ParcelId", ad.ParcelId.ToString());
|
||||
cmd.Parameters.AddWithValue(":ParentEstate", ad.ParentEstate.ToString());
|
||||
cmd.Parameters.AddWithValue(":SnapshotId", ad.SnapshotId.ToString ());
|
||||
cmd.Parameters.AddWithValue(":SimName", ad.SimName.ToString());
|
||||
cmd.Parameters.AddWithValue(":GlobalPos", ad.GlobalPos.ToString());
|
||||
cmd.Parameters.AddWithValue(":ParcelName", ad.ParcelName.ToString());
|
||||
cmd.Parameters.AddWithValue(":Flags", ad.Flags.ToString());
|
||||
cmd.Parameters.AddWithValue(":ListingPrice", ad.Price.ToString ());
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.DebugFormat("[PROFILES_DATA]" +
|
||||
": ClassifiedesUpdate exception {0}", e.Message);
|
||||
result = e.Message;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public bool DeleteClassifiedRecord(UUID recordId)
|
||||
{
|
||||
string query = string.Empty;
|
||||
|
||||
query += "DELETE FROM classifieds WHERE ";
|
||||
query += "classifieduuid = :ClasifiedId";
|
||||
|
||||
try
|
||||
{
|
||||
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = query;
|
||||
cmd.Parameters.AddWithValue(":ClassifiedId", recordId.ToString());
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.DebugFormat("[PROFILES_DATA]" +
|
||||
": DeleteClassifiedRecord exception {0}", e.Message);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool GetClassifiedInfo(ref UserClassifiedAdd ad, ref string result)
|
||||
{
|
||||
IDataReader reader = null;
|
||||
string query = string.Empty;
|
||||
|
||||
query += "SELECT * FROM classifieds WHERE ";
|
||||
query += "classifieduuid = :AdId";
|
||||
|
||||
try
|
||||
{
|
||||
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = query;
|
||||
cmd.Parameters.AddWithValue(":AdId", ad.ClassifiedId.ToString());
|
||||
|
||||
using (reader = cmd.ExecuteReader())
|
||||
{
|
||||
if(reader.Read ())
|
||||
{
|
||||
ad.CreatorId = new UUID(reader["creatoruuid"].ToString());
|
||||
ad.ParcelId = new UUID(reader["parceluuid"].ToString ());
|
||||
ad.SnapshotId = new UUID(reader["snapshotuuid"].ToString ());
|
||||
ad.CreationDate = Convert.ToInt32(reader["creationdate"]);
|
||||
ad.ExpirationDate = Convert.ToInt32(reader["expirationdate"]);
|
||||
ad.ParentEstate = Convert.ToInt32(reader["parentestate"]);
|
||||
ad.Flags = (byte) Convert.ToUInt32(reader["classifiedflags"]);
|
||||
ad.Category = Convert.ToInt32(reader["category"]);
|
||||
ad.Price = Convert.ToInt16(reader["priceforlisting"]);
|
||||
ad.Name = reader["name"].ToString();
|
||||
ad.Description = reader["description"].ToString();
|
||||
ad.SimName = reader["simname"].ToString();
|
||||
ad.GlobalPos = reader["posglobal"].ToString();
|
||||
ad.ParcelName = reader["parcelname"].ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.DebugFormat("[PROFILES_DATA]" +
|
||||
": GetPickInfo exception {0}", e.Message);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public OSDArray GetAvatarPicks(UUID avatarId)
|
||||
{
|
||||
IDataReader reader = null;
|
||||
string query = string.Empty;
|
||||
|
||||
query += "SELECT `pickuuid`,`name` FROM userpicks WHERE ";
|
||||
query += "creatoruuid = :Id";
|
||||
OSDArray data = new OSDArray();
|
||||
|
||||
try
|
||||
{
|
||||
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = query;
|
||||
cmd.Parameters.AddWithValue(":Id", avatarId.ToString());
|
||||
|
||||
using (reader = cmd.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
OSDMap record = new OSDMap();
|
||||
|
||||
record.Add("pickuuid",OSD.FromString((string)reader["pickuuid"]));
|
||||
record.Add("name",OSD.FromString((string)reader["name"]));
|
||||
data.Add(record);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.DebugFormat("[PROFILES_DATA]" +
|
||||
": GetAvatarPicks exception {0}", e.Message);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
public UserProfilePick GetPickInfo(UUID avatarId, UUID pickId)
|
||||
{
|
||||
IDataReader reader = null;
|
||||
string query = string.Empty;
|
||||
UserProfilePick pick = new UserProfilePick();
|
||||
|
||||
query += "SELECT * FROM userpicks WHERE ";
|
||||
query += "creatoruuid = :CreatorId AND ";
|
||||
query += "pickuuid = :PickId";
|
||||
|
||||
try
|
||||
{
|
||||
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = query;
|
||||
cmd.Parameters.AddWithValue(":CreatorId", avatarId.ToString());
|
||||
cmd.Parameters.AddWithValue(":PickId", pickId.ToString());
|
||||
|
||||
using (reader = cmd.ExecuteReader())
|
||||
{
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
string description = (string)reader["description"];
|
||||
|
||||
if (string.IsNullOrEmpty(description))
|
||||
description = "No description given.";
|
||||
|
||||
UUID.TryParse((string)reader["pickuuid"], out pick.PickId);
|
||||
UUID.TryParse((string)reader["creatoruuid"], out pick.CreatorId);
|
||||
UUID.TryParse((string)reader["parceluuid"], out pick.ParcelId);
|
||||
UUID.TryParse((string)reader["snapshotuuid"], out pick.SnapshotId);
|
||||
pick.GlobalPos = (string)reader["posglobal"];
|
||||
bool.TryParse((string)reader["toppick"].ToString(), out pick.TopPick);
|
||||
bool.TryParse((string)reader["enabled"].ToString(), out pick.Enabled);
|
||||
pick.Name = (string)reader["name"];
|
||||
pick.Desc = description;
|
||||
pick.User = (string)reader["user"];
|
||||
pick.OriginalName = (string)reader["originalname"];
|
||||
pick.SimName = (string)reader["simname"];
|
||||
pick.SortOrder = (int)reader["sortorder"];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.DebugFormat("[PROFILES_DATA]" +
|
||||
": GetPickInfo exception {0}", e.Message);
|
||||
}
|
||||
return pick;
|
||||
}
|
||||
|
||||
public bool UpdatePicksRecord(UserProfilePick pick)
|
||||
{
|
||||
string query = string.Empty;
|
||||
|
||||
query += "INSERT OR REPLACE INTO userpicks (";
|
||||
query += "pickuuid, ";
|
||||
query += "creatoruuid, ";
|
||||
query += "toppick, ";
|
||||
query += "parceluuid, ";
|
||||
query += "name, ";
|
||||
query += "description, ";
|
||||
query += "snapshotuuid, ";
|
||||
query += "user, ";
|
||||
query += "originalname, ";
|
||||
query += "simname, ";
|
||||
query += "posglobal, ";
|
||||
query += "sortorder, ";
|
||||
query += "enabled ) ";
|
||||
query += "VALUES (";
|
||||
query += ":PickId,";
|
||||
query += ":CreatorId,";
|
||||
query += ":TopPick,";
|
||||
query += ":ParcelId,";
|
||||
query += ":Name,";
|
||||
query += ":Desc,";
|
||||
query += ":SnapshotId,";
|
||||
query += ":User,";
|
||||
query += ":Original,";
|
||||
query += ":SimName,";
|
||||
query += ":GlobalPos,";
|
||||
query += ":SortOrder,";
|
||||
query += ":Enabled) ";
|
||||
|
||||
try
|
||||
{
|
||||
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
|
||||
{
|
||||
int top_pick;
|
||||
int.TryParse(pick.TopPick.ToString(), out top_pick);
|
||||
int enabled;
|
||||
int.TryParse(pick.Enabled.ToString(), out enabled);
|
||||
|
||||
cmd.CommandText = query;
|
||||
cmd.Parameters.AddWithValue(":PickId", pick.PickId.ToString());
|
||||
cmd.Parameters.AddWithValue(":CreatorId", pick.CreatorId.ToString());
|
||||
cmd.Parameters.AddWithValue(":TopPick", top_pick);
|
||||
cmd.Parameters.AddWithValue(":ParcelId", pick.ParcelId.ToString());
|
||||
cmd.Parameters.AddWithValue(":Name", pick.Name.ToString());
|
||||
cmd.Parameters.AddWithValue(":Desc", pick.Desc.ToString());
|
||||
cmd.Parameters.AddWithValue(":SnapshotId", pick.SnapshotId.ToString());
|
||||
cmd.Parameters.AddWithValue(":User", pick.User.ToString());
|
||||
cmd.Parameters.AddWithValue(":Original", pick.OriginalName.ToString());
|
||||
cmd.Parameters.AddWithValue(":SimName",pick.SimName.ToString());
|
||||
cmd.Parameters.AddWithValue(":GlobalPos", pick.GlobalPos);
|
||||
cmd.Parameters.AddWithValue(":SortOrder", pick.SortOrder.ToString ());
|
||||
cmd.Parameters.AddWithValue(":Enabled", enabled);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.DebugFormat("[PROFILES_DATA]" +
|
||||
": UpdateAvatarNotes exception {0}", e.Message);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool DeletePicksRecord(UUID pickId)
|
||||
{
|
||||
string query = string.Empty;
|
||||
|
||||
query += "DELETE FROM userpicks WHERE ";
|
||||
query += "pickuuid = :PickId";
|
||||
|
||||
try
|
||||
{
|
||||
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = query;
|
||||
cmd.Parameters.AddWithValue(":PickId", pickId.ToString());
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.DebugFormat("[PROFILES_DATA]" +
|
||||
": DeleteUserPickRecord exception {0}", e.Message);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool GetAvatarNotes(ref UserProfileNotes notes)
|
||||
{
|
||||
IDataReader reader = null;
|
||||
string query = string.Empty;
|
||||
|
||||
query += "SELECT `notes` FROM usernotes WHERE ";
|
||||
query += "useruuid = :Id AND ";
|
||||
query += "targetuuid = :TargetId";
|
||||
OSDArray data = new OSDArray();
|
||||
|
||||
try
|
||||
{
|
||||
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = query;
|
||||
cmd.Parameters.AddWithValue(":Id", notes.UserId.ToString());
|
||||
cmd.Parameters.AddWithValue(":TargetId", notes.TargetId.ToString());
|
||||
|
||||
using (reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
notes.Notes = OSD.FromString((string)reader["notes"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.DebugFormat("[PROFILES_DATA]" +
|
||||
": GetAvatarNotes exception {0}", e.Message);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool UpdateAvatarNotes(ref UserProfileNotes note, ref string result)
|
||||
{
|
||||
string query = string.Empty;
|
||||
bool remove;
|
||||
|
||||
if(string.IsNullOrEmpty(note.Notes))
|
||||
{
|
||||
remove = true;
|
||||
query += "DELETE FROM usernotes WHERE ";
|
||||
query += "useruuid=:UserId AND ";
|
||||
query += "targetuuid=:TargetId";
|
||||
}
|
||||
else
|
||||
{
|
||||
remove = false;
|
||||
query += "INSERT OR REPLACE INTO usernotes VALUES ( ";
|
||||
query += ":UserId,";
|
||||
query += ":TargetId,";
|
||||
query += ":Notes )";
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = query;
|
||||
|
||||
if(!remove)
|
||||
cmd.Parameters.AddWithValue(":Notes", note.Notes);
|
||||
cmd.Parameters.AddWithValue(":TargetId", note.TargetId.ToString ());
|
||||
cmd.Parameters.AddWithValue(":UserId", note.UserId.ToString());
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.DebugFormat("[PROFILES_DATA]" +
|
||||
": UpdateAvatarNotes exception {0}", e.Message);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool GetAvatarProperties(ref UserProfileProperties props, ref string result)
|
||||
{
|
||||
IDataReader reader = null;
|
||||
string query = string.Empty;
|
||||
|
||||
query += "SELECT * FROM userprofile WHERE ";
|
||||
query += "useruuid = :Id";
|
||||
|
||||
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = query;
|
||||
cmd.Parameters.AddWithValue(":Id", props.UserId.ToString());
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
reader = cmd.ExecuteReader();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
m_log.DebugFormat("[PROFILES_DATA]" +
|
||||
": GetAvatarProperties exception {0}", e.Message);
|
||||
result = e.Message;
|
||||
return false;
|
||||
}
|
||||
if(reader != null && reader.Read())
|
||||
{
|
||||
m_log.DebugFormat("[PROFILES_DATA]" +
|
||||
": Getting data for {0}.", props.UserId);
|
||||
|
||||
props.WebUrl = (string)reader["profileURL"];
|
||||
UUID.TryParse((string)reader["profileImage"], out props.ImageId);
|
||||
props.AboutText = (string)reader["profileAboutText"];
|
||||
UUID.TryParse((string)reader["profileFirstImage"], out props.FirstLifeImageId);
|
||||
props.FirstLifeText = (string)reader["profileFirstText"];
|
||||
UUID.TryParse((string)reader["profilePartner"], out props.PartnerId);
|
||||
props.WantToMask = (int)reader["profileWantToMask"];
|
||||
props.WantToText = (string)reader["profileWantToText"];
|
||||
props.SkillsMask = (int)reader["profileSkillsMask"];
|
||||
props.SkillsText = (string)reader["profileSkillsText"];
|
||||
props.Language = (string)reader["profileLanguages"];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.DebugFormat("[PROFILES_DATA]" +
|
||||
": No data for {0}", props.UserId);
|
||||
|
||||
props.WebUrl = string.Empty;
|
||||
props.ImageId = UUID.Zero;
|
||||
props.AboutText = string.Empty;
|
||||
props.FirstLifeImageId = UUID.Zero;
|
||||
props.FirstLifeText = string.Empty;
|
||||
props.PartnerId = UUID.Zero;
|
||||
props.WantToMask = 0;
|
||||
props.WantToText = string.Empty;
|
||||
props.SkillsMask = 0;
|
||||
props.SkillsText = string.Empty;
|
||||
props.Language = string.Empty;
|
||||
props.PublishProfile = false;
|
||||
props.PublishMature = false;
|
||||
|
||||
query = "INSERT INTO userprofile (";
|
||||
query += "useruuid, ";
|
||||
query += "profilePartner, ";
|
||||
query += "profileAllowPublish, ";
|
||||
query += "profileMaturePublish, ";
|
||||
query += "profileURL, ";
|
||||
query += "profileWantToMask, ";
|
||||
query += "profileWantToText, ";
|
||||
query += "profileSkillsMask, ";
|
||||
query += "profileSkillsText, ";
|
||||
query += "profileLanguages, ";
|
||||
query += "profileImage, ";
|
||||
query += "profileAboutText, ";
|
||||
query += "profileFirstImage, ";
|
||||
query += "profileFirstText) VALUES (";
|
||||
query += ":userId, ";
|
||||
query += ":profilePartner, ";
|
||||
query += ":profileAllowPublish, ";
|
||||
query += ":profileMaturePublish, ";
|
||||
query += ":profileURL, ";
|
||||
query += ":profileWantToMask, ";
|
||||
query += ":profileWantToText, ";
|
||||
query += ":profileSkillsMask, ";
|
||||
query += ":profileSkillsText, ";
|
||||
query += ":profileLanguages, ";
|
||||
query += ":profileImage, ";
|
||||
query += ":profileAboutText, ";
|
||||
query += ":profileFirstImage, ";
|
||||
query += ":profileFirstText)";
|
||||
|
||||
using (SqliteCommand put = (SqliteCommand)m_connection.CreateCommand())
|
||||
{
|
||||
put.CommandText = query;
|
||||
put.Parameters.AddWithValue(":userId", props.UserId.ToString());
|
||||
put.Parameters.AddWithValue(":profilePartner", props.PartnerId.ToString());
|
||||
put.Parameters.AddWithValue(":profileAllowPublish", props.PublishProfile);
|
||||
put.Parameters.AddWithValue(":profileMaturePublish", props.PublishMature);
|
||||
put.Parameters.AddWithValue(":profileURL", props.WebUrl);
|
||||
put.Parameters.AddWithValue(":profileWantToMask", props.WantToMask);
|
||||
put.Parameters.AddWithValue(":profileWantToText", props.WantToText);
|
||||
put.Parameters.AddWithValue(":profileSkillsMask", props.SkillsMask);
|
||||
put.Parameters.AddWithValue(":profileSkillsText", props.SkillsText);
|
||||
put.Parameters.AddWithValue(":profileLanguages", props.Language);
|
||||
put.Parameters.AddWithValue(":profileImage", props.ImageId.ToString());
|
||||
put.Parameters.AddWithValue(":profileAboutText", props.AboutText);
|
||||
put.Parameters.AddWithValue(":profileFirstImage", props.FirstLifeImageId.ToString());
|
||||
put.Parameters.AddWithValue(":profileFirstText", props.FirstLifeText);
|
||||
|
||||
put.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool UpdateAvatarProperties(ref UserProfileProperties props, ref string result)
|
||||
{
|
||||
string query = string.Empty;
|
||||
|
||||
query += "UPDATE userprofile SET ";
|
||||
query += "profilePartner=:profilePartner, ";
|
||||
query += "profileURL=:profileURL, ";
|
||||
query += "profileImage=:image, ";
|
||||
query += "profileAboutText=:abouttext,";
|
||||
query += "profileFirstImage=:firstlifeimage,";
|
||||
query += "profileFirstText=:firstlifetext ";
|
||||
query += "WHERE useruuid=:uuid";
|
||||
|
||||
try
|
||||
{
|
||||
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = query;
|
||||
cmd.Parameters.AddWithValue(":profileURL", props.WebUrl);
|
||||
cmd.Parameters.AddWithValue(":profilePartner", props.PartnerId.ToString());
|
||||
cmd.Parameters.AddWithValue(":image", props.ImageId.ToString());
|
||||
cmd.Parameters.AddWithValue(":abouttext", props.AboutText);
|
||||
cmd.Parameters.AddWithValue(":firstlifeimage", props.FirstLifeImageId.ToString());
|
||||
cmd.Parameters.AddWithValue(":firstlifetext", props.FirstLifeText);
|
||||
cmd.Parameters.AddWithValue(":uuid", props.UserId.ToString());
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.DebugFormat("[PROFILES_DATA]" +
|
||||
": AgentPropertiesUpdate exception {0}", e.Message);
|
||||
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool UpdateAvatarInterests(UserProfileProperties up, ref string result)
|
||||
{
|
||||
string query = string.Empty;
|
||||
|
||||
query += "UPDATE userprofile SET ";
|
||||
query += "profileWantToMask=:WantMask, ";
|
||||
query += "profileWantToText=:WantText,";
|
||||
query += "profileSkillsMask=:SkillsMask,";
|
||||
query += "profileSkillsText=:SkillsText, ";
|
||||
query += "profileLanguages=:Languages ";
|
||||
query += "WHERE useruuid=:uuid";
|
||||
|
||||
try
|
||||
{
|
||||
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = query;
|
||||
cmd.Parameters.AddWithValue(":WantMask", up.WantToMask);
|
||||
cmd.Parameters.AddWithValue(":WantText", up.WantToText);
|
||||
cmd.Parameters.AddWithValue(":SkillsMask", up.SkillsMask);
|
||||
cmd.Parameters.AddWithValue(":SkillsText", up.SkillsText);
|
||||
cmd.Parameters.AddWithValue(":Languages", up.Language);
|
||||
cmd.Parameters.AddWithValue(":uuid", up.UserId.ToString());
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.DebugFormat("[PROFILES_DATA]" +
|
||||
": AgentInterestsUpdate exception {0}", e.Message);
|
||||
result = e.Message;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public bool GetUserAppData(ref UserAppData props, ref string result)
|
||||
{
|
||||
IDataReader reader = null;
|
||||
string query = string.Empty;
|
||||
|
||||
query += "SELECT * FROM `userdata` WHERE ";
|
||||
query += "UserId = :Id AND ";
|
||||
query += "TagId = :TagId";
|
||||
|
||||
try
|
||||
{
|
||||
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = query;
|
||||
cmd.Parameters.AddWithValue(":Id", props.UserId.ToString());
|
||||
cmd.Parameters.AddWithValue (":TagId", props.TagId.ToString());
|
||||
|
||||
using (reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
|
||||
{
|
||||
if(reader.Read())
|
||||
{
|
||||
props.DataKey = (string)reader["DataKey"];
|
||||
props.DataVal = (string)reader["DataVal"];
|
||||
}
|
||||
else
|
||||
{
|
||||
query += "INSERT INTO userdata VALUES ( ";
|
||||
query += ":UserId,";
|
||||
query += ":TagId,";
|
||||
query += ":DataKey,";
|
||||
query += ":DataVal) ";
|
||||
|
||||
using (SqliteCommand put = (SqliteCommand)m_connection.CreateCommand())
|
||||
{
|
||||
put.Parameters.AddWithValue(":Id", props.UserId.ToString());
|
||||
put.Parameters.AddWithValue(":TagId", props.TagId.ToString());
|
||||
put.Parameters.AddWithValue(":DataKey", props.DataKey.ToString());
|
||||
put.Parameters.AddWithValue(":DataVal", props.DataVal.ToString());
|
||||
|
||||
put.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.DebugFormat("[PROFILES_DATA]" +
|
||||
": Requst application data exception {0}", e.Message);
|
||||
result = e.Message;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public bool SetUserAppData(UserAppData props, ref string result)
|
||||
{
|
||||
string query = string.Empty;
|
||||
|
||||
query += "UPDATE userdata SET ";
|
||||
query += "TagId = :TagId, ";
|
||||
query += "DataKey = :DataKey, ";
|
||||
query += "DataVal = :DataVal WHERE ";
|
||||
query += "UserId = :UserId AND ";
|
||||
query += "TagId = :TagId";
|
||||
|
||||
try
|
||||
{
|
||||
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = query;
|
||||
cmd.Parameters.AddWithValue(":UserId", props.UserId.ToString());
|
||||
cmd.Parameters.AddWithValue(":TagId", props.TagId.ToString ());
|
||||
cmd.Parameters.AddWithValue(":DataKey", props.DataKey.ToString ());
|
||||
cmd.Parameters.AddWithValue(":DataVal", props.DataKey.ToString ());
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.DebugFormat("[PROFILES_DATA]" +
|
||||
": SetUserData exception {0}", e.Message);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public OSDArray GetUserImageAssets(UUID avatarId)
|
||||
{
|
||||
IDataReader reader = null;
|
||||
OSDArray data = new OSDArray();
|
||||
string query = "SELECT `snapshotuuid` FROM {0} WHERE `creatoruuid` = :Id";
|
||||
|
||||
// Get classified image assets
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = query;
|
||||
cmd.Parameters.AddWithValue(":Id", avatarId.ToString());
|
||||
|
||||
using (reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
|
||||
{
|
||||
while(reader.Read())
|
||||
{
|
||||
data.Add(new OSDString((string)reader["snapshotuuid"].ToString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = query;
|
||||
cmd.Parameters.AddWithValue(":Id", avatarId.ToString());
|
||||
|
||||
using (reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
|
||||
{
|
||||
if(reader.Read())
|
||||
{
|
||||
data.Add(new OSDString((string)reader["snapshotuuid"].ToString ()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
query = "SELECT `profileImage`, `profileFirstImage` FROM `userprofile` WHERE `useruuid` = :Id";
|
||||
|
||||
using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = query;
|
||||
cmd.Parameters.AddWithValue(":Id", avatarId.ToString());
|
||||
|
||||
using (reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
|
||||
{
|
||||
if(reader.Read())
|
||||
{
|
||||
data.Add(new OSDString((string)reader["profileImage"].ToString ()));
|
||||
data.Add(new OSDString((string)reader["profileFirstImage"].ToString ()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.DebugFormat("[PROFILES_DATA]" +
|
||||
": GetAvatarNotes exception {0}", e.Message);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,5 +120,24 @@ namespace OpenSim.Framework
|
||||
sequenceNum = args["seq_num"].AsInteger();
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
Animation other = obj as Animation;
|
||||
if (other != null)
|
||||
{
|
||||
return (other.AnimID.Equals(this.AnimID)
|
||||
&& other.SequenceNum == this.SequenceNum
|
||||
&& other.ObjectID.Equals(this.ObjectID) );
|
||||
}
|
||||
return base.Equals(obj);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "AnimID=" + AnimID.ToString()
|
||||
+ "/seq=" + SequenceNum.ToString()
|
||||
+ "/objID=" + ObjectID.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ namespace OpenSim.Framework
|
||||
protected AvatarWearable[] m_wearables;
|
||||
protected Dictionary<int, List<AvatarAttachment>> m_attachments;
|
||||
protected float m_avatarHeight = 0;
|
||||
protected UUID[] m_texturehashes;
|
||||
|
||||
public virtual int Serial
|
||||
{
|
||||
@@ -98,6 +99,8 @@ namespace OpenSim.Framework
|
||||
SetDefaultParams();
|
||||
SetHeight();
|
||||
m_attachments = new Dictionary<int, List<AvatarAttachment>>();
|
||||
|
||||
ResetTextureHashes();
|
||||
}
|
||||
|
||||
public AvatarAppearance(OSDMap map)
|
||||
@@ -108,32 +111,6 @@ namespace OpenSim.Framework
|
||||
SetHeight();
|
||||
}
|
||||
|
||||
public AvatarAppearance(AvatarWearable[] wearables, Primitive.TextureEntry textureEntry, byte[] visualParams)
|
||||
{
|
||||
// m_log.WarnFormat("[AVATAR APPEARANCE] create initialized appearance");
|
||||
|
||||
m_serial = 0;
|
||||
|
||||
if (wearables != null)
|
||||
m_wearables = wearables;
|
||||
else
|
||||
SetDefaultWearables();
|
||||
|
||||
if (textureEntry != null)
|
||||
m_texture = textureEntry;
|
||||
else
|
||||
SetDefaultTexture();
|
||||
|
||||
if (visualParams != null)
|
||||
m_visualparams = visualParams;
|
||||
else
|
||||
SetDefaultParams();
|
||||
|
||||
SetHeight();
|
||||
|
||||
m_attachments = new Dictionary<int, List<AvatarAttachment>>();
|
||||
}
|
||||
|
||||
public AvatarAppearance(AvatarAppearance appearance) : this(appearance, true)
|
||||
{
|
||||
}
|
||||
@@ -151,6 +128,8 @@ namespace OpenSim.Framework
|
||||
SetHeight();
|
||||
m_attachments = new Dictionary<int, List<AvatarAttachment>>();
|
||||
|
||||
ResetTextureHashes();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -166,6 +145,10 @@ namespace OpenSim.Framework
|
||||
SetWearable(i,appearance.Wearables[i]);
|
||||
}
|
||||
|
||||
m_texturehashes = new UUID[AvatarAppearance.TEXTURE_COUNT];
|
||||
for (int i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
|
||||
m_texturehashes[i] = new UUID(appearance.m_texturehashes[i]);
|
||||
|
||||
m_texture = null;
|
||||
if (appearance.Texture != null)
|
||||
{
|
||||
@@ -200,6 +183,37 @@ namespace OpenSim.Framework
|
||||
}
|
||||
}
|
||||
|
||||
public void ResetTextureHashes()
|
||||
{
|
||||
m_texturehashes = new UUID[AvatarAppearance.TEXTURE_COUNT];
|
||||
for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
|
||||
m_texturehashes[i] = UUID.Zero;
|
||||
}
|
||||
|
||||
public UUID GetTextureHash(int textureIndex)
|
||||
{
|
||||
return m_texturehashes[NormalizeBakedTextureIndex(textureIndex)];
|
||||
}
|
||||
|
||||
public void SetTextureHash(int textureIndex, UUID textureHash)
|
||||
{
|
||||
m_texturehashes[NormalizeBakedTextureIndex(textureIndex)] = new UUID(textureHash);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normalizes the texture index to the actual bake index, this is done to
|
||||
/// accommodate older viewers that send the BAKE_INDICES index rather than
|
||||
/// the actual texture index
|
||||
/// </summary>
|
||||
private int NormalizeBakedTextureIndex(int textureIndex)
|
||||
{
|
||||
// Earlier viewer send the index into the baked index array, just trying to be careful here
|
||||
if (textureIndex < BAKE_INDICES.Length)
|
||||
return BAKE_INDICES[textureIndex];
|
||||
|
||||
return textureIndex;
|
||||
}
|
||||
|
||||
public void ClearWearables()
|
||||
{
|
||||
m_wearables = new AvatarWearable[AvatarWearable.MAX_WEARABLES];
|
||||
@@ -223,12 +237,7 @@ namespace OpenSim.Framework
|
||||
m_serial = 0;
|
||||
|
||||
SetDefaultTexture();
|
||||
|
||||
//for (int i = 0; i < BAKE_INDICES.Length; i++)
|
||||
// {
|
||||
// int idx = BAKE_INDICES[i];
|
||||
// m_texture.FaceTextures[idx].TextureID = UUID.Zero;
|
||||
// }
|
||||
ResetTextureHashes();
|
||||
}
|
||||
|
||||
protected virtual void SetDefaultParams()
|
||||
@@ -459,45 +468,59 @@ namespace OpenSim.Framework
|
||||
if (attachpoint == 0)
|
||||
return false;
|
||||
|
||||
if (item == UUID.Zero)
|
||||
lock (m_attachments)
|
||||
{
|
||||
lock (m_attachments)
|
||||
if (item == UUID.Zero)
|
||||
{
|
||||
if (m_attachments.ContainsKey(attachpoint))
|
||||
{
|
||||
m_attachments.Remove(attachpoint);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// When a user logs in, the attachment item ids are pulled from persistence in the Avatars table. However,
|
||||
// the asset ids are not saved. When the avatar enters a simulator the attachments are set again. If
|
||||
// we simply perform an item check here then the asset ids (which are now present) are never set, and NPC attachments
|
||||
// later fail unless the attachment is detached and reattached.
|
||||
//
|
||||
// Therefore, we will carry on with the set if the existing attachment has no asset id.
|
||||
AvatarAttachment existingAttachment = GetAttachmentForItem(item);
|
||||
if (existingAttachment != null)
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[AVATAR APPEARANCE]: Found existing attachment for {0}, asset {1} at point {2}",
|
||||
// existingAttachment.ItemID, existingAttachment.AssetID, existingAttachment.AttachPoint);
|
||||
|
||||
if (existingAttachment.AssetID != UUID.Zero && existingAttachment.AttachPoint == (attachpoint & 0x7F))
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[AVATAR APPEARANCE]: Ignoring attempt to attach an already attached item {0} at point {1}",
|
||||
item, attachpoint);
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove it here so that the later append does not add a second attachment but we still update
|
||||
// the assetID
|
||||
DetachAttachment(existingAttachment.ItemID);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// When a user logs in, the attachment item ids are pulled from persistence in the Avatars table. However,
|
||||
// the asset ids are not saved. When the avatar enters a simulator the attachments are set again. If
|
||||
// we simply perform an item check here then the asset ids (which are now present) are never set, and NPC attachments
|
||||
// later fail unless the attachment is detached and reattached.
|
||||
//
|
||||
// Therefore, we will carry on with the set if the existing attachment has no asset id.
|
||||
AvatarAttachment existingAttachment = GetAttachmentForItem(item);
|
||||
if (existingAttachment != null
|
||||
&& existingAttachment.AssetID != UUID.Zero
|
||||
&& existingAttachment.AttachPoint == (attachpoint & 0x7F))
|
||||
{
|
||||
// m_log.DebugFormat("[AVATAR APPEARANCE] attempt to attach an already attached item {0}",item);
|
||||
return false;
|
||||
}
|
||||
|
||||
// check if this is an append or a replace, 0x80 marks it as an append
|
||||
if ((attachpoint & 0x80) > 0)
|
||||
{
|
||||
// strip the append bit
|
||||
int point = attachpoint & 0x7F;
|
||||
AppendAttachment(new AvatarAttachment(point, item, asset));
|
||||
}
|
||||
else
|
||||
{
|
||||
ReplaceAttachment(new AvatarAttachment(attachpoint,item, asset));
|
||||
// check if this is an append or a replace, 0x80 marks it as an append
|
||||
if ((attachpoint & 0x80) > 0)
|
||||
{
|
||||
// strip the append bit
|
||||
int point = attachpoint & 0x7F;
|
||||
AppendAttachment(new AvatarAttachment(point, item, asset));
|
||||
}
|
||||
else
|
||||
{
|
||||
ReplaceAttachment(new AvatarAttachment(attachpoint,item, asset));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -547,6 +570,10 @@ namespace OpenSim.Framework
|
||||
int index = kvp.Value.FindIndex(delegate(AvatarAttachment a) { return a.ItemID == itemID; });
|
||||
if (index >= 0)
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[AVATAR APPEARANCE]: Detaching attachment {0}, index {1}, point {2}",
|
||||
// m_attachments[kvp.Key][index].ItemID, index, m_attachments[kvp.Key][index].AttachPoint);
|
||||
|
||||
// Remove it from the list of attachments at that attach point
|
||||
m_attachments[kvp.Key].RemoveAt(index);
|
||||
|
||||
@@ -580,6 +607,12 @@ namespace OpenSim.Framework
|
||||
data["serial"] = OSD.FromInteger(m_serial);
|
||||
data["height"] = OSD.FromReal(m_avatarHeight);
|
||||
|
||||
// Hashes
|
||||
OSDArray hashes = new OSDArray(AvatarAppearance.TEXTURE_COUNT);
|
||||
for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
|
||||
hashes.Add(OSD.FromUUID(m_texturehashes[i]));
|
||||
data["hashes"] = hashes;
|
||||
|
||||
// Wearables
|
||||
OSDArray wears = new OSDArray(AvatarWearable.MAX_WEARABLES);
|
||||
for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++)
|
||||
@@ -624,6 +657,25 @@ namespace OpenSim.Framework
|
||||
|
||||
try
|
||||
{
|
||||
// Hashes
|
||||
m_texturehashes = new UUID[AvatarAppearance.TEXTURE_COUNT];
|
||||
if ((data != null) && (data["hashes"] != null) && (data["hashes"]).Type == OSDType.Array)
|
||||
{
|
||||
OSDArray hashes = (OSDArray)(data["hashes"]);
|
||||
for (int i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
|
||||
{
|
||||
UUID hashID = UUID.Zero;
|
||||
if (i < hashes.Count && hashes[i] != null)
|
||||
hashID = hashes[i].AsUUID();
|
||||
m_texturehashes[i] = hashID;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
|
||||
m_texturehashes[i] = UUID.Zero;
|
||||
}
|
||||
|
||||
// Wearables
|
||||
SetDefaultWearables();
|
||||
if ((data != null) && (data["wearables"] != null) && (data["wearables"]).Type == OSDType.Array)
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace OpenSim.Framework
|
||||
{
|
||||
lock (m_queueSync)
|
||||
{
|
||||
if (m_queue.Count < 1 && m_pqueue.Count < 1)
|
||||
while (m_queue.Count < 1 && m_pqueue.Count < 1)
|
||||
{
|
||||
Monitor.Wait(m_queueSync);
|
||||
}
|
||||
@@ -76,9 +76,10 @@ namespace OpenSim.Framework
|
||||
{
|
||||
lock (m_queueSync)
|
||||
{
|
||||
if (m_queue.Count < 1 && m_pqueue.Count < 1)
|
||||
bool success = true;
|
||||
while (m_queue.Count < 1 && m_pqueue.Count < 1 && success)
|
||||
{
|
||||
Monitor.Wait(m_queueSync, msTimeout);
|
||||
success = Monitor.Wait(m_queueSync, msTimeout);
|
||||
}
|
||||
|
||||
if (m_pqueue.Count > 0)
|
||||
@@ -89,8 +90,17 @@ namespace OpenSim.Framework
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicate whether this queue contains the given item.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method is not thread-safe. Do not rely on the result without consistent external locking.
|
||||
/// </remarks>
|
||||
public bool Contains(T item)
|
||||
{
|
||||
if (m_queue.Count < 1 && m_pqueue.Count < 1)
|
||||
return false;
|
||||
|
||||
lock (m_queueSync)
|
||||
{
|
||||
if (m_pqueue.Contains(item))
|
||||
@@ -99,16 +109,28 @@ namespace OpenSim.Framework
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a count of the number of requests on this queue.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method is not thread-safe. Do not rely on the result without consistent external locking.
|
||||
/// </remarks>
|
||||
public int Count()
|
||||
{
|
||||
lock (m_queueSync)
|
||||
{
|
||||
return m_queue.Count+m_pqueue.Count;
|
||||
}
|
||||
return m_queue.Count + m_pqueue.Count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the array of items on this queue.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method is not thread-safe. Do not rely on the result without consistent external locking.
|
||||
/// </remarks>
|
||||
public T[] GetQueueArray()
|
||||
{
|
||||
if (m_queue.Count < 1 && m_pqueue.Count < 1)
|
||||
return new T[0];
|
||||
|
||||
lock (m_queueSync)
|
||||
{
|
||||
return m_queue.ToArray();
|
||||
|
||||
46
OpenSim/Framework/CachedTextureEventArg.cs
Normal file
46
OpenSim/Framework/CachedTextureEventArg.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* 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 the OpenSimulator Project 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 DEVELOPERS ``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 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Framework
|
||||
{
|
||||
public class CachedTextureRequestArg
|
||||
{
|
||||
public int BakedTextureIndex;
|
||||
public UUID WearableHashID;
|
||||
}
|
||||
|
||||
public class CachedTextureResponseArg
|
||||
{
|
||||
public int BakedTextureIndex;
|
||||
public UUID BakedTextureID;
|
||||
public String HostName;
|
||||
}
|
||||
}
|
||||
@@ -171,9 +171,10 @@ namespace OpenSim.Framework
|
||||
/// Soon to be decommissioned
|
||||
/// </summary>
|
||||
/// <param name="cAgent"></param>
|
||||
public void CopyFrom(ChildAgentDataUpdate cAgent)
|
||||
public void CopyFrom(ChildAgentDataUpdate cAgent, UUID sid)
|
||||
{
|
||||
AgentID = new UUID(cAgent.AgentID);
|
||||
SessionID = sid;
|
||||
|
||||
// next: ???
|
||||
Size = new Vector3();
|
||||
@@ -286,7 +287,13 @@ namespace OpenSim.Framework
|
||||
public Vector3 AtAxis;
|
||||
public Vector3 LeftAxis;
|
||||
public Vector3 UpAxis;
|
||||
public bool ChangedGrid;
|
||||
|
||||
/// <summary>
|
||||
/// Signal on a V2 teleport that Scene.IncomingChildAgentDataUpdate(AgentData ad) should wait for the
|
||||
/// scene presence to become root (triggered when the viewer sends a CompleteAgentMovement UDP packet after
|
||||
/// establishing the connection triggered by it's receipt of a TeleportFinish EQ message).
|
||||
/// </summary>
|
||||
public bool SenderWantsToWaitForRoot;
|
||||
|
||||
public float Far;
|
||||
public float Aspect;
|
||||
@@ -355,8 +362,9 @@ namespace OpenSim.Framework
|
||||
args["left_axis"] = OSD.FromString(LeftAxis.ToString());
|
||||
args["up_axis"] = OSD.FromString(UpAxis.ToString());
|
||||
|
||||
|
||||
args["changed_grid"] = OSD.FromBoolean(ChangedGrid);
|
||||
//backwards compatibility
|
||||
args["changed_grid"] = OSD.FromBoolean(SenderWantsToWaitForRoot);
|
||||
args["wait_for_root"] = OSD.FromBoolean(SenderWantsToWaitForRoot);
|
||||
args["far"] = OSD.FromReal(Far);
|
||||
args["aspect"] = OSD.FromReal(Aspect);
|
||||
|
||||
@@ -525,8 +533,8 @@ namespace OpenSim.Framework
|
||||
if (args["up_axis"] != null)
|
||||
Vector3.TryParse(args["up_axis"].AsString(), out AtAxis);
|
||||
|
||||
if (args["changed_grid"] != null)
|
||||
ChangedGrid = args["changed_grid"].AsBoolean();
|
||||
if (args.ContainsKey("wait_for_root") && args["wait_for_root"] != null)
|
||||
SenderWantsToWaitForRoot = args["wait_for_root"].AsBoolean();
|
||||
|
||||
if (args["far"] != null)
|
||||
Far = (float)(args["far"].AsReal());
|
||||
|
||||
@@ -33,12 +33,13 @@ namespace OpenSim.Framework
|
||||
{
|
||||
public class ClientInfo
|
||||
{
|
||||
public AgentCircuitData agentcircuit;
|
||||
public readonly DateTime StartedTime = DateTime.Now;
|
||||
public AgentCircuitData agentcircuit = null;
|
||||
|
||||
public Dictionary<uint, byte[]> needAck;
|
||||
|
||||
public List<byte[]> out_packets;
|
||||
public Dictionary<uint, uint> pendingAcks;
|
||||
public List<byte[]> out_packets = new List<byte[]>();
|
||||
public Dictionary<uint, uint> pendingAcks = new Dictionary<uint,uint>();
|
||||
public EndPoint proxyEP;
|
||||
|
||||
public uint sequence;
|
||||
@@ -53,5 +54,9 @@ namespace OpenSim.Framework
|
||||
public int assetThrottle;
|
||||
public int textureThrottle;
|
||||
public int totalThrottle;
|
||||
|
||||
public Dictionary<string, int> SyncRequests = new Dictionary<string,int>();
|
||||
public Dictionary<string, int> AsyncRequests = new Dictionary<string,int>();
|
||||
public Dictionary<string, int> GenericRequests = new Dictionary<string,int>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,12 +156,32 @@ namespace OpenSim.Framework.Console
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a minimum vector input from the console to an OpenMetaverse.Vector3
|
||||
/// Convert a console integer to an int, automatically complaining if a console is given.
|
||||
/// </summary>
|
||||
/// <param name='console'>Can be null if no console is available.</param>
|
||||
/// <param name='rawConsoleVector'>/param>
|
||||
/// <param name='vector'></param>
|
||||
/// <returns></returns>
|
||||
public static bool TryParseConsoleBool(ICommandConsole console, string rawConsoleString, out bool b)
|
||||
{
|
||||
if (!bool.TryParse(rawConsoleString, out b))
|
||||
{
|
||||
if (console != null)
|
||||
console.OutputFormat("ERROR: {0} is not a true or false value", rawConsoleString);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a console integer to an int, automatically complaining if a console is given.
|
||||
/// </summary>
|
||||
/// <param name='console'>Can be null if no console is available.</param>
|
||||
/// <param name='rawConsoleInt'>/param>
|
||||
/// <param name='i'></param>
|
||||
/// <returns></returns>
|
||||
public static bool TryParseConsoleInt(ICommandConsole console, string rawConsoleInt, out int i)
|
||||
{
|
||||
if (!int.TryParse(rawConsoleInt, out i))
|
||||
@@ -174,6 +194,31 @@ namespace OpenSim.Framework.Console
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a console integer to a natural int, automatically complaining if a console is given.
|
||||
/// </summary>
|
||||
/// <param name='console'>Can be null if no console is available.</param>
|
||||
/// <param name='rawConsoleInt'>/param>
|
||||
/// <param name='i'></param>
|
||||
/// <returns></returns>
|
||||
public static bool TryParseConsoleNaturalInt(ICommandConsole console, string rawConsoleInt, out int i)
|
||||
{
|
||||
if (TryParseConsoleInt(console, rawConsoleInt, out i))
|
||||
{
|
||||
if (i < 0)
|
||||
{
|
||||
if (console != null)
|
||||
console.OutputFormat("ERROR: {0} is not a positive integer", rawConsoleInt);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a minimum vector input from the console to an OpenMetaverse.Vector3
|
||||
|
||||
@@ -420,6 +420,21 @@ namespace OpenSim.Framework.Console
|
||||
SetCursorLeft(0);
|
||||
m_cursorYPosition = SetCursorTop(m_cursorYPosition);
|
||||
|
||||
if (m_echo)
|
||||
System.Console.Write("{0}{1} ", prompt, m_commandLine);
|
||||
else
|
||||
System.Console.Write("{0}", prompt);
|
||||
|
||||
break;
|
||||
case ConsoleKey.Delete:
|
||||
if (m_cursorXPosition == m_commandLine.Length)
|
||||
break;
|
||||
|
||||
m_commandLine.Remove(m_cursorXPosition, 1);
|
||||
|
||||
SetCursorLeft(0);
|
||||
m_cursorYPosition = SetCursorTop(m_cursorYPosition);
|
||||
|
||||
if (m_echo)
|
||||
System.Console.Write("{0}{1} ", prompt, m_commandLine);
|
||||
else
|
||||
|
||||
@@ -234,7 +234,7 @@ namespace OpenSim.Framework.Console
|
||||
string uri = "/ReadResponses/" + sessionID.ToString() + "/";
|
||||
|
||||
m_Server.AddPollServiceHTTPHandler(
|
||||
uri, new PollServiceEventArgs(null, HasEvents, GetEvents, NoEvents, sessionID));
|
||||
uri, new PollServiceEventArgs(null, uri, HasEvents, GetEvents, NoEvents, sessionID,25000)); // 25 secs timeout
|
||||
|
||||
XmlDocument xmldoc = new XmlDocument();
|
||||
XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration,
|
||||
@@ -425,7 +425,7 @@ namespace OpenSim.Framework.Console
|
||||
return false;
|
||||
}
|
||||
|
||||
private Hashtable GetEvents(UUID RequestID, UUID sessionID, string request)
|
||||
private Hashtable GetEvents(UUID RequestID, UUID sessionID)
|
||||
{
|
||||
ConsoleConnection c = null;
|
||||
|
||||
|
||||
@@ -29,10 +29,12 @@ using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using System.Xml.Schema;
|
||||
using System.Xml.Serialization;
|
||||
using log4net;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.StructuredData;
|
||||
|
||||
@@ -48,13 +50,20 @@ namespace OpenSim.Framework
|
||||
/// within their data store. However, avoid storing large amounts of data because that
|
||||
/// would slow down database access.
|
||||
/// </remarks>
|
||||
public class DAMap : IDictionary<string, OSDMap>, IXmlSerializable
|
||||
public class DAMap : IXmlSerializable
|
||||
{
|
||||
private static readonly int MIN_STORE_NAME_LENGTH = 4;
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
protected OSDMap m_map;
|
||||
|
||||
public DAMap() { m_map = new OSDMap(); }
|
||||
private static readonly int MIN_NAMESPACE_LENGTH = 4;
|
||||
|
||||
private OSDMap m_map = new OSDMap();
|
||||
|
||||
// WARNING: this is temporary for experimentation only, it will be removed!!!!
|
||||
public OSDMap TopLevelMap
|
||||
{
|
||||
get { return m_map; }
|
||||
set { m_map = value; }
|
||||
}
|
||||
|
||||
public XmlSchema GetSchema() { return null; }
|
||||
|
||||
@@ -64,39 +73,34 @@ namespace OpenSim.Framework
|
||||
map.ReadXml(rawXml);
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
public void ReadXml(XmlReader reader)
|
||||
{
|
||||
ReadXml(reader.ReadInnerXml());
|
||||
}
|
||||
|
||||
public void ReadXml(string rawXml)
|
||||
{
|
||||
// System.Console.WriteLine("Trying to deserialize [{0}]", rawXml);
|
||||
|
||||
lock (this)
|
||||
{
|
||||
m_map = (OSDMap)OSDParser.DeserializeLLSDXml(rawXml);
|
||||
}
|
||||
|
||||
// WARNING: this is temporary for experimentation only, it will be removed!!!!
|
||||
public OSDMap TopLevelMap
|
||||
{
|
||||
get { return m_map; }
|
||||
set { m_map = value; }
|
||||
}
|
||||
|
||||
|
||||
public void ReadXml(XmlReader reader)
|
||||
{
|
||||
ReadXml(reader.ReadInnerXml());
|
||||
}
|
||||
|
||||
public string ToXml()
|
||||
{
|
||||
lock (this)
|
||||
return OSDParser.SerializeLLSDXmlString(m_map);
|
||||
SanitiseMap(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteXml(XmlWriter writer)
|
||||
{
|
||||
writer.WriteRaw(ToXml());
|
||||
}
|
||||
|
||||
|
||||
public string ToXml()
|
||||
{
|
||||
lock (this)
|
||||
return OSDParser.SerializeLLSDXmlString(m_map);
|
||||
}
|
||||
|
||||
public void CopyFrom(DAMap other)
|
||||
{
|
||||
// Deep copy
|
||||
@@ -104,7 +108,7 @@ namespace OpenSim.Framework
|
||||
string data = null;
|
||||
lock (other)
|
||||
{
|
||||
if (other.Count > 0)
|
||||
if (other.CountNamespaces > 0)
|
||||
{
|
||||
data = OSDParser.SerializeLLSDXmlString(other.m_map);
|
||||
}
|
||||
@@ -120,59 +124,132 @@ namespace OpenSim.Framework
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of data stores.
|
||||
/// Sanitise the map to remove any namespaces or stores that are not OSDMap.
|
||||
/// </summary>
|
||||
public int Count { get { lock (this) { return m_map.Count; } } }
|
||||
|
||||
public bool IsReadOnly { get { return false; } }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the names of the data stores.
|
||||
/// </summary>
|
||||
public ICollection<string> Keys { get { lock (this) { return m_map.Keys; } } }
|
||||
|
||||
/// <summary>
|
||||
/// Returns all the data stores.
|
||||
/// </summary>
|
||||
public ICollection<OSDMap> Values
|
||||
/// <param name='map'>
|
||||
/// </param>
|
||||
public static void SanitiseMap(DAMap daMap)
|
||||
{
|
||||
get
|
||||
List<string> keysToRemove = null;
|
||||
|
||||
OSDMap namespacesMap = daMap.m_map;
|
||||
|
||||
foreach (string key in namespacesMap.Keys)
|
||||
{
|
||||
lock (this)
|
||||
// Console.WriteLine("Processing ns {0}", key);
|
||||
if (!(namespacesMap[key] is OSDMap))
|
||||
{
|
||||
List<OSDMap> stores = new List<OSDMap>(m_map.Count);
|
||||
foreach (OSD llsd in m_map.Values)
|
||||
stores.Add((OSDMap)llsd);
|
||||
return stores;
|
||||
if (keysToRemove == null)
|
||||
keysToRemove = new List<string>();
|
||||
|
||||
keysToRemove.Add(key);
|
||||
}
|
||||
}
|
||||
|
||||
if (keysToRemove != null)
|
||||
{
|
||||
foreach (string key in keysToRemove)
|
||||
{
|
||||
// Console.WriteLine ("Removing bad ns {0}", key);
|
||||
namespacesMap.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (OSD nsOsd in namespacesMap.Values)
|
||||
{
|
||||
OSDMap nsOsdMap = (OSDMap)nsOsd;
|
||||
keysToRemove = null;
|
||||
|
||||
foreach (string key in nsOsdMap.Keys)
|
||||
{
|
||||
if (!(nsOsdMap[key] is OSDMap))
|
||||
{
|
||||
if (keysToRemove == null)
|
||||
keysToRemove = new List<string>();
|
||||
|
||||
keysToRemove.Add(key);
|
||||
}
|
||||
}
|
||||
|
||||
if (keysToRemove != null)
|
||||
foreach (string key in keysToRemove)
|
||||
nsOsdMap.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets one data store.
|
||||
/// Get the number of namespaces
|
||||
/// </summary>
|
||||
/// <param name="key">Store name</param>
|
||||
/// <returns></returns>
|
||||
public OSDMap this[string key]
|
||||
{
|
||||
get
|
||||
{
|
||||
OSD llsd;
|
||||
|
||||
public int CountNamespaces { get { lock (this) { return m_map.Count; } } }
|
||||
|
||||
/// <summary>
|
||||
/// Get the number of stores.
|
||||
/// </summary>
|
||||
public int CountStores
|
||||
{
|
||||
get
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
lock (this)
|
||||
{
|
||||
if (m_map.TryGetValue(key, out llsd))
|
||||
return (OSDMap)llsd;
|
||||
else
|
||||
return null;
|
||||
foreach (OSD osdNamespace in m_map)
|
||||
{
|
||||
count += ((OSDMap)osdNamespace).Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve a Dynamic Attribute store
|
||||
/// </summary>
|
||||
/// <param name="ns">namespace for the store - use "OpenSim" for in-core modules</param>
|
||||
/// <param name="storeName">name of the store within the namespace</param>
|
||||
/// <returns>an OSDMap representing the stored data, or null if not found</returns>
|
||||
public OSDMap GetStore(string ns, string storeName)
|
||||
{
|
||||
OSD namespaceOsd;
|
||||
|
||||
lock (this)
|
||||
{
|
||||
ValidateKey(key);
|
||||
lock (this)
|
||||
m_map[key] = value;
|
||||
if (m_map.TryGetValue(ns, out namespaceOsd))
|
||||
{
|
||||
OSD store;
|
||||
|
||||
if (((OSDMap)namespaceOsd).TryGetValue(storeName, out store))
|
||||
return (OSDMap)store;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves a Dynamic attribute store
|
||||
/// </summary>
|
||||
/// <param name="ns">namespace for the store - use "OpenSim" for in-core modules</param>
|
||||
/// <param name="storeName">name of the store within the namespace</param>
|
||||
/// <param name="store">an OSDMap representing the data to store</param>
|
||||
public void SetStore(string ns, string storeName, OSDMap store)
|
||||
{
|
||||
ValidateNamespace(ns);
|
||||
OSDMap nsMap;
|
||||
|
||||
lock (this)
|
||||
{
|
||||
if (!m_map.ContainsKey(ns))
|
||||
{
|
||||
nsMap = new OSDMap();
|
||||
m_map[ns] = nsMap;
|
||||
}
|
||||
|
||||
nsMap = (OSDMap)m_map[ns];
|
||||
|
||||
// m_log.DebugFormat("[DA MAP]: Setting store to {0}:{1}", ns, storeName);
|
||||
nsMap[storeName] = store;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,54 +257,46 @@ namespace OpenSim.Framework
|
||||
/// Validate the key used for storing separate data stores.
|
||||
/// </summary>
|
||||
/// <param name='key'></param>
|
||||
public static void ValidateKey(string key)
|
||||
public static void ValidateNamespace(string ns)
|
||||
{
|
||||
if (key.Length < MIN_STORE_NAME_LENGTH)
|
||||
throw new Exception("Minimum store name length is " + MIN_STORE_NAME_LENGTH);
|
||||
if (ns.Length < MIN_NAMESPACE_LENGTH)
|
||||
throw new Exception("Minimum namespace length is " + MIN_NAMESPACE_LENGTH);
|
||||
}
|
||||
|
||||
public bool ContainsKey(string key)
|
||||
public bool ContainsStore(string ns, string storeName)
|
||||
{
|
||||
lock (this)
|
||||
return m_map.ContainsKey(key);
|
||||
}
|
||||
OSD namespaceOsd;
|
||||
|
||||
public void Add(string key, OSDMap store)
|
||||
{
|
||||
ValidateKey(key);
|
||||
lock (this)
|
||||
m_map.Add(key, store);
|
||||
}
|
||||
|
||||
public void Add(KeyValuePair<string, OSDMap> kvp)
|
||||
{
|
||||
ValidateKey(kvp.Key);
|
||||
lock (this)
|
||||
m_map.Add(kvp.Key, kvp.Value);
|
||||
}
|
||||
|
||||
public bool Remove(string key)
|
||||
{
|
||||
lock (this)
|
||||
return m_map.Remove(key);
|
||||
}
|
||||
|
||||
public bool TryGetValue(string key, out OSDMap store)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
OSD llsd;
|
||||
if (m_map.TryGetValue(key, out llsd))
|
||||
if (m_map.TryGetValue(ns, out namespaceOsd))
|
||||
{
|
||||
store = (OSDMap)llsd;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
store = null;
|
||||
return false;
|
||||
return ((OSDMap)namespaceOsd).ContainsKey(storeName);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryGetStore(string ns, string storeName, out OSDMap store)
|
||||
{
|
||||
OSD namespaceOsd;
|
||||
|
||||
lock (this)
|
||||
{
|
||||
if (m_map.TryGetValue(ns, out namespaceOsd))
|
||||
{
|
||||
OSD storeOsd;
|
||||
|
||||
bool result = ((OSDMap)namespaceOsd).TryGetValue(storeName, out storeOsd);
|
||||
store = (OSDMap)storeOsd;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
store = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
@@ -235,39 +304,25 @@ namespace OpenSim.Framework
|
||||
lock (this)
|
||||
m_map.Clear();
|
||||
}
|
||||
|
||||
public bool Contains(KeyValuePair<string, OSDMap> kvp)
|
||||
|
||||
public bool RemoveStore(string ns, string storeName)
|
||||
{
|
||||
OSD namespaceOsd;
|
||||
|
||||
lock (this)
|
||||
return m_map.ContainsKey(kvp.Key);
|
||||
}
|
||||
{
|
||||
if (m_map.TryGetValue(ns, out namespaceOsd))
|
||||
{
|
||||
OSDMap namespaceOsdMap = (OSDMap)namespaceOsd;
|
||||
namespaceOsdMap.Remove(storeName);
|
||||
|
||||
public void CopyTo(KeyValuePair<string, OSDMap>[] array, int index)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
// Don't keep empty namespaces around
|
||||
if (namespaceOsdMap.Count <= 0)
|
||||
m_map.Remove(ns);
|
||||
}
|
||||
}
|
||||
|
||||
public bool Remove(KeyValuePair<string, OSDMap> kvp)
|
||||
{
|
||||
lock (this)
|
||||
return m_map.Remove(kvp.Key);
|
||||
}
|
||||
|
||||
public System.Collections.IDictionaryEnumerator GetEnumerator()
|
||||
{
|
||||
lock (this)
|
||||
return m_map.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator<KeyValuePair<string, OSDMap>> IEnumerable<KeyValuePair<string, OSDMap>>.GetEnumerator()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
lock (this)
|
||||
return m_map.GetEnumerator();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,22 +42,22 @@ namespace OpenSim.Framework
|
||||
/// This class stores and retrieves dynamic objects.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Experimental - DO NOT USE.
|
||||
/// Experimental - DO NOT USE. Does not yet have namespace support.
|
||||
/// </remarks>
|
||||
public class DOMap
|
||||
{
|
||||
private IDictionary<string, object> m_map;
|
||||
|
||||
public void Add(string key, object dynObj)
|
||||
public void Add(string ns, string objName, object dynObj)
|
||||
{
|
||||
DAMap.ValidateKey(key);
|
||||
DAMap.ValidateNamespace(ns);
|
||||
|
||||
lock (this)
|
||||
{
|
||||
if (m_map == null)
|
||||
m_map = new Dictionary<string, object>();
|
||||
|
||||
m_map.Add(key, dynObj);
|
||||
m_map.Add(objName, dynObj);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,30 @@ namespace OpenSim.Framework
|
||||
set { m_EstateName = value; }
|
||||
}
|
||||
|
||||
private bool m_AllowLandmark = true;
|
||||
|
||||
public bool AllowLandmark
|
||||
{
|
||||
get { return m_AllowLandmark; }
|
||||
set { m_AllowLandmark = value; }
|
||||
}
|
||||
|
||||
private bool m_AllowParcelChanges = true;
|
||||
|
||||
public bool AllowParcelChanges
|
||||
{
|
||||
get { return m_AllowParcelChanges; }
|
||||
set { m_AllowParcelChanges = value; }
|
||||
}
|
||||
|
||||
private bool m_AllowSetHome = true;
|
||||
|
||||
public bool AllowSetHome
|
||||
{
|
||||
get { return m_AllowSetHome; }
|
||||
set { m_AllowSetHome = value; }
|
||||
}
|
||||
|
||||
private uint m_ParentEstateID = 1;
|
||||
|
||||
public uint ParentEstateID
|
||||
@@ -374,10 +398,18 @@ namespace OpenSim.Framework
|
||||
return l_EstateAccess.Contains(user);
|
||||
}
|
||||
|
||||
public void SetFromFlags(ulong regionFlags)
|
||||
{
|
||||
ResetHomeOnTeleport = ((regionFlags & (ulong)OpenMetaverse.RegionFlags.ResetHomeOnTeleport) == (ulong)OpenMetaverse.RegionFlags.ResetHomeOnTeleport);
|
||||
BlockDwell = ((regionFlags & (ulong)OpenMetaverse.RegionFlags.BlockDwell) == (ulong)OpenMetaverse.RegionFlags.BlockDwell);
|
||||
AllowLandmark = ((regionFlags & (ulong)OpenMetaverse.RegionFlags.AllowLandmark) == (ulong)OpenMetaverse.RegionFlags.AllowLandmark);
|
||||
AllowParcelChanges = ((regionFlags & (ulong)OpenMetaverse.RegionFlags.AllowParcelChanges) == (ulong)OpenMetaverse.RegionFlags.AllowParcelChanges);
|
||||
AllowSetHome = ((regionFlags & (ulong)OpenMetaverse.RegionFlags.AllowSetHome) == (ulong)OpenMetaverse.RegionFlags.AllowSetHome);
|
||||
}
|
||||
|
||||
public bool GroupAccess(UUID groupID)
|
||||
{
|
||||
return l_EstateGroups.Contains(groupID);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,24 @@ namespace OpenSim.Framework
|
||||
binaryBucket = new byte[0];
|
||||
}
|
||||
|
||||
public GridInstantMessage(GridInstantMessage im, bool addTimestamp)
|
||||
{
|
||||
fromAgentID = im.fromAgentID;
|
||||
fromAgentName = im.fromAgentName;
|
||||
toAgentID = im.toAgentID;
|
||||
dialog = im.dialog;
|
||||
fromGroup = im.fromGroup;
|
||||
message = im.message;
|
||||
imSessionID = im.imSessionID;
|
||||
offline = im.offline;
|
||||
Position = im.Position;
|
||||
binaryBucket = im.binaryBucket;
|
||||
RegionID = im.RegionID;
|
||||
|
||||
if (addTimestamp)
|
||||
timestamp = (uint)Util.UnixTimeSinceEpoch();
|
||||
}
|
||||
|
||||
public GridInstantMessage(IScene scene, UUID _fromAgentID,
|
||||
string _fromAgentName, UUID _toAgentID,
|
||||
byte _dialog, bool _fromGroup, string _message,
|
||||
|
||||
@@ -64,7 +64,9 @@ namespace OpenSim.Framework
|
||||
|
||||
public delegate void NetworkStats(int inPackets, int outPackets, int unAckedBytes);
|
||||
|
||||
public delegate void SetAppearance(IClientAPI remoteClient, Primitive.TextureEntry textureEntry, byte[] visualParams);
|
||||
public delegate void CachedTextureRequest(IClientAPI remoteClient, int serial, List<CachedTextureRequestArg> cachedTextureRequest);
|
||||
|
||||
public delegate void SetAppearance(IClientAPI remoteClient, Primitive.TextureEntry textureEntry, byte[] visualParams, List<CachedTextureRequestArg> cachedTextureData);
|
||||
|
||||
public delegate void StartAnim(IClientAPI remoteClient, UUID animID);
|
||||
|
||||
@@ -313,7 +315,7 @@ namespace OpenSim.Framework
|
||||
public delegate void ObjectPermissions(
|
||||
IClientAPI controller, UUID agentID, UUID sessionID, byte field, uint localId, uint mask, byte set);
|
||||
|
||||
public delegate void EconomyDataRequest(UUID agentID);
|
||||
public delegate void EconomyDataRequest(IClientAPI client);
|
||||
|
||||
public delegate void ObjectIncludeInSearch(IClientAPI remoteClient, bool IncludeInSearch, uint localID);
|
||||
|
||||
@@ -780,6 +782,7 @@ namespace OpenSim.Framework
|
||||
event EstateChangeInfo OnEstateChangeInfo;
|
||||
event EstateManageTelehub OnEstateManageTelehub;
|
||||
// [Obsolete("LLClientView Specific.")]
|
||||
event CachedTextureRequest OnCachedTextureRequest;
|
||||
event SetAppearance OnSetAppearance;
|
||||
// [Obsolete("LLClientView Specific - Replace and rename OnAvatarUpdate. Difference from SetAppearance?")]
|
||||
event AvatarNowWearing OnAvatarNowWearing;
|
||||
@@ -822,6 +825,8 @@ namespace OpenSim.Framework
|
||||
/// </remarks>
|
||||
event UpdateAgent OnAgentUpdate;
|
||||
|
||||
event UpdateAgent OnAgentCameraUpdate;
|
||||
|
||||
event AgentRequestSit OnAgentRequestSit;
|
||||
event AgentSit OnAgentSit;
|
||||
event AvatarPickerRequest OnAvatarPickerRequest;
|
||||
@@ -1087,14 +1092,15 @@ namespace OpenSim.Framework
|
||||
/// <param name="textureEntry"></param>
|
||||
void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry);
|
||||
|
||||
void SendCachedTextureResponse(ISceneEntity avatar, int serial, List<CachedTextureResponseArg> cachedTextures);
|
||||
|
||||
void SendStartPingCheck(byte seq);
|
||||
|
||||
/// <summary>
|
||||
/// Tell the client that an object has been deleted
|
||||
/// </summary>
|
||||
/// <param name="regionHandle"></param>
|
||||
/// <param name="localID"></param>
|
||||
void SendKillObject(ulong regionHandle, List<uint> localID);
|
||||
void SendKillObject(List<uint> localID);
|
||||
|
||||
void SendAnimations(UUID[] animID, int[] seqs, UUID sourceAgentId, UUID[] objectIDs);
|
||||
void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args);
|
||||
@@ -1116,8 +1122,8 @@ namespace OpenSim.Framework
|
||||
|
||||
void SendInstantMessage(GridInstantMessage im);
|
||||
|
||||
void SendGenericMessage(string method, List<string> message);
|
||||
void SendGenericMessage(string method, List<byte[]> message);
|
||||
void SendGenericMessage(string method, UUID invoice, List<string> message);
|
||||
void SendGenericMessage(string method, UUID invoice, List<byte[]> message);
|
||||
|
||||
void SendLayerData(float[] map);
|
||||
void SendLayerData(int px, int py, float[] map);
|
||||
@@ -1155,7 +1161,8 @@ namespace OpenSim.Framework
|
||||
void SendTeleportStart(uint flags);
|
||||
void SendTeleportProgress(uint flags, string message);
|
||||
|
||||
void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance);
|
||||
void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance, int transactionType, UUID sourceID, bool sourceIsGroup, UUID destID, bool destIsGroup, int amount, string item);
|
||||
|
||||
void SendPayPrice(UUID objectID, int[] payPrice);
|
||||
|
||||
void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations);
|
||||
@@ -1250,8 +1257,6 @@ namespace OpenSim.Framework
|
||||
void SendDialog(string objectname, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch,
|
||||
string[] buttonlabels);
|
||||
|
||||
bool AddMoney(int debit);
|
||||
|
||||
/// <summary>
|
||||
/// Update the client as to where the sun is currently located.
|
||||
/// </summary>
|
||||
@@ -1471,7 +1476,7 @@ namespace OpenSim.Framework
|
||||
void SendChangeUserRights(UUID agentID, UUID friendID, int rights);
|
||||
void SendTextBoxRequest(string message, int chatChannel, string objectname, UUID ownerID, string ownerFirstName, string ownerLastName, UUID objectId);
|
||||
|
||||
void StopFlying(ISceneEntity presence);
|
||||
void SendAgentTerseUpdate(ISceneEntity presence);
|
||||
|
||||
void SendPlacesReply(UUID queryID, UUID transactionID, PlacesReplyData[] data);
|
||||
}
|
||||
|
||||
@@ -38,7 +38,8 @@ namespace OpenSim.Framework
|
||||
int GetBalance(UUID agentID);
|
||||
bool UploadCovered(UUID agentID, int amount);
|
||||
bool AmountCovered(UUID agentID, int amount);
|
||||
void ApplyCharge(UUID agentID, int amount, string text);
|
||||
void ApplyCharge(UUID agentID, int amount, MoneyTransactionType type);
|
||||
void ApplyCharge(UUID agentID, int amount, MoneyTransactionType type, string extraData);
|
||||
void ApplyUploadCharge(UUID agentID, int amount, string text);
|
||||
|
||||
int UploadCharge { get; }
|
||||
|
||||
47
OpenSim/Framework/IPeople.cs
Normal file
47
OpenSim/Framework/IPeople.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* 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 the OpenSimulator Project 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 DEVELOPERS ``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 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Framework
|
||||
{
|
||||
public class UserData
|
||||
{
|
||||
public UUID Id { get; set; }
|
||||
public string FirstName { get; set; }
|
||||
public string LastName { get; set; }
|
||||
public string HomeURL { get; set; }
|
||||
public Dictionary<string, object> ServerURLs { get; set; }
|
||||
}
|
||||
|
||||
public interface IPeople
|
||||
{
|
||||
List<UserData> GetUserData(string query, int page_size, int page_number);
|
||||
}
|
||||
}
|
||||
@@ -136,5 +136,10 @@ namespace OpenSim.Framework
|
||||
ISceneObject DeserializeObject(string representation);
|
||||
|
||||
bool CheckClient(UUID agentID, System.Net.IPEndPoint ep);
|
||||
|
||||
/// <summary>
|
||||
/// Start the scene and associated scripts within it.
|
||||
/// </summary>
|
||||
void Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,10 +33,10 @@ namespace OpenSim.Framework
|
||||
[Serializable]
|
||||
public class Location : ICloneable
|
||||
{
|
||||
private readonly int m_x;
|
||||
private readonly int m_y;
|
||||
private readonly uint m_x;
|
||||
private readonly uint m_y;
|
||||
|
||||
public Location(int x, int y)
|
||||
public Location(uint x, uint y)
|
||||
{
|
||||
m_x = x;
|
||||
m_y = y;
|
||||
@@ -44,21 +44,21 @@ namespace OpenSim.Framework
|
||||
|
||||
public Location(ulong regionHandle)
|
||||
{
|
||||
m_x = (int) regionHandle;
|
||||
m_y = (int) (regionHandle >> 32);
|
||||
m_x = (uint)(regionHandle >> 32);
|
||||
m_y = (uint)(regionHandle & (ulong)uint.MaxValue);
|
||||
}
|
||||
|
||||
public ulong RegionHandle
|
||||
{
|
||||
get { return Utils.UIntsToLong((uint)m_x, (uint)m_y); }
|
||||
get { return Utils.UIntsToLong(m_x, m_y); }
|
||||
}
|
||||
|
||||
public int X
|
||||
public uint X
|
||||
{
|
||||
get { return m_x; }
|
||||
}
|
||||
|
||||
public int Y
|
||||
public uint Y
|
||||
{
|
||||
get { return m_y; }
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
@@ -45,16 +45,16 @@ namespace OpenSim.Framework.Monitoring
|
||||
sb.Append(Environment.NewLine);
|
||||
|
||||
sb.AppendFormat(
|
||||
"Allocated to OpenSim objects: {0} MB\n",
|
||||
"Heap allocated to OpenSim : {0} MB\n",
|
||||
Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0));
|
||||
|
||||
sb.AppendFormat(
|
||||
"OpenSim last object memory churn : {0} MB/s\n",
|
||||
Math.Round((MemoryWatchdog.LastMemoryChurn * 1000) / 1024.0 / 1024, 3));
|
||||
"Last heap allocation rate : {0} MB/s\n",
|
||||
Math.Round((MemoryWatchdog.LastHeapAllocationRate * 1000) / 1024.0 / 1024, 3));
|
||||
|
||||
sb.AppendFormat(
|
||||
"OpenSim average object memory churn : {0} MB/s\n",
|
||||
Math.Round((MemoryWatchdog.AverageMemoryChurn * 1000) / 1024.0 / 1024, 3));
|
||||
"Average heap allocation rate: {0} MB/s\n",
|
||||
Math.Round((MemoryWatchdog.AverageHeapAllocationRate * 1000) / 1024.0 / 1024, 3));
|
||||
|
||||
sb.AppendFormat(
|
||||
"Process memory : {0} MB\n",
|
||||
|
||||
118
OpenSim/Framework/Monitoring/Checks/Check.cs
Normal file
118
OpenSim/Framework/Monitoring/Checks/Check.cs
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* 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 the OpenSimulator Project 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 DEVELOPERS ``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 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace OpenSim.Framework.Monitoring
|
||||
{
|
||||
public class Check
|
||||
{
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
public static readonly char[] DisallowedShortNameCharacters = { '.' };
|
||||
|
||||
/// <summary>
|
||||
/// Category of this stat (e.g. cache, scene, etc).
|
||||
/// </summary>
|
||||
public string Category { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Containing name for this stat.
|
||||
/// FIXME: In the case of a scene, this is currently the scene name (though this leaves
|
||||
/// us with a to-be-resolved problem of non-unique region names).
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The container.
|
||||
/// </value>
|
||||
public string Container { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Action used to check whether alert should go off.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Should return true if check passes. False otherwise.
|
||||
/// </remarks>
|
||||
public Func<Check, bool> CheckFunc { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Message from the last failure, if any. If there is no message or no failure then will be null.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Should be set by the CheckFunc when applicable.
|
||||
/// </remarks>
|
||||
public string LastFailureMessage { get; set; }
|
||||
|
||||
public StatVerbosity Verbosity { get; private set; }
|
||||
public string ShortName { get; private set; }
|
||||
public string Name { get; private set; }
|
||||
public string Description { get; private set; }
|
||||
|
||||
public Check(
|
||||
string shortName,
|
||||
string name,
|
||||
string description,
|
||||
string category,
|
||||
string container,
|
||||
Func<Check, bool> checkFunc,
|
||||
StatVerbosity verbosity)
|
||||
{
|
||||
if (ChecksManager.SubCommands.Contains(category))
|
||||
throw new Exception(
|
||||
string.Format("Alert cannot be in category '{0}' since this is reserved for a subcommand", category));
|
||||
|
||||
foreach (char c in DisallowedShortNameCharacters)
|
||||
{
|
||||
if (shortName.IndexOf(c) != -1)
|
||||
throw new Exception(string.Format("Alert name {0} cannot contain character {1}", shortName, c));
|
||||
}
|
||||
|
||||
ShortName = shortName;
|
||||
Name = name;
|
||||
Description = description;
|
||||
Category = category;
|
||||
Container = container;
|
||||
CheckFunc = checkFunc;
|
||||
Verbosity = verbosity;
|
||||
}
|
||||
|
||||
public bool CheckIt()
|
||||
{
|
||||
return CheckFunc(this);
|
||||
}
|
||||
|
||||
public virtual string ToConsoleString()
|
||||
{
|
||||
return string.Format(
|
||||
"{0}.{1}.{2} - {3}",
|
||||
Category,
|
||||
Container,
|
||||
ShortName,
|
||||
Description);
|
||||
}
|
||||
}
|
||||
}
|
||||
262
OpenSim/Framework/Monitoring/ChecksManager.cs
Normal file
262
OpenSim/Framework/Monitoring/ChecksManager.cs
Normal file
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* 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 the OpenSimulator Project 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 DEVELOPERS ``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 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using log4net;
|
||||
|
||||
namespace OpenSim.Framework.Monitoring
|
||||
{
|
||||
/// <summary>
|
||||
/// Static class used to register/deregister checks on runtime conditions.
|
||||
/// </summary>
|
||||
public static class ChecksManager
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
// Subcommand used to list other stats.
|
||||
public const string ListSubCommand = "list";
|
||||
|
||||
// All subcommands
|
||||
public static HashSet<string> SubCommands = new HashSet<string> { ListSubCommand };
|
||||
|
||||
/// <summary>
|
||||
/// Checks categorized by category/container/shortname
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Do not add or remove directly from this dictionary.
|
||||
/// </remarks>
|
||||
public static SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Check>>> RegisteredChecks
|
||||
= new SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Check>>>();
|
||||
|
||||
public static void RegisterConsoleCommands(ICommandConsole console)
|
||||
{
|
||||
console.Commands.AddCommand(
|
||||
"General",
|
||||
false,
|
||||
"show checks",
|
||||
"show checks",
|
||||
"Show checks configured for this server",
|
||||
"If no argument is specified then info on all checks will be shown.\n"
|
||||
+ "'list' argument will show check categories.\n"
|
||||
+ "THIS FACILITY IS EXPERIMENTAL",
|
||||
HandleShowchecksCommand);
|
||||
}
|
||||
|
||||
public static void HandleShowchecksCommand(string module, string[] cmd)
|
||||
{
|
||||
ICommandConsole con = MainConsole.Instance;
|
||||
|
||||
if (cmd.Length > 2)
|
||||
{
|
||||
foreach (string name in cmd.Skip(2))
|
||||
{
|
||||
string[] components = name.Split('.');
|
||||
|
||||
string categoryName = components[0];
|
||||
// string containerName = components.Length > 1 ? components[1] : null;
|
||||
|
||||
if (categoryName == ListSubCommand)
|
||||
{
|
||||
con.Output("check categories available are:");
|
||||
|
||||
foreach (string category in RegisteredChecks.Keys)
|
||||
con.OutputFormat(" {0}", category);
|
||||
}
|
||||
// else
|
||||
// {
|
||||
// SortedDictionary<string, SortedDictionary<string, Check>> category;
|
||||
// if (!Registeredchecks.TryGetValue(categoryName, out category))
|
||||
// {
|
||||
// con.OutputFormat("No such category as {0}", categoryName);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if (String.IsNullOrEmpty(containerName))
|
||||
// {
|
||||
// OutputConfiguredToConsole(con, category);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// SortedDictionary<string, Check> container;
|
||||
// if (category.TryGetValue(containerName, out container))
|
||||
// {
|
||||
// OutputContainerChecksToConsole(con, container);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// con.OutputFormat("No such container {0} in category {1}", containerName, categoryName);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
OutputAllChecksToConsole(con);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a statistic.
|
||||
/// </summary>
|
||||
/// <param name='stat'></param>
|
||||
/// <returns></returns>
|
||||
public static bool RegisterCheck(Check check)
|
||||
{
|
||||
SortedDictionary<string, SortedDictionary<string, Check>> category = null, newCategory;
|
||||
SortedDictionary<string, Check> container = null, newContainer;
|
||||
|
||||
lock (RegisteredChecks)
|
||||
{
|
||||
// Check name is not unique across category/container/shortname key.
|
||||
// XXX: For now just return false. This is to avoid problems in regression tests where all tests
|
||||
// in a class are run in the same instance of the VM.
|
||||
if (TryGetCheckParents(check, out category, out container))
|
||||
return false;
|
||||
|
||||
// We take a copy-on-write approach here of replacing dictionaries when keys are added or removed.
|
||||
// This means that we don't need to lock or copy them on iteration, which will be a much more
|
||||
// common operation after startup.
|
||||
if (container != null)
|
||||
newContainer = new SortedDictionary<string, Check>(container);
|
||||
else
|
||||
newContainer = new SortedDictionary<string, Check>();
|
||||
|
||||
if (category != null)
|
||||
newCategory = new SortedDictionary<string, SortedDictionary<string, Check>>(category);
|
||||
else
|
||||
newCategory = new SortedDictionary<string, SortedDictionary<string, Check>>();
|
||||
|
||||
newContainer[check.ShortName] = check;
|
||||
newCategory[check.Container] = newContainer;
|
||||
RegisteredChecks[check.Category] = newCategory;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deregister an check
|
||||
/// </summary>>
|
||||
/// <param name='stat'></param>
|
||||
/// <returns></returns>
|
||||
public static bool DeregisterCheck(Check check)
|
||||
{
|
||||
SortedDictionary<string, SortedDictionary<string, Check>> category = null, newCategory;
|
||||
SortedDictionary<string, Check> container = null, newContainer;
|
||||
|
||||
lock (RegisteredChecks)
|
||||
{
|
||||
if (!TryGetCheckParents(check, out category, out container))
|
||||
return false;
|
||||
|
||||
newContainer = new SortedDictionary<string, Check>(container);
|
||||
newContainer.Remove(check.ShortName);
|
||||
|
||||
newCategory = new SortedDictionary<string, SortedDictionary<string, Check>>(category);
|
||||
newCategory.Remove(check.Container);
|
||||
|
||||
newCategory[check.Container] = newContainer;
|
||||
RegisteredChecks[check.Category] = newCategory;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool TryGetCheckParents(
|
||||
Check check,
|
||||
out SortedDictionary<string, SortedDictionary<string, Check>> category,
|
||||
out SortedDictionary<string, Check> container)
|
||||
{
|
||||
category = null;
|
||||
container = null;
|
||||
|
||||
lock (RegisteredChecks)
|
||||
{
|
||||
if (RegisteredChecks.TryGetValue(check.Category, out category))
|
||||
{
|
||||
if (category.TryGetValue(check.Container, out container))
|
||||
{
|
||||
if (container.ContainsKey(check.ShortName))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void CheckChecks()
|
||||
{
|
||||
lock (RegisteredChecks)
|
||||
{
|
||||
foreach (SortedDictionary<string, SortedDictionary<string, Check>> category in RegisteredChecks.Values)
|
||||
{
|
||||
foreach (SortedDictionary<string, Check> container in category.Values)
|
||||
{
|
||||
foreach (Check check in container.Values)
|
||||
{
|
||||
if (!check.CheckIt())
|
||||
m_log.WarnFormat(
|
||||
"[CHECKS MANAGER]: Check {0}.{1}.{2} failed with message {3}", check.Category, check.Container, check.ShortName, check.LastFailureMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void OutputAllChecksToConsole(ICommandConsole con)
|
||||
{
|
||||
foreach (var category in RegisteredChecks.Values)
|
||||
{
|
||||
OutputCategoryChecksToConsole(con, category);
|
||||
}
|
||||
}
|
||||
|
||||
private static void OutputCategoryChecksToConsole(
|
||||
ICommandConsole con, SortedDictionary<string, SortedDictionary<string, Check>> category)
|
||||
{
|
||||
foreach (var container in category.Values)
|
||||
{
|
||||
OutputContainerChecksToConsole(con, container);
|
||||
}
|
||||
}
|
||||
|
||||
private static void OutputContainerChecksToConsole(ICommandConsole con, SortedDictionary<string, Check> container)
|
||||
{
|
||||
foreach (Check check in container.Values)
|
||||
{
|
||||
con.Output(check.ToConsoleString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -60,17 +60,17 @@ namespace OpenSim.Framework.Monitoring
|
||||
private static bool m_enabled;
|
||||
|
||||
/// <summary>
|
||||
/// Last memory churn in bytes per millisecond.
|
||||
/// Average heap allocation rate in bytes per millisecond.
|
||||
/// </summary>
|
||||
public static double AverageMemoryChurn
|
||||
public static double AverageHeapAllocationRate
|
||||
{
|
||||
get { if (m_samples.Count > 0) return m_samples.Average(); else return 0; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Average memory churn in bytes per millisecond.
|
||||
/// Last heap allocation in bytes
|
||||
/// </summary>
|
||||
public static double LastMemoryChurn
|
||||
public static double LastHeapAllocationRate
|
||||
{
|
||||
get { if (m_samples.Count > 0) return m_samples.Last(); else return 0; }
|
||||
}
|
||||
|
||||
349
OpenSim/Framework/Monitoring/ServerStatsCollector.cs
Normal file
349
OpenSim/Framework/Monitoring/ServerStatsCollector.cs
Normal file
@@ -0,0 +1,349 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* 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 the OpenSimulator Project 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 DEVELOPERS ``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 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using log4net;
|
||||
using Nini.Config;
|
||||
using OpenMetaverse.StructuredData;
|
||||
using OpenSim.Framework;
|
||||
|
||||
namespace OpenSim.Framework.Monitoring
|
||||
{
|
||||
public class ServerStatsCollector
|
||||
{
|
||||
private readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private readonly string LogHeader = "[SERVER STATS]";
|
||||
|
||||
public bool Enabled = false;
|
||||
private static Dictionary<string, Stat> RegisteredStats = new Dictionary<string, Stat>();
|
||||
|
||||
public readonly string CategoryServer = "server";
|
||||
|
||||
public readonly string ContainerThreadpool = "threadpool";
|
||||
public readonly string ContainerProcessor = "processor";
|
||||
public readonly string ContainerMemory = "memory";
|
||||
public readonly string ContainerNetwork = "network";
|
||||
public readonly string ContainerProcess = "process";
|
||||
|
||||
public string NetworkInterfaceTypes = "Ethernet";
|
||||
|
||||
readonly int performanceCounterSampleInterval = 500;
|
||||
// int lastperformanceCounterSampleTime = 0;
|
||||
|
||||
private class PerfCounterControl
|
||||
{
|
||||
public PerformanceCounter perfCounter;
|
||||
public int lastFetch;
|
||||
public string name;
|
||||
public PerfCounterControl(PerformanceCounter pPc)
|
||||
: this(pPc, String.Empty)
|
||||
{
|
||||
}
|
||||
public PerfCounterControl(PerformanceCounter pPc, string pName)
|
||||
{
|
||||
perfCounter = pPc;
|
||||
lastFetch = 0;
|
||||
name = pName;
|
||||
}
|
||||
}
|
||||
|
||||
PerfCounterControl processorPercentPerfCounter = null;
|
||||
|
||||
// IRegionModuleBase.Initialize
|
||||
public void Initialise(IConfigSource source)
|
||||
{
|
||||
IConfig cfg = source.Configs["Monitoring"];
|
||||
|
||||
if (cfg != null)
|
||||
Enabled = cfg.GetBoolean("ServerStatsEnabled", true);
|
||||
|
||||
if (Enabled)
|
||||
{
|
||||
NetworkInterfaceTypes = cfg.GetString("NetworkInterfaceTypes", "Ethernet");
|
||||
}
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
if (RegisteredStats.Count == 0)
|
||||
RegisterServerStats();
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
if (RegisteredStats.Count > 0)
|
||||
{
|
||||
foreach (Stat stat in RegisteredStats.Values)
|
||||
{
|
||||
StatsManager.DeregisterStat(stat);
|
||||
stat.Dispose();
|
||||
}
|
||||
RegisteredStats.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private void MakeStat(string pName, string pDesc, string pUnit, string pContainer, Action<Stat> act)
|
||||
{
|
||||
MakeStat(pName, pDesc, pUnit, pContainer, act, MeasuresOfInterest.None);
|
||||
}
|
||||
|
||||
private void MakeStat(string pName, string pDesc, string pUnit, string pContainer, Action<Stat> act, MeasuresOfInterest moi)
|
||||
{
|
||||
string desc = pDesc;
|
||||
if (desc == null)
|
||||
desc = pName;
|
||||
Stat stat = new Stat(pName, pName, desc, pUnit, CategoryServer, pContainer, StatType.Pull, moi, act, StatVerbosity.Debug);
|
||||
StatsManager.RegisterStat(stat);
|
||||
RegisteredStats.Add(pName, stat);
|
||||
}
|
||||
|
||||
public void RegisterServerStats()
|
||||
{
|
||||
// lastperformanceCounterSampleTime = Util.EnvironmentTickCount();
|
||||
PerformanceCounter tempPC;
|
||||
Stat tempStat;
|
||||
string tempName;
|
||||
|
||||
try
|
||||
{
|
||||
tempName = "CPUPercent";
|
||||
tempPC = new PerformanceCounter("Processor", "% Processor Time", "_Total");
|
||||
processorPercentPerfCounter = new PerfCounterControl(tempPC);
|
||||
// A long time bug in mono is that CPU percent is reported as CPU percent idle. Windows reports CPU percent busy.
|
||||
tempStat = new Stat(tempName, tempName, "", "percent", CategoryServer, ContainerProcessor,
|
||||
StatType.Pull, (s) => { GetNextValue(s, processorPercentPerfCounter, Util.IsWindows() ? 1 : -1); },
|
||||
StatVerbosity.Info);
|
||||
StatsManager.RegisterStat(tempStat);
|
||||
RegisteredStats.Add(tempName, tempStat);
|
||||
|
||||
MakeStat("TotalProcessorTime", null, "sec", ContainerProcessor,
|
||||
(s) => { s.Value = Process.GetCurrentProcess().TotalProcessorTime.TotalSeconds; });
|
||||
|
||||
MakeStat("UserProcessorTime", null, "sec", ContainerProcessor,
|
||||
(s) => { s.Value = Process.GetCurrentProcess().UserProcessorTime.TotalSeconds; });
|
||||
|
||||
MakeStat("PrivilegedProcessorTime", null, "sec", ContainerProcessor,
|
||||
(s) => { s.Value = Process.GetCurrentProcess().PrivilegedProcessorTime.TotalSeconds; });
|
||||
|
||||
MakeStat("Threads", null, "threads", ContainerProcessor,
|
||||
(s) => { s.Value = Process.GetCurrentProcess().Threads.Count; });
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("{0} Exception creating 'Process': {1}", LogHeader, e);
|
||||
}
|
||||
|
||||
MakeStat("BuiltinThreadpoolWorkerThreadsAvailable", null, "threads", ContainerThreadpool,
|
||||
s =>
|
||||
{
|
||||
int workerThreads, iocpThreads;
|
||||
ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads);
|
||||
s.Value = workerThreads;
|
||||
});
|
||||
|
||||
MakeStat("BuiltinThreadpoolIOCPThreadsAvailable", null, "threads", ContainerThreadpool,
|
||||
s =>
|
||||
{
|
||||
int workerThreads, iocpThreads;
|
||||
ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads);
|
||||
s.Value = iocpThreads;
|
||||
});
|
||||
|
||||
if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool && Util.GetSmartThreadPoolInfo() != null)
|
||||
{
|
||||
MakeStat("STPMaxThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MaxThreads);
|
||||
MakeStat("STPMinThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MinThreads);
|
||||
MakeStat("STPConcurrency", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MaxConcurrentWorkItems);
|
||||
MakeStat("STPActiveThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().ActiveThreads);
|
||||
MakeStat("STPInUseThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().InUseThreads);
|
||||
MakeStat("STPWorkItemsWaiting", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().WaitingCallbacks);
|
||||
}
|
||||
|
||||
MakeStat(
|
||||
"HTTPRequestsMade",
|
||||
"Number of outbound HTTP requests made",
|
||||
"requests",
|
||||
ContainerNetwork,
|
||||
s => s.Value = WebUtil.RequestNumber,
|
||||
MeasuresOfInterest.AverageChangeOverTime);
|
||||
|
||||
try
|
||||
{
|
||||
List<string> okInterfaceTypes = new List<string>(NetworkInterfaceTypes.Split(','));
|
||||
|
||||
IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces();
|
||||
foreach (NetworkInterface nic in nics)
|
||||
{
|
||||
if (nic.OperationalStatus != OperationalStatus.Up)
|
||||
continue;
|
||||
|
||||
string nicInterfaceType = nic.NetworkInterfaceType.ToString();
|
||||
if (!okInterfaceTypes.Contains(nicInterfaceType))
|
||||
{
|
||||
m_log.DebugFormat("{0} Not including stats for network interface '{1}' of type '{2}'.",
|
||||
LogHeader, nic.Name, nicInterfaceType);
|
||||
m_log.DebugFormat("{0} To include, add to comma separated list in [Monitoring]NetworkInterfaceTypes={1}",
|
||||
LogHeader, NetworkInterfaceTypes);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nic.Supports(NetworkInterfaceComponent.IPv4))
|
||||
{
|
||||
IPv4InterfaceStatistics nicStats = nic.GetIPv4Statistics();
|
||||
if (nicStats != null)
|
||||
{
|
||||
MakeStat("BytesRcvd/" + nic.Name, nic.Name, "KB", ContainerNetwork,
|
||||
(s) => { LookupNic(s, (ns) => { return ns.BytesReceived; }, 1024.0); });
|
||||
MakeStat("BytesSent/" + nic.Name, nic.Name, "KB", ContainerNetwork,
|
||||
(s) => { LookupNic(s, (ns) => { return ns.BytesSent; }, 1024.0); });
|
||||
MakeStat("TotalBytes/" + nic.Name, nic.Name, "KB", ContainerNetwork,
|
||||
(s) => { LookupNic(s, (ns) => { return ns.BytesSent + ns.BytesReceived; }, 1024.0); });
|
||||
}
|
||||
}
|
||||
// TODO: add IPv6 (it may actually happen someday)
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("{0} Exception creating 'Network Interface': {1}", LogHeader, e);
|
||||
}
|
||||
|
||||
MakeStat("ProcessMemory", null, "MB", ContainerMemory,
|
||||
(s) => { s.Value = Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024d / 1024d, 3); });
|
||||
MakeStat("HeapMemory", null, "MB", ContainerMemory,
|
||||
(s) => { s.Value = Math.Round(GC.GetTotalMemory(false) / 1024d / 1024d, 3); });
|
||||
MakeStat("LastHeapAllocationRate", null, "MB/sec", ContainerMemory,
|
||||
(s) => { s.Value = Math.Round(MemoryWatchdog.LastHeapAllocationRate * 1000d / 1024d / 1024d, 3); });
|
||||
MakeStat("AverageHeapAllocationRate", null, "MB/sec", ContainerMemory,
|
||||
(s) => { s.Value = Math.Round(MemoryWatchdog.AverageHeapAllocationRate * 1000d / 1024d / 1024d, 3); });
|
||||
}
|
||||
|
||||
// Notes on performance counters:
|
||||
// "How To Read Performance Counters": http://blogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx
|
||||
// "How to get the CPU Usage in C#": http://stackoverflow.com/questions/278071/how-to-get-the-cpu-usage-in-c
|
||||
// "Mono Performance Counters": http://www.mono-project.com/Mono_Performance_Counters
|
||||
private delegate double PerfCounterNextValue();
|
||||
private void GetNextValue(Stat stat, PerfCounterControl perfControl)
|
||||
{
|
||||
GetNextValue(stat, perfControl, 1.0);
|
||||
}
|
||||
private void GetNextValue(Stat stat, PerfCounterControl perfControl, double factor)
|
||||
{
|
||||
if (Util.EnvironmentTickCountSubtract(perfControl.lastFetch) > performanceCounterSampleInterval)
|
||||
{
|
||||
if (perfControl != null && perfControl.perfCounter != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Kludge for factor to run double duty. If -1, subtract the value from one
|
||||
if (factor == -1)
|
||||
stat.Value = 1 - perfControl.perfCounter.NextValue();
|
||||
else
|
||||
stat.Value = perfControl.perfCounter.NextValue() / factor;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("{0} Exception on NextValue fetching {1}: {2}", LogHeader, stat.Name, e);
|
||||
}
|
||||
perfControl.lastFetch = Util.EnvironmentTickCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Lookup the nic that goes with this stat and set the value by using a fetch action.
|
||||
// Not sure about closure with delegates inside delegates.
|
||||
private delegate double GetIPv4StatValue(IPv4InterfaceStatistics interfaceStat);
|
||||
private void LookupNic(Stat stat, GetIPv4StatValue getter, double factor)
|
||||
{
|
||||
// Get the one nic that has the name of this stat
|
||||
IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces().Where(
|
||||
(network) => network.Name == stat.Description);
|
||||
try
|
||||
{
|
||||
foreach (NetworkInterface nic in nics)
|
||||
{
|
||||
IPv4InterfaceStatistics intrStats = nic.GetIPv4Statistics();
|
||||
if (intrStats != null)
|
||||
{
|
||||
double newVal = Math.Round(getter(intrStats) / factor, 3);
|
||||
stat.Value = newVal;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// There are times interfaces go away so we just won't update the stat for this
|
||||
m_log.ErrorFormat("{0} Exception fetching stat on interface '{1}'", LogHeader, stat.Description);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ServerStatsAggregator : Stat
|
||||
{
|
||||
public ServerStatsAggregator(
|
||||
string shortName,
|
||||
string name,
|
||||
string description,
|
||||
string unitName,
|
||||
string category,
|
||||
string container
|
||||
)
|
||||
: base(
|
||||
shortName,
|
||||
name,
|
||||
description,
|
||||
unitName,
|
||||
category,
|
||||
container,
|
||||
StatType.Push,
|
||||
MeasuresOfInterest.None,
|
||||
null,
|
||||
StatVerbosity.Info)
|
||||
{
|
||||
}
|
||||
public override string ToConsoleString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public override OSDMap ToOSDMap()
|
||||
{
|
||||
OSDMap ret = new OSDMap();
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.StructuredData;
|
||||
@@ -39,8 +40,6 @@ namespace OpenSim.Framework.Monitoring
|
||||
/// </summary>
|
||||
public class SimExtraStatsCollector : BaseStatsCollector
|
||||
{
|
||||
private long abnormalClientThreadTerminations;
|
||||
|
||||
// private long assetsInCache;
|
||||
// private long texturesInCache;
|
||||
// private long assetCacheMemoryUsage;
|
||||
@@ -73,11 +72,6 @@ namespace OpenSim.Framework.Monitoring
|
||||
private volatile float activeScripts;
|
||||
private volatile float scriptLinesPerSecond;
|
||||
|
||||
/// <summary>
|
||||
/// Number of times that a client thread terminated because of an exception
|
||||
/// </summary>
|
||||
public long AbnormalClientThreadTerminations { get { return abnormalClientThreadTerminations; } }
|
||||
|
||||
// /// <summary>
|
||||
// /// These statistics are being collected by push rather than pull. Pull would be simpler, but I had the
|
||||
// /// notion of providing some flow statistics (which pull wouldn't give us). Though admittedly these
|
||||
@@ -166,11 +160,6 @@ namespace OpenSim.Framework.Monitoring
|
||||
private IDictionary<UUID, PacketQueueStatsCollector> packetQueueStatsCollectors
|
||||
= new Dictionary<UUID, PacketQueueStatsCollector>();
|
||||
|
||||
public void AddAbnormalClientThreadTermination()
|
||||
{
|
||||
abnormalClientThreadTerminations++;
|
||||
}
|
||||
|
||||
// public void AddAsset(AssetBase asset)
|
||||
// {
|
||||
// assetsInCache++;
|
||||
@@ -324,10 +313,12 @@ Asset service request failures: {3}" + Environment.NewLine,
|
||||
sb.Append(Environment.NewLine);
|
||||
sb.Append("CONNECTION STATISTICS");
|
||||
sb.Append(Environment.NewLine);
|
||||
sb.Append(
|
||||
string.Format(
|
||||
"Abnormal client thread terminations: {0}" + Environment.NewLine,
|
||||
abnormalClientThreadTerminations));
|
||||
|
||||
List<Stat> stats = StatsManager.GetStatsFromEachContainer("clientstack", "ClientLogoutsDueToNoReceives");
|
||||
|
||||
sb.AppendFormat(
|
||||
"Client logouts due to no data receive timeout: {0}\n\n",
|
||||
stats != null ? stats.Sum(s => s.Value).ToString() : "unknown");
|
||||
|
||||
// sb.Append(Environment.NewLine);
|
||||
// sb.Append("INVENTORY STATISTICS");
|
||||
@@ -338,7 +329,7 @@ Asset service request failures: {3}" + Environment.NewLine,
|
||||
// InventoryServiceRetrievalFailures));
|
||||
|
||||
sb.Append(Environment.NewLine);
|
||||
sb.Append("FRAME STATISTICS");
|
||||
sb.Append("SAMPLE FRAME STATISTICS");
|
||||
sb.Append(Environment.NewLine);
|
||||
sb.Append("Dilatn SimFPS PhyFPS AgntUp RootAg ChldAg Prims AtvPrm AtvScr ScrLPS");
|
||||
sb.Append(Environment.NewLine);
|
||||
@@ -359,8 +350,9 @@ Asset service request failures: {3}" + Environment.NewLine,
|
||||
inPacketsPerSecond, outPacketsPerSecond, pendingDownloads, pendingUploads, unackedBytes, totalFrameTime,
|
||||
netFrameTime, physicsFrameTime, otherFrameTime, agentFrameTime, imageFrameTime));
|
||||
|
||||
/* 20130319 RA: For the moment, disable the dump of 'scene' catagory as they are mostly output by
|
||||
* the two formatted printouts above.
|
||||
SortedDictionary<string, SortedDictionary<string, Stat>> sceneStats;
|
||||
|
||||
if (StatsManager.TryGetStats("scene", out sceneStats))
|
||||
{
|
||||
foreach (KeyValuePair<string, SortedDictionary<string, Stat>> kvp in sceneStats)
|
||||
@@ -374,6 +366,7 @@ Asset service request failures: {3}" + Environment.NewLine,
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
sb.Append(Environment.NewLine);
|
||||
|
||||
@@ -34,142 +34,6 @@ using OpenMetaverse.StructuredData;
|
||||
|
||||
namespace OpenSim.Framework.Monitoring
|
||||
{
|
||||
// Create a time histogram of events. The histogram is built in a wrap-around
|
||||
// array of equally distributed buckets.
|
||||
// For instance, a minute long histogram of second sized buckets would be:
|
||||
// new EventHistogram(60, 1000)
|
||||
public class EventHistogram
|
||||
{
|
||||
private int m_timeBase;
|
||||
private int m_numBuckets;
|
||||
private int m_bucketMilliseconds;
|
||||
private int m_lastBucket;
|
||||
private int m_totalHistogramMilliseconds;
|
||||
private long[] m_histogram;
|
||||
private object histoLock = new object();
|
||||
|
||||
public EventHistogram(int numberOfBuckets, int millisecondsPerBucket)
|
||||
{
|
||||
m_numBuckets = numberOfBuckets;
|
||||
m_bucketMilliseconds = millisecondsPerBucket;
|
||||
m_totalHistogramMilliseconds = m_numBuckets * m_bucketMilliseconds;
|
||||
|
||||
m_histogram = new long[m_numBuckets];
|
||||
Zero();
|
||||
m_lastBucket = 0;
|
||||
m_timeBase = Util.EnvironmentTickCount();
|
||||
}
|
||||
|
||||
public void Event()
|
||||
{
|
||||
this.Event(1);
|
||||
}
|
||||
|
||||
// Record an event at time 'now' in the histogram.
|
||||
public void Event(int cnt)
|
||||
{
|
||||
lock (histoLock)
|
||||
{
|
||||
// The time as displaced from the base of the histogram
|
||||
int bucketTime = Util.EnvironmentTickCountSubtract(m_timeBase);
|
||||
|
||||
// If more than the total time of the histogram, we just start over
|
||||
if (bucketTime > m_totalHistogramMilliseconds)
|
||||
{
|
||||
Zero();
|
||||
m_lastBucket = 0;
|
||||
m_timeBase = Util.EnvironmentTickCount();
|
||||
}
|
||||
else
|
||||
{
|
||||
// To which bucket should we add this event?
|
||||
int bucket = bucketTime / m_bucketMilliseconds;
|
||||
|
||||
// Advance m_lastBucket to the new bucket. Zero any buckets skipped over.
|
||||
while (bucket != m_lastBucket)
|
||||
{
|
||||
// Zero from just after the last bucket to the new bucket or the end
|
||||
for (int jj = m_lastBucket + 1; jj <= Math.Min(bucket, m_numBuckets - 1); jj++)
|
||||
{
|
||||
m_histogram[jj] = 0;
|
||||
}
|
||||
m_lastBucket = bucket;
|
||||
// If the new bucket is off the end, wrap around to the beginning
|
||||
if (bucket > m_numBuckets)
|
||||
{
|
||||
bucket -= m_numBuckets;
|
||||
m_lastBucket = 0;
|
||||
m_histogram[m_lastBucket] = 0;
|
||||
m_timeBase += m_totalHistogramMilliseconds;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_histogram[m_lastBucket] += cnt;
|
||||
}
|
||||
}
|
||||
|
||||
// Get a copy of the current histogram
|
||||
public long[] GetHistogram()
|
||||
{
|
||||
long[] ret = new long[m_numBuckets];
|
||||
lock (histoLock)
|
||||
{
|
||||
int indx = m_lastBucket + 1;
|
||||
for (int ii = 0; ii < m_numBuckets; ii++, indx++)
|
||||
{
|
||||
if (indx >= m_numBuckets)
|
||||
indx = 0;
|
||||
ret[ii] = m_histogram[indx];
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public OSDMap GetHistogramAsOSDMap()
|
||||
{
|
||||
OSDMap ret = new OSDMap();
|
||||
|
||||
ret.Add("Buckets", OSD.FromInteger(m_numBuckets));
|
||||
ret.Add("BucketMilliseconds", OSD.FromInteger(m_bucketMilliseconds));
|
||||
ret.Add("TotalMilliseconds", OSD.FromInteger(m_totalHistogramMilliseconds));
|
||||
|
||||
// Compute a number for the first bucket in the histogram.
|
||||
// This will allow readers to know how this histogram relates to any previously read histogram.
|
||||
int baseBucketNum = (m_timeBase / m_bucketMilliseconds) + m_lastBucket + 1;
|
||||
ret.Add("BaseNumber", OSD.FromInteger(baseBucketNum));
|
||||
|
||||
ret.Add("Values", GetHistogramAsOSDArray());
|
||||
|
||||
return ret;
|
||||
}
|
||||
// Get a copy of the current histogram
|
||||
public OSDArray GetHistogramAsOSDArray()
|
||||
{
|
||||
OSDArray ret = new OSDArray(m_numBuckets);
|
||||
lock (histoLock)
|
||||
{
|
||||
int indx = m_lastBucket + 1;
|
||||
for (int ii = 0; ii < m_numBuckets; ii++, indx++)
|
||||
{
|
||||
if (indx >= m_numBuckets)
|
||||
indx = 0;
|
||||
ret[ii] = OSD.FromLong(m_histogram[indx]);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Zero out the histogram
|
||||
public void Zero()
|
||||
{
|
||||
lock (histoLock)
|
||||
{
|
||||
for (int ii = 0; ii < m_numBuckets; ii++)
|
||||
m_histogram[ii] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A statistic that wraps a counter.
|
||||
// Built this way mostly so histograms and history can be created.
|
||||
public class CounterStat : Stat
|
||||
@@ -224,5 +88,32 @@ public class CounterStat : Stat
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// CounterStat is a basic stat plus histograms
|
||||
public override OSDMap ToOSDMap()
|
||||
{
|
||||
// Get the foundational instance
|
||||
OSDMap map = base.ToOSDMap();
|
||||
|
||||
map["StatType"] = "CounterStat";
|
||||
|
||||
// If there are any histograms, add a new field that is an array of histograms as OSDMaps
|
||||
if (m_histograms.Count > 0)
|
||||
{
|
||||
lock (counterLock)
|
||||
{
|
||||
if (m_histograms.Count > 0)
|
||||
{
|
||||
OSDArray histos = new OSDArray();
|
||||
foreach (EventHistogram histo in m_histograms.Values)
|
||||
{
|
||||
histos.Add(histo.GetHistogramAsOSDMap());
|
||||
}
|
||||
map.Add("Histograms", histos);
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
173
OpenSim/Framework/Monitoring/Stats/EventHistogram.cs
Executable file
173
OpenSim/Framework/Monitoring/Stats/EventHistogram.cs
Executable file
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* 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 the OpenSimulator Project 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 DEVELOPERS ``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 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using OpenMetaverse.StructuredData;
|
||||
|
||||
namespace OpenSim.Framework.Monitoring
|
||||
{
|
||||
// Create a time histogram of events. The histogram is built in a wrap-around
|
||||
// array of equally distributed buckets.
|
||||
// For instance, a minute long histogram of second sized buckets would be:
|
||||
// new EventHistogram(60, 1000)
|
||||
public class EventHistogram
|
||||
{
|
||||
private int m_timeBase;
|
||||
private int m_numBuckets;
|
||||
private int m_bucketMilliseconds;
|
||||
private int m_lastBucket;
|
||||
private int m_totalHistogramMilliseconds;
|
||||
private long[] m_histogram;
|
||||
private object histoLock = new object();
|
||||
|
||||
public EventHistogram(int numberOfBuckets, int millisecondsPerBucket)
|
||||
{
|
||||
m_numBuckets = numberOfBuckets;
|
||||
m_bucketMilliseconds = millisecondsPerBucket;
|
||||
m_totalHistogramMilliseconds = m_numBuckets * m_bucketMilliseconds;
|
||||
|
||||
m_histogram = new long[m_numBuckets];
|
||||
Zero();
|
||||
m_lastBucket = 0;
|
||||
m_timeBase = Util.EnvironmentTickCount();
|
||||
}
|
||||
|
||||
public void Event()
|
||||
{
|
||||
this.Event(1);
|
||||
}
|
||||
|
||||
// Record an event at time 'now' in the histogram.
|
||||
public void Event(int cnt)
|
||||
{
|
||||
lock (histoLock)
|
||||
{
|
||||
// The time as displaced from the base of the histogram
|
||||
int bucketTime = Util.EnvironmentTickCountSubtract(m_timeBase);
|
||||
|
||||
// If more than the total time of the histogram, we just start over
|
||||
if (bucketTime > m_totalHistogramMilliseconds)
|
||||
{
|
||||
Zero();
|
||||
m_lastBucket = 0;
|
||||
m_timeBase = Util.EnvironmentTickCount();
|
||||
}
|
||||
else
|
||||
{
|
||||
// To which bucket should we add this event?
|
||||
int bucket = bucketTime / m_bucketMilliseconds;
|
||||
|
||||
// Advance m_lastBucket to the new bucket. Zero any buckets skipped over.
|
||||
while (bucket != m_lastBucket)
|
||||
{
|
||||
// Zero from just after the last bucket to the new bucket or the end
|
||||
for (int jj = m_lastBucket + 1; jj <= Math.Min(bucket, m_numBuckets - 1); jj++)
|
||||
{
|
||||
m_histogram[jj] = 0;
|
||||
}
|
||||
m_lastBucket = bucket;
|
||||
// If the new bucket is off the end, wrap around to the beginning
|
||||
if (bucket > m_numBuckets)
|
||||
{
|
||||
bucket -= m_numBuckets;
|
||||
m_lastBucket = 0;
|
||||
m_histogram[m_lastBucket] = 0;
|
||||
m_timeBase += m_totalHistogramMilliseconds;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_histogram[m_lastBucket] += cnt;
|
||||
}
|
||||
}
|
||||
|
||||
// Get a copy of the current histogram
|
||||
public long[] GetHistogram()
|
||||
{
|
||||
long[] ret = new long[m_numBuckets];
|
||||
lock (histoLock)
|
||||
{
|
||||
int indx = m_lastBucket + 1;
|
||||
for (int ii = 0; ii < m_numBuckets; ii++, indx++)
|
||||
{
|
||||
if (indx >= m_numBuckets)
|
||||
indx = 0;
|
||||
ret[ii] = m_histogram[indx];
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public OSDMap GetHistogramAsOSDMap()
|
||||
{
|
||||
OSDMap ret = new OSDMap();
|
||||
|
||||
ret.Add("Buckets", OSD.FromInteger(m_numBuckets));
|
||||
ret.Add("BucketMilliseconds", OSD.FromInteger(m_bucketMilliseconds));
|
||||
ret.Add("TotalMilliseconds", OSD.FromInteger(m_totalHistogramMilliseconds));
|
||||
|
||||
// Compute a number for the first bucket in the histogram.
|
||||
// This will allow readers to know how this histogram relates to any previously read histogram.
|
||||
int baseBucketNum = (m_timeBase / m_bucketMilliseconds) + m_lastBucket + 1;
|
||||
ret.Add("BaseNumber", OSD.FromInteger(baseBucketNum));
|
||||
|
||||
ret.Add("Values", GetHistogramAsOSDArray());
|
||||
|
||||
return ret;
|
||||
}
|
||||
// Get a copy of the current histogram
|
||||
public OSDArray GetHistogramAsOSDArray()
|
||||
{
|
||||
OSDArray ret = new OSDArray(m_numBuckets);
|
||||
lock (histoLock)
|
||||
{
|
||||
int indx = m_lastBucket + 1;
|
||||
for (int ii = 0; ii < m_numBuckets; ii++, indx++)
|
||||
{
|
||||
if (indx >= m_numBuckets)
|
||||
indx = 0;
|
||||
ret[ii] = OSD.FromLong(m_histogram[indx]);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Zero out the histogram
|
||||
public void Zero()
|
||||
{
|
||||
lock (histoLock)
|
||||
{
|
||||
for (int ii = 0; ii < m_numBuckets; ii++)
|
||||
m_histogram[ii] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -29,6 +29,8 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
using OpenMetaverse.StructuredData;
|
||||
|
||||
namespace OpenSim.Framework.Monitoring
|
||||
{
|
||||
public class PercentageStat : Stat
|
||||
@@ -84,5 +86,19 @@ namespace OpenSim.Framework.Monitoring
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
// PercentageStat is a basic stat plus percent calc
|
||||
public override OSDMap ToOSDMap()
|
||||
{
|
||||
// Get the foundational instance
|
||||
OSDMap map = base.ToOSDMap();
|
||||
|
||||
map["StatType"] = "PercentageStat";
|
||||
|
||||
map.Add("Antecedent", OSD.FromLong(Antecedent));
|
||||
map.Add("Consequent", OSD.FromLong(Consequent));
|
||||
|
||||
return map;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,8 +27,10 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
using log4net;
|
||||
using OpenMetaverse.StructuredData;
|
||||
|
||||
namespace OpenSim.Framework.Monitoring
|
||||
@@ -38,6 +40,10 @@ namespace OpenSim.Framework.Monitoring
|
||||
/// </summary>
|
||||
public class Stat : IDisposable
|
||||
{
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
public static readonly char[] DisallowedShortNameCharacters = { '.' };
|
||||
|
||||
/// <summary>
|
||||
/// Category of this stat (e.g. cache, scene, etc).
|
||||
/// </summary>
|
||||
@@ -95,7 +101,7 @@ namespace OpenSim.Framework.Monitoring
|
||||
/// <remarks>
|
||||
/// Will be null if no measures of interest require samples.
|
||||
/// </remarks>
|
||||
private static Queue<double> m_samples;
|
||||
private Queue<double> m_samples;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum number of statistical samples.
|
||||
@@ -162,6 +168,12 @@ namespace OpenSim.Framework.Monitoring
|
||||
throw new Exception(
|
||||
string.Format("Stat cannot be in category '{0}' since this is reserved for a subcommand", category));
|
||||
|
||||
foreach (char c in DisallowedShortNameCharacters)
|
||||
{
|
||||
if (shortName.IndexOf(c) != -1)
|
||||
throw new Exception(string.Format("Stat name {0} cannot contain character {1}", shortName, c));
|
||||
}
|
||||
|
||||
ShortName = shortName;
|
||||
Name = name;
|
||||
Description = description;
|
||||
@@ -204,6 +216,8 @@ namespace OpenSim.Framework.Monitoring
|
||||
if (m_samples.Count >= m_maxSamples)
|
||||
m_samples.Dequeue();
|
||||
|
||||
// m_log.DebugFormat("[STAT]: Recording value {0} for {1}", newValue, Name);
|
||||
|
||||
m_samples.Enqueue(newValue);
|
||||
}
|
||||
}
|
||||
@@ -211,7 +225,13 @@ namespace OpenSim.Framework.Monitoring
|
||||
public virtual string ToConsoleString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.AppendFormat("{0}.{1}.{2} : {3} {4}", Category, Container, ShortName, Value, UnitName);
|
||||
sb.AppendFormat(
|
||||
"{0}.{1}.{2} : {3}{4}",
|
||||
Category,
|
||||
Container,
|
||||
ShortName,
|
||||
Value,
|
||||
UnitName == null || UnitName == "" ? "" : string.Format(" {0}", UnitName));
|
||||
|
||||
AppendMeasuresOfInterest(sb);
|
||||
|
||||
@@ -221,6 +241,8 @@ namespace OpenSim.Framework.Monitoring
|
||||
public virtual OSDMap ToOSDMap()
|
||||
{
|
||||
OSDMap ret = new OSDMap();
|
||||
ret.Add("StatType", "Stat"); // used by overloading classes to denote type of stat
|
||||
|
||||
ret.Add("Category", OSD.FromString(Category));
|
||||
ret.Add("Container", OSD.FromString(Container));
|
||||
ret.Add("ShortName", OSD.FromString(ShortName));
|
||||
@@ -229,31 +251,74 @@ namespace OpenSim.Framework.Monitoring
|
||||
ret.Add("UnitName", OSD.FromString(UnitName));
|
||||
ret.Add("Value", OSD.FromReal(Value));
|
||||
|
||||
double lastChangeOverTime, averageChangeOverTime;
|
||||
if (ComputeMeasuresOfInterest(out lastChangeOverTime, out averageChangeOverTime))
|
||||
{
|
||||
ret.Add("LastChangeOverTime", OSD.FromReal(lastChangeOverTime));
|
||||
ret.Add("AverageChangeOverTime", OSD.FromReal(averageChangeOverTime));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected void AppendMeasuresOfInterest(StringBuilder sb)
|
||||
// Compute the averages over time and return same.
|
||||
// Return 'true' if averages were actually computed. 'false' if no average info.
|
||||
public bool ComputeMeasuresOfInterest(out double lastChangeOverTime, out double averageChangeOverTime)
|
||||
{
|
||||
if ((MeasuresOfInterest & MeasuresOfInterest.AverageChangeOverTime)
|
||||
== MeasuresOfInterest.AverageChangeOverTime)
|
||||
bool ret = false;
|
||||
lastChangeOverTime = 0;
|
||||
averageChangeOverTime = 0;
|
||||
|
||||
if ((MeasuresOfInterest & MeasuresOfInterest.AverageChangeOverTime) == MeasuresOfInterest.AverageChangeOverTime)
|
||||
{
|
||||
double totalChange = 0;
|
||||
double? penultimateSample = null;
|
||||
double? lastSample = null;
|
||||
|
||||
lock (m_samples)
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[STAT]: Samples for {0} are {1}",
|
||||
// Name, string.Join(",", m_samples.Select(s => s.ToString()).ToArray()));
|
||||
|
||||
foreach (double s in m_samples)
|
||||
{
|
||||
if (lastSample != null)
|
||||
totalChange += s - (double)lastSample;
|
||||
|
||||
penultimateSample = lastSample;
|
||||
lastSample = s;
|
||||
}
|
||||
}
|
||||
|
||||
if (lastSample != null && penultimateSample != null)
|
||||
{
|
||||
lastChangeOverTime
|
||||
= ((double)lastSample - (double)penultimateSample) / (Watchdog.WATCHDOG_INTERVAL_MS / 1000);
|
||||
}
|
||||
|
||||
int divisor = m_samples.Count <= 1 ? 1 : m_samples.Count - 1;
|
||||
|
||||
sb.AppendFormat(", {0:0.##}{1}/s", totalChange / divisor / (Watchdog.WATCHDOG_INTERVAL_MS / 1000), UnitName);
|
||||
averageChangeOverTime = totalChange / divisor / (Watchdog.WATCHDOG_INTERVAL_MS / 1000);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected void AppendMeasuresOfInterest(StringBuilder sb)
|
||||
{
|
||||
double lastChangeOverTime = 0;
|
||||
double averageChangeOverTime = 0;
|
||||
|
||||
if (ComputeMeasuresOfInterest(out lastChangeOverTime, out averageChangeOverTime))
|
||||
{
|
||||
sb.AppendFormat(
|
||||
", {0:0.##}{1}/s, {2:0.##}{3}/s",
|
||||
lastChangeOverTime,
|
||||
UnitName == null || UnitName == "" ? "" : string.Format(" {0}", UnitName),
|
||||
averageChangeOverTime,
|
||||
UnitName == null || UnitName == "" ? "" : string.Format(" {0}", UnitName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
108
OpenSim/Framework/Monitoring/StatsLogger.cs
Normal file
108
OpenSim/Framework/Monitoring/StatsLogger.cs
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* 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 the OpenSimulator Project 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 DEVELOPERS ``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 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Timers;
|
||||
using log4net;
|
||||
|
||||
namespace OpenSim.Framework.Monitoring
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a means to continuously log stats for debugging purposes.
|
||||
/// </summary>
|
||||
public static class StatsLogger
|
||||
{
|
||||
private static readonly ILog m_statsLog = LogManager.GetLogger("special.StatsLogger");
|
||||
|
||||
private static Timer m_loggingTimer;
|
||||
private static int m_statsLogIntervalMs = 5000;
|
||||
|
||||
public static void RegisterConsoleCommands(ICommandConsole console)
|
||||
{
|
||||
console.Commands.AddCommand(
|
||||
"Debug",
|
||||
false,
|
||||
"debug stats record",
|
||||
"debug stats record start|stop",
|
||||
"Control whether stats are being regularly recorded to a separate file.",
|
||||
"For debug purposes. Experimental.",
|
||||
HandleStatsRecordCommand);
|
||||
}
|
||||
|
||||
public static void HandleStatsRecordCommand(string module, string[] cmd)
|
||||
{
|
||||
ICommandConsole con = MainConsole.Instance;
|
||||
|
||||
if (cmd.Length != 4)
|
||||
{
|
||||
con.Output("Usage: debug stats record start|stop");
|
||||
return;
|
||||
}
|
||||
|
||||
if (cmd[3] == "start")
|
||||
{
|
||||
Start();
|
||||
con.OutputFormat("Now recording all stats to file every {0}ms", m_statsLogIntervalMs);
|
||||
}
|
||||
else if (cmd[3] == "stop")
|
||||
{
|
||||
Stop();
|
||||
con.Output("Stopped recording stats to file.");
|
||||
}
|
||||
}
|
||||
|
||||
public static void Start()
|
||||
{
|
||||
if (m_loggingTimer != null)
|
||||
Stop();
|
||||
|
||||
m_loggingTimer = new Timer(m_statsLogIntervalMs);
|
||||
m_loggingTimer.AutoReset = false;
|
||||
m_loggingTimer.Elapsed += Log;
|
||||
m_loggingTimer.Start();
|
||||
}
|
||||
|
||||
public static void Stop()
|
||||
{
|
||||
if (m_loggingTimer != null)
|
||||
{
|
||||
m_loggingTimer.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
private static void Log(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
m_statsLog.InfoFormat("*** STATS REPORT AT {0} ***", DateTime.Now);
|
||||
|
||||
foreach (string report in StatsManager.GetAllStatsReports())
|
||||
m_statsLog.Info(report);
|
||||
|
||||
m_loggingTimer.Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,15 +26,20 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using OpenSim.Framework;
|
||||
using OpenMetaverse.StructuredData;
|
||||
|
||||
namespace OpenSim.Framework.Monitoring
|
||||
{
|
||||
/// <summary>
|
||||
/// Singleton used to provide access to statistics reporters
|
||||
/// Static class used to register/deregister/fetch statistics
|
||||
/// </summary>
|
||||
public class StatsManager
|
||||
public static class StatsManager
|
||||
{
|
||||
// Subcommand used to list other stats.
|
||||
public const string AllSubCommand = "all";
|
||||
@@ -54,13 +59,13 @@ namespace OpenSim.Framework.Monitoring
|
||||
public static SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>> RegisteredStats
|
||||
= new SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>>();
|
||||
|
||||
private static AssetStatsCollector assetStats;
|
||||
private static UserStatsCollector userStats;
|
||||
private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector();
|
||||
// private static AssetStatsCollector assetStats;
|
||||
// private static UserStatsCollector userStats;
|
||||
// private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector();
|
||||
|
||||
public static AssetStatsCollector AssetStats { get { return assetStats; } }
|
||||
public static UserStatsCollector UserStats { get { return userStats; } }
|
||||
public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } }
|
||||
// public static AssetStatsCollector AssetStats { get { return assetStats; } }
|
||||
// public static UserStatsCollector UserStats { get { return userStats; } }
|
||||
public static SimExtraStatsCollector SimExtraStats { get; set; }
|
||||
|
||||
public static void RegisterConsoleCommands(ICommandConsole console)
|
||||
{
|
||||
@@ -68,14 +73,18 @@ namespace OpenSim.Framework.Monitoring
|
||||
"General",
|
||||
false,
|
||||
"show stats",
|
||||
"show stats [list|all|<category>]",
|
||||
"show stats [list|all|(<category>[.<container>])+",
|
||||
"Show statistical information for this server",
|
||||
"If no final argument is specified then legacy statistics information is currently shown.\n"
|
||||
+ "If list is specified then statistic categories are shown.\n"
|
||||
+ "If all is specified then all registered statistics are shown.\n"
|
||||
+ "If a category name is specified then only statistics from that category are shown.\n"
|
||||
+ "'list' argument will show statistic categories.\n"
|
||||
+ "'all' will show all statistics.\n"
|
||||
+ "A <category> name will show statistics from that category.\n"
|
||||
+ "A <category>.<container> name will show statistics from that category in that container.\n"
|
||||
+ "More than one name can be given separated by spaces.\n"
|
||||
+ "THIS STATS FACILITY IS EXPERIMENTAL AND DOES NOT YET CONTAIN ALL STATS",
|
||||
HandleShowStatsCommand);
|
||||
|
||||
StatsLogger.RegisterConsoleCommands(console);
|
||||
}
|
||||
|
||||
public static void HandleShowStatsCommand(string module, string[] cmd)
|
||||
@@ -84,43 +93,47 @@ namespace OpenSim.Framework.Monitoring
|
||||
|
||||
if (cmd.Length > 2)
|
||||
{
|
||||
var categoryName = cmd[2];
|
||||
var containerName = cmd.Length > 3 ? cmd[3] : String.Empty;
|
||||
foreach (string name in cmd.Skip(2))
|
||||
{
|
||||
string[] components = name.Split('.');
|
||||
|
||||
if (categoryName == AllSubCommand)
|
||||
{
|
||||
foreach (var category in RegisteredStats.Values)
|
||||
string categoryName = components[0];
|
||||
string containerName = components.Length > 1 ? components[1] : null;
|
||||
|
||||
if (categoryName == AllSubCommand)
|
||||
{
|
||||
OutputCategoryStatsToConsole(con, category);
|
||||
OutputAllStatsToConsole(con);
|
||||
}
|
||||
}
|
||||
else if (categoryName == ListSubCommand)
|
||||
{
|
||||
con.Output("Statistic categories available are:");
|
||||
foreach (string category in RegisteredStats.Keys)
|
||||
con.OutputFormat(" {0}", category);
|
||||
}
|
||||
else
|
||||
{
|
||||
SortedDictionary<string, SortedDictionary<string, Stat>> category;
|
||||
if (!RegisteredStats.TryGetValue(categoryName, out category))
|
||||
else if (categoryName == ListSubCommand)
|
||||
{
|
||||
con.OutputFormat("No such category as {0}", categoryName);
|
||||
con.Output("Statistic categories available are:");
|
||||
foreach (string category in RegisteredStats.Keys)
|
||||
con.OutputFormat(" {0}", category);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (String.IsNullOrEmpty(containerName))
|
||||
OutputCategoryStatsToConsole(con, category);
|
||||
SortedDictionary<string, SortedDictionary<string, Stat>> category;
|
||||
if (!RegisteredStats.TryGetValue(categoryName, out category))
|
||||
{
|
||||
con.OutputFormat("No such category as {0}", categoryName);
|
||||
}
|
||||
else
|
||||
{
|
||||
SortedDictionary<string, Stat> container;
|
||||
if (category.TryGetValue(containerName, out container))
|
||||
if (String.IsNullOrEmpty(containerName))
|
||||
{
|
||||
OutputContainerStatsToConsole(con, container);
|
||||
OutputCategoryStatsToConsole(con, category);
|
||||
}
|
||||
else
|
||||
{
|
||||
con.OutputFormat("No such container {0} in category {1}", containerName, categoryName);
|
||||
SortedDictionary<string, Stat> container;
|
||||
if (category.TryGetValue(containerName, out container))
|
||||
{
|
||||
OutputContainerStatsToConsole(con, container);
|
||||
}
|
||||
else
|
||||
{
|
||||
con.OutputFormat("No such container {0} in category {1}", containerName, categoryName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -129,51 +142,187 @@ namespace OpenSim.Framework.Monitoring
|
||||
else
|
||||
{
|
||||
// Legacy
|
||||
con.Output(SimExtraStats.Report());
|
||||
if (SimExtraStats != null)
|
||||
con.Output(SimExtraStats.Report());
|
||||
else
|
||||
OutputAllStatsToConsole(con);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<string> GetAllStatsReports()
|
||||
{
|
||||
List<string> reports = new List<string>();
|
||||
|
||||
foreach (var category in RegisteredStats.Values)
|
||||
reports.AddRange(GetCategoryStatsReports(category));
|
||||
|
||||
return reports;
|
||||
}
|
||||
|
||||
private static void OutputAllStatsToConsole(ICommandConsole con)
|
||||
{
|
||||
foreach (string report in GetAllStatsReports())
|
||||
con.Output(report);
|
||||
}
|
||||
|
||||
private static List<string> GetCategoryStatsReports(
|
||||
SortedDictionary<string, SortedDictionary<string, Stat>> category)
|
||||
{
|
||||
List<string> reports = new List<string>();
|
||||
|
||||
foreach (var container in category.Values)
|
||||
reports.AddRange(GetContainerStatsReports(container));
|
||||
|
||||
return reports;
|
||||
}
|
||||
|
||||
private static void OutputCategoryStatsToConsole(
|
||||
ICommandConsole con, SortedDictionary<string, SortedDictionary<string, Stat>> category)
|
||||
{
|
||||
foreach (var container in category.Values)
|
||||
{
|
||||
OutputContainerStatsToConsole(con, container);
|
||||
}
|
||||
foreach (string report in GetCategoryStatsReports(category))
|
||||
con.Output(report);
|
||||
}
|
||||
|
||||
private static void OutputContainerStatsToConsole( ICommandConsole con, SortedDictionary<string, Stat> container)
|
||||
private static List<string> GetContainerStatsReports(SortedDictionary<string, Stat> container)
|
||||
{
|
||||
List<string> reports = new List<string>();
|
||||
|
||||
foreach (Stat stat in container.Values)
|
||||
reports.Add(stat.ToConsoleString());
|
||||
|
||||
return reports;
|
||||
}
|
||||
|
||||
private static void OutputContainerStatsToConsole(
|
||||
ICommandConsole con, SortedDictionary<string, Stat> container)
|
||||
{
|
||||
foreach (string report in GetContainerStatsReports(container))
|
||||
con.Output(report);
|
||||
}
|
||||
|
||||
// Creates an OSDMap of the format:
|
||||
// { categoryName: {
|
||||
// containerName: {
|
||||
// statName: {
|
||||
// "Name": name,
|
||||
// "ShortName": shortName,
|
||||
// ...
|
||||
// },
|
||||
// statName: {
|
||||
// "Name": name,
|
||||
// "ShortName": shortName,
|
||||
// ...
|
||||
// },
|
||||
// ...
|
||||
// },
|
||||
// containerName: {
|
||||
// ...
|
||||
// },
|
||||
// ...
|
||||
// },
|
||||
// categoryName: {
|
||||
// ...
|
||||
// },
|
||||
// ...
|
||||
// }
|
||||
// The passed in parameters will filter the categories, containers and stats returned. If any of the
|
||||
// parameters are either EmptyOrNull or the AllSubCommand value, all of that type will be returned.
|
||||
// Case matters.
|
||||
public static OSDMap GetStatsAsOSDMap(string pCategoryName, string pContainerName, string pStatName)
|
||||
{
|
||||
OSDMap map = new OSDMap();
|
||||
|
||||
foreach (string catName in RegisteredStats.Keys)
|
||||
{
|
||||
con.Output(stat.ToConsoleString());
|
||||
// Do this category if null spec, "all" subcommand or category name matches passed parameter.
|
||||
// Skip category if none of the above.
|
||||
if (!(String.IsNullOrEmpty(pCategoryName) || pCategoryName == AllSubCommand || pCategoryName == catName))
|
||||
continue;
|
||||
|
||||
OSDMap contMap = new OSDMap();
|
||||
foreach (string contName in RegisteredStats[catName].Keys)
|
||||
{
|
||||
if (!(string.IsNullOrEmpty(pContainerName) || pContainerName == AllSubCommand || pContainerName == contName))
|
||||
continue;
|
||||
|
||||
OSDMap statMap = new OSDMap();
|
||||
|
||||
SortedDictionary<string, Stat> theStats = RegisteredStats[catName][contName];
|
||||
foreach (string statName in theStats.Keys)
|
||||
{
|
||||
if (!(String.IsNullOrEmpty(pStatName) || pStatName == AllSubCommand || pStatName == statName))
|
||||
continue;
|
||||
|
||||
statMap.Add(statName, theStats[statName].ToOSDMap());
|
||||
}
|
||||
|
||||
contMap.Add(contName, statMap);
|
||||
}
|
||||
map.Add(catName, contMap);
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start collecting statistics related to assets.
|
||||
/// Should only be called once.
|
||||
/// </summary>
|
||||
public static AssetStatsCollector StartCollectingAssetStats()
|
||||
public static Hashtable HandleStatsRequest(Hashtable request)
|
||||
{
|
||||
assetStats = new AssetStatsCollector();
|
||||
Hashtable responsedata = new Hashtable();
|
||||
// string regpath = request["uri"].ToString();
|
||||
int response_code = 200;
|
||||
string contenttype = "text/json";
|
||||
|
||||
return assetStats;
|
||||
string pCategoryName = StatsManager.AllSubCommand;
|
||||
string pContainerName = StatsManager.AllSubCommand;
|
||||
string pStatName = StatsManager.AllSubCommand;
|
||||
|
||||
if (request.ContainsKey("cat")) pCategoryName = request["cat"].ToString();
|
||||
if (request.ContainsKey("cont")) pContainerName = request["cat"].ToString();
|
||||
if (request.ContainsKey("stat")) pStatName = request["cat"].ToString();
|
||||
|
||||
string strOut = StatsManager.GetStatsAsOSDMap(pCategoryName, pContainerName, pStatName).ToString();
|
||||
|
||||
// If requestor wants it as a callback function, build response as a function rather than just the JSON string.
|
||||
if (request.ContainsKey("callback"))
|
||||
{
|
||||
strOut = request["callback"].ToString() + "(" + strOut + ");";
|
||||
}
|
||||
|
||||
// m_log.DebugFormat("{0} StatFetch: uri={1}, cat={2}, cont={3}, stat={4}, resp={5}",
|
||||
// LogHeader, regpath, pCategoryName, pContainerName, pStatName, strOut);
|
||||
|
||||
responsedata["int_response_code"] = response_code;
|
||||
responsedata["content_type"] = contenttype;
|
||||
responsedata["keepalive"] = false;
|
||||
responsedata["str_response_string"] = strOut;
|
||||
responsedata["access_control_allow_origin"] = "*";
|
||||
|
||||
return responsedata;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start collecting statistics related to users.
|
||||
/// Should only be called once.
|
||||
/// </summary>
|
||||
public static UserStatsCollector StartCollectingUserStats()
|
||||
{
|
||||
userStats = new UserStatsCollector();
|
||||
|
||||
return userStats;
|
||||
}
|
||||
// /// <summary>
|
||||
// /// Start collecting statistics related to assets.
|
||||
// /// Should only be called once.
|
||||
// /// </summary>
|
||||
// public static AssetStatsCollector StartCollectingAssetStats()
|
||||
// {
|
||||
// assetStats = new AssetStatsCollector();
|
||||
//
|
||||
// return assetStats;
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Start collecting statistics related to users.
|
||||
// /// Should only be called once.
|
||||
// /// </summary>
|
||||
// public static UserStatsCollector StartCollectingUserStats()
|
||||
// {
|
||||
// userStats = new UserStatsCollector();
|
||||
//
|
||||
// return userStats;
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Registers a statistic.
|
||||
/// Register a statistic.
|
||||
/// </summary>
|
||||
/// <param name='stat'></param>
|
||||
/// <returns></returns>
|
||||
@@ -187,7 +336,7 @@ namespace OpenSim.Framework.Monitoring
|
||||
// Stat name is not unique across category/container/shortname key.
|
||||
// XXX: For now just return false. This is to avoid problems in regression tests where all tests
|
||||
// in a class are run in the same instance of the VM.
|
||||
if (TryGetStat(stat, out category, out container))
|
||||
if (TryGetStatParents(stat, out category, out container))
|
||||
return false;
|
||||
|
||||
// We take a copy-on-write approach here of replacing dictionaries when keys are added or removed.
|
||||
@@ -223,7 +372,7 @@ namespace OpenSim.Framework.Monitoring
|
||||
|
||||
lock (RegisteredStats)
|
||||
{
|
||||
if (!TryGetStat(stat, out category, out container))
|
||||
if (!TryGetStatParents(stat, out category, out container))
|
||||
return false;
|
||||
|
||||
newContainer = new SortedDictionary<string, Stat>(container);
|
||||
@@ -239,12 +388,67 @@ namespace OpenSim.Framework.Monitoring
|
||||
}
|
||||
}
|
||||
|
||||
public static bool TryGetStats(string category, out SortedDictionary<string, SortedDictionary<string, Stat>> stats)
|
||||
public static bool TryGetStat(string category, string container, string statShortName, out Stat stat)
|
||||
{
|
||||
return RegisteredStats.TryGetValue(category, out stats);
|
||||
stat = null;
|
||||
SortedDictionary<string, SortedDictionary<string, Stat>> categoryStats;
|
||||
|
||||
lock (RegisteredStats)
|
||||
{
|
||||
if (!TryGetStatsForCategory(category, out categoryStats))
|
||||
return false;
|
||||
|
||||
SortedDictionary<string, Stat> containerStats;
|
||||
|
||||
if (!categoryStats.TryGetValue(container, out containerStats))
|
||||
return false;
|
||||
|
||||
return containerStats.TryGetValue(statShortName, out stat);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool TryGetStat(
|
||||
public static bool TryGetStatsForCategory(
|
||||
string category, out SortedDictionary<string, SortedDictionary<string, Stat>> stats)
|
||||
{
|
||||
lock (RegisteredStats)
|
||||
return RegisteredStats.TryGetValue(category, out stats);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the same stat for each container in a given category.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The stats if there were any to fetch. Otherwise null.
|
||||
/// </returns>
|
||||
/// <param name='category'></param>
|
||||
/// <param name='statShortName'></param>
|
||||
public static List<Stat> GetStatsFromEachContainer(string category, string statShortName)
|
||||
{
|
||||
SortedDictionary<string, SortedDictionary<string, Stat>> categoryStats;
|
||||
|
||||
lock (RegisteredStats)
|
||||
{
|
||||
if (!RegisteredStats.TryGetValue(category, out categoryStats))
|
||||
return null;
|
||||
|
||||
List<Stat> stats = null;
|
||||
|
||||
foreach (SortedDictionary<string, Stat> containerStats in categoryStats.Values)
|
||||
{
|
||||
if (containerStats.ContainsKey(statShortName))
|
||||
{
|
||||
if (stats == null)
|
||||
stats = new List<Stat>();
|
||||
|
||||
stats.Add(containerStats[statShortName]);
|
||||
}
|
||||
}
|
||||
|
||||
return stats;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool TryGetStatParents(
|
||||
Stat stat,
|
||||
out SortedDictionary<string, SortedDictionary<string, Stat>> category,
|
||||
out SortedDictionary<string, Stat> container)
|
||||
|
||||
@@ -380,6 +380,7 @@ namespace OpenSim.Framework.Monitoring
|
||||
if (MemoryWatchdog.Enabled)
|
||||
MemoryWatchdog.Update();
|
||||
|
||||
ChecksManager.CheckChecks();
|
||||
StatsManager.RecordStats();
|
||||
|
||||
m_watchdogTimer.Start();
|
||||
|
||||
@@ -86,25 +86,22 @@ namespace OpenSim.Framework.Servers
|
||||
/// </summary>
|
||||
protected virtual void StartupSpecific()
|
||||
{
|
||||
if (m_console == null)
|
||||
return;
|
||||
|
||||
StatsManager.SimExtraStats = new SimExtraStatsCollector();
|
||||
RegisterCommonCommands();
|
||||
|
||||
m_console.Commands.AddCommand("General", false, "quit",
|
||||
"quit",
|
||||
"Quit the application", HandleQuit);
|
||||
RegisterCommonComponents(Config);
|
||||
}
|
||||
|
||||
m_console.Commands.AddCommand("General", false, "shutdown",
|
||||
"shutdown",
|
||||
"Quit the application", HandleQuit);
|
||||
protected override void ShutdownSpecific()
|
||||
{
|
||||
m_log.Info("[SHUTDOWN]: Shutdown processing on main thread complete. Exiting...");
|
||||
|
||||
RemovePIDFile();
|
||||
|
||||
base.ShutdownSpecific();
|
||||
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Should be overriden and referenced by descendents if they need to perform extra shutdown processing
|
||||
/// </summary>
|
||||
public virtual void ShutdownSpecific() {}
|
||||
|
||||
/// <summary>
|
||||
/// Provides a list of help topics that are available. Overriding classes should append their topics to the
|
||||
/// information returned when the base method is called.
|
||||
@@ -143,25 +140,8 @@ namespace OpenSim.Framework.Servers
|
||||
timeTaken.Minutes, timeTaken.Seconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Should be overriden and referenced by descendents if they need to perform extra shutdown processing
|
||||
/// </summary>
|
||||
public virtual void Shutdown()
|
||||
public string osSecret
|
||||
{
|
||||
ShutdownSpecific();
|
||||
|
||||
m_log.Info("[SHUTDOWN]: Shutdown processing on main thread complete. Exiting...");
|
||||
RemovePIDFile();
|
||||
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
private void HandleQuit(string module, string[] args)
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
public string osSecret {
|
||||
// Secret uuid for the simulator
|
||||
get { return m_osSecret; }
|
||||
}
|
||||
|
||||
@@ -54,7 +54,6 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private HttpServerLogWriter httpserverlog = new HttpServerLogWriter();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// This is a pending websocket request before it got an sucessful upgrade response.
|
||||
/// The consumer must call handler.HandshakeAndUpgrade() to signal to the handler to
|
||||
@@ -81,6 +80,11 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
/// </remarks>
|
||||
public int RequestNumber { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Statistic for holding number of requests processed.
|
||||
/// </summary>
|
||||
private Stat m_requestsProcessedStat;
|
||||
|
||||
private volatile int NotSocketErrors = 0;
|
||||
public volatile bool HTTPDRunning = false;
|
||||
|
||||
@@ -383,6 +387,8 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
|
||||
if (TryGetPollServiceHTTPHandler(request.UriPath.ToString(), out psEvArgs))
|
||||
{
|
||||
psEvArgs.RequestsReceived++;
|
||||
|
||||
PollServiceHttpRequest psreq = new PollServiceHttpRequest(psEvArgs, context, request);
|
||||
|
||||
if (psEvArgs.Request != null)
|
||||
@@ -436,9 +442,8 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
}
|
||||
}
|
||||
|
||||
public void OnHandleRequestIOThread(IHttpClientContext context, IHttpRequest request)
|
||||
private void OnHandleRequestIOThread(IHttpClientContext context, IHttpRequest request)
|
||||
{
|
||||
|
||||
OSHttpRequest req = new OSHttpRequest(context, request);
|
||||
WebSocketRequestDelegate dWebSocketRequestDelegate = null;
|
||||
lock (m_WebSocketHandlers)
|
||||
@@ -453,9 +458,8 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
}
|
||||
|
||||
OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context);
|
||||
|
||||
HandleRequest(req, resp);
|
||||
|
||||
resp.ReuseContext = true;
|
||||
HandleRequest(req, resp);
|
||||
|
||||
// !!!HACK ALERT!!!
|
||||
// There seems to be a bug in the underlying http code that makes subsequent requests
|
||||
@@ -686,7 +690,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
|
||||
if (buffer != null)
|
||||
{
|
||||
if (!response.SendChunked)
|
||||
if (!response.SendChunked && response.ContentLength64 <= 0)
|
||||
response.ContentLength64 = buffer.LongLength;
|
||||
|
||||
response.OutputStream.Write(buffer, 0, buffer.Length);
|
||||
@@ -1824,6 +1828,21 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
// useful without inbound HTTP.
|
||||
throw e;
|
||||
}
|
||||
|
||||
m_requestsProcessedStat
|
||||
= new Stat(
|
||||
"HTTPRequestsServed",
|
||||
"Number of inbound HTTP requests processed",
|
||||
"",
|
||||
"requests",
|
||||
"httpserver",
|
||||
Port.ToString(),
|
||||
StatType.Pull,
|
||||
MeasuresOfInterest.AverageChangeOverTime,
|
||||
stat => stat.Value = RequestNumber,
|
||||
StatVerbosity.Debug);
|
||||
|
||||
StatsManager.RegisterStat(m_requestsProcessedStat);
|
||||
}
|
||||
|
||||
public void httpServerDisconnectMonitor(IHttpClientContext source, SocketError err)
|
||||
@@ -1854,6 +1873,9 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
public void Stop()
|
||||
{
|
||||
HTTPDRunning = false;
|
||||
|
||||
StatsManager.DeregisterStat(m_requestsProcessedStat);
|
||||
|
||||
try
|
||||
{
|
||||
m_PollServiceManager.Stop();
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* 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 the OpenSimulator Project 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 DEVELOPERS ``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 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.
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
|
||||
namespace OpenSim.Framework.Servers.HttpServer
|
||||
{
|
||||
/// <summary>
|
||||
/// Base handler for writing to an output stream
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Inheriting classes should override ProcessRequest() rather than Handle()
|
||||
/// </remarks>
|
||||
public abstract class BaseOutputStreamHandler : BaseRequestHandler, IRequestHandler
|
||||
{
|
||||
protected BaseOutputStreamHandler(string httpMethod, string path) : this(httpMethod, path, null, null) {}
|
||||
|
||||
protected BaseOutputStreamHandler(string httpMethod, string path, string name, string description)
|
||||
: base(httpMethod, path, name, description) {}
|
||||
|
||||
public virtual void Handle(
|
||||
string path, Stream request, Stream response, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||
{
|
||||
RequestsReceived++;
|
||||
|
||||
ProcessRequest(path, request, response, httpRequest, httpResponse);
|
||||
|
||||
RequestsHandled++;
|
||||
}
|
||||
|
||||
protected virtual void ProcessRequest(
|
||||
string path, Stream request, Stream response, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,10 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
{
|
||||
public abstract class BaseRequestHandler
|
||||
{
|
||||
public int RequestsReceived { get; protected set; }
|
||||
|
||||
public int RequestsHandled { get; protected set; }
|
||||
|
||||
public virtual string ContentType
|
||||
{
|
||||
get { return "application/xml"; }
|
||||
|
||||
@@ -29,14 +29,35 @@ using System.IO;
|
||||
|
||||
namespace OpenSim.Framework.Servers.HttpServer
|
||||
{
|
||||
/// <summary>
|
||||
/// Base streamed request handler.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Inheriting classes should override ProcessRequest() rather than Handle()
|
||||
/// </remarks>
|
||||
public abstract class BaseStreamHandler : BaseRequestHandler, IStreamedRequestHandler
|
||||
{
|
||||
public abstract byte[] Handle(string path, Stream request,
|
||||
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse);
|
||||
|
||||
protected BaseStreamHandler(string httpMethod, string path) : this(httpMethod, path, null, null) {}
|
||||
|
||||
protected BaseStreamHandler(string httpMethod, string path, string name, string description)
|
||||
: base(httpMethod, path, name, description) {}
|
||||
|
||||
public virtual byte[] Handle(
|
||||
string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||
{
|
||||
RequestsReceived++;
|
||||
|
||||
byte[] result = ProcessRequest(path, request, httpRequest, httpResponse);
|
||||
|
||||
RequestsHandled++;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected virtual byte[] ProcessRequest(
|
||||
string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,7 +45,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
m_method = binaryMethod;
|
||||
}
|
||||
|
||||
public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||
protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||
{
|
||||
byte[] data = ReadFully(request);
|
||||
string param = GetParam(path);
|
||||
|
||||
@@ -32,7 +32,6 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
{
|
||||
public interface IRequestHandler
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Name for this handler.
|
||||
/// </summary>
|
||||
@@ -59,6 +58,19 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
|
||||
// Return path
|
||||
string Path { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of requests received by this handler
|
||||
/// </summary>
|
||||
int RequestsReceived { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of requests handled.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Should be equal to RequestsReceived unless requested are being handled slowly or there is deadlock.
|
||||
/// </remarks>
|
||||
int RequestsHandled { get; }
|
||||
}
|
||||
|
||||
public interface IStreamedRequestHandler : IRequestHandler
|
||||
@@ -69,7 +81,6 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
|
||||
public interface IStreamHandler : IRequestHandler
|
||||
{
|
||||
// Handle request stream, return byte array
|
||||
void Handle(string path, Stream request, Stream response, IOSHttpRequest httpReqbuest, IOSHttpResponse httpResponse);
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
public delegate void RequestMethod(UUID requestID, Hashtable request);
|
||||
public delegate bool HasEventsMethod(UUID requestID, UUID pId);
|
||||
|
||||
public delegate Hashtable GetEventsMethod(UUID requestID, UUID pId, string request);
|
||||
public delegate Hashtable GetEventsMethod(UUID requestID, UUID pId);
|
||||
|
||||
public delegate Hashtable NoEventsMethod(UUID requestID, UUID pId);
|
||||
|
||||
@@ -45,17 +45,42 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
public NoEventsMethod NoEvents;
|
||||
public RequestMethod Request;
|
||||
public UUID Id;
|
||||
public int TimeOutms;
|
||||
public EventType Type;
|
||||
|
||||
public enum EventType : int
|
||||
{
|
||||
LongPoll = 0,
|
||||
LslHttp = 1,
|
||||
Inventory = 2
|
||||
}
|
||||
|
||||
public string Url { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of requests received for this poll service.
|
||||
/// </summary>
|
||||
public int RequestsReceived { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of requests handled by this poll service.
|
||||
/// </summary>
|
||||
public int RequestsHandled { get; set; }
|
||||
|
||||
public PollServiceEventArgs(
|
||||
RequestMethod pRequest,
|
||||
string pUrl,
|
||||
HasEventsMethod pHasEvents, GetEventsMethod pGetEvents, NoEventsMethod pNoEvents,
|
||||
UUID pId)
|
||||
UUID pId, int pTimeOutms)
|
||||
{
|
||||
Request = pRequest;
|
||||
Url = pUrl;
|
||||
HasEvents = pHasEvents;
|
||||
GetEvents = pGetEvents;
|
||||
NoEvents = pNoEvents;
|
||||
Id = pId;
|
||||
TimeOutms = pTimeOutms;
|
||||
Type = EventType.LongPoll;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,13 +26,19 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using HttpServer;
|
||||
using log4net;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Framework.Servers.HttpServer
|
||||
{
|
||||
public class PollServiceHttpRequest
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
public readonly PollServiceEventArgs PollServiceArgs;
|
||||
public readonly IHttpClientContext HttpContext;
|
||||
public readonly IHttpRequest Request;
|
||||
@@ -48,5 +54,44 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
RequestTime = System.Environment.TickCount;
|
||||
RequestID = UUID.Random();
|
||||
}
|
||||
|
||||
internal void DoHTTPGruntWork(BaseHttpServer server, Hashtable responsedata)
|
||||
{
|
||||
OSHttpResponse response
|
||||
= new OSHttpResponse(new HttpResponse(HttpContext, Request), HttpContext);
|
||||
|
||||
byte[] buffer = server.DoHTTPGruntWork(responsedata, response);
|
||||
|
||||
response.SendChunked = false;
|
||||
response.ContentLength64 = buffer.Length;
|
||||
response.ContentEncoding = Encoding.UTF8;
|
||||
|
||||
try
|
||||
{
|
||||
response.OutputStream.Write(buffer, 0, buffer.Length);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
m_log.Warn(string.Format("[POLL SERVICE WORKER THREAD]: Error ", ex));
|
||||
}
|
||||
finally
|
||||
{
|
||||
//response.OutputStream.Close();
|
||||
try
|
||||
{
|
||||
response.OutputStream.Flush();
|
||||
response.Send();
|
||||
|
||||
//if (!response.KeepAlive && response.ReuseContext)
|
||||
// response.FreeContext();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Warn(String.Format("[POLL SERVICE WORKER THREAD]: Error ", e));
|
||||
}
|
||||
|
||||
PollServiceArgs.RequestsHandled++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,54 +33,57 @@ using log4net;
|
||||
using HttpServer;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Monitoring;
|
||||
using Amib.Threading;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenSim.Framework.Servers.HttpServer
|
||||
{
|
||||
public class PollServiceRequestManager
|
||||
{
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private readonly BaseHttpServer m_server;
|
||||
private static Queue m_requests = Queue.Synchronized(new Queue());
|
||||
|
||||
private BlockingQueue<PollServiceHttpRequest> m_requests = new BlockingQueue<PollServiceHttpRequest>();
|
||||
private static List<PollServiceHttpRequest> m_longPollRequests = new List<PollServiceHttpRequest>();
|
||||
|
||||
private uint m_WorkerThreadCount = 0;
|
||||
private Thread[] m_workerThreads;
|
||||
private PollServiceWorkerThread[] m_PollServiceWorkerThreads;
|
||||
private volatile bool m_running = true;
|
||||
private int m_pollTimeout;
|
||||
|
||||
private bool m_running = true;
|
||||
|
||||
private SmartThreadPool m_threadPool = new SmartThreadPool(20000, 12, 2);
|
||||
|
||||
// private int m_timeout = 1000; // increase timeout 250; now use the event one
|
||||
|
||||
public PollServiceRequestManager(BaseHttpServer pSrv, uint pWorkerThreadCount, int pTimeout)
|
||||
{
|
||||
m_server = pSrv;
|
||||
m_WorkerThreadCount = pWorkerThreadCount;
|
||||
m_pollTimeout = pTimeout;
|
||||
m_workerThreads = new Thread[m_WorkerThreadCount];
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
m_running = true;
|
||||
m_workerThreads = new Thread[m_WorkerThreadCount];
|
||||
m_PollServiceWorkerThreads = new PollServiceWorkerThread[m_WorkerThreadCount];
|
||||
|
||||
//startup worker threads
|
||||
for (uint i = 0; i < m_WorkerThreadCount; i++)
|
||||
{
|
||||
m_PollServiceWorkerThreads[i] = new PollServiceWorkerThread(m_server, m_pollTimeout);
|
||||
m_PollServiceWorkerThreads[i].ReQueue += ReQueueEvent;
|
||||
|
||||
m_workerThreads[i]
|
||||
= Watchdog.StartThread(
|
||||
m_PollServiceWorkerThreads[i].ThreadStart,
|
||||
String.Format("PollServiceWorkerThread{0}", i),
|
||||
PoolWorkerJob,
|
||||
string.Format("PollServiceWorkerThread{0}:{1}", i, m_server.Port),
|
||||
ThreadPriority.Normal,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
null,
|
||||
int.MaxValue);
|
||||
}
|
||||
|
||||
Watchdog.StartThread(
|
||||
this.ThreadStart,
|
||||
"PollServiceWatcherThread",
|
||||
this.CheckLongPollThreads,
|
||||
string.Format("LongPollServiceWatcherThread:{0}", m_server.Port),
|
||||
ThreadPriority.Normal,
|
||||
false,
|
||||
true,
|
||||
@@ -88,77 +91,172 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
1000 * 60 * 10);
|
||||
}
|
||||
|
||||
internal void ReQueueEvent(PollServiceHttpRequest req)
|
||||
private void ReQueueEvent(PollServiceHttpRequest req)
|
||||
{
|
||||
// Do accounting stuff here
|
||||
Enqueue(req);
|
||||
if (m_running)
|
||||
{
|
||||
// delay the enqueueing for 100ms. There's no need to have the event
|
||||
// actively on the queue
|
||||
Timer t = new Timer(self => {
|
||||
((Timer)self).Dispose();
|
||||
m_requests.Enqueue(req);
|
||||
});
|
||||
|
||||
t.Change(100, Timeout.Infinite);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void Enqueue(PollServiceHttpRequest req)
|
||||
{
|
||||
lock (m_requests)
|
||||
m_requests.Enqueue(req);
|
||||
if (m_running)
|
||||
{
|
||||
if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.LongPoll)
|
||||
{
|
||||
lock (m_longPollRequests)
|
||||
m_longPollRequests.Add(req);
|
||||
}
|
||||
else
|
||||
m_requests.Enqueue(req);
|
||||
}
|
||||
}
|
||||
|
||||
public void ThreadStart()
|
||||
private void CheckLongPollThreads()
|
||||
{
|
||||
// The only purpose of this thread is to check the EQs for events.
|
||||
// If there are events, that thread will be placed in the "ready-to-serve" queue, m_requests.
|
||||
// If there are no events, that thread will be back to its "waiting" queue, m_longPollRequests.
|
||||
// All other types of tasks (Inventory handlers, http-in, etc) don't have the long-poll nature,
|
||||
// so if they aren't ready to be served by a worker thread (no events), they are placed
|
||||
// directly back in the "ready-to-serve" queue by the worker thread.
|
||||
while (m_running)
|
||||
{
|
||||
Thread.Sleep(500);
|
||||
Watchdog.UpdateThread();
|
||||
ProcessQueuedRequests();
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessQueuedRequests()
|
||||
{
|
||||
lock (m_requests)
|
||||
{
|
||||
if (m_requests.Count == 0)
|
||||
return;
|
||||
|
||||
// m_log.DebugFormat("[POLL SERVICE REQUEST MANAGER]: Processing {0} requests", m_requests.Count);
|
||||
|
||||
int reqperthread = (int) (m_requests.Count/m_WorkerThreadCount) + 1;
|
||||
|
||||
// For Each WorkerThread
|
||||
for (int tc = 0; tc < m_WorkerThreadCount && m_requests.Count > 0; tc++)
|
||||
// List<PollServiceHttpRequest> not_ready = new List<PollServiceHttpRequest>();
|
||||
lock (m_longPollRequests)
|
||||
{
|
||||
//Loop over number of requests each thread handles.
|
||||
for (int i = 0; i < reqperthread && m_requests.Count > 0; i++)
|
||||
if (m_longPollRequests.Count > 0 && m_running)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_PollServiceWorkerThreads[tc].Enqueue((PollServiceHttpRequest)m_requests.Dequeue());
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
// The queue is empty, we did our calculations wrong!
|
||||
return;
|
||||
}
|
||||
|
||||
List<PollServiceHttpRequest> ready = m_longPollRequests.FindAll(req =>
|
||||
(req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id) || // there are events in this EQ
|
||||
(Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms) // no events, but timeout
|
||||
);
|
||||
|
||||
ready.ForEach(req =>
|
||||
{
|
||||
m_requests.Enqueue(req);
|
||||
m_longPollRequests.Remove(req);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
m_running = false;
|
||||
|
||||
foreach (object o in m_requests)
|
||||
{
|
||||
PollServiceHttpRequest req = (PollServiceHttpRequest) o;
|
||||
PollServiceWorkerThread.DoHTTPGruntWork(
|
||||
m_server, req, req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
|
||||
}
|
||||
|
||||
m_requests.Clear();
|
||||
// m_timeout = -10000; // cause all to expire
|
||||
Thread.Sleep(1000); // let the world move
|
||||
|
||||
foreach (Thread t in m_workerThreads)
|
||||
Watchdog.AbortThread(t.ManagedThreadId);
|
||||
|
||||
PollServiceHttpRequest wreq;
|
||||
|
||||
lock (m_longPollRequests)
|
||||
{
|
||||
t.Abort();
|
||||
if (m_longPollRequests.Count > 0 && m_running)
|
||||
m_longPollRequests.ForEach(req => m_requests.Enqueue(req));
|
||||
}
|
||||
|
||||
while (m_requests.Count() > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
wreq = m_requests.Dequeue(0);
|
||||
wreq.DoHTTPGruntWork(
|
||||
m_server, wreq.PollServiceArgs.NoEvents(wreq.RequestID, wreq.PollServiceArgs.Id));
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
m_longPollRequests.Clear();
|
||||
m_requests.Clear();
|
||||
}
|
||||
|
||||
// work threads
|
||||
|
||||
private void PoolWorkerJob()
|
||||
{
|
||||
while (m_running)
|
||||
{
|
||||
PollServiceHttpRequest req = m_requests.Dequeue(5000);
|
||||
//m_log.WarnFormat("[YYY]: Dequeued {0}", (req == null ? "null" : req.PollServiceArgs.Type.ToString()));
|
||||
|
||||
Watchdog.UpdateThread();
|
||||
if (req != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id))
|
||||
{
|
||||
Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id);
|
||||
|
||||
if (responsedata == null)
|
||||
continue;
|
||||
|
||||
if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.LongPoll) // This is the event queue
|
||||
{
|
||||
try
|
||||
{
|
||||
req.DoHTTPGruntWork(m_server, responsedata);
|
||||
}
|
||||
catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream
|
||||
{
|
||||
// Ignore it, no need to reply
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_threadPool.QueueWorkItem(x =>
|
||||
{
|
||||
try
|
||||
{
|
||||
req.DoHTTPGruntWork(m_server, responsedata);
|
||||
}
|
||||
catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream
|
||||
{
|
||||
// Ignore it, no need to reply
|
||||
}
|
||||
|
||||
return null;
|
||||
}, null);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms)
|
||||
{
|
||||
req.DoHTTPGruntWork(
|
||||
m_server, req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
|
||||
}
|
||||
else
|
||||
{
|
||||
ReQueueEvent(req);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("Exception in poll service thread: " + e.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,165 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* 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 the OpenSimulator Project 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 DEVELOPERS ``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 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using HttpServer;
|
||||
using OpenMetaverse;
|
||||
using System.Reflection;
|
||||
using log4net;
|
||||
using OpenSim.Framework.Monitoring;
|
||||
|
||||
namespace OpenSim.Framework.Servers.HttpServer
|
||||
{
|
||||
public delegate void ReQueuePollServiceItem(PollServiceHttpRequest req);
|
||||
|
||||
public class PollServiceWorkerThread
|
||||
{
|
||||
private static readonly ILog m_log =
|
||||
LogManager.GetLogger(
|
||||
MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
public event ReQueuePollServiceItem ReQueue;
|
||||
|
||||
private readonly BaseHttpServer m_server;
|
||||
private BlockingQueue<PollServiceHttpRequest> m_request;
|
||||
private bool m_running = true;
|
||||
private int m_timeout = 250;
|
||||
|
||||
public PollServiceWorkerThread(BaseHttpServer pSrv, int pTimeout)
|
||||
{
|
||||
m_request = new BlockingQueue<PollServiceHttpRequest>();
|
||||
m_server = pSrv;
|
||||
m_timeout = pTimeout;
|
||||
}
|
||||
|
||||
public void ThreadStart()
|
||||
{
|
||||
Run();
|
||||
}
|
||||
|
||||
public void Run()
|
||||
{
|
||||
while (m_running)
|
||||
{
|
||||
PollServiceHttpRequest req = m_request.Dequeue();
|
||||
|
||||
Watchdog.UpdateThread();
|
||||
|
||||
try
|
||||
{
|
||||
if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id))
|
||||
{
|
||||
StreamReader str;
|
||||
try
|
||||
{
|
||||
str = new StreamReader(req.Request.Body);
|
||||
}
|
||||
catch (System.ArgumentException)
|
||||
{
|
||||
// Stream was not readable means a child agent
|
||||
// was closed due to logout, leaving the
|
||||
// Event Queue request orphaned.
|
||||
continue;
|
||||
}
|
||||
|
||||
Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id, str.ReadToEnd());
|
||||
DoHTTPGruntWork(m_server, req, responsedata);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((Environment.TickCount - req.RequestTime) > m_timeout)
|
||||
{
|
||||
DoHTTPGruntWork(
|
||||
m_server,
|
||||
req,
|
||||
req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
|
||||
}
|
||||
else
|
||||
{
|
||||
ReQueuePollServiceItem reQueueItem = ReQueue;
|
||||
if (reQueueItem != null)
|
||||
reQueueItem(req);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("Exception in poll service thread: " + e.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void Enqueue(PollServiceHttpRequest pPollServiceHttpRequest)
|
||||
{
|
||||
m_request.Enqueue(pPollServiceHttpRequest);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// FIXME: This should be part of BaseHttpServer
|
||||
/// </summary>
|
||||
internal static void DoHTTPGruntWork(BaseHttpServer server, PollServiceHttpRequest req, Hashtable responsedata)
|
||||
{
|
||||
OSHttpResponse response
|
||||
= new OSHttpResponse(new HttpResponse(req.HttpContext, req.Request), req.HttpContext);
|
||||
|
||||
byte[] buffer = server.DoHTTPGruntWork(responsedata, response);
|
||||
|
||||
response.SendChunked = false;
|
||||
response.ContentLength64 = buffer.Length;
|
||||
response.ContentEncoding = Encoding.UTF8;
|
||||
|
||||
try
|
||||
{
|
||||
response.OutputStream.Write(buffer, 0, buffer.Length);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
m_log.Warn(string.Format("[POLL SERVICE WORKER THREAD]: Error ", ex));
|
||||
}
|
||||
finally
|
||||
{
|
||||
//response.OutputStream.Close();
|
||||
try
|
||||
{
|
||||
response.OutputStream.Flush();
|
||||
response.Send();
|
||||
|
||||
//if (!response.KeepAlive && response.ReuseContext)
|
||||
// response.FreeContext();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Warn(String.Format("[POLL SERVICE WORKER THREAD]: Error ", e));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
{
|
||||
public delegate TResponse RestDeserialiseMethod<TRequest, TResponse>(TRequest request);
|
||||
|
||||
public class RestDeserialiseHandler<TRequest, TResponse> : BaseRequestHandler, IStreamHandler
|
||||
public class RestDeserialiseHandler<TRequest, TResponse> : BaseOutputStreamHandler, IStreamHandler
|
||||
where TRequest : new()
|
||||
{
|
||||
private RestDeserialiseMethod<TRequest, TResponse> m_method;
|
||||
@@ -48,7 +48,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
m_method = method;
|
||||
}
|
||||
|
||||
public void Handle(string path, Stream request, Stream responseStream,
|
||||
protected override void ProcessRequest(string path, Stream request, Stream responseStream,
|
||||
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||
{
|
||||
TRequest deserial;
|
||||
|
||||
@@ -183,7 +183,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
|
||||
public delegate bool CheckIdentityMethod(string sid, string aid);
|
||||
|
||||
public class RestDeserialiseSecureHandler<TRequest, TResponse> : BaseRequestHandler, IStreamHandler
|
||||
public class RestDeserialiseSecureHandler<TRequest, TResponse> : BaseOutputStreamHandler, IStreamHandler
|
||||
where TRequest : new()
|
||||
{
|
||||
private static readonly ILog m_log
|
||||
@@ -201,7 +201,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
m_method = method;
|
||||
}
|
||||
|
||||
public void Handle(string path, Stream request, Stream responseStream,
|
||||
protected override void ProcessRequest(string path, Stream request, Stream responseStream,
|
||||
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||
{
|
||||
RestSessionObject<TRequest> deserial = default(RestSessionObject<TRequest>);
|
||||
@@ -237,7 +237,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
|
||||
public delegate bool CheckTrustedSourceMethod(IPEndPoint peer);
|
||||
|
||||
public class RestDeserialiseTrustedHandler<TRequest, TResponse> : BaseRequestHandler, IStreamHandler
|
||||
public class RestDeserialiseTrustedHandler<TRequest, TResponse> : BaseOutputStreamHandler, IStreamHandler
|
||||
where TRequest : new()
|
||||
{
|
||||
private static readonly ILog m_log
|
||||
@@ -260,7 +260,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
m_method = method;
|
||||
}
|
||||
|
||||
public void Handle(string path, Stream request, Stream responseStream,
|
||||
protected override void ProcessRequest(string path, Stream request, Stream responseStream,
|
||||
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||
{
|
||||
TRequest deserial = default(TRequest);
|
||||
@@ -292,6 +292,5 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
serializer.Serialize(xmlWriter, response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
m_restMethod = restMethod;
|
||||
}
|
||||
|
||||
public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||
protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||
{
|
||||
Encoding encoding = Encoding.UTF8;
|
||||
StreamReader streamReader = new StreamReader(request, encoding);
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
/// <summary>
|
||||
/// This is a regular HTTP Request... This may be removed in the future.
|
||||
/// </summary>
|
||||
public event RegularHttpRequestDelegate OnRegularHttpRequest;
|
||||
// public event RegularHttpRequestDelegate OnRegularHttpRequest;
|
||||
|
||||
/// <summary>
|
||||
/// When the upgrade from a HTTP request to a Websocket is completed, this will be fired
|
||||
@@ -304,15 +304,14 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
if (d != null)
|
||||
d(this, new UpgradeCompletedEventArgs());
|
||||
}
|
||||
catch (IOException fail)
|
||||
catch (IOException)
|
||||
{
|
||||
Close(string.Empty);
|
||||
}
|
||||
catch (ObjectDisposedException fail)
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
Close(string.Empty);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -414,8 +413,6 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
_socketState.Header = pheader;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (_socketState.FrameComplete)
|
||||
{
|
||||
ProcessFrame(_socketState);
|
||||
@@ -424,7 +421,6 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
_socketState.ExpectedBytes = 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -457,8 +453,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
_socketState.ReceivedBytes.Clear();
|
||||
_socketState.ExpectedBytes = 0;
|
||||
// do some processing
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
if (offset > 0)
|
||||
@@ -477,13 +472,12 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
{
|
||||
// We can't read the stream anymore...
|
||||
}
|
||||
|
||||
}
|
||||
catch (IOException fail)
|
||||
catch (IOException)
|
||||
{
|
||||
Close(string.Empty);
|
||||
}
|
||||
catch (ObjectDisposedException fail)
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
Close(string.Empty);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user