solr-connection.c revision 53ec1ff2231d477db3103c51987fa9cb6033bc16
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2006-2008 Dovecot authors, see the included COPYING file */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen/* curl: 7.16.0 curl_multi_timeout */
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen#include "lib.h"
0536ccb51d41e3078c3a9fa33e509fb4b2420f95Timo Sirainen#include "str.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "strescape.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include "solr-connection.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include <curl/curl.h>
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include <expat.h>
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainenenum solr_xml_response_state {
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen SOLR_XML_RESPONSE_STATE_ROOT,
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen SOLR_XML_RESPONSE_STATE_RESPONSE,
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen SOLR_XML_RESPONSE_STATE_RESULT,
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen SOLR_XML_RESPONSE_STATE_DOC,
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen SOLR_XML_RESPONSE_STATE_CONTENT
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen};
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainenenum solr_xml_content_state {
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen SOLR_XML_CONTENT_STATE_NONE = 0,
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen SOLR_XML_CONTENT_STATE_UID,
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen SOLR_XML_CONTENT_STATE_SCORE
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen};
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainenstruct solr_lookup_xml_context {
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen enum solr_xml_response_state state;
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen enum solr_xml_content_state content_state;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen int depth;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen ARRAY_TYPE(seq_range) *uids;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen};
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenstruct solr_connection_post {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct solr_connection *conn;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen const unsigned char *data;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen size_t size, pos;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen unsigned int failed:1;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen};
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainenstruct solr_connection {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen CURL *curl;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen CURLM *curlm;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen char curl_errorbuf[CURL_ERROR_SIZE];
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen struct curl_slist *headers, *headers_post;
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen XML_Parser xml_parser;
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen char *url;
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen char *http_failure;
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen unsigned int debug:1;
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen unsigned int posting:1;
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen unsigned int xml_failed:1;
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen};
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainenstatic size_t
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainencurl_output_func(void *data, size_t element_size, size_t nmemb, void *context)
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen{
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen struct solr_connection_post *post = context;
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen size_t size = element_size * nmemb;
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen /* @UNSAFE */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (size > post->size - post->pos)
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen size = post->size - post->pos;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen memcpy(data, post->data + post->pos, size);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen post->pos += size;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return size;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainenstatic int solr_xml_parse(struct solr_connection *conn,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const void *data, size_t size, bool done)
7db932bd4934cd967eeae643300aef5b91caeaeaTimo Sirainen{
7db932bd4934cd967eeae643300aef5b91caeaeaTimo Sirainen enum XML_Error err;
74066569545099304b20e790df7c261883d1746bTimo Sirainen int line;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (conn->xml_failed)
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen return -1;
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen if (XML_Parse(conn->xml_parser, data, size, done))
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen return 0;
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen err = XML_GetErrorCode(conn->xml_parser);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (err != XML_ERROR_FINISHED) {
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen line = XML_GetCurrentLineNumber(conn->xml_parser);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_error("fts_solr: Invalid XML input at line %d: %s",
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen line, XML_ErrorString(err));
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen conn->xml_failed = TRUE;
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen return -1;
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen }
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen return 0;
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen}
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainenstatic size_t
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainencurl_input_func(void *data, size_t element_size, size_t nmemb, void *context)
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen{
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen struct solr_connection *conn = context;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen size_t size = element_size * nmemb;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen (void)solr_xml_parse(conn, data, size, FALSE);
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen return size;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen}
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainenstatic size_t
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainencurl_header_func(void *data, size_t element_size, size_t nmemb, void *context)
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen{
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen struct solr_connection *conn = context;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen size_t size = element_size * nmemb;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen const unsigned char *p;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen size_t i;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
0892446b45c195461bb7be6599f02d97e1e2c9b2Timo Sirainen if (conn->http_failure != NULL)
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen return size;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen for (i = 0, p = data; i < size; i++) {
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen if (p[i] == ' ') {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i++;
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen break;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
9e095dd6a77097356aca8216356d4d71ef1bea45Timo Sirainen }
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen if (i == size || p[i] < '0' || p[i] > '9')
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen i = 0;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen conn->http_failure = i_strndup(p + i, size - i);
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen return size;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen}
0892446b45c195461bb7be6599f02d97e1e2c9b2Timo Sirainen
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainenstruct solr_connection *solr_connection_init(const char *url, bool debug)
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen{
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen struct solr_connection *conn;
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen conn = i_new(struct solr_connection, 1);
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen conn->url = i_strdup(url);
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen conn->debug = debug;
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen conn->curlm = curl_multi_init();
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen conn->curl = curl_easy_init();
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen if (conn->curl == NULL || conn->curlm == NULL) {
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen i_fatal_status(FATAL_OUTOFMEM,
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen "fts_solr: Failed to allocate curl");
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen }
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen /* set global curl options */
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen curl_easy_setopt(conn->curl, CURLOPT_ERRORBUFFER, conn->curl_errorbuf);
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen if (conn->debug)
e4c81823af1fc43ca3f2ce9eb4af7fc8f57b13a5Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_VERBOSE, 1L);
e4c81823af1fc43ca3f2ce9eb4af7fc8f57b13a5Timo Sirainen
2524ef7b34965a1b1895d6140fd8296bf57c78d2Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_NOPROGRESS, 1L);
0892446b45c195461bb7be6599f02d97e1e2c9b2Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_NOSIGNAL, 1L);
e4c81823af1fc43ca3f2ce9eb4af7fc8f57b13a5Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_READFUNCTION, curl_output_func);
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_WRITEFUNCTION, curl_input_func);
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_WRITEDATA, conn);
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_HEADERFUNCTION, curl_header_func);
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_HEADERDATA, conn);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen conn->headers = curl_slist_append(NULL, "Content-Type: text/xml");
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen conn->headers_post = curl_slist_append(NULL, "Content-Type: text/xml");
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen conn->headers_post = curl_slist_append(conn->headers_post,
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen "Transfer-Encoding: chunked");
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen conn->headers_post = curl_slist_append(conn->headers_post,
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen "Expect:");
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_HTTPHEADER, conn->headers);
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen conn->xml_parser = XML_ParserCreate("UTF-8");
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen if (conn->xml_parser == NULL) {
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen i_fatal_status(FATAL_OUTOFMEM,
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen "fts_solr: Failed to allocate XML parser");
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen }
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen return conn;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen}
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainenvoid solr_connection_deinit(struct solr_connection *conn)
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen{
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen curl_slist_free_all(conn->headers);
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen curl_slist_free_all(conn->headers_post);
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen curl_multi_cleanup(conn->curlm);
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen curl_easy_cleanup(conn->curl);
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen i_free(conn->url);
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen i_free(conn);
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen}
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainenvoid solr_connection_quote_str(struct solr_connection *conn, string_t *dest,
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen const char *str)
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen{
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen char *encoded;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen encoded = curl_easy_escape(conn->curl, str_escape(str), 0);
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen str_printfa(dest, "%%22%s%%22", encoded);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen curl_free(encoded);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic const char *attrs_get_name(const char **attrs)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
20344c0e814139e3c365fbb9287478f91512089eTimo Sirainen for (; *attrs != NULL; attrs += 2) {
20344c0e814139e3c365fbb9287478f91512089eTimo Sirainen if (strcmp(attrs[0], "name") == 0)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen return attrs[1];
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return "";
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic void
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainensolr_lookup_xml_start(void *context, const char *name, const char **attrs)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
20344c0e814139e3c365fbb9287478f91512089eTimo Sirainen struct solr_lookup_xml_context *ctx = context;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const char *name_attr;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen i_assert(ctx->depth >= (int)ctx->state);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen ctx->depth++;
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen if (ctx->depth - 1 > (int)ctx->state) {
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen /* skipping over unwanted elements */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen /* response -> result -> doc */
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen switch (ctx->state) {
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen case SOLR_XML_RESPONSE_STATE_ROOT:
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen if (strcmp(name, "response") == 0)
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen ctx->state++;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen break;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen case SOLR_XML_RESPONSE_STATE_RESPONSE:
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen if (strcmp(name, "result") == 0)
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen ctx->state++;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen break;
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen case SOLR_XML_RESPONSE_STATE_RESULT:
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen if (strcmp(name, "doc") == 0)
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen ctx->state++;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen break;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen case SOLR_XML_RESPONSE_STATE_DOC:
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen name_attr = attrs_get_name(attrs);
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen if (strcmp(name_attr, "uid") == 0)
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen ctx->content_state = SOLR_XML_CONTENT_STATE_UID;
601f5f14c6cde28f0e0c6ca7c5d735315d3d48dfTimo Sirainen else if (strcmp(name_attr, "score") == 0)
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen ctx->content_state = SOLR_XML_CONTENT_STATE_SCORE;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen else
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen break;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen ctx->state++;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen break;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen case SOLR_XML_RESPONSE_STATE_CONTENT:
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen break;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen }
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen}
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainenstatic void solr_lookup_xml_end(void *context, const char *name ATTR_UNUSED)
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct solr_lookup_xml_context *ctx = context;
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen i_assert(ctx->depth >= (int)ctx->state);
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen if (ctx->depth == (int)ctx->state) {
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen ctx->state--;
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen ctx->content_state = SOLR_XML_CONTENT_STATE_NONE;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen ctx->depth--;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainenstatic void solr_lookup_xml_data(void *context, const char *str, int len)
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen{
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen struct solr_lookup_xml_context *ctx = context;
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen uint32_t uid;
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen int i;
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen switch (ctx->content_state) {
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen case SOLR_XML_CONTENT_STATE_NONE:
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen break;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen case SOLR_XML_CONTENT_STATE_UID:
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen for (i = 0, uid = 0; i < len; i++) {
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen if (str[i] < '0' || str[i] > '9')
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen break;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen uid = uid*10 + str[i]-'0';
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen }
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen if (i != len) {
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen i_error("fts_solr: received invalid uid");
548e394330621952db0f03dd667b70184c4a37b6Timo Sirainen break;
548e394330621952db0f03dd667b70184c4a37b6Timo Sirainen }
7d207b1e77a7b5e3fda640e353acfc86d261fedfTimo Sirainen seq_range_array_add(ctx->uids, 0, uid);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen break;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen case SOLR_XML_CONTENT_STATE_SCORE:
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen /* FIXME */
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen break;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen }
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen}
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainenint solr_connection_select(struct solr_connection *conn, const char *query,
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen ARRAY_TYPE(seq_range) *uids)
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen{
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen struct solr_lookup_xml_context solr_lookup_context;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen string_t *str;
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen CURLcode ret;
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen long httpret;
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen i_assert(!conn->posting);
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen memset(&solr_lookup_context, 0, sizeof(solr_lookup_context));
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen solr_lookup_context.uids = uids;
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen i_free_and_null(conn->http_failure);
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen conn->xml_failed = FALSE;
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen XML_ParserReset(conn->xml_parser, "UTF-8");
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen XML_SetElementHandler(conn->xml_parser,
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen solr_lookup_xml_start, solr_lookup_xml_end);
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen XML_SetCharacterDataHandler(conn->xml_parser, solr_lookup_xml_data);
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen XML_SetUserData(conn->xml_parser, &solr_lookup_context);
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen
923115fd382904fa13bb09bf307bf2835b52df60Timo Sirainen str = t_str_new(256);
923115fd382904fa13bb09bf307bf2835b52df60Timo Sirainen str_append(str, conn->url);
923115fd382904fa13bb09bf307bf2835b52df60Timo Sirainen str_append(str, "select?");
923115fd382904fa13bb09bf307bf2835b52df60Timo Sirainen str_append(str, query);
923115fd382904fa13bb09bf307bf2835b52df60Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_URL, str_c(str));
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen ret = curl_easy_perform(conn->curl);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen if (ret != 0) {
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen i_error("fts_solr: HTTP GET failed: %s",
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen conn->curl_errorbuf);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen return -1;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen }
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen curl_easy_getinfo(conn->curl, CURLINFO_RESPONSE_CODE, &httpret);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen if (httpret != 200) {
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen i_error("fts_solr: Lookup failed: %s", conn->http_failure);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen ret = -1;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen }
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen return solr_xml_parse(conn, NULL, 0, TRUE);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen}
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainenstruct solr_connection_post *
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainensolr_connection_post_begin(struct solr_connection *conn)
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen{
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen struct solr_connection_post *post;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen CURLMcode merr;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen string_t *str;
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen post = i_new(struct solr_connection_post, 1);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen post->conn = conn;
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen i_assert(!conn->posting);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen conn->posting = TRUE;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen i_free_and_null(conn->http_failure);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_READDATA, post);
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen merr = curl_multi_add_handle(conn->curlm, conn->curl);
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen if (merr != CURLM_OK) {
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen i_error("fts_solr: curl_multi_add_handle() failed: %s",
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen curl_multi_strerror(merr));
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen post->failed = TRUE;
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen } else {
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen str = t_str_new(256);
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen str_append(str, conn->url);
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen str_append(str, "update");
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_URL, str_c(str));
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_HTTPHEADER,
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen conn->headers_post);
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_POST, (long)1);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
0611067f385a37773800225256dcd5cf6aa34212Timo Sirainen return post;
0611067f385a37773800225256dcd5cf6aa34212Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
0611067f385a37773800225256dcd5cf6aa34212Timo Sirainenvoid solr_connection_post_more(struct solr_connection_post *post,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const unsigned char *data, size_t size)
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainen{
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainen fd_set fdread;
b7651d283ca261015ef3c445f1f27f340f0864e2Timo Sirainen fd_set fdwrite;
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainen fd_set fdexcep;
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainen struct timeval timeout_tv;
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainen long timeout;
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen CURLMcode merr;
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainen int ret, handles, maxfd;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_assert(post->conn->posting);
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen if (post->failed)
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen return;
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen post->data = data;
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen post->size = size;
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen post->pos = 0;
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen for (;;) {
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen merr = curl_multi_perform(post->conn->curlm, &handles);
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen if (merr == CURLM_CALL_MULTI_PERFORM)
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen continue;
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen if (merr != CURLM_OK) {
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen i_error("fts_solr: curl_multi_perform() failed: %s",
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen curl_multi_strerror(merr));
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen break;
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if ((post->pos == post->size && post->size != 0) ||
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen (handles == 0 && post->size == 0)) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* everything sent successfully */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return;
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* everything wasn't sent - wait. just use select,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen since libcurl interface is easiest with it. */
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen FD_ZERO(&fdread);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen FD_ZERO(&fdwrite);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen FD_ZERO(&fdexcep);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen merr = curl_multi_fdset(post->conn->curlm, &fdread, &fdwrite,
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen &fdexcep, &maxfd);
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen if (merr != CURLM_OK) {
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen i_error("fts_solr: curl_multi_fdset() failed: %s",
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen curl_multi_strerror(merr));
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen break;
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen }
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen i_assert(maxfd >= 0);
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen merr = curl_multi_timeout(post->conn->curlm, &timeout);
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen if (merr != CURLM_OK) {
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen i_error("fts_solr: curl_multi_timeout() failed: %s",
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen curl_multi_strerror(merr));
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen break;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen if (timeout < 0) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen timeout_tv.tv_sec = 1;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen timeout_tv.tv_usec = 0;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen } else {
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen timeout_tv.tv_sec = timeout / 1000;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen timeout_tv.tv_usec = (timeout % 1000) * 1000;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen ret = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout_tv);
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen if (ret < 0) {
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen i_error("fts_solr: select() failed: %m");
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen break;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen post->failed = TRUE;
37ab3cde96bfa4bc5304c0c348fc420aec79572dTimo Sirainen}
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainenint solr_connection_post_end(struct solr_connection_post *post)
37ab3cde96bfa4bc5304c0c348fc420aec79572dTimo Sirainen{
37ab3cde96bfa4bc5304c0c348fc420aec79572dTimo Sirainen struct solr_connection *conn = post->conn;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen long httpret;
f4bbeadda12fbd7c219063db68f3e78646d83c2cTimo Sirainen int ret = post->failed ? -1 : 0;
0b47e9f5e0181053b4d9ca7b426b0e5c185e820eTimo Sirainen
0b47e9f5e0181053b4d9ca7b426b0e5c185e820eTimo Sirainen i_assert(conn->posting);
abe8754852e70763e92f74caabbcc13d0917714cTimo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen solr_connection_post_more(post, NULL, 0);
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen curl_easy_getinfo(conn->curl, CURLINFO_RESPONSE_CODE, &httpret);
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen if (httpret != 200 && ret == 0) {
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen i_error("fts_solr: Indexing failed: %s", conn->http_failure);
90b8f131849540fa374aede95edd86d47d35c09dTimo Sirainen ret = -1;
90b8f131849540fa374aede95edd86d47d35c09dTimo Sirainen }
90b8f131849540fa374aede95edd86d47d35c09dTimo Sirainen
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_READDATA, NULL);
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_POST, (long)0);
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_HTTPHEADER, conn->headers);
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen (void)curl_multi_remove_handle(conn->curlm, conn->curl);
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen i_free(post);
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen conn->posting = FALSE;
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen return ret;
90b8f131849540fa374aede95edd86d47d35c09dTimo Sirainen}
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenint solr_connection_post(struct solr_connection *conn, const char *cmd)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct solr_connection_post *post;
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen post = solr_connection_post_begin(conn);
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen solr_connection_post_more(post, (const unsigned char *)cmd,
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen strlen(cmd));
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen return solr_connection_post_end(post);
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen}
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen