Ema has submitted this change and it was merged.

Change subject: Remove loglines cache to mitigate a possible memory leak.
......................................................................


Remove loglines cache to mitigate a possible memory leak.

Varnishkafka3 leverages a bitmap int variable returned by the Varnish 3 API
to create a cache of loglines. This behavior is not present anymore in the
Varnish 4 API and the new log grouping features filled a lot of gaps that
varnishkafka had to overcome with ad hoc code. The loglines cache is completely
removed to use a single logline, initialized at startup and re-setted after each
request proceesed (eventually freed too).

Bug: T124278
Change-Id: I40c04ca91d9d31b4d0d735298f874ed6b883120d
---
M config.c
M varnishkafka.c
M varnishkafka.h
3 files changed, 22 insertions(+), 123 deletions(-)

Approvals:
  Ottomata: Looks good to me, but someone else must approve
  Ema: Verified; Looks good to me, approved
  BBlack: Looks good to me, but someone else must approve



diff --git a/config.c b/config.c
index 3987fe2..f15b227 100644
--- a/config.c
+++ b/config.c
@@ -191,10 +191,6 @@
                }
        } else if (!strcmp(name, "logline.data.copy"))
                conf.datacopy = conf_tof(val);
-       else if (!strcmp(name, "logline.hash.size"))
-               conf.loglines_hsize = atoi(val);
-       else if (!strcmp(name, "logline.hash.max"))
-               conf.loglines_hmax = atoi(val);
        else if (!strcmp(name, "logline.scratch.size"))
                conf.scratch_size = atoi(val);
        else if (!strcmp(name, "varnish.arg.q")) {
diff --git a/varnishkafka.c b/varnishkafka.c
index 02f399f..51d97fd 100644
--- a/varnishkafka.c
+++ b/varnishkafka.c
@@ -73,21 +73,10 @@
        [FMT_CONF_KEY]  = "Key"
 };
 
-/**
- * Logline cache
- */
-static struct {
-       LIST_HEAD(, logline) lps;    /* Current loglines in bucket */
-       int                  cnt;    /* Current number of loglines in bucket */
-       uint64_t             hit;    /* Cache hits */
-       uint64_t             miss;   /* Cache misses */
-       uint64_t             purge;  /* Cache entry purges (bucket full) */
-} *loglines;
-
-static int logline_cnt = 0; /* Current number of loglines in memory */
+/* logline accumulator reused across log transactions */
+struct logline *lp = NULL;
 
 static void logrotate(void);
-
 
 /**
  * Counters
@@ -111,7 +100,6 @@
               "\"trunc\":%"PRIu64", "
               "\"scratch_toosmall\":%"PRIu64", "
               "\"scratch_tmpbufs\":%"PRIu64", "
-              "\"lp_curr\":%i, "
               "\"seq\":%"PRIu64" "
               "} }\n",
               (unsigned long long)time(NULL),
@@ -121,7 +109,6 @@
               cnt.trunc,
               cnt.scratch_toosmall,
               cnt.scratch_tmpbufs,
-              logline_cnt,
               conf.sequence_number);
 }
 
@@ -1566,21 +1553,6 @@
        }
 }
 
-
-
-/**
- * Initialize log line lookup hash
- */
-static void loglines_init (void) {
-       loglines = calloc(sizeof(*loglines), conf.loglines_hsize);
-}
-
-/**
- * Returns the hash key (bucket) for a given log id
- */
-#define logline_hkey(id) ((id) % conf.loglines_hsize)
-
-
 /**
  * Resets the given logline and makes it ready for accumulating a new request.
  */
@@ -1589,10 +1561,8 @@
        struct tmpbuf *tmpbuf;
 
        /* Clear logline, except for scratch pad since it will be overwritten */
-
        for (i = 0 ; i < conf.fconf_cnt ; i++)
-               memset(lp->match[i], 0,
-                      conf.fconf[i].fmt_cnt * sizeof(*lp->match[i]));
+               memset(lp->match[i], 0, conf.fconf[i].fmt_cnt * 
sizeof(*lp->match[i]));
 
        /* Free temporary buffers */
        while ((tmpbuf = lp->tmpbuf)) {
@@ -1608,69 +1578,23 @@
 
        lp->seq       = 0;
        lp->sof       = 0;
-       lp->tags_seen = 0;
        lp->t_last    = time(NULL);
 }
 
 
 /**
- * Free up all loglines.
+ * Returns a new logline
  */
-static void loglines_term (void) {
-       unsigned int hkey;
-       for (hkey = 0 ; hkey < conf.loglines_hsize ; hkey++) {
-               struct logline *lp;
-               while ((lp = LIST_FIRST(&loglines[hkey].lps))) {
-                       logline_reset(lp);
-                       LIST_REMOVE(lp, link);
-                       free(lp);
-                       logline_cnt--;
-               }
-       }
-       free(loglines);
-}
-
-
-/**
- * Returns a logline.
- */
-static inline struct logline *logline_get (unsigned int id) {
-       struct logline *lp, *oldest = NULL;
-       unsigned int hkey = logline_hkey(id);
+static inline struct logline *logline_get () {
        int i;
        char *ptr;
-
-       LIST_FOREACH(lp, &loglines[hkey].lps, link) {
-               if (lp->id == id) {
-                       /* Cache hit: return existing logline */
-                       loglines[hkey].hit++;
-                       return lp;
-               } else if (loglines[hkey].cnt > conf.loglines_hmax &&
-                          lp->tags_seen &&
-                          (!oldest || lp->t_last < oldest->t_last)) {
-                       oldest = lp;
-               }
-       }
-
-       /* Cache miss */
-       loglines[hkey].miss++;
-
-       if (oldest) {
-               /* Remove oldest entry.
-                * We will not loose a log record here since this only
-                * matches when 'tags_seen' is zero. */
-               LIST_REMOVE(oldest, link);
-               loglines[hkey].cnt--;
-               loglines[hkey].purge++;
-               free(oldest);
-               logline_cnt--;
-       }
+       struct logline *lp;
 
        /* Allocate and set up new logline */
        lp = malloc(sizeof(*lp) + conf.scratch_size +
                    (conf.total_fmt_cnt * sizeof(*lp->match[0])));
        memset(lp, 0, sizeof(*lp));
-       lp->id = id;
+
        ptr = (char *)(lp+1) + conf.scratch_size;
        for (i = 0 ; i < conf.fconf_cnt ; i++) {
                size_t msize = conf.fconf[i].fmt_cnt * sizeof(*lp->match[i]);
@@ -1678,10 +1602,6 @@
                memset(lp->match[i], 0, msize);
                ptr += msize;
        }
-
-       LIST_INSERT_HEAD(&loglines[hkey].lps, lp, link);
-       loglines[hkey].cnt++;
-       logline_cnt++;
 
        return lp;
 }
@@ -1771,15 +1691,13 @@
  * A trasaction cursor (vsl.h) points to a list of tags associated with 
transaction id.
  * This function parses the current tag pointed by the cursor.
  */
-static int parse_tag (struct VSL_transaction *t, uint64_t bitmap)
+static int parse_tag(struct VSL_transaction *t)
 {
-       struct logline *lp;
        int    is_complete = 0;
 
        /* Data carried by the transaction's current cursor */
        enum VSL_tag_e tag = VSL_TAG(t->c->rec.ptr);
        const char * tag_data = VSL_CDATA(t->c->rec.ptr);
-       long vxid = VSL_ID(t->c->rec.ptr);
 
        /* Avoiding VSL_LEN to prevent \0 termination char
         * to be counted causing \u0000 to be displayed in JSON
@@ -1797,12 +1715,6 @@
         * it will be kept in case of future expansions.
         */
        int spec = VSL_CLIENT(t->c->rec.ptr) ? VSL_CLIENTMARKER : 
VSL_BACKENDMARKER;
-
-       if (unlikely(!(lp = logline_get(vxid))))
-               return -1;
-
-       /* Update bitfield of seen tags (-m regexp) */
-       lp->tags_seen |= bitmap;
 
        /* Truncate data if exceeding configured max */
        if (unlikely(len > conf.tag_size_max)) {
@@ -1852,15 +1764,14 @@
        struct VSL_transaction *t;
        /* Loop through the transations of the grouping */
        while ((t = *pt++)) {
+               /* Only client requests are allowed */
+               if (t->type != VSL_t_req)
+                       continue;
+               if (t->reason == VSL_r_esi)
+                       continue;
                /* loop through the tags */
-               uint64_t bitmap = 0;
                while (VSL_Next(t->c) == 1) {
-                       /* Only client requests are allowed */
-                       if (t->type != VSL_t_req)
-                               continue;
-                       if (t->reason == VSL_r_esi)
-                               continue;
-                       parse_tag(t, bitmap);
+                       parse_tag(t);
                }
        }
        return 0;
@@ -2027,8 +1938,6 @@
        conf.daemonize = 1;
        conf.datacopy  = 1;
        conf.tag_size_max   = 2048;
-       conf.loglines_hsize = 5000;
-       conf.loglines_hmax  = 5;
        conf.scratch_size   = 4096;
        conf.stats_interval = 60;
        conf.stats_file     = strdup("/tmp/varnishkafka.stats.json");
@@ -2162,9 +2071,6 @@
        if (conf.log_level >= 7)
                tag_dump();
 
-       /* Prepare logline cache */
-       loglines_init();
-
        /* Daemonize if desired */
        if (conf.daemonize) {
                if (daemon(0, 0) == -1) {
@@ -2260,6 +2166,10 @@
        wait_for.tv_nsec = 10000000L;
        int dispatch_status = 0;
 
+       /* Creating a new logline (will be re-used across log transactions) */
+       if (unlikely(!(lp = logline_get())))
+               return -1;
+
        while (conf.run) {
                dispatch_status = VSLQ_Dispatch(conf.vslq, transaction_scribe, 
NULL);
 
@@ -2297,7 +2207,6 @@
                rd_kafka_destroy(rk);
        }
 
-       loglines_term();
        print_stats();
 
        /* if stats_fp is set (i.e. open), close it. */
@@ -2308,9 +2217,11 @@
 
        free(conf.stats_file);
 
+       free(lp);
+
        rate_limiters_rollover(time(NULL));
 
        varnish_api_cleaning();
 
        exit(0);
-}
+}
\ No newline at end of file
diff --git a/varnishkafka.h b/varnishkafka.h
index 0e452d7..3191c18 100644
--- a/varnishkafka.h
+++ b/varnishkafka.h
@@ -74,19 +74,13 @@
 
 
 /**
- * Currently parsed logline(s)
+ * Currently parsed logline
  */
 struct logline {
        LIST_ENTRY(logline)  link;
 
-       /* Log id */
-       unsigned int  id;
-
        /* Per fmt_conf logline matches */
        struct match *match[FMT_CONF_NUM];
-
-       /* Tags seen (for -m regexp) */
-       uint64_t tags_seen;
 
        /* Sequence number */
        uint64_t seq;
@@ -191,8 +185,6 @@
        int         datacopy;
        fmt_enc_t   fmt_enc;
        int         total_fmt_cnt;
-       int         loglines_hsize;  /* Log id hash size */
-       int         loglines_hmax;   /* Max log ids per hash bucket */
        int         tag_size_max;    /* Maximum tag size to accept without
                                      * truncating it. */
 

-- 
To view, visit https://gerrit.wikimedia.org/r/276439
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I40c04ca91d9d31b4d0d735298f874ed6b883120d
Gerrit-PatchSet: 18
Gerrit-Project: operations/software/varnish/varnishkafka
Gerrit-Branch: master
Gerrit-Owner: Elukey <[email protected]>
Gerrit-Reviewer: BBlack <[email protected]>
Gerrit-Reviewer: Elukey <[email protected]>
Gerrit-Reviewer: Ema <[email protected]>
Gerrit-Reviewer: Ottomata <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to