diff options
author | Adam Frisby | 2009-11-23 17:20:03 +1100 |
---|---|---|
committer | Adam Frisby | 2009-11-23 17:20:03 +1100 |
commit | b516fe67a00b81923945ecaab49e996408aa8172 (patch) | |
tree | 1752489d32aa06b192b54d4598f319abd6ddd5f0 /OpenSim/Data | |
parent | * Adds a modicum of additional checking to the Inventory Service (MySQL only) (diff) | |
download | opensim-SC_OLD-b516fe67a00b81923945ecaab49e996408aa8172.zip opensim-SC_OLD-b516fe67a00b81923945ecaab49e996408aa8172.tar.gz opensim-SC_OLD-b516fe67a00b81923945ecaab49e996408aa8172.tar.bz2 opensim-SC_OLD-b516fe67a00b81923945ecaab49e996408aa8172.tar.xz |
* Implements SQL Rollback support to Inventory Service for quicker backup restoration.
* Can optionally replace the OpenGridMode committed earlier.
* Will create a series of incrementing restore SQL files, one per user, in folders listed per-day.
* For MySql Section of InventoryService INI:
rollback = "true"
rollbackdir = "/absolute/path/to/rollback/storage/dir"
Diffstat (limited to 'OpenSim/Data')
-rw-r--r-- | OpenSim/Data/MySQL/MySQLInventoryData.cs | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/OpenSim/Data/MySQL/MySQLInventoryData.cs b/OpenSim/Data/MySQL/MySQLInventoryData.cs index 063dd91..0ea0cb7 100644 --- a/OpenSim/Data/MySQL/MySQLInventoryData.cs +++ b/OpenSim/Data/MySQL/MySQLInventoryData.cs | |||
@@ -26,6 +26,7 @@ | |||
26 | */ | 26 | */ |
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.IO; | ||
29 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
30 | using System.Reflection; | 31 | using System.Reflection; |
31 | using log4net; | 32 | using log4net; |
@@ -463,6 +464,125 @@ namespace OpenSim.Data.MySQL | |||
463 | } | 464 | } |
464 | } | 465 | } |
465 | 466 | ||
467 | #region Inventory Rollback-via-.sql Support | ||
468 | /// <summary> | ||
469 | /// Not a good SQL escape function, but it'll do the job (if mutilate the data.) | ||
470 | /// Someone may want to write something better here. | ||
471 | /// </summary> | ||
472 | /// <param name="str"></param> | ||
473 | /// <returns></returns> | ||
474 | private static string cheapSQLescape(string str) | ||
475 | { | ||
476 | str = str.Replace("\\", ""); | ||
477 | str = str.Replace("'", ""); | ||
478 | str = str.Replace("\"", ""); | ||
479 | return "'" + str + "'"; | ||
480 | } | ||
481 | |||
482 | private static string InventoryItemToSql(InventoryItemBase item) | ||
483 | { | ||
484 | string sql = | ||
485 | "REPLACE /*! INVITEM AT ***$SUBS$*** */ INTO inventoryitems (inventoryID, assetID, assetType, parentFolderID, avatarID, inventoryName" | ||
486 | + ", inventoryDescription, inventoryNextPermissions, inventoryCurrentPermissions, invType" | ||
487 | + ", creatorID, inventoryBasePermissions, inventoryEveryOnePermissions, inventoryGroupPermissions, salePrice, saleType" | ||
488 | + ", creationDate, groupID, groupOwned, flags) VALUES "; | ||
489 | sql += | ||
490 | "(?inventoryID, ?assetID, ?assetType, ?parentFolderID, ?avatarID, ?inventoryName, ?inventoryDescription" | ||
491 | + ", ?inventoryNextPermissions, ?inventoryCurrentPermissions, ?invType, ?creatorID" | ||
492 | + ", ?inventoryBasePermissions, ?inventoryEveryOnePermissions, ?inventoryGroupPermissions, ?salePrice, ?saleType, ?creationDate" | ||
493 | + ", ?groupID, ?groupOwned, ?flags);\r\n"; | ||
494 | |||
495 | string itemName = item.Name; | ||
496 | string itemDesc = item.Description; | ||
497 | |||
498 | sql = sql.Replace("$SUBS$", Util.UnixTimeSinceEpoch().ToString()); | ||
499 | |||
500 | sql = sql.Replace("?inventoryID", cheapSQLescape(item.ID.ToString())); | ||
501 | sql = sql.Replace("?assetID", cheapSQLescape(item.AssetID.ToString())); | ||
502 | sql = sql.Replace("?assetType", cheapSQLescape(item.AssetType.ToString())); | ||
503 | sql = sql.Replace("?parentFolderID", cheapSQLescape(item.Folder.ToString())); | ||
504 | sql = sql.Replace("?avatarID", cheapSQLescape(item.Owner.ToString())); | ||
505 | sql = sql.Replace("?inventoryName", cheapSQLescape(itemName)); | ||
506 | sql = sql.Replace("?inventoryDescription", cheapSQLescape(itemDesc)); | ||
507 | sql = sql.Replace("?inventoryNextPermissions", cheapSQLescape(item.NextPermissions.ToString())); | ||
508 | sql = sql.Replace("?inventoryCurrentPermissions", cheapSQLescape(item.CurrentPermissions.ToString())); | ||
509 | sql = sql.Replace("?invType", cheapSQLescape(item.InvType.ToString())); | ||
510 | sql = sql.Replace("?creatorID", cheapSQLescape(item.CreatorId)); | ||
511 | sql = sql.Replace("?inventoryBasePermissions", cheapSQLescape(item.BasePermissions.ToString())); | ||
512 | sql = sql.Replace("?inventoryEveryOnePermissions", cheapSQLescape(item.EveryOnePermissions.ToString())); | ||
513 | sql = sql.Replace("?inventoryGroupPermissions", cheapSQLescape(item.GroupPermissions.ToString())); | ||
514 | sql = sql.Replace("?salePrice", cheapSQLescape(item.SalePrice.ToString())); | ||
515 | sql = sql.Replace("?saleType", cheapSQLescape(unchecked((sbyte)item.SaleType).ToString())); | ||
516 | sql = sql.Replace("?creationDate", cheapSQLescape(item.CreationDate.ToString())); | ||
517 | sql = sql.Replace("?groupID", cheapSQLescape(item.GroupID.ToString())); | ||
518 | sql = sql.Replace("?groupOwned", cheapSQLescape(item.GroupOwned.ToString())); | ||
519 | sql = sql.Replace("?flags", cheapSQLescape(item.Flags.ToString())); | ||
520 | |||
521 | return sql; | ||
522 | } | ||
523 | |||
524 | private static string InventoryFolderToSql(InventoryFolderBase folder) | ||
525 | { | ||
526 | string sql = | ||
527 | "REPLACE /*! INVFOLDER AT ***$SUBS$*** */ INTO inventoryfolders (folderID, agentID, parentFolderID, folderName, type, version) VALUES "; | ||
528 | sql += "(?folderID, ?agentID, ?parentFolderID, ?folderName, ?type, ?version);\r\n"; | ||
529 | |||
530 | string folderName = folder.Name; | ||
531 | |||
532 | sql = sql.Replace("$SUBS$", Util.UnixTimeSinceEpoch().ToString()); | ||
533 | |||
534 | sql = sql.Replace("?folderID", cheapSQLescape(folder.ID.ToString())); | ||
535 | sql = sql.Replace("?agentID", cheapSQLescape(folder.Owner.ToString())); | ||
536 | sql = sql.Replace("?parentFolderID", cheapSQLescape(folder.ParentID.ToString())); | ||
537 | sql = sql.Replace("?folderName", cheapSQLescape(folderName)); | ||
538 | sql = sql.Replace("?type", cheapSQLescape(folder.Type.ToString())); | ||
539 | sql = sql.Replace("?version", cheapSQLescape(folder.Version.ToString())); | ||
540 | |||
541 | return sql; | ||
542 | } | ||
543 | |||
544 | private static string getRollbackFolderDate() | ||
545 | { | ||
546 | return DateTime.UtcNow.Year.ToString() + "-" + DateTime.UtcNow.Month.ToString() + "-" + | ||
547 | DateTime.UtcNow.Day.ToString(); | ||
548 | } | ||
549 | |||
550 | private void StoreRollbackItem(UUID ItemID) | ||
551 | { | ||
552 | if(rollbackStore == true) | ||
553 | { | ||
554 | string todaysPath = RollbackGetTodaysPath(); | ||
555 | |||
556 | InventoryItemBase imb = getInventoryItem(ItemID); | ||
557 | string sql = InventoryItemToSql(imb); | ||
558 | File.AppendAllText(Path.Combine(todaysPath, imb.Owner.ToString()), sql); | ||
559 | } | ||
560 | } | ||
561 | |||
562 | private void StoreRollbackFolder(UUID FolderID) | ||
563 | { | ||
564 | if (rollbackStore == true) | ||
565 | { | ||
566 | string todaysPath = RollbackGetTodaysPath(); | ||
567 | |||
568 | InventoryFolderBase ifb = getInventoryFolder(FolderID); | ||
569 | string sql = InventoryFolderToSql(ifb); | ||
570 | File.AppendAllText(Path.Combine(todaysPath, ifb.Owner.ToString()), sql); | ||
571 | } | ||
572 | } | ||
573 | |||
574 | private string RollbackGetTodaysPath() | ||
575 | { | ||
576 | if (!Directory.Exists(rollbackDir)) | ||
577 | Directory.CreateDirectory(rollbackDir); | ||
578 | |||
579 | string todaysPath = Path.Combine(rollbackDir, getRollbackFolderDate()); | ||
580 | if (!Directory.Exists(todaysPath)) | ||
581 | Directory.CreateDirectory(todaysPath); | ||
582 | return todaysPath; | ||
583 | } | ||
584 | #endregion | ||
585 | |||
466 | /// <summary> | 586 | /// <summary> |
467 | /// Adds a specified item to the database | 587 | /// Adds a specified item to the database |
468 | /// </summary> | 588 | /// </summary> |
@@ -549,6 +669,8 @@ namespace OpenSim.Data.MySQL | |||
549 | /// <param name="item">Inventory item to update</param> | 669 | /// <param name="item">Inventory item to update</param> |
550 | public void updateInventoryItem(InventoryItemBase item) | 670 | public void updateInventoryItem(InventoryItemBase item) |
551 | { | 671 | { |
672 | StoreRollbackItem(item.ID); | ||
673 | |||
552 | addInventoryItem(item); | 674 | addInventoryItem(item); |
553 | } | 675 | } |
554 | 676 | ||
@@ -558,6 +680,8 @@ namespace OpenSim.Data.MySQL | |||
558 | /// <param name="item">The inventory item UUID to delete</param> | 680 | /// <param name="item">The inventory item UUID to delete</param> |
559 | public void deleteInventoryItem(UUID itemID) | 681 | public void deleteInventoryItem(UUID itemID) |
560 | { | 682 | { |
683 | StoreRollbackItem(itemID); | ||
684 | |||
561 | try | 685 | try |
562 | { | 686 | { |
563 | database.CheckConnection(); | 687 | database.CheckConnection(); |
@@ -634,6 +758,7 @@ namespace OpenSim.Data.MySQL | |||
634 | /// <param name="folder">Folder to update</param> | 758 | /// <param name="folder">Folder to update</param> |
635 | public void updateInventoryFolder(InventoryFolderBase folder) | 759 | public void updateInventoryFolder(InventoryFolderBase folder) |
636 | { | 760 | { |
761 | StoreRollbackFolder(folder.ID); | ||
637 | addInventoryFolder(folder); | 762 | addInventoryFolder(folder); |
638 | } | 763 | } |
639 | 764 | ||
@@ -644,6 +769,8 @@ namespace OpenSim.Data.MySQL | |||
644 | /// <remarks>UPDATE inventoryfolders SET parentFolderID=?parentFolderID WHERE folderID=?folderID</remarks> | 769 | /// <remarks>UPDATE inventoryfolders SET parentFolderID=?parentFolderID WHERE folderID=?folderID</remarks> |
645 | public void moveInventoryFolder(InventoryFolderBase folder) | 770 | public void moveInventoryFolder(InventoryFolderBase folder) |
646 | { | 771 | { |
772 | StoreRollbackFolder(folder.ID); | ||
773 | |||
647 | string sql = | 774 | string sql = |
648 | "UPDATE inventoryfolders SET parentFolderID=?parentFolderID WHERE folderID=?folderID"; | 775 | "UPDATE inventoryfolders SET parentFolderID=?parentFolderID WHERE folderID=?folderID"; |
649 | 776 | ||
@@ -805,6 +932,8 @@ namespace OpenSim.Data.MySQL | |||
805 | /// <param name="folderID">the folder UUID</param> | 932 | /// <param name="folderID">the folder UUID</param> |
806 | protected void deleteOneFolder(UUID folderID) | 933 | protected void deleteOneFolder(UUID folderID) |
807 | { | 934 | { |
935 | StoreRollbackFolder(folderID); | ||
936 | |||
808 | try | 937 | try |
809 | { | 938 | { |
810 | database.CheckConnection(); | 939 | database.CheckConnection(); |
@@ -831,6 +960,14 @@ namespace OpenSim.Data.MySQL | |||
831 | /// <param name="folderID">the folder UUID</param> | 960 | /// <param name="folderID">the folder UUID</param> |
832 | protected void deleteItemsInFolder(UUID folderID) | 961 | protected void deleteItemsInFolder(UUID folderID) |
833 | { | 962 | { |
963 | if (rollbackStore) | ||
964 | { | ||
965 | foreach (InventoryItemBase itemBase in getInventoryInFolder(folderID)) | ||
966 | { | ||
967 | StoreRollbackItem(itemBase.ID); | ||
968 | } | ||
969 | } | ||
970 | |||
834 | try | 971 | try |
835 | { | 972 | { |
836 | database.CheckConnection(); | 973 | database.CheckConnection(); |
@@ -865,17 +1002,34 @@ namespace OpenSim.Data.MySQL | |||
865 | //Delete all sub-folders | 1002 | //Delete all sub-folders |
866 | foreach (InventoryFolderBase f in subFolders) | 1003 | foreach (InventoryFolderBase f in subFolders) |
867 | { | 1004 | { |
1005 | StoreRollbackFolder(f.ID); | ||
868 | deleteOneFolder(f.ID); | 1006 | deleteOneFolder(f.ID); |
1007 | |||
1008 | if(rollbackStore) | ||
1009 | { | ||
1010 | foreach (InventoryItemBase itemBase in getInventoryInFolder(f.ID)) | ||
1011 | { | ||
1012 | StoreRollbackItem(itemBase.ID); | ||
1013 | } | ||
1014 | } | ||
869 | deleteItemsInFolder(f.ID); | 1015 | deleteItemsInFolder(f.ID); |
870 | } | 1016 | } |
871 | } | 1017 | } |
872 | 1018 | ||
1019 | StoreRollbackFolder(folderID); | ||
873 | //Delete the actual row | 1020 | //Delete the actual row |
874 | deleteOneFolder(folderID); | 1021 | deleteOneFolder(folderID); |
875 | 1022 | ||
876 | // Just delete the folder context in OGM | 1023 | // Just delete the folder context in OGM |
877 | if (opengridmode == false) | 1024 | if (opengridmode == false) |
878 | { | 1025 | { |
1026 | if (rollbackStore) | ||
1027 | { | ||
1028 | foreach (InventoryItemBase itemBase in getInventoryInFolder(folderID)) | ||
1029 | { | ||
1030 | StoreRollbackItem(itemBase.ID); | ||
1031 | } | ||
1032 | } | ||
879 | deleteItemsInFolder(folderID); | 1033 | deleteItemsInFolder(folderID); |
880 | } | 1034 | } |
881 | } | 1035 | } |