
How plugins work
----------------

All plugins in the `libraries/plugins` directory are iterated over by `CMakeLists.txt`. The manifest directory iterates through all plugins, adding them to the `hive_plugins` build target. Any other build target wanting to access all plugins
available at build time should link to this target.

There is a plugin in `example_plugins` called `example_api_plugin` which is a working example of adding a custom API call.

Registering plugins
-------------------

- Plugins are enabled with the `plugins` config file option.
- By default, hived runs the `chain`, `p2p`, and `webserver` plugins.
- Some plugins may keep records in the database (such as `account_history`).  If you change whether such a plugin is disabled/enabled, you should also replay the chain. Detecting this situation and automatically replaying when needed will be implemented in a future release.
- To make an API visible, include the associated plugin in the `plugins` config file option. Only APIs explicitly made available through the config will be registered.

Autogenerating code
-------------------

A skeleton structure containing much of the boilerplate of creating a new plugin with an API can be autogenerated by running `programs/util/newplugin.py`.

- Register signal handlers and custom evaluators in `plugin_initialize()` (if needed)
- Register APIs in `plugin_initialize()`
- API plugins should be separate from the stateful plugin they grant access to. This allows for the API to be disabled while keeping track of state for the plugin.

Startup/Shutdown of Plugins
---------------------------

- Plugins can specify dependencies with the `APPBASE_PLUGIN_REQUIRES` macro, which takes a bubble list of dependencies.
- There is undefined behavior if there are circular dependencies. Be careful how you design the data flow between plugins to eliminate circular dependencies.
- `plugin_initialze` and `plugin_startup` both guarantee that any dependencies are already initialized or started before the dependent plugin is called.
- `plugin_shutdown` is called in the reverse order from startup. Any dependencies will still be running when shutdown is called.
- You can get a reference to a plugin with `appbase::app().get_plugin< PLUIGN >()` or a pointer with `appbase::app().find_plugin< PLUGIN >()`. get_plugin will fail and find_plugin will return a nullptr if the plugin is not registered or has not been initialized. These methods guarantee you are accessing initialized date.
- Because of the inialization order, it is safe to call get/find_plugin on dependencies in initialization, startup, and shutdown.
- It is only safe to call get/find_plugin on an optional dependency in startup. An optional dependency is not explicitly specified. It is simply some optional behavior if a plugin is enabled. See `condenser_api` for an example of optional dependencies.

Asynchronous APIs
-----------------

-The json rpc plugin dispatches API requests asynchronously. This means your API call can be preempted or delayed and must be designed with parallelism in mind.
- To help, chainbase provides a simple read/write locking mechanism: `with_read_lock` and `with_write_lock`.
- This is a global lock over the entire database.
- The methods take a lambda that will be protected with the lock. For most API calls, `with_read_lock` will be sufficient.
- To ensure consistent block times, the read lock automatically expires after 1 second. Design your API call with this in mind. If the API call takes longer than 1 second, your results are undefined. It is best to create limitations on the API call to ensure it does not take longer than 1 second to execute (shorter than 250ms is preferable).
