Subject Re: [Firebird-Architect] External Engines (and Plugins)
Author Vlad Khorsun
Adriano dos Santos Fernandes :
> Vlad Khorsun escreveu:
>> As we defining our own API we free to do anything we wish. Any "language"
>> plugin author are free to redefine rules for its own wrapper. I know few Delphi
>> components set and all of them used zero-based indexes and have no problems with
>> it (remember Delphi ? its Pascal for which zero-based arrays is not natural). I
>> really wonder why our C++ based API must have such not-natural behavior...
>>
> Java array index is 0 based, but SQL index are 1 based. 1 based index
> for SQL is much more common (even in 0 based languages). IBPP also uses
> 1-based indexes.

This is your expirience. My expirience show use of 0 based indexes even in "1
based languages". What should we do ? Create public discussion, ask IEEE, ask
UN, or listen our own brain ? :)

>>> For ExternaEngine and for future INTL plugin, yes. For Trace, I don't
>>> know exactly how it works. But imagine a plugin that wants to receive
>>> these events:
>>> - engineInitialized
>>> - engineShutingDown
>>>
>>> There is no factory for it. It should be:
>>> class EngineListener
>>> {
>>> virtual void engineInitialized() = 0;
>>> virtual void engineShutingDown() = 0;
>>> };
>>>
>>> void Plugin::setEngineListener(EngineListener*);
>>>
>> This is auto-load plugin which will receive notification in its constructor and
>> second notification in destructor or using new fb_shutdown_callback call.
>>
> Plugin is object constructed and destructed by FB. It can't receive
> notifications on destructor.

User library implements factory which creates some user-defined object. This
object have constructor, destructor (or its equivalents) and able to use
fb_shutdown_callback. Is it clean now ?

>>>>>> It seems for me it is better to introduce enumeration of
>>>>>> known plugin types and create only universal method to register all kinds of
>>>>>> factories, such as
>>>>>>
>>>>>> Plugin::registerFactory(PluginKind, PluginFactory).
>>>>>>
>>>>>>
>>>>>>
>>>>> This will cause a plugin to extend a whole set of methods to just do one
>>>>> thing.
>>>>>
>>>>>
>>>> I don't understand, explain please.
>>>>
>>>>
>>> class PluginFactoryImpl : public PluginFactory
>>> {
>>> virtual createExternalEngine...
>>> virtual createCharacterSet... // this is EE plugin, but need to
>>> override all PluginFactory
>>> };
>>>
>>> And if you want to extend PluginFactory for each PluginKind, it doesn't
>>> differ much from current design.
>>>
>> It seems we again lost understanding of each other. I offer following:
>>
>> 1. Change your ExternalEngineFactory interface by
>>
>> class PluginFactory
>> {
>> public:
>> virtual Plugin* FB_CALL createPlugin(Error*, const char** args) = 0;
>> }
>>
>> 2. Rename your Plugin interface to PluginManager and change its
>> setExternalEngineFactory method by
>>
>> class PluginManager
>> {
>> public:
>>
>> ...
>> enum PluginKind {pkExternalEngine, pkTrace, pkIntl, ...};
>>
>> virtual void FB_CALL registerPluginFactory(PluginKind kind, PluginFactory*
>> factory) = 0;
>> }
>>
>> 3. Firebird have PluginManager implementation and passed it into
>> PluginEntryPoint function when plugin library is loaded.
>>
>> 4. Plugin library implemented PluginFactory interface for each kind of contained
>> plugin and passed instance of each factory into obtained at PluginEntryPoint
>> function PluginManager::registerPluginFactory method.
>>
>> 5. PluginManager have all necessary additional methods (or interfaces) which may
>> be used by any plugin.
>>
> I see no advantage. Just some class/method rename and inability to have
> non-factories plugins.

It not forced us to introduce methods in PluginManager for every new plugin
kind supported by the engine. I think its good and correct approach. Also i see
no sence to introduce PluginFactory interface and allow to not use it. And i see
important task to name things correctly - generic plugin API must be separate
from all other XXX API's.

>>>> So, you offer to declare as many REPLICATE triggers as destination datasources
>>>> and mark each of them by corresponding datasource name in <misc info> ? I don't
>>>> think its OK. Instead i would put all destinations names into separate table and
>>>> read this table in one REPLICATE trigger.
> No. Example was with one trigger per table. It just encode info
> necessary to the trigger work in the entrypoint.

Imagine i have N destinations. How must i change your trigger example, to
replicate to the all of them ?

> Otherwise a new table
> should be created mapping trigger metadata names to misc info.

And remove <misc info> from trigger declaration ?

Regards,
Vlad