/* This file is part of vmod-tbf Copyright (C) 2013-2018 Sergey Poznyakoff Vmod-tbf is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. Vmod-tbf is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with vmod-tbf. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include "vsha256.h" #include "pthread.h" #if VARNISHAPI_MAJOR > 5 # include # include # include #else # include # include # include # include #endif #define WSPTR(s) ((s)->ws) #ifndef USEC_PER_SEC # define USEC_PER_SEC 1000000L #endif #define DEBUG 1 struct dump_header { uint32_t version; uint32_t debug; uint32_t size; uint32_t count; uint32_t root; }; #define DUMP_VERSION 0 enum { CHILD_LEFT, CHILD_RIGHT }; #define FL_CHILD_LEFT 0x1 #define FL_CHILD_RIGHT 0x2 enum node_status { NST_INCOMPLETE, NST_INIT }; struct node { uint8_t key[SHA256_LEN]; #ifdef DEBUG char *keystr; #endif struct node *parent; /* Parent node */ struct node *child[2]; /* Left and right child nodes */ struct node *prev, *next; /* More (prev) and less (next) recently updated nodes. */ pthread_cond_t notbusy; /* Prevent simultaneous updates */ int busy:1; /* Node is in use if 1 */ enum node_status status; /* Node status */ uint32_t ord; /* Used when dumping nodes and computing tree stats */ /* Actual TBF payload: */ uint64_t timestamp; /* microseconds since epoch */ size_t tokens; /* tokens available */ }; struct tree { /* Root node of the tree */ struct node *root; /* All nodes are linked in a LRU fashion, head pointing to the most recently used, and tail to the last recently used ones. */ struct node *head, *tail; pthread_mutex_t mutex; size_t refcnt; }; enum node_lookup_result { NODE_FOUND, NODE_NEW };