Gossamer Forum
Home : Products : Gossamer Links : Development, Plugins and Globals :

GT plugin system bug (or "feature" :-), problems, and additional info (FYI) & Solution suggestion

Quote Reply
GT plugin system bug (or "feature" :-), problems, and additional info (FYI) & Solution suggestion
I noticed a very interesting problem, with the GT plugin system. I hooked the 'handle_page' in PRE mode, in my several plugins (Extended_link, Advanced_Link_Expirator, Timer_Page).

Well, this means, all hooked functions of these 3 plugins, should be executed in a sequence (using 'handle_page' in PRE mode).
Except, if one function will have a STOP action.
If one has STOP action, the execution of this PRE hook will stop, and the remaining plugin functionss be will *NOT* executed, neither the original code.

=> So if the function sequence has the following order: (Extended_link, Advanced_Link_Expirator, Timer_Page), and we have a STOP action in Extended_link to stop the original code, we also get the result, that the rest of the functions of Advanced_Link_Expirator, Timer_Page will be NOT executed!
We do *NOT WANT* to execute the original code, but we still *WANT* to execute the function of Advanced_Link_Expirator, Timer_Page, but they will be not executed, because the Extended_link function already had a STOP action, to stop original code. Eh...

Interesting, right?
Well, this functionality is good, it is a feature, so should work like this. And here comes the BUT.

But problem is, that we can NOT change or define the execution order of different plugins' functions, that belongs to same hook.

Why? Because the plugins (and plugin names, too), are stored in a hash, which is loaded from plugin.cfg file. It is stored as hash of hashes. The plugin names are the keys, and we know, the keys are not stored sorted internally in Perl in any way. Therefore, when a hook is executed, the order of executed plugin functions can NOT changed or defined by the plugin developer in any way, it is assigned by Perl itself internally. Frown
I hear, some of you may say, this is not a bug, this is a "feature" Laugh. IMHO, this is a bug. I do not argue about that. Does not matter.


Solutions to correct the bug:
1) This is basically a workaround:
The bug is in admin/GT/Plugins.pm in sub load_cfg function somewhere around line 207:
Code:
foreach my $plugin (keys %$PLUGIN_CFG) {
...
}
The keys are not sorted, before they are used.

The corrected code (bugfix) should look like:
Code:
foreach my $plugin (sort keys %$PLUGIN_CFG) {
...
}
Well, this is the easiest bugfix we can do now, to correct the problem of unsorted function executing. After applying this bugfix, we can have some plugins executed with higher priority, than other plugins, if we change the plugin name, to be first or last in the abc order.

Now, if I rename Extended_link to => Xtended_Link_Display, and Timer_Page to => AAA_Timer_Page, then the execution order will be the following for the 'handle_page' hook:
. . . a) executes the function of AAA_Timer_Page plugin, hooked to 'handle_page', then
. . . b) executes the function of Advanced_Link_Expirator plugin, hooked to 'handle_page', then
. . . c) executes the function of Xtended_Link_Display plugin, hooked to 'handle_page'.
If we have a STOP action in function of Xtended_Link_Display plugin, it will stop executing the original code, which would be executed otherwise.

Finally we reached to execute some plugins with higher priority, others with lower (depending on plugin name). That was what we wanted.

2) The following is a difficulter solution, to implement sortable execution of plugins in the GT plugin system.
We would like the following results:
. . . a) sortable execution order of the functions using the same hook, but which can be found in different plugins.
Example: each our installed plugins use the hook 'handle_page', and we want to decide which one to execute with higher, which with lower, and which with normal (does not matter in what order we execute it)

. . . b) also there is possible (but seems not too much logic to do that) to have the same hook used multiple times in the same plugin. These should also have sortable execution order. The solution I suggest for a) will solve the problem of b), if there will be ever need for that.

Solution:
The plugin.cfg now has the following format (shortened version):
Code:
$DUMP = {
'Timer_Page' => {
'hooks' => [
[
'handle_page',
'PRE',
'Plugins::Timer_Page::function',
'1'
]
],
'menu' => [],
'meta' => {},
'registry' => {},
'user' => [],
'version' => '2.01'
},
'Extended_link' => {
'hooks' => [
[
'handle_page',
'PRE',
'Plugins::Extended_link::function',
'1'
]
],
'menu' => [],
'meta' => {},
'registry' => {},
'user' => [],
'version' => '1.0'
},
'Advanced_Link_Expirator' => {
'hooks' => [
[
'handle_page',
'PRE',
'Plugins::Advanced_Link_Expirator::function',
'1'
]
],
'menu' => [ ],
'meta' => {},
'registry' => {},
'user' => [],
'version' => '1.0'
}
};

Warning! Please do not do any changes in the PLUGIN.CFG! This is strictly development information only, for advanced Perl-LSQL developers (Alex, GT staff), and not for Links SQL users!

We should modify it to the following (the code with red is added in the format):
Code:
$DUMP = {
[
{

'Timer_Page' => {
'hooks' => [
[
'handle_page',
'PRE',
'Plugins::Timer_Page::function',
# plugin priority level (0 disabled, 1 lowest, 5 highest, 3 is normal user level)
'5',
# plugin subpriority level (1 lowest, 100 highest, 50 is normal user level)
'75'

]
],
'menu' => [],
'meta' => {},
'registry' => {},
'user' => [],
'version' => '2.01'
},
},
{

'Extended_link' => {
'hooks' => [
[
'handle_page',
'PRE',
'Plugins::Extended_link::function',
# plugin priority level (0 disabled, 1 lowest, 5 highest, 3 is normal user level)
'1',
# plugin subpriority level (1 lowest, 100 highest, 50 is normal user level)
'50'

]
],
'menu' => [],
'meta' => {},
'registry' => {},
'user' => [],
'version' => '1.0'
},
},
{

'Advanced_Link_Expirator' => {
'hooks' => [
[
'handle_page',
'PRE',
'Plugins::Advanced_Link_Expirator::function',
# plugin priority level (0 disabled, 1 lowest, 5 highest, 3 is normal user level)
'3',
# plugin subpriority level (1 lowest, 100 highest, 50 is normal user level)
'50'

]
],
'menu' => [ ],
'meta' => {},
'registry' => {},
'user' => [],
'version' => '1.0'
}
}
]

};

Plugin Priority Options:
- plugin priority level: is valid, if number and between 0-5.
0 means, plugin is disabled
1 means, plugin has the lowest priority
3 is normal user level (but all noncompatible plugins, or those which are compatible only with earlier GT plugin system, will set automatically the 1(lowest) level.)
5 means, plugin has the highest priority (this should be used only in very rare cases, when the plugin should be executed very last in the hook function list)

- plugin subpriority level: is valid, if number and between 1-100.
1 means, plugin has the lowest priority
50 is normal user level (but all noncompatible plugins, or those which are compatible only with earlier GT plugin system, will set automatically the 1(lowest) level.)
100 means, plugin has the highest subpriority ( The highest priority (100) should be extremely rarely used by plugins. User plugins should only use max 90, as the highest priority, to leave space for very important plugins. GT should not allow higher subpriorities, than 90 in general, except in extreme cases, when it is really required, and proved by the plugin developer. )
The plugin should be executed very last in the hook function list.
101+ Should be Never used by user created plugins. Allowed only for special system plugins of GT.

The current plugin system mainly should be changed in:
- the /admin/GT/Plugins.pm in sub load_cfg and sub save_cfg functions. These funtions are responsible to load (or save), order, then merge hook functions into _pre_hook and _post_hook hashes, which contains the function lists sorted by plugins.
- Also /admin/Links/Plugins.pm should be changed to manage those new config structures (get, set, etc...)
- Of course there we also need an admin interface, to be able to manage those new features, and change plugin priorities, so changes in admin.pm are also needed.
These are the main places, what should be changed for the new Plugin System (maybe at other places, too but I did not investigated this).

I'm sure, this Improved Plugin System would qualify almost every needs. Would it? Angelic

In addition to this plugin system improvement, I just would need a 'user_page' hook in Links.pm and I would be 99% satisfied Wink Cool

Opinions, comments, constructive critics are welcome!

(I may ask edit right for this thread later, if I may find any error, what I would like to correct. I have to go now, so I post it without rereading this long post.)

Best regards,
Webmaster33


Paid Support
from Webmaster33. Expert in Perl programming & Gossamer Threads applications. (click here for prices)
Webmaster33's products (upd.2004.09.26) | Private message | Contact me | Was my post helpful? Donate my help...

Last edited by:

webmaster33: Aug 31, 2002, 9:29 AM
Quote Reply
Re: [webmaster33] GT plugin system bug (or "feature" :-), problems, and additional info (FYI) & Solution suggestion In reply to
I agree that running multiple plugins using the same hook needs a better mechanism for determining order but your idea of priority from 1 - 100 is not a good idea IMO

The plugin priority is determined by the author if I understand you correctly, so what if we all accidentally chose the same, how will they then be sorted, also what if a plugin running before mine affects the way mine functions?....your idea doesn't seem to solve the problem, it just re-sorts things a bit but essentially leaves you at square one.

Last edited by:

Paul: Aug 31, 2002, 9:50 AM
Quote Reply
Re: [Paul] GT plugin system bug (or "feature" :-), problems, and additional info (FYI) & Solution suggestion In reply to
Not exactly. Not priority from 1 - 100.

It is a multi-level priority system.
1) is base priority from 0 - 5

2) each base priority has a subpriority from 1 - 100. The 100+ levels are for GT system plugins.

Quote:
The plugin priority is determined by the author if I understand you correctly, so what if we all accidentally chose the same, how will they then be sorted, also what if a plugin running before mine affects the way mine functions?

Usually (80%) the plugin execution order does not matter.
If 2 plugins have the same level (base priority + subpriority), they should be executed in order, as they were stored (likely depends on internal hash storage order). And usually the order will be not matter.
If there are very rare conflicts, the plugin developers will likely change the priority, or even the user could change priority of each plugin (yes, I would allow the user to change the default priorities, if it is needed).

Best regards,
Webmaster33


Paid Support
from Webmaster33. Expert in Perl programming & Gossamer Threads applications. (click here for prices)
Webmaster33's products (upd.2004.09.26) | Private message | Contact me | Was my post helpful? Donate my help...
Quote Reply
Re: [webmaster33] GT plugin system bug (or "feature" :-), problems, and additional info (FYI) & Solution suggestion In reply to
Conflicts are rare and it just seems like an awfully big change to make for something that doesn't really solve the problem and still could result in ordering problems.

It would be silly for plugin developers to have to worry about orders and sub-orders and whatever else when making the plugin, really it is something that needs to be addressed in the plugin system and not with plugins.

The plugin system should simply keep running until all plugins on a certain hook have run and if a STOP was encountered the execution then stops otherwise it carries on. That is all that's needed IMO.

Last edited by:

Paul: Aug 31, 2002, 9:58 AM
Quote Reply
Re: [Paul] GT plugin system bug (or "feature" :-), problems, and additional info (FYI) & Solution suggestion In reply to
My solution could solve the current problem.

I'm suggesting it, because I've found current plugin system is unusable for me(at this point), until executing ordering is not possible.

My suggestion is the best solution, I can imagine currently.
Also if I remember correctly operating systems, use similar priority system...?!

If you know better solution, please post it!

Best regards,
Webmaster33


Paid Support
from Webmaster33. Expert in Perl programming & Gossamer Threads applications. (click here for prices)
Webmaster33's products (upd.2004.09.26) | Private message | Contact me | Was my post helpful? Donate my help...
Quote Reply
Re: [webmaster33] GT plugin system bug (or "feature" :-), problems, and additional info (FYI) & Solution suggestion In reply to
>>
If you know better solution, please post it!
<<

I already did.
Quote Reply
Re: [webmaster33] GT plugin system bug (or "feature" :-), problems, and additional info (FYI) & Solution suggestion In reply to
I haven't checked if what you say is true (setting a STOP action, and then the rest of the plugins are not executed), but I guess it is, since you seem to have tested this.

My proposal: nstead of having just a STOP action, GT could add one more action that executes all the other plugin PRE hooks, but does not execute the coderef passed in.

BTW: in the pod for GT/Plugins/Installer.pm it says something about a position, FIRST or LAST. Does anybody know if this is implemented (I didn't find reference to this anywhere else)?

Ivan
-----
Iyengar Yoga Resources / GT Plugins
Quote Reply
Re: [yogi] GT plugin system bug (or "feature" :-), problems, and additional info (FYI) & Solution suggestion In reply to
>>
BTW: in the pod for GT/Plugins/Installer.pm it says something about a position, FIRST or LAST. Does anybody know if this is implemented (I didn't find reference to this anywhere else)?
<<

yeah Ive been using FIRST and LAST in all my plugins :) ....its shown in the plugin wizard too.
Quote Reply
Re: [Paul] GT plugin system bug (or "feature" :-), problems, and additional info (FYI) & Solution suggestion In reply to
Well, I am using it too in my plugins, but does it have an effect?

Ivan
-----
Iyengar Yoga Resources / GT Plugins
Quote Reply
Re: [yogi] GT plugin system bug (or "feature" :-), problems, and additional info (FYI) & Solution suggestion In reply to
Oh, well i always assumed it did, no idea though Wink
Quote Reply
Re: [Paul] GT plugin system bug (or "feature" :-), problems, and additional info (FYI) & Solution suggestion In reply to
I just had a look at GT/Plugins.pm, and did not see a mention of FIRST or LAST anywhere.

What I did see, however, was that w33 is right, all further plugin hooks are dismissed if one plugins says STOP. This also happens for POST hooks. Adding a new action that executes the other plugins but does not execute the coderef would just be a small change.

Ivan
-----
Iyengar Yoga Resources / GT Plugins
Quote Reply
Re: [yogi] GT plugin system bug (or "feature" :-), problems, and additional info (FYI) & Solution suggestion In reply to
Yep, I'm not saying he's wrong but I just prefer my "solution" mentioned above :)

>>
The plugin system should simply keep running until all plugins on a certain hook have run and if a STOP was encountered the execution then stops otherwise it carries on. That is all that's needed IMO.
<<
Quote Reply
Re: [Paul] GT plugin system bug (or "feature" :-), problems, and additional info (FYI) & Solution suggestion In reply to
I agree with you. This should be the default thing that happens when you do a STOP action. Imagine, though, that you have a PRE hook on "handle_page" and you want to print your own page if a certain parameter is passed in (my honourable PageBuilder plugin does just that...). Anyway, if there is an other plugin that want's to do something similar, then we have a real problem....

Ivan
-----
Iyengar Yoga Resources / GT Plugins
Quote Reply
Re: [yogi] GT plugin system bug (or "feature" :-), problems, and additional info (FYI) & Solution suggestion In reply to
I see the point, that Yogi wrote, and I prefer his idea, to add new actions, which makes the plugin system more flexible.

Ideas, suggestions:

1) STOP_ORIGINAL action: Based on Yogi's idea, could be added a STOP_ORIGINAL action, which will stop executing only the original function. This would help my problem (partially).

2) Plugin Compatibility list of plugin: each plugin could have a checklist about those plugins, which are NOT compatible with this plugin, and warn the user about that, at install time. This should be an install.pm function. Each plugin could provide this list, but not necessarily.

3) Plugin Dependency list of plugin: each plugin could have dependency on some other plugins. So if a plugin needs another plugin to be executed correctly, then will warn the user to install the required plugin (user warned at install time, ).

4) open Priorities and Subpriorities developer list: we should have a public list for developers, about Priorities and Subpriorities used by each plugin. It would be placed on the web (E.g. on GT site), and each developer could submit, and change plugin priority data. This way we will *NEVER* have plugin priority conflicts. It is so easy...

But while the STOP_ORIGINAL action could partially resolve my current problem, there is still need for plugin execution ordering.
Just imagine, if we need page display timing. If the Timer_Page plugin will be executed after, my Xtended Link Display plugin, then it will not get the initial time point, so the final computer & displayed elapsed time will be wrong. Additionally Timer_Page plugin should be executed really as first plugin to measure correct time. Another reason why priority is still needed.


The bottom line is, that I aggree Yogi to add new actions, but I still uphold my opinion on my plugin execution order solution. My solution could make more flexible the plugin system (also I told, it is not a new idea, operation systems also use similar way to prioritize their processes).

About the FIRST or LAST options: I have the same experiance, I did not find any fingertips about the FIRST or LAST options in the core code. Maybe it was not implemented yet, but Alex wanted that the plugin developers use these options, to be able to use them, when later will be implemented.
Anyway, if I imagine how it would work, since it exists only in the installer.pm, the FIRST would be relative to the currently installed plugins, and depend on the order how the plugins are installed.
This behaviour of the current plugin system is wrong approach (IMPO). Also IMPO the FIRST or LAST options was an attempt to prioritize, order somehow the plugin execution process. Similar thing, what I would like.

Neither the installer.pm, neither the plugin system itself can not decide what priority & order to give for a plugin, it has not artificial intelligence. We (the plugin developers) must decide how and in what order our plugin should executed, to work fine and to be compatible with other plugins. Just imagine, if a plugin output is correctly a hash, but it passes values, what will not compatible with other plugins, there will be problem. But it may want to pass these values to finally display it in link.html or want to pass to another plugin which has -1 subpriority, so we can be sure it will pass to that plugin only.

I think my solution could be better than FIRST or LAST options. I'm not arrogant, please do not misunderstand me, I just know what solution could make my plugin working and make more cooperative with other's plugins, so all of them could be more plexibly executable. Yes, my solution would need sometimes a bit coordination, conversation between plugin developers about those plugins, which need extremly low or extremely high priorities. But most plugins (70-80%) will run under normal (3) priority, and order will not matter for them. Also the open Priorities and Subpriorities List would also solve a lot problems.

Best regards,
Webmaster33


Paid Support
from Webmaster33. Expert in Perl programming & Gossamer Threads applications. (click here for prices)
Webmaster33's products (upd.2004.09.26) | Private message | Contact me | Was my post helpful? Donate my help...