<commit_before>/*
 * Caching HTTP responses.
 *
 * author: <NAME> <<EMAIL>>
 */

#include "http-cache-internal.h"
#include "http-request.h"
#include "header-writer.h"
#include "strmap.h"
#include "http-response.h"
#include "uri-address.h"
#include "strref2.h"
#include "growing-buffer.h"
#include "tpool.h"
#include "http-util.h"
#include "async.h"
#include "background.h"

#include <string.h>
#include <time.h>
#include <stdlib.h>

struct http_cache {
    pool_t pool;
    struct cache *cache;
    struct memcached_stock *memcached_stock;
    struct hstock *tcp_stock;

    struct list_head requests;

    struct background_manager background;
};

struct http_cache_flush {
    struct background_job background;
};

struct http_cache_request {
    struct list_head siblings;

    pool_t pool, caller_pool;

#ifndef NDEBUG
    struct pool_notify caller_pool_notify;
#endif

    /**
     * The cache object which got this request.
     */
    struct http_cache *cache;
    http_method_t method;
    struct uri_with_address *uwa;
    const char *url;

    /** headers from the original request */
    struct strmap *headers;

    struct http_response_handler_ref handler;

    /**
     * Information on the request passed to http_cache_request().
     */
    struct http_cache_info *info;

    /**
     * The document which was found in the cache, in case this is a
     * request to test the validity of the cache entry.  If this is
     * NULL, then we had a cache miss.
     */
    struct http_cache_document *document;

    /**
     * The response body from the http_cache_document.  This is not
     * used for the heap backend: it creates the #istream_t on demand
     * with http_cache_heap_istream().
     */
    istream_t document_body;

    /**
     * This struct holds response information while this module
     * receives the response body.
     */
    struct {
        http_status_t status;
        struct strmap *headers;

        /**
         * The response body istream we got from the http_request()
         * callback.
         */
        istream_t input;

        /**
         * The current size of #output.  We could use
         * growing_buffer_size() here, but that would be too
         * expensive.
         */
        size_t length;

        /**
         * A sink for the response body, read from #input.
         */
        struct growing_buffer *output;
    } response;

    struct async_operation operation;
    struct async_operation_ref async_ref;
};

static void
http_cache_memcached_put_callback(void *ctx)
{
    struct http_cache_request *request = ctx;

    list_remove(&request->siblings);
}

static void
http_cache_put(struct http_cache_request *request)
{
    assert(request != NULL);
    assert(request->info != NULL);

    cache_log(4, "http_cache: put %s\n", request->url);

    if (request->cache->cache != NULL)
        http_cache_heap_put(request->cache->cache, request->cache->pool, request->url,
                            request->info, request->headers, request->response.status,
                            request->response.headers, request->response.output);
    else if (request->cache->memcached_stock != NULL) {
        list_add(&request->siblings, &request->cache->requests);

        http_cache_memcached_put(request->pool, request->cache->memcached_stock,
                                 request->cache->pool,
                                 &request->cache->background,
                                 request->url,
                                 request->info,
                                 request->headers,
                                 request->response.status, request->response.headers,
                                 growing_buffer_istream(request->response.output),
                                 http_cache_memcached_put_callback, request,
                                 &request->async_ref);
    }
}

static void
http_cache_remove(struct http_cache *cache, const char *url,
                  struct http_cache_document *document)
{
    if (cache->cache != NULL)
        http_cache_heap_remove(cache->cache, url, document);
}

static void
http_cache_remove_url(struct http_cache *cache, const char *url,
                      struct strmap *headers)
{
    if (cache->cache != NULL)
        http_cache_heap_remove_url(cache->cache, url, headers);
    else if (cache->memcached_stock != NULL)<commit_msg>http-cache: create background job for memcached SET<commit_after>/*
 * Caching HTTP responses.
 *
 * author: <NAME> <<EMAIL>>
 */

#include "http-cache-internal.h"
#include "http-request.h"
#include "header-writer.h"
#include "strmap.h"
#include "http-response.h"
#include "uri-address.h"
#include "strref2.h"
#include "growing-buffer.h"
#include "tpool.h"
#include "http-util.h"
#include "async.h"
#include "background.h"

#include <string.h>
#include <time.h>
#include <stdlib.h>

struct http_cache {
    pool_t pool;
    struct cache *cache;
    struct memcached_stock *memcached_stock;
    struct hstock *tcp_stock;

    struct list_head requests;

    struct background_manager background;
};

struct http_cache_flush {
    struct background_job background;
};

struct http_cache_request {
    struct list_head siblings;

    pool_t pool, caller_pool;

#ifndef NDEBUG
    struct pool_notify caller_pool_notify;
#endif

    /**
     * The cache object which got this request.
     */
    struct http_cache *cache;
    http_method_t method;
    struct uri_with_address *uwa;
    const char *url;

    /** headers from the original request */
    struct strmap *headers;

    struct http_response_handler_ref handler;

    /**
     * Information on the request passed to http_cache_request().
     */
    struct http_cache_info *info;

    /**
     * The document which was found in the cache, in case this is a
     * request to test the validity of the cache entry.  If this is
     * NULL, then we had a cache miss.
     */
    struct http_cache_document *document;

    /**
     * The response body from the http_cache_document.  This is not
     * used for the heap backend: it creates the #istream_t on demand
     * with http_cache_heap_istream().
     */
    istream_t document_body;

    /**
     * This struct holds response information while this module
     * receives the response body.
     */
    struct {
        http_status_t status;
        struct strmap *headers;

        /**
         * The response body istream we got from the http_request()
         * callback.
         */
        istream_t input;

        /**
         * The current size of #output.  We could use
         * growing_buffer_size() here, but that would be too
         * expensive.
         */
        size_t length;

        /**
         * A sink for the response body, read from #input.
         */
        struct growing_buffer *output;
    } response;

    struct async_operation operation;
    struct async_operation_ref async_ref;
};

static void
http_cache_memcached_put_callback(void *ctx)
{
    struct background_job *job = ctx;
    background_manager_remove(job);
}

static void
http_cache_put(struct http_cache_request *request)
{
    assert(request != NULL);
    assert(request->info != NULL);

    cache_log(4, "http_cache: put %s\n", request->url);

    if (request->cache->cache != NULL)
        http_cache_heap_put(request->cache->cache, request->cache->pool, request->url,
                            request->info, request->headers, request->response.status,
                            request->response.headers, request->response.output);
    else if (request->cache->memcached_stock != NULL) {
        struct background_job *job = p_malloc(request->pool, sizeof(*job));

        http_cache_memcached_put(request->pool, request->cache->memcached_stock,
                                 request->cache->pool,
                                 &request->cache->background,
                                 request->url,
                                 request->info,
                                 request->headers,
                                 request->response.status, request->response.headers,
                                 growing_buffer_istream(request->response.output),
                                 http_cache_memcached_put_callback, job,
                                 background_job_add(&request->cache->background,
                                                    job));
    }
}

static void
http_cache_remove(struct http_cache *cache, const char *url,
                  struct http_cache_document *document)
{
    if (cache->cache != NULL)
        http_cache_heap_remove(cache->cache, url, document);
}

static void
http_cache_remove_url(struct http_cache *cache, const char *url,
                      struct strmap *headers)
{
    if (cache->cache != NULL)
        http_cache_heap_remove_url(cache->cache, url, headers);
    else if (cache->memcached_stock != NULL)
{'fraction_non_alphanumeric': 0.09725657746795592, 'fraction_numerical': 0.00044974139869574995, 'mean_word_length': 2.239257101238165, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 91, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 20, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '607595', 'n_tokens_mistral': 2506, 'n_tokens_neox': 2467, 'n_words': 671}