aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/TaskInventoryDictionary.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Framework/TaskInventoryDictionary.cs189
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
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Threading;
31using System.Reflection;
30using System.Xml; 32using System.Xml;
33using System.Diagnostics;
31using System.Xml.Schema; 34using System.Xml.Schema;
32using System.Xml.Serialization; 35using System.Xml.Serialization;
36using log4net;
33using OpenMetaverse; 37using OpenMetaverse;
34 38
35namespace OpenSim.Framework 39namespace 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