Be TaskManager Documentation |
The plugin interface of Be TaskManager allows you to define additional performance information, which can be added to the performance view. This information is represented in an hierarchical namespace. Objects in the namespace are called "performance counter". These performane counter objects contain information needed to display the namespace in a hierachical listview. Each object also contains a "data provider". This object is queryed to display your performance information inside the graph view. This object returns the current value of the performance data.
The plugin API is inspired by COM. Therefore it seperates interface and implementation. If you aren't familiar with COM: an interface is simply a pure abstract base class. Implementing an interface means to derive a class from the interface base class and implement all is pure virtual functions.
This preliminary information and subject to change. I will ensure neigher binary nor source compablility with this interface. One of the next versions of Be TaskManager will include the final version of the plugin interface. Don't use this in production code.
Implement this interface to create your own performance counter. A performance counter is simply an object in the hierarchical namespace. Through this interface the user (this means: Be TaskManager) can request the children of this performance counter and its name and path.
There are two name for a performance counter: "internal name" and display name. The internal name is used to compose the path of the object and therefore has to be unique. The display name is displayed to the user and needs not to be unique. For example: if you want to display all teams in the namespace, you would use the name of the team as display name and the team id (because it's unique) as internal name. The internal name of a performance counter can be requested through InternalName(), the display name through Name().
ChildAt() and CountChildren() are normally implemented by calling the namespace's EnumChildren() and storing the returned children in a BList. The performance counter is responsible for deleting its children, when the object is destroyed.
class IPerformanceCounter
{
public:
IPerformanceCounter() {}
virtual ~IPerformanceCounter() {}
virtual int32 CountChildren() = 0;
virtual IPerformanceCounter *ChildAt(int32 i) = 0;
virtual IDataProvider *DataProvider() = 0;
virtual const char *Name() const = 0;
virtual const char *Path() const = 0;
virtual const char *InternalName() const = 0;
};
The following example shows a generic implementation of this interface:
|
You don't need to implement this interface. It's implemented by the taskmanager and passed to you as parameter.
You normally don't call any other method than EnumChildren. This method iterates over all plugins and calls their EnumChildren function. See IPerformanceCounterPlugin for details.
class IPerformanceCounterNamespace
{
public:
IPerformanceCounterNamespace() {}
virtual ~IPerformanceCounterNamespace() {}
virtual status_t EnumChildren(const char *path, BList *children) = 0;
virtual IDataProvider *DataProvider(const char *path) = 0;
virtual IPerformanceCounter *Root() = 0;
};
This interface allows you to add additional objects to the namespace. By implementing the EnumChildren function you can add new nodes to the namespace.
class IPerformanceCounterPlugin
{
public:
IPerformanceCounterPlugin() {}
virtual ~IPerformanceCounterPlugin() {}
virtual status_t EnumChildren(IPerformanceCounterNamespace *counterNamespace, const char *path, BList *children) = 0;
};
This example implementation adds two new nodes to the namespace. It uses the generic implementation of IPerformanceCounter shown above:
|
Every time the current value of your performance information object is needed Be TaskManager calls the function IDataProvider::GetNextValue(). This value is displayed to the user in the graph view. The implemenation of GetNextValue() is very simple. Simply set the passed reference ('value') to the current value. Return true if the call was successful, false if it wasn't. If you return false you should set value to 0.0 before you return.
The function Clone() returns an exact clone of the object. Equal() compares two data providers. If they are equal it returns true. Note: Don't simply compare pointers the when you implement this function. First try to cast the passed object to your implementation class (using dynamic_cast). If this succeeds you should compare all members.
class IDataProvider
{
public:
IDataProvider() {}
virtual ~IDataProvider() {}
virtual bool GetNextValue(float &value) = 0;
virtual uint32 Flags() = 0;
virtual uint32 Unit() = 0;
virtual BString DisplayName() = 0;
virtual IDataProvider *Clone() = 0;
virtual bool Equal(IDataProvider *other) = 0;
enum enumFlags {
DP_TYPE_ABSOLUTE = 1,
DP_TYPE_RELATIVE = 2,
DP_TYPE_PERCENT = 4,
DT_TYPE_HIDDEN = 8,
};
enum enumUnit {
DP_UNIT_NONE,
DP_UNIT_BYTE,
DP_UNIT_KILOBYTE,
DP_UNIT_MEGABYTE,
DP_UNIT_PAGES,
DP_UNIT_RPM,
DP_UNIT_DEGREES,
DP_UNIT_VOLT,
DP_UNIT_WATT,
DP_UNIT_AMPERE,
};
};
Flags:
DP_TYPE_ABSOLUTE | The value returned by GetNextValue() is used "as-is" |
DP_TYPE_RELATIVE | The returned value is divided by the time between the the last two calls of GetNextValue() in milliseconds. |
DP_TYPE_PERCENT | The returned value is multiplyed by 100, before it's displayed to the user. If the result is out of the range [0,100] it is restricted to that range. |
DT_TYPE_HIDDEN | Currently unused. |
The meaning of the unit value should be clear. The returned value is currently only used to display the correct unit symbol. The only exception is DP_UNIT_PAGES. If that unit is used the returned value is converted to kilobytes (multiplyed by B_PAGE_SIZE/1024) before it is displayed to the user.
A plugin is implemented as shared library. Be TaskManager loads all shared libraries in the "add_ons" directory during startup. Then it loads the exported function "CreateCounterPlugin" and calls it. That function must be declared like this:
extern "C" status_t __declspec(dllexport) CreateCounterPlugin(IPerformanceCounterPlugin **plugin);
Example implementation:
|
If you implement IDataProvider you normally should derive the implementation class from BArchivable. This is necessary because the data provider objects get archived, when the view is replicated. If your data provider isn't derived from BArchivable, it isn't displayed in the replicant.
To implement an archivable data provider follow the following steps:
Example implementation:
|
If you need more information about how to write plugins simply write me an email. I will help you asap.