Re: Release status.
- From: Nat Friedman <nat novell com>
- To: Jim McDonald <Jim mcdee net>
- Cc: "dashboard-hackers gnome org" <dashboard-hackers gnome org>
- Subject: Re: Release status.
- Date: Tue, 09 Dec 2003 09:25:57 -0500
On Tue, 2003-12-09 at 08:28, Jim McDonald wrote:
> I've had a quick look at this issue and hacked (*really* hacked)
> together what appears to be a quick fix, centered around RunQuery().
> Whenever RunQuery() is called it attempts to EndInvoke() all threads
> that were BeginInvoke()d the last time RunQuery() ran. This seems to
> do the trick.
>
> The patch is ugly, though. Ideally it would keep proper track of
> what backends were active and which had finished and maintain the list
> properly, but I don't have time to do that until at least this
> weekend.
>
> If anyone wants to look at the fix I've made my replacement
> cluepacket-manager.cs available at
> http://www.devzero.net/downloads/cluepacket-manager.cs
I patched this a bit, here's my new version.
It's still not working for me, though, I get a hang in EndInvoke at some
point. Also, lots of this:
Killing: Bookmarks
Exception: System.InvalidOperationException: The requested
operation cannot be performed
(null)
Exception Rethrown at:
in (unmanaged) /usr/lib/libmono.so.0(mono_raise_exception+0x1b)
[0x40093087]
in (unmanaged) /usr/lib/libmono.so.0 [0x400a32dd]
in <0x0003b> (wrapper delegate-end-invoke)
System.MulticastDelegate:end_invoke_void_IAsyncResult
(System.IAsyncResult)
in [0x00085] (at
/home/nat/cvs/dashboard/engine/cluepacket-manager.cs:89)
Dashboard.CluePacketManager:RunQuery (Dashboard.CluePacket)
Best,
Nat
//
// GNOME Dashboard
//
// cluepacket-manager.cs: Dispatches clues to backends as they come in
// from frontends.
//
// Authors:
// Nat Friedman <nat nat org>
// Miguel de Icaza <miguel ximian com>
// Joe Shaw <joe assbarn com>
//
using System;
using System.Collections;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Runtime.Remoting.Messaging;
namespace Dashboard {
public delegate void QueryBackendHandler (Backend b, CluePacket cp);
public class RunningQuery {
public IAsyncResult iar;
public QueryBackendHandler qbh;
public string name;
public RunningQuery (QueryBackendHandler q, IAsyncResult i, string n)
{
iar = i;
qbh = q;
name = n;
}
}
public class CluePacketManager {
// A list of all the loaded Dashboard.Backend objects.
ArrayList backends = new ArrayList ();
// Where to look for backend DLLs.
string backends_dir;
// Keep track of backend handlers that are currently running
ArrayList running_queries = new ArrayList();
// The MatchFilter object, to which we send the
// matches when they come in from the backends.
MatchFilter match_filter;
// Our callback invoked when a backend query is done,
// to check for errors.
AsyncCallback query_backend_done;
public CluePacketManager (MatchFilter filter)
{
this.match_filter = filter;
query_backend_done = new AsyncCallback (QueryBackendDone);
}
// This function gets called whenever a new cluepacket
// comes in from a frontend.
public void ProcessFrontendCluePacket (CluePacket cp)
{
// Let the MatchFilter know that we just got a fresh
// cluepacket, so that it knows what the most current
// cluepacket is, and can avoid displaying matches
// from old cludepackets.
this.match_filter.NotifyNewCluePacket (cp);
this.RunQuery (cp);
}
public void RunQuery (CluePacket cp)
{
if (cp == null || cp.Clues.Count == 0)
return;
lock (this.running_queries)
{
Console.WriteLine ("Killing handlers from previous requests");
foreach (RunningQuery q in running_queries)
{
Console.WriteLine ("Killing: " + q.name);
try
{
q.qbh.EndInvoke (q.iar);
}
catch (Exception ex)
{
Console.WriteLine ("Exception: " + ex);
// The item has probably already finished
}
}
running_queries = new ArrayList ();
}
Console.WriteLine ("\n\nRunning Query:\n------\n{0}", cp.ToString ());
lock (this.backends) {
foreach (Backend backend in this.backends) {
if (! backend.Initialized)
continue;
if (! backend.AcceptCluePacket (cp))
continue;
lock (this.running_queries) {
// Process each of the backends in a new thread.
QueryBackendHandler query_backend = new QueryBackendHandler (this.QueryBackend);
IAsyncResult query_ar = query_backend.BeginInvoke (backend, cp, query_backend_done, null);
running_queries.Add (new RunningQuery (query_backend, query_ar, backend.Name));
}
}
}
}
// Ask the backend for matches and new clues based on
// the current cluepacket.
private void QueryBackend (Backend backend, CluePacket cp)
{
BackendResult result;
Console.WriteLine ("--sending--> {0}", backend.Name);
// Send the cluepacket to the backend.
try {
result = backend.ProcessCluePacket (cp);
if (result == null) {
Console.WriteLine ("<--done (no match)-- " + backend.Name);
return;
}
} catch (Exception e) {
Console.WriteLine ("ERROR in '{0}': {1}", backend.Name, e);
Console.WriteLine ("<--done (ERROR)-- " + backend.Name);
return;
}
int nmatches = result.Matches != null ? result.Matches.Count : 0;
int nclues = result.NewClues != null ? result.NewClues.Count : 0;
if (nmatches == 0 && nclues == 0)
Console.WriteLine ("<--nothing-- {2}", nmatches, nclues, backend.Name);
else
Console.WriteLine ("<--[m{0}:c{1}]-- {2}", nmatches, nclues, backend.Name);
// Send the matches to the match filter.
if (nmatches > 0) {
foreach (Match m in result.Matches) {
Console.WriteLine( "Sending matches to the match filter." );
match_filter.NotifyMatch (cp, m);
}
}
// Cluechain.
if (nclues > 0) {
CluePacket new_cp = new CluePacket (cp);
// Have an array of "Text:Type" to track what we've already seen.
// Use IndexOf to search it?
foreach (Clue new_clue in result.NewClues) {
new_cp.AddClue (new_clue);
}
if (new_cp != cp) {
Console.WriteLine( "Have a new CluePacket, time to do more work!");
RunQuery (new_cp);
} else {
Console.WriteLine( "This CluePacket is the same as the last one, why do more work?");
}
}
}
// Called back by the runtime, when the QueryBackend
// async method terminates
void QueryBackendDone (IAsyncResult ar)
{
QueryBackendHandler query_backend = (QueryBackendHandler) (((AsyncResult)ar).AsyncDelegate);
try {
query_backend.EndInvoke (ar);
} catch (Exception e) {
Console.WriteLine ("Exception inside QueryBackend");
// Console.WriteLine (e);
}
}
// Search the backends directory for DLLs that are
// Dashboard backends and start them up.
public void LoadBackends ()
{
backends_dir = Environment.GetEnvironmentVariable ("DASHBOARD_BACKEND_PATH");
if (backends_dir == null || backends_dir == "")
backends_dir = "../backends";
string [] files = Directory.GetFiles (backends_dir, "*.dll");
foreach (string file in files) {
try {
Console.WriteLine ("Checking backend " + file);
Assembly a = Assembly.LoadFrom (file);
Type [] types = a.GetTypes ();
foreach (Type t in types) {
if (!t.IsSubclassOf (typeof (Backend)))
continue;
Console.WriteLine ("Loading backend " + file);
Backend backend = (Backend) Activator.CreateInstance (t);
ThreadPool.QueueUserWorkItem (new WaitCallback (this.LaunchBackend), backend);
}
} catch {
//
// Ignore an error if the file is not really an assembly
//
}
}
}
// In a separate thread
void LaunchBackend (object o)
{
try {
Backend b = (Backend) o;
if (b.Startup ()) {
Console.WriteLine ("{0} successfully loaded", b.Name);
lock (backends){
backends.Add (b);
}
} else {
Console.WriteLine ("{0} NOT loaded", b.Name);
}
} catch (Exception e) {
Console.WriteLine ("Received exception while loading Backend:");
Console.WriteLine (" Backend type: {0}\n" + o.GetType ().ToString ());
Console.WriteLine ("Exception is:\n{0}", e);
}
}
// FIXME: This should not be here. It's only in the
// CPM because that's where we're keeping the backend
// list.
public void NotifyBackendLinkClicked (string url)
{
string backend_name = null;
string[] split;
try {
split = url.Split (':');
backend_name = split [1];
} catch {
Console.WriteLine ("Could not get backend name from link URL");
return;
}
if (backend_name == null || backend_name == "") {
Console.WriteLine ("Could not get backend name from link URL");
return;
}
string user_data = url.Substring (backend_name.Length + "backend::".Length);
Console.WriteLine ("LinkClicked [{0}] [{1}]", backend_name, user_data);
lock (backends) {
foreach (Backend b in this.backends)
if (b.Name == backend_name) {
b.LinkClicked (user_data);
return;
}
}
}
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]