76
79
public UniverseManager ()
78
universe = new Dictionary<string, Element> ();
81
universe = new UniverseCollection ();
82
universe_lock = new object ();
80
84
update_thread = new Thread (new ThreadStart (UniverseUpdateLoop));
81
85
update_thread.IsBackground = true;
82
86
update_thread.Priority = ThreadPriority.Lowest;
88
Services.Network.StateChanged += OnNetworkStateChanged;
91
void OnNetworkStateChanged (object sender, NetworkStateChangedEventArgs e)
85
96
public void Initialize ()
103
114
update_thread.Start ();
106
public IEnumerable<Element> Search (string query, IEnumerable<Type> filter)
117
public IEnumerable<Item> Search (string query, IEnumerable<Type> filter)
108
return Search (query, filter, (Element) null);
119
return Search (query, filter, (Item) null);
111
public IEnumerable<Element> Search (string query, IEnumerable<Type> filter, Element other)
122
public IEnumerable<Item> Search (string query, IEnumerable<Type> filter, Item other)
113
if (filter.Count () == 1 && filter.First () == typeof (Act))
114
return Search (query, filter, PluginManager.Actions.OfType<Element> (), other);
117
return Search (query, filter, universe.Values, other);
125
return Search (query, filter, universe.Values, other);
120
public IEnumerable<Element> Search (string query, IEnumerable<Type> filter, IEnumerable<Element> objects)
128
public IEnumerable<Item> Search (string query, IEnumerable<Type> filter, IEnumerable<Item> objects)
122
130
return Search (query, filter, objects, null);
125
public IEnumerable<Element> Search (string query, IEnumerable<Type> filter, IEnumerable<Element> elements, Element other)
133
public IEnumerable<Item> Search (string query, IEnumerable<Type> filter, IEnumerable<Item> elements, Item other)
127
Element text = new ImplicitTextItem (query);
135
Item text = new ImplicitTextItem (query);
129
136
string lquery = query.ToLower ();
131
foreach (Element element in elements)
132
element.UpdateRelevance (lquery, other);
135
.Where (element => epsilon < Math.Abs (element.Relevance) && element.PassesTypeFilter (filter))
139
.Where (element => element.PassesTypeFilter (filter) && epsilon < Math.Abs (element.UpdateRelevance (lquery, other)))
136
140
.OrderByDescending (element => element.Relevance)
137
.Concat (text.PassesTypeFilter (filter)
139
: Enumerable.Empty<Element> ()
141
.Concat (text.PassesTypeFilter (filter) ? new [] { text } : Enumerable.Empty<Item> ())
145
146
/// Returns if an object likely contains children.
147
148
/// <param name="o">
148
/// A <see cref="Element"/>
149
/// A <see cref="Item"/>
151
152
/// A <see cref="System.Boolean"/>
153
public bool ElementHasChildren (Element element)
154
public bool ItemHasChildren (Item item)
155
return element is Item && (element as Item).HasChildren ();
156
return item.HasChildren ();
161
162
void UniverseUpdateLoop ()
163
164
Random rand = new Random ();
164
DateTime startUpdate = DateTime.Now;
165
DateTime startUpdate = DateTime.UtcNow;
167
168
Thread.Sleep (UpdateTimeout);
168
169
if (Do.Controller.IsSummoned) continue;
169
startUpdate = DateTime.Now;
170
startUpdate = DateTime.UtcNow;
171
172
if (rand.Next (10) == 0) {
173
ReloadActions (universe);
175
176
foreach (ItemSource source in PluginManager.ItemSources) {
176
ReloadSource (source);
177
if (UpdateRunTime < DateTime.Now - startUpdate) {
177
ReloadSource (source, universe);
179
if (UpdateRunTime < DateTime.UtcNow - startUpdate) {
178
180
Thread.Sleep (UpdateTimeout);
179
startUpdate = DateTime.Now;
181
// sleeping for a bit
182
startUpdate = DateTime.UtcNow;
186
189
/// Reloads all actions in the universe.
188
void ReloadActions ()
191
void ReloadActions (UniverseCollection universe)
190
193
Log<UniverseManager>.Debug ("Reloading actions...");
192
foreach (Act action in PluginManager.Actions) {
193
universe.Remove (action.UniqueId);
195
foreach (Act action in PluginManager.Actions) {
196
universe [action.UniqueId] = action;
194
lock (universe_lock) {
195
foreach (Act action in PluginManager.Actions) {
196
if (universe.ContainsKey (action.UniqueId))
197
universe.Remove (action.UniqueId);
199
foreach (Act action in PluginManager.Actions)
200
universe [action.UniqueId] = action;
203
206
/// not be called on the main thread to avoid blocking the UI if the
204
207
/// item source takes a long time to update.
206
void ReloadSource (ItemSource source)
209
void ReloadSource (ItemSource source, UniverseCollection universe)
208
211
SafeItemSource safeSource;
209
212
IEnumerable<Item> oldItems, newItems;
211
214
if (source == null) throw new ArgumentNullException ("source");
213
216
safeSource = source.RetainSafe ();
214
Log<UniverseManager>.Debug ("Reloading item source \"{0}\"...", safeSource.Name);
215
217
oldItems = safeSource.Items;
216
218
// We call UpdateItems outside of the lock so as not to block other
217
219
// threads in contention for the lock if UpdateItems blocks.
220
Log<UniverseManager>.Debug ("Reloading item source \"{0}\"...", safeSource.Name);
218
221
safeSource.UpdateItems ();
219
222
newItems = safeSource.Items;
224
lock (universe_lock) {
222
225
foreach (Item item in oldItems) {
223
226
if (universe.ContainsKey (item.UniqueId))
224
227
universe.Remove (item.UniqueId);
232
235
void ReloadUniverse ()
234
237
Log<UniverseManager>.Info ("Reloading universe...");
236
PluginManager.ItemSources.ForEach (ReloadSource);
239
// A new temporary universe is created so that searches made during the reload (as threaded
240
// searches are allowed will not see an interuption in available items). Additionally this
241
// serves to clear out unused items that are orphaned from their item service.
242
UniverseCollection tmpUniverse = new UniverseCollection ();
243
ReloadActions (tmpUniverse);
244
PluginManager.ItemSources.ForEach (source => ReloadSource (source, tmpUniverse));
246
// Clearing the old universe is not needed and considered harmful as enumerables in existence
247
// already will be based off the old universe. Clearing it may cause an exception to be thrown.
248
// Once those enumerables are destroyed, so too will the old universe.
249
universe = tmpUniverse;
237
250
Log<UniverseManager>.Info ("Universe contains {0} items.", universe.Count);
273
/// Attempts to get an Element for a given UniqueId.
286
/// Attempts to get an Item for a given UniqueId.
275
288
/// <param name="UniqueId">
276
289
/// A <see cref="System.String"/>
278
291
/// <param name="item">
279
/// A <see cref="Element"/>
292
/// A <see cref="Item"/>
281
public bool TryGetElementForUniqueId (string uid, out Element element)
294
public bool TryGetItemForUniqueId (string uid, out Item element)
296
lock (universe_lock) {
284
297
if (universe.ContainsKey (uid)) {
285
298
element = universe [uid];