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