|a resource adapter||Is a adapter which gives each resource a common interface. This interface covers basic requirements such as closing a resource. ResourcePool::Resource acts as a base class for all resources.|
|a factory||Is used to construct resources on demand. Is usually not more than a storage of the required information to create a resource. ResourcePool::Factory acts as a base class for all factories.|
A resource adapter has to provide a generic interface to ResourcePool for your resource. This interface is used to interact with the resource. Some of the methods are optional, you can just skip them if you have carefully derived your own resource adapter from ResourcePool::Resource which will provide some defaults for you.
Each resource adapter manages exactly one resource. This means for example one database connection or whatever your resource might be. The pooling and management of more resources is done by ResourcePool and does not require any attention of your resource adapter.
I will describe the methods of this class in the order in which they are used by ResourcePool.
The normal life cycle of a resource adapter ends here. The remaining method are used to handle failure...
Constructor The constructor of a resource adapter will only be used from the according factory. You have all the freedom you can imagine for the prototype of the constructor (as you have it in every derived class in every programming language). I suggest to name your constructor new() (a perl convention, not a language requirement).
The actual work the constructor has to do is to create the resource (e.g. database connection) and storing it in its private data. If everything went fine the constructor must return its bless()ed reference. Otherwise you have the option to return undef to indicate that the creation of a resource failed.
If your constructor returns an object, ResourcePool will add this resource to its internal pool of available resources.
precheck This method is used to check the vitality of this resource. ResourcePool calls this method before it uses the resource to check its validity. ResourcePool will not use this resource any more if this method returns a false value.
The precheck() method is very important to the high availability functionality of ResourcePool and ResourcePool::LoadBalancer. This method, together with >, builds the backbone of the fault detection mechanism. If you want ResourcePool to detect broken resources you need to carefully implement this method to return a false value if the resource is not longer valid.
This method is most probably implemented by doing so nop (no operation) with the resource. Choose the cheapest non modifying operation possible and analyze its result. If everything is as expected return true otherwise false. (The DBI extension does a ping() to detect broken connections)
This method can also be used to implement some code which restores a state for this resource. This way you can guarantee a common state of the resources you obtain from ResourcePool. Imagine a database connection pool which guarantees you that AutoCommit is off on the handles you get from the pool, even if you have returned a connection where you manually changed the AutoCommit setting.
If your precheck() method returns a true value, ResourcePool will go on and supply the resource to the client code. Otherwise it will throw this resource away and performing the recovery as described in the ResourcePool documentation.
get_plain_resource This method just returns the internally stored resource. You have to return the actual resource you are implementing the adapter for. E.g. the DBI handle or whatever your extension manages. The return value of this method will be passed to the client code as return value of the get() method.
ResourcePool will than remove this resource from its list of available resources (so that a used resource can not be used simultaneously).
From the moment on where this method returns you lose control over this resource. Later, when you get back the resource from the client (which has called the free() method of ResourcePool) you can not make any assumptions of the state of the resource. The client could have done everything which can be done with this resource, including closing it (e.g. disconnecting from the database).
postcheck The postcheck() method is very similar to the previously described > method. The only difference is that the postcheck() method is called after the client has returned a resource to the pool.
As mentioned above, you can not make any assumptions of the state of the resource. The client could have done everything. As for the > method you can use this method also to place some code which restores the original state or doing some cleanup (e.g. a rollback() on a database connection).
ResourcePool will throw this resource away if this method returns a false value, otherwise ResourcePool will add this resource to its list of available resources and use it again if required (the cycle starts again with the precheck() method).
close This method is used (surprise surprise) to close the resource. Its called immediately before the resource adapter itself gets destroyed.
The following simplified call-graph tries to demonstrate the most important important processes which take place with your resource. Please note that this is reduced to the processes relevant to the resource adapter class.
fail_close This method is used to close a resource which is known to be broken (either because one of > or > failed or the client used the fail() method of ResourcePool to hand it back to the pool.
The difference to the > method is very subtle. For many resource there is no difference anyway. For some others you might want to skip some cleanup operations which will fail anyway if the resource is broken.
Client . ResourcePool and . resource adapter code . LoadBalancer . . . --------> get() ----------------------> precheck() -----------+ . . | . +------------------------<-----------------------+ . | on failure . . +------------------------> fail_close() ---------+ . | tries another . | . | available resource <---------------------------+ . | . . | on success . . +------------------------> get_plain_resource() -+ . . | --------<-----------------------------<-----------------------+ . . . . --------> free() ---------------------> postcheck() ----------+ . . | . +------------------------<-----------------------+ . | on failure . . +------------------------> fail_close() ---------| . | on success . . +--> Add back to pool . . . . . --------> fail() ---------------------> fail_close() ---------| . .
(the free() and fail() methods do return meaningful values which are in not directly related to the resource adapter implementation.)
The diagram is separated into three sections: the leftmost section represents the user code, this is the software which uses ResourcePool; the middle one represents the ResourcePool core. For this diagram it makes no difference if you are using ResourcePool::LoadBalancer as well; the right most section represents the resource adapter of the extension.
The purpose of a factory is to store information which is required to create a resource. The factory is constructed and configured by the user code and then passed to the ResourcePool on construction.
create_resource Returns a resource adapter (a ResourcePool::Resource derived class). ResourcePool uses this method to create new resources as required. As a result of the fact the the constructor of a resource adapter may fail and return undef, the create_resource method is also allowed to return undef. In that case ResourcePool would apply the error handling as configured. info This method is used if ResourcePool does some error reporting. You should return a human readable string which describes the resources which are created through this factory. For a database resource this could be the data-source name.
As you have learned every ResourcePool consists of two parts. The namespace where you should place this two packages are ResourcePool::Factory and ResourcePool::Resource. Below this two namespaces you should add the complete perl-class name for which resource your extension is. E.g. The Net::LDAP factory and resource adapter are called ResourcePool::Factory::Net::LDAP and ResourcePool::Resource::Net::LDAP.
If you upload you extension to CPAN you should name the package according to your resource adapter name.
The reality delivers the best examples. Please have a look into the implementation of the already existing extensions like DBI or Net::LDAP.
Copyright (C) 2001-2009 by Markus Winand <firstname.lastname@example.org> This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
|perl v5.20.3||RESOURCEPOOL::EXTENSIONGUIDE (3)||2009-11-25|