diff options
author | Justin Clarke Casey | 2008-01-11 17:00:21 +0000 |
---|---|---|
committer | Justin Clarke Casey | 2008-01-11 17:00:21 +0000 |
commit | 48be04df1d804137a736d83de157265555a63d31 (patch) | |
tree | f4fbf722ab2dba911da0f7f37138be9c41019067 | |
parent | manually open the db connection. Mono does this automatically, .NET doesn't (diff) | |
download | opensim-SC_OLD-48be04df1d804137a736d83de157265555a63d31.zip opensim-SC_OLD-48be04df1d804137a736d83de157265555a63d31.tar.gz opensim-SC_OLD-48be04df1d804137a736d83de157265555a63d31.tar.bz2 opensim-SC_OLD-48be04df1d804137a736d83de157265555a63d31.tar.xz |
* Do database implementation for prim inventory items in mysql
* Properly clean up items when a region object is deleted
* Update persisted prim when an inventory script is changed
* No user functionality yet
-rw-r--r-- | OpenSim/Framework/Data.MySQL/MySQLDataStore.cs | 325 | ||||
-rw-r--r-- | OpenSim/Framework/Data.SQLite/SQLiteRegionData.cs | 51 | ||||
-rw-r--r-- | OpenSim/Region/Environment/Scenes/SceneObjectGroup.Inventory.cs | 7 |
3 files changed, 351 insertions, 32 deletions
diff --git a/OpenSim/Framework/Data.MySQL/MySQLDataStore.cs b/OpenSim/Framework/Data.MySQL/MySQLDataStore.cs index 3c25533..6d33a36 100644 --- a/OpenSim/Framework/Data.MySQL/MySQLDataStore.cs +++ b/OpenSim/Framework/Data.MySQL/MySQLDataStore.cs | |||
@@ -44,6 +44,7 @@ namespace OpenSim.Framework.Data.MySQL | |||
44 | { | 44 | { |
45 | private const string m_primSelect = "select * from prims"; | 45 | private const string m_primSelect = "select * from prims"; |
46 | private const string m_shapeSelect = "select * from primshapes"; | 46 | private const string m_shapeSelect = "select * from primshapes"; |
47 | private const string m_itemsSelect = "select * from primitems"; | ||
47 | private const string m_terrainSelect = "select * from terrain limit 1"; | 48 | private const string m_terrainSelect = "select * from terrain limit 1"; |
48 | private const string m_landSelect = "select * from land"; | 49 | private const string m_landSelect = "select * from land"; |
49 | private const string m_landAccessListSelect = "select * from landaccesslist"; | 50 | private const string m_landAccessListSelect = "select * from landaccesslist"; |
@@ -51,15 +52,21 @@ namespace OpenSim.Framework.Data.MySQL | |||
51 | private DataSet m_dataSet; | 52 | private DataSet m_dataSet; |
52 | private MySqlDataAdapter m_primDataAdapter; | 53 | private MySqlDataAdapter m_primDataAdapter; |
53 | private MySqlDataAdapter m_shapeDataAdapter; | 54 | private MySqlDataAdapter m_shapeDataAdapter; |
55 | private MySqlDataAdapter m_itemsDataAdapter; | ||
54 | private MySqlConnection m_connection; | 56 | private MySqlConnection m_connection; |
55 | private MySqlDataAdapter m_terrainDataAdapter; | 57 | private MySqlDataAdapter m_terrainDataAdapter; |
56 | private MySqlDataAdapter m_landDataAdapter; | 58 | private MySqlDataAdapter m_landDataAdapter; |
57 | private MySqlDataAdapter m_landAccessListDataAdapter; | 59 | private MySqlDataAdapter m_landAccessListDataAdapter; |
60 | |||
58 | private DataTable m_primTable; | 61 | private DataTable m_primTable; |
59 | private DataTable m_shapeTable; | 62 | private DataTable m_shapeTable; |
63 | private DataTable m_itemsTable; | ||
60 | private DataTable m_terrainTable; | 64 | private DataTable m_terrainTable; |
61 | private DataTable m_landTable; | 65 | private DataTable m_landTable; |
62 | private DataTable m_landAccessListTable; | 66 | private DataTable m_landAccessListTable; |
67 | |||
68 | // Temporary attribute while this is experimental | ||
69 | private bool persistPrimInventories; | ||
63 | 70 | ||
64 | /*********************************************************************** | 71 | /*********************************************************************** |
65 | * | 72 | * |
@@ -71,6 +78,7 @@ namespace OpenSim.Framework.Data.MySQL | |||
71 | public void Initialise(string connectionstring, bool persistPrimInventories) | 78 | public void Initialise(string connectionstring, bool persistPrimInventories) |
72 | { | 79 | { |
73 | m_dataSet = new DataSet(); | 80 | m_dataSet = new DataSet(); |
81 | this.persistPrimInventories = persistPrimInventories; | ||
74 | 82 | ||
75 | MainLog.Instance.Verbose("DATASTORE", "MySql - connecting: " + connectionstring); | 83 | MainLog.Instance.Verbose("DATASTORE", "MySql - connecting: " + connectionstring); |
76 | m_connection = new MySqlConnection(connectionstring); | 84 | m_connection = new MySqlConnection(connectionstring); |
@@ -80,6 +88,9 @@ namespace OpenSim.Framework.Data.MySQL | |||
80 | 88 | ||
81 | MySqlCommand shapeSelectCmd = new MySqlCommand(m_shapeSelect, m_connection); | 89 | MySqlCommand shapeSelectCmd = new MySqlCommand(m_shapeSelect, m_connection); |
82 | m_shapeDataAdapter = new MySqlDataAdapter(shapeSelectCmd); | 90 | m_shapeDataAdapter = new MySqlDataAdapter(shapeSelectCmd); |
91 | |||
92 | MySqlCommand itemsSelectCmd = new MySqlCommand(m_itemsSelect, m_connection); | ||
93 | m_itemsDataAdapter = new MySqlDataAdapter(itemsSelectCmd); | ||
83 | 94 | ||
84 | MySqlCommand terrainSelectCmd = new MySqlCommand(m_terrainSelect, m_connection); | 95 | MySqlCommand terrainSelectCmd = new MySqlCommand(m_terrainSelect, m_connection); |
85 | m_terrainDataAdapter = new MySqlDataAdapter(terrainSelectCmd); | 96 | m_terrainDataAdapter = new MySqlDataAdapter(terrainSelectCmd); |
@@ -103,6 +114,14 @@ namespace OpenSim.Framework.Data.MySQL | |||
103 | m_dataSet.Tables.Add(m_shapeTable); | 114 | m_dataSet.Tables.Add(m_shapeTable); |
104 | SetupShapeCommands(m_shapeDataAdapter, m_connection); | 115 | SetupShapeCommands(m_shapeDataAdapter, m_connection); |
105 | m_shapeDataAdapter.Fill(m_shapeTable); | 116 | m_shapeDataAdapter.Fill(m_shapeTable); |
117 | |||
118 | if (persistPrimInventories) | ||
119 | { | ||
120 | m_itemsTable = createItemsTable(); | ||
121 | m_dataSet.Tables.Add(m_itemsTable); | ||
122 | SetupItemsCommands(m_itemsDataAdapter, m_connection); | ||
123 | m_itemsDataAdapter.Fill(m_itemsTable); | ||
124 | } | ||
106 | 125 | ||
107 | m_terrainTable = createTerrainTable(); | 126 | m_terrainTable = createTerrainTable(); |
108 | m_dataSet.Tables.Add(m_terrainTable); | 127 | m_dataSet.Tables.Add(m_terrainTable); |
@@ -146,6 +165,7 @@ namespace OpenSim.Framework.Data.MySQL | |||
146 | { | 165 | { |
147 | DataTable prims = m_primTable; | 166 | DataTable prims = m_primTable; |
148 | DataTable shapes = m_shapeTable; | 167 | DataTable shapes = m_shapeTable; |
168 | DataTable items = m_itemsTable; | ||
149 | 169 | ||
150 | string selectExp = "SceneGroupID = '" + Util.ToRawUuidString(obj) + "'"; | 170 | string selectExp = "SceneGroupID = '" + Util.ToRawUuidString(obj) + "'"; |
151 | lock (m_dataSet) | 171 | lock (m_dataSet) |
@@ -153,12 +173,27 @@ namespace OpenSim.Framework.Data.MySQL | |||
153 | DataRow[] primRows = prims.Select(selectExp); | 173 | DataRow[] primRows = prims.Select(selectExp); |
154 | foreach (DataRow row in primRows) | 174 | foreach (DataRow row in primRows) |
155 | { | 175 | { |
176 | // Remove shapes row | ||
156 | LLUUID uuid = new LLUUID((string) row["UUID"]); | 177 | LLUUID uuid = new LLUUID((string) row["UUID"]); |
157 | DataRow shapeRow = shapes.Rows.Find(Util.ToRawUuidString(uuid)); | 178 | DataRow shapeRow = shapes.Rows.Find(Util.ToRawUuidString(uuid)); |
158 | if (shapeRow != null) | 179 | if (shapeRow != null) |
159 | { | 180 | { |
160 | shapeRow.Delete(); | 181 | shapeRow.Delete(); |
161 | } | 182 | } |
183 | |||
184 | if (persistPrimInventories) | ||
185 | { | ||
186 | // Remove items rows | ||
187 | String sql = String.Format("primID = '{0}'", uuid); | ||
188 | DataRow[] itemRows = items.Select(sql); | ||
189 | |||
190 | foreach (DataRow itemsRow in itemRows) | ||
191 | { | ||
192 | shapeRow.Delete(); | ||
193 | } | ||
194 | } | ||
195 | |||
196 | // Remove prim row | ||
162 | row.Delete(); | 197 | row.Delete(); |
163 | } | 198 | } |
164 | } | 199 | } |
@@ -166,6 +201,9 @@ namespace OpenSim.Framework.Data.MySQL | |||
166 | Commit(); | 201 | Commit(); |
167 | } | 202 | } |
168 | 203 | ||
204 | /// <summary> | ||
205 | /// Load persisted objects from region storage. | ||
206 | /// </summary> | ||
169 | public List<SceneObjectGroup> LoadObjects(LLUUID regionUUID) | 207 | public List<SceneObjectGroup> LoadObjects(LLUUID regionUUID) |
170 | { | 208 | { |
171 | Dictionary<LLUUID, SceneObjectGroup> createdObjects = new Dictionary<LLUUID, SceneObjectGroup>(); | 209 | Dictionary<LLUUID, SceneObjectGroup> createdObjects = new Dictionary<LLUUID, SceneObjectGroup>(); |
@@ -186,14 +224,17 @@ namespace OpenSim.Framework.Data.MySQL | |||
186 | 224 | ||
187 | foreach (DataRow primRow in primsForRegion) | 225 | foreach (DataRow primRow in primsForRegion) |
188 | { | 226 | { |
189 | try | 227 | try |
190 | { | 228 | { |
191 | string uuid = (string) primRow["UUID"]; | 229 | string uuid = (string) primRow["UUID"]; |
192 | string objID = (string) primRow["SceneGroupID"]; | 230 | string objID = (string) primRow["SceneGroupID"]; |
231 | |||
232 | SceneObjectPart prim = buildPrim(primRow); | ||
233 | |||
193 | if (uuid == objID) //is new SceneObjectGroup ? | 234 | if (uuid == objID) //is new SceneObjectGroup ? |
194 | { | 235 | { |
195 | SceneObjectGroup group = new SceneObjectGroup(); | 236 | SceneObjectGroup group = new SceneObjectGroup(); |
196 | SceneObjectPart prim = buildPrim(primRow); | 237 | |
197 | DataRow shapeRow = shapes.Rows.Find(Util.ToRawUuidString(prim.UUID)); | 238 | DataRow shapeRow = shapes.Rows.Find(Util.ToRawUuidString(prim.UUID)); |
198 | if (shapeRow != null) | 239 | if (shapeRow != null) |
199 | { | 240 | { |
@@ -213,7 +254,6 @@ namespace OpenSim.Framework.Data.MySQL | |||
213 | } | 254 | } |
214 | else | 255 | else |
215 | { | 256 | { |
216 | SceneObjectPart prim = buildPrim(primRow); | ||
217 | DataRow shapeRow = shapes.Rows.Find(Util.ToRawUuidString(prim.UUID)); | 257 | DataRow shapeRow = shapes.Rows.Find(Util.ToRawUuidString(prim.UUID)); |
218 | if (shapeRow != null) | 258 | if (shapeRow != null) |
219 | { | 259 | { |
@@ -227,6 +267,11 @@ namespace OpenSim.Framework.Data.MySQL | |||
227 | } | 267 | } |
228 | createdObjects[new LLUUID(objID)].AddPart(prim); | 268 | createdObjects[new LLUUID(objID)].AddPart(prim); |
229 | } | 269 | } |
270 | |||
271 | if (persistPrimInventories) | ||
272 | { | ||
273 | LoadItems(prim); | ||
274 | } | ||
230 | } | 275 | } |
231 | catch (Exception e) | 276 | catch (Exception e) |
232 | { | 277 | { |
@@ -241,7 +286,39 @@ namespace OpenSim.Framework.Data.MySQL | |||
241 | } | 286 | } |
242 | return retvals; | 287 | return retvals; |
243 | } | 288 | } |
244 | 289 | ||
290 | /// <summary> | ||
291 | /// Load in a prim's persisted inventory. | ||
292 | /// </summary> | ||
293 | /// <param name="prim"></param> | ||
294 | private void LoadItems(SceneObjectPart prim) | ||
295 | { | ||
296 | MainLog.Instance.Verbose("DATASTORE", "Loading inventory for {0}, {1}", prim.Name, prim.UUID); | ||
297 | |||
298 | DataTable dbItems = m_itemsTable; | ||
299 | |||
300 | String sql = String.Format("primID = '{0}'", prim.UUID.ToString()); | ||
301 | DataRow[] dbItemRows = dbItems.Select(sql); | ||
302 | |||
303 | IList<TaskInventoryItem> inventory = new List<TaskInventoryItem>(); | ||
304 | |||
305 | foreach (DataRow row in dbItemRows) | ||
306 | { | ||
307 | TaskInventoryItem item = buildItem(row); | ||
308 | inventory.Add(item); | ||
309 | |||
310 | MainLog.Instance.Verbose("DATASTORE", "Restored item {0}, {1}", item.name, item.item_id); | ||
311 | } | ||
312 | |||
313 | prim.AddInventoryItems(inventory); | ||
314 | |||
315 | // XXX A nasty little hack to recover the folder id for the prim (which is currently stored in | ||
316 | // every item). This data should really be stored in the prim table itself. | ||
317 | if (dbItemRows.Length > 0) | ||
318 | { | ||
319 | prim.FolderID = inventory[0].parent_id; | ||
320 | } | ||
321 | } | ||
245 | 322 | ||
246 | public void StoreTerrain(double[,] ter, LLUUID regionID) | 323 | public void StoreTerrain(double[,] ter, LLUUID regionID) |
247 | { | 324 | { |
@@ -437,6 +514,12 @@ namespace OpenSim.Framework.Data.MySQL | |||
437 | 514 | ||
438 | m_primDataAdapter.Update(m_primTable); | 515 | m_primDataAdapter.Update(m_primTable); |
439 | m_shapeDataAdapter.Update(m_shapeTable); | 516 | m_shapeDataAdapter.Update(m_shapeTable); |
517 | |||
518 | if (persistPrimInventories) | ||
519 | { | ||
520 | m_itemsDataAdapter.Update(m_itemsTable); | ||
521 | } | ||
522 | |||
440 | m_terrainDataAdapter.Update(m_terrainTable); | 523 | m_terrainDataAdapter.Update(m_terrainTable); |
441 | m_landDataAdapter.Update(m_landTable); | 524 | m_landDataAdapter.Update(m_landTable); |
442 | m_landAccessListDataAdapter.Update(m_landAccessListTable); | 525 | m_landAccessListDataAdapter.Update(m_landAccessListTable); |
@@ -630,6 +713,38 @@ namespace OpenSim.Framework.Data.MySQL | |||
630 | 713 | ||
631 | return shapes; | 714 | return shapes; |
632 | } | 715 | } |
716 | |||
717 | private DataTable createItemsTable() | ||
718 | { | ||
719 | DataTable items = new DataTable("primitems"); | ||
720 | |||
721 | createCol(items, "itemID", typeof (String)); | ||
722 | createCol(items, "primID", typeof (String)); | ||
723 | createCol(items, "assetID", typeof (String)); | ||
724 | createCol(items, "parentFolderID", typeof (String)); | ||
725 | |||
726 | createCol(items, "invType", typeof (Int32)); | ||
727 | createCol(items, "assetType", typeof (Int32)); | ||
728 | |||
729 | createCol(items, "name", typeof (String)); | ||
730 | createCol(items, "description", typeof (String)); | ||
731 | |||
732 | createCol(items, "creationDate", typeof (Int64)); | ||
733 | createCol(items, "creatorID", typeof (String)); | ||
734 | createCol(items, "ownerID", typeof (String)); | ||
735 | createCol(items, "lastOwnerID", typeof (String)); | ||
736 | createCol(items, "groupID", typeof (String)); | ||
737 | |||
738 | createCol(items, "nextPermissions", typeof (Int32)); | ||
739 | createCol(items, "currentPermissions", typeof (Int32)); | ||
740 | createCol(items, "basePermissions", typeof (Int32)); | ||
741 | createCol(items, "everyonePermissions", typeof (Int32)); | ||
742 | createCol(items, "groupPermissions", typeof (Int32)); | ||
743 | |||
744 | items.PrimaryKey = new DataColumn[] {items.Columns["itemID"]}; | ||
745 | |||
746 | return items; | ||
747 | } | ||
633 | 748 | ||
634 | /*********************************************************************** | 749 | /*********************************************************************** |
635 | * | 750 | * |
@@ -727,6 +842,41 @@ namespace OpenSim.Framework.Data.MySQL | |||
727 | } | 842 | } |
728 | return prim; | 843 | return prim; |
729 | } | 844 | } |
845 | |||
846 | |||
847 | /// <summary> | ||
848 | /// Build a prim inventory item from the persisted data. | ||
849 | /// </summary> | ||
850 | /// <param name="row"></param> | ||
851 | /// <returns></returns> | ||
852 | private TaskInventoryItem buildItem(DataRow row) | ||
853 | { | ||
854 | TaskInventoryItem taskItem = new TaskInventoryItem(); | ||
855 | |||
856 | taskItem.item_id = new LLUUID((String)row["itemID"]); | ||
857 | taskItem.ParentPartID = new LLUUID((String)row["primID"]); | ||
858 | taskItem.asset_id = new LLUUID((String)row["assetID"]); | ||
859 | taskItem.parent_id = new LLUUID((String)row["parentFolderID"]); | ||
860 | |||
861 | taskItem.inv_type = Convert.ToInt32(row["invType"]); | ||
862 | taskItem.type = Convert.ToInt32(row["assetType"]); | ||
863 | |||
864 | taskItem.name = (String)row["name"]; | ||
865 | taskItem.desc = (String)row["description"]; | ||
866 | taskItem.creation_date = Convert.ToUInt32(row["creationDate"]); | ||
867 | taskItem.creator_id = new LLUUID((String)row["creatorID"]); | ||
868 | taskItem.owner_id = new LLUUID((String)row["ownerID"]); | ||
869 | taskItem.last_owner_id = new LLUUID((String)row["lastOwnerID"]); | ||
870 | taskItem.group_id = new LLUUID((String)row["groupID"]); | ||
871 | |||
872 | taskItem.next_owner_mask = Convert.ToUInt32(row["nextPermissions"]); | ||
873 | taskItem.owner_mask = Convert.ToUInt32(row["currentPermissions"]); | ||
874 | taskItem.base_mask = Convert.ToUInt32(row["basePermissions"]); | ||
875 | taskItem.everyone_mask = Convert.ToUInt32(row["everyonePermissions"]); | ||
876 | taskItem.group_mask = Convert.ToUInt32(row["groupPermissions"]); | ||
877 | |||
878 | return taskItem; | ||
879 | } | ||
730 | 880 | ||
731 | private LandData buildLandData(DataRow row) | 881 | private LandData buildLandData(DataRow row) |
732 | { | 882 | { |
@@ -870,6 +1020,30 @@ namespace OpenSim.Framework.Data.MySQL | |||
870 | } | 1020 | } |
871 | } | 1021 | } |
872 | } | 1022 | } |
1023 | |||
1024 | private void fillItemRow(DataRow row, TaskInventoryItem taskItem) | ||
1025 | { | ||
1026 | row["itemID"] = taskItem.item_id; | ||
1027 | row["primID"] = taskItem.ParentPartID; | ||
1028 | row["assetID"] = taskItem.asset_id; | ||
1029 | row["parentFolderID"] = taskItem.parent_id; | ||
1030 | |||
1031 | row["invType"] = taskItem.inv_type; | ||
1032 | row["assetType"] = taskItem.type; | ||
1033 | |||
1034 | row["name"] = taskItem.name; | ||
1035 | row["description"] = taskItem.desc; | ||
1036 | row["creationDate"] = taskItem.creation_date; | ||
1037 | row["creatorID"] = taskItem.creator_id; | ||
1038 | row["ownerID"] = taskItem.owner_id; | ||
1039 | row["lastOwnerID"] = taskItem.last_owner_id; | ||
1040 | row["groupID"] = taskItem.group_id; | ||
1041 | row["nextPermissions"] = taskItem.next_owner_mask; | ||
1042 | row["currentPermissions"] = taskItem.owner_mask; | ||
1043 | row["basePermissions"] = taskItem.base_mask; | ||
1044 | row["everyonePermissions"] = taskItem.everyone_mask; | ||
1045 | row["groupPermissions"] = taskItem.group_mask; | ||
1046 | } | ||
873 | 1047 | ||
874 | private void fillLandRow(DataRow row, LandData land, LLUUID regionUUID) | 1048 | private void fillLandRow(DataRow row, LandData land, LLUUID regionUUID) |
875 | { | 1049 | { |
@@ -1017,7 +1191,79 @@ namespace OpenSim.Framework.Data.MySQL | |||
1017 | { | 1191 | { |
1018 | fillShapeRow(shapeRow, prim); | 1192 | fillShapeRow(shapeRow, prim); |
1019 | } | 1193 | } |
1194 | |||
1195 | if (persistPrimInventories) | ||
1196 | { | ||
1197 | addPrimInventory(prim.UUID, prim.TaskInventory); | ||
1198 | } | ||
1020 | } | 1199 | } |
1200 | |||
1201 | /// <summary> | ||
1202 | /// Persist prim inventory. Deletes, updates and inserts rows. | ||
1203 | /// </summary> | ||
1204 | /// <param name="primID"></param> | ||
1205 | /// <param name="items"></param> | ||
1206 | /// <returns></returns> | ||
1207 | private void addPrimInventory(LLUUID primID, IDictionary<LLUUID, TaskInventoryItem> items) | ||
1208 | { | ||
1209 | MainLog.Instance.Verbose("DATASTORE", "Entered addPrimInventory with prim ID {0}", primID); | ||
1210 | |||
1211 | // Find all existing inventory rows for this prim | ||
1212 | DataTable dbItems = m_itemsTable; | ||
1213 | |||
1214 | String sql = String.Format("primID = '{0}'", primID); | ||
1215 | DataRow[] dbItemRows = dbItems.Select(sql); | ||
1216 | |||
1217 | // Build structures for manipulation purposes | ||
1218 | IDictionary<String, DataRow> dbItemsToRemove = new Dictionary<String, DataRow>(); | ||
1219 | ICollection<TaskInventoryItem> itemsToAdd | ||
1220 | = new List<TaskInventoryItem>(); | ||
1221 | |||
1222 | foreach (DataRow row in dbItemRows) | ||
1223 | { | ||
1224 | dbItemsToRemove.Add((String)row["itemID"], row); | ||
1225 | } | ||
1226 | |||
1227 | // Eliminate rows from the deletion set which already exist for this prim's inventory | ||
1228 | // TODO Very temporary, need to take account of simple metadata changes soon | ||
1229 | foreach (LLUUID itemId in items.Keys) | ||
1230 | { | ||
1231 | String rawItemId = itemId.ToString(); | ||
1232 | |||
1233 | if (dbItemsToRemove.ContainsKey(rawItemId)) | ||
1234 | { | ||
1235 | dbItemsToRemove.Remove(rawItemId); | ||
1236 | } | ||
1237 | else | ||
1238 | { | ||
1239 | itemsToAdd.Add(items[itemId]); | ||
1240 | } | ||
1241 | } | ||
1242 | |||
1243 | // Delete excess rows | ||
1244 | foreach (DataRow row in dbItemsToRemove.Values) | ||
1245 | { | ||
1246 | MainLog.Instance.Verbose( | ||
1247 | "DATASTORE", | ||
1248 | "Removing item {0}, {1} from prim ID {2}", | ||
1249 | row["name"], row["itemID"], row["primID"]); | ||
1250 | |||
1251 | row.Delete(); | ||
1252 | } | ||
1253 | |||
1254 | // Insert items not already present | ||
1255 | foreach (TaskInventoryItem newItem in itemsToAdd) | ||
1256 | { | ||
1257 | MainLog.Instance.Verbose( | ||
1258 | "DATASTORE", | ||
1259 | "Adding item {0}, {1} to prim ID {1}", | ||
1260 | newItem.name, newItem.item_id, newItem.ParentPartID); | ||
1261 | |||
1262 | DataRow newItemRow = dbItems.NewRow(); | ||
1263 | fillItemRow(newItemRow, newItem); | ||
1264 | dbItems.Rows.Add(newItemRow); | ||
1265 | } | ||
1266 | } | ||
1021 | 1267 | ||
1022 | /*********************************************************************** | 1268 | /*********************************************************************** |
1023 | * | 1269 | * |
@@ -1111,6 +1357,9 @@ namespace OpenSim.Framework.Data.MySQL | |||
1111 | } | 1357 | } |
1112 | sql += subsql; | 1358 | sql += subsql; |
1113 | sql += ")"; | 1359 | sql += ")"; |
1360 | |||
1361 | //MainLog.Instance.Verbose("DATASTORE", "defineTable() sql {0}", sql); | ||
1362 | |||
1114 | return sql; | 1363 | return sql; |
1115 | } | 1364 | } |
1116 | 1365 | ||
@@ -1166,6 +1415,20 @@ namespace OpenSim.Framework.Data.MySQL | |||
1166 | delete.Connection = conn; | 1415 | delete.Connection = conn; |
1167 | da.DeleteCommand = delete; | 1416 | da.DeleteCommand = delete; |
1168 | } | 1417 | } |
1418 | |||
1419 | private void SetupItemsCommands(MySqlDataAdapter da, MySqlConnection conn) | ||
1420 | { | ||
1421 | da.InsertCommand = createInsertCommand("primitems", m_itemsTable); | ||
1422 | da.InsertCommand.Connection = conn; | ||
1423 | |||
1424 | da.UpdateCommand = createUpdateCommand("primitems", "itemID = :itemID", m_itemsTable); | ||
1425 | da.UpdateCommand.Connection = conn; | ||
1426 | |||
1427 | MySqlCommand delete = new MySqlCommand("delete from primitems where itemID = :itemID"); | ||
1428 | delete.Parameters.Add(createMySqlParameter("itemID", typeof (String))); | ||
1429 | delete.Connection = conn; | ||
1430 | da.DeleteCommand = delete; | ||
1431 | } | ||
1169 | 1432 | ||
1170 | private void SetupTerrainCommands(MySqlDataAdapter da, MySqlConnection conn) | 1433 | private void SetupTerrainCommands(MySqlDataAdapter da, MySqlConnection conn) |
1171 | { | 1434 | { |
@@ -1206,12 +1469,14 @@ namespace OpenSim.Framework.Data.MySQL | |||
1206 | { | 1469 | { |
1207 | string createPrims = defineTable(createPrimTable()); | 1470 | string createPrims = defineTable(createPrimTable()); |
1208 | string createShapes = defineTable(createShapeTable()); | 1471 | string createShapes = defineTable(createShapeTable()); |
1472 | string createItems = defineTable(createItemsTable()); | ||
1209 | string createTerrain = defineTable(createTerrainTable()); | 1473 | string createTerrain = defineTable(createTerrainTable()); |
1210 | string createLand = defineTable(createLandTable()); | 1474 | string createLand = defineTable(createLandTable()); |
1211 | string createLandAccessList = defineTable(createLandAccessListTable()); | 1475 | string createLandAccessList = defineTable(createLandAccessListTable()); |
1212 | 1476 | ||
1213 | MySqlCommand pcmd = new MySqlCommand(createPrims, conn); | 1477 | MySqlCommand pcmd = new MySqlCommand(createPrims, conn); |
1214 | MySqlCommand scmd = new MySqlCommand(createShapes, conn); | 1478 | MySqlCommand scmd = new MySqlCommand(createShapes, conn); |
1479 | MySqlCommand icmd = new MySqlCommand(createItems, conn); | ||
1215 | MySqlCommand tcmd = new MySqlCommand(createTerrain, conn); | 1480 | MySqlCommand tcmd = new MySqlCommand(createTerrain, conn); |
1216 | MySqlCommand lcmd = new MySqlCommand(createLand, conn); | 1481 | MySqlCommand lcmd = new MySqlCommand(createLand, conn); |
1217 | MySqlCommand lalcmd = new MySqlCommand(createLandAccessList, conn); | 1482 | MySqlCommand lalcmd = new MySqlCommand(createLandAccessList, conn); |
@@ -1225,45 +1490,54 @@ namespace OpenSim.Framework.Data.MySQL | |||
1225 | { | 1490 | { |
1226 | pcmd.ExecuteNonQuery(); | 1491 | pcmd.ExecuteNonQuery(); |
1227 | } | 1492 | } |
1228 | catch (MySqlException) | 1493 | catch (MySqlException e) |
1229 | { | 1494 | { |
1230 | MainLog.Instance.Warn("MySql", "Primitives Table Already Exists"); | 1495 | MainLog.Instance.Warn("MySql", "Primitives Table Already Exists: {0}", e); |
1231 | } | 1496 | } |
1232 | 1497 | ||
1233 | try | 1498 | try |
1234 | { | 1499 | { |
1235 | scmd.ExecuteNonQuery(); | 1500 | scmd.ExecuteNonQuery(); |
1236 | } | 1501 | } |
1237 | catch (MySqlException) | 1502 | catch (MySqlException e) |
1238 | { | 1503 | { |
1239 | MainLog.Instance.Warn("MySql", "Shapes Table Already Exists"); | 1504 | MainLog.Instance.Warn("MySql", "Shapes Table Already Exists: {0}", e); |
1240 | } | 1505 | } |
1506 | |||
1507 | try | ||
1508 | { | ||
1509 | icmd.ExecuteNonQuery(); | ||
1510 | } | ||
1511 | catch (MySqlException e) | ||
1512 | { | ||
1513 | MainLog.Instance.Warn("MySql", "Items Table Already Exists: {0}", e); | ||
1514 | } | ||
1241 | 1515 | ||
1242 | try | 1516 | try |
1243 | { | 1517 | { |
1244 | tcmd.ExecuteNonQuery(); | 1518 | tcmd.ExecuteNonQuery(); |
1245 | } | 1519 | } |
1246 | catch (MySqlException) | 1520 | catch (MySqlException e) |
1247 | { | 1521 | { |
1248 | MainLog.Instance.Warn("MySql", "Terrain Table Already Exists"); | 1522 | MainLog.Instance.Warn("MySql", "Terrain Table Already Exists: {0}", e); |
1249 | } | 1523 | } |
1250 | 1524 | ||
1251 | try | 1525 | try |
1252 | { | 1526 | { |
1253 | lcmd.ExecuteNonQuery(); | 1527 | lcmd.ExecuteNonQuery(); |
1254 | } | 1528 | } |
1255 | catch (MySqlException) | 1529 | catch (MySqlException e) |
1256 | { | 1530 | { |
1257 | MainLog.Instance.Warn("MySql", "Land Table Already Exists"); | 1531 | MainLog.Instance.Warn("MySql", "Land Table Already Exists: {0}", e); |
1258 | } | 1532 | } |
1259 | 1533 | ||
1260 | try | 1534 | try |
1261 | { | 1535 | { |
1262 | lalcmd.ExecuteNonQuery(); | 1536 | lalcmd.ExecuteNonQuery(); |
1263 | } | 1537 | } |
1264 | catch (MySqlException) | 1538 | catch (MySqlException e) |
1265 | { | 1539 | { |
1266 | MainLog.Instance.Warn("MySql", "LandAccessList Table Already Exists"); | 1540 | MainLog.Instance.Warn("MySql", "LandAccessList Table Already Exists: {0}", e); |
1267 | } | 1541 | } |
1268 | conn.Close(); | 1542 | conn.Close(); |
1269 | } | 1543 | } |
@@ -1274,6 +1548,8 @@ namespace OpenSim.Framework.Data.MySQL | |||
1274 | MySqlDataAdapter pDa = new MySqlDataAdapter(primSelectCmd); | 1548 | MySqlDataAdapter pDa = new MySqlDataAdapter(primSelectCmd); |
1275 | MySqlCommand shapeSelectCmd = new MySqlCommand(m_shapeSelect, conn); | 1549 | MySqlCommand shapeSelectCmd = new MySqlCommand(m_shapeSelect, conn); |
1276 | MySqlDataAdapter sDa = new MySqlDataAdapter(shapeSelectCmd); | 1550 | MySqlDataAdapter sDa = new MySqlDataAdapter(shapeSelectCmd); |
1551 | MySqlCommand itemsSelectCmd = new MySqlCommand(m_itemsSelect, conn); | ||
1552 | MySqlDataAdapter iDa = new MySqlDataAdapter(itemsSelectCmd); | ||
1277 | MySqlCommand terrainSelectCmd = new MySqlCommand(m_terrainSelect, conn); | 1553 | MySqlCommand terrainSelectCmd = new MySqlCommand(m_terrainSelect, conn); |
1278 | MySqlDataAdapter tDa = new MySqlDataAdapter(terrainSelectCmd); | 1554 | MySqlDataAdapter tDa = new MySqlDataAdapter(terrainSelectCmd); |
1279 | MySqlCommand landSelectCmd = new MySqlCommand(m_landSelect, conn); | 1555 | MySqlCommand landSelectCmd = new MySqlCommand(m_landSelect, conn); |
@@ -1286,6 +1562,10 @@ namespace OpenSim.Framework.Data.MySQL | |||
1286 | { | 1562 | { |
1287 | pDa.Fill(tmpDS, "prims"); | 1563 | pDa.Fill(tmpDS, "prims"); |
1288 | sDa.Fill(tmpDS, "primshapes"); | 1564 | sDa.Fill(tmpDS, "primshapes"); |
1565 | |||
1566 | if (persistPrimInventories) | ||
1567 | iDa.Fill(tmpDS, "primitems"); | ||
1568 | |||
1289 | tDa.Fill(tmpDS, "terrain"); | 1569 | tDa.Fill(tmpDS, "terrain"); |
1290 | lDa.Fill(tmpDS, "land"); | 1570 | lDa.Fill(tmpDS, "land"); |
1291 | lalDa.Fill(tmpDS, "landaccesslist"); | 1571 | lalDa.Fill(tmpDS, "landaccesslist"); |
@@ -1298,6 +1578,10 @@ namespace OpenSim.Framework.Data.MySQL | |||
1298 | 1578 | ||
1299 | pDa.Fill(tmpDS, "prims"); | 1579 | pDa.Fill(tmpDS, "prims"); |
1300 | sDa.Fill(tmpDS, "primshapes"); | 1580 | sDa.Fill(tmpDS, "primshapes"); |
1581 | |||
1582 | if (persistPrimInventories) | ||
1583 | iDa.Fill(tmpDS, "primitems"); | ||
1584 | |||
1301 | tDa.Fill(tmpDS, "terrain"); | 1585 | tDa.Fill(tmpDS, "terrain"); |
1302 | lDa.Fill(tmpDS, "land"); | 1586 | lDa.Fill(tmpDS, "land"); |
1303 | lalDa.Fill(tmpDS, "landaccesslist"); | 1587 | lalDa.Fill(tmpDS, "landaccesslist"); |
@@ -1310,6 +1594,7 @@ namespace OpenSim.Framework.Data.MySQL | |||
1310 | return false; | 1594 | return false; |
1311 | } | 1595 | } |
1312 | } | 1596 | } |
1597 | |||
1313 | foreach (DataColumn col in createShapeTable().Columns) | 1598 | foreach (DataColumn col in createShapeTable().Columns) |
1314 | { | 1599 | { |
1315 | if (!tmpDS.Tables["primshapes"].Columns.Contains(col.ColumnName)) | 1600 | if (!tmpDS.Tables["primshapes"].Columns.Contains(col.ColumnName)) |
@@ -1318,6 +1603,9 @@ namespace OpenSim.Framework.Data.MySQL | |||
1318 | return false; | 1603 | return false; |
1319 | } | 1604 | } |
1320 | } | 1605 | } |
1606 | |||
1607 | // XXX primitems should probably go here eventually | ||
1608 | |||
1321 | foreach (DataColumn col in createTerrainTable().Columns) | 1609 | foreach (DataColumn col in createTerrainTable().Columns) |
1322 | { | 1610 | { |
1323 | if (!tmpDS.Tables["terrain"].Columns.Contains(col.ColumnName)) | 1611 | if (!tmpDS.Tables["terrain"].Columns.Contains(col.ColumnName)) |
@@ -1326,6 +1614,7 @@ namespace OpenSim.Framework.Data.MySQL | |||
1326 | return false; | 1614 | return false; |
1327 | } | 1615 | } |
1328 | } | 1616 | } |
1617 | |||
1329 | foreach (DataColumn col in createLandTable().Columns) | 1618 | foreach (DataColumn col in createLandTable().Columns) |
1330 | { | 1619 | { |
1331 | if (!tmpDS.Tables["land"].Columns.Contains(col.ColumnName)) | 1620 | if (!tmpDS.Tables["land"].Columns.Contains(col.ColumnName)) |
@@ -1334,6 +1623,7 @@ namespace OpenSim.Framework.Data.MySQL | |||
1334 | return false; | 1623 | return false; |
1335 | } | 1624 | } |
1336 | } | 1625 | } |
1626 | |||
1337 | foreach (DataColumn col in createLandAccessListTable().Columns) | 1627 | foreach (DataColumn col in createLandAccessListTable().Columns) |
1338 | { | 1628 | { |
1339 | if (!tmpDS.Tables["landaccesslist"].Columns.Contains(col.ColumnName)) | 1629 | if (!tmpDS.Tables["landaccesslist"].Columns.Contains(col.ColumnName)) |
@@ -1342,6 +1632,7 @@ namespace OpenSim.Framework.Data.MySQL | |||
1342 | return false; | 1632 | return false; |
1343 | } | 1633 | } |
1344 | } | 1634 | } |
1635 | |||
1345 | return true; | 1636 | return true; |
1346 | } | 1637 | } |
1347 | 1638 | ||
@@ -1395,6 +1686,10 @@ namespace OpenSim.Framework.Data.MySQL | |||
1395 | { | 1686 | { |
1396 | return "integer"; | 1687 | return "integer"; |
1397 | } | 1688 | } |
1689 | else if (type == typeof (Int64)) | ||
1690 | { | ||
1691 | return "bigint"; | ||
1692 | } | ||
1398 | else if (type == typeof (Double)) | 1693 | else if (type == typeof (Double)) |
1399 | { | 1694 | { |
1400 | return "float"; | 1695 | return "float"; |
@@ -1409,4 +1704,4 @@ namespace OpenSim.Framework.Data.MySQL | |||
1409 | } | 1704 | } |
1410 | } | 1705 | } |
1411 | } | 1706 | } |
1412 | } \ No newline at end of file | 1707 | } |
diff --git a/OpenSim/Framework/Data.SQLite/SQLiteRegionData.cs b/OpenSim/Framework/Data.SQLite/SQLiteRegionData.cs index 96dd5ac..dfd4535 100644 --- a/OpenSim/Framework/Data.SQLite/SQLiteRegionData.cs +++ b/OpenSim/Framework/Data.SQLite/SQLiteRegionData.cs | |||
@@ -61,6 +61,7 @@ namespace OpenSim.Framework.Data.SQLite | |||
61 | 61 | ||
62 | private String m_connectionString; | 62 | private String m_connectionString; |
63 | 63 | ||
64 | // Temporary attribute while this is experimental | ||
64 | private bool persistPrimInventories; | 65 | private bool persistPrimInventories; |
65 | 66 | ||
66 | /*********************************************************************** | 67 | /*********************************************************************** |
@@ -208,6 +209,7 @@ namespace OpenSim.Framework.Data.SQLite | |||
208 | { | 209 | { |
209 | DataTable prims = ds.Tables["prims"]; | 210 | DataTable prims = ds.Tables["prims"]; |
210 | DataTable shapes = ds.Tables["primshapes"]; | 211 | DataTable shapes = ds.Tables["primshapes"]; |
212 | DataTable items = ds.Tables["primitems"]; | ||
211 | 213 | ||
212 | string selectExp = "SceneGroupID = '" + Util.ToRawUuidString(obj) + "'"; | 214 | string selectExp = "SceneGroupID = '" + Util.ToRawUuidString(obj) + "'"; |
213 | lock (ds) | 215 | lock (ds) |
@@ -215,13 +217,28 @@ namespace OpenSim.Framework.Data.SQLite | |||
215 | DataRow[] primRows = prims.Select(selectExp); | 217 | DataRow[] primRows = prims.Select(selectExp); |
216 | foreach (DataRow row in primRows) | 218 | foreach (DataRow row in primRows) |
217 | { | 219 | { |
220 | // Remove shape rows | ||
218 | LLUUID uuid = new LLUUID((string) row["UUID"]); | 221 | LLUUID uuid = new LLUUID((string) row["UUID"]); |
219 | DataRow shapeRow = shapes.Rows.Find(Util.ToRawUuidString(uuid)); | 222 | DataRow shapeRow = shapes.Rows.Find(Util.ToRawUuidString(uuid)); |
220 | if (shapeRow != null) | 223 | if (shapeRow != null) |
221 | { | 224 | { |
222 | shapeRow.Delete(); | 225 | shapeRow.Delete(); |
223 | } | 226 | } |
224 | row.Delete(); | 227 | |
228 | if (persistPrimInventories) | ||
229 | { | ||
230 | // Remove items rows | ||
231 | String sql = String.Format("primID = '{0}'", uuid); | ||
232 | DataRow[] itemRows = items.Select(sql); | ||
233 | |||
234 | foreach (DataRow itemsRow in itemRows) | ||
235 | { | ||
236 | itemsRow.Delete(); | ||
237 | } | ||
238 | } | ||
239 | |||
240 | // Remove prim row | ||
241 | row.Delete(); | ||
225 | } | 242 | } |
226 | } | 243 | } |
227 | 244 | ||
@@ -1444,6 +1461,20 @@ namespace OpenSim.Framework.Data.SQLite | |||
1444 | param.SourceColumn = name; | 1461 | param.SourceColumn = name; |
1445 | param.SourceVersion = DataRowVersion.Current; | 1462 | param.SourceVersion = DataRowVersion.Current; |
1446 | return param; | 1463 | return param; |
1464 | } | ||
1465 | |||
1466 | private void setupPrimCommands(SqliteDataAdapter da, SqliteConnection conn) | ||
1467 | { | ||
1468 | da.InsertCommand = createInsertCommand("prims", ds.Tables["prims"]); | ||
1469 | da.InsertCommand.Connection = conn; | ||
1470 | |||
1471 | da.UpdateCommand = createUpdateCommand("prims", "UUID=:UUID", ds.Tables["prims"]); | ||
1472 | da.UpdateCommand.Connection = conn; | ||
1473 | |||
1474 | SqliteCommand delete = new SqliteCommand("delete from prims where UUID = :UUID"); | ||
1475 | delete.Parameters.Add(createSqliteParameter("UUID", typeof (String))); | ||
1476 | delete.Connection = conn; | ||
1477 | da.DeleteCommand = delete; | ||
1447 | } | 1478 | } |
1448 | 1479 | ||
1449 | private void setupItemsCommands(SqliteDataAdapter da, SqliteConnection conn) | 1480 | private void setupItemsCommands(SqliteDataAdapter da, SqliteConnection conn) |
@@ -1460,20 +1491,6 @@ namespace OpenSim.Framework.Data.SQLite | |||
1460 | da.DeleteCommand = delete; | 1491 | da.DeleteCommand = delete; |
1461 | } | 1492 | } |
1462 | 1493 | ||
1463 | private void setupPrimCommands(SqliteDataAdapter da, SqliteConnection conn) | ||
1464 | { | ||
1465 | da.InsertCommand = createInsertCommand("prims", ds.Tables["prims"]); | ||
1466 | da.InsertCommand.Connection = conn; | ||
1467 | |||
1468 | da.UpdateCommand = createUpdateCommand("prims", "UUID=:UUID", ds.Tables["prims"]); | ||
1469 | da.UpdateCommand.Connection = conn; | ||
1470 | |||
1471 | SqliteCommand delete = new SqliteCommand("delete from prims where UUID = :UUID"); | ||
1472 | delete.Parameters.Add(createSqliteParameter("UUID", typeof (String))); | ||
1473 | delete.Connection = conn; | ||
1474 | da.DeleteCommand = delete; | ||
1475 | } | ||
1476 | |||
1477 | private void setupTerrainCommands(SqliteDataAdapter da, SqliteConnection conn) | 1494 | private void setupTerrainCommands(SqliteDataAdapter da, SqliteConnection conn) |
1478 | { | 1495 | { |
1479 | da.InsertCommand = createInsertCommand("terrain", ds.Tables["terrain"]); | 1496 | da.InsertCommand = createInsertCommand("terrain", ds.Tables["terrain"]); |
@@ -1656,8 +1673,8 @@ namespace OpenSim.Framework.Data.SQLite | |||
1656 | return false; | 1673 | return false; |
1657 | } | 1674 | } |
1658 | } | 1675 | } |
1659 | 1676 | ||
1660 | // TODO Not restoring prim inventories quite yet | 1677 | // XXX primitems should probably go here eventually |
1661 | 1678 | ||
1662 | foreach (DataColumn col in createTerrainTable().Columns) | 1679 | foreach (DataColumn col in createTerrainTable().Columns) |
1663 | { | 1680 | { |
diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.Inventory.cs index b188fdd..d694f67 100644 --- a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.Inventory.cs +++ b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.Inventory.cs | |||
@@ -235,6 +235,13 @@ namespace OpenSim.Region.Environment.Scenes | |||
235 | if (part != null) | 235 | if (part != null) |
236 | { | 236 | { |
237 | part.UpdateInventoryItem(item); | 237 | part.UpdateInventoryItem(item); |
238 | |||
239 | // It might seem somewhat crude to update the whole group for a single prim inventory change, | ||
240 | // but it's possible that other prim inventory changes will take place before the region | ||
241 | // persistence thread visits this object. In the future, changes can be signalled at a more | ||
242 | // granular level, or we could let the datastore worry about whether prims have really | ||
243 | // changed since they were last persisted. | ||
244 | HasChanged = true; | ||
238 | 245 | ||
239 | return true; | 246 | return true; |
240 | } | 247 | } |