It's becoming clear that the Client Subsystem will be the most important addition to the core since the original completition of the hncore API's; a LOT of code will be depending on this subsystem, so it's critical that it gets done right the first time, since writing it twice will take 5x the time (5 modules depending on it). Hence, I'm not rushing into coding it until I have a clear underastanding of the subsystems responsibilities, requirements and design.
The Client subsystem will be composed of two classes - BaseClient class, from which plugins shall derive their customized Client's, and ClientManager singleton, which will provide various lookups and views to the clients listing. Those two classes will need to serve three purposes:
- Reduce duplicate code over plugins in related topics, such as chunk requests for example.
- Provide information about clients to user interfaces
- Provide various views about the clients listing (possibly spanning tens of thousands of objects).
The first bullet wasn't originally planned for the subsystem, however as I realized that the same chunk-request generation code has been copied verbatim from ed2k to bt to http, it clearly shows this must be generalized. A4AF handling, chunkmaps and similar should also be centralized into this BaseClient class to further reduce duplicate code over modules.
The second bullet is generally const virtual methods, providing access to various client data, including nicknames, software, protocol and so on. Plugins shall simply override the virtual functions to return their information.
The third could be considered hardest to implement. It will need either multiple different containers, or single multi_index container for the various views; the views must be kept up2date (which might impose some limitations on the BaseClient class API). It must be possible to look up all clients for a specific download, all connected clients, all clients with specific client software, all clients which have requested a specific file and so on. This will allow lot of interesting and custom views that user interfaces can then implement. Also, it should be considered that the listing may contain tens of thousands of objects, hence any kind of looping on the listing is completely out of the question.
An iterator-based interface for the ClientManager class could be a nice and clean solution, however I'm slightly concerned that if I expose multi_index_container and the iterators in the public interface, some of the testers on slower machines will be unable to compile Hydranode anymore - we did run into similar issue some some 4 months ago, when I was using multi_index containers in many places and exposed them in header files - memory and time requirements during compilation skyrocketed. To add to the problem, the derived Client classes are most often the largest classes in the module (ed2k one is 2500 lines, bt is 800), and they usually include a large set of hnbase and hncore headers already)... Lately, I'v used wrapper iterators, (
ed2k/downloadlist.h, DownloadList class), however this approach doesn't scale well. The alternative - using a combination of STL containers - is way too much of a nightmare - been there, done that, really don't want to go there anymore.
Edit: Actually, the above only affects ClientManager class, not BaseClient class; and ClientManager class will only be needed by ui modules (hnsh) and cgcomm module(s), so it's acceptable to expose multi_index_containers in the public API; BaseClient API will be very light-weight on the compiler/compile times.
Madcat, ZzZz