Re: Plugin System



On Sat, 2003-09-06 at 18:59, Jody Goldberg wrote:
> Apologies for the delay.
> 
> On Tue, Sep 02, 2003 at 05:57:49PM -0700, Bob Smith wrote:
> > Different parts of the plugin system.
> > 
> > Main parts:
> > 1. Discovery.
> > 2. Activation.
> 
> - We'll need to define what is meant by those terms.
> Discovery : Name seems fairly self evident.  The act of finding what
>     plugins are available.  What is not terribly clear is why we

Yeah.

>     need to do this at start up.  To date we've made the simplifying

Thats something that needs to be addressed. Although, you could make the
argument that you too are discovering the plugins on startup. You just
only have one way of doing that. 

>     assumption that its inexpensive to load 10-20 hopefully small
>     xml files by searching directories.  We should have a valid

You probably could speed this up by letting the discovery mechanisms
cache things that will rarely change. 

>     reason for using that model instead of a pango-querymodules
>     approach.

There's a few ways to do this:
1. Have a binary file that's all the plugin information boiled down into
a nice fast single file that the plugin system could read. That would
make startup the fastest. Plugins would need to be registered with the
file when installed.
2. The xml way, each plugin defines a separate file describing itself.
This is relatively fast, but somewhat inflexible. You have two very
different types of information in the plugin description file. Metadata
for the plugin, and information relating to how to load the plugin. From
my experience, if you don't have an autoconf style .in file used to
write the xml file, then it becomes a real hassle to deal with the xml
file. If you move the plugin, you have to sort through all the metadata
to get to the location property. Also, all metadata isn't relevant at
all times. For example, you don't need the service metadata until you
enable the plugin, so disabled plugins waste memory. This could be
optimized by breaking the plugin file up into more files, but that makes
managing them a little more difficult. If you get a plugin from a
friend, you have to deal with balling up all the files, and making sure
the location fields reflect your computer. One way out of this would be
similar to 1. Make the plugins self describing, and have a utility to
generate the one or multiple xml files out of it.
3. Dynamic with caching. Support multiple discovery modules, they
discover each of their plugins however they want. The information they
discover will almost never change so can be cached with a mechanism
similar to 1. So, the first time you run Gnumeric or just after adding a
plugin, Gnumeric load time is slow. After that, the load time will be
very quick. This is the way I was considering most when I wrote the
document. This would allow things like this senario. I run a buisness. I
want my spreadsheets to support a common look. So, I implement plugins
using python. To make things easier to manage, I provide the plugins on
the company's webserver. Simple enough. I have an xml file on the server
describe the plugins, and I write a simple discovery module that query's
the server's plugin list, copy's the plugin files down if they are not
already there or old. This might add only a second to the load time if
done properly. This makes it really easy to manage an office's plugins.
Everything happens automagically. For things like mono, You could just
drop your foo.dll into the plugin directory and it automatically
recognizes it as a plugin. 

> 
> Activate : This term is so overloaded that I'm unclear which meaning
>     you intend.

Sorry. The loader mechanism you implement.

> 
> > Notes:
> > 1. Proxies. A lot of programs wont need proxy objects. Let the application provide them.
> 
> What's a proxy ?

An object that acts like a service but is just a wrapper around it so
you can delay the loading of a plugin until absolutely necessary.

> 
> > One main GObject that deals with these features:
> > 1. State property.
> > 2. Add directory. State becomes PROCESSING. Idle callback to update metadata.
> > 3. Remove directory. State becomes PROCESSING. Remove metadata. Idle callback to unload relevent plugins.
> > 4. A function to get a list of directories.
> Why are we talking about directories at this level ?  If we're truly
> going to abstract discovery isn't 'xml files in directories' an
> implementation detail of the current form ?

This allows the user of the application to give a hint to discovery
objects where to look for plugins. Discovery objects are free to look
elsewhere (for example, a web server). Ex, Three different plugin
discovery mechanisms. One for R files, One for Mono and one for XML
described plugins. They all might want to look in
"/usr/share/gnumeric/plugins" and "/home/foo/.gnumeric/.plugins". A user
might want to look for plugins in "/shared/gnumeric/plugins" too. This
would inform all the discovery objects to look for their plugins in that
directory too.

> 
> Why talk of idle handlers ?
> 

So if things take too long to load, the GUI can be refreshed while it
processes without the need of threads.

> > Notes:
> > 1. When a plugin is removed, remove it via an idle handler.
> > 3. Do as much as possible through idle callbacks. The plugin system should stay out of everyone's way.
> why ?
> That seems like it will make our lives harder than necessary
> The only area what speed seems to be an issue is application
> startup.  Direct user interventions to enable/disable things can
> operate on a more leasurely time scale.  I'd opt for simple
> implementation (synchronous) unless there is a pressing reason.
> 

Ok.

> > 2. Keep in mind the possibility of caching a completed metadata tree (or parts of it) so the next run is faster.
> This should explicitly be cached at _install_ time.  Not some
> autogenerated cache at run time.  The former has nice packaging
> semantics, the later is a permissioning nightmare.

Discussion postponed until Discovery mechanism worked out a bit more.
(Do we want to stick with xml files then?)

> > 1. A service almost never can be shared between apps, so
> > information about them (Like metadata description, parsers, and
> > display widgets) should usually be implemented in the application
> > itself rather then a generic library.
> 
> Agreed.  Although I would add the notion that a plugin should be
> able to add service types for other plugins to implement.
>  

Yes. Agreed.

> ---------------------------------------------------------------------
> 
> Hmm, this commentary seems harsher than I meant it to be.  I'd
> recommend starting simpler.  Lets agree on some goals and entity
> names.

Didn't seem overly harsh. Seems like we needed to go over some
definitions and discuss stuff before it everything makes sense. 

> 
> Service 	: An interface specification.

Yes.

> ServiceImpl	: A factory that produces objects supporting a Service

This is a detail. My plugins don't need factories, they just need one
instance of a service. If the instance of a service supports spawning of
more objects like a factory, thats up to the service itself to decide.
Maybe we should say, ServiceInstance.

> Plugin  : A blob that that contains implementations of services

Taking ServiceInstance from above,
Plugin: A blob that contains instances of services.

> PluginMetaData : 1) User visible, translatable text describing a
> 		    plugin and the ServiceImpls it contains.

Ok.

> 		 2) Implementation detail.  A machine readable
> 		    characterization of which ServiceImples the plugin
> 		    contains.  It should specify what service(s) each
> 		    impl supports, and may define service specific
> 		    information.

Hmm.. I'm not sure where this really comes in. Could you elaborate?

> 
> Discovery : A two part process
> 	    1) The act of finding what plugins are available
> 	    2) loading the PluginMetaData for the plugins from (1)
> 

Agreed.

> Beyond that things start to get fuzzy.  So I'll move on to goals.

Yeah.

> It should be possible to :
> - Start up quickly.  Anything that degrades startup performance more
>   than the current approach in gnumeric is a non-starter.

I would agree that in the general case it should start up quickly. The
first time it starts up though could be slow IMHO. If done the way I
would like to, the first time would be a little slower then done now,
and probably faster subsequent times.

> - Define plugins on a per application basis.  Sharing them seems
>   like a very rare use case (?example?).

Agreed. I've thought about this some more and still couldn't figure out
a good example of when they really would need to be shared. The way I
described things in the doc though, it wouldn't be impossible to share
plugins. You would just add a directory to the list that contains the
shared plugins in each app sharing them.

> - Manage plugins along multiple dimensions
>     : User vs Group vs System
>     : version and possibly architecture support for parallel
>       installability. (ala gcc).

Yes. This sounds good.

> - Support multiple languages for implementation via 'Loader's.  I'm
>   still talking about the simple gnumeric form so far.  This refers
>   only to implementation language, not for self describing entities.

This is the Activation that I talked about in the document. We're in
agreement here.

> - Support a dependency graph for plugins (NO CYCLES).  This is
>   necesary to support things like loader as a Service

Agreed.

> Simlifying assumptions :
> - Ultra basic instance management.  There is at most 1 instance of a
>   plugin within each application.  You mentioned wanting to
>   segregate the metadata which seems reasonable.

Yes.

> 
> - implementations are in process.  Something could conceivably wrap
>   an out of process implementation, but apps should assume all calls
>   are local.

Yes.

> 
> - Try to have only 2 basic services to keep the loaders simple
>     : General	= does something when activated
>     		  does something else when deactivated
> 	No objects, no instance data.

I was thinking about doing things all the GObject way, but this seems
reasonable too.

>     : GObject	= service types can layer on top of this.  Its not a
> 	    perfect fit (eg GnmFunctionGroup).  Lets see if its
> 	    enough.

Ok.
Could you give an example of why GnmFunctionGroup is not suited for
GObject?

> 
> Areas with more flexibility :
> - Run time performance.  I don't see adjusting the set of plugins,
>   or the set of active plugins as a common task.

Agreed. Thats why I mentioned idle handlers in the document. Optimize
for run time speed in the use of the plugins, and let things like
adjusting the set of plugins or activation be slower but still not
interfere with the GUI.

> 
> -------------------------------------------------
> 
> blah, I'm out of time.  Its obviously missing alot.  Tack on what
> you'd like, or want to clarify/change and we can iterate it.

Have a look at this email when you get a chance, point out anything you
think wrong and I'll fix up the document to include this stuff. Then we
can iterate. :)

> 
> -------------------------------------------------
> 
> Explain to me why we need self describing mono plugins.  I'm still
> not convinced we need all this complexity to avoid having the xml
> files.

For better support of easy packaging of plugins (Just download this
plugin to your plugin directory and your done) and remote plugin
support.

I'm also not quite convinced we need all the complexity. But, I think on
the other side of things, I don't think the user should have to put up
with the complexity of managing the xml files or running a script on a
plugin to generate them from a plugin is very justified when it can
easily be automated and hidden from the user.


---  Bob Smith <bob thestuff net>  ---
++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++
..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.

Attachment: signature.asc
Description: This is a digitally signed message part



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]