diff options
Diffstat (limited to 'OpenSim/Framework/TaskInventoryDictionary.cs')
-rw-r--r-- | OpenSim/Framework/TaskInventoryDictionary.cs | 132 |
1 files changed, 127 insertions, 5 deletions
diff --git a/OpenSim/Framework/TaskInventoryDictionary.cs b/OpenSim/Framework/TaskInventoryDictionary.cs index 25ae6b0..940e567 100644 --- a/OpenSim/Framework/TaskInventoryDictionary.cs +++ b/OpenSim/Framework/TaskInventoryDictionary.cs | |||
@@ -27,9 +27,13 @@ | |||
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Threading; | ||
31 | using System.Reflection; | ||
30 | using System.Xml; | 32 | using System.Xml; |
33 | using System.Diagnostics; | ||
31 | using System.Xml.Schema; | 34 | using System.Xml.Schema; |
32 | using System.Xml.Serialization; | 35 | using System.Xml.Serialization; |
36 | using log4net; | ||
33 | using OpenMetaverse; | 37 | using OpenMetaverse; |
34 | 38 | ||
35 | namespace OpenSim.Framework | 39 | namespace OpenSim.Framework |
@@ -45,6 +49,125 @@ namespace OpenSim.Framework | |||
45 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 49 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
46 | 50 | ||
47 | private static XmlSerializer tiiSerializer = new XmlSerializer(typeof (TaskInventoryItem)); | 51 | private static XmlSerializer tiiSerializer = new XmlSerializer(typeof (TaskInventoryItem)); |
52 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
53 | |||
54 | private Thread LockedByThread; | ||
55 | /// <value> | ||
56 | /// An advanced lock for inventory data | ||
57 | /// </value> | ||
58 | private System.Threading.ReaderWriterLockSlim m_itemLock = new System.Threading.ReaderWriterLockSlim(); | ||
59 | |||
60 | /// <summary> | ||
61 | /// Are we readlocked by the calling thread? | ||
62 | /// </summary> | ||
63 | public bool IsReadLockedByMe() | ||
64 | { | ||
65 | if (m_itemLock.RecursiveReadCount > 0) | ||
66 | { | ||
67 | return true; | ||
68 | } | ||
69 | else | ||
70 | { | ||
71 | return false; | ||
72 | } | ||
73 | } | ||
74 | |||
75 | /// <summary> | ||
76 | /// Lock our inventory list for reading (many can read, one can write) | ||
77 | /// </summary> | ||
78 | public void LockItemsForRead(bool locked) | ||
79 | { | ||
80 | if (locked) | ||
81 | { | ||
82 | if (m_itemLock.IsWriteLockHeld && LockedByThread != null) | ||
83 | { | ||
84 | if (!LockedByThread.IsAlive) | ||
85 | { | ||
86 | //Locked by dead thread, reset. | ||
87 | m_itemLock = new System.Threading.ReaderWriterLockSlim(); | ||
88 | } | ||
89 | } | ||
90 | |||
91 | if (m_itemLock.RecursiveReadCount > 0) | ||
92 | { | ||
93 | m_log.Error("[TaskInventoryDictionary] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue."); | ||
94 | try | ||
95 | { | ||
96 | StackTrace stackTrace = new StackTrace(); // get call stack | ||
97 | StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames) | ||
98 | |||
99 | // write call stack method names | ||
100 | foreach (StackFrame stackFrame in stackFrames) | ||
101 | { | ||
102 | m_log.Error("[SceneObjectGroup.m_parts] "+(stackFrame.GetMethod().Name)); // write method name | ||
103 | } | ||
104 | } | ||
105 | catch | ||
106 | {} | ||
107 | m_itemLock.ExitReadLock(); | ||
108 | } | ||
109 | if (m_itemLock.RecursiveWriteCount > 0) | ||
110 | { | ||
111 | m_log.Error("[TaskInventoryDictionary] Recursive write lock requested. This should not happen and means something needs to be fixed."); | ||
112 | m_itemLock.ExitWriteLock(); | ||
113 | } | ||
114 | |||
115 | while (!m_itemLock.TryEnterReadLock(60000)) | ||
116 | { | ||
117 | m_log.Error("Thread lock detected while trying to aquire READ lock in TaskInventoryDictionary. Locked by thread " + LockedByThread.Name + ". I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed."); | ||
118 | if (m_itemLock.IsWriteLockHeld) | ||
119 | { | ||
120 | m_itemLock = new System.Threading.ReaderWriterLockSlim(); | ||
121 | } | ||
122 | } | ||
123 | } | ||
124 | else | ||
125 | { | ||
126 | if (m_itemLock.RecursiveReadCount>0) | ||
127 | { | ||
128 | m_itemLock.ExitReadLock(); | ||
129 | } | ||
130 | } | ||
131 | } | ||
132 | |||
133 | /// <summary> | ||
134 | /// Lock our inventory list for writing (many can read, one can write) | ||
135 | /// </summary> | ||
136 | public void LockItemsForWrite(bool locked) | ||
137 | { | ||
138 | if (locked) | ||
139 | { | ||
140 | //Enter a write lock, wait indefinately for one to open. | ||
141 | if (m_itemLock.RecursiveReadCount > 0) | ||
142 | { | ||
143 | m_log.Error("[TaskInventoryDictionary] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue."); | ||
144 | m_itemLock.ExitReadLock(); | ||
145 | } | ||
146 | if (m_itemLock.RecursiveWriteCount > 0) | ||
147 | { | ||
148 | m_log.Error("[TaskInventoryDictionary] Recursive write lock requested. This should not happen and means something needs to be fixed."); | ||
149 | m_itemLock.ExitWriteLock(); | ||
150 | } | ||
151 | while (!m_itemLock.TryEnterWriteLock(60000)) | ||
152 | { | ||
153 | m_log.Error("Thread lock detected while trying to aquire WRITE lock in TaskInventoryDictionary. Locked by thread " + LockedByThread.Name + ". I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed."); | ||
154 | System.Console.WriteLine("My call stack:\n" + Environment.StackTrace); | ||
155 | if (m_itemLock.IsWriteLockHeld) | ||
156 | { | ||
157 | m_itemLock = new System.Threading.ReaderWriterLockSlim(); | ||
158 | } | ||
159 | } | ||
160 | |||
161 | LockedByThread = Thread.CurrentThread; | ||
162 | } | ||
163 | else | ||
164 | { | ||
165 | if (m_itemLock.RecursiveWriteCount > 0) | ||
166 | { | ||
167 | m_itemLock.ExitWriteLock(); | ||
168 | } | ||
169 | } | ||
170 | } | ||
48 | 171 | ||
49 | #region ICloneable Members | 172 | #region ICloneable Members |
50 | 173 | ||
@@ -52,13 +175,12 @@ namespace OpenSim.Framework | |||
52 | { | 175 | { |
53 | TaskInventoryDictionary clone = new TaskInventoryDictionary(); | 176 | TaskInventoryDictionary clone = new TaskInventoryDictionary(); |
54 | 177 | ||
55 | lock (this) | 178 | m_itemLock.EnterReadLock(); |
179 | foreach (UUID uuid in Keys) | ||
56 | { | 180 | { |
57 | foreach (UUID uuid in Keys) | 181 | clone.Add(uuid, (TaskInventoryItem) this[uuid].Clone()); |
58 | { | ||
59 | clone.Add(uuid, (TaskInventoryItem) this[uuid].Clone()); | ||
60 | } | ||
61 | } | 182 | } |
183 | m_itemLock.ExitReadLock(); | ||
62 | 184 | ||
63 | return clone; | 185 | return clone; |
64 | } | 186 | } |