solr-connection.c revision acc4e0a41f1c8ef0559a19c280afc1b97b9e0818
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (c) 2006-2008 Dovecot authors, see the included COPYING file */
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch/* curl: 7.16.0 curl_multi_timeout */
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#include "lib.h"
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#include "array.h"
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#include "str.h"
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#include "strescape.h"
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#include "solr-connection.h"
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
6d573191bea1a64d6046be070487a5705a2d0204Stephan Bosch#include <curl/curl.h>
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#include <expat.h>
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen
7384b4e78eaab44693c985192276e31322155e32Stephan Boschenum solr_xml_response_state {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch SOLR_XML_RESPONSE_STATE_ROOT,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch SOLR_XML_RESPONSE_STATE_RESPONSE,
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen SOLR_XML_RESPONSE_STATE_RESULT,
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen SOLR_XML_RESPONSE_STATE_DOC,
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen SOLR_XML_RESPONSE_STATE_CONTENT
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen};
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainenenum solr_xml_content_state {
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen SOLR_XML_CONTENT_STATE_NONE = 0,
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen SOLR_XML_CONTENT_STATE_UID,
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen SOLR_XML_CONTENT_STATE_SCORE,
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen SOLR_XML_CONTENT_STATE_MAILBOX,
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen SOLR_XML_CONTENT_STATE_UIDVALIDITY
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch};
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstruct solr_lookup_xml_context {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch enum solr_xml_response_state state;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch enum solr_xml_content_state content_state;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch int depth;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch uint32_t uid, uidvalidity;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch float score;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch char *mailbox;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch solr_uid_map_callback_t *callback;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch void *context;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch ARRAY_TYPE(seq_range) *uids;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch ARRAY_TYPE(fts_score_map) *scores;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch};
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstruct solr_connection_post {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch struct solr_connection *conn;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch const unsigned char *data;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch size_t size, pos;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch unsigned int failed:1;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch};
c6494255de7b934281dd052960fd8ab5aa48e79eTimo Sirainen
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstruct solr_connection {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch CURL *curl;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch CURLM *curlm;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch char curl_errorbuf[CURL_ERROR_SIZE];
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch struct curl_slist *headers, *headers_post;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch XML_Parser xml_parser;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch char *url;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch char *http_failure;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch unsigned int debug:1;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch unsigned int posting:1;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch unsigned int xml_failed:1;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch};
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstatic size_t
7384b4e78eaab44693c985192276e31322155e32Stephan Boschcurl_output_func(void *data, size_t element_size, size_t nmemb, void *context)
069def4dc35022852d569b7ab75a3b19d2cb0f1cTimo Sirainen{
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch struct solr_connection_post *post = context;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch size_t size = element_size * nmemb;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
6d573191bea1a64d6046be070487a5705a2d0204Stephan Bosch /* @UNSAFE */
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (size > post->size - post->pos)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch size = post->size - post->pos;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch memcpy(data, post->data + post->pos, size);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch post->pos += size;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch return size;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch}
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstatic int solr_xml_parse(struct solr_connection *conn,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch const void *data, size_t size, bool done)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch{
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch enum XML_Error err;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch int line;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (conn->xml_failed)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch return -1;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (XML_Parse(conn->xml_parser, data, size, done))
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch return 0;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
fe681e6db72f30bd754b622005bbe298e5ca775aTimo Sirainen err = XML_GetErrorCode(conn->xml_parser);
fe681e6db72f30bd754b622005bbe298e5ca775aTimo Sirainen if (err != XML_ERROR_FINISHED) {
fe681e6db72f30bd754b622005bbe298e5ca775aTimo Sirainen line = XML_GetCurrentLineNumber(conn->xml_parser);
fe681e6db72f30bd754b622005bbe298e5ca775aTimo Sirainen i_error("fts_solr: Invalid XML input at line %d: %s",
fe681e6db72f30bd754b622005bbe298e5ca775aTimo Sirainen line, XML_ErrorString(err));
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch conn->xml_failed = TRUE;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch return -1;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch }
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch return 0;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch}
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstatic size_t
fb1be3de0159d6a10e916ad992e2bc53be64c6d5Timo Sirainencurl_input_func(void *data, size_t element_size, size_t nmemb, void *context)
fb1be3de0159d6a10e916ad992e2bc53be64c6d5Timo Sirainen{
fb1be3de0159d6a10e916ad992e2bc53be64c6d5Timo Sirainen struct solr_connection *conn = context;
6bc9fb43cc1ac24693d030a6cbfa43bc7cbc82cbTimo Sirainen size_t size = element_size * nmemb;
6bc9fb43cc1ac24693d030a6cbfa43bc7cbc82cbTimo Sirainen
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen (void)solr_xml_parse(conn, data, size, FALSE);
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen return size;
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen}
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstatic size_t
7384b4e78eaab44693c985192276e31322155e32Stephan Boschcurl_header_func(void *data, size_t element_size, size_t nmemb, void *context)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch{
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch struct solr_connection *conn = context;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch size_t size = element_size * nmemb;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch const unsigned char *p;
fc94140acba51adafedafbc8491a3223a51db7a8Stephan Bosch size_t i;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (conn->http_failure != NULL)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch return size;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch for (i = 0, p = data; i < size; i++) {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (p[i] == ' ') {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch i++;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch break;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch }
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch }
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (i == size || p[i] < '0' || p[i] > '9')
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch i = 0;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch conn->http_failure = i_strndup(p + i, size - i);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch return size;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch}
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstruct solr_connection *solr_connection_init(const char *url, bool debug)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch{
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch struct solr_connection *conn;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch conn = i_new(struct solr_connection, 1);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch conn->url = i_strdup(url);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch conn->debug = debug;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch conn->curlm = curl_multi_init();
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch conn->curl = curl_easy_init();
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (conn->curl == NULL || conn->curlm == NULL) {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch i_fatal_status(FATAL_OUTOFMEM,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch "fts_solr: Failed to allocate curl");
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch }
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch /* set global curl options */
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch curl_easy_setopt(conn->curl, CURLOPT_ERRORBUFFER, conn->curl_errorbuf);
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch if (conn->debug)
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch curl_easy_setopt(conn->curl, CURLOPT_VERBOSE, 1L);
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch curl_easy_setopt(conn->curl, CURLOPT_NOPROGRESS, 1L);
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch curl_easy_setopt(conn->curl, CURLOPT_NOSIGNAL, 1L);
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch curl_easy_setopt(conn->curl, CURLOPT_READFUNCTION, curl_output_func);
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch curl_easy_setopt(conn->curl, CURLOPT_WRITEFUNCTION, curl_input_func);
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch curl_easy_setopt(conn->curl, CURLOPT_WRITEDATA, conn);
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch curl_easy_setopt(conn->curl, CURLOPT_HEADERFUNCTION, curl_header_func);
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch curl_easy_setopt(conn->curl, CURLOPT_HEADERDATA, conn);
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch conn->headers = curl_slist_append(NULL, "Content-Type: text/xml");
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch conn->headers_post = curl_slist_append(NULL, "Content-Type: text/xml");
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch conn->headers_post = curl_slist_append(conn->headers_post,
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch "Transfer-Encoding: chunked");
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch conn->headers_post = curl_slist_append(conn->headers_post,
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch "Expect:");
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch curl_easy_setopt(conn->curl, CURLOPT_HTTPHEADER, conn->headers);
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch conn->xml_parser = XML_ParserCreate("UTF-8");
b99130e4cf4af4e6b103b949456222f3a2dff424Timo Sirainen if (conn->xml_parser == NULL) {
b99130e4cf4af4e6b103b949456222f3a2dff424Timo Sirainen i_fatal_status(FATAL_OUTOFMEM,
b99130e4cf4af4e6b103b949456222f3a2dff424Timo Sirainen "fts_solr: Failed to allocate XML parser");
b99130e4cf4af4e6b103b949456222f3a2dff424Timo Sirainen }
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch return conn;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch}
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Boschvoid solr_connection_deinit(struct solr_connection *conn)
6d573191bea1a64d6046be070487a5705a2d0204Stephan Bosch{
6d573191bea1a64d6046be070487a5705a2d0204Stephan Bosch curl_slist_free_all(conn->headers);
6d573191bea1a64d6046be070487a5705a2d0204Stephan Bosch curl_slist_free_all(conn->headers_post);
6d573191bea1a64d6046be070487a5705a2d0204Stephan Bosch curl_multi_cleanup(conn->curlm);
6d573191bea1a64d6046be070487a5705a2d0204Stephan Bosch curl_easy_cleanup(conn->curl);
6d573191bea1a64d6046be070487a5705a2d0204Stephan Bosch i_free(conn->url);
6d573191bea1a64d6046be070487a5705a2d0204Stephan Bosch i_free(conn);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch}
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Boschvoid solr_connection_quote_str(struct solr_connection *conn, string_t *dest,
4521d35c263add6af3f1ae55b3760291767ce50cTimo Sirainen const char *str)
4521d35c263add6af3f1ae55b3760291767ce50cTimo Sirainen{
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch char *encoded;
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch encoded = curl_easy_escape(conn->curl, str_escape(str), 0);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch str_printfa(dest, "%%22%s%%22", encoded);
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen curl_free(encoded);
4521d35c263add6af3f1ae55b3760291767ce50cTimo Sirainen}
4521d35c263add6af3f1ae55b3760291767ce50cTimo Sirainen
4521d35c263add6af3f1ae55b3760291767ce50cTimo Sirainenstatic const char *attrs_get_name(const char **attrs)
4521d35c263add6af3f1ae55b3760291767ce50cTimo Sirainen{
4521d35c263add6af3f1ae55b3760291767ce50cTimo Sirainen for (; *attrs != NULL; attrs += 2) {
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen if (strcmp(attrs[0], "name") == 0)
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen return attrs[1];
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen }
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen return "";
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch}
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainenstatic void
7384b4e78eaab44693c985192276e31322155e32Stephan Boschsolr_lookup_xml_start(void *context, const char *name, const char **attrs)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch{
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch struct solr_lookup_xml_context *ctx = context;
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen const char *name_attr;
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen i_assert(ctx->depth >= (int)ctx->state);
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen ctx->depth++;
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen if (ctx->depth - 1 > (int)ctx->state) {
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch /* skipping over unwanted elements */
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch return;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch }
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch /* response -> result -> doc */
6d573191bea1a64d6046be070487a5705a2d0204Stephan Bosch switch (ctx->state) {
6d573191bea1a64d6046be070487a5705a2d0204Stephan Bosch case SOLR_XML_RESPONSE_STATE_ROOT:
6d573191bea1a64d6046be070487a5705a2d0204Stephan Bosch if (strcmp(name, "response") == 0)
6d573191bea1a64d6046be070487a5705a2d0204Stephan Bosch ctx->state++;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch break;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch case SOLR_XML_RESPONSE_STATE_RESPONSE:
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (strcmp(name, "result") == 0)
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch ctx->state++;
57962a937b214be3a131f78005509afaa26fe4bfTimo Sirainen break;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch case SOLR_XML_RESPONSE_STATE_RESULT:
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (strcmp(name, "doc") == 0) {
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch ctx->state++;
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch ctx->uid = 0;
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch ctx->score = 0;
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch i_free_and_null(ctx->mailbox);
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch ctx->uidvalidity = 0;
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch }
6bc9fb43cc1ac24693d030a6cbfa43bc7cbc82cbTimo Sirainen break;
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch case SOLR_XML_RESPONSE_STATE_DOC:
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch name_attr = attrs_get_name(attrs);
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch if (strcmp(name_attr, "uid") == 0)
069b28a2ef54072a221fe4ac67aaeb4e83fee6c1Timo Sirainen ctx->content_state = SOLR_XML_CONTENT_STATE_UID;
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch else if (strcmp(name_attr, "score") == 0)
791fb70b3255a11a91ce0c2dc3ae1460d4cf8459Timo Sirainen ctx->content_state = SOLR_XML_CONTENT_STATE_SCORE;
791fb70b3255a11a91ce0c2dc3ae1460d4cf8459Timo Sirainen else if (strcmp(name_attr, "box") == 0)
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch ctx->content_state = SOLR_XML_CONTENT_STATE_MAILBOX;
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch else if (strcmp(name_attr, "uidv") == 0)
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch ctx->content_state = SOLR_XML_CONTENT_STATE_UIDVALIDITY;
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch else
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch break;
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch ctx->state++;
a4e186e3ef267fc7a6b592788067c8c9c87d0785Stephan Bosch break;
a4e186e3ef267fc7a6b592788067c8c9c87d0785Stephan Bosch case SOLR_XML_RESPONSE_STATE_CONTENT:
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch break;
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch }
069b28a2ef54072a221fe4ac67aaeb4e83fee6c1Timo Sirainen}
069b28a2ef54072a221fe4ac67aaeb4e83fee6c1Timo Sirainen
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Boschstatic void solr_lookup_add_doc(struct solr_lookup_xml_context *ctx)
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch{
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch struct fts_score_map *score;
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch if (ctx->uid == 0) {
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch i_error("fts_solr: Query didn't return uid");
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch return;
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch }
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch if (ctx->callback != NULL) {
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch if (ctx->mailbox == NULL) {
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch i_error("fts_solr: Query didn't return mailbox");
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch return;
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch }
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch if (!ctx->callback(ctx->mailbox, ctx->uidvalidity,
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch &ctx->uid, ctx->context))
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch return;
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch }
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch seq_range_array_add(ctx->uids, 0, ctx->uid);
069b28a2ef54072a221fe4ac67aaeb4e83fee6c1Timo Sirainen if (ctx->scores != NULL && ctx->score != 0) {
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch score = array_append_space(ctx->scores);
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch score->uid = ctx->uid;
99feb6521535a7dc59d8dda89981ceac084b3e88Timo Sirainen score->score = ctx->score;
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch }
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch}
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Boschstatic void solr_lookup_xml_end(void *context, const char *name ATTR_UNUSED)
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch{
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch struct solr_lookup_xml_context *ctx = context;
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch i_assert(ctx->depth >= (int)ctx->state);
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch if (ctx->depth == (int)ctx->state) {
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch if (ctx->state == SOLR_XML_RESPONSE_STATE_DOC)
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch solr_lookup_add_doc(ctx);
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch ctx->state--;
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch ctx->content_state = SOLR_XML_CONTENT_STATE_NONE;
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch }
fb025942616dfec7770455a7092d01f2e516314dTimo Sirainen ctx->depth--;
fb025942616dfec7770455a7092d01f2e516314dTimo Sirainen}
fb025942616dfec7770455a7092d01f2e516314dTimo Sirainen
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Boschstatic int uint32_parse(const char *str, int len, uint32_t *value_r)
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch{
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch uint32_t value = 0;
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch int i;
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch for (i = 0; i < len; i++) {
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch if (str[i] < '0' || str[i] > '9')
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch break;
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch value = value*10 + str[i]-'0';
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch }
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch if (i != len)
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch return -1;
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch *value_r = value;
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch return 0;
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch}
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Boschstatic void solr_lookup_xml_data(void *context, const char *str, int len)
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch{
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch struct solr_lookup_xml_context *ctx = context;
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch char *new_name;
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch switch (ctx->content_state) {
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch case SOLR_XML_CONTENT_STATE_NONE:
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch break;
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch case SOLR_XML_CONTENT_STATE_UID:
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch if (uint32_parse(str, len, &ctx->uid) < 0)
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch i_error("fts_solr: received invalid uid");
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch break;
069b28a2ef54072a221fe4ac67aaeb4e83fee6c1Timo Sirainen case SOLR_XML_CONTENT_STATE_SCORE:
069b28a2ef54072a221fe4ac67aaeb4e83fee6c1Timo Sirainen T_BEGIN {
069b28a2ef54072a221fe4ac67aaeb4e83fee6c1Timo Sirainen ctx->score = strtod(t_strndup(str, len), NULL);
069b28a2ef54072a221fe4ac67aaeb4e83fee6c1Timo Sirainen } T_END;
069b28a2ef54072a221fe4ac67aaeb4e83fee6c1Timo Sirainen break;
069b28a2ef54072a221fe4ac67aaeb4e83fee6c1Timo Sirainen case SOLR_XML_CONTENT_STATE_MAILBOX:
069b28a2ef54072a221fe4ac67aaeb4e83fee6c1Timo Sirainen /* this may be called multiple times, for example if input
069b28a2ef54072a221fe4ac67aaeb4e83fee6c1Timo Sirainen contains '&' characters */
069b28a2ef54072a221fe4ac67aaeb4e83fee6c1Timo Sirainen new_name = ctx->mailbox == NULL ? i_strndup(str, len) :
069b28a2ef54072a221fe4ac67aaeb4e83fee6c1Timo Sirainen i_strconcat(ctx->mailbox, t_strndup(str, len), NULL);
069b28a2ef54072a221fe4ac67aaeb4e83fee6c1Timo Sirainen i_free(ctx->mailbox);
069b28a2ef54072a221fe4ac67aaeb4e83fee6c1Timo Sirainen ctx->mailbox = new_name;
069b28a2ef54072a221fe4ac67aaeb4e83fee6c1Timo Sirainen break;
a4e186e3ef267fc7a6b592788067c8c9c87d0785Stephan Bosch case SOLR_XML_CONTENT_STATE_UIDVALIDITY:
a4e186e3ef267fc7a6b592788067c8c9c87d0785Stephan Bosch if (uint32_parse(str, len, &ctx->uidvalidity) < 0)
a4e186e3ef267fc7a6b592788067c8c9c87d0785Stephan Bosch i_error("fts_solr: received invalid uidvalidity");
a4e186e3ef267fc7a6b592788067c8c9c87d0785Stephan Bosch break;
a4e186e3ef267fc7a6b592788067c8c9c87d0785Stephan Bosch }
a4e186e3ef267fc7a6b592788067c8c9c87d0785Stephan Bosch}
a4e186e3ef267fc7a6b592788067c8c9c87d0785Stephan Bosch
a4e186e3ef267fc7a6b592788067c8c9c87d0785Stephan Boschint solr_connection_select(struct solr_connection *conn, const char *query,
a4e186e3ef267fc7a6b592788067c8c9c87d0785Stephan Bosch solr_uid_map_callback_t *callback, void *context,
a4e186e3ef267fc7a6b592788067c8c9c87d0785Stephan Bosch ARRAY_TYPE(seq_range) *uids,
99feb6521535a7dc59d8dda89981ceac084b3e88Timo Sirainen ARRAY_TYPE(fts_score_map) *scores)
99feb6521535a7dc59d8dda89981ceac084b3e88Timo Sirainen{
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch struct solr_lookup_xml_context solr_lookup_context;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch string_t *str;
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen CURLcode ret;
99feb6521535a7dc59d8dda89981ceac084b3e88Timo Sirainen long httpret;
a4e186e3ef267fc7a6b592788067c8c9c87d0785Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch i_assert(!conn->posting);
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen
667de5cf294d833b3d47dd455bacff4fd68dd146Timo Sirainen memset(&solr_lookup_context, 0, sizeof(solr_lookup_context));
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch solr_lookup_context.uids = uids;
a4e186e3ef267fc7a6b592788067c8c9c87d0785Stephan Bosch solr_lookup_context.scores = scores;
a4e186e3ef267fc7a6b592788067c8c9c87d0785Stephan Bosch solr_lookup_context.callback = callback;
a4e186e3ef267fc7a6b592788067c8c9c87d0785Stephan Bosch solr_lookup_context.context = context;
fb025942616dfec7770455a7092d01f2e516314dTimo Sirainen
fb025942616dfec7770455a7092d01f2e516314dTimo Sirainen i_free_and_null(conn->http_failure);
99feb6521535a7dc59d8dda89981ceac084b3e88Timo Sirainen conn->xml_failed = FALSE;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch XML_ParserReset(conn->xml_parser, "UTF-8");
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch XML_SetElementHandler(conn->xml_parser,
99feb6521535a7dc59d8dda89981ceac084b3e88Timo Sirainen solr_lookup_xml_start, solr_lookup_xml_end);
50d1446e71cfbdc5b6d7bafcf91b7bff453989d3Stephan Bosch XML_SetCharacterDataHandler(conn->xml_parser, solr_lookup_xml_data);
50d1446e71cfbdc5b6d7bafcf91b7bff453989d3Stephan Bosch XML_SetUserData(conn->xml_parser, &solr_lookup_context);
50d1446e71cfbdc5b6d7bafcf91b7bff453989d3Stephan Bosch
50d1446e71cfbdc5b6d7bafcf91b7bff453989d3Stephan Bosch str = t_str_new(256);
50d1446e71cfbdc5b6d7bafcf91b7bff453989d3Stephan Bosch str_append(str, conn->url);
50d1446e71cfbdc5b6d7bafcf91b7bff453989d3Stephan Bosch str_append(str, "select?");
50d1446e71cfbdc5b6d7bafcf91b7bff453989d3Stephan Bosch str_append(str, query);
50d1446e71cfbdc5b6d7bafcf91b7bff453989d3Stephan Bosch
99feb6521535a7dc59d8dda89981ceac084b3e88Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_URL, str_c(str));
99feb6521535a7dc59d8dda89981ceac084b3e88Timo Sirainen ret = curl_easy_perform(conn->curl);
99feb6521535a7dc59d8dda89981ceac084b3e88Timo Sirainen if (ret != 0) {
a4e186e3ef267fc7a6b592788067c8c9c87d0785Stephan Bosch i_error("fts_solr: HTTP GET failed: %s",
99feb6521535a7dc59d8dda89981ceac084b3e88Timo Sirainen conn->curl_errorbuf);
50d1446e71cfbdc5b6d7bafcf91b7bff453989d3Stephan Bosch return -1;
99feb6521535a7dc59d8dda89981ceac084b3e88Timo Sirainen }
99feb6521535a7dc59d8dda89981ceac084b3e88Timo Sirainen curl_easy_getinfo(conn->curl, CURLINFO_RESPONSE_CODE, &httpret);
99feb6521535a7dc59d8dda89981ceac084b3e88Timo Sirainen if (httpret != 200) {
a4e186e3ef267fc7a6b592788067c8c9c87d0785Stephan Bosch i_error("fts_solr: Lookup failed: %s", conn->http_failure);
99feb6521535a7dc59d8dda89981ceac084b3e88Timo Sirainen ret = -1;
99feb6521535a7dc59d8dda89981ceac084b3e88Timo Sirainen }
99feb6521535a7dc59d8dda89981ceac084b3e88Timo Sirainen return solr_xml_parse(conn, NULL, 0, TRUE);
99feb6521535a7dc59d8dda89981ceac084b3e88Timo Sirainen}
a4e186e3ef267fc7a6b592788067c8c9c87d0785Stephan Bosch
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainenstruct solr_connection_post *
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainensolr_connection_post_begin(struct solr_connection *conn)
50d1446e71cfbdc5b6d7bafcf91b7bff453989d3Stephan Bosch{
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch struct solr_connection_post *post;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch CURLMcode merr;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch string_t *str;
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch post = i_new(struct solr_connection_post, 1);
fb025942616dfec7770455a7092d01f2e516314dTimo Sirainen post->conn = conn;
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch i_assert(!conn->posting);
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch conn->posting = TRUE;
069b28a2ef54072a221fe4ac67aaeb4e83fee6c1Timo Sirainen
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch i_free_and_null(conn->http_failure);
a4e186e3ef267fc7a6b592788067c8c9c87d0785Stephan Bosch
a4e186e3ef267fc7a6b592788067c8c9c87d0785Stephan Bosch curl_easy_setopt(conn->curl, CURLOPT_READDATA, post);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch merr = curl_multi_add_handle(conn->curlm, conn->curl);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (merr != CURLM_OK) {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch i_error("fts_solr: curl_multi_add_handle() failed: %s",
a4e186e3ef267fc7a6b592788067c8c9c87d0785Stephan Bosch curl_multi_strerror(merr));
a4e186e3ef267fc7a6b592788067c8c9c87d0785Stephan Bosch post->failed = TRUE;
a4e186e3ef267fc7a6b592788067c8c9c87d0785Stephan Bosch } else {
a4e186e3ef267fc7a6b592788067c8c9c87d0785Stephan Bosch str = t_str_new(256);
a4e186e3ef267fc7a6b592788067c8c9c87d0785Stephan Bosch str_append(str, conn->url);
a4e186e3ef267fc7a6b592788067c8c9c87d0785Stephan Bosch str_append(str, "update");
a4e186e3ef267fc7a6b592788067c8c9c87d0785Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch curl_easy_setopt(conn->curl, CURLOPT_URL, str_c(str));
99feb6521535a7dc59d8dda89981ceac084b3e88Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_HTTPHEADER,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch conn->headers_post);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch curl_easy_setopt(conn->curl, CURLOPT_POST, (long)1);
ccd968b44a40b9c2cf6278fabfa2a80cc5d9e46bTimo Sirainen }
ccd968b44a40b9c2cf6278fabfa2a80cc5d9e46bTimo Sirainen return post;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch}
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Boschvoid solr_connection_post_more(struct solr_connection_post *post,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch const unsigned char *data, size_t size)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch{
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch fd_set fdread;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch fd_set fdwrite;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch fd_set fdexcep;
27421074812b84d144b68388e597f4700f4f1c1bStephan Bosch struct timeval timeout_tv;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch long timeout;
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch CURLMsg *msg;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch CURLMcode merr;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch int ret, handles, maxfd, n;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch i_assert(post->conn->posting);
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch if (post->failed)
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch return;
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch post->data = data;
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch post->size = size;
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch post->pos = 0;
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch for (;;) {
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch merr = curl_multi_perform(post->conn->curlm, &handles);
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch if (merr == CURLM_CALL_MULTI_PERFORM)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch continue;
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch if (merr != CURLM_OK) {
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch i_error("fts_solr: curl_multi_perform() failed: %s",
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch curl_multi_strerror(merr));
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch break;
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch }
b99130e4cf4af4e6b103b949456222f3a2dff424Timo Sirainen if ((post->pos == post->size && post->size != 0) ||
b99130e4cf4af4e6b103b949456222f3a2dff424Timo Sirainen (handles == 0 && post->size == 0)) {
b99130e4cf4af4e6b103b949456222f3a2dff424Timo Sirainen /* everything sent successfully */
b99130e4cf4af4e6b103b949456222f3a2dff424Timo Sirainen return;
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch }
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch msg = curl_multi_info_read(post->conn->curlm, &n);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (msg != NULL && msg->msg == CURLMSG_DONE &&
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen msg->data.result != CURLE_OK) {
2ccb0bce340110ab68d1a490103d7b0271962139Stephan Bosch i_error("fts_solr: curl post failed: %s",
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch curl_easy_strerror(msg->data.result));
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch break;
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen }
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen
dd61a7356c4e00d733fd6cd99b29d979b9eb26dfTimo Sirainen /* everything wasn't sent - wait. just use select,
dd61a7356c4e00d733fd6cd99b29d979b9eb26dfTimo Sirainen since libcurl interface is easiest with it. */
dd61a7356c4e00d733fd6cd99b29d979b9eb26dfTimo Sirainen FD_ZERO(&fdread);
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch FD_ZERO(&fdwrite);
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch FD_ZERO(&fdexcep);
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch merr = curl_multi_fdset(post->conn->curlm, &fdread, &fdwrite,
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen &fdexcep, &maxfd);
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen if (merr != CURLM_OK) {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch i_error("fts_solr: curl_multi_fdset() failed: %s",
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch curl_multi_strerror(merr));
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch break;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch }
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch i_assert(maxfd >= 0);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch merr = curl_multi_timeout(post->conn->curlm, &timeout);
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch if (merr != CURLM_OK) {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch i_error("fts_solr: curl_multi_timeout() failed: %s",
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch curl_multi_strerror(merr));
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch break;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch }
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (timeout < 0) {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch timeout_tv.tv_sec = 1;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch timeout_tv.tv_usec = 0;
99feb6521535a7dc59d8dda89981ceac084b3e88Timo Sirainen } else {
99feb6521535a7dc59d8dda89981ceac084b3e88Timo Sirainen timeout_tv.tv_sec = timeout / 1000;
99feb6521535a7dc59d8dda89981ceac084b3e88Timo Sirainen timeout_tv.tv_usec = (timeout % 1000) * 1000;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch }
99feb6521535a7dc59d8dda89981ceac084b3e88Timo Sirainen ret = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout_tv);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (ret < 0) {
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch i_error("fts_solr: select() failed: %m");
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch break;
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen }
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch }
99feb6521535a7dc59d8dda89981ceac084b3e88Timo Sirainen post->failed = TRUE;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch}
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Boschint solr_connection_post_end(struct solr_connection_post *post)
858a13d06402d3d6e2dc683f6696c14192ad6b02Stephan Bosch{
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch struct solr_connection *conn = post->conn;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch long httpret;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch int ret = post->failed ? -1 : 0;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch i_assert(conn->posting);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch solr_connection_post_more(post, NULL, 0);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch curl_easy_getinfo(conn->curl, CURLINFO_RESPONSE_CODE, &httpret);
ccd968b44a40b9c2cf6278fabfa2a80cc5d9e46bTimo Sirainen if (httpret != 200 && ret == 0) {
ccd968b44a40b9c2cf6278fabfa2a80cc5d9e46bTimo Sirainen i_error("fts_solr: Indexing failed: %s", conn->http_failure);
ccd968b44a40b9c2cf6278fabfa2a80cc5d9e46bTimo Sirainen ret = -1;
ccd968b44a40b9c2cf6278fabfa2a80cc5d9e46bTimo Sirainen }
ccd968b44a40b9c2cf6278fabfa2a80cc5d9e46bTimo Sirainen
ccd968b44a40b9c2cf6278fabfa2a80cc5d9e46bTimo Sirainen curl_easy_setopt(conn->curl, CURLOPT_READDATA, NULL);
ccd968b44a40b9c2cf6278fabfa2a80cc5d9e46bTimo Sirainen curl_easy_setopt(conn->curl, CURLOPT_POST, (long)0);
ccd968b44a40b9c2cf6278fabfa2a80cc5d9e46bTimo Sirainen curl_easy_setopt(conn->curl, CURLOPT_HTTPHEADER, conn->headers);
ccd968b44a40b9c2cf6278fabfa2a80cc5d9e46bTimo Sirainen
ccd968b44a40b9c2cf6278fabfa2a80cc5d9e46bTimo Sirainen (void)curl_multi_remove_handle(conn->curlm, conn->curl);
ccd968b44a40b9c2cf6278fabfa2a80cc5d9e46bTimo Sirainen i_free(post);
6c768e0e1ca2da178e79f7435c32ced01f6bcb24Timo Sirainen
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch conn->posting = FALSE;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch return ret;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch}
6c768e0e1ca2da178e79f7435c32ced01f6bcb24Timo Sirainen
7384b4e78eaab44693c985192276e31322155e32Stephan Boschint solr_connection_post(struct solr_connection *conn, const char *cmd)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch{
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch struct solr_connection_post *post;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
6c768e0e1ca2da178e79f7435c32ced01f6bcb24Timo Sirainen post = solr_connection_post_begin(conn);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch solr_connection_post_more(post, (const unsigned char *)cmd,
6c768e0e1ca2da178e79f7435c32ced01f6bcb24Timo Sirainen strlen(cmd));
6c768e0e1ca2da178e79f7435c32ced01f6bcb24Timo Sirainen return solr_connection_post_end(post);
6c768e0e1ca2da178e79f7435c32ced01f6bcb24Timo Sirainen}
6c768e0e1ca2da178e79f7435c32ced01f6bcb24Timo Sirainen