Compare commits
416 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
511122834b | ||
|
|
4830431eb0 | ||
|
|
a7e7bed660 | ||
|
|
84a149ecbf | ||
|
|
571a75f934 | ||
|
|
0094971186 | ||
|
|
1bd89ac287 | ||
|
|
6221356712 | ||
|
|
67ffb64764 | ||
|
|
f83343d302 | ||
|
|
8fdf70b87e | ||
|
|
766a31431e | ||
|
|
d0c1780839 | ||
|
|
acfe603a5f | ||
|
|
d82d6bb1ec | ||
|
|
5ca7395e17 | ||
|
|
3e1ca2bd21 | ||
|
|
f106ba87ca | ||
|
|
a27c2432bb | ||
|
|
dbdcf2d995 | ||
|
|
daf44cc65e | ||
|
|
ff8a768258 | ||
|
|
2eade55471 | ||
|
|
8b5e2f2cd2 | ||
|
|
75f63ecfcd | ||
|
|
e7ea053c4a | ||
|
|
1df58d04b1 | ||
|
|
75fdd6054d | ||
|
|
f76cc6036e | ||
|
|
31246ecd04 | ||
|
|
85593d8d25 | ||
|
|
083eb7679b | ||
|
|
44580e2233 | ||
|
|
42bdf44658 | ||
|
|
970249a3c7 | ||
|
|
8996ac1a9c | ||
|
|
2cd95fac73 | ||
|
|
b16bc7b01c | ||
|
|
b704de9bf8 | ||
|
|
585d0800dd | ||
|
|
70b51f12cd | ||
|
|
d6d82dbd3c | ||
|
|
e24edada24 | ||
|
|
253f8de8cd | ||
|
|
babfbe8d6d | ||
|
|
4664090b34 | ||
|
|
b22c92368f | ||
|
|
32ddfc2740 | ||
|
|
732554be04 | ||
|
|
f384a6291e | ||
|
|
8de5c29e2c | ||
|
|
7889e7757a | ||
|
|
2dc92e7de1 | ||
|
|
a37c59b43e | ||
|
|
cbdfe96905 | ||
|
|
4c0ec86176 | ||
|
|
e2b3b7a2ae | ||
|
|
8502517d80 | ||
|
|
c01db5fbdd | ||
|
|
c6dea6ee78 | ||
|
|
35a6361b24 | ||
|
|
07d7a5fd76 | ||
|
|
c06a9ffe5c | ||
|
|
f1267730ef | ||
|
|
979b17165b | ||
|
|
b6f10780c2 | ||
|
|
03b2b5b77b | ||
|
|
6bdef1f70b | ||
|
|
3a9a8d2113 | ||
|
|
83c113896e | ||
|
|
997700c4aa | ||
|
|
ac0a527976 | ||
|
|
8999f06025 | ||
|
|
ddcbd4bb7d | ||
|
|
3ce46adb2a | ||
|
|
f4d82a56f4 | ||
|
|
7dbc93c62a | ||
|
|
1d2466889a | ||
|
|
845d2b193a | ||
|
|
69ec85f491 | ||
|
|
2603a2891b | ||
|
|
f99dae03cb | ||
|
|
60cf42cb8d | ||
|
|
3f0fa9f707 | ||
|
|
53de6d94ea | ||
|
|
07d6a0385f | ||
|
|
2d7adcb22f | ||
|
|
3c85afbb43 | ||
|
|
dacc20ee48 | ||
|
|
b29e9d37e7 | ||
|
|
8bcf753127 | ||
|
|
6e39cc316f | ||
|
|
e34385634b | ||
|
|
c5eabb28b4 | ||
|
|
5827b6e1aa | ||
|
|
cf2cdc191d | ||
|
|
7c54630a2d | ||
|
|
30b3657a66 | ||
|
|
67195618d5 | ||
|
|
3dbf4a1002 | ||
|
|
e0b457d3c3 | ||
|
|
d09c35f506 | ||
|
|
995314f91f | ||
|
|
4781297b4e | ||
|
|
6d83f3f021 | ||
|
|
e1120cb74d | ||
|
|
8755aeb348 | ||
|
|
f6fdfd16f5 | ||
|
|
455d36c4c7 | ||
|
|
b2a1348adc | ||
|
|
6aee08ac3c | ||
|
|
dff0fb5690 | ||
|
|
f3cc20050e | ||
|
|
c6a6631efc | ||
|
|
993bcec088 | ||
|
|
0971c7ae77 | ||
|
|
9a7d0e489c | ||
|
|
48ee73bfa7 | ||
|
|
725751fd6c | ||
|
|
663059ac5c | ||
|
|
ec5f17b2ce | ||
|
|
b05cb3b2bf | ||
|
|
a97f6f8668 | ||
|
|
08874d6b9e | ||
|
|
04619a9b13 | ||
|
|
b858be345a | ||
|
|
dc74a50225 | ||
|
|
c7ded0618c | ||
|
|
5f0d54c209 | ||
|
|
b781a23c44 | ||
|
|
9c3c9b7f5f | ||
|
|
76bd2e2d72 | ||
|
|
3dbe7313d1 | ||
|
|
1a2627031d | ||
|
|
9bd6271570 | ||
|
|
01cb8033a4 | ||
|
|
a89c56dcf1 | ||
|
|
9c65207936 | ||
|
|
431156f6c4 | ||
|
|
5f15ee95dc | ||
|
|
fc9f50d940 | ||
|
|
4035badd20 | ||
|
|
9643915093 | ||
|
|
857f24a5e2 | ||
|
|
5ce5ce6edb | ||
|
|
4cbadc3c49 | ||
|
|
56f565b601 | ||
|
|
a8c0e16e47 | ||
|
|
aa521fb385 | ||
|
|
0882cf0fc3 | ||
|
|
0dd9a68eb7 | ||
|
|
1b2830b929 | ||
|
|
60e4ce20b8 | ||
|
|
85824d2cd9 | ||
|
|
ec32c1d4b6 | ||
|
|
f0c0376660 | ||
|
|
5cd7bc2848 | ||
|
|
c7a8afbb8d | ||
|
|
6a24515269 | ||
|
|
c34e6f25b1 | ||
|
|
1a623bb266 | ||
|
|
0fbfef9649 | ||
|
|
050617ae0e | ||
|
|
04f4dd3dc7 | ||
|
|
2be786709b | ||
|
|
61c20bd06a | ||
|
|
065c5839b5 | ||
|
|
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 |
@@ -65,6 +65,7 @@ what it is today.
|
||||
* A_Biondi
|
||||
* alex_carnell
|
||||
* Alan Webb (IBM)
|
||||
* Aleric
|
||||
* Allen Kerensky
|
||||
* BigFootAg
|
||||
* BlueWall Slade
|
||||
@@ -86,6 +87,7 @@ what it is today.
|
||||
* Garmin Kawaguichi
|
||||
* Gerhard
|
||||
* Godfrey
|
||||
* Greg C.
|
||||
* Grumly57
|
||||
* GuduleLapointe
|
||||
* Ewe Loon
|
||||
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
}
|
||||
@@ -907,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));
|
||||
}
|
||||
@@ -1005,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);
|
||||
@@ -1189,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
|
||||
@@ -1228,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);
|
||||
|
||||
@@ -1279,8 +1278,7 @@ namespace OpenSim.Groups
|
||||
if (queue != null)
|
||||
{
|
||||
queue.Enqueue(queue.BuildEvent("AgentGroupDataUpdate", llDataStruct), GetRequestingAgentID(remoteClient));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void SendScenePresenceUpdate(UUID AgentID, string Title)
|
||||
@@ -1342,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();
|
||||
@@ -1402,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);
|
||||
|
||||
@@ -254,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);
|
||||
@@ -396,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
|
||||
@@ -590,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
|
||||
@@ -638,10 +623,13 @@ namespace OpenSim.Groups
|
||||
if (agent != null)
|
||||
break;
|
||||
}
|
||||
if (agent == null) // oops
|
||||
return AgentID.ToString();
|
||||
if (agent != null)
|
||||
return Util.ProduceUserUniversalIdentifier(agent);
|
||||
|
||||
// we don't know anything about this foreign user
|
||||
// try asking the user management module, which may know more
|
||||
return m_UserManagement.GetUserUUI(AgentID);
|
||||
|
||||
return Util.ProduceUserUniversalIdentifier(agent);
|
||||
}
|
||||
|
||||
private string AgentUUIForOutside(string AgentIDStr)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ using Mono.Addins;
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion("0.7.6.*")]
|
||||
[assembly: AssemblyVersion("0.8.0.*")]
|
||||
|
||||
[assembly: Addin("OpenSim.Groups", "0.1")]
|
||||
[assembly: AddinDependency("OpenSim", "0.5")]
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -740,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
|
||||
|
||||
@@ -255,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))
|
||||
|
||||
@@ -30,7 +30,7 @@ using Mono.Addins;
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion("0.7.6.*")]
|
||||
[assembly: AssemblyVersion("0.8.0.*")]
|
||||
|
||||
[assembly: Addin("OpenSim.OfflineIM", "0.1")]
|
||||
[assembly: AddinDependency("OpenSim", "0.5")]
|
||||
|
||||
@@ -62,4 +62,4 @@ using System.Runtime.InteropServices;
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("0.7.6.*")]
|
||||
|
||||
[assembly : AssemblyVersion("0.7.6.*")]
|
||||
[assembly : AssemblyVersion("0.8.0.*")]
|
||||
|
||||
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion("0.7.6.*")]
|
||||
[assembly: AssemblyVersion("0.8.0.*")]
|
||||
|
||||
|
||||
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion("0.7.6.*")]
|
||||
[assembly: AssemblyVersion("0.8.0.*")]
|
||||
|
||||
|
||||
@@ -327,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");
|
||||
}
|
||||
@@ -352,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");
|
||||
}
|
||||
|
||||
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion("0.7.6.*")]
|
||||
[assembly: AssemblyVersion("0.8.0.*")]
|
||||
|
||||
|
||||
@@ -81,6 +81,7 @@ namespace OpenSim.Data
|
||||
bool Delete(UUID regionID);
|
||||
|
||||
List<RegionData> GetDefaultRegions(UUID scopeID);
|
||||
List<RegionData> GetDefaultHypergridRegions(UUID scopeID);
|
||||
List<RegionData> GetFallbackRegions(UUID scopeID, int x, int y);
|
||||
List<RegionData> GetHyperlinks(UUID scopeID);
|
||||
}
|
||||
|
||||
@@ -315,6 +315,11 @@ namespace OpenSim.Data.MSSQL
|
||||
return Get((int)RegionFlags.DefaultRegion, scopeID);
|
||||
}
|
||||
|
||||
public List<RegionData> GetDefaultHypergridRegions(UUID scopeID)
|
||||
{
|
||||
return Get((int)RegionFlags.DefaultHGRegion, scopeID);
|
||||
}
|
||||
|
||||
public List<RegionData> GetFallbackRegions(UUID scopeID, int x, int y)
|
||||
{
|
||||
List<RegionData> regions = Get((int)RegionFlags.FallbackRegion, scopeID);
|
||||
|
||||
@@ -351,7 +351,7 @@ IF EXISTS (SELECT UUID FROM prims WHERE UUID = @UUID)
|
||||
ScriptAccessPin = @ScriptAccessPin, AllowedDrop = @AllowedDrop, DieAtEdge = @DieAtEdge, SalePrice = @SalePrice,
|
||||
SaleType = @SaleType, ColorR = @ColorR, ColorG = @ColorG, ColorB = @ColorB, ColorA = @ColorA, ParticleSystem = @ParticleSystem,
|
||||
ClickAction = @ClickAction, Material = @Material, CollisionSound = @CollisionSound, CollisionSoundVolume = @CollisionSoundVolume, PassTouches = @PassTouches,
|
||||
LinkNumber = @LinkNumber, MediaURL = @MediaURL, DynAttrs = @DynAttrs,
|
||||
LinkNumber = @LinkNumber, MediaURL = @MediaURL, AttachedPosX = @AttachedPosX, AttachedPosY = @AttachedPosY, AttachedPosZ = @AttachedPosZ, DynAttrs = @DynAttrs,
|
||||
PhysicsShapeType = @PhysicsShapeType, Density = @Density, GravityModifier = @GravityModifier, Friction = @Friction, Restitution = @Restitution
|
||||
WHERE UUID = @UUID
|
||||
END
|
||||
@@ -367,7 +367,7 @@ ELSE
|
||||
PayPrice, PayButton1, PayButton2, PayButton3, PayButton4, LoopedSound, LoopedSoundGain, TextureAnimation, OmegaX,
|
||||
OmegaY, OmegaZ, CameraEyeOffsetX, CameraEyeOffsetY, CameraEyeOffsetZ, CameraAtOffsetX, CameraAtOffsetY, CameraAtOffsetZ,
|
||||
ForceMouselook, ScriptAccessPin, AllowedDrop, DieAtEdge, SalePrice, SaleType, ColorR, ColorG, ColorB, ColorA,
|
||||
ParticleSystem, ClickAction, Material, CollisionSound, CollisionSoundVolume, PassTouches, LinkNumber, MediaURL, DynAttrs,
|
||||
ParticleSystem, ClickAction, Material, CollisionSound, CollisionSoundVolume, PassTouches, LinkNumber, MediaURL, AttachedPosX, AttachedPosY, AttachedPosZ, DynAttrs,
|
||||
PhysicsShapeType, Density, GravityModifier, Friction, Restitution
|
||||
) VALUES (
|
||||
@UUID, @CreationDate, @Name, @Text, @Description, @SitName, @TouchName, @ObjectFlags, @OwnerMask, @NextOwnerMask, @GroupMask,
|
||||
@@ -378,7 +378,7 @@ ELSE
|
||||
@PayPrice, @PayButton1, @PayButton2, @PayButton3, @PayButton4, @LoopedSound, @LoopedSoundGain, @TextureAnimation, @OmegaX,
|
||||
@OmegaY, @OmegaZ, @CameraEyeOffsetX, @CameraEyeOffsetY, @CameraEyeOffsetZ, @CameraAtOffsetX, @CameraAtOffsetY, @CameraAtOffsetZ,
|
||||
@ForceMouselook, @ScriptAccessPin, @AllowedDrop, @DieAtEdge, @SalePrice, @SaleType, @ColorR, @ColorG, @ColorB, @ColorA,
|
||||
@ParticleSystem, @ClickAction, @Material, @CollisionSound, @CollisionSoundVolume, @PassTouches, @LinkNumber, @MediaURL, @DynAttrs,
|
||||
@ParticleSystem, @ClickAction, @Material, @CollisionSound, @CollisionSoundVolume, @PassTouches, @LinkNumber, @MediaURL, @AttachedPosX, @AttachedPosY, @AttachedPosZ, @DynAttrs,
|
||||
@PhysicsShapeType, @Density, @GravityModifier, @Friction, @Restitution
|
||||
)
|
||||
END";
|
||||
@@ -1695,6 +1695,12 @@ VALUES
|
||||
if (!(primRow["MediaURL"] is System.DBNull))
|
||||
prim.MediaUrl = (string)primRow["MediaURL"];
|
||||
|
||||
if (!(primRow["AttachedPosX"] is System.DBNull))
|
||||
prim.AttachedPos = new Vector3(
|
||||
Convert.ToSingle(primRow["AttachedPosX"]),
|
||||
Convert.ToSingle(primRow["AttachedPosY"]),
|
||||
Convert.ToSingle(primRow["AttachedPosZ"]));
|
||||
|
||||
if (!(primRow["DynAttrs"] is System.DBNull))
|
||||
prim.DynAttrs = DAMap.FromXml((string)primRow["DynAttrs"]);
|
||||
else
|
||||
@@ -2099,7 +2105,10 @@ VALUES
|
||||
parameters.Add(_Database.CreateParameter("PassTouches", 0));
|
||||
parameters.Add(_Database.CreateParameter("LinkNumber", prim.LinkNum));
|
||||
parameters.Add(_Database.CreateParameter("MediaURL", prim.MediaUrl));
|
||||
|
||||
parameters.Add(_Database.CreateParameter("AttachedPosX", prim.AttachedPos.X));
|
||||
parameters.Add(_Database.CreateParameter("AttachedPosY", prim.AttachedPos.Y));
|
||||
parameters.Add(_Database.CreateParameter("AttachedPosZ", prim.AttachedPos.Z));
|
||||
|
||||
if (prim.DynAttrs.CountNamespaces > 0)
|
||||
parameters.Add(_Database.CreateParameter("DynAttrs", prim.DynAttrs.ToXml()));
|
||||
else
|
||||
|
||||
@@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
|
||||
[assembly : AssemblyVersion("0.7.6.*")]
|
||||
[assembly : AssemblyVersion("0.8.0.*")]
|
||||
|
||||
|
||||
@@ -1168,3 +1168,15 @@ ALTER TABLE prims ADD `Friction` double NOT NULL default '0.6';
|
||||
ALTER TABLE prims ADD `Restitution` double NOT NULL default '0.5';
|
||||
|
||||
COMMIT
|
||||
|
||||
:VERSION 40 #---------------- Save Attachment info
|
||||
|
||||
BEGIN TRANSACTION
|
||||
|
||||
ALTER TABLE prims ADD AttachedPosX float(53) default 0.0;
|
||||
ALTER TABLE prims ADD AttachedPosY float(53) default 0.0;
|
||||
ALTER TABLE prims ADD AttachedPosZ float(53) default 0.0;
|
||||
ALTER TABLE primshapes ADD LastAttachPoint int not null default 0;
|
||||
|
||||
COMMIT
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -310,6 +310,11 @@ namespace OpenSim.Data.MySQL
|
||||
return Get((int)RegionFlags.DefaultRegion, scopeID);
|
||||
}
|
||||
|
||||
public List<RegionData> GetDefaultHypergridRegions(UUID scopeID)
|
||||
{
|
||||
return Get((int)RegionFlags.DefaultHGRegion, scopeID);
|
||||
}
|
||||
|
||||
public List<RegionData> GetFallbackRegions(UUID scopeID, int x, int y)
|
||||
{
|
||||
List<RegionData> regions = Get((int)RegionFlags.FallbackRegion, scopeID);
|
||||
|
||||
@@ -173,7 +173,8 @@ namespace OpenSim.Data.MySQL
|
||||
"ParticleSystem, ClickAction, Material, " +
|
||||
"CollisionSound, CollisionSoundVolume, " +
|
||||
"PassTouches, " +
|
||||
"LinkNumber, MediaURL, KeyframeMotion, " +
|
||||
"LinkNumber, MediaURL, AttachedPosX, " +
|
||||
"AttachedPosY, AttachedPosZ, KeyframeMotion, " +
|
||||
"PhysicsShapeType, Density, GravityModifier, " +
|
||||
"Friction, Restitution, DynAttrs " +
|
||||
") values (" + "?UUID, " +
|
||||
@@ -208,7 +209,8 @@ namespace OpenSim.Data.MySQL
|
||||
"?ColorB, ?ColorA, ?ParticleSystem, " +
|
||||
"?ClickAction, ?Material, ?CollisionSound, " +
|
||||
"?CollisionSoundVolume, ?PassTouches, " +
|
||||
"?LinkNumber, ?MediaURL, ?KeyframeMotion, " +
|
||||
"?LinkNumber, ?MediaURL, ?AttachedPosX, " +
|
||||
"?AttachedPosY, ?AttachedPosZ, ?KeyframeMotion, " +
|
||||
"?PhysicsShapeType, ?Density, ?GravityModifier, " +
|
||||
"?Friction, ?Restitution, ?DynAttrs)";
|
||||
|
||||
@@ -227,7 +229,7 @@ namespace OpenSim.Data.MySQL
|
||||
"PathTaperX, PathTaperY, PathTwist, " +
|
||||
"PathTwistBegin, ProfileBegin, ProfileEnd, " +
|
||||
"ProfileCurve, ProfileHollow, Texture, " +
|
||||
"ExtraParams, State, Media) " +
|
||||
"ExtraParams, State, LastAttachPoint, Media) " +
|
||||
"values (?UUID, " +
|
||||
"?Shape, ?ScaleX, ?ScaleY, ?ScaleZ, " +
|
||||
"?PCode, ?PathBegin, ?PathEnd, " +
|
||||
@@ -239,7 +241,7 @@ namespace OpenSim.Data.MySQL
|
||||
"?PathTwistBegin, ?ProfileBegin, " +
|
||||
"?ProfileEnd, ?ProfileCurve, " +
|
||||
"?ProfileHollow, ?Texture, ?ExtraParams, " +
|
||||
"?State, ?Media)";
|
||||
"?State, ?LastAttachPoint, ?Media)";
|
||||
|
||||
FillShapeCommand(cmd, prim);
|
||||
|
||||
@@ -1303,7 +1305,16 @@ namespace OpenSim.Data.MySQL
|
||||
|
||||
if (!(row["MediaURL"] is System.DBNull))
|
||||
prim.MediaUrl = (string)row["MediaURL"];
|
||||
|
||||
|
||||
if (!(row["AttachedPosX"] is System.DBNull))
|
||||
{
|
||||
prim.AttachedPos = new Vector3(
|
||||
(float)(double)row["AttachedPosX"],
|
||||
(float)(double)row["AttachedPosY"],
|
||||
(float)(double)row["AttachedPosZ"]
|
||||
);
|
||||
}
|
||||
|
||||
if (!(row["DynAttrs"] is System.DBNull))
|
||||
prim.DynAttrs = DAMap.FromXml((string)row["DynAttrs"]);
|
||||
else
|
||||
@@ -1673,6 +1684,12 @@ namespace OpenSim.Data.MySQL
|
||||
|
||||
cmd.Parameters.AddWithValue("LinkNumber", prim.LinkNum);
|
||||
cmd.Parameters.AddWithValue("MediaURL", prim.MediaUrl);
|
||||
if (prim.AttachedPos != null)
|
||||
{
|
||||
cmd.Parameters.AddWithValue("AttachedPosX", (double)prim.AttachedPos.X);
|
||||
cmd.Parameters.AddWithValue("AttachedPosY", (double)prim.AttachedPos.Y);
|
||||
cmd.Parameters.AddWithValue("AttachedPosZ", (double)prim.AttachedPos.Z);
|
||||
}
|
||||
|
||||
if (prim.KeyframeMotion != null)
|
||||
cmd.Parameters.AddWithValue("KeyframeMotion", prim.KeyframeMotion.Serialize());
|
||||
@@ -1879,6 +1896,7 @@ namespace OpenSim.Data.MySQL
|
||||
s.ExtraParams = (byte[])row["ExtraParams"];
|
||||
|
||||
s.State = (byte)(int)row["State"];
|
||||
s.LastAttachPoint = (byte)(int)row["LastAttachPoint"];
|
||||
|
||||
if (!(row["Media"] is System.DBNull))
|
||||
s.Media = PrimitiveBaseShape.MediaList.FromXml((string)row["Media"]);
|
||||
@@ -1925,6 +1943,7 @@ namespace OpenSim.Data.MySQL
|
||||
cmd.Parameters.AddWithValue("Texture", s.TextureEntry);
|
||||
cmd.Parameters.AddWithValue("ExtraParams", s.ExtraParams);
|
||||
cmd.Parameters.AddWithValue("State", s.State);
|
||||
cmd.Parameters.AddWithValue("LastAttachPoint", s.LastAttachPoint);
|
||||
cmd.Parameters.AddWithValue("Media", null == s.Media ? null : s.Media.ToXml());
|
||||
}
|
||||
|
||||
|
||||
@@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
|
||||
[assembly : AssemblyVersion("0.7.6.*")]
|
||||
[assembly : AssemblyVersion("0.8.0.*")]
|
||||
|
||||
|
||||
@@ -930,3 +930,13 @@ BEGIN;
|
||||
ALTER TABLE prims ADD COLUMN `KeyframeMotion` blob;
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 49 #--------------------- Save attachment info
|
||||
|
||||
BEGIN;
|
||||
ALTER TABLE prims ADD COLUMN AttachedPosX double default 0;
|
||||
ALTER TABLE prims ADD COLUMN AttachedPosY double default 0;
|
||||
ALTER TABLE prims ADD COLUMN AttachedPosZ double default 0;
|
||||
ALTER TABLE primshapes ADD COLUMN LastAttachPoint int(4) not null default '0';
|
||||
COMMIT;
|
||||
|
||||
|
||||
@@ -239,6 +239,11 @@ namespace OpenSim.Data.Null
|
||||
return Get((int)RegionFlags.DefaultRegion, scopeID);
|
||||
}
|
||||
|
||||
public List<RegionData> GetDefaultHypergridRegions(UUID scopeID)
|
||||
{
|
||||
return Get((int)RegionFlags.DefaultHGRegion, scopeID);
|
||||
}
|
||||
|
||||
public List<RegionData> GetFallbackRegions(UUID scopeID, int x, int y)
|
||||
{
|
||||
List<RegionData> regions = Get((int)RegionFlags.FallbackRegion, scopeID);
|
||||
|
||||
@@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
|
||||
[assembly : AssemblyVersion("0.7.6.*")]
|
||||
[assembly : AssemblyVersion("0.8.0.*")]
|
||||
|
||||
|
||||
295
OpenSim/Data/PGSQL/PGSQLAssetData.cs
Normal file
295
OpenSim/Data/PGSQL/PGSQLAssetData.cs
Normal file
@@ -0,0 +1,295 @@
|
||||
/*
|
||||
* 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.Data;
|
||||
using System.Reflection;
|
||||
using System.Collections.Generic;
|
||||
using OpenMetaverse;
|
||||
using log4net;
|
||||
using OpenSim.Framework;
|
||||
using Npgsql;
|
||||
using NpgsqlTypes;
|
||||
|
||||
namespace OpenSim.Data.PGSQL
|
||||
{
|
||||
/// <summary>
|
||||
/// A PGSQL Interface for the Asset server
|
||||
/// </summary>
|
||||
public class PGSQLAssetData : AssetDataBase
|
||||
{
|
||||
private const string _migrationStore = "AssetStore";
|
||||
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private long m_ticksToEpoch;
|
||||
/// <summary>
|
||||
/// Database manager
|
||||
/// </summary>
|
||||
private PGSQLManager m_database;
|
||||
private string m_connectionString;
|
||||
|
||||
protected virtual Assembly Assembly
|
||||
{
|
||||
get { return GetType().Assembly; }
|
||||
}
|
||||
|
||||
#region IPlugin Members
|
||||
|
||||
override public void Dispose() { }
|
||||
|
||||
/// <summary>
|
||||
/// <para>Initialises asset interface</para>
|
||||
/// </summary>
|
||||
// [Obsolete("Cannot be default-initialized!")]
|
||||
override public void Initialise()
|
||||
{
|
||||
m_log.Info("[PGSQLAssetData]: " + Name + " cannot be default-initialized!");
|
||||
throw new PluginNotInitialisedException(Name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialises asset interface
|
||||
/// </summary>
|
||||
/// <para>
|
||||
/// a string instead of file, if someone writes the support
|
||||
/// </para>
|
||||
/// <param name="connectionString">connect string</param>
|
||||
override public void Initialise(string connectionString)
|
||||
{
|
||||
m_ticksToEpoch = new System.DateTime(1970, 1, 1).Ticks;
|
||||
|
||||
m_database = new PGSQLManager(connectionString);
|
||||
m_connectionString = connectionString;
|
||||
|
||||
//New migration to check for DB changes
|
||||
m_database.CheckMigration(_migrationStore);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Database provider version.
|
||||
/// </summary>
|
||||
override public string Version
|
||||
{
|
||||
get { return m_database.getVersion(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The name of this DB provider.
|
||||
/// </summary>
|
||||
override public string Name
|
||||
{
|
||||
get { return "PGSQL Asset storage engine"; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IAssetDataPlugin Members
|
||||
|
||||
/// <summary>
|
||||
/// Fetch Asset from m_database
|
||||
/// </summary>
|
||||
/// <param name="assetID">the asset UUID</param>
|
||||
/// <returns></returns>
|
||||
override public AssetBase GetAsset(UUID assetID)
|
||||
{
|
||||
string sql = "SELECT * FROM assets WHERE id = :id";
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
cmd.Parameters.Add(m_database.CreateParameter("id", assetID));
|
||||
conn.Open();
|
||||
using (NpgsqlDataReader reader = cmd.ExecuteReader())
|
||||
{
|
||||
if (reader.Read())
|
||||
{
|
||||
AssetBase asset = new AssetBase(
|
||||
DBGuid.FromDB(reader["id"]),
|
||||
(string)reader["name"],
|
||||
Convert.ToSByte(reader["assetType"]),
|
||||
reader["creatorid"].ToString()
|
||||
);
|
||||
// Region Main
|
||||
asset.Description = (string)reader["description"];
|
||||
asset.Local = Convert.ToBoolean(reader["local"]);
|
||||
asset.Temporary = Convert.ToBoolean(reader["temporary"]);
|
||||
asset.Flags = (AssetFlags)(Convert.ToInt32(reader["asset_flags"]));
|
||||
asset.Data = (byte[])reader["data"];
|
||||
return asset;
|
||||
}
|
||||
return null; // throw new Exception("No rows to return");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create asset in m_database
|
||||
/// </summary>
|
||||
/// <param name="asset">the asset</param>
|
||||
override public void StoreAsset(AssetBase asset)
|
||||
{
|
||||
|
||||
string sql =
|
||||
@"UPDATE assets set name = :name, description = :description, " + "\"assetType\" " + @" = :assetType,
|
||||
local = :local, temporary = :temporary, creatorid = :creatorid, data = :data
|
||||
WHERE id=:id;
|
||||
|
||||
INSERT INTO assets
|
||||
(id, name, description, " + "\"assetType\" " + @", local,
|
||||
temporary, create_time, access_time, creatorid, asset_flags, data)
|
||||
Select :id, :name, :description, :assetType, :local,
|
||||
:temporary, :create_time, :access_time, :creatorid, :asset_flags, :data
|
||||
Where not EXISTS(SELECT * FROM assets WHERE id=:id)
|
||||
";
|
||||
|
||||
string assetName = asset.Name;
|
||||
if (asset.Name.Length > 64)
|
||||
{
|
||||
assetName = asset.Name.Substring(0, 64);
|
||||
m_log.WarnFormat(
|
||||
"[ASSET DB]: Name '{0}' for asset {1} truncated from {2} to {3} characters on add",
|
||||
asset.Name, asset.ID, asset.Name.Length, assetName.Length);
|
||||
}
|
||||
|
||||
string assetDescription = asset.Description;
|
||||
if (asset.Description.Length > 64)
|
||||
{
|
||||
assetDescription = asset.Description.Substring(0, 64);
|
||||
m_log.WarnFormat(
|
||||
"[ASSET DB]: Description '{0}' for asset {1} truncated from {2} to {3} characters on add",
|
||||
asset.Description, asset.ID, asset.Description.Length, assetDescription.Length);
|
||||
}
|
||||
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
using (NpgsqlCommand command = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
int now = (int)((System.DateTime.Now.Ticks - m_ticksToEpoch) / 10000000);
|
||||
command.Parameters.Add(m_database.CreateParameter("id", asset.FullID));
|
||||
command.Parameters.Add(m_database.CreateParameter("name", assetName));
|
||||
command.Parameters.Add(m_database.CreateParameter("description", assetDescription));
|
||||
command.Parameters.Add(m_database.CreateParameter("assetType", asset.Type));
|
||||
command.Parameters.Add(m_database.CreateParameter("local", asset.Local));
|
||||
command.Parameters.Add(m_database.CreateParameter("temporary", asset.Temporary));
|
||||
command.Parameters.Add(m_database.CreateParameter("access_time", now));
|
||||
command.Parameters.Add(m_database.CreateParameter("create_time", now));
|
||||
command.Parameters.Add(m_database.CreateParameter("asset_flags", (int)asset.Flags));
|
||||
command.Parameters.Add(m_database.CreateParameter("creatorid", asset.Metadata.CreatorID));
|
||||
command.Parameters.Add(m_database.CreateParameter("data", asset.Data));
|
||||
conn.Open();
|
||||
try
|
||||
{
|
||||
command.ExecuteNonQuery();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
m_log.Error("[ASSET DB]: Error storing item :" + e.Message + " sql "+sql);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Commented out since currently unused - this probably should be called in GetAsset()
|
||||
// private void UpdateAccessTime(AssetBase asset)
|
||||
// {
|
||||
// using (AutoClosingSqlCommand cmd = m_database.Query("UPDATE assets SET access_time = :access_time WHERE id=:id"))
|
||||
// {
|
||||
// int now = (int)((System.DateTime.Now.Ticks - m_ticksToEpoch) / 10000000);
|
||||
// cmd.Parameters.AddWithValue(":id", asset.FullID.ToString());
|
||||
// cmd.Parameters.AddWithValue(":access_time", now);
|
||||
// try
|
||||
// {
|
||||
// cmd.ExecuteNonQuery();
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// m_log.Error(e.ToString());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Check if asset exist in m_database
|
||||
/// </summary>
|
||||
/// <param name="uuid"></param>
|
||||
/// <returns>true if exist.</returns>
|
||||
override public bool ExistsAsset(UUID uuid)
|
||||
{
|
||||
if (GetAsset(uuid) != null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of AssetMetadata objects. The list is a subset of
|
||||
/// the entire data set offset by <paramref name="start" /> containing
|
||||
/// <paramref name="count" /> elements.
|
||||
/// </summary>
|
||||
/// <param name="start">The number of results to discard from the total data set.</param>
|
||||
/// <param name="count">The number of rows the returned list should contain.</param>
|
||||
/// <returns>A list of AssetMetadata objects.</returns>
|
||||
public override List<AssetMetadata> FetchAssetMetadataSet(int start, int count)
|
||||
{
|
||||
List<AssetMetadata> retList = new List<AssetMetadata>(count);
|
||||
string sql = @" SELECT id, name, description, " + "\"assetType\"" + @", temporary, creatorid
|
||||
FROM assets
|
||||
order by id
|
||||
limit :stop
|
||||
offset :start;";
|
||||
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
cmd.Parameters.Add(m_database.CreateParameter("start", start));
|
||||
cmd.Parameters.Add(m_database.CreateParameter("stop", start + count - 1));
|
||||
conn.Open();
|
||||
using (NpgsqlDataReader reader = cmd.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
AssetMetadata metadata = new AssetMetadata();
|
||||
metadata.FullID = DBGuid.FromDB(reader["id"]);
|
||||
metadata.Name = (string)reader["name"];
|
||||
metadata.Description = (string)reader["description"];
|
||||
metadata.Type = Convert.ToSByte(reader["assetType"]);
|
||||
metadata.Temporary = Convert.ToBoolean(reader["temporary"]);
|
||||
metadata.CreatorID = (string)reader["creatorid"];
|
||||
retList.Add(metadata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retList;
|
||||
}
|
||||
|
||||
public override bool Delete(string id)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
254
OpenSim/Data/PGSQL/PGSQLAuthenticationData.cs
Normal file
254
OpenSim/Data/PGSQL/PGSQLAuthenticationData.cs
Normal file
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
* 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 OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Data;
|
||||
using Npgsql;
|
||||
using NpgsqlTypes;
|
||||
|
||||
namespace OpenSim.Data.PGSQL
|
||||
{
|
||||
public class PGSQLAuthenticationData : IAuthenticationData
|
||||
{
|
||||
private string m_Realm;
|
||||
private List<string> m_ColumnNames = null;
|
||||
private int m_LastExpire = 0;
|
||||
private string m_ConnectionString;
|
||||
private PGSQLManager m_database;
|
||||
|
||||
protected virtual Assembly Assembly
|
||||
{
|
||||
get { return GetType().Assembly; }
|
||||
}
|
||||
|
||||
public PGSQLAuthenticationData(string connectionString, string realm)
|
||||
{
|
||||
m_Realm = realm;
|
||||
m_ConnectionString = connectionString;
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
{
|
||||
conn.Open();
|
||||
Migration m = new Migration(conn, GetType().Assembly, "AuthStore");
|
||||
m_database = new PGSQLManager(m_ConnectionString);
|
||||
m.Update();
|
||||
}
|
||||
}
|
||||
|
||||
public AuthenticationData Get(UUID principalID)
|
||||
{
|
||||
AuthenticationData ret = new AuthenticationData();
|
||||
ret.Data = new Dictionary<string, object>();
|
||||
|
||||
string sql = string.Format("select * from {0} where uuid = :principalID", m_Realm);
|
||||
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
cmd.Parameters.Add(m_database.CreateParameter("principalID", principalID));
|
||||
conn.Open();
|
||||
using (NpgsqlDataReader result = cmd.ExecuteReader())
|
||||
{
|
||||
if (result.Read())
|
||||
{
|
||||
ret.PrincipalID = principalID;
|
||||
|
||||
if (m_ColumnNames == null)
|
||||
{
|
||||
m_ColumnNames = new List<string>();
|
||||
|
||||
DataTable schemaTable = result.GetSchemaTable();
|
||||
foreach (DataRow row in schemaTable.Rows)
|
||||
m_ColumnNames.Add(row["ColumnName"].ToString());
|
||||
}
|
||||
|
||||
foreach (string s in m_ColumnNames)
|
||||
{
|
||||
if (s == "UUID"||s == "uuid")
|
||||
continue;
|
||||
|
||||
ret.Data[s] = result[s].ToString();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool Store(AuthenticationData data)
|
||||
{
|
||||
if (data.Data.ContainsKey("UUID"))
|
||||
data.Data.Remove("UUID");
|
||||
if (data.Data.ContainsKey("uuid"))
|
||||
data.Data.Remove("uuid");
|
||||
|
||||
/*
|
||||
Dictionary<string, object> oAuth = new Dictionary<string, object>();
|
||||
|
||||
foreach (KeyValuePair<string, object> oDado in data.Data)
|
||||
{
|
||||
if (oDado.Key != oDado.Key.ToLower())
|
||||
{
|
||||
oAuth.Add(oDado.Key.ToLower(), oDado.Value);
|
||||
}
|
||||
}
|
||||
foreach (KeyValuePair<string, object> oDado in data.Data)
|
||||
{
|
||||
if (!oAuth.ContainsKey(oDado.Key.ToLower())) {
|
||||
oAuth.Add(oDado.Key.ToLower(), oDado.Value);
|
||||
}
|
||||
}
|
||||
*/
|
||||
string[] fields = new List<string>(data.Data.Keys).ToArray();
|
||||
StringBuilder updateBuilder = new StringBuilder();
|
||||
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand())
|
||||
{
|
||||
updateBuilder.AppendFormat("update {0} set ", m_Realm);
|
||||
|
||||
bool first = true;
|
||||
foreach (string field in fields)
|
||||
{
|
||||
if (!first)
|
||||
updateBuilder.Append(", ");
|
||||
updateBuilder.AppendFormat("\"{0}\" = :{0}",field);
|
||||
|
||||
first = false;
|
||||
|
||||
cmd.Parameters.Add(m_database.CreateParameter("" + field, data.Data[field]));
|
||||
}
|
||||
|
||||
updateBuilder.Append(" where uuid = :principalID");
|
||||
|
||||
cmd.CommandText = updateBuilder.ToString();
|
||||
cmd.Connection = conn;
|
||||
cmd.Parameters.Add(m_database.CreateParameter("principalID", data.PrincipalID));
|
||||
|
||||
conn.Open();
|
||||
if (cmd.ExecuteNonQuery() < 1)
|
||||
{
|
||||
StringBuilder insertBuilder = new StringBuilder();
|
||||
|
||||
insertBuilder.AppendFormat("insert into {0} (uuid, \"", m_Realm);
|
||||
insertBuilder.Append(String.Join("\", \"", fields));
|
||||
insertBuilder.Append("\") values (:principalID, :");
|
||||
insertBuilder.Append(String.Join(", :", fields));
|
||||
insertBuilder.Append(")");
|
||||
|
||||
cmd.CommandText = insertBuilder.ToString();
|
||||
|
||||
if (cmd.ExecuteNonQuery() < 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool SetDataItem(UUID principalID, string item, string value)
|
||||
{
|
||||
string sql = string.Format("update {0} set {1} = :{1} where uuid = :UUID", m_Realm, item);
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
cmd.Parameters.Add(m_database.CreateParameter("" + item, value));
|
||||
conn.Open();
|
||||
if (cmd.ExecuteNonQuery() > 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool SetToken(UUID principalID, string token, int lifetime)
|
||||
{
|
||||
if (System.Environment.TickCount - m_LastExpire > 30000)
|
||||
DoExpire();
|
||||
|
||||
string sql = "insert into tokens (uuid, token, validity) values (:principalID, :token, :lifetime)";
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
cmd.Parameters.Add(m_database.CreateParameter("principalID", principalID));
|
||||
cmd.Parameters.Add(m_database.CreateParameter("token", token));
|
||||
cmd.Parameters.Add(m_database.CreateParameter("lifetime", DateTime.Now.AddMinutes(lifetime)));
|
||||
conn.Open();
|
||||
|
||||
if (cmd.ExecuteNonQuery() > 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool CheckToken(UUID principalID, string token, int lifetime)
|
||||
{
|
||||
if (System.Environment.TickCount - m_LastExpire > 30000)
|
||||
DoExpire();
|
||||
|
||||
DateTime validDate = DateTime.Now.AddMinutes(lifetime);
|
||||
string sql = "update tokens set validity = :validDate where uuid = :principalID and token = :token and validity > (CURRENT_DATE + CURRENT_TIME)";
|
||||
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
cmd.Parameters.Add(m_database.CreateParameter("principalID", principalID));
|
||||
cmd.Parameters.Add(m_database.CreateParameter("token", token));
|
||||
cmd.Parameters.Add(m_database.CreateParameter("validDate", validDate));
|
||||
conn.Open();
|
||||
|
||||
if (cmd.ExecuteNonQuery() > 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void DoExpire()
|
||||
{
|
||||
DateTime currentDateTime = DateTime.Now;
|
||||
string sql = "delete from tokens where validity < :currentDateTime";
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
conn.Open();
|
||||
cmd.Parameters.Add(m_database.CreateParameter("currentDateTime", currentDateTime));
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
m_LastExpire = System.Environment.TickCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
72
OpenSim/Data/PGSQL/PGSQLAvatarData.cs
Normal file
72
OpenSim/Data/PGSQL/PGSQLAvatarData.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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.Reflection;
|
||||
using System.Threading;
|
||||
using log4net;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using Npgsql;
|
||||
using NpgsqlTypes;
|
||||
|
||||
|
||||
namespace OpenSim.Data.PGSQL
|
||||
{
|
||||
/// <summary>
|
||||
/// A PGSQL Interface for Avatar Storage
|
||||
/// </summary>
|
||||
public class PGSQLAvatarData : PGSQLGenericTableHandler<AvatarBaseData>,
|
||||
IAvatarData
|
||||
{
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
public PGSQLAvatarData(string connectionString, string realm) :
|
||||
base(connectionString, realm, "Avatar")
|
||||
{
|
||||
}
|
||||
|
||||
public bool Delete(UUID principalID, string name)
|
||||
{
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand())
|
||||
{
|
||||
|
||||
cmd.CommandText = String.Format("DELETE FROM {0} where \"PrincipalID\" = :PrincipalID and \"Name\" = :Name", m_Realm);
|
||||
cmd.Parameters.Add(m_database.CreateParameter("PrincipalID", principalID));
|
||||
cmd.Parameters.Add(m_database.CreateParameter("Name", name));
|
||||
cmd.Connection = conn;
|
||||
conn.Open();
|
||||
if (cmd.ExecuteNonQuery() > 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
602
OpenSim/Data/PGSQL/PGSQLEstateData.cs
Normal file
602
OpenSim/Data/PGSQL/PGSQLEstateData.cs
Normal file
@@ -0,0 +1,602 @@
|
||||
/*
|
||||
* 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.Reflection;
|
||||
using log4net;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using System.Data;
|
||||
using Npgsql;
|
||||
using NpgsqlTypes;
|
||||
|
||||
namespace OpenSim.Data.PGSQL
|
||||
{
|
||||
public class PGSQLEstateStore : IEstateDataStore
|
||||
{
|
||||
private const string _migrationStore = "EstateStore";
|
||||
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private PGSQLManager _Database;
|
||||
private string m_connectionString;
|
||||
private FieldInfo[] _Fields;
|
||||
private Dictionary<string, FieldInfo> _FieldMap = new Dictionary<string, FieldInfo>();
|
||||
|
||||
#region Public methods
|
||||
|
||||
public PGSQLEstateStore()
|
||||
{
|
||||
}
|
||||
|
||||
public PGSQLEstateStore(string connectionString)
|
||||
{
|
||||
Initialise(connectionString);
|
||||
}
|
||||
|
||||
protected virtual Assembly Assembly
|
||||
{
|
||||
get { return GetType().Assembly; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialises the estatedata class.
|
||||
/// </summary>
|
||||
/// <param name="connectionString">connectionString.</param>
|
||||
public void Initialise(string connectionString)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(connectionString))
|
||||
{
|
||||
m_connectionString = connectionString;
|
||||
_Database = new PGSQLManager(connectionString);
|
||||
}
|
||||
|
||||
//Migration settings
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
{
|
||||
conn.Open();
|
||||
Migration m = new Migration(conn, GetType().Assembly, "EstateStore");
|
||||
m.Update();
|
||||
}
|
||||
|
||||
//Interesting way to get parameters! Maybe implement that also with other types
|
||||
Type t = typeof(EstateSettings);
|
||||
_Fields = t.GetFields(BindingFlags.NonPublic |
|
||||
BindingFlags.Instance |
|
||||
BindingFlags.DeclaredOnly);
|
||||
|
||||
foreach (FieldInfo f in _Fields)
|
||||
{
|
||||
if (f.Name.Substring(0, 2) == "m_")
|
||||
_FieldMap[f.Name.Substring(2)] = f;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads the estate settings.
|
||||
/// </summary>
|
||||
/// <param name="regionID">region ID.</param>
|
||||
/// <returns></returns>
|
||||
public EstateSettings LoadEstateSettings(UUID regionID, bool create)
|
||||
{
|
||||
EstateSettings es = new EstateSettings();
|
||||
|
||||
string sql = "select estate_settings.\"" + String.Join("\",estate_settings.\"", FieldList) +
|
||||
"\" from estate_map left join estate_settings on estate_map.\"EstateID\" = estate_settings.\"EstateID\" " +
|
||||
" where estate_settings.\"EstateID\" is not null and \"RegionID\" = :RegionID";
|
||||
|
||||
bool insertEstate = false;
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
cmd.Parameters.Add(_Database.CreateParameter("RegionID", regionID));
|
||||
conn.Open();
|
||||
using (NpgsqlDataReader reader = cmd.ExecuteReader())
|
||||
{
|
||||
if (reader.Read())
|
||||
{
|
||||
foreach (string name in FieldList)
|
||||
{
|
||||
FieldInfo f = _FieldMap[name];
|
||||
object v = reader[name];
|
||||
if (f.FieldType == typeof(bool))
|
||||
{
|
||||
f.SetValue(es, v);
|
||||
}
|
||||
else if (f.FieldType == typeof(UUID))
|
||||
{
|
||||
UUID estUUID = UUID.Zero;
|
||||
|
||||
UUID.TryParse(v.ToString(), out estUUID);
|
||||
|
||||
f.SetValue(es, estUUID);
|
||||
}
|
||||
else if (f.FieldType == typeof(string))
|
||||
{
|
||||
f.SetValue(es, v.ToString());
|
||||
}
|
||||
else if (f.FieldType == typeof(UInt32))
|
||||
{
|
||||
f.SetValue(es, Convert.ToUInt32(v));
|
||||
}
|
||||
else if (f.FieldType == typeof(Single))
|
||||
{
|
||||
f.SetValue(es, Convert.ToSingle(v));
|
||||
}
|
||||
else
|
||||
f.SetValue(es, v);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
insertEstate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (insertEstate && create)
|
||||
{
|
||||
DoCreate(es);
|
||||
LinkRegion(regionID, (int)es.EstateID);
|
||||
}
|
||||
|
||||
LoadBanList(es);
|
||||
|
||||
es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers");
|
||||
es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users");
|
||||
es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups");
|
||||
|
||||
//Set event
|
||||
es.OnSave += StoreEstateSettings;
|
||||
return es;
|
||||
}
|
||||
|
||||
public EstateSettings CreateNewEstate()
|
||||
{
|
||||
EstateSettings es = new EstateSettings();
|
||||
es.OnSave += StoreEstateSettings;
|
||||
|
||||
DoCreate(es);
|
||||
|
||||
LoadBanList(es);
|
||||
|
||||
es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers");
|
||||
es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users");
|
||||
es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups");
|
||||
|
||||
return es;
|
||||
}
|
||||
|
||||
private void DoCreate(EstateSettings es)
|
||||
{
|
||||
List<string> names = new List<string>(FieldList);
|
||||
|
||||
names.Remove("EstateID");
|
||||
|
||||
string sql = string.Format("insert into estate_settings (\"{0}\") values ( :{1} )", String.Join("\",\"", names.ToArray()), String.Join(", :", names.ToArray()));
|
||||
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
using (NpgsqlCommand insertCommand = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
insertCommand.CommandText = sql;
|
||||
|
||||
foreach (string name in names)
|
||||
{
|
||||
insertCommand.Parameters.Add(_Database.CreateParameter("" + name, _FieldMap[name].GetValue(es)));
|
||||
}
|
||||
//NpgsqlParameter idParameter = new NpgsqlParameter("ID", SqlDbType.Int);
|
||||
//idParameter.Direction = ParameterDirection.Output;
|
||||
//insertCommand.Parameters.Add(idParameter);
|
||||
conn.Open();
|
||||
|
||||
es.EstateID = 100;
|
||||
|
||||
if (insertCommand.ExecuteNonQuery() > 0)
|
||||
{
|
||||
insertCommand.CommandText = "Select cast(lastval() as int) as ID ;";
|
||||
|
||||
using (NpgsqlDataReader result = insertCommand.ExecuteReader())
|
||||
{
|
||||
if (result.Read())
|
||||
{
|
||||
es.EstateID = (uint)result.GetInt32(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//TODO check if this is needed??
|
||||
es.Save();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores the estate settings.
|
||||
/// </summary>
|
||||
/// <param name="es">estate settings</param>
|
||||
public void StoreEstateSettings(EstateSettings es)
|
||||
{
|
||||
List<string> names = new List<string>(FieldList);
|
||||
|
||||
names.Remove("EstateID");
|
||||
|
||||
string sql = string.Format("UPDATE estate_settings SET ");
|
||||
foreach (string name in names)
|
||||
{
|
||||
sql += "\"" + name + "\" = :" + name + ", ";
|
||||
}
|
||||
sql = sql.Remove(sql.LastIndexOf(","));
|
||||
sql += " WHERE \"EstateID\" = :EstateID";
|
||||
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
foreach (string name in names)
|
||||
{
|
||||
cmd.Parameters.Add(_Database.CreateParameter("" + name, _FieldMap[name].GetValue(es)));
|
||||
}
|
||||
|
||||
cmd.Parameters.Add(_Database.CreateParameter("EstateID", es.EstateID));
|
||||
conn.Open();
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
SaveBanList(es);
|
||||
SaveUUIDList(es.EstateID, "estate_managers", es.EstateManagers);
|
||||
SaveUUIDList(es.EstateID, "estate_users", es.EstateAccess);
|
||||
SaveUUIDList(es.EstateID, "estate_groups", es.EstateGroups);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private methods
|
||||
|
||||
private string[] FieldList
|
||||
{
|
||||
get { return new List<string>(_FieldMap.Keys).ToArray(); }
|
||||
}
|
||||
|
||||
private void LoadBanList(EstateSettings es)
|
||||
{
|
||||
es.ClearBans();
|
||||
|
||||
string sql = "select \"bannedUUID\" from estateban where \"EstateID\" = :EstateID";
|
||||
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
NpgsqlParameter idParameter = new NpgsqlParameter("EstateID", DbType.Int32);
|
||||
idParameter.Value = es.EstateID;
|
||||
cmd.Parameters.Add(idParameter);
|
||||
conn.Open();
|
||||
using (NpgsqlDataReader reader = cmd.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
EstateBan eb = new EstateBan();
|
||||
|
||||
eb.BannedUserID = new UUID((Guid)reader["bannedUUID"]); //uuid;
|
||||
eb.BannedHostAddress = "0.0.0.0";
|
||||
eb.BannedHostIPMask = "0.0.0.0";
|
||||
es.AddBan(eb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private UUID[] LoadUUIDList(uint estateID, string table)
|
||||
{
|
||||
List<UUID> uuids = new List<UUID>();
|
||||
|
||||
string sql = string.Format("select uuid from {0} where \"EstateID\" = :EstateID", table);
|
||||
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
cmd.Parameters.Add(_Database.CreateParameter("EstateID", estateID));
|
||||
conn.Open();
|
||||
using (NpgsqlDataReader reader = cmd.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
uuids.Add(new UUID((Guid)reader["uuid"])); //uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return uuids.ToArray();
|
||||
}
|
||||
|
||||
private void SaveBanList(EstateSettings es)
|
||||
{
|
||||
//Delete first
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
{
|
||||
conn.Open();
|
||||
using (NpgsqlCommand cmd = conn.CreateCommand())
|
||||
{
|
||||
cmd.CommandText = "delete from estateban where \"EstateID\" = :EstateID";
|
||||
cmd.Parameters.AddWithValue("EstateID", (int)es.EstateID);
|
||||
cmd.ExecuteNonQuery();
|
||||
|
||||
//Insert after
|
||||
cmd.CommandText = "insert into estateban (\"EstateID\", \"bannedUUID\",\"bannedIp\", \"bannedIpHostMask\", \"bannedNameMask\") values ( :EstateID, :bannedUUID, '','','' )";
|
||||
cmd.Parameters.AddWithValue("bannedUUID", Guid.Empty);
|
||||
foreach (EstateBan b in es.EstateBans)
|
||||
{
|
||||
cmd.Parameters["bannedUUID"].Value = b.BannedUserID.Guid;
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveUUIDList(uint estateID, string table, UUID[] data)
|
||||
{
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
{
|
||||
conn.Open();
|
||||
using (NpgsqlCommand cmd = conn.CreateCommand())
|
||||
{
|
||||
cmd.Parameters.AddWithValue("EstateID", (int)estateID);
|
||||
cmd.CommandText = string.Format("delete from {0} where \"EstateID\" = :EstateID", table);
|
||||
cmd.ExecuteNonQuery();
|
||||
|
||||
cmd.CommandText = string.Format("insert into {0} (\"EstateID\", uuid) values ( :EstateID, :uuid )", table);
|
||||
cmd.Parameters.AddWithValue("uuid", Guid.Empty);
|
||||
foreach (UUID uuid in data)
|
||||
{
|
||||
cmd.Parameters["uuid"].Value = uuid.Guid; //.ToString(); //TODO check if this works
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public EstateSettings LoadEstateSettings(int estateID)
|
||||
{
|
||||
EstateSettings es = new EstateSettings();
|
||||
string sql = "select estate_settings.\"" + String.Join("\",estate_settings.\"", FieldList) + "\" from estate_settings where \"EstateID\" = :EstateID";
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
{
|
||||
conn.Open();
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("EstateID", (int)estateID);
|
||||
using (NpgsqlDataReader reader = cmd.ExecuteReader())
|
||||
{
|
||||
if (reader.Read())
|
||||
{
|
||||
foreach (string name in FieldList)
|
||||
{
|
||||
FieldInfo f = _FieldMap[name];
|
||||
object v = reader[name];
|
||||
if (f.FieldType == typeof(bool))
|
||||
{
|
||||
f.SetValue(es, Convert.ToInt32(v) != 0);
|
||||
}
|
||||
else if (f.FieldType == typeof(UUID))
|
||||
{
|
||||
f.SetValue(es, new UUID((Guid)v)); // uuid);
|
||||
}
|
||||
else if (f.FieldType == typeof(string))
|
||||
{
|
||||
f.SetValue(es, v.ToString());
|
||||
}
|
||||
else if (f.FieldType == typeof(UInt32))
|
||||
{
|
||||
f.SetValue(es, Convert.ToUInt32(v));
|
||||
}
|
||||
else if (f.FieldType == typeof(Single))
|
||||
{
|
||||
f.SetValue(es, Convert.ToSingle(v));
|
||||
}
|
||||
else
|
||||
f.SetValue(es, v);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
LoadBanList(es);
|
||||
|
||||
es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers");
|
||||
es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users");
|
||||
es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups");
|
||||
|
||||
//Set event
|
||||
es.OnSave += StoreEstateSettings;
|
||||
return es;
|
||||
|
||||
}
|
||||
|
||||
public List<EstateSettings> LoadEstateSettingsAll()
|
||||
{
|
||||
List<EstateSettings> allEstateSettings = new List<EstateSettings>();
|
||||
|
||||
List<int> allEstateIds = GetEstatesAll();
|
||||
|
||||
foreach (int estateId in allEstateIds)
|
||||
allEstateSettings.Add(LoadEstateSettings(estateId));
|
||||
|
||||
return allEstateSettings;
|
||||
}
|
||||
|
||||
public List<int> GetEstates(string search)
|
||||
{
|
||||
List<int> result = new List<int>();
|
||||
string sql = "select \"EstateID\" from estate_settings where lower(\"EstateName\") = lower(:EstateName)";
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
{
|
||||
conn.Open();
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("EstateName", search);
|
||||
|
||||
using (IDataReader reader = cmd.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
result.Add(Convert.ToInt32(reader["EstateID"]));
|
||||
}
|
||||
reader.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<int> GetEstatesAll()
|
||||
{
|
||||
List<int> result = new List<int>();
|
||||
string sql = "select \"EstateID\" from estate_settings";
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
{
|
||||
conn.Open();
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
using (IDataReader reader = cmd.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
result.Add(Convert.ToInt32(reader["EstateID"]));
|
||||
}
|
||||
reader.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<int> GetEstatesByOwner(UUID ownerID)
|
||||
{
|
||||
List<int> result = new List<int>();
|
||||
string sql = "select \"estateID\" from estate_settings where \"EstateOwner\" = :EstateOwner";
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
{
|
||||
conn.Open();
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("EstateOwner", ownerID);
|
||||
|
||||
using (IDataReader reader = cmd.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
result.Add(Convert.ToInt32(reader["EstateID"]));
|
||||
}
|
||||
reader.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool LinkRegion(UUID regionID, int estateID)
|
||||
{
|
||||
string deleteSQL = "delete from estate_map where \"RegionID\" = :RegionID";
|
||||
string insertSQL = "insert into estate_map values (:RegionID, :EstateID)";
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
NpgsqlTransaction transaction = conn.BeginTransaction();
|
||||
|
||||
try
|
||||
{
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(deleteSQL, conn))
|
||||
{
|
||||
cmd.Transaction = transaction;
|
||||
cmd.Parameters.AddWithValue("RegionID", regionID.Guid);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(insertSQL, conn))
|
||||
{
|
||||
cmd.Transaction = transaction;
|
||||
cmd.Parameters.AddWithValue("RegionID", regionID.Guid);
|
||||
cmd.Parameters.AddWithValue("EstateID", estateID);
|
||||
|
||||
int ret = cmd.ExecuteNonQuery();
|
||||
|
||||
if (ret != 0)
|
||||
transaction.Commit();
|
||||
else
|
||||
transaction.Rollback();
|
||||
|
||||
return (ret != 0);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
m_log.Error("[REGION DB]: LinkRegion failed: " + ex.Message);
|
||||
transaction.Rollback();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<UUID> GetRegions(int estateID)
|
||||
{
|
||||
List<UUID> result = new List<UUID>();
|
||||
string sql = "select \"RegionID\" from estate_map where \"EstateID\" = :EstateID";
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
{
|
||||
conn.Open();
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("EstateID", estateID);
|
||||
|
||||
using (IDataReader reader = cmd.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
result.Add(DBGuid.FromDB(reader["RegionID"]));
|
||||
}
|
||||
reader.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool DeleteEstate(int estateID)
|
||||
{
|
||||
// TODO: Implementation!
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
111
OpenSim/Data/PGSQL/PGSQLFramework.cs
Normal file
111
OpenSim/Data/PGSQL/PGSQLFramework.cs
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* 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.Data;
|
||||
using System.Reflection;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using Npgsql;
|
||||
|
||||
namespace OpenSim.Data.PGSQL
|
||||
{
|
||||
/// <summary>
|
||||
/// A database interface class to a user profile storage system
|
||||
/// </summary>
|
||||
public class PGSqlFramework
|
||||
{
|
||||
private static readonly log4net.ILog m_log =
|
||||
log4net.LogManager.GetLogger(
|
||||
System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
protected string m_connectionString;
|
||||
protected object m_dbLock = new object();
|
||||
|
||||
protected PGSqlFramework(string connectionString)
|
||||
{
|
||||
m_connectionString = connectionString;
|
||||
InitializeMonoSecurity();
|
||||
}
|
||||
|
||||
public void InitializeMonoSecurity()
|
||||
{
|
||||
if (!Util.IsPlatformMono)
|
||||
{
|
||||
|
||||
if (AppDomain.CurrentDomain.GetData("MonoSecurityPostgresAdded") == null)
|
||||
{
|
||||
AppDomain.CurrentDomain.SetData("MonoSecurityPostgresAdded", "true");
|
||||
|
||||
AppDomain currentDomain = AppDomain.CurrentDomain;
|
||||
currentDomain.AssemblyResolve += new ResolveEventHandler(ResolveEventHandlerMonoSec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private System.Reflection.Assembly ResolveEventHandlerMonoSec(object sender, ResolveEventArgs args)
|
||||
{
|
||||
Assembly MyAssembly = null;
|
||||
|
||||
if (args.Name.Substring(0, args.Name.IndexOf(",")) == "Mono.Security")
|
||||
{
|
||||
MyAssembly = Assembly.LoadFrom("lib/NET/Mono.Security.dll");
|
||||
}
|
||||
|
||||
//Return the loaded assembly.
|
||||
return MyAssembly;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
// All non queries are funneled through one connection
|
||||
// to increase performance a little
|
||||
//
|
||||
protected int ExecuteNonQuery(NpgsqlCommand cmd)
|
||||
{
|
||||
lock (m_dbLock)
|
||||
{
|
||||
using (NpgsqlConnection dbcon = new NpgsqlConnection(m_connectionString))
|
||||
{
|
||||
dbcon.Open();
|
||||
cmd.Connection = dbcon;
|
||||
|
||||
try
|
||||
{
|
||||
return cmd.ExecuteNonQuery();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error(e.Message, e);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
116
OpenSim/Data/PGSQL/PGSQLFriendsData.cs
Normal file
116
OpenSim/Data/PGSQL/PGSQLFriendsData.cs
Normal file
@@ -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;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using Npgsql;
|
||||
|
||||
namespace OpenSim.Data.PGSQL
|
||||
{
|
||||
public class PGSQLFriendsData : PGSQLGenericTableHandler<FriendsData>, IFriendsData
|
||||
{
|
||||
public PGSQLFriendsData(string connectionString, string realm)
|
||||
: base(connectionString, realm, "FriendsStore")
|
||||
{
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
{
|
||||
conn.Open();
|
||||
Migration m = new Migration(conn, GetType().Assembly, "FriendsStore");
|
||||
m.Update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public bool Delete(string principalID, string friend)
|
||||
{
|
||||
UUID princUUID = UUID.Zero;
|
||||
|
||||
bool ret = UUID.TryParse(principalID, out princUUID);
|
||||
|
||||
if (ret)
|
||||
return Delete(princUUID, friend);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool Delete(UUID principalID, string friend)
|
||||
{
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand())
|
||||
{
|
||||
cmd.CommandText = String.Format("delete from {0} where \"PrincipalID\" = :PrincipalID and \"Friend\" = :Friend", m_Realm);
|
||||
cmd.Parameters.Add(m_database.CreateParameter("PrincipalID", principalID.ToString()));
|
||||
cmd.Parameters.Add(m_database.CreateParameter("Friend", friend));
|
||||
cmd.Connection = conn;
|
||||
conn.Open();
|
||||
cmd.ExecuteNonQuery();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public FriendsData[] GetFriends(string principalID)
|
||||
{
|
||||
UUID princUUID = UUID.Zero;
|
||||
|
||||
bool ret = UUID.TryParse(principalID, out princUUID);
|
||||
|
||||
if (ret)
|
||||
return GetFriends(princUUID);
|
||||
else
|
||||
return new FriendsData[0];
|
||||
}
|
||||
|
||||
public FriendsData[] GetFriends(UUID principalID)
|
||||
{
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand())
|
||||
{
|
||||
|
||||
cmd.CommandText = String.Format("select a.*,case when b.\"Flags\" is null then '-1' else b.\"Flags\" end as \"TheirFlags\" from {0} as a " +
|
||||
" left join {0} as b on a.\"PrincipalID\" = b.\"Friend\" and a.\"Friend\" = b.\"PrincipalID\" " +
|
||||
" where a.\"PrincipalID\" = :PrincipalID", m_Realm);
|
||||
cmd.Parameters.Add(m_database.CreateParameter("PrincipalID", principalID.ToString()));
|
||||
cmd.Connection = conn;
|
||||
conn.Open();
|
||||
return DoQuery(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
public FriendsData[] GetFriends(Guid principalID)
|
||||
{
|
||||
return GetFriends(principalID);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
519
OpenSim/Data/PGSQL/PGSQLGenericTableHandler.cs
Normal file
519
OpenSim/Data/PGSQL/PGSQLGenericTableHandler.cs
Normal file
@@ -0,0 +1,519 @@
|
||||
/*
|
||||
* 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;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using System.Text;
|
||||
using Npgsql;
|
||||
|
||||
namespace OpenSim.Data.PGSQL
|
||||
{
|
||||
public class PGSQLGenericTableHandler<T> : PGSqlFramework where T : class, new()
|
||||
{
|
||||
private static readonly ILog m_log =
|
||||
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
protected string m_ConnectionString;
|
||||
protected PGSQLManager m_database; //used for parameter type translation
|
||||
protected Dictionary<string, FieldInfo> m_Fields =
|
||||
new Dictionary<string, FieldInfo>();
|
||||
|
||||
protected Dictionary<string, string> m_FieldTypes = new Dictionary<string, string>();
|
||||
|
||||
protected List<string> m_ColumnNames = null;
|
||||
protected string m_Realm;
|
||||
protected FieldInfo m_DataField = null;
|
||||
|
||||
protected virtual Assembly Assembly
|
||||
{
|
||||
get { return GetType().Assembly; }
|
||||
}
|
||||
|
||||
public PGSQLGenericTableHandler(string connectionString,
|
||||
string realm, string storeName)
|
||||
: base(connectionString)
|
||||
{
|
||||
m_Realm = realm;
|
||||
|
||||
m_ConnectionString = connectionString;
|
||||
|
||||
if (storeName != String.Empty)
|
||||
{
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
{
|
||||
conn.Open();
|
||||
Migration m = new Migration(conn, GetType().Assembly, storeName);
|
||||
m.Update();
|
||||
}
|
||||
|
||||
}
|
||||
m_database = new PGSQLManager(m_ConnectionString);
|
||||
|
||||
Type t = typeof(T);
|
||||
FieldInfo[] fields = t.GetFields(BindingFlags.Public |
|
||||
BindingFlags.Instance |
|
||||
BindingFlags.DeclaredOnly);
|
||||
|
||||
LoadFieldTypes();
|
||||
|
||||
if (fields.Length == 0)
|
||||
return;
|
||||
|
||||
foreach (FieldInfo f in fields)
|
||||
{
|
||||
if (f.Name != "Data")
|
||||
m_Fields[f.Name] = f;
|
||||
else
|
||||
m_DataField = f;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void LoadFieldTypes()
|
||||
{
|
||||
m_FieldTypes = new Dictionary<string, string>();
|
||||
|
||||
string query = string.Format(@"select column_name,data_type
|
||||
from INFORMATION_SCHEMA.COLUMNS
|
||||
where table_name = lower('{0}');
|
||||
|
||||
", m_Realm);
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(query, conn))
|
||||
{
|
||||
conn.Open();
|
||||
using (NpgsqlDataReader rdr = cmd.ExecuteReader())
|
||||
{
|
||||
while (rdr.Read())
|
||||
{
|
||||
// query produces 0 to many rows of single column, so always add the first item in each row
|
||||
m_FieldTypes.Add((string)rdr[0], (string)rdr[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckColumnNames(NpgsqlDataReader reader)
|
||||
{
|
||||
if (m_ColumnNames != null)
|
||||
return;
|
||||
|
||||
m_ColumnNames = new List<string>();
|
||||
|
||||
DataTable schemaTable = reader.GetSchemaTable();
|
||||
|
||||
foreach (DataRow row in schemaTable.Rows)
|
||||
{
|
||||
if (row["ColumnName"] != null &&
|
||||
(!m_Fields.ContainsKey(row["ColumnName"].ToString())))
|
||||
m_ColumnNames.Add(row["ColumnName"].ToString());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// TODO GET CONSTRAINTS FROM POSTGRESQL
|
||||
private List<string> GetConstraints()
|
||||
{
|
||||
List<string> constraints = new List<string>();
|
||||
string query = string.Format(@"SELECT kcu.column_name
|
||||
FROM information_schema.table_constraints tc
|
||||
LEFT JOIN information_schema.key_column_usage kcu
|
||||
ON tc.constraint_catalog = kcu.constraint_catalog
|
||||
AND tc.constraint_schema = kcu.constraint_schema
|
||||
AND tc.constraint_name = kcu.constraint_name
|
||||
|
||||
LEFT JOIN information_schema.referential_constraints rc
|
||||
ON tc.constraint_catalog = rc.constraint_catalog
|
||||
AND tc.constraint_schema = rc.constraint_schema
|
||||
AND tc.constraint_name = rc.constraint_name
|
||||
|
||||
LEFT JOIN information_schema.constraint_column_usage ccu
|
||||
ON rc.unique_constraint_catalog = ccu.constraint_catalog
|
||||
AND rc.unique_constraint_schema = ccu.constraint_schema
|
||||
AND rc.unique_constraint_name = ccu.constraint_name
|
||||
|
||||
where tc.table_name = lower('{0}')
|
||||
and lower(tc.constraint_type) in ('primary key')
|
||||
and kcu.column_name is not null
|
||||
;", m_Realm);
|
||||
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(query, conn))
|
||||
{
|
||||
conn.Open();
|
||||
using (NpgsqlDataReader rdr = cmd.ExecuteReader())
|
||||
{
|
||||
while (rdr.Read())
|
||||
{
|
||||
// query produces 0 to many rows of single column, so always add the first item in each row
|
||||
constraints.Add((string)rdr[0]);
|
||||
}
|
||||
}
|
||||
return constraints;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual T[] Get(string field, string key)
|
||||
{
|
||||
return Get(new string[] { field }, new string[] { key });
|
||||
}
|
||||
|
||||
public virtual T[] Get(string[] fields, string[] keys)
|
||||
{
|
||||
if (fields.Length != keys.Length)
|
||||
return new T[0];
|
||||
|
||||
List<string> terms = new List<string>();
|
||||
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand())
|
||||
{
|
||||
|
||||
for (int i = 0; i < fields.Length; i++)
|
||||
{
|
||||
if ( m_FieldTypes.ContainsKey(fields[i]) )
|
||||
cmd.Parameters.Add(m_database.CreateParameter(fields[i], keys[i], m_FieldTypes[fields[i]]));
|
||||
else
|
||||
cmd.Parameters.Add(m_database.CreateParameter(fields[i], keys[i]));
|
||||
|
||||
terms.Add(" \"" + fields[i] + "\" = :" + fields[i]);
|
||||
}
|
||||
|
||||
string where = String.Join(" AND ", terms.ToArray());
|
||||
|
||||
string query = String.Format("SELECT * FROM {0} WHERE {1}",
|
||||
m_Realm, where);
|
||||
|
||||
cmd.Connection = conn;
|
||||
cmd.CommandText = query;
|
||||
conn.Open();
|
||||
return DoQuery(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
protected T[] DoQuery(NpgsqlCommand cmd)
|
||||
{
|
||||
List<T> result = new List<T>();
|
||||
if (cmd.Connection == null)
|
||||
{
|
||||
cmd.Connection = new NpgsqlConnection(m_connectionString);
|
||||
}
|
||||
if (cmd.Connection.State == ConnectionState.Closed)
|
||||
{
|
||||
cmd.Connection.Open();
|
||||
}
|
||||
using (NpgsqlDataReader reader = cmd.ExecuteReader())
|
||||
{
|
||||
if (reader == null)
|
||||
return new T[0];
|
||||
|
||||
CheckColumnNames(reader);
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
T row = new T();
|
||||
|
||||
foreach (string name in m_Fields.Keys)
|
||||
{
|
||||
if (m_Fields[name].GetValue(row) is bool)
|
||||
{
|
||||
int v = Convert.ToInt32(reader[name]);
|
||||
m_Fields[name].SetValue(row, v != 0 ? true : false);
|
||||
}
|
||||
else if (m_Fields[name].GetValue(row) is UUID)
|
||||
{
|
||||
UUID uuid = UUID.Zero;
|
||||
|
||||
UUID.TryParse(reader[name].ToString(), out uuid);
|
||||
m_Fields[name].SetValue(row, uuid);
|
||||
}
|
||||
else if (m_Fields[name].GetValue(row) is int)
|
||||
{
|
||||
int v = Convert.ToInt32(reader[name]);
|
||||
m_Fields[name].SetValue(row, v);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Fields[name].SetValue(row, reader[name]);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_DataField != null)
|
||||
{
|
||||
Dictionary<string, string> data =
|
||||
new Dictionary<string, string>();
|
||||
|
||||
foreach (string col in m_ColumnNames)
|
||||
{
|
||||
data[col] = reader[col].ToString();
|
||||
|
||||
if (data[col] == null)
|
||||
data[col] = String.Empty;
|
||||
}
|
||||
|
||||
m_DataField.SetValue(row, data);
|
||||
}
|
||||
|
||||
result.Add(row);
|
||||
}
|
||||
return result.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual T[] Get(string where)
|
||||
{
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand())
|
||||
{
|
||||
|
||||
string query = String.Format("SELECT * FROM {0} WHERE {1}",
|
||||
m_Realm, where);
|
||||
cmd.Connection = conn;
|
||||
cmd.CommandText = query;
|
||||
|
||||
//m_log.WarnFormat("[PGSQLGenericTable]: SELECT {0} WHERE {1}", m_Realm, where);
|
||||
|
||||
conn.Open();
|
||||
return DoQuery(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool Store(T row)
|
||||
{
|
||||
List<string> constraintFields = GetConstraints();
|
||||
List<KeyValuePair<string, string>> constraints = new List<KeyValuePair<string, string>>();
|
||||
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand())
|
||||
{
|
||||
|
||||
StringBuilder query = new StringBuilder();
|
||||
List<String> names = new List<String>();
|
||||
List<String> values = new List<String>();
|
||||
|
||||
foreach (FieldInfo fi in m_Fields.Values)
|
||||
{
|
||||
names.Add(fi.Name);
|
||||
values.Add(":" + fi.Name);
|
||||
// Temporarily return more information about what field is unexpectedly null for
|
||||
// http://opensimulator.org/mantis/view.php?id=5403. This might be due to a bug in the
|
||||
// InventoryTransferModule or we may be required to substitute a DBNull here.
|
||||
if (fi.GetValue(row) == null)
|
||||
throw new NullReferenceException(
|
||||
string.Format(
|
||||
"[PGSQL GENERIC TABLE HANDLER]: Trying to store field {0} for {1} which is unexpectedly null",
|
||||
fi.Name, row));
|
||||
|
||||
if (constraintFields.Count > 0 && constraintFields.Contains(fi.Name))
|
||||
{
|
||||
constraints.Add(new KeyValuePair<string, string>(fi.Name, fi.GetValue(row).ToString() ));
|
||||
}
|
||||
if (m_FieldTypes.ContainsKey(fi.Name))
|
||||
cmd.Parameters.Add(m_database.CreateParameter(fi.Name, fi.GetValue(row), m_FieldTypes[fi.Name]));
|
||||
else
|
||||
cmd.Parameters.Add(m_database.CreateParameter(fi.Name, fi.GetValue(row)));
|
||||
}
|
||||
|
||||
if (m_DataField != null)
|
||||
{
|
||||
Dictionary<string, string> data =
|
||||
(Dictionary<string, string>)m_DataField.GetValue(row);
|
||||
|
||||
foreach (KeyValuePair<string, string> kvp in data)
|
||||
{
|
||||
if (constraintFields.Count > 0 && constraintFields.Contains(kvp.Key))
|
||||
{
|
||||
constraints.Add(new KeyValuePair<string, string>(kvp.Key, kvp.Key));
|
||||
}
|
||||
names.Add(kvp.Key);
|
||||
values.Add(":" + kvp.Key);
|
||||
|
||||
if (m_FieldTypes.ContainsKey(kvp.Key))
|
||||
cmd.Parameters.Add(m_database.CreateParameter("" + kvp.Key, kvp.Value, m_FieldTypes[kvp.Key]));
|
||||
else
|
||||
cmd.Parameters.Add(m_database.CreateParameter("" + kvp.Key, kvp.Value));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
query.AppendFormat("UPDATE {0} SET ", m_Realm);
|
||||
int i = 0;
|
||||
for (i = 0; i < names.Count - 1; i++)
|
||||
{
|
||||
query.AppendFormat("\"{0}\" = {1}, ", names[i], values[i]);
|
||||
}
|
||||
query.AppendFormat("\"{0}\" = {1} ", names[i], values[i]);
|
||||
if (constraints.Count > 0)
|
||||
{
|
||||
List<string> terms = new List<string>();
|
||||
for (int j = 0; j < constraints.Count; j++)
|
||||
{
|
||||
terms.Add(String.Format(" \"{0}\" = :{0}", constraints[j].Key));
|
||||
}
|
||||
string where = String.Join(" AND ", terms.ToArray());
|
||||
query.AppendFormat(" WHERE {0} ", where);
|
||||
|
||||
}
|
||||
cmd.Connection = conn;
|
||||
cmd.CommandText = query.ToString();
|
||||
|
||||
conn.Open();
|
||||
if (cmd.ExecuteNonQuery() > 0)
|
||||
{
|
||||
//m_log.WarnFormat("[PGSQLGenericTable]: Updating {0}", m_Realm);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// assume record has not yet been inserted
|
||||
|
||||
query = new StringBuilder();
|
||||
query.AppendFormat("INSERT INTO {0} (\"", m_Realm);
|
||||
query.Append(String.Join("\",\"", names.ToArray()));
|
||||
query.Append("\") values (" + String.Join(",", values.ToArray()) + ")");
|
||||
cmd.Connection = conn;
|
||||
cmd.CommandText = query.ToString();
|
||||
|
||||
// m_log.WarnFormat("[PGSQLGenericTable]: Inserting into {0} sql {1}", m_Realm, cmd.CommandText);
|
||||
|
||||
if (conn.State != ConnectionState.Open)
|
||||
conn.Open();
|
||||
if (cmd.ExecuteNonQuery() > 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool Delete(string field, string key)
|
||||
{
|
||||
return Delete(new string[] { field }, new string[] { key });
|
||||
}
|
||||
|
||||
public virtual bool Delete(string[] fields, string[] keys)
|
||||
{
|
||||
if (fields.Length != keys.Length)
|
||||
return false;
|
||||
|
||||
List<string> terms = new List<string>();
|
||||
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand())
|
||||
{
|
||||
for (int i = 0; i < fields.Length; i++)
|
||||
{
|
||||
if (m_FieldTypes.ContainsKey(fields[i]))
|
||||
cmd.Parameters.Add(m_database.CreateParameter(fields[i], keys[i], m_FieldTypes[fields[i]]));
|
||||
else
|
||||
cmd.Parameters.Add(m_database.CreateParameter(fields[i], keys[i]));
|
||||
|
||||
terms.Add(" \"" + fields[i] + "\" = :" + fields[i]);
|
||||
}
|
||||
|
||||
string where = String.Join(" AND ", terms.ToArray());
|
||||
|
||||
string query = String.Format("DELETE FROM {0} WHERE {1}", m_Realm, where);
|
||||
|
||||
cmd.Connection = conn;
|
||||
cmd.CommandText = query;
|
||||
conn.Open();
|
||||
|
||||
if (cmd.ExecuteNonQuery() > 0)
|
||||
{
|
||||
//m_log.Warn("[PGSQLGenericTable]: " + deleteCommand);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public long GetCount(string field, string key)
|
||||
{
|
||||
return GetCount(new string[] { field }, new string[] { key });
|
||||
}
|
||||
|
||||
public long GetCount(string[] fields, string[] keys)
|
||||
{
|
||||
if (fields.Length != keys.Length)
|
||||
return 0;
|
||||
|
||||
List<string> terms = new List<string>();
|
||||
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand())
|
||||
{
|
||||
for (int i = 0; i < fields.Length; i++)
|
||||
{
|
||||
cmd.Parameters.AddWithValue(fields[i], keys[i]);
|
||||
terms.Add("\"" + fields[i] + "\" = :" + fields[i]);
|
||||
}
|
||||
|
||||
string where = String.Join(" and ", terms.ToArray());
|
||||
|
||||
string query = String.Format("select count(*) from {0} where {1}",
|
||||
m_Realm, where);
|
||||
|
||||
cmd.CommandText = query;
|
||||
|
||||
Object result = DoQueryScalar(cmd);
|
||||
|
||||
return Convert.ToInt64(result);
|
||||
}
|
||||
}
|
||||
|
||||
public long GetCount(string where)
|
||||
{
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand())
|
||||
{
|
||||
string query = String.Format("select count(*) from {0} where {1}",
|
||||
m_Realm, where);
|
||||
|
||||
cmd.CommandText = query;
|
||||
|
||||
object result = DoQueryScalar(cmd);
|
||||
|
||||
return Convert.ToInt64(result);
|
||||
}
|
||||
}
|
||||
|
||||
public object DoQueryScalar(NpgsqlCommand cmd)
|
||||
{
|
||||
using (NpgsqlConnection dbcon = new NpgsqlConnection(m_ConnectionString))
|
||||
{
|
||||
dbcon.Open();
|
||||
cmd.Connection = dbcon;
|
||||
|
||||
return cmd.ExecuteScalar();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
68
OpenSim/Data/PGSQL/PGSQLGridUserData.cs
Normal file
68
OpenSim/Data/PGSQL/PGSQLGridUserData.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
namespace OpenSim.Data.PGSQL
|
||||
{
|
||||
/// <summary>
|
||||
/// A PGSQL Interface for Avatar Storage
|
||||
/// </summary>
|
||||
public class PGSQLGridUserData : PGSQLGenericTableHandler<GridUserData>,
|
||||
IGridUserData
|
||||
{
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
public PGSQLGridUserData(string connectionString, string realm) :
|
||||
base(connectionString, realm, "GridUserStore")
|
||||
{
|
||||
}
|
||||
|
||||
public new GridUserData Get(string userID)
|
||||
{
|
||||
GridUserData[] ret = Get("UserID", userID);
|
||||
|
||||
if (ret.Length == 0)
|
||||
return null;
|
||||
|
||||
return ret[0];
|
||||
}
|
||||
|
||||
public GridUserData[] GetAll(string userID)
|
||||
{
|
||||
return base.Get(String.Format("\"UserID\" LIKE '{0}%'", userID));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
481
OpenSim/Data/PGSQL/PGSQLGroupsData.cs
Normal file
481
OpenSim/Data/PGSQL/PGSQLGroupsData.cs
Normal file
@@ -0,0 +1,481 @@
|
||||
/*
|
||||
* 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.Reflection;
|
||||
using OpenSim.Framework;
|
||||
using OpenMetaverse;
|
||||
using Npgsql;
|
||||
|
||||
namespace OpenSim.Data.PGSQL
|
||||
{
|
||||
public class PGSQLGroupsData : IGroupsData
|
||||
{
|
||||
private PGSqlGroupsGroupsHandler m_Groups;
|
||||
private PGSqlGroupsMembershipHandler m_Membership;
|
||||
private PGSqlGroupsRolesHandler m_Roles;
|
||||
private PGSqlGroupsRoleMembershipHandler m_RoleMembership;
|
||||
private PGSqlGroupsInvitesHandler m_Invites;
|
||||
private PGSqlGroupsNoticesHandler m_Notices;
|
||||
private PGSqlGroupsPrincipalsHandler m_Principals;
|
||||
|
||||
public PGSQLGroupsData(string connectionString, string realm)
|
||||
{
|
||||
m_Groups = new PGSqlGroupsGroupsHandler(connectionString, realm + "_groups", realm + "_Store");
|
||||
m_Membership = new PGSqlGroupsMembershipHandler(connectionString, realm + "_membership");
|
||||
m_Roles = new PGSqlGroupsRolesHandler(connectionString, realm + "_roles");
|
||||
m_RoleMembership = new PGSqlGroupsRoleMembershipHandler(connectionString, realm + "_rolemembership");
|
||||
m_Invites = new PGSqlGroupsInvitesHandler(connectionString, realm + "_invites");
|
||||
m_Notices = new PGSqlGroupsNoticesHandler(connectionString, realm + "_notices");
|
||||
m_Principals = new PGSqlGroupsPrincipalsHandler(connectionString, realm + "_principals");
|
||||
}
|
||||
|
||||
#region groups table
|
||||
public bool StoreGroup(GroupData data)
|
||||
{
|
||||
return m_Groups.Store(data);
|
||||
}
|
||||
|
||||
public GroupData RetrieveGroup(UUID groupID)
|
||||
{
|
||||
GroupData[] groups = m_Groups.Get("GroupID", groupID.ToString());
|
||||
if (groups.Length > 0)
|
||||
return groups[0];
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public GroupData RetrieveGroup(string name)
|
||||
{
|
||||
GroupData[] groups = m_Groups.Get("Name", name);
|
||||
if (groups.Length > 0)
|
||||
return groups[0];
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public GroupData[] RetrieveGroups(string pattern)
|
||||
{
|
||||
if (string.IsNullOrEmpty(pattern)) // True for where clause
|
||||
pattern = " true ORDER BY lower(\"Name\") LIMIT 100";
|
||||
else
|
||||
pattern = string.Format(" lower(\"Name\") LIKE lower('%{0}%') ORDER BY lower(\"Name\") LIMIT 100", pattern);
|
||||
|
||||
return m_Groups.Get(pattern);
|
||||
}
|
||||
|
||||
public bool DeleteGroup(UUID groupID)
|
||||
{
|
||||
return m_Groups.Delete("GroupID", groupID.ToString());
|
||||
}
|
||||
|
||||
public int GroupsCount()
|
||||
{
|
||||
return (int)m_Groups.GetCount(" \"Location\" = \"\"");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region membership table
|
||||
public MembershipData[] RetrieveMembers(UUID groupID)
|
||||
{
|
||||
return m_Membership.Get("GroupID", groupID.ToString());
|
||||
}
|
||||
|
||||
public MembershipData RetrieveMember(UUID groupID, string pricipalID)
|
||||
{
|
||||
MembershipData[] m = m_Membership.Get(new string[] { "GroupID", "PrincipalID" },
|
||||
new string[] { groupID.ToString(), pricipalID });
|
||||
if (m != null && m.Length > 0)
|
||||
return m[0];
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public MembershipData[] RetrieveMemberships(string pricipalID)
|
||||
{
|
||||
return m_Membership.Get("PrincipalID", pricipalID.ToString());
|
||||
}
|
||||
|
||||
public bool StoreMember(MembershipData data)
|
||||
{
|
||||
return m_Membership.Store(data);
|
||||
}
|
||||
|
||||
public bool DeleteMember(UUID groupID, string pricipalID)
|
||||
{
|
||||
return m_Membership.Delete(new string[] { "GroupID", "PrincipalID" },
|
||||
new string[] { groupID.ToString(), pricipalID });
|
||||
}
|
||||
|
||||
public int MemberCount(UUID groupID)
|
||||
{
|
||||
return (int)m_Membership.GetCount("GroupID", groupID.ToString());
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region roles table
|
||||
public bool StoreRole(RoleData data)
|
||||
{
|
||||
return m_Roles.Store(data);
|
||||
}
|
||||
|
||||
public RoleData RetrieveRole(UUID groupID, UUID roleID)
|
||||
{
|
||||
RoleData[] data = m_Roles.Get(new string[] { "GroupID", "RoleID" },
|
||||
new string[] { groupID.ToString(), roleID.ToString() });
|
||||
|
||||
if (data != null && data.Length > 0)
|
||||
return data[0];
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public RoleData[] RetrieveRoles(UUID groupID)
|
||||
{
|
||||
//return m_Roles.RetrieveRoles(groupID);
|
||||
return m_Roles.Get("GroupID", groupID.ToString());
|
||||
}
|
||||
|
||||
public bool DeleteRole(UUID groupID, UUID roleID)
|
||||
{
|
||||
return m_Roles.Delete(new string[] { "GroupID", "RoleID" },
|
||||
new string[] { groupID.ToString(), roleID.ToString() });
|
||||
}
|
||||
|
||||
public int RoleCount(UUID groupID)
|
||||
{
|
||||
return (int)m_Roles.GetCount("GroupID", groupID.ToString());
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region rolememberhip table
|
||||
public RoleMembershipData[] RetrieveRolesMembers(UUID groupID)
|
||||
{
|
||||
RoleMembershipData[] data = m_RoleMembership.Get("GroupID", groupID.ToString());
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public RoleMembershipData[] RetrieveRoleMembers(UUID groupID, UUID roleID)
|
||||
{
|
||||
RoleMembershipData[] data = m_RoleMembership.Get(new string[] { "GroupID", "RoleID" },
|
||||
new string[] { groupID.ToString(), roleID.ToString() });
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public RoleMembershipData[] RetrieveMemberRoles(UUID groupID, string principalID)
|
||||
{
|
||||
RoleMembershipData[] data = m_RoleMembership.Get(new string[] { "GroupID", "PrincipalID" },
|
||||
new string[] { groupID.ToString(), principalID.ToString() });
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public RoleMembershipData RetrieveRoleMember(UUID groupID, UUID roleID, string principalID)
|
||||
{
|
||||
RoleMembershipData[] data = m_RoleMembership.Get(new string[] { "GroupID", "RoleID", "PrincipalID" },
|
||||
new string[] { groupID.ToString(), roleID.ToString(), principalID.ToString() });
|
||||
|
||||
if (data != null && data.Length > 0)
|
||||
return data[0];
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public int RoleMemberCount(UUID groupID, UUID roleID)
|
||||
{
|
||||
return (int)m_RoleMembership.GetCount(new string[] { "GroupID", "RoleID" },
|
||||
new string[] { groupID.ToString(), roleID.ToString() });
|
||||
}
|
||||
|
||||
public bool StoreRoleMember(RoleMembershipData data)
|
||||
{
|
||||
return m_RoleMembership.Store(data);
|
||||
}
|
||||
|
||||
public bool DeleteRoleMember(RoleMembershipData data)
|
||||
{
|
||||
return m_RoleMembership.Delete(new string[] { "GroupID", "RoleID", "PrincipalID"},
|
||||
new string[] { data.GroupID.ToString(), data.RoleID.ToString(), data.PrincipalID });
|
||||
}
|
||||
|
||||
public bool DeleteMemberAllRoles(UUID groupID, string principalID)
|
||||
{
|
||||
return m_RoleMembership.Delete(new string[] { "GroupID", "PrincipalID" },
|
||||
new string[] { groupID.ToString(), principalID });
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region principals table
|
||||
public bool StorePrincipal(PrincipalData data)
|
||||
{
|
||||
return m_Principals.Store(data);
|
||||
}
|
||||
|
||||
public PrincipalData RetrievePrincipal(string principalID)
|
||||
{
|
||||
PrincipalData[] p = m_Principals.Get("PrincipalID", principalID);
|
||||
if (p != null && p.Length > 0)
|
||||
return p[0];
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool DeletePrincipal(string principalID)
|
||||
{
|
||||
return m_Principals.Delete("PrincipalID", principalID);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region invites table
|
||||
|
||||
public bool StoreInvitation(InvitationData data)
|
||||
{
|
||||
return m_Invites.Store(data);
|
||||
}
|
||||
|
||||
public InvitationData RetrieveInvitation(UUID inviteID)
|
||||
{
|
||||
InvitationData[] invites = m_Invites.Get("InviteID", inviteID.ToString());
|
||||
|
||||
if (invites != null && invites.Length > 0)
|
||||
return invites[0];
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public InvitationData RetrieveInvitation(UUID groupID, string principalID)
|
||||
{
|
||||
InvitationData[] invites = m_Invites.Get(new string[] { "GroupID", "PrincipalID" },
|
||||
new string[] { groupID.ToString(), principalID });
|
||||
|
||||
if (invites != null && invites.Length > 0)
|
||||
return invites[0];
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool DeleteInvite(UUID inviteID)
|
||||
{
|
||||
return m_Invites.Delete("InviteID", inviteID.ToString());
|
||||
}
|
||||
|
||||
public void DeleteOldInvites()
|
||||
{
|
||||
m_Invites.DeleteOld();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region notices table
|
||||
|
||||
public bool StoreNotice(NoticeData data)
|
||||
{
|
||||
return m_Notices.Store(data);
|
||||
}
|
||||
|
||||
public NoticeData RetrieveNotice(UUID noticeID)
|
||||
{
|
||||
NoticeData[] notices = m_Notices.Get("NoticeID", noticeID.ToString());
|
||||
|
||||
if (notices != null && notices.Length > 0)
|
||||
return notices[0];
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public NoticeData[] RetrieveNotices(UUID groupID)
|
||||
{
|
||||
NoticeData[] notices = m_Notices.Get("GroupID", groupID.ToString());
|
||||
|
||||
return notices;
|
||||
}
|
||||
|
||||
public bool DeleteNotice(UUID noticeID)
|
||||
{
|
||||
return m_Notices.Delete("NoticeID", noticeID.ToString());
|
||||
}
|
||||
|
||||
public void DeleteOldNotices()
|
||||
{
|
||||
m_Notices.DeleteOld();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region combinations
|
||||
public MembershipData RetrievePrincipalGroupMembership(string principalID, UUID groupID)
|
||||
{
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
public MembershipData[] RetrievePrincipalGroupMemberships(string principalID)
|
||||
{
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public class PGSqlGroupsGroupsHandler : PGSQLGenericTableHandler<GroupData>
|
||||
{
|
||||
protected override Assembly Assembly
|
||||
{
|
||||
// WARNING! Moving migrations to this assembly!!!
|
||||
get { return GetType().Assembly; }
|
||||
}
|
||||
|
||||
public PGSqlGroupsGroupsHandler(string connectionString, string realm, string store)
|
||||
: base(connectionString, realm, store)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class PGSqlGroupsMembershipHandler : PGSQLGenericTableHandler<MembershipData>
|
||||
{
|
||||
protected override Assembly Assembly
|
||||
{
|
||||
// WARNING! Moving migrations to this assembly!!!
|
||||
get { return GetType().Assembly; }
|
||||
}
|
||||
|
||||
public PGSqlGroupsMembershipHandler(string connectionString, string realm)
|
||||
: base(connectionString, realm, string.Empty)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class PGSqlGroupsRolesHandler : PGSQLGenericTableHandler<RoleData>
|
||||
{
|
||||
protected override Assembly Assembly
|
||||
{
|
||||
// WARNING! Moving migrations to this assembly!!!
|
||||
get { return GetType().Assembly; }
|
||||
}
|
||||
|
||||
public PGSqlGroupsRolesHandler(string connectionString, string realm)
|
||||
: base(connectionString, realm, string.Empty)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class PGSqlGroupsRoleMembershipHandler : PGSQLGenericTableHandler<RoleMembershipData>
|
||||
{
|
||||
protected override Assembly Assembly
|
||||
{
|
||||
// WARNING! Moving migrations to this assembly!!!
|
||||
get { return GetType().Assembly; }
|
||||
}
|
||||
|
||||
public PGSqlGroupsRoleMembershipHandler(string connectionString, string realm)
|
||||
: base(connectionString, realm, string.Empty)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class PGSqlGroupsInvitesHandler : PGSQLGenericTableHandler<InvitationData>
|
||||
{
|
||||
protected override Assembly Assembly
|
||||
{
|
||||
// WARNING! Moving migrations to this assembly!!!
|
||||
get { return GetType().Assembly; }
|
||||
}
|
||||
|
||||
public PGSqlGroupsInvitesHandler(string connectionString, string realm)
|
||||
: base(connectionString, realm, string.Empty)
|
||||
{
|
||||
}
|
||||
|
||||
public void DeleteOld()
|
||||
{
|
||||
uint now = (uint)Util.UnixTimeSinceEpoch();
|
||||
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand())
|
||||
{
|
||||
cmd.CommandText = String.Format("delete from {0} where \"TMStamp\" < :tstamp", m_Realm);
|
||||
cmd.Parameters.AddWithValue("tstamp", now - 14 * 24 * 60 * 60); // > 2 weeks old
|
||||
|
||||
ExecuteNonQuery(cmd);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class PGSqlGroupsNoticesHandler : PGSQLGenericTableHandler<NoticeData>
|
||||
{
|
||||
protected override Assembly Assembly
|
||||
{
|
||||
// WARNING! Moving migrations to this assembly!!!
|
||||
get { return GetType().Assembly; }
|
||||
}
|
||||
|
||||
public PGSqlGroupsNoticesHandler(string connectionString, string realm)
|
||||
: base(connectionString, realm, string.Empty)
|
||||
{
|
||||
}
|
||||
|
||||
public void DeleteOld()
|
||||
{
|
||||
uint now = (uint)Util.UnixTimeSinceEpoch();
|
||||
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand())
|
||||
{
|
||||
cmd.CommandText = String.Format("delete from {0} where \"TMStamp\" < :tstamp", m_Realm);
|
||||
cmd.Parameters.AddWithValue("tstamp", now - 14 * 24 * 60 * 60); // > 2 weeks old
|
||||
|
||||
ExecuteNonQuery(cmd);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class PGSqlGroupsPrincipalsHandler : PGSQLGenericTableHandler<PrincipalData>
|
||||
{
|
||||
protected override Assembly Assembly
|
||||
{
|
||||
// WARNING! Moving migrations to this assembly!!!
|
||||
get { return GetType().Assembly; }
|
||||
}
|
||||
|
||||
public PGSqlGroupsPrincipalsHandler(string connectionString, string realm)
|
||||
: base(connectionString, realm, string.Empty)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
80
OpenSim/Data/PGSQL/PGSQLHGTravelData.cs
Normal file
80
OpenSim/Data/PGSQL/PGSQLHGTravelData.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 Npgsql;
|
||||
|
||||
namespace OpenSim.Data.PGSQL
|
||||
{
|
||||
/// <summary>
|
||||
/// A PGSQL Interface for user grid data
|
||||
/// </summary>
|
||||
public class PGSQLHGTravelData : PGSQLGenericTableHandler<HGTravelingData>, IHGTravelingData
|
||||
{
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
public PGSQLHGTravelData(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 (NpgsqlCommand cmd = new NpgsqlCommand())
|
||||
{
|
||||
cmd.CommandText = String.Format(@"delete from {0} where ""TMStamp"" < CURRENT_DATE - INTERVAL '2 day'", m_Realm);
|
||||
|
||||
ExecuteNonQuery(cmd);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
831
OpenSim/Data/PGSQL/PGSQLInventoryData.cs
Normal file
831
OpenSim/Data/PGSQL/PGSQLInventoryData.cs
Normal file
@@ -0,0 +1,831 @@
|
||||
/*
|
||||
* 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;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using Npgsql;
|
||||
|
||||
namespace OpenSim.Data.PGSQL
|
||||
{
|
||||
/// <summary>
|
||||
/// A PGSQL interface for the inventory server
|
||||
/// </summary>
|
||||
public class PGSQLInventoryData : IInventoryDataPlugin
|
||||
{
|
||||
private const string _migrationStore = "InventoryStore";
|
||||
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
/// <summary>
|
||||
/// The database manager
|
||||
/// </summary>
|
||||
private PGSQLManager database;
|
||||
private string m_connectionString;
|
||||
|
||||
#region IPlugin members
|
||||
|
||||
[Obsolete("Cannot be default-initialized!")]
|
||||
public void Initialise()
|
||||
{
|
||||
m_log.Info("[PGSQLInventoryData]: " + Name + " cannot be default-initialized!");
|
||||
throw new PluginNotInitialisedException(Name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads and initialises the PGSQL inventory storage interface
|
||||
/// </summary>
|
||||
/// <param name="connectionString">connect string</param>
|
||||
/// <remarks>use PGSQL_connection.ini</remarks>
|
||||
public void Initialise(string connectionString)
|
||||
{
|
||||
m_connectionString = connectionString;
|
||||
database = new PGSQLManager(connectionString);
|
||||
|
||||
//New migrations check of store
|
||||
database.CheckMigration(_migrationStore);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The name of this DB provider
|
||||
/// </summary>
|
||||
/// <returns>A string containing the name of the DB provider</returns>
|
||||
public string Name
|
||||
{
|
||||
get { return "PGSQL Inventory Data Interface"; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes this DB provider
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
database = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the version of this DB provider
|
||||
/// </summary>
|
||||
/// <returns>A string containing the DB provider</returns>
|
||||
public string Version
|
||||
{
|
||||
get { return database.getVersion(); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Folder methods
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of the root folders within a users inventory
|
||||
/// </summary>
|
||||
/// <param name="user">The user whos inventory is to be searched</param>
|
||||
/// <returns>A list of folder objects</returns>
|
||||
public List<InventoryFolderBase> getUserRootFolders(UUID user)
|
||||
{
|
||||
if (user == UUID.Zero)
|
||||
return new List<InventoryFolderBase>();
|
||||
|
||||
return getInventoryFolders(UUID.Zero, user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// see InventoryItemBase.getUserRootFolder
|
||||
/// </summary>
|
||||
/// <param name="user">the User UUID</param>
|
||||
/// <returns></returns>
|
||||
public InventoryFolderBase getUserRootFolder(UUID user)
|
||||
{
|
||||
List<InventoryFolderBase> items = getUserRootFolders(user);
|
||||
|
||||
InventoryFolderBase rootFolder = null;
|
||||
|
||||
// There should only ever be one root folder for a user. However, if there's more
|
||||
// than one we'll simply use the first one rather than failing. It would be even
|
||||
// nicer to print some message to this effect, but this feels like it's too low a
|
||||
// to put such a message out, and it's too minor right now to spare the time to
|
||||
// suitably refactor.
|
||||
if (items.Count > 0)
|
||||
{
|
||||
rootFolder = items[0];
|
||||
}
|
||||
|
||||
return rootFolder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of folders in a users inventory contained within the specified folder
|
||||
/// </summary>
|
||||
/// <param name="parentID">The folder to search</param>
|
||||
/// <returns>A list of inventory folders</returns>
|
||||
public List<InventoryFolderBase> getInventoryFolders(UUID parentID)
|
||||
{
|
||||
return getInventoryFolders(parentID, UUID.Zero);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a specified inventory folder
|
||||
/// </summary>
|
||||
/// <param name="folderID">The folder to return</param>
|
||||
/// <returns>A folder class</returns>
|
||||
public InventoryFolderBase getInventoryFolder(UUID folderID)
|
||||
{
|
||||
string sql = "SELECT * FROM inventoryfolders WHERE \"folderID\" = :folderID";
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
cmd.Parameters.Add(database.CreateParameter("folderID", folderID));
|
||||
conn.Open();
|
||||
using (NpgsqlDataReader reader = cmd.ExecuteReader())
|
||||
{
|
||||
if (reader.Read())
|
||||
{
|
||||
return readInventoryFolder(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_log.InfoFormat("[INVENTORY DB] : Found no inventory folder with ID : {0}", folderID);
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all child folders in the hierarchy from the parent folder and down.
|
||||
/// Does not return the parent folder itself.
|
||||
/// </summary>
|
||||
/// <param name="parentID">The folder to get subfolders for</param>
|
||||
/// <returns>A list of inventory folders</returns>
|
||||
public List<InventoryFolderBase> getFolderHierarchy(UUID parentID)
|
||||
{
|
||||
//Note maybe change this to use a Dataset that loading in all folders of a user and then go throw it that way.
|
||||
//Note this is changed so it opens only one connection to the database and not everytime it wants to get data.
|
||||
|
||||
/* NOTE: the implementation below is very inefficient (makes a separate request to get subfolders for
|
||||
* every found folder, recursively). Inventory code for other DBs has been already rewritten to get ALL
|
||||
* inventory for a specific user at once.
|
||||
*
|
||||
* Meanwhile, one little thing is corrected: getFolderHierarchy(UUID.Zero) doesn't make sense and should never
|
||||
* be used, so check for that and return an empty list.
|
||||
*/
|
||||
|
||||
List<InventoryFolderBase> folders = new List<InventoryFolderBase>();
|
||||
|
||||
if (parentID == UUID.Zero)
|
||||
return folders;
|
||||
|
||||
string sql = "SELECT * FROM inventoryfolders WHERE \"parentFolderID\" = :parentID";
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
cmd.Parameters.Add(database.CreateParameter("parentID", parentID));
|
||||
conn.Open();
|
||||
folders.AddRange(getInventoryFolders(cmd));
|
||||
|
||||
List<InventoryFolderBase> tempFolders = new List<InventoryFolderBase>();
|
||||
|
||||
foreach (InventoryFolderBase folderBase in folders)
|
||||
{
|
||||
tempFolders.AddRange(getFolderHierarchy(folderBase.ID, cmd));
|
||||
}
|
||||
if (tempFolders.Count > 0)
|
||||
{
|
||||
folders.AddRange(tempFolders);
|
||||
}
|
||||
}
|
||||
return folders;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new inventory folder
|
||||
/// </summary>
|
||||
/// <param name="folder">Folder to create</param>
|
||||
public void addInventoryFolder(InventoryFolderBase folder)
|
||||
{
|
||||
string sql = "INSERT INTO inventoryfolders (\"folderID\", \"agentID\", \"parentFolderID\", \"folderName\", type, version) " +
|
||||
" VALUES (:folderID, :agentID, :parentFolderID, :folderName, :type, :version);";
|
||||
|
||||
string folderName = folder.Name;
|
||||
if (folderName.Length > 64)
|
||||
{
|
||||
folderName = folderName.Substring(0, 64);
|
||||
m_log.Warn("[INVENTORY DB]: Name field truncated from " + folder.Name.Length.ToString() + " to " + folderName.Length + " characters on add");
|
||||
}
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
cmd.Parameters.Add(database.CreateParameter("folderID", folder.ID));
|
||||
cmd.Parameters.Add(database.CreateParameter("agentID", folder.Owner));
|
||||
cmd.Parameters.Add(database.CreateParameter("parentFolderID", folder.ParentID));
|
||||
cmd.Parameters.Add(database.CreateParameter("folderName", folderName));
|
||||
cmd.Parameters.Add(database.CreateParameter("type", folder.Type));
|
||||
cmd.Parameters.Add(database.CreateParameter("version", folder.Version));
|
||||
conn.Open();
|
||||
try
|
||||
{
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("[INVENTORY DB]: Error : {0}", e.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates an inventory folder
|
||||
/// </summary>
|
||||
/// <param name="folder">Folder to update</param>
|
||||
public void updateInventoryFolder(InventoryFolderBase folder)
|
||||
{
|
||||
string sql = @"UPDATE inventoryfolders SET ""agentID"" = :agentID,
|
||||
""parentFolderID"" = :parentFolderID,
|
||||
""folderName"" = :folderName,
|
||||
type = :type,
|
||||
version = :version
|
||||
WHERE folderID = :folderID";
|
||||
|
||||
string folderName = folder.Name;
|
||||
if (folderName.Length > 64)
|
||||
{
|
||||
folderName = folderName.Substring(0, 64);
|
||||
m_log.Warn("[INVENTORY DB]: Name field truncated from " + folder.Name.Length.ToString() + " to " + folderName.Length + " characters on update");
|
||||
}
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
cmd.Parameters.Add(database.CreateParameter("folderID", folder.ID));
|
||||
cmd.Parameters.Add(database.CreateParameter("agentID", folder.Owner));
|
||||
cmd.Parameters.Add(database.CreateParameter("parentFolderID", folder.ParentID));
|
||||
cmd.Parameters.Add(database.CreateParameter("folderName", folderName));
|
||||
cmd.Parameters.Add(database.CreateParameter("type", folder.Type));
|
||||
cmd.Parameters.Add(database.CreateParameter("version", folder.Version));
|
||||
conn.Open();
|
||||
try
|
||||
{
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("[INVENTORY DB]: Error : {0}", e.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates an inventory folder
|
||||
/// </summary>
|
||||
/// <param name="folder">Folder to update</param>
|
||||
public void moveInventoryFolder(InventoryFolderBase folder)
|
||||
{
|
||||
string sql = @"UPDATE inventoryfolders SET ""parentFolderID"" = :parentFolderID WHERE ""folderID"" = :folderID";
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
cmd.Parameters.Add(database.CreateParameter("parentFolderID", folder.ParentID));
|
||||
cmd.Parameters.Add(database.CreateParameter("folderID", folder.ID));
|
||||
conn.Open();
|
||||
try
|
||||
{
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("[INVENTORY DB]: Error : {0}", e.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Delete an inventory folder
|
||||
/// </summary>
|
||||
/// <param name="folderID">Id of folder to delete</param>
|
||||
public void deleteInventoryFolder(UUID folderID)
|
||||
{
|
||||
string sql = @"SELECT * FROM inventoryfolders WHERE ""parentFolderID"" = :parentID";
|
||||
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
List<InventoryFolderBase> subFolders;
|
||||
cmd.Parameters.Add(database.CreateParameter("parentID", UUID.Zero));
|
||||
conn.Open();
|
||||
subFolders = getFolderHierarchy(folderID, cmd);
|
||||
|
||||
|
||||
//Delete all sub-folders
|
||||
foreach (InventoryFolderBase f in subFolders)
|
||||
{
|
||||
DeleteOneFolder(f.ID, conn);
|
||||
DeleteItemsInFolder(f.ID, conn);
|
||||
}
|
||||
|
||||
//Delete the actual row
|
||||
DeleteOneFolder(folderID, conn);
|
||||
DeleteItemsInFolder(folderID, conn);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Item Methods
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of items in a specified folder
|
||||
/// </summary>
|
||||
/// <param name="folderID">The folder to search</param>
|
||||
/// <returns>A list containing inventory items</returns>
|
||||
public List<InventoryItemBase> getInventoryInFolder(UUID folderID)
|
||||
{
|
||||
string sql = @"SELECT * FROM inventoryitems WHERE ""parentFolderID"" = :parentFolderID";
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
cmd.Parameters.Add(database.CreateParameter("parentFolderID", folderID));
|
||||
conn.Open();
|
||||
List<InventoryItemBase> items = new List<InventoryItemBase>();
|
||||
|
||||
using (NpgsqlDataReader reader = cmd.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
items.Add(readInventoryItem(reader));
|
||||
}
|
||||
}
|
||||
return items;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a specified inventory item
|
||||
/// </summary>
|
||||
/// <param name="itemID">The item ID</param>
|
||||
/// <returns>An inventory item</returns>
|
||||
public InventoryItemBase getInventoryItem(UUID itemID)
|
||||
{
|
||||
string sql = @"SELECT * FROM inventoryitems WHERE ""inventoryID"" = :inventoryID";
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
cmd.Parameters.Add(database.CreateParameter("inventoryID", itemID));
|
||||
conn.Open();
|
||||
using (NpgsqlDataReader reader = cmd.ExecuteReader())
|
||||
{
|
||||
if (reader.Read())
|
||||
{
|
||||
return readInventoryItem(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_log.InfoFormat("[INVENTORY DB]: Found no inventory item with ID : {0}", itemID);
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a specified item to the database
|
||||
/// </summary>
|
||||
/// <param name="item">The inventory item</param>
|
||||
public void addInventoryItem(InventoryItemBase item)
|
||||
{
|
||||
if (getInventoryItem(item.ID) != null)
|
||||
{
|
||||
updateInventoryItem(item);
|
||||
return;
|
||||
}
|
||||
|
||||
string sql = @"INSERT INTO inventoryitems
|
||||
(""inventoryID"", ""assetID"", ""assetType"", ""parentFolderID"", ""avatarID"", ""inventoryName"",
|
||||
""inventoryDescription"", ""inventoryNextPermissions"", ""inventoryCurrentPermissions"",
|
||||
""invType"", ""creatorID"", ""inventoryBasePermissions"", ""inventoryEveryOnePermissions"", ""inventoryGroupPermissions"",
|
||||
""salePrice"", ""SaleType"", ""creationDate"", ""groupID"", ""groupOwned"", flags)
|
||||
VALUES
|
||||
(:inventoryID, :assetID, :assetType, :parentFolderID, :avatarID, :inventoryName, :inventoryDescription,
|
||||
:inventoryNextPermissions, :inventoryCurrentPermissions, :invType, :creatorID,
|
||||
:inventoryBasePermissions, :inventoryEveryOnePermissions, :inventoryGroupPermissions, :SalePrice, :SaleType,
|
||||
:creationDate, :groupID, :groupOwned, :flags)";
|
||||
|
||||
string itemName = item.Name;
|
||||
if (item.Name.Length > 64)
|
||||
{
|
||||
itemName = item.Name.Substring(0, 64);
|
||||
m_log.Warn("[INVENTORY DB]: Name field truncated from " + item.Name.Length.ToString() + " to " + itemName.Length.ToString() + " characters");
|
||||
}
|
||||
|
||||
string itemDesc = item.Description;
|
||||
if (item.Description.Length > 128)
|
||||
{
|
||||
itemDesc = item.Description.Substring(0, 128);
|
||||
m_log.Warn("[INVENTORY DB]: Description field truncated from " + item.Description.Length.ToString() + " to " + itemDesc.Length.ToString() + " characters");
|
||||
}
|
||||
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
using (NpgsqlCommand command = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
command.Parameters.Add(database.CreateParameter("inventoryID", item.ID));
|
||||
command.Parameters.Add(database.CreateParameter("assetID", item.AssetID));
|
||||
command.Parameters.Add(database.CreateParameter("assetType", item.AssetType));
|
||||
command.Parameters.Add(database.CreateParameter("parentFolderID", item.Folder));
|
||||
command.Parameters.Add(database.CreateParameter("avatarID", item.Owner));
|
||||
command.Parameters.Add(database.CreateParameter("inventoryName", itemName));
|
||||
command.Parameters.Add(database.CreateParameter("inventoryDescription", itemDesc));
|
||||
command.Parameters.Add(database.CreateParameter("inventoryNextPermissions", item.NextPermissions));
|
||||
command.Parameters.Add(database.CreateParameter("inventoryCurrentPermissions", item.CurrentPermissions));
|
||||
command.Parameters.Add(database.CreateParameter("invType", item.InvType));
|
||||
command.Parameters.Add(database.CreateParameter("creatorID", item.CreatorId));
|
||||
command.Parameters.Add(database.CreateParameter("inventoryBasePermissions", item.BasePermissions));
|
||||
command.Parameters.Add(database.CreateParameter("inventoryEveryOnePermissions", item.EveryOnePermissions));
|
||||
command.Parameters.Add(database.CreateParameter("inventoryGroupPermissions", item.GroupPermissions));
|
||||
command.Parameters.Add(database.CreateParameter("SalePrice", item.SalePrice));
|
||||
command.Parameters.Add(database.CreateParameter("SaleType", item.SaleType));
|
||||
command.Parameters.Add(database.CreateParameter("creationDate", item.CreationDate));
|
||||
command.Parameters.Add(database.CreateParameter("groupID", item.GroupID));
|
||||
command.Parameters.Add(database.CreateParameter("groupOwned", item.GroupOwned));
|
||||
command.Parameters.Add(database.CreateParameter("flags", item.Flags));
|
||||
conn.Open();
|
||||
try
|
||||
{
|
||||
command.ExecuteNonQuery();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error("[INVENTORY DB]: Error inserting item :" + e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
sql = @"UPDATE inventoryfolders SET version = version + 1 WHERE ""folderID"" = @folderID";
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
using (NpgsqlCommand command = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
command.Parameters.Add(database.CreateParameter("folderID", item.Folder.ToString()));
|
||||
conn.Open();
|
||||
try
|
||||
{
|
||||
command.ExecuteNonQuery();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error("[INVENTORY DB] Error updating inventory folder for new item :" + e.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the specified inventory item
|
||||
/// </summary>
|
||||
/// <param name="item">Inventory item to update</param>
|
||||
public void updateInventoryItem(InventoryItemBase item)
|
||||
{
|
||||
string sql = @"UPDATE inventoryitems SET ""assetID"" = :assetID,
|
||||
""assetType"" = :assetType,
|
||||
""parentFolderID"" = :parentFolderID,
|
||||
""avatarID"" = :avatarID,
|
||||
""inventoryName"" = :inventoryName,
|
||||
""inventoryDescription"" = :inventoryDescription,
|
||||
""inventoryNextPermissions"" = :inventoryNextPermissions,
|
||||
""inventoryCurrentPermissions"" = :inventoryCurrentPermissions,
|
||||
""invType"" = :invType,
|
||||
""creatorID"" = :creatorID,
|
||||
""inventoryBasePermissions"" = :inventoryBasePermissions,
|
||||
""inventoryEveryOnePermissions"" = :inventoryEveryOnePermissions,
|
||||
""inventoryGroupPermissions"" = :inventoryGroupPermissions,
|
||||
""salePrice"" = :SalePrice,
|
||||
""saleType"" = :SaleType,
|
||||
""creationDate"" = :creationDate,
|
||||
""groupID"" = :groupID,
|
||||
""groupOwned"" = :groupOwned,
|
||||
flags = :flags
|
||||
WHERE ""inventoryID"" = :inventoryID";
|
||||
|
||||
string itemName = item.Name;
|
||||
if (item.Name.Length > 64)
|
||||
{
|
||||
itemName = item.Name.Substring(0, 64);
|
||||
m_log.Warn("[INVENTORY DB]: Name field truncated from " + item.Name.Length.ToString() + " to " + itemName.Length.ToString() + " characters on update");
|
||||
}
|
||||
|
||||
string itemDesc = item.Description;
|
||||
if (item.Description.Length > 128)
|
||||
{
|
||||
itemDesc = item.Description.Substring(0, 128);
|
||||
m_log.Warn("[INVENTORY DB]: Description field truncated from " + item.Description.Length.ToString() + " to " + itemDesc.Length.ToString() + " characters on update");
|
||||
}
|
||||
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
using (NpgsqlCommand command = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
command.Parameters.Add(database.CreateParameter("inventoryID", item.ID));
|
||||
command.Parameters.Add(database.CreateParameter("assetID", item.AssetID));
|
||||
command.Parameters.Add(database.CreateParameter("assetType", item.AssetType));
|
||||
command.Parameters.Add(database.CreateParameter("parentFolderID", item.Folder));
|
||||
command.Parameters.Add(database.CreateParameter("avatarID", item.Owner));
|
||||
command.Parameters.Add(database.CreateParameter("inventoryName", itemName));
|
||||
command.Parameters.Add(database.CreateParameter("inventoryDescription", itemDesc));
|
||||
command.Parameters.Add(database.CreateParameter("inventoryNextPermissions", item.NextPermissions));
|
||||
command.Parameters.Add(database.CreateParameter("inventoryCurrentPermissions", item.CurrentPermissions));
|
||||
command.Parameters.Add(database.CreateParameter("invType", item.InvType));
|
||||
command.Parameters.Add(database.CreateParameter("creatorID", item.CreatorId));
|
||||
command.Parameters.Add(database.CreateParameter("inventoryBasePermissions", item.BasePermissions));
|
||||
command.Parameters.Add(database.CreateParameter("inventoryEveryOnePermissions", item.EveryOnePermissions));
|
||||
command.Parameters.Add(database.CreateParameter("inventoryGroupPermissions", item.GroupPermissions));
|
||||
command.Parameters.Add(database.CreateParameter("SalePrice", item.SalePrice));
|
||||
command.Parameters.Add(database.CreateParameter("SaleType", item.SaleType));
|
||||
command.Parameters.Add(database.CreateParameter("creationDate", item.CreationDate));
|
||||
command.Parameters.Add(database.CreateParameter("groupID", item.GroupID));
|
||||
command.Parameters.Add(database.CreateParameter("groupOwned", item.GroupOwned));
|
||||
command.Parameters.Add(database.CreateParameter("flags", item.Flags));
|
||||
conn.Open();
|
||||
try
|
||||
{
|
||||
command.ExecuteNonQuery();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error("[INVENTORY DB]: Error updating item :" + e.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// See IInventoryDataPlugin
|
||||
|
||||
/// <summary>
|
||||
/// Delete an item in inventory database
|
||||
/// </summary>
|
||||
/// <param name="itemID">the item UUID</param>
|
||||
public void deleteInventoryItem(UUID itemID)
|
||||
{
|
||||
string sql = @"DELETE FROM inventoryitems WHERE ""inventoryID""=:inventoryID";
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
cmd.Parameters.Add(database.CreateParameter("inventoryID", itemID));
|
||||
try
|
||||
{
|
||||
conn.Open();
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error("[INVENTORY DB]: Error deleting item :" + e.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public InventoryItemBase queryInventoryItem(UUID itemID)
|
||||
{
|
||||
return getInventoryItem(itemID);
|
||||
}
|
||||
|
||||
public InventoryFolderBase queryInventoryFolder(UUID folderID)
|
||||
{
|
||||
return getInventoryFolder(folderID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all activated gesture-items in the inventory of the specified avatar.
|
||||
/// </summary>
|
||||
/// <param name="avatarID">The <see cref="UUID"/> of the avatar</param>
|
||||
/// <returns>
|
||||
/// The list of gestures (<see cref="InventoryItemBase"/>s)
|
||||
/// </returns>
|
||||
public List<InventoryItemBase> fetchActiveGestures(UUID avatarID)
|
||||
{
|
||||
string sql = @"SELECT * FROM inventoryitems WHERE ""avatarID"" = :uuid AND ""assetType"" = :assetType and flags = 1";
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
cmd.Parameters.Add(database.CreateParameter("uuid", avatarID));
|
||||
cmd.Parameters.Add(database.CreateParameter("assetType", (int)AssetType.Gesture));
|
||||
conn.Open();
|
||||
using (NpgsqlDataReader reader = cmd.ExecuteReader())
|
||||
{
|
||||
List<InventoryItemBase> gestureList = new List<InventoryItemBase>();
|
||||
while (reader.Read())
|
||||
{
|
||||
gestureList.Add(readInventoryItem(reader));
|
||||
}
|
||||
return gestureList;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private methods
|
||||
|
||||
/// <summary>
|
||||
/// Delete an item in inventory database
|
||||
/// </summary>
|
||||
/// <param name="folderID">the item ID</param>
|
||||
/// <param name="connection">connection to the database</param>
|
||||
private void DeleteItemsInFolder(UUID folderID, NpgsqlConnection connection)
|
||||
{
|
||||
using (NpgsqlCommand command = new NpgsqlCommand(@"DELETE FROM inventoryitems WHERE ""folderID""=:folderID", connection))
|
||||
{
|
||||
command.Parameters.Add(database.CreateParameter("folderID", folderID));
|
||||
|
||||
try
|
||||
{
|
||||
command.ExecuteNonQuery();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error("[INVENTORY DB] Error deleting item :" + e.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the folder hierarchy in a loop.
|
||||
/// </summary>
|
||||
/// <param name="parentID">parent ID.</param>
|
||||
/// <param name="command">SQL command/connection to database</param>
|
||||
/// <returns></returns>
|
||||
private static List<InventoryFolderBase> getFolderHierarchy(UUID parentID, NpgsqlCommand command)
|
||||
{
|
||||
command.Parameters["parentID"].Value = parentID.Guid; //.ToString();
|
||||
|
||||
List<InventoryFolderBase> folders = getInventoryFolders(command);
|
||||
|
||||
if (folders.Count > 0)
|
||||
{
|
||||
List<InventoryFolderBase> tempFolders = new List<InventoryFolderBase>();
|
||||
|
||||
foreach (InventoryFolderBase folderBase in folders)
|
||||
{
|
||||
tempFolders.AddRange(getFolderHierarchy(folderBase.ID, command));
|
||||
}
|
||||
|
||||
if (tempFolders.Count > 0)
|
||||
{
|
||||
folders.AddRange(tempFolders);
|
||||
}
|
||||
}
|
||||
return folders;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the inventory folders.
|
||||
/// </summary>
|
||||
/// <param name="parentID">parentID, use UUID.Zero to get root</param>
|
||||
/// <param name="user">user id, use UUID.Zero, if you want all folders from a parentID.</param>
|
||||
/// <returns></returns>
|
||||
private List<InventoryFolderBase> getInventoryFolders(UUID parentID, UUID user)
|
||||
{
|
||||
string sql = @"SELECT * FROM inventoryfolders WHERE ""parentFolderID"" = :parentID AND ""agentID"" = :uuid";
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
|
||||
using (NpgsqlCommand command = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
if (user == UUID.Zero)
|
||||
{
|
||||
command.Parameters.Add(database.CreateParameter("uuid", "%"));
|
||||
}
|
||||
else
|
||||
{
|
||||
command.Parameters.Add(database.CreateParameter("uuid", user));
|
||||
}
|
||||
command.Parameters.Add(database.CreateParameter("parentID", parentID));
|
||||
conn.Open();
|
||||
return getInventoryFolders(command);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the inventory folders.
|
||||
/// </summary>
|
||||
/// <param name="command">SQLcommand.</param>
|
||||
/// <returns></returns>
|
||||
private static List<InventoryFolderBase> getInventoryFolders(NpgsqlCommand command)
|
||||
{
|
||||
using (NpgsqlDataReader reader = command.ExecuteReader())
|
||||
{
|
||||
|
||||
List<InventoryFolderBase> items = new List<InventoryFolderBase>();
|
||||
while (reader.Read())
|
||||
{
|
||||
items.Add(readInventoryFolder(reader));
|
||||
}
|
||||
return items;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a list of inventory folders returned by a query.
|
||||
/// </summary>
|
||||
/// <param name="reader">A PGSQL Data Reader</param>
|
||||
/// <returns>A List containing inventory folders</returns>
|
||||
protected static InventoryFolderBase readInventoryFolder(NpgsqlDataReader reader)
|
||||
{
|
||||
try
|
||||
{
|
||||
InventoryFolderBase folder = new InventoryFolderBase();
|
||||
folder.Owner = DBGuid.FromDB(reader["agentID"]);
|
||||
folder.ParentID = DBGuid.FromDB(reader["parentFolderID"]);
|
||||
folder.ID = DBGuid.FromDB(reader["folderID"]);
|
||||
folder.Name = (string)reader["folderName"];
|
||||
folder.Type = (short)reader["type"];
|
||||
folder.Version = Convert.ToUInt16(reader["version"]);
|
||||
|
||||
return folder;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error("[INVENTORY DB] Error reading inventory folder :" + e.Message);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a one item from an SQL result
|
||||
/// </summary>
|
||||
/// <param name="reader">The SQL Result</param>
|
||||
/// <returns>the item read</returns>
|
||||
private static InventoryItemBase readInventoryItem(IDataRecord reader)
|
||||
{
|
||||
try
|
||||
{
|
||||
InventoryItemBase item = new InventoryItemBase();
|
||||
|
||||
item.ID = DBGuid.FromDB(reader["inventoryID"]);
|
||||
item.AssetID = DBGuid.FromDB(reader["assetID"]);
|
||||
item.AssetType = Convert.ToInt32(reader["assetType"].ToString());
|
||||
item.Folder = DBGuid.FromDB(reader["parentFolderID"]);
|
||||
item.Owner = DBGuid.FromDB(reader["avatarID"]);
|
||||
item.Name = reader["inventoryName"].ToString();
|
||||
item.Description = reader["inventoryDescription"].ToString();
|
||||
item.NextPermissions = Convert.ToUInt32(reader["inventoryNextPermissions"]);
|
||||
item.CurrentPermissions = Convert.ToUInt32(reader["inventoryCurrentPermissions"]);
|
||||
item.InvType = Convert.ToInt32(reader["invType"].ToString());
|
||||
item.CreatorId = reader["creatorID"].ToString();
|
||||
item.BasePermissions = Convert.ToUInt32(reader["inventoryBasePermissions"]);
|
||||
item.EveryOnePermissions = Convert.ToUInt32(reader["inventoryEveryOnePermissions"]);
|
||||
item.GroupPermissions = Convert.ToUInt32(reader["inventoryGroupPermissions"]);
|
||||
item.SalePrice = Convert.ToInt32(reader["salePrice"]);
|
||||
item.SaleType = Convert.ToByte(reader["saleType"]);
|
||||
item.CreationDate = Convert.ToInt32(reader["creationDate"]);
|
||||
item.GroupID = DBGuid.FromDB(reader["groupID"]);
|
||||
item.GroupOwned = Convert.ToBoolean(reader["groupOwned"]);
|
||||
item.Flags = Convert.ToUInt32(reader["flags"]);
|
||||
|
||||
return item;
|
||||
}
|
||||
catch (NpgsqlException e)
|
||||
{
|
||||
m_log.Error("[INVENTORY DB]: Error reading inventory item :" + e.Message);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Delete a folder in inventory databasae
|
||||
/// </summary>
|
||||
/// <param name="folderID">the folder UUID</param>
|
||||
/// <param name="connection">connection to database</param>
|
||||
private void DeleteOneFolder(UUID folderID, NpgsqlConnection connection)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (NpgsqlCommand command = new NpgsqlCommand(@"DELETE FROM inventoryfolders WHERE ""folderID""=:folderID and type=-1", connection))
|
||||
{
|
||||
command.Parameters.Add(database.CreateParameter("folderID", folderID));
|
||||
|
||||
command.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
catch (NpgsqlException e)
|
||||
{
|
||||
m_log.Error("[INVENTORY DB]: Error deleting folder :" + e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
350
OpenSim/Data/PGSQL/PGSQLManager.cs
Normal file
350
OpenSim/Data/PGSQL/PGSQLManager.cs
Normal file
@@ -0,0 +1,350 @@
|
||||
/*
|
||||
* 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.IO;
|
||||
using System.Reflection;
|
||||
using OpenSim.Framework;
|
||||
using log4net;
|
||||
using OpenMetaverse;
|
||||
using Npgsql;
|
||||
using NpgsqlTypes;
|
||||
|
||||
namespace OpenSim.Data.PGSQL
|
||||
{
|
||||
/// <summary>
|
||||
/// A management class for the MS SQL Storage Engine
|
||||
/// </summary>
|
||||
public class PGSQLManager
|
||||
{
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
/// <summary>
|
||||
/// Connection string for ADO.net
|
||||
/// </summary>
|
||||
private readonly string connectionString;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the manager and set the connectionstring
|
||||
/// </summary>
|
||||
/// <param name="connection"></param>
|
||||
public PGSQLManager(string connection)
|
||||
{
|
||||
connectionString = connection;
|
||||
InitializeMonoSecurity();
|
||||
}
|
||||
|
||||
public void InitializeMonoSecurity()
|
||||
{
|
||||
if (!Util.IsPlatformMono)
|
||||
{
|
||||
if (AppDomain.CurrentDomain.GetData("MonoSecurityPostgresAdded") == null)
|
||||
{
|
||||
AppDomain.CurrentDomain.SetData("MonoSecurityPostgresAdded", "true");
|
||||
|
||||
AppDomain currentDomain = AppDomain.CurrentDomain;
|
||||
currentDomain.AssemblyResolve += new ResolveEventHandler(ResolveEventHandlerMonoSec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private System.Reflection.Assembly ResolveEventHandlerMonoSec(object sender, ResolveEventArgs args)
|
||||
{
|
||||
Assembly MyAssembly = null;
|
||||
|
||||
if (args.Name.Substring(0, args.Name.IndexOf(",")) == "Mono.Security")
|
||||
{
|
||||
MyAssembly = Assembly.LoadFrom("lib/NET/Mono.Security.dll");
|
||||
}
|
||||
|
||||
//Return the loaded assembly.
|
||||
return MyAssembly;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Type conversion to a SQLDbType functions
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
internal NpgsqlDbType DbtypeFromType(Type type)
|
||||
{
|
||||
if (type == typeof(string))
|
||||
{
|
||||
return NpgsqlDbType.Varchar;
|
||||
}
|
||||
if (type == typeof(double))
|
||||
{
|
||||
return NpgsqlDbType.Double;
|
||||
}
|
||||
if (type == typeof(Single))
|
||||
{
|
||||
return NpgsqlDbType.Double;
|
||||
}
|
||||
if (type == typeof(int))
|
||||
{
|
||||
return NpgsqlDbType.Integer;
|
||||
}
|
||||
if (type == typeof(bool))
|
||||
{
|
||||
return NpgsqlDbType.Boolean;
|
||||
}
|
||||
if (type == typeof(UUID))
|
||||
{
|
||||
return NpgsqlDbType.Uuid;
|
||||
}
|
||||
if (type == typeof(byte))
|
||||
{
|
||||
return NpgsqlDbType.Smallint;
|
||||
}
|
||||
if (type == typeof(sbyte))
|
||||
{
|
||||
return NpgsqlDbType.Integer;
|
||||
}
|
||||
if (type == typeof(Byte[]))
|
||||
{
|
||||
return NpgsqlDbType.Bytea;
|
||||
}
|
||||
if (type == typeof(uint) || type == typeof(ushort))
|
||||
{
|
||||
return NpgsqlDbType.Integer;
|
||||
}
|
||||
if (type == typeof(ulong))
|
||||
{
|
||||
return NpgsqlDbType.Bigint;
|
||||
}
|
||||
if (type == typeof(DateTime))
|
||||
{
|
||||
return NpgsqlDbType.Timestamp;
|
||||
}
|
||||
|
||||
return NpgsqlDbType.Varchar;
|
||||
}
|
||||
|
||||
internal NpgsqlDbType DbtypeFromString(Type type, string PGFieldType)
|
||||
{
|
||||
if (PGFieldType == "")
|
||||
{
|
||||
return DbtypeFromType(type);
|
||||
}
|
||||
|
||||
if (PGFieldType == "character varying")
|
||||
{
|
||||
return NpgsqlDbType.Varchar;
|
||||
}
|
||||
if (PGFieldType == "double precision")
|
||||
{
|
||||
return NpgsqlDbType.Double;
|
||||
}
|
||||
if (PGFieldType == "integer")
|
||||
{
|
||||
return NpgsqlDbType.Integer;
|
||||
}
|
||||
if (PGFieldType == "smallint")
|
||||
{
|
||||
return NpgsqlDbType.Smallint;
|
||||
}
|
||||
if (PGFieldType == "boolean")
|
||||
{
|
||||
return NpgsqlDbType.Boolean;
|
||||
}
|
||||
if (PGFieldType == "uuid")
|
||||
{
|
||||
return NpgsqlDbType.Uuid;
|
||||
}
|
||||
if (PGFieldType == "bytea")
|
||||
{
|
||||
return NpgsqlDbType.Bytea;
|
||||
}
|
||||
|
||||
return DbtypeFromType(type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates value for parameter.
|
||||
/// </summary>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <returns></returns>
|
||||
private static object CreateParameterValue(object value)
|
||||
{
|
||||
Type valueType = value.GetType();
|
||||
|
||||
if (valueType == typeof(UUID)) //TODO check if this works
|
||||
{
|
||||
return ((UUID) value).Guid;
|
||||
}
|
||||
if (valueType == typeof(UUID))
|
||||
{
|
||||
return ((UUID)value).Guid;
|
||||
}
|
||||
if (valueType == typeof(bool))
|
||||
{
|
||||
return (bool)value;
|
||||
}
|
||||
if (valueType == typeof(Byte[]))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
if (valueType == typeof(int))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create value for parameter based on PGSQL Schema
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="PGFieldType"></param>
|
||||
/// <returns></returns>
|
||||
internal static object CreateParameterValue(object value, string PGFieldType)
|
||||
{
|
||||
if (PGFieldType == "uuid")
|
||||
{
|
||||
UUID uidout;
|
||||
UUID.TryParse(value.ToString(), out uidout);
|
||||
return uidout;
|
||||
}
|
||||
if (PGFieldType == "integer")
|
||||
{
|
||||
int intout;
|
||||
int.TryParse(value.ToString(), out intout);
|
||||
return intout;
|
||||
}
|
||||
if (PGFieldType == "boolean")
|
||||
{
|
||||
return (value.ToString() == "true");
|
||||
}
|
||||
if (PGFieldType == "timestamp with time zone")
|
||||
{
|
||||
return (DateTime)value;
|
||||
}
|
||||
if (PGFieldType == "timestamp without time zone")
|
||||
{
|
||||
return (DateTime)value;
|
||||
}
|
||||
return CreateParameterValue(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a parameter for a command
|
||||
/// </summary>
|
||||
/// <param name="parameterName">Name of the parameter.</param>
|
||||
/// <param name="parameterObject">parameter object.</param>
|
||||
/// <returns></returns>
|
||||
internal NpgsqlParameter CreateParameter(string parameterName, object parameterObject)
|
||||
{
|
||||
return CreateParameter(parameterName, parameterObject, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the parameter for a command.
|
||||
/// </summary>
|
||||
/// <param name="parameterName">Name of the parameter.</param>
|
||||
/// <param name="parameterObject">parameter object.</param>
|
||||
/// <param name="parameterOut">if set to <c>true</c> parameter is a output parameter</param>
|
||||
/// <returns></returns>
|
||||
internal NpgsqlParameter CreateParameter(string parameterName, object parameterObject, bool parameterOut)
|
||||
{
|
||||
//Tweak so we dont always have to add : sign
|
||||
if (parameterName.StartsWith(":")) parameterName = parameterName.Replace(":","");
|
||||
|
||||
//HACK if object is null, it is turned into a string, there are no nullable type till now
|
||||
if (parameterObject == null) parameterObject = "";
|
||||
|
||||
NpgsqlParameter parameter = new NpgsqlParameter(parameterName, DbtypeFromType(parameterObject.GetType()));
|
||||
|
||||
if (parameterOut)
|
||||
{
|
||||
parameter.Direction = ParameterDirection.Output;
|
||||
}
|
||||
else
|
||||
{
|
||||
parameter.Direction = ParameterDirection.Input;
|
||||
parameter.Value = CreateParameterValue(parameterObject);
|
||||
}
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a parameter with PGSQL schema type
|
||||
/// </summary>
|
||||
/// <param name="parameterName"></param>
|
||||
/// <param name="parameterObject"></param>
|
||||
/// <param name="PGFieldType"></param>
|
||||
/// <returns></returns>
|
||||
internal NpgsqlParameter CreateParameter(string parameterName, object parameterObject, string PGFieldType)
|
||||
{
|
||||
//Tweak so we dont always have to add : sign
|
||||
if (parameterName.StartsWith(":")) parameterName = parameterName.Replace(":", "");
|
||||
|
||||
//HACK if object is null, it is turned into a string, there are no nullable type till now
|
||||
if (parameterObject == null) parameterObject = "";
|
||||
|
||||
NpgsqlParameter parameter = new NpgsqlParameter(parameterName, DbtypeFromString(parameterObject.GetType(), PGFieldType));
|
||||
|
||||
parameter.Direction = ParameterDirection.Input;
|
||||
parameter.Value = CreateParameterValue(parameterObject, PGFieldType);
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if we need to do some migrations to the database
|
||||
/// </summary>
|
||||
/// <param name="migrationStore">migrationStore.</param>
|
||||
public void CheckMigration(string migrationStore)
|
||||
{
|
||||
using (NpgsqlConnection connection = new NpgsqlConnection(connectionString))
|
||||
{
|
||||
connection.Open();
|
||||
Assembly assem = GetType().Assembly;
|
||||
PGSQLMigration migration = new PGSQLMigration(connection, assem, migrationStore);
|
||||
|
||||
migration.Update();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the version of this DB provider
|
||||
/// </summary>
|
||||
/// <returns>A string containing the DB provider</returns>
|
||||
public string getVersion()
|
||||
{
|
||||
Module module = GetType().Module;
|
||||
// string dllName = module.Assembly.ManifestModule.Name;
|
||||
Version dllVersion = module.Assembly.GetName().Version;
|
||||
|
||||
return
|
||||
string.Format("{0}.{1}.{2}.{3}", dllVersion.Major, dllVersion.Minor, dllVersion.Build,
|
||||
dllVersion.Revision);
|
||||
}
|
||||
}
|
||||
}
|
||||
102
OpenSim/Data/PGSQL/PGSQLMigration.cs
Normal file
102
OpenSim/Data/PGSQL/PGSQLMigration.cs
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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 Npgsql;
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.Reflection;
|
||||
|
||||
namespace OpenSim.Data.PGSQL
|
||||
{
|
||||
public class PGSQLMigration : Migration
|
||||
{
|
||||
public PGSQLMigration(NpgsqlConnection conn, Assembly assem, string type)
|
||||
: base(conn, assem, type)
|
||||
{
|
||||
}
|
||||
|
||||
public PGSQLMigration(NpgsqlConnection conn, Assembly assem, string subtype, string type)
|
||||
: base(conn, assem, subtype, type)
|
||||
{
|
||||
}
|
||||
|
||||
protected override int FindVersion(DbConnection conn, string type)
|
||||
{
|
||||
int version = 0;
|
||||
NpgsqlConnection lcConn = (NpgsqlConnection)conn;
|
||||
|
||||
using (NpgsqlCommand cmd = lcConn.CreateCommand())
|
||||
{
|
||||
try
|
||||
{
|
||||
cmd.CommandText = "select version from migrations where name = '" + type + "' " +
|
||||
" order by version desc limit 1"; //Must be
|
||||
using (NpgsqlDataReader reader = cmd.ExecuteReader())
|
||||
{
|
||||
if (reader.Read())
|
||||
{
|
||||
version = Convert.ToInt32(reader["version"]);
|
||||
}
|
||||
reader.Close();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Return -1 to indicate table does not exist
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
protected override void ExecuteScript(DbConnection conn, string[] script)
|
||||
{
|
||||
if (!(conn is NpgsqlConnection))
|
||||
{
|
||||
base.ExecuteScript(conn, script);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (string sql in script)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, (NpgsqlConnection)conn))
|
||||
{
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw new Exception(sql);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
56
OpenSim/Data/PGSQL/PGSQLOfflineIMData.cs
Normal file
56
OpenSim/Data/PGSQL/PGSQLOfflineIMData.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 System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using OpenSim.Framework;
|
||||
using OpenMetaverse;
|
||||
using Npgsql;
|
||||
|
||||
namespace OpenSim.Data.PGSQL
|
||||
{
|
||||
public class PGSQLOfflineIMData : PGSQLGenericTableHandler<OfflineIMData>, IOfflineIMData
|
||||
{
|
||||
public PGSQLOfflineIMData(string connectionString, string realm)
|
||||
: base(connectionString, realm, "IM_Store")
|
||||
{
|
||||
}
|
||||
|
||||
public void DeleteOld()
|
||||
{
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand())
|
||||
{
|
||||
cmd.CommandText = String.Format("delete from {0} where \"TMStamp\" < CURRENT_DATE - INTERVAL '2 week'", m_Realm);
|
||||
|
||||
ExecuteNonQuery(cmd);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
115
OpenSim/Data/PGSQL/PGSQLPresenceData.cs
Normal file
115
OpenSim/Data/PGSQL/PGSQLPresenceData.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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 Npgsql;
|
||||
|
||||
namespace OpenSim.Data.PGSQL
|
||||
{
|
||||
/// <summary>
|
||||
/// A PGSQL Interface for the Presence Server
|
||||
/// </summary>
|
||||
public class PGSQLPresenceData : PGSQLGenericTableHandler<PresenceData>,
|
||||
IPresenceData
|
||||
{
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
public PGSQLPresenceData(string connectionString, string realm) :
|
||||
base(connectionString, realm, "Presence")
|
||||
{
|
||||
}
|
||||
|
||||
public PresenceData Get(UUID sessionID)
|
||||
{
|
||||
PresenceData[] ret = Get("SessionID", sessionID.ToString());
|
||||
|
||||
if (ret.Length == 0)
|
||||
return null;
|
||||
|
||||
return ret[0];
|
||||
}
|
||||
|
||||
public void LogoutRegionAgents(UUID regionID)
|
||||
{
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand())
|
||||
{
|
||||
|
||||
cmd.CommandText = String.Format(@"DELETE FROM {0} WHERE ""RegionID""=:RegionID", m_Realm);
|
||||
|
||||
cmd.Parameters.Add(m_database.CreateParameter("RegionID", regionID));
|
||||
cmd.Connection = conn;
|
||||
conn.Open();
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
|
||||
public bool ReportAgent(UUID sessionID, UUID regionID)
|
||||
{
|
||||
PresenceData[] pd = Get("SessionID", sessionID.ToString());
|
||||
if (pd.Length == 0)
|
||||
return false;
|
||||
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand())
|
||||
{
|
||||
|
||||
cmd.CommandText = String.Format(@"UPDATE {0} SET
|
||||
""RegionID"" = :RegionID
|
||||
WHERE ""SessionID"" = :SessionID", m_Realm);
|
||||
|
||||
cmd.Parameters.Add(m_database.CreateParameter("SessionID", sessionID));
|
||||
cmd.Parameters.Add(m_database.CreateParameter("RegionID", regionID));
|
||||
cmd.Connection = conn;
|
||||
conn.Open();
|
||||
if (cmd.ExecuteNonQuery() == 0)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool VerifyAgent(UUID agentId, UUID secureSessionID)
|
||||
{
|
||||
PresenceData[] ret = Get("SecureSessionID", secureSessionID.ToString());
|
||||
|
||||
if (ret.Length == 0)
|
||||
return false;
|
||||
|
||||
if(ret[0].UserID != agentId.ToString())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
392
OpenSim/Data/PGSQL/PGSQLRegionData.cs
Normal file
392
OpenSim/Data/PGSQL/PGSQLRegionData.cs
Normal file
@@ -0,0 +1,392 @@
|
||||
/*
|
||||
* 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.Drawing;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using log4net;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using RegionFlags = OpenSim.Framework.RegionFlags;
|
||||
using Npgsql;
|
||||
|
||||
namespace OpenSim.Data.PGSQL
|
||||
{
|
||||
/// <summary>
|
||||
/// A PGSQL Interface for the Region Server.
|
||||
/// </summary>
|
||||
public class PGSQLRegionData : IRegionData
|
||||
{
|
||||
private string m_Realm;
|
||||
private List<string> m_ColumnNames = null;
|
||||
private string m_ConnectionString;
|
||||
private PGSQLManager m_database;
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
protected Dictionary<string, string> m_FieldTypes = new Dictionary<string, string>();
|
||||
|
||||
protected virtual Assembly Assembly
|
||||
{
|
||||
get { return GetType().Assembly; }
|
||||
}
|
||||
|
||||
public PGSQLRegionData(string connectionString, string realm)
|
||||
{
|
||||
m_Realm = realm;
|
||||
m_ConnectionString = connectionString;
|
||||
m_database = new PGSQLManager(connectionString);
|
||||
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
{
|
||||
conn.Open();
|
||||
Migration m = new Migration(conn, GetType().Assembly, "GridStore");
|
||||
m.Update();
|
||||
}
|
||||
LoadFieldTypes();
|
||||
}
|
||||
|
||||
private void LoadFieldTypes()
|
||||
{
|
||||
m_FieldTypes = new Dictionary<string, string>();
|
||||
|
||||
string query = string.Format(@"select column_name,data_type
|
||||
from INFORMATION_SCHEMA.COLUMNS
|
||||
where table_name = lower('{0}');
|
||||
|
||||
", m_Realm);
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(query, conn))
|
||||
{
|
||||
conn.Open();
|
||||
using (NpgsqlDataReader rdr = cmd.ExecuteReader())
|
||||
{
|
||||
while (rdr.Read())
|
||||
{
|
||||
// query produces 0 to many rows of single column, so always add the first item in each row
|
||||
m_FieldTypes.Add((string)rdr[0], (string)rdr[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<RegionData> Get(string regionName, UUID scopeID)
|
||||
{
|
||||
string sql = "select * from "+m_Realm+" where lower(\"regionName\") like lower(:regionName) ";
|
||||
if (scopeID != UUID.Zero)
|
||||
sql += " and \"ScopeID\" = :scopeID";
|
||||
sql += " order by lower(\"regionName\")";
|
||||
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
cmd.Parameters.Add(m_database.CreateParameter("regionName", regionName));
|
||||
if (scopeID != UUID.Zero)
|
||||
cmd.Parameters.Add(m_database.CreateParameter("scopeID", scopeID));
|
||||
conn.Open();
|
||||
return RunCommand(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
public RegionData Get(int posX, int posY, UUID scopeID)
|
||||
{
|
||||
string sql = "select * from "+m_Realm+" where \"locX\" = :posX and \"locY\" = :posY";
|
||||
if (scopeID != UUID.Zero)
|
||||
sql += " and \"ScopeID\" = :scopeID";
|
||||
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
cmd.Parameters.Add(m_database.CreateParameter("posX", posX));
|
||||
cmd.Parameters.Add(m_database.CreateParameter("posY", posY));
|
||||
if (scopeID != UUID.Zero)
|
||||
cmd.Parameters.Add(m_database.CreateParameter("scopeID", scopeID));
|
||||
conn.Open();
|
||||
List<RegionData> ret = RunCommand(cmd);
|
||||
if (ret.Count == 0)
|
||||
return null;
|
||||
|
||||
return ret[0];
|
||||
}
|
||||
}
|
||||
|
||||
public RegionData Get(UUID regionID, UUID scopeID)
|
||||
{
|
||||
string sql = "select * from "+m_Realm+" where uuid = :regionID";
|
||||
if (scopeID != UUID.Zero)
|
||||
sql += " and \"ScopeID\" = :scopeID";
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
cmd.Parameters.Add(m_database.CreateParameter("regionID", regionID));
|
||||
if (scopeID != UUID.Zero)
|
||||
cmd.Parameters.Add(m_database.CreateParameter("scopeID", scopeID));
|
||||
conn.Open();
|
||||
List<RegionData> ret = RunCommand(cmd);
|
||||
if (ret.Count == 0)
|
||||
return null;
|
||||
|
||||
return ret[0];
|
||||
}
|
||||
}
|
||||
|
||||
public List<RegionData> Get(int startX, int startY, int endX, int endY, UUID scopeID)
|
||||
{
|
||||
string sql = "select * from "+m_Realm+" where \"locX\" between :startX and :endX and \"locY\" between :startY and :endY";
|
||||
if (scopeID != UUID.Zero)
|
||||
sql += " and \"ScopeID\" = :scopeID";
|
||||
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
cmd.Parameters.Add(m_database.CreateParameter("startX", startX));
|
||||
cmd.Parameters.Add(m_database.CreateParameter("startY", startY));
|
||||
cmd.Parameters.Add(m_database.CreateParameter("endX", endX));
|
||||
cmd.Parameters.Add(m_database.CreateParameter("endY", endY));
|
||||
cmd.Parameters.Add(m_database.CreateParameter("scopeID", scopeID));
|
||||
conn.Open();
|
||||
return RunCommand(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
public List<RegionData> RunCommand(NpgsqlCommand cmd)
|
||||
{
|
||||
List<RegionData> retList = new List<RegionData>();
|
||||
|
||||
NpgsqlDataReader result = cmd.ExecuteReader();
|
||||
|
||||
while (result.Read())
|
||||
{
|
||||
RegionData ret = new RegionData();
|
||||
ret.Data = new Dictionary<string, object>();
|
||||
|
||||
UUID regionID;
|
||||
UUID.TryParse(result["uuid"].ToString(), out regionID);
|
||||
ret.RegionID = regionID;
|
||||
UUID scope;
|
||||
UUID.TryParse(result["ScopeID"].ToString(), out scope);
|
||||
ret.ScopeID = scope;
|
||||
ret.RegionName = result["regionName"].ToString();
|
||||
ret.posX = Convert.ToInt32(result["locX"]);
|
||||
ret.posY = Convert.ToInt32(result["locY"]);
|
||||
ret.sizeX = Convert.ToInt32(result["sizeX"]);
|
||||
ret.sizeY = Convert.ToInt32(result["sizeY"]);
|
||||
|
||||
if (m_ColumnNames == null)
|
||||
{
|
||||
m_ColumnNames = new List<string>();
|
||||
|
||||
DataTable schemaTable = result.GetSchemaTable();
|
||||
foreach (DataRow row in schemaTable.Rows)
|
||||
m_ColumnNames.Add(row["ColumnName"].ToString());
|
||||
}
|
||||
|
||||
foreach (string s in m_ColumnNames)
|
||||
{
|
||||
if (s == "uuid")
|
||||
continue;
|
||||
if (s == "ScopeID")
|
||||
continue;
|
||||
if (s == "regionName")
|
||||
continue;
|
||||
if (s == "locX")
|
||||
continue;
|
||||
if (s == "locY")
|
||||
continue;
|
||||
|
||||
ret.Data[s] = result[s].ToString();
|
||||
}
|
||||
|
||||
retList.Add(ret);
|
||||
}
|
||||
return retList;
|
||||
}
|
||||
|
||||
public bool Store(RegionData data)
|
||||
{
|
||||
if (data.Data.ContainsKey("uuid"))
|
||||
data.Data.Remove("uuid");
|
||||
if (data.Data.ContainsKey("ScopeID"))
|
||||
data.Data.Remove("ScopeID");
|
||||
if (data.Data.ContainsKey("regionName"))
|
||||
data.Data.Remove("regionName");
|
||||
if (data.Data.ContainsKey("posX"))
|
||||
data.Data.Remove("posX");
|
||||
if (data.Data.ContainsKey("posY"))
|
||||
data.Data.Remove("posY");
|
||||
if (data.Data.ContainsKey("sizeX"))
|
||||
data.Data.Remove("sizeX");
|
||||
if (data.Data.ContainsKey("sizeY"))
|
||||
data.Data.Remove("sizeY");
|
||||
if (data.Data.ContainsKey("locX"))
|
||||
data.Data.Remove("locX");
|
||||
if (data.Data.ContainsKey("locY"))
|
||||
data.Data.Remove("locY");
|
||||
|
||||
string[] fields = new List<string>(data.Data.Keys).ToArray();
|
||||
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand())
|
||||
{
|
||||
|
||||
string update = "update " + m_Realm + " set \"locX\"=:posX, \"locY\"=:posY, \"sizeX\"=:sizeX, \"sizeY\"=:sizeY ";
|
||||
|
||||
foreach (string field in fields)
|
||||
{
|
||||
|
||||
update += ", ";
|
||||
update += " \"" + field + "\" = :" + field;
|
||||
|
||||
if (m_FieldTypes.ContainsKey(field))
|
||||
cmd.Parameters.Add(m_database.CreateParameter(field, data.Data[field], m_FieldTypes[field]));
|
||||
else
|
||||
cmd.Parameters.Add(m_database.CreateParameter(field, data.Data[field]));
|
||||
}
|
||||
|
||||
update += " where uuid = :regionID";
|
||||
|
||||
if (data.ScopeID != UUID.Zero)
|
||||
update += " and \"ScopeID\" = :scopeID";
|
||||
|
||||
cmd.CommandText = update;
|
||||
cmd.Connection = conn;
|
||||
cmd.Parameters.Add(m_database.CreateParameter("regionID", data.RegionID));
|
||||
cmd.Parameters.Add(m_database.CreateParameter("regionName", data.RegionName));
|
||||
cmd.Parameters.Add(m_database.CreateParameter("scopeID", data.ScopeID));
|
||||
cmd.Parameters.Add(m_database.CreateParameter("posX", data.posX));
|
||||
cmd.Parameters.Add(m_database.CreateParameter("posY", data.posY));
|
||||
cmd.Parameters.Add(m_database.CreateParameter("sizeX", data.sizeX));
|
||||
cmd.Parameters.Add(m_database.CreateParameter("sizeY", data.sizeY));
|
||||
conn.Open();
|
||||
try
|
||||
{
|
||||
if (cmd.ExecuteNonQuery() < 1)
|
||||
{
|
||||
string insert = "insert into " + m_Realm + " (uuid, \"ScopeID\", \"locX\", \"locY\", \"sizeX\", \"sizeY\", \"regionName\", \"" +
|
||||
String.Join("\", \"", fields) +
|
||||
"\") values (:regionID, :scopeID, :posX, :posY, :sizeX, :sizeY, :regionName, :" + String.Join(", :", fields) + ")";
|
||||
|
||||
cmd.CommandText = insert;
|
||||
|
||||
try
|
||||
{
|
||||
if (cmd.ExecuteNonQuery() < 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
m_log.Warn("[PGSQL Grid]: Error inserting into Regions table: " + ex.Message + ", INSERT sql: " + insert);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
m_log.Warn("[PGSQL Grid]: Error updating Regions table: " + ex.Message + ", UPDATE sql: " + update);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool SetDataItem(UUID regionID, string item, string value)
|
||||
{
|
||||
string sql = "update " + m_Realm +
|
||||
" set \"" + item + "\" = :" + item + " where uuid = :UUID";
|
||||
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
cmd.Parameters.Add(m_database.CreateParameter("" + item, value));
|
||||
cmd.Parameters.Add(m_database.CreateParameter("UUID", regionID));
|
||||
conn.Open();
|
||||
if (cmd.ExecuteNonQuery() > 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool Delete(UUID regionID)
|
||||
{
|
||||
string sql = "delete from " + m_Realm +
|
||||
" where uuid = :UUID";
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
cmd.Parameters.Add(m_database.CreateParameter("UUID", regionID));
|
||||
conn.Open();
|
||||
if (cmd.ExecuteNonQuery() > 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<RegionData> GetDefaultRegions(UUID scopeID)
|
||||
{
|
||||
return Get((int)RegionFlags.DefaultRegion, scopeID);
|
||||
}
|
||||
|
||||
public List<RegionData> GetDefaultHypergridRegions(UUID scopeID)
|
||||
{
|
||||
return Get((int)RegionFlags.DefaultHGRegion, scopeID);
|
||||
}
|
||||
|
||||
public List<RegionData> GetFallbackRegions(UUID scopeID, int x, int y)
|
||||
{
|
||||
List<RegionData> regions = Get((int)RegionFlags.FallbackRegion, scopeID);
|
||||
RegionDataDistanceCompare distanceComparer = new RegionDataDistanceCompare(x, y);
|
||||
regions.Sort(distanceComparer);
|
||||
|
||||
return regions;
|
||||
}
|
||||
|
||||
public List<RegionData> GetHyperlinks(UUID scopeID)
|
||||
{
|
||||
return Get((int)RegionFlags.Hyperlink, scopeID);
|
||||
}
|
||||
|
||||
private List<RegionData> Get(int regionFlags, UUID scopeID)
|
||||
{
|
||||
string sql = "SELECT * FROM " + m_Realm + " WHERE (flags & " + regionFlags.ToString() + ") <> 0";
|
||||
if (scopeID != UUID.Zero)
|
||||
sql += " AND \"ScopeID\" = :scopeID";
|
||||
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
cmd.Parameters.Add(m_database.CreateParameter("scopeID", scopeID));
|
||||
conn.Open();
|
||||
return RunCommand(cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2247
OpenSim/Data/PGSQL/PGSQLSimulationData.cs
Normal file
2247
OpenSim/Data/PGSQL/PGSQLSimulationData.cs
Normal file
File diff suppressed because it is too large
Load Diff
325
OpenSim/Data/PGSQL/PGSQLUserAccountData.cs
Normal file
325
OpenSim/Data/PGSQL/PGSQLUserAccountData.cs
Normal file
@@ -0,0 +1,325 @@
|
||||
/*
|
||||
* 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.Data;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using System.Text;
|
||||
using Npgsql;
|
||||
using log4net;
|
||||
using System.Reflection;
|
||||
|
||||
namespace OpenSim.Data.PGSQL
|
||||
{
|
||||
public class PGSQLUserAccountData : PGSQLGenericTableHandler<UserAccountData>,IUserAccountData
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
|
||||
public PGSQLUserAccountData(string connectionString, string realm) :
|
||||
base(connectionString, realm, "UserAccount")
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
private string m_Realm;
|
||||
private List<string> m_ColumnNames = null;
|
||||
private PGSQLManager m_database;
|
||||
|
||||
public PGSQLUserAccountData(string connectionString, string realm) :
|
||||
base(connectionString, realm, "UserAccount")
|
||||
{
|
||||
m_Realm = realm;
|
||||
m_ConnectionString = connectionString;
|
||||
m_database = new PGSQLManager(connectionString);
|
||||
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
{
|
||||
conn.Open();
|
||||
Migration m = new Migration(conn, GetType().Assembly, "UserAccount");
|
||||
m.Update();
|
||||
}
|
||||
}
|
||||
*/
|
||||
/*
|
||||
public List<UserAccountData> Query(UUID principalID, UUID scopeID, string query)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
public override UserAccountData[] Get(string[] fields, string[] keys)
|
||||
{
|
||||
UserAccountData[] retUA = base.Get(fields,keys);
|
||||
|
||||
if (retUA.Length > 0)
|
||||
{
|
||||
Dictionary<string, string> data = retUA[0].Data;
|
||||
Dictionary<string, string> data2 = new Dictionary<string, string>();
|
||||
|
||||
foreach (KeyValuePair<string,string> chave in data)
|
||||
{
|
||||
string s2 = chave.Key;
|
||||
|
||||
data2[s2] = chave.Value;
|
||||
|
||||
if (!m_FieldTypes.ContainsKey(chave.Key))
|
||||
{
|
||||
string tipo = "";
|
||||
m_FieldTypes.TryGetValue(chave.Key, out tipo);
|
||||
m_FieldTypes.Add(s2, tipo);
|
||||
}
|
||||
}
|
||||
foreach (KeyValuePair<string, string> chave in data2)
|
||||
{
|
||||
if (!retUA[0].Data.ContainsKey(chave.Key))
|
||||
retUA[0].Data.Add(chave.Key, chave.Value);
|
||||
}
|
||||
}
|
||||
|
||||
return retUA;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
public UserAccountData Get(UUID principalID, UUID scopeID)
|
||||
{
|
||||
UserAccountData ret = new UserAccountData();
|
||||
ret.Data = new Dictionary<string, string>();
|
||||
|
||||
string sql = string.Format(@"select * from {0} where ""PrincipalID"" = :principalID", m_Realm);
|
||||
if (scopeID != UUID.Zero)
|
||||
sql += @" and ""ScopeID"" = :scopeID";
|
||||
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
cmd.Parameters.Add(m_database.CreateParameter("principalID", principalID));
|
||||
cmd.Parameters.Add(m_database.CreateParameter("scopeID", scopeID));
|
||||
|
||||
conn.Open();
|
||||
using (NpgsqlDataReader result = cmd.ExecuteReader())
|
||||
{
|
||||
if (result.Read())
|
||||
{
|
||||
ret.PrincipalID = principalID;
|
||||
UUID scope;
|
||||
UUID.TryParse(result["scopeid"].ToString(), out scope);
|
||||
ret.ScopeID = scope;
|
||||
|
||||
if (m_ColumnNames == null)
|
||||
{
|
||||
m_ColumnNames = new List<string>();
|
||||
|
||||
DataTable schemaTable = result.GetSchemaTable();
|
||||
foreach (DataRow row in schemaTable.Rows)
|
||||
m_ColumnNames.Add(row["ColumnName"].ToString());
|
||||
}
|
||||
|
||||
foreach (string s in m_ColumnNames)
|
||||
{
|
||||
string s2 = s;
|
||||
if (s2 == "uuid")
|
||||
continue;
|
||||
if (s2 == "scopeid")
|
||||
continue;
|
||||
|
||||
ret.Data[s] = result[s].ToString();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public override bool Store(UserAccountData data)
|
||||
{
|
||||
if (data.Data.ContainsKey("PrincipalID"))
|
||||
data.Data.Remove("PrincipalID");
|
||||
if (data.Data.ContainsKey("ScopeID"))
|
||||
data.Data.Remove("ScopeID");
|
||||
|
||||
string[] fields = new List<string>(data.Data.Keys).ToArray();
|
||||
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand())
|
||||
{
|
||||
m_log.DebugFormat("[USER]: Try to update user {0} {1}", data.FirstName, data.LastName);
|
||||
|
||||
StringBuilder updateBuilder = new StringBuilder();
|
||||
updateBuilder.AppendFormat("update {0} set ", m_Realm);
|
||||
bool first = true;
|
||||
foreach (string field in fields)
|
||||
{
|
||||
if (!first)
|
||||
updateBuilder.Append(", ");
|
||||
updateBuilder.AppendFormat("\"{0}\" = :{0}", field);
|
||||
|
||||
first = false;
|
||||
if (m_FieldTypes.ContainsKey(field))
|
||||
cmd.Parameters.Add(m_database.CreateParameter("" + field, data.Data[field], m_FieldTypes[field]));
|
||||
else
|
||||
cmd.Parameters.Add(m_database.CreateParameter("" + field, data.Data[field]));
|
||||
}
|
||||
|
||||
updateBuilder.Append(" where \"PrincipalID\" = :principalID");
|
||||
|
||||
if (data.ScopeID != UUID.Zero)
|
||||
updateBuilder.Append(" and \"ScopeID\" = :scopeID");
|
||||
|
||||
cmd.CommandText = updateBuilder.ToString();
|
||||
cmd.Connection = conn;
|
||||
cmd.Parameters.Add(m_database.CreateParameter("principalID", data.PrincipalID));
|
||||
cmd.Parameters.Add(m_database.CreateParameter("scopeID", data.ScopeID));
|
||||
|
||||
m_log.DebugFormat("[USER]: SQL update user {0} ", cmd.CommandText);
|
||||
|
||||
conn.Open();
|
||||
|
||||
m_log.DebugFormat("[USER]: CON opened update user {0} ", cmd.CommandText);
|
||||
|
||||
int conta = 0;
|
||||
try
|
||||
{
|
||||
conta = cmd.ExecuteNonQuery();
|
||||
}
|
||||
catch (Exception e){
|
||||
m_log.ErrorFormat("[USER]: ERROR opened update user {0} ", e.Message);
|
||||
}
|
||||
|
||||
|
||||
if (conta < 1)
|
||||
{
|
||||
m_log.DebugFormat("[USER]: Try to insert user {0} {1}", data.FirstName, data.LastName);
|
||||
|
||||
StringBuilder insertBuilder = new StringBuilder();
|
||||
insertBuilder.AppendFormat(@"insert into {0} (""PrincipalID"", ""ScopeID"", ""FirstName"", ""LastName"", """, m_Realm);
|
||||
insertBuilder.Append(String.Join(@""", """, fields));
|
||||
insertBuilder.Append(@""") values (:principalID, :scopeID, :FirstName, :LastName, :");
|
||||
insertBuilder.Append(String.Join(", :", fields));
|
||||
insertBuilder.Append(");");
|
||||
|
||||
cmd.Parameters.Add(m_database.CreateParameter("FirstName", data.FirstName));
|
||||
cmd.Parameters.Add(m_database.CreateParameter("LastName", data.LastName));
|
||||
|
||||
cmd.CommandText = insertBuilder.ToString();
|
||||
|
||||
if (cmd.ExecuteNonQuery() < 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
m_log.DebugFormat("[USER]: User {0} {1} exists", data.FirstName, data.LastName);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public bool Store(UserAccountData data, UUID principalID, string token)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public bool SetDataItem(UUID principalID, string item, string value)
|
||||
{
|
||||
string sql = string.Format(@"update {0} set {1} = :{1} where ""UUID"" = :UUID", m_Realm, item);
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
if (m_FieldTypes.ContainsKey(item))
|
||||
cmd.Parameters.Add(m_database.CreateParameter("" + item, value, m_FieldTypes[item]));
|
||||
else
|
||||
cmd.Parameters.Add(m_database.CreateParameter("" + item, value));
|
||||
|
||||
cmd.Parameters.Add(m_database.CreateParameter("UUID", principalID));
|
||||
conn.Open();
|
||||
|
||||
if (cmd.ExecuteNonQuery() > 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
public UserAccountData[] Get(string[] keys, string[] vals)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
*/
|
||||
|
||||
public UserAccountData[] GetUsers(UUID scopeID, string query)
|
||||
{
|
||||
string[] words = query.Split(new char[] { ' ' });
|
||||
|
||||
for (int i = 0; i < words.Length; i++)
|
||||
{
|
||||
if (words[i].Length < 3)
|
||||
{
|
||||
if (i != words.Length - 1)
|
||||
Array.Copy(words, i + 1, words, i, words.Length - i - 1);
|
||||
Array.Resize(ref words, words.Length - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (words.Length == 0)
|
||||
return new UserAccountData[0];
|
||||
|
||||
if (words.Length > 2)
|
||||
return new UserAccountData[0];
|
||||
|
||||
string sql = "";
|
||||
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand())
|
||||
{
|
||||
if (words.Length == 1)
|
||||
{
|
||||
sql = String.Format(@"select * from {0} where (""ScopeID""=:ScopeID or ""ScopeID""='00000000-0000-0000-0000-000000000000') and (""FirstName"" ilike :search or ""LastName"" ilike :search)", m_Realm);
|
||||
cmd.Parameters.Add(m_database.CreateParameter("scopeID", scopeID));
|
||||
cmd.Parameters.Add(m_database.CreateParameter("search", "%" + words[0] + "%"));
|
||||
}
|
||||
else
|
||||
{
|
||||
sql = String.Format(@"select * from {0} where (""ScopeID""=:ScopeID or ""ScopeID""='00000000-0000-0000-0000-000000000000') and (""FirstName"" ilike :searchFirst or ""LastName"" ilike :searchLast)", m_Realm);
|
||||
cmd.Parameters.Add(m_database.CreateParameter("searchFirst", "%" + words[0] + "%"));
|
||||
cmd.Parameters.Add(m_database.CreateParameter("searchLast", "%" + words[1] + "%"));
|
||||
cmd.Parameters.Add(m_database.CreateParameter("ScopeID", scopeID.ToString()));
|
||||
}
|
||||
cmd.Connection = conn;
|
||||
cmd.CommandText = sql;
|
||||
conn.Open();
|
||||
return DoQuery(cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1075
OpenSim/Data/PGSQL/PGSQLUserProfilesData.cs
Normal file
1075
OpenSim/Data/PGSQL/PGSQLUserProfilesData.cs
Normal file
File diff suppressed because it is too large
Load Diff
535
OpenSim/Data/PGSQL/PGSQLXAssetData.cs
Normal file
535
OpenSim/Data/PGSQL/PGSQLXAssetData.cs
Normal file
@@ -0,0 +1,535 @@
|
||||
/*
|
||||
* 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.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Reflection;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using log4net;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Data;
|
||||
using Npgsql;
|
||||
|
||||
namespace OpenSim.Data.PGSQL
|
||||
{
|
||||
public class PGSQLXAssetData : IXAssetDataPlugin
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
protected virtual Assembly Assembly
|
||||
{
|
||||
get { return GetType().Assembly; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Number of days that must pass before we update the access time on an asset when it has been fetched.
|
||||
/// </summary>
|
||||
private const int DaysBetweenAccessTimeUpdates = 30;
|
||||
|
||||
private bool m_enableCompression = false;
|
||||
private string m_connectionString;
|
||||
private object m_dbLock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// We can reuse this for all hashing since all methods are single-threaded through m_dbBLock
|
||||
/// </summary>
|
||||
private HashAlgorithm hasher = new SHA256CryptoServiceProvider();
|
||||
|
||||
#region IPlugin Members
|
||||
|
||||
public string Version { get { return "1.0.0.0"; } }
|
||||
|
||||
/// <summary>
|
||||
/// <para>Initialises Asset interface</para>
|
||||
/// <para>
|
||||
/// <list type="bullet">
|
||||
/// <item>Loads and initialises the PGSQL storage plugin.</item>
|
||||
/// <item>Warns and uses the obsolete pgsql_connection.ini if connect string is empty.</item>
|
||||
/// <item>Check for migration</item>
|
||||
/// </list>
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="connect">connect string</param>
|
||||
public void Initialise(string connect)
|
||||
{
|
||||
m_log.ErrorFormat("[PGSQL XASSETDATA]: ***********************************************************");
|
||||
m_log.ErrorFormat("[PGSQL XASSETDATA]: ***********************************************************");
|
||||
m_log.ErrorFormat("[PGSQL XASSETDATA]: ***********************************************************");
|
||||
m_log.ErrorFormat("[PGSQL XASSETDATA]: THIS PLUGIN IS STRICTLY EXPERIMENTAL.");
|
||||
m_log.ErrorFormat("[PGSQL XASSETDATA]: DO NOT USE FOR ANY DATA THAT YOU DO NOT MIND LOSING.");
|
||||
m_log.ErrorFormat("[PGSQL XASSETDATA]: DATABASE TABLES CAN CHANGE AT ANY TIME, CAUSING EXISTING DATA TO BE LOST.");
|
||||
m_log.ErrorFormat("[PGSQL XASSETDATA]: ***********************************************************");
|
||||
m_log.ErrorFormat("[PGSQL XASSETDATA]: ***********************************************************");
|
||||
m_log.ErrorFormat("[PGSQL XASSETDATA]: ***********************************************************");
|
||||
|
||||
m_connectionString = connect;
|
||||
|
||||
using (NpgsqlConnection dbcon = new NpgsqlConnection(m_connectionString))
|
||||
{
|
||||
dbcon.Open();
|
||||
Migration m = new Migration(dbcon, Assembly, "XAssetStore");
|
||||
m.Update();
|
||||
}
|
||||
}
|
||||
|
||||
public void Initialise()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Dispose() { }
|
||||
|
||||
/// <summary>
|
||||
/// The name of this DB provider
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get { return "PGSQL XAsset storage engine"; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IAssetDataPlugin Members
|
||||
|
||||
/// <summary>
|
||||
/// Fetch Asset <paramref name="assetID"/> from database
|
||||
/// </summary>
|
||||
/// <param name="assetID">Asset UUID to fetch</param>
|
||||
/// <returns>Return the asset</returns>
|
||||
/// <remarks>On failure : throw an exception and attempt to reconnect to database</remarks>
|
||||
public AssetBase GetAsset(UUID assetID)
|
||||
{
|
||||
// m_log.DebugFormat("[PGSQL XASSET DATA]: Looking for asset {0}", assetID);
|
||||
|
||||
AssetBase asset = null;
|
||||
lock (m_dbLock)
|
||||
{
|
||||
using (NpgsqlConnection dbcon = new NpgsqlConnection(m_connectionString))
|
||||
{
|
||||
dbcon.Open();
|
||||
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(
|
||||
@"SELECT ""Name"", ""Description"", ""AccessTime"", ""AssetType"", ""Local"", ""Temporary"", ""AssetFlags"", ""CreatorID"", ""Data""
|
||||
FROM XAssetsMeta
|
||||
JOIN XAssetsData ON XAssetsMeta.Hash = XAssetsData.Hash WHERE ""ID""=:ID",
|
||||
dbcon))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("ID", assetID.ToString());
|
||||
|
||||
try
|
||||
{
|
||||
using (NpgsqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow))
|
||||
{
|
||||
if (dbReader.Read())
|
||||
{
|
||||
asset = new AssetBase(assetID, (string)dbReader["Name"], (sbyte)dbReader["AssetType"], dbReader["CreatorID"].ToString());
|
||||
asset.Data = (byte[])dbReader["Data"];
|
||||
asset.Description = (string)dbReader["Description"];
|
||||
|
||||
string local = dbReader["Local"].ToString();
|
||||
if (local.Equals("1") || local.Equals("true", StringComparison.InvariantCultureIgnoreCase))
|
||||
asset.Local = true;
|
||||
else
|
||||
asset.Local = false;
|
||||
|
||||
asset.Temporary = Convert.ToBoolean(dbReader["Temporary"]);
|
||||
asset.Flags = (AssetFlags)Convert.ToInt32(dbReader["AssetFlags"]);
|
||||
|
||||
if (m_enableCompression)
|
||||
{
|
||||
using (GZipStream decompressionStream = new GZipStream(new MemoryStream(asset.Data), CompressionMode.Decompress))
|
||||
{
|
||||
MemoryStream outputStream = new MemoryStream();
|
||||
WebUtil.CopyStream(decompressionStream, outputStream, int.MaxValue);
|
||||
// int compressedLength = asset.Data.Length;
|
||||
asset.Data = outputStream.ToArray();
|
||||
|
||||
// m_log.DebugFormat(
|
||||
// "[XASSET DB]: Decompressed {0} {1} to {2} bytes from {3}",
|
||||
// asset.ID, asset.Name, asset.Data.Length, compressedLength);
|
||||
}
|
||||
}
|
||||
|
||||
UpdateAccessTime(asset.Metadata, (int)dbReader["AccessTime"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error(string.Format("[PGSQL XASSET DATA]: Failure fetching asset {0}", assetID), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return asset;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create an asset in database, or update it if existing.
|
||||
/// </summary>
|
||||
/// <param name="asset">Asset UUID to create</param>
|
||||
/// <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 (NpgsqlConnection dbcon = new NpgsqlConnection(m_connectionString))
|
||||
{
|
||||
dbcon.Open();
|
||||
|
||||
using (NpgsqlTransaction transaction = dbcon.BeginTransaction())
|
||||
{
|
||||
string assetName = asset.Name;
|
||||
if (asset.Name.Length > 64)
|
||||
{
|
||||
assetName = asset.Name.Substring(0, 64);
|
||||
m_log.WarnFormat(
|
||||
"[XASSET DB]: Name '{0}' for asset {1} truncated from {2} to {3} characters on add",
|
||||
asset.Name, asset.ID, asset.Name.Length, assetName.Length);
|
||||
}
|
||||
|
||||
string assetDescription = asset.Description;
|
||||
if (asset.Description.Length > 64)
|
||||
{
|
||||
assetDescription = asset.Description.Substring(0, 64);
|
||||
m_log.WarnFormat(
|
||||
"[XASSET DB]: Description '{0}' for asset {1} truncated from {2} to {3} characters on add",
|
||||
asset.Description, asset.ID, asset.Description.Length, assetDescription.Length);
|
||||
}
|
||||
|
||||
if (m_enableCompression)
|
||||
{
|
||||
MemoryStream outputStream = new MemoryStream();
|
||||
|
||||
using (GZipStream compressionStream = new GZipStream(outputStream, CompressionMode.Compress, false))
|
||||
{
|
||||
// Console.WriteLine(WebUtil.CopyTo(new MemoryStream(asset.Data), compressionStream, int.MaxValue));
|
||||
// We have to close the compression stream in order to make sure it writes everything out to the underlying memory output stream.
|
||||
compressionStream.Close();
|
||||
byte[] compressedData = outputStream.ToArray();
|
||||
asset.Data = compressedData;
|
||||
}
|
||||
}
|
||||
|
||||
byte[] hash = hasher.ComputeHash(asset.Data);
|
||||
|
||||
// m_log.DebugFormat(
|
||||
// "[XASSET DB]: Compressed data size for {0} {1}, hash {2} is {3}",
|
||||
// asset.ID, asset.Name, hash, compressedData.Length);
|
||||
|
||||
try
|
||||
{
|
||||
using (NpgsqlCommand cmd =
|
||||
new NpgsqlCommand(
|
||||
@"insert INTO XAssetsMeta(""ID"", ""Hash"", ""Name"", ""Description"", ""AssetType"", ""Local"", ""Temporary"", ""CreateTime"", ""AccessTime"", ""AssetFlags"", ""CreatorID"")
|
||||
Select :ID, :Hash, :Name, :Description, :AssetType, :Local, :Temporary, :CreateTime, :AccessTime, :AssetFlags, :CreatorID
|
||||
where not exists( Select ""ID"" from XAssetsMeta where ""ID"" = :ID ;
|
||||
|
||||
update XAssetsMeta
|
||||
set ""ID"" = :ID, ""Hash"" = :Hash, ""Name"" = :Name, ""Description"" = :Description,
|
||||
""AssetType"" = :AssetType, ""Local"" = :Local, ""Temporary"" = :Temporary, ""CreateTime"" = :CreateTime,
|
||||
""AccessTime"" = :AccessTime, ""AssetFlags"" = :AssetFlags, ""CreatorID"" = :CreatorID
|
||||
where ""ID"" = :ID;
|
||||
",
|
||||
dbcon))
|
||||
{
|
||||
// create unix epoch time
|
||||
int now = (int)Utils.DateTimeToUnixTime(DateTime.UtcNow);
|
||||
cmd.Parameters.AddWithValue("ID", asset.ID);
|
||||
cmd.Parameters.AddWithValue("Hash", hash);
|
||||
cmd.Parameters.AddWithValue("Name", assetName);
|
||||
cmd.Parameters.AddWithValue("Description", assetDescription);
|
||||
cmd.Parameters.AddWithValue("AssetType", asset.Type);
|
||||
cmd.Parameters.AddWithValue("Local", asset.Local);
|
||||
cmd.Parameters.AddWithValue("Temporary", asset.Temporary);
|
||||
cmd.Parameters.AddWithValue("CreateTime", now);
|
||||
cmd.Parameters.AddWithValue("AccessTime", now);
|
||||
cmd.Parameters.AddWithValue("CreatorID", asset.Metadata.CreatorID);
|
||||
cmd.Parameters.AddWithValue("AssetFlags", (int)asset.Flags);
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("[ASSET DB]: PGSQL failure creating asset metadata {0} with name \"{1}\". Error: {2}",
|
||||
asset.FullID, asset.Name, e.Message);
|
||||
|
||||
transaction.Rollback();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ExistsData(dbcon, transaction, hash))
|
||||
{
|
||||
try
|
||||
{
|
||||
using (NpgsqlCommand cmd =
|
||||
new NpgsqlCommand(
|
||||
@"INSERT INTO XAssetsData(""Hash"", ""Data"") VALUES(:Hash, :Data)",
|
||||
dbcon))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("Hash", hash);
|
||||
cmd.Parameters.AddWithValue("Data", asset.Data);
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("[XASSET DB]: PGSQL failure creating asset data {0} with name \"{1}\". Error: {2}",
|
||||
asset.FullID, asset.Name, e.Message);
|
||||
|
||||
transaction.Rollback();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
transaction.Commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the access time of the asset if it was accessed above a given threshhold amount of time.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This gives us some insight into assets which haven't ben accessed for a long period. This is only done
|
||||
/// over the threshold time to avoid excessive database writes as assets are fetched.
|
||||
/// </remarks>
|
||||
/// <param name='asset'></param>
|
||||
/// <param name='accessTime'></param>
|
||||
private void UpdateAccessTime(AssetMetadata assetMetadata, int accessTime)
|
||||
{
|
||||
DateTime now = DateTime.UtcNow;
|
||||
|
||||
if ((now - Utils.UnixTimeToDateTime(accessTime)).TotalDays < DaysBetweenAccessTimeUpdates)
|
||||
return;
|
||||
|
||||
lock (m_dbLock)
|
||||
{
|
||||
using (NpgsqlConnection dbcon = new NpgsqlConnection(m_connectionString))
|
||||
{
|
||||
dbcon.Open();
|
||||
NpgsqlCommand cmd =
|
||||
new NpgsqlCommand(@"update XAssetsMeta set ""AccessTime""=:AccessTime where ID=:ID", dbcon);
|
||||
|
||||
try
|
||||
{
|
||||
using (cmd)
|
||||
{
|
||||
// create unix epoch time
|
||||
cmd.Parameters.AddWithValue("ID", assetMetadata.ID);
|
||||
cmd.Parameters.AddWithValue("AccessTime", (int)Utils.DateTimeToUnixTime(now));
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat(
|
||||
"[XASSET PGSQL DB]: Failure updating access_time for asset {0} with name {1} : {2}",
|
||||
assetMetadata.ID, assetMetadata.Name, e.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// We assume we already have the m_dbLock.
|
||||
/// </summary>
|
||||
/// TODO: need to actually use the transaction.
|
||||
/// <param name="dbcon"></param>
|
||||
/// <param name="transaction"></param>
|
||||
/// <param name="hash"></param>
|
||||
/// <returns></returns>
|
||||
private bool ExistsData(NpgsqlConnection dbcon, NpgsqlTransaction transaction, byte[] hash)
|
||||
{
|
||||
// m_log.DebugFormat("[ASSETS DB]: Checking for asset {0}", uuid);
|
||||
|
||||
bool exists = false;
|
||||
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(@"SELECT ""Hash"" FROM XAssetsData WHERE ""Hash""=:Hash", dbcon))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("Hash", hash);
|
||||
|
||||
try
|
||||
{
|
||||
using (NpgsqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow))
|
||||
{
|
||||
if (dbReader.Read())
|
||||
{
|
||||
// m_log.DebugFormat("[ASSETS DB]: Found asset {0}", uuid);
|
||||
exists = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat(
|
||||
"[XASSETS DB]: PGSql failure in ExistsData fetching hash {0}. Exception {1}{2}",
|
||||
hash, e.Message, e.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
return exists;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the asset exists in the database
|
||||
/// </summary>
|
||||
/// <param name="uuid">The asset UUID</param>
|
||||
/// <returns>true if it exists, false otherwise.</returns>
|
||||
public bool ExistsAsset(UUID uuid)
|
||||
{
|
||||
// m_log.DebugFormat("[ASSETS DB]: Checking for asset {0}", uuid);
|
||||
|
||||
bool assetExists = false;
|
||||
|
||||
lock (m_dbLock)
|
||||
{
|
||||
using (NpgsqlConnection dbcon = new NpgsqlConnection(m_connectionString))
|
||||
{
|
||||
dbcon.Open();
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(@"SELECT ""ID"" FROM XAssetsMeta WHERE ""ID""=:ID", dbcon))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("ID", uuid.ToString());
|
||||
|
||||
try
|
||||
{
|
||||
using (NpgsqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow))
|
||||
{
|
||||
if (dbReader.Read())
|
||||
{
|
||||
// m_log.DebugFormat("[ASSETS DB]: Found asset {0}", uuid);
|
||||
assetExists = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error(string.Format("[XASSETS DB]: PGSql failure fetching asset {0}", uuid), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return assetExists;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of AssetMetadata objects. The list is a subset of
|
||||
/// the entire data set offset by <paramref name="start" /> containing
|
||||
/// <paramref name="count" /> elements.
|
||||
/// </summary>
|
||||
/// <param name="start">The number of results to discard from the total data set.</param>
|
||||
/// <param name="count">The number of rows the returned list should contain.</param>
|
||||
/// <returns>A list of AssetMetadata objects.</returns>
|
||||
public List<AssetMetadata> FetchAssetMetadataSet(int start, int count)
|
||||
{
|
||||
List<AssetMetadata> retList = new List<AssetMetadata>(count);
|
||||
|
||||
lock (m_dbLock)
|
||||
{
|
||||
using (NpgsqlConnection dbcon = new NpgsqlConnection(m_connectionString))
|
||||
{
|
||||
dbcon.Open();
|
||||
NpgsqlCommand cmd = new NpgsqlCommand( @"SELECT ""Name"", ""Description"", ""AccessTime"", ""AssetType"", ""Temporary"", ""ID"", ""AssetFlags"", ""CreatorID""
|
||||
FROM XAssetsMeta
|
||||
LIMIT :start, :count", dbcon);
|
||||
cmd.Parameters.AddWithValue("start", start);
|
||||
cmd.Parameters.AddWithValue("count", count);
|
||||
|
||||
try
|
||||
{
|
||||
using (NpgsqlDataReader dbReader = cmd.ExecuteReader())
|
||||
{
|
||||
while (dbReader.Read())
|
||||
{
|
||||
AssetMetadata metadata = new AssetMetadata();
|
||||
metadata.Name = (string)dbReader["Name"];
|
||||
metadata.Description = (string)dbReader["Description"];
|
||||
metadata.Type = (sbyte)dbReader["AssetType"];
|
||||
metadata.Temporary = Convert.ToBoolean(dbReader["Temporary"]); // Not sure if this is correct.
|
||||
metadata.Flags = (AssetFlags)Convert.ToInt32(dbReader["AssetFlags"]);
|
||||
metadata.FullID = DBGuid.FromDB(dbReader["ID"]);
|
||||
metadata.CreatorID = dbReader["CreatorID"].ToString();
|
||||
|
||||
// We'll ignore this for now - it appears unused!
|
||||
// metadata.SHA1 = dbReader["hash"]);
|
||||
|
||||
UpdateAccessTime(metadata, (int)dbReader["AccessTime"]);
|
||||
|
||||
retList.Add(metadata);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error("[XASSETS DB]: PGSql failure fetching asset set" + Environment.NewLine + e.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retList;
|
||||
}
|
||||
|
||||
public bool Delete(string id)
|
||||
{
|
||||
// m_log.DebugFormat("[XASSETS DB]: Deleting asset {0}", id);
|
||||
|
||||
lock (m_dbLock)
|
||||
{
|
||||
using (NpgsqlConnection dbcon = new NpgsqlConnection(m_connectionString))
|
||||
{
|
||||
dbcon.Open();
|
||||
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(@"delete from XAssetsMeta where ""ID""=:ID", dbcon))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("ID", id);
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
// TODO: How do we deal with data from deleted assets? Probably not easily reapable unless we
|
||||
// keep a reference count (?)
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
330
OpenSim/Data/PGSQL/PGSQLXInventoryData.cs
Normal file
330
OpenSim/Data/PGSQL/PGSQLXInventoryData.cs
Normal file
@@ -0,0 +1,330 @@
|
||||
/*
|
||||
* 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.Data;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using log4net;
|
||||
using Npgsql;
|
||||
using NpgsqlTypes;
|
||||
|
||||
namespace OpenSim.Data.PGSQL
|
||||
{
|
||||
public class PGSQLXInventoryData : IXInventoryData
|
||||
{
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(
|
||||
// MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private PGSQLFolderHandler m_Folders;
|
||||
private PGSQLItemHandler m_Items;
|
||||
|
||||
public PGSQLXInventoryData(string conn, string realm)
|
||||
{
|
||||
m_Folders = new PGSQLFolderHandler(
|
||||
conn, "inventoryfolders", "InventoryStore");
|
||||
m_Items = new PGSQLItemHandler(
|
||||
conn, "inventoryitems", String.Empty);
|
||||
}
|
||||
|
||||
public static UUID str2UUID(string strUUID)
|
||||
{
|
||||
UUID newUUID = UUID.Zero;
|
||||
|
||||
UUID.TryParse(strUUID, out newUUID);
|
||||
|
||||
return newUUID;
|
||||
}
|
||||
|
||||
public XInventoryFolder[] GetFolders(string[] fields, string[] vals)
|
||||
{
|
||||
return m_Folders.Get(fields, vals);
|
||||
}
|
||||
|
||||
public XInventoryItem[] GetItems(string[] fields, string[] vals)
|
||||
{
|
||||
return m_Items.Get(fields, vals);
|
||||
}
|
||||
|
||||
public bool StoreFolder(XInventoryFolder folder)
|
||||
{
|
||||
if (folder.folderName.Length > 64)
|
||||
folder.folderName = folder.folderName.Substring(0, 64);
|
||||
return m_Folders.Store(folder);
|
||||
}
|
||||
|
||||
public bool StoreItem(XInventoryItem item)
|
||||
{
|
||||
if (item.inventoryName.Length > 64)
|
||||
item.inventoryName = item.inventoryName.Substring(0, 64);
|
||||
if (item.inventoryDescription.Length > 128)
|
||||
item.inventoryDescription = item.inventoryDescription.Substring(0, 128);
|
||||
|
||||
return m_Items.Store(item);
|
||||
}
|
||||
|
||||
public bool DeleteFolders(string field, string val)
|
||||
{
|
||||
return m_Folders.Delete(field, val);
|
||||
}
|
||||
|
||||
public bool DeleteFolders(string[] fields, string[] vals)
|
||||
{
|
||||
return m_Folders.Delete(fields, vals);
|
||||
}
|
||||
|
||||
public bool DeleteItems(string field, string val)
|
||||
{
|
||||
return m_Items.Delete(field, val);
|
||||
}
|
||||
|
||||
public bool DeleteItems(string[] fields, string[] vals)
|
||||
{
|
||||
return m_Items.Delete(fields, vals);
|
||||
}
|
||||
|
||||
public bool MoveItem(string id, string newParent)
|
||||
{
|
||||
return m_Items.MoveItem(id, newParent);
|
||||
}
|
||||
|
||||
public bool MoveFolder(string id, string newParent)
|
||||
{
|
||||
return m_Folders.MoveFolder(id, newParent);
|
||||
}
|
||||
|
||||
public XInventoryItem[] GetActiveGestures(UUID principalID)
|
||||
{
|
||||
return m_Items.GetActiveGestures(principalID.ToString());
|
||||
}
|
||||
|
||||
public int GetAssetPermissions(UUID principalID, UUID assetID)
|
||||
{
|
||||
return m_Items.GetAssetPermissions(principalID, assetID);
|
||||
}
|
||||
}
|
||||
|
||||
public class PGSQLItemHandler : PGSQLInventoryHandler<XInventoryItem>
|
||||
{
|
||||
public PGSQLItemHandler(string c, string t, string m) :
|
||||
base(c, t, m)
|
||||
{
|
||||
}
|
||||
|
||||
public bool MoveItem(string id, string newParent)
|
||||
{
|
||||
XInventoryItem[] retrievedItems = Get(new string[] { "inventoryID" }, new string[] { id });
|
||||
if (retrievedItems.Length == 0)
|
||||
return false;
|
||||
|
||||
UUID oldParent = retrievedItems[0].parentFolderID;
|
||||
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
{
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand())
|
||||
{
|
||||
cmd.CommandText = String.Format(@"update {0} set ""parentFolderID"" = :ParentFolderID where ""inventoryID"" = :InventoryID", m_Realm);
|
||||
cmd.Parameters.Add(m_database.CreateParameter("ParentFolderID", newParent));
|
||||
cmd.Parameters.Add(m_database.CreateParameter("InventoryID", id ));
|
||||
cmd.Connection = conn;
|
||||
conn.Open();
|
||||
|
||||
if (cmd.ExecuteNonQuery() == 0)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
IncrementFolderVersion(oldParent);
|
||||
IncrementFolderVersion(newParent);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public XInventoryItem[] GetActiveGestures(string principalID)
|
||||
{
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
{
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand())
|
||||
{
|
||||
cmd.CommandText = String.Format(@"select * from inventoryitems where ""avatarID"" = :uuid and ""assetType"" = :type and ""flags"" = 1", m_Realm);
|
||||
|
||||
UUID princID = UUID.Zero;
|
||||
UUID.TryParse(principalID, out princID);
|
||||
|
||||
cmd.Parameters.Add(m_database.CreateParameter("uuid", principalID));
|
||||
cmd.Parameters.Add(m_database.CreateParameter("type", (int)AssetType.Gesture));
|
||||
cmd.Connection = conn;
|
||||
conn.Open();
|
||||
return DoQuery(cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int GetAssetPermissions(UUID principalID, UUID assetID)
|
||||
{
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
{
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand())
|
||||
{
|
||||
cmd.CommandText = String.Format(@"select bit_or(""inventoryCurrentPermissions"") as ""inventoryCurrentPermissions""
|
||||
from inventoryitems
|
||||
where ""avatarID"" = :PrincipalID
|
||||
and ""assetID"" = :AssetID
|
||||
group by ""assetID"" ", m_Realm);
|
||||
|
||||
cmd.Parameters.Add(m_database.CreateParameter("PrincipalID", principalID));
|
||||
cmd.Parameters.Add(m_database.CreateParameter("AssetID", assetID));
|
||||
cmd.Connection = conn;
|
||||
conn.Open();
|
||||
using (NpgsqlDataReader reader = cmd.ExecuteReader())
|
||||
{
|
||||
|
||||
int perms = 0;
|
||||
|
||||
if (reader.Read())
|
||||
{
|
||||
perms = Convert.ToInt32(reader["inventoryCurrentPermissions"]);
|
||||
}
|
||||
|
||||
return perms;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Store(XInventoryItem item)
|
||||
{
|
||||
if (!base.Store(item))
|
||||
return false;
|
||||
|
||||
IncrementFolderVersion(item.parentFolderID);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public class PGSQLFolderHandler : PGSQLInventoryHandler<XInventoryFolder>
|
||||
{
|
||||
public PGSQLFolderHandler(string c, string t, string m) :
|
||||
base(c, t, m)
|
||||
{
|
||||
}
|
||||
|
||||
public bool MoveFolder(string id, string newParentFolderID)
|
||||
{
|
||||
XInventoryFolder[] folders = Get(new string[] { "folderID" }, new string[] { id });
|
||||
|
||||
if (folders.Length == 0)
|
||||
return false;
|
||||
|
||||
UUID oldParentFolderUUID = folders[0].parentFolderID;
|
||||
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
{
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand())
|
||||
{
|
||||
UUID foldID = UUID.Zero;
|
||||
UUID.TryParse(id, out foldID);
|
||||
|
||||
UUID newPar = UUID.Zero;
|
||||
UUID.TryParse(newParentFolderID, out newPar);
|
||||
|
||||
cmd.CommandText = String.Format(@"update {0} set ""parentFolderID"" = :ParentFolderID where ""folderID"" = :folderID", m_Realm);
|
||||
cmd.Parameters.Add(m_database.CreateParameter("ParentFolderID", newPar));
|
||||
cmd.Parameters.Add(m_database.CreateParameter("folderID", foldID));
|
||||
cmd.Connection = conn;
|
||||
conn.Open();
|
||||
|
||||
if (cmd.ExecuteNonQuery() == 0)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
IncrementFolderVersion(oldParentFolderUUID);
|
||||
IncrementFolderVersion(newParentFolderID);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool Store(XInventoryFolder folder)
|
||||
{
|
||||
if (!base.Store(folder))
|
||||
return false;
|
||||
|
||||
IncrementFolderVersion(folder.parentFolderID);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public class PGSQLInventoryHandler<T> : PGSQLGenericTableHandler<T> where T: class, new()
|
||||
{
|
||||
public PGSQLInventoryHandler(string c, string t, string m) : base(c, t, m) {}
|
||||
|
||||
protected bool IncrementFolderVersion(UUID folderID)
|
||||
{
|
||||
return IncrementFolderVersion(folderID.ToString());
|
||||
}
|
||||
|
||||
protected bool IncrementFolderVersion(string folderID)
|
||||
{
|
||||
// m_log.DebugFormat("[PGSQL ITEM HANDLER]: Incrementing version on folder {0}", folderID);
|
||||
// Util.PrintCallStack();
|
||||
|
||||
string sql = @"update inventoryfolders set version=version+1 where ""folderID"" = :folderID";
|
||||
|
||||
using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
|
||||
{
|
||||
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
|
||||
{
|
||||
UUID foldID = UUID.Zero;
|
||||
UUID.TryParse(folderID, out foldID);
|
||||
|
||||
conn.Open();
|
||||
|
||||
cmd.Parameters.Add( m_database.CreateParameter("folderID", foldID) );
|
||||
|
||||
try
|
||||
{
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
65
OpenSim/Data/PGSQL/Properties/AssemblyInfo.cs
Normal file
65
OpenSim/Data/PGSQL/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
|
||||
[assembly : AssemblyTitle("OpenSim.Data.PGSQL")]
|
||||
[assembly : AssemblyDescription("")]
|
||||
[assembly : AssemblyConfiguration("")]
|
||||
[assembly : AssemblyCompany("http://opensimulator.org")]
|
||||
[assembly : AssemblyProduct("OpenSim.Data.PGSQL")]
|
||||
[assembly : AssemblyCopyright("Copyright (c) OpenSimulator.org Developers 2007-2009")]
|
||||
[assembly : AssemblyTrademark("")]
|
||||
[assembly : AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
|
||||
[assembly : ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
|
||||
[assembly : Guid("0e1c1ca4-2cf2-4315-b0e7-432c02feea8a")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
|
||||
[assembly : AssemblyVersion("0.7.6.*")]
|
||||
|
||||
94
OpenSim/Data/PGSQL/Resources/AssetStore.migrations
Normal file
94
OpenSim/Data/PGSQL/Resources/AssetStore.migrations
Normal file
@@ -0,0 +1,94 @@
|
||||
:VERSION 1
|
||||
|
||||
CREATE TABLE assets (
|
||||
"id" varchar(36) NOT NULL PRIMARY KEY,
|
||||
"name" varchar(64) NOT NULL,
|
||||
"description" varchar(64) NOT NULL,
|
||||
"assetType" smallint NOT NULL,
|
||||
"local" smallint NOT NULL,
|
||||
"temporary" smallint NOT NULL,
|
||||
"data" bytea NOT NULL
|
||||
) ;
|
||||
|
||||
:VERSION 2
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE Tmp_assets
|
||||
(
|
||||
"id" varchar(36) NOT NULL,
|
||||
"name" varchar(64) NOT NULL,
|
||||
"description" varchar(64) NOT NULL,
|
||||
"assetType" smallint NOT NULL,
|
||||
"local" boolean NOT NULL,
|
||||
"temporary" boolean NOT NULL,
|
||||
"data" bytea NOT NULL
|
||||
) ;
|
||||
|
||||
INSERT INTO Tmp_assets ("id", "name", "description", "assetType", "local", "temporary", "data")
|
||||
SELECT "id", "name", "description", "assetType", case when "local" = 1 then true else false end, case when "temporary" = 1 then true else false end, "data"
|
||||
FROM assets ;
|
||||
|
||||
DROP TABLE assets;
|
||||
|
||||
Alter table Tmp_assets
|
||||
rename to assets;
|
||||
|
||||
ALTER TABLE assets ADD PRIMARY KEY ("id");
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
||||
:VERSION 3
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
ALTER TABLE assets add "create_time" integer default 0;
|
||||
ALTER TABLE assets add "access_time" integer default 0;
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
||||
:VERSION 4
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE Tmp_assets
|
||||
(
|
||||
"id" uuid NOT NULL,
|
||||
"name" varchar(64) NOT NULL,
|
||||
"description" varchar(64) NOT NULL,
|
||||
"assetType" smallint NOT NULL,
|
||||
"local" boolean NOT NULL,
|
||||
"temporary" boolean NOT NULL,
|
||||
"data" bytea NOT NULL,
|
||||
"create_time" int NULL,
|
||||
"access_time" int NULL
|
||||
) ;
|
||||
|
||||
|
||||
INSERT INTO Tmp_assets ("id", "name", "description", "assetType", "local", "temporary", "data", "create_time", "access_time")
|
||||
SELECT cast("id" as uuid), "name", "description", "assetType", "local", "temporary", "data", "create_time", "access_time"
|
||||
FROM assets ;
|
||||
|
||||
DROP TABLE assets;
|
||||
|
||||
Alter table Tmp_assets
|
||||
rename to assets;
|
||||
|
||||
ALTER TABLE assets ADD PRIMARY KEY ("id");
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
||||
:VERSION 5
|
||||
|
||||
DELETE FROM assets WHERE "id" = 'dc4b9f0b-d008-45c6-96a4-01dd947ac621';
|
||||
|
||||
:VERSION 6
|
||||
|
||||
ALTER TABLE assets ADD "asset_flags" INTEGER NOT NULL DEFAULT 0;
|
||||
|
||||
:VERSION 7
|
||||
|
||||
alter table assets add "creatorid" varchar(36) not null default '';
|
||||
32
OpenSim/Data/PGSQL/Resources/AuthStore.migrations
Normal file
32
OpenSim/Data/PGSQL/Resources/AuthStore.migrations
Normal file
@@ -0,0 +1,32 @@
|
||||
:VERSION 1
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE auth (
|
||||
uuid uuid NOT NULL default '00000000-0000-0000-0000-000000000000',
|
||||
"passwordHash" varchar(32) NOT NULL,
|
||||
"passwordSalt" varchar(32) NOT NULL,
|
||||
"webLoginKey" varchar(255) NOT NULL,
|
||||
"accountType" VARCHAR(32) NOT NULL DEFAULT 'UserAccount'
|
||||
) ;
|
||||
|
||||
CREATE TABLE tokens (
|
||||
uuid uuid NOT NULL default '00000000-0000-0000-0000-000000000000',
|
||||
token varchar(255) NOT NULL,
|
||||
validity TIMESTAMP NOT NULL )
|
||||
;
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 2
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
INSERT INTO auth (uuid, "passwordHash", "passwordSalt", "webLoginKey", "accountType")
|
||||
SELECT uuid AS UUID, passwordHash AS passwordHash, passwordSalt AS passwordSalt, webLoginKey AS webLoginKey, 'UserAccount' as accountType
|
||||
FROM users
|
||||
where exists ( Select * from information_schema.tables where table_name = 'users' )
|
||||
;
|
||||
|
||||
COMMIT;
|
||||
|
||||
59
OpenSim/Data/PGSQL/Resources/Avatar.migrations
Normal file
59
OpenSim/Data/PGSQL/Resources/Avatar.migrations
Normal file
@@ -0,0 +1,59 @@
|
||||
:VERSION 1
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE Avatars (
|
||||
"PrincipalID" uuid NOT NULL PRIMARY KEY,
|
||||
"Name" varchar(32) NOT NULL,
|
||||
"Value" varchar(255) NOT NULL DEFAULT ''
|
||||
);
|
||||
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 2
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE Tmp_Avatars
|
||||
(
|
||||
"PrincipalID" uuid NOT NULL,
|
||||
"Name" varchar(32) NOT NULL,
|
||||
"Value" text NOT NULL DEFAULT ''
|
||||
) ;
|
||||
|
||||
INSERT INTO Tmp_Avatars ("PrincipalID", "Name", "Value")
|
||||
SELECT "PrincipalID", cast("Name" as text), "Value"
|
||||
FROM Avatars ;
|
||||
|
||||
DROP TABLE Avatars;
|
||||
|
||||
Alter table Tmp_Avatars
|
||||
rename to Avatars;
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 3
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE Tmp_Avatars
|
||||
(
|
||||
"PrincipalID" uuid NOT NULL,
|
||||
"Name" varchar(32) NOT NULL,
|
||||
"Value" text NOT NULL DEFAULT ''
|
||||
);
|
||||
|
||||
ALTER TABLE Tmp_Avatars ADD PRIMARY KEY ("PrincipalID", "Name");
|
||||
|
||||
|
||||
INSERT INTO Tmp_Avatars ("PrincipalID", "Name", "Value")
|
||||
SELECT "PrincipalID", "Name", cast("Value" as text) FROM Avatars ;
|
||||
|
||||
DROP TABLE Avatars;
|
||||
|
||||
Alter table Tmp_Avatars
|
||||
rename to Avatars;
|
||||
|
||||
COMMIT;
|
||||
|
||||
307
OpenSim/Data/PGSQL/Resources/EstateStore.migrations
Normal file
307
OpenSim/Data/PGSQL/Resources/EstateStore.migrations
Normal file
@@ -0,0 +1,307 @@
|
||||
:VERSION 1
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE estate_managers(
|
||||
"EstateID" int NOT NULL Primary Key,
|
||||
uuid varchar(36) NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE estate_groups(
|
||||
"EstateID" int NOT NULL,
|
||||
uuid varchar(36) NOT NULL
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE estate_users(
|
||||
"EstateID" int NOT NULL,
|
||||
uuid varchar(36) NOT NULL
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE estateban(
|
||||
"EstateID" int NOT NULL,
|
||||
"bannedUUID" varchar(36) NOT NULL,
|
||||
"bannedIp" varchar(16) NOT NULL,
|
||||
"bannedIpHostMask" varchar(16) NOT NULL,
|
||||
"bannedNameMask" varchar(64) NULL DEFAULT NULL
|
||||
);
|
||||
|
||||
Create Sequence estate_settings_id increment by 100 start with 100;
|
||||
|
||||
CREATE TABLE estate_settings(
|
||||
"EstateID" integer DEFAULT nextval('estate_settings_id') NOT NULL,
|
||||
"EstateName" varchar(64) NULL DEFAULT (NULL),
|
||||
"AbuseEmailToEstateOwner" boolean NOT NULL,
|
||||
"DenyAnonymous" boolean NOT NULL,
|
||||
"ResetHomeOnTeleport" boolean NOT NULL,
|
||||
"FixedSun" boolean NOT NULL,
|
||||
"DenyTransacted" boolean NOT NULL,
|
||||
"BlockDwell" boolean NOT NULL,
|
||||
"DenyIdentified" boolean NOT NULL,
|
||||
"AllowVoice" boolean NOT NULL,
|
||||
"UseGlobalTime" boolean NOT NULL,
|
||||
"PricePerMeter" int NOT NULL,
|
||||
"TaxFree" boolean NOT NULL,
|
||||
"AllowDirectTeleport" boolean NOT NULL,
|
||||
"RedirectGridX" int NOT NULL,
|
||||
"RedirectGridY" int NOT NULL,
|
||||
"ParentEstateID" int NOT NULL,
|
||||
"SunPosition" double precision NOT NULL,
|
||||
"EstateSkipScripts" boolean NOT NULL,
|
||||
"BillableFactor" double precision NOT NULL,
|
||||
"PublicAccess" boolean NOT NULL,
|
||||
"AbuseEmail" varchar(255) NOT NULL,
|
||||
"EstateOwner" varchar(36) NOT NULL,
|
||||
"DenyMinors" boolean NOT NULL
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE estate_map(
|
||||
"RegionID" varchar(36) NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000'),
|
||||
"EstateID" int NOT NULL
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 2
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE INDEX IX_estate_managers ON estate_managers
|
||||
(
|
||||
"EstateID"
|
||||
);
|
||||
|
||||
|
||||
CREATE INDEX IX_estate_groups ON estate_groups
|
||||
(
|
||||
"EstateID"
|
||||
);
|
||||
|
||||
|
||||
CREATE INDEX IX_estate_users ON estate_users
|
||||
(
|
||||
"EstateID"
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 3
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE Tmp_estateban
|
||||
(
|
||||
"EstateID" int NOT NULL,
|
||||
"bannedUUID" varchar(36) NOT NULL,
|
||||
"bannedIp" varchar(16) NULL,
|
||||
"bannedIpHostMask" varchar(16) NULL,
|
||||
"bannedNameMask" varchar(64) NULL
|
||||
);
|
||||
|
||||
INSERT INTO Tmp_estateban ("EstateID", "bannedUUID", "bannedIp", "bannedIpHostMask", "bannedNameMask")
|
||||
SELECT "EstateID", "bannedUUID", "bannedIp", "bannedIpHostMask", "bannedNameMask" FROM estateban;
|
||||
|
||||
DROP TABLE estateban;
|
||||
|
||||
Alter table Tmp_estateban
|
||||
rename to estateban;
|
||||
|
||||
CREATE INDEX IX_estateban ON estateban
|
||||
(
|
||||
"EstateID"
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
||||
:VERSION 4
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE Tmp_estate_managers
|
||||
(
|
||||
"EstateID" int NOT NULL,
|
||||
uuid uuid NOT NULL
|
||||
);
|
||||
|
||||
INSERT INTO Tmp_estate_managers ("EstateID", uuid)
|
||||
SELECT "EstateID", cast(uuid as uuid) FROM estate_managers;
|
||||
|
||||
DROP TABLE estate_managers;
|
||||
|
||||
Alter table Tmp_estate_managers
|
||||
rename to estate_managers;
|
||||
|
||||
CREATE INDEX IX_estate_managers ON estate_managers
|
||||
(
|
||||
"EstateID"
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
||||
:VERSION 5
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE Tmp_estate_groups
|
||||
(
|
||||
"EstateID" int NOT NULL,
|
||||
uuid uuid NOT NULL
|
||||
) ;
|
||||
|
||||
INSERT INTO Tmp_estate_groups ("EstateID", uuid)
|
||||
SELECT "EstateID", cast(uuid as uuid) FROM estate_groups;
|
||||
|
||||
DROP TABLE estate_groups;
|
||||
|
||||
Alter table Tmp_estate_groups
|
||||
rename to estate_groups;
|
||||
|
||||
CREATE INDEX IX_estate_groups ON estate_groups
|
||||
(
|
||||
"EstateID"
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
||||
:VERSION 6
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE Tmp_estate_users
|
||||
(
|
||||
"EstateID" int NOT NULL,
|
||||
uuid uuid NOT NULL
|
||||
);
|
||||
|
||||
INSERT INTO Tmp_estate_users ("EstateID", uuid)
|
||||
SELECT "EstateID", cast(uuid as uuid) FROM estate_users ;
|
||||
|
||||
DROP TABLE estate_users;
|
||||
|
||||
Alter table Tmp_estate_users
|
||||
rename to estate_users;
|
||||
|
||||
CREATE INDEX IX_estate_users ON estate_users
|
||||
(
|
||||
"EstateID"
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
||||
:VERSION 7
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE Tmp_estateban
|
||||
(
|
||||
"EstateID" int NOT NULL,
|
||||
"bannedUUID" uuid NOT NULL,
|
||||
"bannedIp" varchar(16) NULL,
|
||||
"bannedIpHostMask" varchar(16) NULL,
|
||||
"bannedNameMask" varchar(64) NULL
|
||||
);
|
||||
|
||||
INSERT INTO Tmp_estateban ("EstateID", "bannedUUID", "bannedIp", "bannedIpHostMask", "bannedNameMask")
|
||||
SELECT "EstateID", cast("bannedUUID" as uuid), "bannedIp", "bannedIpHostMask", "bannedNameMask" FROM estateban ;
|
||||
|
||||
DROP TABLE estateban;
|
||||
|
||||
Alter table Tmp_estateban
|
||||
rename to estateban;
|
||||
|
||||
CREATE INDEX IX_estateban ON estateban
|
||||
(
|
||||
"EstateID"
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
||||
:VERSION 8
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE Tmp_estate_settings
|
||||
(
|
||||
"EstateID" integer default nextval('estate_settings_id') NOT NULL,
|
||||
"EstateName" varchar(64) NULL DEFAULT (NULL),
|
||||
"AbuseEmailToEstateOwner" boolean NOT NULL,
|
||||
"DenyAnonymous" boolean NOT NULL,
|
||||
"ResetHomeOnTeleport" boolean NOT NULL,
|
||||
"FixedSun" boolean NOT NULL,
|
||||
"DenyTransacted" boolean NOT NULL,
|
||||
"BlockDwell" boolean NOT NULL,
|
||||
"DenyIdentified" boolean NOT NULL,
|
||||
"AllowVoice" boolean NOT NULL,
|
||||
"UseGlobalTime" boolean NOT NULL,
|
||||
"PricePerMeter" int NOT NULL,
|
||||
"TaxFree" boolean NOT NULL,
|
||||
"AllowDirectTeleport" boolean NOT NULL,
|
||||
"RedirectGridX" int NOT NULL,
|
||||
"RedirectGridY" int NOT NULL,
|
||||
"ParentEstateID" int NOT NULL,
|
||||
"SunPosition" double precision NOT NULL,
|
||||
"EstateSkipScripts" boolean NOT NULL,
|
||||
"BillableFactor" double precision NOT NULL,
|
||||
"PublicAccess" boolean NOT NULL,
|
||||
"AbuseEmail" varchar(255) NOT NULL,
|
||||
"EstateOwner" uuid NOT NULL,
|
||||
"DenyMinors" boolean NOT NULL
|
||||
);
|
||||
|
||||
INSERT INTO Tmp_estate_settings ("EstateID", "EstateName", "AbuseEmailToEstateOwner", "DenyAnonymous", "ResetHomeOnTeleport", "FixedSun", "DenyTransacted", "BlockDwell", "DenyIdentified", "AllowVoice", "UseGlobalTime", "PricePerMeter", "TaxFree", "AllowDirectTeleport", "RedirectGridX", "RedirectGridY", "ParentEstateID", "SunPosition", "EstateSkipScripts", "BillableFactor", "PublicAccess", "AbuseEmail", "EstateOwner", "DenyMinors")
|
||||
SELECT "EstateID", "EstateName", "AbuseEmailToEstateOwner", "DenyAnonymous", "ResetHomeOnTeleport", "FixedSun", "DenyTransacted", "BlockDwell", "DenyIdentified", "AllowVoice", "UseGlobalTime", "PricePerMeter", "TaxFree", "AllowDirectTeleport", "RedirectGridX", "RedirectGridY", "ParentEstateID", "SunPosition", "EstateSkipScripts", "BillableFactor", "PublicAccess", "AbuseEmail", cast("EstateOwner" as uuid), "DenyMinors" FROM estate_settings ;
|
||||
|
||||
DROP TABLE estate_settings;
|
||||
|
||||
|
||||
Alter table Tmp_estate_settings
|
||||
rename to estate_settings;
|
||||
|
||||
|
||||
Create index on estate_settings (lower("EstateName"));
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
||||
:VERSION 9
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE Tmp_estate_map
|
||||
(
|
||||
"RegionID" uuid NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000'),
|
||||
"EstateID" int NOT NULL
|
||||
);
|
||||
|
||||
INSERT INTO Tmp_estate_map ("RegionID", "EstateID")
|
||||
SELECT cast("RegionID" as uuid), "EstateID" FROM estate_map ;
|
||||
|
||||
DROP TABLE estate_map;
|
||||
|
||||
Alter table Tmp_estate_map
|
||||
rename to estate_map;
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 10
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
ALTER TABLE estate_settings ADD COLUMN "AllowLandmark" boolean NOT NULL default true;
|
||||
ALTER TABLE estate_settings ADD COLUMN "AllowParcelChanges" boolean NOT NULL default true;
|
||||
ALTER TABLE estate_settings ADD COLUMN "AllowSetHome" boolean NOT NULL default true;
|
||||
COMMIT;
|
||||
|
||||
:VERSION 11
|
||||
|
||||
Begin transaction;
|
||||
|
||||
|
||||
Commit;
|
||||
|
||||
44
OpenSim/Data/PGSQL/Resources/FriendsStore.migrations
Normal file
44
OpenSim/Data/PGSQL/Resources/FriendsStore.migrations
Normal file
@@ -0,0 +1,44 @@
|
||||
:VERSION 1
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE Friends (
|
||||
"PrincipalID" uuid NOT NULL,
|
||||
"Friend" varchar(255) NOT NULL,
|
||||
"Flags" char(16) NOT NULL DEFAULT '0',
|
||||
"Offered" varchar(32) NOT NULL DEFAULT 0);
|
||||
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 2
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
INSERT INTO Friends ("PrincipalID", "Friend", "Flags", "Offered")
|
||||
SELECT "ownerID", "friendID", "friendPerms", 0 FROM userfriends;
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 3
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE Tmp_Friends
|
||||
("PrincipalID" varchar(255) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
|
||||
"Friend" varchar(255) NOT NULL,
|
||||
"Flags" char(16) NOT NULL DEFAULT '0',
|
||||
"Offered" varchar(32) NOT NULL DEFAULT 0) ;
|
||||
|
||||
INSERT INTO Tmp_Friends ("PrincipalID", "Friend", "Flags", "Offered")
|
||||
SELECT cast("PrincipalID" as varchar(255)), "Friend", "Flags", "Offered" FROM Friends ;
|
||||
|
||||
DROP TABLE Friends;
|
||||
|
||||
Alter table Tmp_Friends
|
||||
rename to Friends;
|
||||
|
||||
ALTER TABLE Friends ADD PRIMARY KEY("PrincipalID", "Friend");
|
||||
|
||||
|
||||
COMMIT;
|
||||
242
OpenSim/Data/PGSQL/Resources/GridStore.migrations
Normal file
242
OpenSim/Data/PGSQL/Resources/GridStore.migrations
Normal file
@@ -0,0 +1,242 @@
|
||||
:VERSION 1
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE regions(
|
||||
"regionHandle" varchar(255) NULL,
|
||||
"regionName" varchar(255) NULL,
|
||||
uuid varchar(255) NOT NULL PRIMARY KEY,
|
||||
"regionRecvKey" varchar(255) NULL,
|
||||
"regionSecret" varchar(255) NULL,
|
||||
"regionSendKey" varchar(255) NULL,
|
||||
"regionDataURI" varchar(255) NULL,
|
||||
"serverIP" varchar(255) NULL,
|
||||
"serverPort" varchar(255) NULL,
|
||||
"serverURI" varchar(255) NULL,
|
||||
"locX" varchar(255) NULL,
|
||||
"locY" varchar(255) NULL,
|
||||
"locZ" varchar(255) NULL,
|
||||
"eastOverrideHandle" varchar(255) NULL,
|
||||
"westOverrideHandle" varchar(255) NULL,
|
||||
"southOverrideHandle" varchar(255) NULL,
|
||||
"northOverrideHandle" varchar(255) NULL,
|
||||
"regionAssetURI" varchar(255) NULL,
|
||||
"regionAssetRecvKey" varchar(255) NULL,
|
||||
"regionAssetSendKey" varchar(255) NULL,
|
||||
"regionUserURI" varchar(255) NULL,
|
||||
"regionUserRecvKey" varchar(255) NULL,
|
||||
"regionUserSendKey" varchar(255) NULL,
|
||||
"regionMapTexture" varchar(255) NULL,
|
||||
"serverHttpPort" varchar(255) NULL,
|
||||
"serverRemotingPort" varchar(255) NULL,
|
||||
"owner_uuid" varchar(36) NULL
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
||||
:VERSION 2
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE Tmp_regions
|
||||
(
|
||||
uuid varchar(36) NOT NULL,
|
||||
"regionHandle" bigint NULL,
|
||||
"regionName" varchar(20) NULL,
|
||||
"regionRecvKey" varchar(128) NULL,
|
||||
"regionSendKey" varchar(128) NULL,
|
||||
"regionSecret" varchar(128) NULL,
|
||||
"regionDataURI" varchar(128) NULL,
|
||||
"serverIP" varchar(64) NULL,
|
||||
"serverPort" int NULL,
|
||||
"serverURI" varchar(255) NULL,
|
||||
"locX" int NULL,
|
||||
"locY" int NULL,
|
||||
"locZ" int NULL,
|
||||
"eastOverrideHandle" bigint NULL,
|
||||
"westOverrideHandle" bigint NULL,
|
||||
"southOverrideHandle" bigint NULL,
|
||||
"northOverrideHandle" bigint NULL,
|
||||
"regionAssetURI" varchar(255) NULL,
|
||||
"regionAssetRecvKey" varchar(128) NULL,
|
||||
"regionAssetSendKey" varchar(128) NULL,
|
||||
"regionUserURI" varchar(255) NULL,
|
||||
"regionUserRecvKey" varchar(128) NULL,
|
||||
"regionUserSendKey" varchar(128) NULL,
|
||||
"regionMapTexture" varchar(36) NULL,
|
||||
"serverHttpPort" int NULL,
|
||||
"serverRemotingPort" int NULL,
|
||||
"owner_uuid" varchar(36) NULL,
|
||||
"originUUID" varchar(36) NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000')
|
||||
);
|
||||
|
||||
INSERT INTO Tmp_regions (uuid, "regionHandle", "regionName", "regionRecvKey", "regionSendKey", "regionSecret", "regionDataURI", "serverIP", "serverPort", "serverURI", "locX", "locY", "locZ", "eastOverrideHandle", "westOverrideHandle", "southOverrideHandle", "northOverrideHandle", "regionAssetURI", "regionAssetRecvKey", "regionAssetSendKey", "regionUserURI", "regionUserRecvKey", "regionUserSendKey", "regionMapTexture", "serverHttpPort", "serverRemotingPort", "owner_uuid")
|
||||
SELECT cast(uuid as varchar(36)), cast("regionHandle" as bigint), cast("regionName" as varchar(20)), cast("regionRecvKey" as varchar(128)), cast("regionSendKey" as varchar(128)), cast("regionSecret" as varchar(128)), cast("regionDataURI" as varchar(128)), cast("serverIP" as varchar(64)), cast("serverPort" as int), "serverURI", cast("locX" as int), cast("locY" as int), cast("locZ" as int), cast("eastOverrideHandle" as bigint), cast("westOverrideHandle" as bigint),
|
||||
cast("southOverrideHandle" as bigint), cast("northOverrideHandle" as bigint), "regionAssetURI", cast("regionAssetRecvKey" as varchar(128)), cast("regionAssetSendKey" as varchar(128)), "regionUserURI", cast("regionUserRecvKey" as varchar(128)), cast("regionUserSendKey" as varchar(128)), cast("regionMapTexture" as varchar(36)),
|
||||
cast("serverHttpPort" as int), cast("serverRemotingPort" as int), "owner_uuid"
|
||||
FROM regions;
|
||||
|
||||
DROP TABLE regions;
|
||||
|
||||
alter table Tmp_regions
|
||||
rename to regions;
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 3
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE INDEX IX_regions_name ON regions
|
||||
(
|
||||
"regionName"
|
||||
);
|
||||
|
||||
CREATE INDEX IX_regions_handle ON regions
|
||||
(
|
||||
"regionHandle"
|
||||
);
|
||||
|
||||
|
||||
CREATE INDEX IX_regions_override ON regions
|
||||
(
|
||||
"eastOverrideHandle",
|
||||
"westOverrideHandle",
|
||||
"southOverrideHandle",
|
||||
"northOverrideHandle"
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
||||
:VERSION 4
|
||||
|
||||
/* To prevent any potential data loss issues, you should review this script in detail before running it outside the cotext of the database designer.*/
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE Tmp_regions
|
||||
(
|
||||
uuid uuid NOT NULL,
|
||||
"regionHandle" bigint NULL,
|
||||
"regionName" varchar(20) NULL,
|
||||
"regionRecvKey" varchar(128) NULL,
|
||||
"regionSendKey" varchar(128) NULL,
|
||||
"regionSecret" varchar(128) NULL,
|
||||
"regionDataURI" varchar(128) NULL,
|
||||
"serverIP" varchar(64) NULL,
|
||||
"serverPort" int NULL,
|
||||
"serverURI" varchar(255) NULL,
|
||||
"locX" int NULL,
|
||||
"locY" int NULL,
|
||||
"locZ" int NULL,
|
||||
"eastOverrideHandle" bigint NULL,
|
||||
"westOverrideHandle" bigint NULL,
|
||||
"southOverrideHandle" bigint NULL,
|
||||
"northOverrideHandle" bigint NULL,
|
||||
"regionAssetURI" varchar(255) NULL,
|
||||
"regionAssetRecvKey" varchar(128) NULL,
|
||||
"regionAssetSendKey" varchar(128) NULL,
|
||||
"regionUserURI" varchar(255) NULL,
|
||||
"regionUserRecvKey" varchar(128) NULL,
|
||||
"regionUserSendKey" varchar(128) NULL,
|
||||
"regionMapTexture" uuid NULL,
|
||||
"serverHttpPort" int NULL,
|
||||
"serverRemotingPort" int NULL,
|
||||
"owner_uuid" uuid NOT NULL,
|
||||
"originUUID" uuid NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000')
|
||||
);
|
||||
|
||||
|
||||
INSERT INTO Tmp_regions (uuid, "regionHandle", "regionName", "regionRecvKey", "regionSendKey", "regionSecret", "regionDataURI", "serverIP", "serverPort", "serverURI", "locX", "locY", "locZ", "eastOverrideHandle", "westOverrideHandle", "southOverrideHandle", "northOverrideHandle", "regionAssetURI", "regionAssetRecvKey", "regionAssetSendKey", "regionUserURI", "regionUserRecvKey", "regionUserSendKey", "regionMapTexture", "serverHttpPort", "serverRemotingPort", "owner_uuid", "originUUID")
|
||||
SELECT cast(uuid as uuid), "regionHandle", "regionName", "regionRecvKey", "regionSendKey", "regionSecret", "regionDataURI", "serverIP", "serverPort", "serverURI", "locX", "locY", "locZ", "eastOverrideHandle", "westOverrideHandle", "southOverrideHandle", "northOverrideHandle", "regionAssetURI", "regionAssetRecvKey", "regionAssetSendKey", "regionUserURI", "regionUserRecvKey", "regionUserSendKey", cast("regionMapTexture" as uuid), "serverHttpPort", "serverRemotingPort", cast( "owner_uuid" as uuid), cast("originUUID" as uuid) FROM regions ;
|
||||
|
||||
|
||||
DROP TABLE regions;
|
||||
|
||||
alter table Tmp_regions rename to regions;
|
||||
|
||||
ALTER TABLE regions ADD CONSTRAINT
|
||||
PK__regions__uuid PRIMARY KEY
|
||||
(
|
||||
uuid
|
||||
);
|
||||
|
||||
CREATE INDEX IX_regions_name ON regions
|
||||
(
|
||||
"regionName"
|
||||
);
|
||||
|
||||
CREATE INDEX IX_regions_handle ON regions
|
||||
(
|
||||
"regionHandle"
|
||||
);
|
||||
|
||||
CREATE INDEX IX_regions_override ON regions
|
||||
(
|
||||
"eastOverrideHandle",
|
||||
"westOverrideHandle",
|
||||
"southOverrideHandle",
|
||||
"northOverrideHandle"
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
||||
:VERSION 5
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
ALTER TABLE regions ADD access int default 0;
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
||||
:VERSION 6
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
ALTER TABLE regions ADD "ScopeID" uuid default '00000000-0000-0000-0000-000000000000';
|
||||
ALTER TABLE regions alter column "owner_uuid" set DEFAULT ('00000000-0000-0000-0000-000000000000');
|
||||
ALTER TABLE regions ADD "sizeX" integer not null default 0;
|
||||
ALTER TABLE regions ADD "sizeY" integer not null default 0;
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
||||
:VERSION 7
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
ALTER TABLE regions ADD "flags" integer NOT NULL DEFAULT 0;
|
||||
CREATE INDEX flags ON regions("flags");
|
||||
ALTER TABLE regions ADD "last_seen" integer NOT NULL DEFAULT 0;
|
||||
ALTER TABLE regions ADD "PrincipalID" uuid NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000';
|
||||
ALTER TABLE regions ADD "Token" varchar(255) NOT NULL DEFAULT 0;
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 8
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
ALTER TABLE regions ALTER COLUMN "regionName" type VarChar(128) ;
|
||||
|
||||
DROP INDEX IX_regions_name;
|
||||
ALTER TABLE regions ALTER COLUMN "regionName" type VarChar(128),
|
||||
ALTER COLUMN "regionName" SET NOT NULL;
|
||||
|
||||
CREATE INDEX IX_regions_name ON regions
|
||||
(
|
||||
"regionName"
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 9
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
ALTER TABLE regions ADD "parcelMapTexture" uuid NULL;
|
||||
|
||||
COMMIT;
|
||||
|
||||
60
OpenSim/Data/PGSQL/Resources/GridUserStore.migrations
Normal file
60
OpenSim/Data/PGSQL/Resources/GridUserStore.migrations
Normal file
@@ -0,0 +1,60 @@
|
||||
:VERSION 1 # --------------------------
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE GridUser (
|
||||
"UserID" VARCHAR(255) NOT NULL Primary Key,
|
||||
"HomeRegionID" CHAR(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
|
||||
"HomePosition" CHAR(64) NOT NULL DEFAULT '<0,0,0>',
|
||||
"HomeLookAt" CHAR(64) NOT NULL DEFAULT '<0,0,0>',
|
||||
"LastRegionID" CHAR(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
|
||||
"LastPosition" CHAR(64) NOT NULL DEFAULT '<0,0,0>',
|
||||
"LastLookAt" CHAR(64) NOT NULL DEFAULT '<0,0,0>',
|
||||
"Online" CHAR(5) NOT NULL DEFAULT 'false',
|
||||
"Login" CHAR(16) NOT NULL DEFAULT '0',
|
||||
"Logout" CHAR(16) NOT NULL DEFAULT '0'
|
||||
) ;
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 2 # --------------------------
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE GridUser_tmp (
|
||||
"UserID" VARCHAR(255) NOT NULL PRIMARY KEY,
|
||||
"HomeRegionID" uuid NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
|
||||
"HomePosition" CHAR(64) NOT NULL DEFAULT '<0,0,0>',
|
||||
"HomeLookAt" CHAR(64) NOT NULL DEFAULT '<0,0,0>',
|
||||
"LastRegionID" uuid NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
|
||||
"LastPosition" CHAR(64) NOT NULL DEFAULT '<0,0,0>',
|
||||
"LastLookAt" CHAR(64) NOT NULL DEFAULT '<0,0,0>',
|
||||
"Online" CHAR(5) NOT NULL DEFAULT 'false',
|
||||
"Login" CHAR(16) NOT NULL DEFAULT '0',
|
||||
"Logout" CHAR(16) NOT NULL DEFAULT '0'
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
||||
INSERT INTO GridUser_tmp ("UserID"
|
||||
,"HomeRegionID"
|
||||
,"HomePosition"
|
||||
,"HomeLookAt"
|
||||
,"LastRegionID"
|
||||
,"LastPosition"
|
||||
,"LastLookAt"
|
||||
,"Online"
|
||||
,"Login"
|
||||
,"Logout")
|
||||
SELECT "UserID", cast("HomeRegionID" as uuid), "HomePosition" ,"HomeLookAt" , cast("LastRegionID" as uuid),
|
||||
"LastPosition"
|
||||
,"LastLookAt"
|
||||
,"Online"
|
||||
,"Login"
|
||||
,"Logout" FROM GridUser;
|
||||
|
||||
DROP TABLE GridUser;
|
||||
|
||||
alter table GridUser_tmp rename to GridUser;
|
||||
|
||||
17
OpenSim/Data/PGSQL/Resources/HGTravelStore.migrations
Normal file
17
OpenSim/Data/PGSQL/Resources/HGTravelStore.migrations
Normal file
@@ -0,0 +1,17 @@
|
||||
:VERSION 1 # --------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
CREATE TABLE hg_traveling_data (
|
||||
"SessionID" VARCHAR(36) NOT NULL Primary Key,
|
||||
"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 default now()
|
||||
);
|
||||
|
||||
|
||||
COMMIT;
|
||||
|
||||
26
OpenSim/Data/PGSQL/Resources/IM_Store.migrations
Normal file
26
OpenSim/Data/PGSQL/Resources/IM_Store.migrations
Normal file
@@ -0,0 +1,26 @@
|
||||
:VERSION 1 # --------------------------
|
||||
|
||||
BEGIN Transaction;
|
||||
|
||||
Create Sequence im_offiline_id increment by 1 start with 1;
|
||||
|
||||
CREATE TABLE im_offline (
|
||||
"ID" integer PRIMARY KEY NOT NULL DEFAULT nextval('im_offiline_id') ,
|
||||
"PrincipalID" char(36) NOT NULL default '',
|
||||
"Message" text NOT NULL,
|
||||
"TMStamp" timestamp NOT NULL default now()
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 2 # --------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
/*
|
||||
INSERT INTO `im_offline` SELECT * from `diva_im_offline`;
|
||||
DROP TABLE `diva_im_offline`;
|
||||
DELETE FROM `migrations` WHERE name='diva_im_Store';
|
||||
*/
|
||||
|
||||
COMMIT;
|
||||
220
OpenSim/Data/PGSQL/Resources/InventoryStore.migrations
Normal file
220
OpenSim/Data/PGSQL/Resources/InventoryStore.migrations
Normal file
@@ -0,0 +1,220 @@
|
||||
:VERSION 1
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE inventoryfolders (
|
||||
"folderID" varchar(36) NOT NULL default '' PRIMARY KEY,
|
||||
"agentID" varchar(36) default NULL,
|
||||
"parentFolderID" varchar(36) default NULL,
|
||||
"folderName" varchar(64) default NULL,
|
||||
"type" smallint NOT NULL default 0,
|
||||
"version" int NOT NULL default 0
|
||||
);
|
||||
|
||||
|
||||
CREATE INDEX owner ON inventoryfolders
|
||||
(
|
||||
"agentID" ASC
|
||||
);
|
||||
|
||||
CREATE INDEX parent ON inventoryfolders
|
||||
(
|
||||
"parentFolderID" ASC
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE inventoryitems (
|
||||
"inventoryID" varchar(36) NOT NULL default '' Primary Key,
|
||||
"assetID" varchar(36) default NULL,
|
||||
"assetType" int default NULL,
|
||||
"parentFolderID" varchar(36) default NULL,
|
||||
"avatarID" varchar(36) default NULL,
|
||||
"inventoryName" varchar(64) default NULL,
|
||||
"inventoryDescription" varchar(128) default NULL,
|
||||
"inventoryNextPermissions" int default NULL,
|
||||
"inventoryCurrentPermissions" int default NULL,
|
||||
"invType" int default NULL,
|
||||
"creatorID" varchar(36) default NULL,
|
||||
"inventoryBasePermissions" int NOT NULL default 0,
|
||||
"inventoryEveryOnePermissions" int NOT NULL default 0,
|
||||
"salePrice" int default NULL,
|
||||
"saleType" smallint default NULL,
|
||||
"creationDate" int default NULL,
|
||||
"groupID" varchar(36) default NULL,
|
||||
"groupOwned" boolean default NULL,
|
||||
"flags" int default NULL
|
||||
);
|
||||
|
||||
|
||||
CREATE INDEX ii_owner ON inventoryitems
|
||||
(
|
||||
"avatarID" ASC
|
||||
);
|
||||
|
||||
CREATE INDEX ii_folder ON inventoryitems
|
||||
(
|
||||
"parentFolderID" ASC
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
||||
:VERSION 2
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
ALTER TABLE inventoryitems ADD "inventoryGroupPermissions" INTEGER NOT NULL default 0;
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 3
|
||||
|
||||
/* To prevent any potential data loss issues, you should review this script in detail before running it outside the cotext of the database designer.*/
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE Tmp_inventoryfolders
|
||||
(
|
||||
"folderID" uuid NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000'),
|
||||
"agentID" uuid NULL DEFAULT (NULL),
|
||||
"parentFolderID" uuid NULL DEFAULT (NULL),
|
||||
"folderName" varchar(64) NULL DEFAULT (NULL),
|
||||
"type" smallint NOT NULL DEFAULT ((0)),
|
||||
"version" int NOT NULL DEFAULT ((0))
|
||||
);
|
||||
|
||||
INSERT INTO Tmp_inventoryfolders ("folderID", "agentID", "parentFolderID", "folderName", type, version)
|
||||
SELECT cast("folderID" as uuid), cast("agentID" as uuid), cast("parentFolderID" as uuid), "folderName", "type", "version"
|
||||
FROM inventoryfolders;
|
||||
|
||||
DROP TABLE inventoryfolders;
|
||||
|
||||
alter table Tmp_inventoryfolders rename to inventoryfolders;
|
||||
|
||||
ALTER TABLE inventoryfolders ADD CONSTRAINT
|
||||
PK__inventor__C2FABFB3173876EA PRIMARY KEY
|
||||
(
|
||||
"folderID"
|
||||
);
|
||||
|
||||
CREATE INDEX owner ON inventoryfolders
|
||||
(
|
||||
"agentID"
|
||||
);
|
||||
|
||||
CREATE INDEX parent ON inventoryfolders
|
||||
(
|
||||
"parentFolderID"
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
||||
:VERSION 4
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE Tmp_inventoryitems
|
||||
(
|
||||
"inventoryID" uuid NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000'),
|
||||
"assetID" uuid NULL DEFAULT (NULL),
|
||||
"assetType" int NULL DEFAULT (NULL),
|
||||
"parentFolderID" uuid NULL DEFAULT (NULL),
|
||||
"avatarID" uuid NULL DEFAULT (NULL),
|
||||
"inventoryName" varchar(64) NULL DEFAULT (NULL),
|
||||
"inventoryDescription" varchar(128) NULL DEFAULT (NULL),
|
||||
"inventoryNextPermissions" int NULL DEFAULT (NULL),
|
||||
"inventoryCurrentPermissions" int NULL DEFAULT (NULL),
|
||||
"invType" int NULL DEFAULT (NULL),
|
||||
"creatorID" uuid NULL DEFAULT (NULL),
|
||||
"inventoryBasePermissions" int NOT NULL DEFAULT ((0)),
|
||||
"inventoryEveryOnePermissions" int NOT NULL DEFAULT ((0)),
|
||||
"salePrice" int NULL DEFAULT (NULL),
|
||||
"SaleType" smallint NULL DEFAULT (NULL),
|
||||
"creationDate" int NULL DEFAULT (NULL),
|
||||
"groupID" uuid NULL DEFAULT (NULL),
|
||||
"groupOwned" boolean NULL DEFAULT (NULL),
|
||||
"flags" int NULL DEFAULT (NULL),
|
||||
"inventoryGroupPermissions" int NOT NULL DEFAULT ((0))
|
||||
);
|
||||
|
||||
|
||||
INSERT INTO Tmp_inventoryitems ("inventoryID", "assetID", "assetType", "parentFolderID", "avatarID", "inventoryName", "inventoryDescription", "inventoryNextPermissions", "inventoryCurrentPermissions", "invType", "creatorID", "inventoryBasePermissions", "inventoryEveryOnePermissions", "salePrice", "SaleType", "creationDate", "groupID", "groupOwned", "flags", "inventoryGroupPermissions")
|
||||
SELECT cast("inventoryID" as uuid), cast("assetID" as uuid), "assetType", cast("parentFolderID" as uuid), cast("avatarID" as uuid), "inventoryName", "inventoryDescription", "inventoryNextPermissions", "inventoryCurrentPermissions", "invType", cast("creatorID" as uuid), "inventoryBasePermissions", "inventoryEveryOnePermissions", "salePrice", "SaleType", "creationDate", cast("groupID" as uuid), "groupOwned", "flags", "inventoryGroupPermissions"
|
||||
FROM inventoryitems ;
|
||||
|
||||
DROP TABLE inventoryitems;
|
||||
|
||||
alter table Tmp_inventoryitems rename to inventoryitems;
|
||||
|
||||
ALTER TABLE inventoryitems ADD CONSTRAINT
|
||||
PK__inventor__C4B7BC2220C1E124 PRIMARY KEY
|
||||
(
|
||||
"inventoryID"
|
||||
);
|
||||
|
||||
|
||||
CREATE INDEX ii2_owner ON inventoryitems
|
||||
(
|
||||
"avatarID"
|
||||
);
|
||||
|
||||
CREATE INDEX ii2_folder ON inventoryitems
|
||||
(
|
||||
"parentFolderID"
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 5
|
||||
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
-- # Restoring defaults:
|
||||
-- # NOTE: "inventoryID" does NOT need one: it's NOT NULL PK and a unique Guid must be provided every time anyway!
|
||||
|
||||
alter table inventoryitems
|
||||
alter column "inventoryBasePermissions" set default 0;
|
||||
alter table inventoryitems
|
||||
alter column "inventoryEveryOnePermissions" set default 0;
|
||||
alter table inventoryitems
|
||||
alter column "inventoryGroupPermissions" set default 0 ;
|
||||
|
||||
COMMIT ;
|
||||
|
||||
:VERSION 7
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
-- # "creatorID" goes back to VARCHAR(36) (???)
|
||||
|
||||
alter table inventoryitems
|
||||
alter column "creatorID" type varchar(36);
|
||||
|
||||
COMMIT ;
|
||||
|
||||
:VERSION 8
|
||||
|
||||
ALTER TABLE inventoryitems
|
||||
alter column "creatorID" set DEFAULT '00000000-0000-0000-0000-000000000000';
|
||||
|
||||
|
||||
:VERSION 9
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
--# "creatorID" goes up to VARCHAR(255)
|
||||
|
||||
alter table inventoryitems
|
||||
alter column "creatorID" type varchar(255);
|
||||
|
||||
Commit;
|
||||
|
||||
:VERSION 10
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
Alter table inventoryitems Rename Column "SaleType" to "saleType";
|
||||
|
||||
Commit;
|
||||
|
||||
16
OpenSim/Data/PGSQL/Resources/LogStore.migrations
Normal file
16
OpenSim/Data/PGSQL/Resources/LogStore.migrations
Normal file
@@ -0,0 +1,16 @@
|
||||
:VERSION 1
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE logs (
|
||||
"logID" int NOT NULL Primary Key,
|
||||
"target" varchar(36) default NULL,
|
||||
"server" varchar(64) default NULL,
|
||||
"method" varchar(64) default NULL,
|
||||
"arguments" varchar(255) default NULL,
|
||||
"priority" int default NULL,
|
||||
"message" text
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
30
OpenSim/Data/PGSQL/Resources/Presence.migrations
Normal file
30
OpenSim/Data/PGSQL/Resources/Presence.migrations
Normal file
@@ -0,0 +1,30 @@
|
||||
:VERSION 1
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE Presence (
|
||||
"UserID" varchar(255) NOT NULL,
|
||||
"RegionID" uuid NOT NULL,
|
||||
"SessionID" uuid NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
|
||||
"SecureSessionID" uuid NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'
|
||||
);
|
||||
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 2
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE UNIQUE INDEX SessionID ON Presence("SessionID");
|
||||
CREATE INDEX UserID ON Presence("UserID");
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 2
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
ALTER TABLE Presence ADD "LastSeen" Timestamp;
|
||||
|
||||
COMMIT;
|
||||
1154
OpenSim/Data/PGSQL/Resources/RegionStore.migrations
Normal file
1154
OpenSim/Data/PGSQL/Resources/RegionStore.migrations
Normal file
File diff suppressed because it is too large
Load Diff
51
OpenSim/Data/PGSQL/Resources/UserAccount.migrations
Normal file
51
OpenSim/Data/PGSQL/Resources/UserAccount.migrations
Normal file
@@ -0,0 +1,51 @@
|
||||
:VERSION 1
|
||||
|
||||
CREATE TABLE UserAccounts (
|
||||
"PrincipalID" uuid NOT NULL Primary key,
|
||||
"ScopeID" uuid NOT NULL,
|
||||
"FirstName" varchar(64) NOT NULL,
|
||||
"LastName" varchar(64) NOT NULL,
|
||||
"Email" varchar(64) NULL,
|
||||
"ServiceURLs" text NULL,
|
||||
"Created" int default NULL
|
||||
);
|
||||
|
||||
|
||||
:VERSION 2
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
INSERT INTO UserAccounts ("PrincipalID", "ScopeID", "FirstName", "LastName", "Email", "ServiceURLs", "Created")
|
||||
SELECT UUID AS "PrincipalID", '00000000-0000-0000-0000-000000000000' AS "ScopeID",
|
||||
username AS "FirstName",
|
||||
lastname AS "LastName",
|
||||
email as "Email", (
|
||||
'AssetServerURI=' +
|
||||
userAssetURI + ' InventoryServerURI=' + userInventoryURI + ' GatewayURI= HomeURI=') AS "ServiceURLs",
|
||||
created as "Created" FROM users;
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 3
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE UNIQUE INDEX "PrincipalID" ON UserAccounts("PrincipalID");
|
||||
CREATE INDEX "Email" ON UserAccounts("Email");
|
||||
CREATE INDEX "FirstName" ON UserAccounts("FirstName");
|
||||
CREATE INDEX "LastName" ON UserAccounts("LastName");
|
||||
CREATE INDEX Name ON UserAccounts("FirstName","LastName");
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 4
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
ALTER TABLE UserAccounts ADD "UserLevel" integer NOT NULL DEFAULT 0;
|
||||
ALTER TABLE UserAccounts ADD "UserFlags" integer NOT NULL DEFAULT 0;
|
||||
ALTER TABLE UserAccounts ADD "UserTitle" varchar(64) NOT NULL DEFAULT '';
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
||||
83
OpenSim/Data/PGSQL/Resources/UserProfiles.migrations
Normal file
83
OpenSim/Data/PGSQL/Resources/UserProfiles.migrations
Normal file
@@ -0,0 +1,83 @@
|
||||
:VERSION 1 # -------------------------------
|
||||
|
||||
begin;
|
||||
|
||||
CREATE TABLE classifieds (
|
||||
"classifieduuid" char(36) NOT NULL,
|
||||
"creatoruuid" char(36) NOT NULL,
|
||||
"creationdate" integer NOT NULL,
|
||||
"expirationdate" integer NOT NULL,
|
||||
"category" varchar(20) NOT NULL,
|
||||
"name" varchar(255) NOT NULL,
|
||||
"description" text NOT NULL,
|
||||
"parceluuid" char(36) NOT NULL,
|
||||
"parentestate" integer NOT NULL,
|
||||
"snapshotuuid" char(36) NOT NULL,
|
||||
"simname" varchar(255) NOT NULL,
|
||||
"posglobal" varchar(255) NOT NULL,
|
||||
"parcelname" varchar(255) NOT NULL,
|
||||
"classifiedflags" integer NOT NULL,
|
||||
"priceforlisting" integer NOT NULL,
|
||||
constraint classifiedspk PRIMARY KEY ("classifieduuid")
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE usernotes (
|
||||
"useruuid" varchar(36) NOT NULL,
|
||||
"targetuuid" varchar(36) NOT NULL,
|
||||
"notes" text NOT NULL,
|
||||
constraint usernoteuk UNIQUE ("useruuid","targetuuid")
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE userpicks (
|
||||
"pickuuid" varchar(36) NOT NULL,
|
||||
"creatoruuid" varchar(36) NOT NULL,
|
||||
"toppick" boolean 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" integer NOT NULL,
|
||||
"enabled" boolean NOT NULL,
|
||||
PRIMARY KEY ("pickuuid")
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE userprofile (
|
||||
"useruuid" varchar(36) NOT NULL,
|
||||
"profilePartner" varchar(36) NOT NULL,
|
||||
"profileAllowPublish" bytea NOT NULL,
|
||||
"profileMaturePublish" bytea NOT NULL,
|
||||
"profileURL" varchar(255) NOT NULL,
|
||||
"profileWantToMask" integer NOT NULL,
|
||||
"profileWantToText" text NOT NULL,
|
||||
"profileSkillsMask" integer 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")
|
||||
);
|
||||
|
||||
commit;
|
||||
|
||||
:VERSION 2 # -------------------------------
|
||||
|
||||
begin;
|
||||
CREATE TABLE userdata (
|
||||
"UserId" char(36) NOT NULL,
|
||||
"TagId" varchar(64) NOT NULL,
|
||||
"DataKey" varchar(255),
|
||||
"DataVal" varchar(255),
|
||||
PRIMARY KEY ("UserId","TagId")
|
||||
);
|
||||
|
||||
commit;
|
||||
|
||||
404
OpenSim/Data/PGSQL/Resources/UserStore.migrations
Normal file
404
OpenSim/Data/PGSQL/Resources/UserStore.migrations
Normal file
@@ -0,0 +1,404 @@
|
||||
:VERSION 1
|
||||
|
||||
CREATE TABLE users (
|
||||
"UUID" varchar(36) NOT NULL default '' Primary Key,
|
||||
"username" varchar(32) NOT NULL,
|
||||
"lastname" varchar(32) NOT NULL,
|
||||
"passwordHash" varchar(32) NOT NULL,
|
||||
"passwordSalt" varchar(32) NOT NULL,
|
||||
"homeRegion" bigint default NULL,
|
||||
"homeLocationX" double precision default NULL,
|
||||
"homeLocationY" double precision default NULL,
|
||||
"homeLocationZ" double precision default NULL,
|
||||
"homeLookAtX" double precision default NULL,
|
||||
"homeLookAtY" double precision default NULL,
|
||||
"homeLookAtZ" double precision default NULL,
|
||||
"created" int NOT NULL,
|
||||
"lastLogin" int NOT NULL,
|
||||
"userInventoryURI" varchar(255) default NULL,
|
||||
"userAssetURI" varchar(255) default NULL,
|
||||
"profileCanDoMask" int default NULL,
|
||||
"profileWantDoMask" int default NULL,
|
||||
"profileAboutText" text,
|
||||
"profileFirstText" text,
|
||||
"profileImage" varchar(36) default NULL,
|
||||
"profileFirstImage" varchar(36) default NULL,
|
||||
"webLoginKey" varchar(36) default NULL
|
||||
);
|
||||
|
||||
CREATE INDEX "usernames" ON users
|
||||
(
|
||||
"username" ASC,
|
||||
"lastname" ASC
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE agents (
|
||||
"UUID" varchar(36) NOT NULL Primary Key,
|
||||
"sessionID" varchar(36) NOT NULL,
|
||||
"secureSessionID" varchar(36) NOT NULL,
|
||||
"agentIP" varchar(16) NOT NULL,
|
||||
"agentPort" int NOT NULL,
|
||||
"agentOnline" smallint NOT NULL,
|
||||
"loginTime" int NOT NULL,
|
||||
"logoutTime" int NOT NULL,
|
||||
"currentRegion" varchar(36) NOT NULL,
|
||||
"currentHandle" bigint NOT NULL,
|
||||
"currentPos" varchar(64) NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX session ON agents
|
||||
(
|
||||
"sessionID" ASC
|
||||
);
|
||||
|
||||
CREATE INDEX ssession ON agents
|
||||
(
|
||||
"secureSessionID" ASC
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE userfriends(
|
||||
"ownerID" varchar(50) NOT NULL,
|
||||
"friendID" varchar(50) NOT NULL,
|
||||
"friendPerms" varchar(50) NOT NULL,
|
||||
"datetimestamp" varchar(50) NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE avatarappearance (
|
||||
"Owner" varchar(36) NOT NULL primary key,
|
||||
"Serial" int NOT NULL,
|
||||
"Visual_Params" bytea NOT NULL,
|
||||
"Texture" bytea NOT NULL,
|
||||
"Avatar_Height" double precision NOT NULL,
|
||||
"Body_Item" varchar(36) NOT NULL,
|
||||
"Body_Asset" varchar(36) NOT NULL,
|
||||
"Skin_Item" varchar(36) NOT NULL,
|
||||
"Skin_Asset" varchar(36) NOT NULL,
|
||||
"Hair_Item" varchar(36) NOT NULL,
|
||||
"Hair_Asset" varchar(36) NOT NULL,
|
||||
"Eyes_Item" varchar(36) NOT NULL,
|
||||
"Eyes_Asset" varchar(36) NOT NULL,
|
||||
"Shirt_Item" varchar(36) NOT NULL,
|
||||
"Shirt_Asset" varchar(36) NOT NULL,
|
||||
"Pants_Item" varchar(36) NOT NULL,
|
||||
"Pants_Asset" varchar(36) NOT NULL,
|
||||
"Shoes_Item" varchar(36) NOT NULL,
|
||||
"Shoes_Asset" varchar(36) NOT NULL,
|
||||
"Socks_Item" varchar(36) NOT NULL,
|
||||
"Socks_Asset" varchar(36) NOT NULL,
|
||||
"Jacket_Item" varchar(36) NOT NULL,
|
||||
"Jacket_Asset" varchar(36) NOT NULL,
|
||||
"Gloves_Item" varchar(36) NOT NULL,
|
||||
"Gloves_Asset" varchar(36) NOT NULL,
|
||||
"Undershirt_Item" varchar(36) NOT NULL,
|
||||
"Undershirt_Asset" varchar(36) NOT NULL,
|
||||
"Underpants_Item" varchar(36) NOT NULL,
|
||||
"Underpants_Asset" varchar(36) NOT NULL,
|
||||
"Skirt_Item" varchar(36) NOT NULL,
|
||||
"Skirt_Asset" varchar(36) NOT NULL
|
||||
);
|
||||
|
||||
:VERSION 2
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
ALTER TABLE users ADD "homeRegionID" varchar(36) NOT NULL default '00000000-0000-0000-0000-000000000000';
|
||||
ALTER TABLE users ADD "userFlags" int NOT NULL default 0;
|
||||
ALTER TABLE users ADD "godLevel" int NOT NULL default 0;
|
||||
ALTER TABLE users ADD "customType" varchar(32) not null default '';
|
||||
ALTER TABLE users ADD "partner" varchar(36) not null default '00000000-0000-0000-0000-000000000000';
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
||||
:VERSION 3
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE avatarattachments (
|
||||
"UUID" varchar(36) NOT NULL
|
||||
, "attachpoint" int NOT NULL
|
||||
, item varchar(36) NOT NULL
|
||||
, asset varchar(36) NOT NULL);
|
||||
|
||||
CREATE INDEX IX_avatarattachments ON avatarattachments
|
||||
(
|
||||
"UUID"
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
||||
:VERSION 4
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE Tmp_userfriends
|
||||
(
|
||||
"ownerID" varchar(36) NOT NULL,
|
||||
"friendID" varchar(36) NOT NULL,
|
||||
"friendPerms" int NOT NULL,
|
||||
"datetimestamp" int NOT NULL
|
||||
);
|
||||
|
||||
INSERT INTO Tmp_userfriends ("ownerID", "friendID", "friendPerms", "datetimestamp")
|
||||
SELECT cast("ownerID" as varchar(36)), cast("friendID" as varchar(36)), cast("friendPerms" as int), cast("datetimestamp" as int)
|
||||
FROM userfriends;
|
||||
|
||||
DROP TABLE userfriends;
|
||||
|
||||
alter table Tmp_userfriends rename to userfriends;
|
||||
|
||||
CREATE INDEX IX_userfriends_ownerID ON userfriends
|
||||
(
|
||||
"ownerID"
|
||||
);
|
||||
|
||||
CREATE INDEX IX_userfriends_friendID ON userfriends
|
||||
(
|
||||
"friendID"
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
||||
:VERSION 5
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
ALTER TABLE users add "email" varchar(250);
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
||||
:VERSION 6
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE Tmp_users
|
||||
(
|
||||
"UUID" uuid NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000'),
|
||||
"username" varchar(32) NOT NULL,
|
||||
"lastname" varchar(32) NOT NULL,
|
||||
"passwordHash" varchar(32) NOT NULL,
|
||||
"passwordSalt" varchar(32) NOT NULL,
|
||||
"homeRegion" bigint NULL DEFAULT (NULL),
|
||||
"homeLocationX" double precision NULL DEFAULT (NULL),
|
||||
"homeLocationY" double precision NULL DEFAULT (NULL),
|
||||
"homeLocationZ" double precision NULL DEFAULT (NULL),
|
||||
"homeLookAtX" double precision NULL DEFAULT (NULL),
|
||||
"homeLookAtY" double precision NULL DEFAULT (NULL),
|
||||
"homeLookAtZ" double precision NULL DEFAULT (NULL),
|
||||
"created" int NOT NULL,
|
||||
"lastLogin" int NOT NULL,
|
||||
"userInventoryURI" varchar(255) NULL DEFAULT (NULL),
|
||||
"userAssetURI" varchar(255) NULL DEFAULT (NULL),
|
||||
"profileCanDoMask" int NULL DEFAULT (NULL),
|
||||
"profileWantDoMask" int NULL DEFAULT (NULL),
|
||||
"profileAboutText" text NULL,
|
||||
"profileFirstText" text NULL,
|
||||
"profileImage" uuid NULL DEFAULT (NULL),
|
||||
"profileFirstImage" uuid NULL DEFAULT (NULL),
|
||||
"webLoginKey" uuid NULL DEFAULT (NULL),
|
||||
"homeRegionID" uuid NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000'),
|
||||
"userFlags" int NOT NULL DEFAULT ((0)),
|
||||
"godLevel" int NOT NULL DEFAULT ((0)),
|
||||
"customType" varchar(32) NOT NULL DEFAULT (''),
|
||||
"partner" uuid NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000'),
|
||||
email varchar(250) NULL
|
||||
);
|
||||
|
||||
INSERT INTO Tmp_users ("UUID", "username", "lastname", "passwordHash", "passwordSalt", "homeRegion", "homeLocationX", "homeLocationY", "homeLocationZ", "homeLookAtX", "homeLookAtY", "homeLookAtZ", "created", "lastLogin", "userInventoryURI", "userAssetURI", "profileCanDoMask", "profileWantDoMask", "profileAboutText", "profileFirstText", "profileImage", "profileFirstImage", "webLoginKey", "homeRegionID", "userFlags", "godLevel", "customType", "partner", email)
|
||||
SELECT cast("UUID" as uuid), "username", "lastname", "passwordHash", "passwordSalt", "homeRegion", "homeLocationX", "homeLocationY", "homeLocationZ", "homeLookAtX", "homeLookAtY", "homeLookAtZ", "created", "lastLogin", "userInventoryURI", "userAssetURI", "profileCanDoMask", "profileWantDoMask", "profileAboutText", "profileFirstText", cast("profileImage" as uuid), cast("profileFirstImage" as uuid), cast("webLoginKey" as uuid), cast("homeRegionID" as uuid), "userFlags", "godLevel", "customType", cast("partner" as uuid), email
|
||||
FROM users ;
|
||||
|
||||
DROP TABLE users;
|
||||
|
||||
alter table Tmp_users rename to users;
|
||||
|
||||
ALTER TABLE users ADD CONSTRAINT
|
||||
PK__users__65A475E737A5467C PRIMARY KEY
|
||||
(
|
||||
"UUID"
|
||||
);
|
||||
|
||||
CREATE INDEX "usernames" ON users
|
||||
(
|
||||
"username",
|
||||
"lastname"
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
||||
:VERSION 7
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE Tmp_agents
|
||||
(
|
||||
"UUID" uuid NOT NULL,
|
||||
"sessionID" uuid NOT NULL,
|
||||
"secureSessionID" uuid NOT NULL,
|
||||
"agentIP" varchar(16) NOT NULL,
|
||||
"agentPort" int NOT NULL,
|
||||
"agentOnline" smallint NOT NULL,
|
||||
"loginTime" int NOT NULL,
|
||||
"logoutTime" int NOT NULL,
|
||||
"currentRegion" uuid NOT NULL,
|
||||
"currentHandle" bigint NOT NULL,
|
||||
"currentPos" varchar(64) NOT NULL
|
||||
);
|
||||
|
||||
INSERT INTO Tmp_agents ("UUID", "sessionID", "secureSessionID", "agentIP", "agentPort", "agentOnline", "loginTime", "logoutTime", "currentRegion", "currentHandle", "currentPos")
|
||||
SELECT cast("UUID" as uuid), cast("sessionID" as uuid), cast("secureSessionID" as uuid), "agentIP", "agentPort", "agentOnline", "loginTime", "logoutTime", cast("currentRegion" as uuid), "currentHandle", "currentPos"
|
||||
FROM agents ;
|
||||
|
||||
DROP TABLE agents;
|
||||
|
||||
alter table Tmp_agents rename to agents;
|
||||
|
||||
ALTER TABLE agents ADD CONSTRAINT
|
||||
PK__agents__65A475E749C3F6B7 PRIMARY KEY
|
||||
(
|
||||
"UUID"
|
||||
) ;
|
||||
|
||||
CREATE INDEX session ON agents
|
||||
(
|
||||
"sessionID"
|
||||
);
|
||||
|
||||
CREATE INDEX ssession ON agents
|
||||
(
|
||||
"secureSessionID"
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
||||
:VERSION 8
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE Tmp_userfriends
|
||||
(
|
||||
"ownerID" uuid NOT NULL,
|
||||
"friendID" uuid NOT NULL,
|
||||
"friendPerms" int NOT NULL,
|
||||
"datetimestamp" int NOT NULL
|
||||
);
|
||||
|
||||
INSERT INTO Tmp_userfriends ("ownerID", "friendID", "friendPerms", "datetimestamp")
|
||||
SELECT cast("ownerID" as uuid), cast( "friendID" as uuid), "friendPerms", "datetimestamp"
|
||||
FROM userfriends;
|
||||
|
||||
DROP TABLE userfriends;
|
||||
|
||||
alter table Tmp_userfriends rename to userfriends;
|
||||
|
||||
CREATE INDEX IX_userfriends_ownerID ON userfriends
|
||||
(
|
||||
"ownerID"
|
||||
);
|
||||
|
||||
CREATE INDEX IX_userfriends_friendID ON userfriends
|
||||
(
|
||||
"friendID"
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
||||
:VERSION 9
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE Tmp_avatarappearance
|
||||
(
|
||||
"Owner" uuid NOT NULL,
|
||||
"Serial" int NOT NULL,
|
||||
"Visual_Params" bytea NOT NULL,
|
||||
"Texture" bytea NOT NULL,
|
||||
"Avatar_Height" double precision NOT NULL,
|
||||
"Body_Item" uuid NOT NULL,
|
||||
"Body_Asset" uuid NOT NULL,
|
||||
"Skin_Item" uuid NOT NULL,
|
||||
"Skin_Asset" uuid NOT NULL,
|
||||
"Hair_Item" uuid NOT NULL,
|
||||
"Hair_Asset" uuid NOT NULL,
|
||||
"Eyes_Item" uuid NOT NULL,
|
||||
"Eyes_Asset" uuid NOT NULL,
|
||||
"Shirt_Item" uuid NOT NULL,
|
||||
"Shirt_Asset" uuid NOT NULL,
|
||||
"Pants_Item" uuid NOT NULL,
|
||||
"Pants_Asset" uuid NOT NULL,
|
||||
"Shoes_Item" uuid NOT NULL,
|
||||
"Shoes_Asset" uuid NOT NULL,
|
||||
"Socks_Item" uuid NOT NULL,
|
||||
"Socks_Asset" uuid NOT NULL,
|
||||
"Jacket_Item" uuid NOT NULL,
|
||||
"Jacket_Asset" uuid NOT NULL,
|
||||
"Gloves_Item" uuid NOT NULL,
|
||||
"Gloves_Asset" uuid NOT NULL,
|
||||
"Undershirt_Item" uuid NOT NULL,
|
||||
"Undershirt_Asset" uuid NOT NULL,
|
||||
"Underpants_Item" uuid NOT NULL,
|
||||
"Underpants_Asset" uuid NOT NULL,
|
||||
"Skirt_Item" uuid NOT NULL,
|
||||
"Skirt_Asset" uuid NOT NULL
|
||||
);
|
||||
|
||||
INSERT INTO Tmp_avatarappearance ("Owner", "Serial", "Visual_Params", "Texture", "Avatar_Height", "Body_Item", "Body_Asset", "Skin_Item", "Skin_Asset", "Hair_Item", "Hair_Asset", "Eyes_Item", "Eyes_Asset", "Shirt_Item", "Shirt_Asset", "Pants_Item", "Pants_Asset", "Shoes_Item", "Shoes_Asset", "Socks_Item", "Socks_Asset", "Jacket_Item", "Jacket_Asset", "Gloves_Item", "Gloves_Asset", "Undershirt_Item", "Undershirt_Asset", "Underpants_Item", "Underpants_Asset", "Skirt_Item", "Skirt_Asset")
|
||||
SELECT cast("Owner" as uuid), "Serial", "Visual_Params", "Texture", "Avatar_Height", cast("Body_Item" as uuid), cast("Body_Asset" as uuid), cast("Skin_Item" as uuid), cast("Skin_Asset" as uuid), cast("Hair_Item" as uuid), cast("Hair_Asset" as uuid), cast("Eyes_Item" as uuid), cast("Eyes_Asset" as uuid), cast("Shirt_Item" as uuid), cast("Shirt_Asset" as uuid), cast("Pants_Item" as uuid), cast("Pants_Asset" as uuid), cast("Shoes_Item" as uuid), cast("Shoes_Asset" as uuid), cast("Socks_Item" as uuid), cast("Socks_Asset" as uuid), cast("Jacket_Item" as uuid), cast("Jacket_Asset" as uuid), cast("Gloves_Item" as uuid), cast("Gloves_Asset" as uuid), cast("Undershirt_Item" as uuid), cast("Undershirt_Asset" as uuid), cast("Underpants_Item" as uuid), cast("Underpants_Asset" as uuid), cast("Skirt_Item" as uuid), cast("Skirt_Asset" as uuid)
|
||||
FROM avatarappearance ;
|
||||
|
||||
DROP TABLE avatarappearance;
|
||||
|
||||
alter table Tmp_avatarappearance rename to avatarappearance;
|
||||
|
||||
ALTER TABLE avatarappearance ADD CONSTRAINT
|
||||
PK__avatarap__7DD115CC4E88ABD4 PRIMARY KEY
|
||||
(
|
||||
"Owner"
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
||||
:VERSION 10
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE Tmp_avatarattachments
|
||||
(
|
||||
"UUID" uuid NOT NULL,
|
||||
"attachpoint" int NOT NULL,
|
||||
item uuid NOT NULL,
|
||||
asset uuid NOT NULL
|
||||
);
|
||||
|
||||
INSERT INTO Tmp_avatarattachments ("UUID", "attachpoint", item, asset)
|
||||
SELECT cast("UUID" as uuid), "attachpoint", cast(item as uuid), cast(asset as uuid)
|
||||
FROM avatarattachments ;
|
||||
|
||||
DROP TABLE avatarattachments;
|
||||
|
||||
alter table Tmp_avatarattachments rename to avatarattachments;
|
||||
|
||||
CREATE INDEX IX_avatarattachments ON avatarattachments
|
||||
(
|
||||
"UUID"
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
||||
:VERSION 11
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
ALTER TABLE users ADD "scopeID" uuid not null default '00000000-0000-0000-0000-000000000000';
|
||||
|
||||
COMMIT;
|
||||
27
OpenSim/Data/PGSQL/Resources/XAssetStore.migrations
Normal file
27
OpenSim/Data/PGSQL/Resources/XAssetStore.migrations
Normal file
@@ -0,0 +1,27 @@
|
||||
# -----------------
|
||||
:VERSION 1
|
||||
|
||||
BEGIN;
|
||||
|
||||
CREATE TABLE XAssetsMeta (
|
||||
"ID" char(36) NOT NULL,
|
||||
"Hash" char(32) NOT NULL,
|
||||
"Name" varchar(64) NOT NULL,
|
||||
"Description" varchar(64) NOT NULL,
|
||||
"AssetType" smallint NOT NULL,
|
||||
"Local" smallint NOT NULL,
|
||||
"Temporary" smallint NOT NULL,
|
||||
"CreateTime" integer NOT NULL,
|
||||
"AccessTime" integer NOT NULL,
|
||||
"AssetFlags" integer NOT NULL,
|
||||
"CreatorID" varchar(128) NOT NULL,
|
||||
PRIMARY KEY ("ID")
|
||||
);
|
||||
|
||||
CREATE TABLE XAssetsData (
|
||||
"Hash" char(32) NOT NULL,
|
||||
"Data" bytea NOT NULL,
|
||||
PRIMARY KEY ("Hash")
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
94
OpenSim/Data/PGSQL/Resources/os_groups_Store.migrations
Normal file
94
OpenSim/Data/PGSQL/Resources/os_groups_Store.migrations
Normal file
@@ -0,0 +1,94 @@
|
||||
:VERSION 1 # --------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
CREATE TABLE os_groups_groups (
|
||||
"GroupID" char(36) Primary Key NOT NULL default '',
|
||||
"Location" varchar(255) NOT NULL default '',
|
||||
"Name" varchar(255) NOT NULL default '',
|
||||
"Charter" text NOT NULL,
|
||||
"InsigniaID" char(36) NOT NULL default '',
|
||||
"FounderID" char(36) NOT NULL default '',
|
||||
"MembershipFee" integer NOT NULL default '0',
|
||||
"OpenEnrollment" varchar(255) NOT NULL default '',
|
||||
"ShowInList" integer NOT NULL default '0',
|
||||
"AllowPublish" integer NOT NULL default '0',
|
||||
"MaturePublish" integer NOT NULL default '0',
|
||||
"OwnerRoleID" char(36) NOT NULL default ''
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE os_groups_membership (
|
||||
"GroupID"char(36) NOT NULL default '',
|
||||
"PrincipalID" VARCHAR(255) NOT NULL default '',
|
||||
"SelectedRoleID" char(36) NOT NULL default '',
|
||||
"Contribution" integer NOT NULL default '0',
|
||||
"ListInProfile" integer NOT NULL default '1',
|
||||
"AcceptNotices" integer NOT NULL default '1',
|
||||
"AccessToken" char(36) NOT NULL default '',
|
||||
constraint os_groupmemberpk primary key ("GroupID", "PrincipalID")
|
||||
);
|
||||
|
||||
|
||||
|
||||
CREATE TABLE os_groups_roles (
|
||||
"GroupID" char(36) NOT NULL default '',
|
||||
"RoleID" char(36) NOT NULL default '',
|
||||
"Name" varchar(255) NOT NULL default '',
|
||||
"Description" varchar(255) NOT NULL default '',
|
||||
"Title" varchar(255) NOT NULL default '',
|
||||
"Powers" bigint NOT NULL default 0,
|
||||
constraint os_grouprolepk PRIMARY KEY ("GroupID","RoleID")
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE os_groups_rolemembership (
|
||||
"GroupID" char(36) NOT NULL default '',
|
||||
"RoleID" char(36) NOT NULL default '',
|
||||
"PrincipalID" VARCHAR(255) NOT NULL default '',
|
||||
constraint os_grouprolememberpk PRIMARY KEY ("GroupID","RoleID","PrincipalID")
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE os_groups_invites (
|
||||
"InviteID" char(36) NOT NULL default '',
|
||||
"GroupID" char(36) NOT NULL default '',
|
||||
"RoleID" char(36) NOT NULL default '',
|
||||
"PrincipalID" VARCHAR(255) NOT NULL default '',
|
||||
"TMStamp" timestamp NOT NULL default now(),
|
||||
constraint os_groupinvitespk PRIMARY KEY ("InviteID")
|
||||
);
|
||||
-- UNIQUE KEY "PrincipalGroup" ("GroupID","PrincipalID")
|
||||
|
||||
|
||||
CREATE TABLE os_groups_notices (
|
||||
"GroupID" char(36) NOT NULL default '',
|
||||
"NoticeID" char(36) NOT NULL default '',
|
||||
"TMStamp" integer NOT NULL default '0',
|
||||
"FromName" varchar(255) NOT NULL default '',
|
||||
"Subject" varchar(255) NOT NULL default '',
|
||||
"Message" text NOT NULL,
|
||||
"HasAttachment" integer NOT NULL default '0',
|
||||
"AttachmentType" integer NOT NULL default '0',
|
||||
"AttachmentName" varchar(128) NOT NULL default '',
|
||||
"AttachmentItemID" char(36) NOT NULL default '',
|
||||
"AttachmentOwnerID" varchar(255) NOT NULL default '',
|
||||
constraint os_groupsnoticespk PRIMARY KEY ("NoticeID")
|
||||
);
|
||||
-- KEY "GroupID" ("GroupID"),
|
||||
-- KEY "TMStamp" ("TMStamp")
|
||||
|
||||
CREATE TABLE os_groups_principals (
|
||||
"PrincipalID" VARCHAR(255) NOT NULL default '',
|
||||
"ActiveGroupID" char(36) NOT NULL default '',
|
||||
constraint os_groupprincpk PRIMARY KEY ("PrincipalID")
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 2 # --------------------------
|
||||
|
||||
BEGIN;
|
||||
|
||||
|
||||
COMMIT;
|
||||
@@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
|
||||
[assembly : AssemblyVersion("0.7.6.*")]
|
||||
[assembly : AssemblyVersion("0.8.0.*")]
|
||||
|
||||
|
||||
@@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
|
||||
[assembly : AssemblyVersion("0.7.6.*")]
|
||||
[assembly : AssemblyVersion("0.8.0.*")]
|
||||
|
||||
|
||||
@@ -600,3 +600,15 @@ BEGIN;
|
||||
ALTER TABLE prims ADD COLUMN `KeyframeMotion` blob;
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 30 #---------------- Save Attachment info
|
||||
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE prims ADD COLUMN AttachedPosX double default '0';
|
||||
ALTER TABLE prims ADD COLUMN AttachedPosY double default '0';
|
||||
ALTER TABLE prims ADD COLUMN AttachedPosZ double default '0';
|
||||
ALTER TABLE primshapes ADD COLUMN LastAttachPoint int not null default '0';
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
||||
@@ -1236,6 +1236,10 @@ namespace OpenSim.Data.SQLite
|
||||
|
||||
createCol(prims, "MediaURL", typeof(String));
|
||||
|
||||
createCol(prims, "AttachedPosX", typeof(Double));
|
||||
createCol(prims, "AttachedPosY", typeof(Double));
|
||||
createCol(prims, "AttachedPosZ", typeof(Double));
|
||||
|
||||
createCol(prims, "DynAttrs", typeof(String));
|
||||
|
||||
createCol(prims, "PhysicsShapeType", typeof(Byte));
|
||||
@@ -1724,6 +1728,12 @@ namespace OpenSim.Data.SQLite
|
||||
prim.MediaUrl = (string)row["MediaURL"];
|
||||
}
|
||||
|
||||
prim.AttachedPos = new Vector3(
|
||||
Convert.ToSingle(row["AttachedPosX"]),
|
||||
Convert.ToSingle(row["AttachedPosY"]),
|
||||
Convert.ToSingle(row["AttachedPosZ"])
|
||||
);
|
||||
|
||||
if (!(row["DynAttrs"] is System.DBNull))
|
||||
{
|
||||
//m_log.DebugFormat("[SQLITE]: DynAttrs type [{0}]", row["DynAttrs"].GetType());
|
||||
@@ -2176,6 +2186,10 @@ namespace OpenSim.Data.SQLite
|
||||
|
||||
row["MediaURL"] = prim.MediaUrl;
|
||||
|
||||
row["AttachedPosX"] = prim.AttachedPos.X;
|
||||
row["AttachedPosY"] = prim.AttachedPos.Y;
|
||||
row["AttachedPosZ"] = prim.AttachedPos.Z;
|
||||
|
||||
if (prim.DynAttrs.CountNamespaces > 0)
|
||||
row["DynAttrs"] = prim.DynAttrs.ToXml();
|
||||
else
|
||||
@@ -2444,6 +2458,7 @@ namespace OpenSim.Data.SQLite
|
||||
s.ProfileCurve = Convert.ToByte(row["ProfileCurve"]);
|
||||
s.ProfileHollow = Convert.ToUInt16(row["ProfileHollow"]);
|
||||
s.State = Convert.ToByte(row["State"]);
|
||||
s.LastAttachPoint = Convert.ToByte(row["LastAttachPoint"]);
|
||||
|
||||
byte[] textureEntry = (byte[])row["Texture"];
|
||||
s.TextureEntry = textureEntry;
|
||||
@@ -2493,6 +2508,7 @@ namespace OpenSim.Data.SQLite
|
||||
row["ProfileCurve"] = s.ProfileCurve;
|
||||
row["ProfileHollow"] = s.ProfileHollow;
|
||||
row["State"] = s.State;
|
||||
row["LastAttachPoint"] = s.LastAttachPoint;
|
||||
|
||||
row["Texture"] = s.TextureEntry;
|
||||
row["ExtraParams"] = s.ExtraParams;
|
||||
|
||||
@@ -59,4 +59,4 @@ using System.Runtime.InteropServices;
|
||||
// Revision
|
||||
//
|
||||
|
||||
[assembly : AssemblyVersion("0.7.6.*")]
|
||||
[assembly : AssemblyVersion("0.8.0.*")]
|
||||
|
||||
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion("0.7.6.*")]
|
||||
[assembly: AssemblyVersion("0.8.0.*")]
|
||||
|
||||
|
||||
275
OpenSim/Framework/BasicDOSProtector.cs
Normal file
275
OpenSim/Framework/BasicDOSProtector.cs
Normal file
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
* 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.Reflection;
|
||||
using log4net;
|
||||
|
||||
namespace OpenSim.Framework
|
||||
{
|
||||
|
||||
public class BasicDOSProtector
|
||||
{
|
||||
public enum ThrottleAction
|
||||
{
|
||||
DoThrottledMethod,
|
||||
DoThrow
|
||||
}
|
||||
private readonly CircularBuffer<int> _generalRequestTimes; // General request checker
|
||||
private readonly BasicDosProtectorOptions _options;
|
||||
private readonly Dictionary<string, CircularBuffer<int>> _deeperInspection; // per client request checker
|
||||
private readonly Dictionary<string, int> _tempBlocked; // blocked list
|
||||
private readonly Dictionary<string, int> _sessions;
|
||||
private readonly System.Timers.Timer _forgetTimer; // Cleanup timer
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private readonly System.Threading.ReaderWriterLockSlim _blockLockSlim = new System.Threading.ReaderWriterLockSlim();
|
||||
private readonly System.Threading.ReaderWriterLockSlim _sessionLockSlim = new System.Threading.ReaderWriterLockSlim();
|
||||
public BasicDOSProtector(BasicDosProtectorOptions options)
|
||||
{
|
||||
_generalRequestTimes = new CircularBuffer<int>(options.MaxRequestsInTimeframe + 1, true);
|
||||
_generalRequestTimes.Put(0);
|
||||
_options = options;
|
||||
_deeperInspection = new Dictionary<string, CircularBuffer<int>>();
|
||||
_tempBlocked = new Dictionary<string, int>();
|
||||
_sessions = new Dictionary<string, int>();
|
||||
_forgetTimer = new System.Timers.Timer();
|
||||
_forgetTimer.Elapsed += delegate
|
||||
{
|
||||
_forgetTimer.Enabled = false;
|
||||
|
||||
List<string> removes = new List<string>();
|
||||
_blockLockSlim.EnterReadLock();
|
||||
foreach (string str in _tempBlocked.Keys)
|
||||
{
|
||||
if (
|
||||
Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(),
|
||||
_tempBlocked[str]) > 0)
|
||||
removes.Add(str);
|
||||
}
|
||||
_blockLockSlim.ExitReadLock();
|
||||
lock (_deeperInspection)
|
||||
{
|
||||
_blockLockSlim.EnterWriteLock();
|
||||
for (int i = 0; i < removes.Count; i++)
|
||||
{
|
||||
_tempBlocked.Remove(removes[i]);
|
||||
_deeperInspection.Remove(removes[i]);
|
||||
_sessions.Remove(removes[i]);
|
||||
}
|
||||
_blockLockSlim.ExitWriteLock();
|
||||
}
|
||||
foreach (string str in removes)
|
||||
{
|
||||
m_log.InfoFormat("[{0}] client: {1} is no longer blocked.",
|
||||
_options.ReportingName, str);
|
||||
}
|
||||
_blockLockSlim.EnterReadLock();
|
||||
if (_tempBlocked.Count > 0)
|
||||
_forgetTimer.Enabled = true;
|
||||
_blockLockSlim.ExitReadLock();
|
||||
};
|
||||
|
||||
_forgetTimer.Interval = _options.ForgetTimeSpan.TotalMilliseconds;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given a string Key, Returns if that context is blocked
|
||||
/// </summary>
|
||||
/// <param name="key">A Key identifying the context</param>
|
||||
/// <returns>bool Yes or No, True or False for blocked</returns>
|
||||
public bool IsBlocked(string key)
|
||||
{
|
||||
bool ret = false;
|
||||
_blockLockSlim.EnterReadLock();
|
||||
ret = _tempBlocked.ContainsKey(key);
|
||||
_blockLockSlim.ExitReadLock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process the velocity of this context
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="endpoint"></param>
|
||||
/// <returns></returns>
|
||||
public bool Process(string key, string endpoint)
|
||||
{
|
||||
if (_options.MaxRequestsInTimeframe < 1 || _options.RequestTimeSpan.TotalMilliseconds < 1)
|
||||
return true;
|
||||
|
||||
string clientstring = key;
|
||||
|
||||
_blockLockSlim.EnterReadLock();
|
||||
if (_tempBlocked.ContainsKey(clientstring))
|
||||
{
|
||||
_blockLockSlim.ExitReadLock();
|
||||
|
||||
if (_options.ThrottledAction == ThrottleAction.DoThrottledMethod)
|
||||
return false;
|
||||
else
|
||||
throw new System.Security.SecurityException("Throttled");
|
||||
}
|
||||
|
||||
_blockLockSlim.ExitReadLock();
|
||||
|
||||
lock (_generalRequestTimes)
|
||||
_generalRequestTimes.Put(Util.EnvironmentTickCount());
|
||||
|
||||
if (_options.MaxConcurrentSessions > 0)
|
||||
{
|
||||
int sessionscount = 0;
|
||||
|
||||
_sessionLockSlim.EnterReadLock();
|
||||
if (_sessions.ContainsKey(key))
|
||||
sessionscount = _sessions[key];
|
||||
_sessionLockSlim.ExitReadLock();
|
||||
|
||||
if (sessionscount > _options.MaxConcurrentSessions)
|
||||
{
|
||||
// Add to blocking and cleanup methods
|
||||
lock (_deeperInspection)
|
||||
{
|
||||
_blockLockSlim.EnterWriteLock();
|
||||
if (!_tempBlocked.ContainsKey(clientstring))
|
||||
{
|
||||
_tempBlocked.Add(clientstring,
|
||||
Util.EnvironmentTickCount() +
|
||||
(int) _options.ForgetTimeSpan.TotalMilliseconds);
|
||||
_forgetTimer.Enabled = true;
|
||||
m_log.WarnFormat("[{0}]: client: {1} is blocked for {2} milliseconds based on concurrency, X-ForwardedForAllowed status is {3}, endpoint:{4}", _options.ReportingName, clientstring, _options.ForgetTimeSpan.TotalMilliseconds, _options.AllowXForwardedFor, endpoint);
|
||||
|
||||
}
|
||||
else
|
||||
_tempBlocked[clientstring] = Util.EnvironmentTickCount() +
|
||||
(int) _options.ForgetTimeSpan.TotalMilliseconds;
|
||||
_blockLockSlim.ExitWriteLock();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
ProcessConcurrency(key, endpoint);
|
||||
}
|
||||
if (_generalRequestTimes.Size == _generalRequestTimes.Capacity &&
|
||||
(Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(), _generalRequestTimes.Get()) <
|
||||
_options.RequestTimeSpan.TotalMilliseconds))
|
||||
{
|
||||
//Trigger deeper inspection
|
||||
if (DeeperInspection(key, endpoint))
|
||||
return true;
|
||||
if (_options.ThrottledAction == ThrottleAction.DoThrottledMethod)
|
||||
return false;
|
||||
else
|
||||
throw new System.Security.SecurityException("Throttled");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private void ProcessConcurrency(string key, string endpoint)
|
||||
{
|
||||
_sessionLockSlim.EnterWriteLock();
|
||||
if (_sessions.ContainsKey(key))
|
||||
_sessions[key] = _sessions[key] + 1;
|
||||
else
|
||||
_sessions.Add(key,1);
|
||||
_sessionLockSlim.ExitWriteLock();
|
||||
}
|
||||
public void ProcessEnd(string key, string endpoint)
|
||||
{
|
||||
_sessionLockSlim.EnterWriteLock();
|
||||
if (_sessions.ContainsKey(key))
|
||||
{
|
||||
_sessions[key]--;
|
||||
if (_sessions[key] <= 0)
|
||||
_sessions.Remove(key);
|
||||
}
|
||||
else
|
||||
_sessions.Add(key, 1);
|
||||
|
||||
_sessionLockSlim.ExitWriteLock();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// At this point, the rate limiting code needs to track 'per user' velocity.
|
||||
/// </summary>
|
||||
/// <param name="key">Context Key, string representing a rate limiting context</param>
|
||||
/// <param name="endpoint"></param>
|
||||
/// <returns></returns>
|
||||
private bool DeeperInspection(string key, string endpoint)
|
||||
{
|
||||
lock (_deeperInspection)
|
||||
{
|
||||
string clientstring = key;
|
||||
|
||||
|
||||
if (_deeperInspection.ContainsKey(clientstring))
|
||||
{
|
||||
_deeperInspection[clientstring].Put(Util.EnvironmentTickCount());
|
||||
if (_deeperInspection[clientstring].Size == _deeperInspection[clientstring].Capacity &&
|
||||
(Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(), _deeperInspection[clientstring].Get()) <
|
||||
_options.RequestTimeSpan.TotalMilliseconds))
|
||||
{
|
||||
//Looks like we're over the limit
|
||||
_blockLockSlim.EnterWriteLock();
|
||||
if (!_tempBlocked.ContainsKey(clientstring))
|
||||
_tempBlocked.Add(clientstring, Util.EnvironmentTickCount() + (int)_options.ForgetTimeSpan.TotalMilliseconds);
|
||||
else
|
||||
_tempBlocked[clientstring] = Util.EnvironmentTickCount() + (int)_options.ForgetTimeSpan.TotalMilliseconds;
|
||||
_blockLockSlim.ExitWriteLock();
|
||||
|
||||
m_log.WarnFormat("[{0}]: client: {1} is blocked for {2} milliseconds, X-ForwardedForAllowed status is {3}, endpoint:{4}", _options.ReportingName, clientstring, _options.ForgetTimeSpan.TotalMilliseconds, _options.AllowXForwardedFor, endpoint);
|
||||
|
||||
return false;
|
||||
}
|
||||
//else
|
||||
// return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_deeperInspection.Add(clientstring, new CircularBuffer<int>(_options.MaxRequestsInTimeframe + 1, true));
|
||||
_deeperInspection[clientstring].Put(Util.EnvironmentTickCount());
|
||||
_forgetTimer.Enabled = true;
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class BasicDosProtectorOptions
|
||||
{
|
||||
public int MaxRequestsInTimeframe;
|
||||
public TimeSpan RequestTimeSpan;
|
||||
public TimeSpan ForgetTimeSpan;
|
||||
public bool AllowXForwardedFor;
|
||||
public string ReportingName = "BASICDOSPROTECTOR";
|
||||
public BasicDOSProtector.ThrottleAction ThrottledAction = BasicDOSProtector.ThrottleAction.DoThrottledMethod;
|
||||
public int MaxConcurrentSessions;
|
||||
}
|
||||
}
|
||||
@@ -287,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;
|
||||
@@ -356,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);
|
||||
|
||||
@@ -526,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());
|
||||
|
||||
312
OpenSim/Framework/CircularBuffer.cs
Normal file
312
OpenSim/Framework/CircularBuffer.cs
Normal file
@@ -0,0 +1,312 @@
|
||||
/*
|
||||
Copyright (c) 2012, Alex Regueiro
|
||||
All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
|
||||
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
|
||||
namespace OpenSim.Framework
|
||||
{
|
||||
public class CircularBuffer<T> : ICollection<T>, IEnumerable<T>, ICollection, IEnumerable
|
||||
{
|
||||
private int capacity;
|
||||
private int size;
|
||||
private int head;
|
||||
private int tail;
|
||||
private T[] buffer;
|
||||
|
||||
[NonSerialized()]
|
||||
private object syncRoot;
|
||||
|
||||
public CircularBuffer(int capacity)
|
||||
: this(capacity, false)
|
||||
{
|
||||
}
|
||||
|
||||
public CircularBuffer(int capacity, bool allowOverflow)
|
||||
{
|
||||
if (capacity < 0)
|
||||
throw new ArgumentException("Needs to have at least 1","capacity");
|
||||
|
||||
this.capacity = capacity;
|
||||
size = 0;
|
||||
head = 0;
|
||||
tail = 0;
|
||||
buffer = new T[capacity];
|
||||
AllowOverflow = allowOverflow;
|
||||
}
|
||||
|
||||
public bool AllowOverflow
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public int Capacity
|
||||
{
|
||||
get { return capacity; }
|
||||
set
|
||||
{
|
||||
if (value == capacity)
|
||||
return;
|
||||
|
||||
if (value < size)
|
||||
throw new ArgumentOutOfRangeException("value","Capacity is too small.");
|
||||
|
||||
var dst = new T[value];
|
||||
if (size > 0)
|
||||
CopyTo(dst);
|
||||
buffer = dst;
|
||||
|
||||
capacity = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int Size
|
||||
{
|
||||
get { return size; }
|
||||
}
|
||||
|
||||
public bool Contains(T item)
|
||||
{
|
||||
int bufferIndex = head;
|
||||
var comparer = EqualityComparer<T>.Default;
|
||||
for (int i = 0; i < size; i++, bufferIndex++)
|
||||
{
|
||||
if (bufferIndex == capacity)
|
||||
bufferIndex = 0;
|
||||
|
||||
if (item == null && buffer[bufferIndex] == null)
|
||||
return true;
|
||||
else if ((buffer[bufferIndex] != null) &&
|
||||
comparer.Equals(buffer[bufferIndex], item))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
size = 0;
|
||||
head = 0;
|
||||
tail = 0;
|
||||
}
|
||||
|
||||
public int Put(T[] src)
|
||||
{
|
||||
return Put(src, 0, src.Length);
|
||||
}
|
||||
|
||||
public int Put(T[] src, int offset, int count)
|
||||
{
|
||||
if (!AllowOverflow && count > capacity - size)
|
||||
throw new InvalidOperationException("Buffer Overflow");
|
||||
|
||||
int srcIndex = offset;
|
||||
for (int i = 0; i < count; i++, tail++, srcIndex++)
|
||||
{
|
||||
if (tail == capacity)
|
||||
tail = 0;
|
||||
buffer[tail] = src[srcIndex];
|
||||
}
|
||||
size = Math.Min(size + count, capacity);
|
||||
return count;
|
||||
}
|
||||
|
||||
public void Put(T item)
|
||||
{
|
||||
if (!AllowOverflow && size == capacity)
|
||||
throw new InvalidOperationException("Buffer Overflow");
|
||||
|
||||
buffer[tail] = item;
|
||||
if (++tail == capacity)
|
||||
tail = 0;
|
||||
size++;
|
||||
}
|
||||
|
||||
public void Skip(int count)
|
||||
{
|
||||
head += count;
|
||||
if (head >= capacity)
|
||||
head -= capacity;
|
||||
}
|
||||
|
||||
public T[] Get(int count)
|
||||
{
|
||||
var dst = new T[count];
|
||||
Get(dst);
|
||||
return dst;
|
||||
}
|
||||
|
||||
public int Get(T[] dst)
|
||||
{
|
||||
return Get(dst, 0, dst.Length);
|
||||
}
|
||||
|
||||
public int Get(T[] dst, int offset, int count)
|
||||
{
|
||||
int realCount = Math.Min(count, size);
|
||||
int dstIndex = offset;
|
||||
for (int i = 0; i < realCount; i++, head++, dstIndex++)
|
||||
{
|
||||
if (head == capacity)
|
||||
head = 0;
|
||||
dst[dstIndex] = buffer[head];
|
||||
}
|
||||
size -= realCount;
|
||||
return realCount;
|
||||
}
|
||||
|
||||
public T Get()
|
||||
{
|
||||
if (size == 0)
|
||||
throw new InvalidOperationException("Buffer Empty");
|
||||
|
||||
var item = buffer[head];
|
||||
if (++head == capacity)
|
||||
head = 0;
|
||||
size--;
|
||||
return item;
|
||||
}
|
||||
|
||||
public void CopyTo(T[] array)
|
||||
{
|
||||
CopyTo(array, 0);
|
||||
}
|
||||
|
||||
public void CopyTo(T[] array, int arrayIndex)
|
||||
{
|
||||
CopyTo(0, array, arrayIndex, size);
|
||||
}
|
||||
|
||||
public void CopyTo(int index, T[] array, int arrayIndex, int count)
|
||||
{
|
||||
if (count > size)
|
||||
throw new ArgumentOutOfRangeException("count", "Count Too Large");
|
||||
|
||||
int bufferIndex = head;
|
||||
for (int i = 0; i < count; i++, bufferIndex++, arrayIndex++)
|
||||
{
|
||||
if (bufferIndex == capacity)
|
||||
bufferIndex = 0;
|
||||
array[arrayIndex] = buffer[bufferIndex];
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
int bufferIndex = head;
|
||||
for (int i = 0; i < size; i++, bufferIndex++)
|
||||
{
|
||||
if (bufferIndex == capacity)
|
||||
bufferIndex = 0;
|
||||
|
||||
yield return buffer[bufferIndex];
|
||||
}
|
||||
}
|
||||
|
||||
public T[] GetBuffer()
|
||||
{
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public T[] ToArray()
|
||||
{
|
||||
var dst = new T[size];
|
||||
CopyTo(dst);
|
||||
return dst;
|
||||
}
|
||||
|
||||
#region ICollection<T> Members
|
||||
|
||||
int ICollection<T>.Count
|
||||
{
|
||||
get { return Size; }
|
||||
}
|
||||
|
||||
bool ICollection<T>.IsReadOnly
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
void ICollection<T>.Add(T item)
|
||||
{
|
||||
Put(item);
|
||||
}
|
||||
|
||||
bool ICollection<T>.Remove(T item)
|
||||
{
|
||||
if (size == 0)
|
||||
return false;
|
||||
|
||||
Get();
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IEnumerable<T> Members
|
||||
|
||||
IEnumerator<T> IEnumerable<T>.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ICollection Members
|
||||
|
||||
int ICollection.Count
|
||||
{
|
||||
get { return Size; }
|
||||
}
|
||||
|
||||
bool ICollection.IsSynchronized
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
object ICollection.SyncRoot
|
||||
{
|
||||
get
|
||||
{
|
||||
if (syncRoot == null)
|
||||
Interlocked.CompareExchange(ref syncRoot, new object(), null);
|
||||
return syncRoot;
|
||||
}
|
||||
}
|
||||
|
||||
void ICollection.CopyTo(Array array, int arrayIndex)
|
||||
{
|
||||
CopyTo((T[])array, arrayIndex);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IEnumerable Members
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return (IEnumerator)GetEnumerator();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
|
||||
[assembly : AssemblyVersion("0.7.6.*")]
|
||||
[assembly : AssemblyVersion("0.8.0.*")]
|
||||
|
||||
|
||||
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion("0.7.6.*")]
|
||||
[assembly: AssemblyVersion("0.8.0.*")]
|
||||
|
||||
|
||||
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion("0.7.6.*")]
|
||||
[assembly: AssemblyVersion("0.8.0.*")]
|
||||
|
||||
|
||||
@@ -55,4 +55,4 @@ using System.Runtime.InteropServices;
|
||||
// You can specify all values by your own or you can build default build and revision
|
||||
// numbers with the '*' character (the default):
|
||||
|
||||
[assembly : AssemblyVersion("0.7.6.*")]
|
||||
[assembly : AssemblyVersion("0.8.0.*")]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -86,24 +86,26 @@ namespace OpenSim.Framework
|
||||
event restart OnRestart;
|
||||
|
||||
/// <summary>
|
||||
/// Add a new client and create a presence for it. All clients except initial login clients will starts off as a child agent
|
||||
/// Add a new agent with an attached client. All agents except initial login clients will starts off as a child agent
|
||||
/// - the later agent crossing will promote it to a root agent.
|
||||
/// </summary>
|
||||
/// <param name="client"></param>
|
||||
/// <param name="type">The type of agent to add.</param>
|
||||
/// <returns>
|
||||
/// The scene agent if the new client was added or if an agent that already existed.</returns>
|
||||
ISceneAgent AddNewClient(IClientAPI client, PresenceType type);
|
||||
ISceneAgent AddNewAgent(IClientAPI client, PresenceType type);
|
||||
|
||||
/// <summary>
|
||||
/// Remove the given client from the scene.
|
||||
/// Tell a single agent to disconnect from the region.
|
||||
/// </summary>
|
||||
/// <param name="agentID"></param>
|
||||
/// <param name="closeChildAgents">Close the neighbour child agents associated with this client.</param>
|
||||
void RemoveClient(UUID agentID, bool closeChildAgents);
|
||||
/// <param name="force">
|
||||
/// Force the agent to close even if it might be in the middle of some other operation. You do not want to
|
||||
/// force unless you are absolutely sure that the agent is dead and a normal close is not working.
|
||||
/// </param>
|
||||
bool CloseAgent(UUID agentID, bool force);
|
||||
|
||||
void Restart();
|
||||
//RegionInfo OtherRegionUp(RegionInfo thisRegion);
|
||||
|
||||
string GetSimulatorVersion();
|
||||
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion("0.7.6.*")]
|
||||
[assembly: AssemblyVersion("0.8.0.*")]
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
@@ -236,12 +100,18 @@ public class CounterStat : Stat
|
||||
// If there are any histograms, add a new field that is an array of histograms as OSDMaps
|
||||
if (m_histograms.Count > 0)
|
||||
{
|
||||
OSDArray histos = new OSDArray();
|
||||
foreach (EventHistogram histo in m_histograms.Values)
|
||||
lock (counterLock)
|
||||
{
|
||||
histos.Add(histo.GetHistogramAsOSDMap());
|
||||
if (m_histograms.Count > 0)
|
||||
{
|
||||
OSDArray histos = new OSDArray();
|
||||
foreach (EventHistogram histo in m_histograms.Values)
|
||||
{
|
||||
histos.Add(histo.GetHistogramAsOSDMap());
|
||||
}
|
||||
map.Add("Histograms", histos);
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -225,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);
|
||||
|
||||
@@ -235,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));
|
||||
@@ -242,37 +250,75 @@ namespace OpenSim.Framework.Monitoring
|
||||
ret.Add("Description", OSD.FromString(Description));
|
||||
ret.Add("UnitName", OSD.FromString(UnitName));
|
||||
ret.Add("Value", OSD.FromReal(Value));
|
||||
ret.Add("StatType", "Stat"); // used by overloading classes to denote type of stat
|
||||
|
||||
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()));
|
||||
// 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,18 +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";
|
||||
@@ -81,6 +83,8 @@ namespace OpenSim.Framework.Monitoring
|
||||
+ "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)
|
||||
@@ -145,29 +149,55 @@ namespace OpenSim.Framework.Monitoring
|
||||
}
|
||||
}
|
||||
|
||||
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 (var category in RegisteredStats.Values)
|
||||
{
|
||||
OutputCategoryStatsToConsole(con, category);
|
||||
}
|
||||
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)
|
||||
{
|
||||
con.Output(stat.ToConsoleString());
|
||||
}
|
||||
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:
|
||||
@@ -234,6 +264,41 @@ namespace OpenSim.Framework.Monitoring
|
||||
return map;
|
||||
}
|
||||
|
||||
public static Hashtable HandleStatsRequest(Hashtable request)
|
||||
{
|
||||
Hashtable responsedata = new Hashtable();
|
||||
// string regpath = request["uri"].ToString();
|
||||
int response_code = 200;
|
||||
string contenttype = "text/json";
|
||||
|
||||
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 assets.
|
||||
// /// Should only be called once.
|
||||
@@ -257,7 +322,7 @@ namespace OpenSim.Framework.Monitoring
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Registers a statistic.
|
||||
/// Register a statistic.
|
||||
/// </summary>
|
||||
/// <param name='stat'></param>
|
||||
/// <returns></returns>
|
||||
@@ -271,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.
|
||||
@@ -307,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);
|
||||
@@ -323,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();
|
||||
|
||||
@@ -105,6 +105,7 @@ namespace OpenSim.Framework
|
||||
private ushort _profileHollow;
|
||||
private Vector3 _scale;
|
||||
private byte _state;
|
||||
private byte _lastattach;
|
||||
private ProfileShape _profileShape;
|
||||
private HollowShape _hollowShape;
|
||||
|
||||
@@ -207,6 +208,7 @@ namespace OpenSim.Framework
|
||||
PCode = (byte)prim.PrimData.PCode;
|
||||
|
||||
State = prim.PrimData.State;
|
||||
LastAttachPoint = prim.PrimData.State;
|
||||
PathBegin = Primitive.PackBeginCut(prim.PrimData.PathBegin);
|
||||
PathEnd = Primitive.PackEndCut(prim.PrimData.PathEnd);
|
||||
PathScaleX = Primitive.PackPathScale(prim.PrimData.PathScaleX);
|
||||
@@ -583,6 +585,15 @@ namespace OpenSim.Framework
|
||||
}
|
||||
}
|
||||
|
||||
public byte LastAttachPoint {
|
||||
get {
|
||||
return _lastattach;
|
||||
}
|
||||
set {
|
||||
_lastattach = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ProfileShape ProfileShape {
|
||||
get {
|
||||
return _profileShape;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user