From 9abf72e46aa5fdb536261e2f8ec3ac22cd909649 Mon Sep 17 00:00:00 2001 From: Leo Balduf Date: Sat, 18 Jun 2016 23:05:58 -0400 Subject: [PATCH] store: add README --- server/store/README.md | 43 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 server/store/README.md diff --git a/server/store/README.md b/server/store/README.md new file mode 100644 index 0000000..05ff3ff --- /dev/null +++ b/server/store/README.md @@ -0,0 +1,43 @@ +## The store Package + +The `store` package offers a storage interface and middlewares sufficient to run a public tracker based on it. + +### Architecture + +The store consists of three parts: +- A set of interfaces, tests based on these interfaces and the store logic, unifying these interfaces into the store +- Drivers, implementing the store interfaces and +- Middleware that depends on the store + +The store interfaces are `IPStore`, `PeerStore` and `StringStore`. +During runtime, each of them will be implemented by a driver. +Even though all different drivers for one interface provide the same functionality, their behaviour can be very different. +For example: The memory implementation keeps all state in-memory - this is very fast, but not persistent, it loses its state on every restart. +A database-backed driver on the other hand could provide persistence, at the cost of performance. + +The pluggable design of Chihaya allows for the different interfaces to use different drivers. +For example: A typical use case of the `StringStore` is to provide blacklists or whitelists for infohashes/client IDs/.... +You'd typically want these lists to be persistent, so you'd choose a driver that provides persistence. +The `PeerStore` on the other hand rarely needs to be persistent, as all peer state will be restored after one announce interval. +You'd therefore typically choose a very performant but non-persistent driver for the `PeerStore`. + +### Testing + +The main store package also contains a set of tests and benchmarks for drivers. +Both use the store interfaces and can work with any driver that implements these interfaces. +The tests verify that the driver behaves as specified by the interface and its documentation. +The benchmarks can be used to compare performance of a wide range of operations on the interfaces. + +This makes it very easy to implement a new driver: +All functions that are part of the store interfaces can be tested easily with the tests that come with the store package. +Generally the memory implementation can be used as a guideline for implementing new drivers. + +Both benchmarks and tests require a clean state to work correctly. +All of the test and benchmark functions therefore take a `*DriverConfig` as a parameter, this should be used to configure the driver in a way that it provides a clean state for every test or benchmark. +For example: Imagine a file-based driver that achieves persistence by storing its state in a file. +It must then be possible to provide the location of this file in the `'DriverConfig`, so that every different benchmark gets to work with a new file. + +Most benchmarks come in two flavors: The "normal" version and the "1K" version. +A normal benchmark uses the same value over and over again to benchmark one operation. +A 1K benchmark uses a different value from a set of 1000 values for every iteration, this can show caching effects, if the driver uses them. +The 1K benchmarks require a little more computation to select the values and thus typically yield slightly lower results even for a "perfect" cache, i.e. the memory implementation.