diff options
Diffstat (limited to 'OpenSim/Framework/TaskInventoryDictionary.cs')
-rw-r--r-- | OpenSim/Framework/TaskInventoryDictionary.cs | 189 |
1 files changed, 183 insertions, 6 deletions
diff --git a/OpenSim/Framework/TaskInventoryDictionary.cs b/OpenSim/Framework/TaskInventoryDictionary.cs index 421bd5d..4d07746 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,180 @@ 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 | // private string WriterStack; | ||
56 | |||
57 | // private Dictionary<Thread, string> ReadLockers = | ||
58 | // new Dictionary<Thread, string>(); | ||
59 | |||
60 | /// <value> | ||
61 | /// An advanced lock for inventory data | ||
62 | /// </value> | ||
63 | private System.Threading.ReaderWriterLockSlim m_itemLock = new System.Threading.ReaderWriterLockSlim(); | ||
64 | |||
65 | /// <summary> | ||
66 | /// Are we readlocked by the calling thread? | ||
67 | /// </summary> | ||
68 | public bool IsReadLockedByMe() | ||
69 | { | ||
70 | if (m_itemLock.RecursiveReadCount > 0) | ||
71 | { | ||
72 | return true; | ||
73 | } | ||
74 | else | ||
75 | { | ||
76 | return false; | ||
77 | } | ||
78 | } | ||
79 | |||
80 | /// <summary> | ||
81 | /// Lock our inventory list for reading (many can read, one can write) | ||
82 | /// </summary> | ||
83 | public void LockItemsForRead(bool locked) | ||
84 | { | ||
85 | if (locked) | ||
86 | { | ||
87 | if (m_itemLock.IsWriteLockHeld && LockedByThread != null) | ||
88 | { | ||
89 | if (!LockedByThread.IsAlive) | ||
90 | { | ||
91 | //Locked by dead thread, reset. | ||
92 | m_itemLock = new System.Threading.ReaderWriterLockSlim(); | ||
93 | } | ||
94 | } | ||
95 | |||
96 | if (m_itemLock.RecursiveReadCount > 0) | ||
97 | { | ||
98 | 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."); | ||
99 | try | ||
100 | { | ||
101 | // That call stack is useful for end users only. RealProgrammers need a full dump. Commented. | ||
102 | // StackTrace stackTrace = new StackTrace(); // get call stack | ||
103 | // StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames) | ||
104 | // | ||
105 | // // write call stack method names | ||
106 | // foreach (StackFrame stackFrame in stackFrames) | ||
107 | // { | ||
108 | // m_log.Error("[SceneObjectGroup.m_parts] "+(stackFrame.GetMethod().Name)); // write method name | ||
109 | // } | ||
110 | |||
111 | // The below is far more useful | ||
112 | // System.Console.WriteLine("------------------------------------------"); | ||
113 | // System.Console.WriteLine("My call stack:\n" + Environment.StackTrace); | ||
114 | // System.Console.WriteLine("------------------------------------------"); | ||
115 | // foreach (KeyValuePair<Thread, string> kvp in ReadLockers) | ||
116 | // { | ||
117 | // System.Console.WriteLine("Locker name {0} call stack:\n" + kvp.Value, kvp.Key.Name); | ||
118 | // System.Console.WriteLine("------------------------------------------"); | ||
119 | // } | ||
120 | } | ||
121 | catch | ||
122 | {} | ||
123 | m_itemLock.ExitReadLock(); | ||
124 | } | ||
125 | if (m_itemLock.RecursiveWriteCount > 0) | ||
126 | { | ||
127 | m_log.Error("[TaskInventoryDictionary] Recursive write lock requested. This should not happen and means something needs to be fixed."); | ||
128 | // try | ||
129 | // { | ||
130 | // System.Console.WriteLine("------------------------------------------"); | ||
131 | // System.Console.WriteLine("My call stack:\n" + Environment.StackTrace); | ||
132 | // System.Console.WriteLine("------------------------------------------"); | ||
133 | // System.Console.WriteLine("Locker's call stack:\n" + WriterStack); | ||
134 | // System.Console.WriteLine("------------------------------------------"); | ||
135 | // } | ||
136 | // catch | ||
137 | // {} | ||
138 | m_itemLock.ExitWriteLock(); | ||
139 | } | ||
140 | |||
141 | while (!m_itemLock.TryEnterReadLock(60000)) | ||
142 | { | ||
143 | 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."); | ||
144 | if (m_itemLock.IsWriteLockHeld) | ||
145 | { | ||
146 | m_itemLock = new System.Threading.ReaderWriterLockSlim(); | ||
147 | // System.Console.WriteLine("------------------------------------------"); | ||
148 | // System.Console.WriteLine("My call stack:\n" + Environment.StackTrace); | ||
149 | // System.Console.WriteLine("------------------------------------------"); | ||
150 | // System.Console.WriteLine("Locker's call stack:\n" + WriterStack); | ||
151 | // System.Console.WriteLine("------------------------------------------"); | ||
152 | // LockedByThread = null; | ||
153 | // ReadLockers.Clear(); | ||
154 | } | ||
155 | } | ||
156 | // ReadLockers[Thread.CurrentThread] = Environment.StackTrace; | ||
157 | } | ||
158 | else | ||
159 | { | ||
160 | if (m_itemLock.RecursiveReadCount>0) | ||
161 | { | ||
162 | m_itemLock.ExitReadLock(); | ||
163 | } | ||
164 | // if (m_itemLock.RecursiveReadCount == 0) | ||
165 | // ReadLockers.Remove(Thread.CurrentThread); | ||
166 | } | ||
167 | } | ||
168 | |||
169 | /// <summary> | ||
170 | /// Lock our inventory list for writing (many can read, one can write) | ||
171 | /// </summary> | ||
172 | public void LockItemsForWrite(bool locked) | ||
173 | { | ||
174 | if (locked) | ||
175 | { | ||
176 | //Enter a write lock, wait indefinately for one to open. | ||
177 | if (m_itemLock.RecursiveReadCount > 0) | ||
178 | { | ||
179 | 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."); | ||
180 | m_itemLock.ExitReadLock(); | ||
181 | } | ||
182 | if (m_itemLock.RecursiveWriteCount > 0) | ||
183 | { | ||
184 | m_log.Error("[TaskInventoryDictionary] Recursive write lock requested. This should not happen and means something needs to be fixed."); | ||
185 | |||
186 | m_itemLock.ExitWriteLock(); | ||
187 | } | ||
188 | while (!m_itemLock.TryEnterWriteLock(60000)) | ||
189 | { | ||
190 | if (m_itemLock.IsWriteLockHeld) | ||
191 | { | ||
192 | 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."); | ||
193 | // System.Console.WriteLine("------------------------------------------"); | ||
194 | // System.Console.WriteLine("My call stack:\n" + Environment.StackTrace); | ||
195 | // System.Console.WriteLine("------------------------------------------"); | ||
196 | // System.Console.WriteLine("Locker's call stack:\n" + WriterStack); | ||
197 | // System.Console.WriteLine("------------------------------------------"); | ||
198 | } | ||
199 | else | ||
200 | { | ||
201 | m_log.Error("Thread lock detected while trying to aquire WRITE lock in TaskInventoryDictionary. Locked by a reader. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed."); | ||
202 | // System.Console.WriteLine("------------------------------------------"); | ||
203 | // System.Console.WriteLine("My call stack:\n" + Environment.StackTrace); | ||
204 | // System.Console.WriteLine("------------------------------------------"); | ||
205 | // foreach (KeyValuePair<Thread, string> kvp in ReadLockers) | ||
206 | // { | ||
207 | // System.Console.WriteLine("Locker name {0} call stack:\n" + kvp.Value, kvp.Key.Name); | ||
208 | // System.Console.WriteLine("------------------------------------------"); | ||
209 | // } | ||
210 | } | ||
211 | m_itemLock = new System.Threading.ReaderWriterLockSlim(); | ||
212 | // ReadLockers.Clear(); | ||
213 | } | ||
214 | |||
215 | LockedByThread = Thread.CurrentThread; | ||
216 | // WriterStack = Environment.StackTrace; | ||
217 | } | ||
218 | else | ||
219 | { | ||
220 | if (m_itemLock.RecursiveWriteCount > 0) | ||
221 | { | ||
222 | m_itemLock.ExitWriteLock(); | ||
223 | } | ||
224 | } | ||
225 | } | ||
48 | 226 | ||
49 | #region ICloneable Members | 227 | #region ICloneable Members |
50 | 228 | ||
@@ -52,14 +230,13 @@ namespace OpenSim.Framework | |||
52 | { | 230 | { |
53 | TaskInventoryDictionary clone = new TaskInventoryDictionary(); | 231 | TaskInventoryDictionary clone = new TaskInventoryDictionary(); |
54 | 232 | ||
55 | lock (this) | 233 | m_itemLock.EnterReadLock(); |
234 | foreach (UUID uuid in Keys) | ||
56 | { | 235 | { |
57 | foreach (UUID uuid in Keys) | 236 | clone.Add(uuid, (TaskInventoryItem) this[uuid].Clone()); |
58 | { | ||
59 | clone.Add(uuid, (TaskInventoryItem) this[uuid].Clone()); | ||
60 | } | ||
61 | } | 237 | } |
62 | 238 | m_itemLock.ExitReadLock(); | |
239 | |||
63 | return clone; | 240 | return clone; |
64 | } | 241 | } |
65 | 242 | ||