mirror of
https://github.com/owntone/owntone-server.git
synced 2025-03-20 12:34:18 -04:00
[cache] Save daap replies gzipped - should improve performance
This commit is contained in:
parent
249d923af2
commit
7dc2a46261
22
src/cache.c
22
src/cache.c
@ -38,6 +38,7 @@
|
|||||||
|
|
||||||
#include "conffile.h"
|
#include "conffile.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
|
#include "httpd.h"
|
||||||
#include "httpd_daap.h"
|
#include "httpd_daap.h"
|
||||||
#include "db.h"
|
#include "db.h"
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
@ -680,7 +681,8 @@ cache_daap_query_add(void *arg, int *retval)
|
|||||||
#undef Q_TMPL
|
#undef Q_TMPL
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Gets a reply from the cache */
|
// Gets a reply from the cache.
|
||||||
|
// cmdarg->evbuf will be filled with the reply (gzipped)
|
||||||
static enum command_state
|
static enum command_state
|
||||||
cache_daap_query_get(void *arg, int *retval)
|
cache_daap_query_get(void *arg, int *retval)
|
||||||
{
|
{
|
||||||
@ -783,6 +785,7 @@ cache_daap_update_cb(int fd, short what, void *arg)
|
|||||||
{
|
{
|
||||||
sqlite3_stmt *stmt;
|
sqlite3_stmt *stmt;
|
||||||
struct evbuffer *evbuf;
|
struct evbuffer *evbuf;
|
||||||
|
struct evbuffer *gzbuf;
|
||||||
char *errmsg;
|
char *errmsg;
|
||||||
char *query;
|
char *query;
|
||||||
int ret;
|
int ret;
|
||||||
@ -818,10 +821,23 @@ cache_daap_update_cb(int fd, short what, void *arg)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
cache_daap_reply_add(query, evbuf);
|
gzbuf = httpd_gzip_deflate(evbuf);
|
||||||
|
if (!gzbuf)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_CACHE, "Error gzipping DAAP reply for query: %s\n", query);
|
||||||
|
cache_daap_query_delete(sqlite3_column_int(stmt, 0));
|
||||||
free(query);
|
free(query);
|
||||||
evbuffer_free(evbuf);
|
evbuffer_free(evbuf);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
evbuffer_free(evbuf);
|
||||||
|
|
||||||
|
cache_daap_reply_add(query, gzbuf);
|
||||||
|
|
||||||
|
free(query);
|
||||||
|
evbuffer_free(gzbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret != SQLITE_DONE)
|
if (ret != SQLITE_DONE)
|
||||||
|
130
src/httpd.c
130
src/httpd.c
@ -139,68 +139,6 @@ struct stream_ctx *g_st;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static struct evbuffer *
|
|
||||||
gzip(struct evbuffer *in)
|
|
||||||
{
|
|
||||||
struct evbuffer *out;
|
|
||||||
struct evbuffer_iovec iovec[1];
|
|
||||||
z_stream strm;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
strm.zalloc = Z_NULL;
|
|
||||||
strm.zfree = Z_NULL;
|
|
||||||
strm.opaque = Z_NULL;
|
|
||||||
|
|
||||||
// Set up a gzip stream (the "+ 16" in 15 + 16), instead of a zlib stream (default)
|
|
||||||
ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY);
|
|
||||||
if (ret != Z_OK)
|
|
||||||
{
|
|
||||||
DPRINTF(E_LOG, L_HTTPD, "zlib setup failed: %s\n", zError(ret));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
strm.next_in = evbuffer_pullup(in, -1);
|
|
||||||
strm.avail_in = evbuffer_get_length(in);
|
|
||||||
|
|
||||||
out = evbuffer_new();
|
|
||||||
if (!out)
|
|
||||||
{
|
|
||||||
DPRINTF(E_LOG, L_HTTPD, "Could not allocate evbuffer for gzipped reply\n");
|
|
||||||
goto out_deflate_end;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For avoiding memcpy. We only reserve length of input buffer, since we don't
|
|
||||||
// want to gzip if the result is larger than raw
|
|
||||||
ret = evbuffer_reserve_space(out, strm.avail_in, iovec, 1);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
DPRINTF(E_LOG, L_HTTPD, "Could not reserve memory for gzipped reply\n");
|
|
||||||
goto out_evbuf_free;
|
|
||||||
}
|
|
||||||
|
|
||||||
strm.next_out = iovec[0].iov_base;
|
|
||||||
strm.avail_out = iovec[0].iov_len;
|
|
||||||
|
|
||||||
ret = deflate(&strm, Z_FINISH);
|
|
||||||
if (ret != Z_STREAM_END)
|
|
||||||
goto out_evbuf_free;
|
|
||||||
|
|
||||||
iovec[0].iov_len -= strm.avail_out;
|
|
||||||
|
|
||||||
evbuffer_commit_space(out, iovec, 1);
|
|
||||||
deflateEnd(&strm);
|
|
||||||
|
|
||||||
return out;
|
|
||||||
|
|
||||||
out_evbuf_free:
|
|
||||||
evbuffer_free(out);
|
|
||||||
|
|
||||||
out_deflate_end:
|
|
||||||
deflateEnd(&strm);
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
stream_end(struct stream_ctx *st, int failed)
|
stream_end(struct stream_ctx *st, int failed)
|
||||||
{
|
{
|
||||||
@ -755,6 +693,69 @@ httpd_stream_file(struct evhttp_request *req, int id)
|
|||||||
free_mfi(mfi, 0);
|
free_mfi(mfi, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct evbuffer *
|
||||||
|
httpd_gzip_deflate(struct evbuffer *in)
|
||||||
|
{
|
||||||
|
struct evbuffer *out;
|
||||||
|
struct evbuffer_iovec iovec[1];
|
||||||
|
z_stream strm;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
strm.zalloc = Z_NULL;
|
||||||
|
strm.zfree = Z_NULL;
|
||||||
|
strm.opaque = Z_NULL;
|
||||||
|
|
||||||
|
// Set up a gzip stream (the "+ 16" in 15 + 16), instead of a zlib stream (default)
|
||||||
|
ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY);
|
||||||
|
if (ret != Z_OK)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_HTTPD, "zlib setup failed: %s\n", zError(ret));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
strm.next_in = evbuffer_pullup(in, -1);
|
||||||
|
strm.avail_in = evbuffer_get_length(in);
|
||||||
|
|
||||||
|
out = evbuffer_new();
|
||||||
|
if (!out)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_HTTPD, "Could not allocate evbuffer for gzipped reply\n");
|
||||||
|
goto out_deflate_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We use this to avoid a memcpy. The 512 is an arbitrary padding to make sure
|
||||||
|
// there is enough space, even if the compressed output should be slightly
|
||||||
|
// larger than input (could happen with small inputs).
|
||||||
|
ret = evbuffer_reserve_space(out, strm.avail_in + 512, iovec, 1);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_HTTPD, "Could not reserve memory for gzipped reply\n");
|
||||||
|
goto out_evbuf_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
strm.next_out = iovec[0].iov_base;
|
||||||
|
strm.avail_out = iovec[0].iov_len;
|
||||||
|
|
||||||
|
ret = deflate(&strm, Z_FINISH);
|
||||||
|
if (ret != Z_STREAM_END)
|
||||||
|
goto out_evbuf_free;
|
||||||
|
|
||||||
|
iovec[0].iov_len -= strm.avail_out;
|
||||||
|
|
||||||
|
evbuffer_commit_space(out, iovec, 1);
|
||||||
|
deflateEnd(&strm);
|
||||||
|
|
||||||
|
return out;
|
||||||
|
|
||||||
|
out_evbuf_free:
|
||||||
|
evbuffer_free(out);
|
||||||
|
|
||||||
|
out_deflate_end:
|
||||||
|
deflateEnd(&strm);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Thread: httpd */
|
/* Thread: httpd */
|
||||||
void
|
void
|
||||||
httpd_send_reply(struct evhttp_request *req, int code, const char *reason, struct evbuffer *evbuf, enum httpd_send_flags flags)
|
httpd_send_reply(struct evhttp_request *req, int code, const char *reason, struct evbuffer *evbuf, enum httpd_send_flags flags)
|
||||||
@ -782,8 +783,10 @@ httpd_send_reply(struct evhttp_request *req, int code, const char *reason, struc
|
|||||||
if (origin && strlen(origin))
|
if (origin && strlen(origin))
|
||||||
evhttp_add_header(output_headers, "Access-Control-Allow-Origin", origin);
|
evhttp_add_header(output_headers, "Access-Control-Allow-Origin", origin);
|
||||||
|
|
||||||
if (do_gzip && (gzbuf = gzip(evbuf)))
|
if (do_gzip && (gzbuf = httpd_gzip_deflate(evbuf)))
|
||||||
{
|
{
|
||||||
|
DPRINTF(E_DBG, L_HTTPD, "Gzipping response\n");
|
||||||
|
|
||||||
evhttp_add_header(output_headers, "Content-Encoding", "gzip");
|
evhttp_add_header(output_headers, "Content-Encoding", "gzip");
|
||||||
evhttp_send_reply(req, code, reason, gzbuf);
|
evhttp_send_reply(req, code, reason, gzbuf);
|
||||||
evbuffer_free(gzbuf);
|
evbuffer_free(gzbuf);
|
||||||
@ -793,7 +796,6 @@ httpd_send_reply(struct evhttp_request *req, int code, const char *reason, struc
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DPRINTF(E_DBG, L_HTTPD, "Not gzipping response\n");
|
|
||||||
evhttp_send_reply(req, code, reason, evbuf);
|
evhttp_send_reply(req, code, reason, evbuf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,10 @@ enum httpd_send_flags
|
|||||||
void
|
void
|
||||||
httpd_stream_file(struct evhttp_request *req, int id);
|
httpd_stream_file(struct evhttp_request *req, int id);
|
||||||
|
|
||||||
|
// Returns a pointer to an evbuffer with gzipped. Must be freed by caller.
|
||||||
|
struct evbuffer *
|
||||||
|
httpd_gzip_deflate(struct evbuffer *in);
|
||||||
|
|
||||||
void
|
void
|
||||||
httpd_send_reply(struct evhttp_request *req, int code, const char *reason, struct evbuffer *evbuf, enum httpd_send_flags flags);
|
httpd_send_reply(struct evhttp_request *req, int code, const char *reason, struct evbuffer *evbuf, enum httpd_send_flags flags);
|
||||||
|
|
||||||
|
@ -2853,7 +2853,9 @@ daap_request(struct evhttp_request *req)
|
|||||||
ret = cache_daap_get(full_uri, evbuf);
|
ret = cache_daap_get(full_uri, evbuf);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
{
|
{
|
||||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0); // TODO not all want this reply
|
// The cache will return the data gzipped, so httpd_send_reply won't need to do it
|
||||||
|
evhttp_add_header(headers, "Content-Encoding", "gzip");
|
||||||
|
httpd_send_reply(req, HTTP_OK, "OK", evbuf, HTTPD_SEND_NO_GZIP); // TODO not all want this reply
|
||||||
|
|
||||||
evbuffer_free(evbuf);
|
evbuffer_free(evbuf);
|
||||||
free(uri);
|
free(uri);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user