diff --git a/docs/error-utils/data_structures/hash_table.md b/docs/error-utils/data_structures/hash_table.md new file mode 100644 index 0000000..9f62213 --- /dev/null +++ b/docs/error-utils/data_structures/hash_table.md @@ -0,0 +1,24 @@ +# Hash table + +One of the main problems with how the errors are defined is that their total number +cannot be set from inside the library and dynamic memory allocation should be avoided. + +To solve this problems an **hash table** with **open addressing** is used. + +!!! Info The hash function used by the library is the 32 bit version of the +**MurmurHash3** implementation, for details refer to [MurmurHash](https://en.wikipedia.org/wiki/MurmurHash) + +When a new error is set its hash value is calculated based on the type and its +instance, then the calculated value is used as the index for the hash table. \ +If a collision happens the next index is calculated using **quadratic probing** +as described by this formula: `next_index = (curr_index + (offset * offset)) % buffer_size` +where the `offset` is the number of collisions and the `buffer_size` variable +is the size of the hash table. + +When an error is reset it's not removed completely from the hash table but can +be replaced with another when needed. + +The advantages of the MurmurHash algorithm is that it takes as input a 32 bit +integer **seed** (which is the error type in our case) and a **stream of bytes** +(which is the error instance), and it is suitable for generic hash-based lookup +like in the case of this library. diff --git a/docs/error-utils/data_structures/heap.md b/docs/error-utils/data_structures/heap.md new file mode 100644 index 0000000..8e80577 --- /dev/null +++ b/docs/error-utils/data_structures/heap.md @@ -0,0 +1,23 @@ +# Heap + +To handle the expiration mechanism of the errors it is needed to get the error +with the **minimum remaining amount of time** before it expire, keeping it possible +to do fast insertion and removal. + +One possible solution would be to sort each error every time it is set or reset +but, in the worst case scenario, it could take a lot of time to do that. + +To solve this problem a separate data structure containing pointer to the errors +is **partially sorted** keeping the minimum element at the first index of the structure; +this structure is a [min heap](https://it.wikipedia.org/wiki/Heap_(struttura_dati)) +with a static array implementation. + +When an error is set a reference to that error is pushed at the end of the heap +and than it is swapped with its parent until it restores the properties of the heap. + +When an error is reset the referenced to that error is swapped with the last element +of the heap and removed, and then the properties of the heap are restored. + +Every time the first element (the minimum) is updated the expire handler is also +updated as well, except for the case in which no errors are running where the +expire handler is stopped. diff --git a/docs/error-utils/error_utils.md b/docs/error-utils/error_utils.md new file mode 100644 index 0000000..b575f6f --- /dev/null +++ b/docs/error-utils/error_utils.md @@ -0,0 +1,36 @@ +# Error utils + +The main purpose of this library is to handle **critical errors** that should +expire after a given time from the moment they were set. + +A critical error is defined as an abnormal situation that should be notified to +the system and can be uniquely identified by a **type**, defined by the user, +and an **instance** that should identify the cause of the error. + +The error instance can be a constant string (useful to give meaning to the instance) +or an integer (useful to enumarate and iterate multiple instances). + +There are three main operations that can be done with an error: +1. **Set** +2. **Reset** +3. **Expire** + +If an error is set the current *timestamp* is saved and an expire handler (usually a timer) +is started or updated. +If a running error is reset it cannot expire anymore, in that case the expire handler +is updated or stopped if there are no running errors. +If an error expires the system is notified through a callback, the expired error +is reset and the expire handler is updated or stopped. + +!!! Important The exipre handler has to be defined and handled by the user, +this library only defines a couple of interfaces and does not manage +the handler internally. + +--- + +The internal structure of the error utils library takes advantage of **two data +structures** to achieve fast insertion, deletion and search: +1. [Hash table](data_structures/hash_table.md): to handle error insertion(*set*) +and deletion(*reset*) +2. [Min heap](data_structures/heap.md): to handle the expire mechanism and sort +the errors based on their expiration time