annotate rdf/SimpleSPARQLQuery.cpp @ 458:f60360209e5c

* Fix race condition in FFTFileCache when reading from the same FFT model from multiple threads (e.g. when applying more than one plugin at once)
author Chris Cannam
date Wed, 15 Oct 2008 12:08:02 +0000
parents ef14acd6d102
children 2019d89ebcf9
rev   line source
Chris@439 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@439 2
Chris@439 3 /*
Chris@439 4 Sonic Visualiser
Chris@439 5 An audio file viewer and annotation editor.
Chris@439 6 Centre for Digital Music, Queen Mary, University of London.
Chris@439 7 This file copyright 2008 QMUL.
Chris@439 8
Chris@439 9 This program is free software; you can redistribute it and/or
Chris@439 10 modify it under the terms of the GNU General Public License as
Chris@439 11 published by the Free Software Foundation; either version 2 of the
Chris@439 12 License, or (at your option) any later version. See the file
Chris@439 13 COPYING included with this distribution for more information.
Chris@439 14 */
Chris@439 15
Chris@439 16 #include "SimpleSPARQLQuery.h"
Chris@439 17 #include "base/ProgressReporter.h"
Chris@439 18
Chris@440 19 #ifdef USE_NEW_RASQAL_API
Chris@440 20 #include <rasqal/rasqal.h>
Chris@440 21 #else
Chris@439 22 #include <rasqal.h>
Chris@440 23 #endif
Chris@439 24
Chris@439 25 #include <iostream>
Chris@439 26
Chris@439 27 using std::cerr;
Chris@439 28 using std::endl;
Chris@439 29
Chris@440 30 #ifdef USE_NEW_RASQAL_API
Chris@440 31 class WrasqalWorldWrapper // wrong but wromantic, etc
Chris@440 32 {
Chris@440 33 public:
Chris@440 34 WrasqalWorldWrapper() : m_world(rasqal_new_world()) { }
Chris@440 35 ~WrasqalWorldWrapper() { rasqal_free_world(m_world); }
Chris@440 36
Chris@440 37 rasqal_world *getWorld() const { return m_world; }
Chris@440 38
Chris@440 39 private:
Chris@440 40 rasqal_world *m_world;
Chris@440 41 };
Chris@440 42 #endif
Chris@440 43
Chris@439 44 class SimpleSPARQLQuery::Impl
Chris@439 45 {
Chris@439 46 public:
Chris@439 47 Impl(QString query);
Chris@439 48 ~Impl();
Chris@439 49
Chris@439 50 void setProgressReporter(ProgressReporter *reporter) { m_reporter = reporter; }
Chris@439 51 bool wasCancelled() const { return m_cancelled; }
Chris@439 52
Chris@439 53 ResultList execute();
Chris@439 54
Chris@439 55 bool isOK() const;
Chris@439 56 QString getErrorString() const;
Chris@439 57
Chris@439 58 protected:
Chris@439 59 static void errorHandler(void *, raptor_locator *, const char *);
Chris@439 60
Chris@440 61 #ifdef USE_NEW_RASQAL_API
Chris@440 62 static WrasqalWorldWrapper m_www;
Chris@440 63 #else
Chris@439 64 static bool m_initialised;
Chris@440 65 #endif
Chris@439 66
Chris@439 67 QString m_query;
Chris@439 68 QString m_errorString;
Chris@439 69 ProgressReporter *m_reporter;
Chris@439 70 bool m_cancelled;
Chris@439 71 };
Chris@439 72
Chris@440 73 #ifdef USE_NEW_RASQAL_API
Chris@440 74 WrasqalWorldWrapper
Chris@440 75 SimpleSPARQLQuery::Impl::m_www;
Chris@440 76 #else
Chris@440 77 bool
Chris@440 78 SimpleSPARQLQuery::Impl::m_initialised = false;
Chris@440 79 #endif
Chris@440 80
Chris@439 81 SimpleSPARQLQuery::SimpleSPARQLQuery(QString query) :
Chris@439 82 m_impl(new Impl(query)) { }
Chris@439 83
Chris@439 84 SimpleSPARQLQuery::~SimpleSPARQLQuery()
Chris@439 85 {
Chris@439 86 delete m_impl;
Chris@439 87 }
Chris@439 88
Chris@439 89 void
Chris@439 90 SimpleSPARQLQuery::setProgressReporter(ProgressReporter *reporter)
Chris@439 91 {
Chris@439 92 m_impl->setProgressReporter(reporter);
Chris@439 93 }
Chris@439 94
Chris@439 95 bool
Chris@439 96 SimpleSPARQLQuery::wasCancelled() const
Chris@439 97 {
Chris@439 98 return m_impl->wasCancelled();
Chris@439 99 }
Chris@439 100
Chris@439 101 SimpleSPARQLQuery::ResultList
Chris@439 102 SimpleSPARQLQuery::execute()
Chris@439 103 {
Chris@439 104 return m_impl->execute();
Chris@439 105 }
Chris@439 106
Chris@439 107 bool
Chris@439 108 SimpleSPARQLQuery::isOK() const
Chris@439 109 {
Chris@439 110 return m_impl->isOK();
Chris@439 111 }
Chris@439 112
Chris@439 113 QString
Chris@439 114 SimpleSPARQLQuery::getErrorString() const
Chris@439 115 {
Chris@439 116 return m_impl->getErrorString();
Chris@439 117 }
Chris@439 118
Chris@439 119 SimpleSPARQLQuery::Impl::Impl(QString query) :
Chris@439 120 m_query(query),
Chris@439 121 m_reporter(0),
Chris@439 122 m_cancelled(false)
Chris@439 123 {
Chris@457 124 // std::cerr << "SimpleSPARQLQuery::Impl: Query is: \"" << query.toStdString() << "\"" << std::endl;
Chris@439 125 }
Chris@439 126
Chris@439 127 SimpleSPARQLQuery::Impl::~Impl()
Chris@439 128 {
Chris@439 129 }
Chris@439 130
Chris@439 131 bool
Chris@439 132 SimpleSPARQLQuery::Impl::isOK() const
Chris@439 133 {
Chris@439 134 return (m_errorString == "");
Chris@439 135 }
Chris@439 136
Chris@439 137 QString
Chris@439 138 SimpleSPARQLQuery::Impl::getErrorString() const
Chris@439 139 {
Chris@439 140 return m_errorString;
Chris@439 141 }
Chris@439 142
Chris@439 143 void
Chris@439 144 SimpleSPARQLQuery::Impl::errorHandler(void *data,
Chris@439 145 raptor_locator *locator,
Chris@439 146 const char *message)
Chris@439 147 {
Chris@439 148 SimpleSPARQLQuery::Impl *impl = (SimpleSPARQLQuery::Impl *)data;
Chris@439 149
Chris@439 150 // char buffer[256];
Chris@439 151 // raptor_format_locator(buffer, 255, locator);
Chris@439 152 // impl->m_errorString = QString("%1 - %2").arg(buffer).arg(message);
Chris@439 153
Chris@439 154 impl->m_errorString = message;
Chris@439 155
Chris@439 156 cerr << "SimpleSPARQLQuery: ERROR: " << impl->m_errorString.toStdString() << endl;
Chris@439 157 }
Chris@439 158
Chris@439 159 SimpleSPARQLQuery::ResultList
Chris@439 160 SimpleSPARQLQuery::Impl::execute()
Chris@439 161 {
Chris@439 162 ResultList list;
Chris@439 163
Chris@440 164 #ifdef USE_NEW_RASQAL_API
Chris@440 165 rasqal_query *query = rasqal_new_query(m_www.getWorld(), "sparql", NULL);
Chris@440 166 #else
Chris@440 167 if (!m_initialised) {
Chris@440 168 m_initialised = true;
Chris@440 169 rasqal_init();
Chris@440 170 }
Chris@439 171 rasqal_query *query = rasqal_new_query("sparql", NULL);
Chris@440 172 #endif
Chris@439 173 if (!query) {
Chris@439 174 m_errorString = "Failed to construct query";
Chris@439 175 cerr << "SimpleSPARQLQuery: ERROR: " << m_errorString.toStdString() << endl;
Chris@439 176 return list;
Chris@439 177 }
Chris@439 178
Chris@439 179 rasqal_query_set_error_handler(query, this, errorHandler);
Chris@439 180 rasqal_query_set_fatal_error_handler(query, this, errorHandler);
Chris@439 181
Chris@439 182 if (rasqal_query_prepare
Chris@439 183 (query, (const unsigned char *)m_query.toUtf8().data(), NULL)) {
Chris@439 184 cerr << "SimpleSPARQLQuery: Failed to prepare query" << endl;
Chris@439 185 rasqal_free_query(query);
Chris@439 186 return list;
Chris@439 187 }
Chris@439 188
Chris@439 189 rasqal_query_results *results = rasqal_query_execute(query);
Chris@439 190
Chris@439 191 // cerr << "Query executed" << endl;
Chris@439 192
Chris@439 193 if (!results) {
Chris@439 194 cerr << "SimpleSPARQLQuery: RASQAL query failed" << endl;
Chris@439 195 rasqal_free_query(query);
Chris@439 196 return list;
Chris@439 197 }
Chris@439 198
Chris@439 199 if (!rasqal_query_results_is_bindings(results)) {
Chris@439 200 cerr << "SimpleSPARQLQuery: RASQAL query has wrong result type (not bindings)" << endl;
Chris@439 201 rasqal_free_query_results(results);
Chris@439 202 rasqal_free_query(query);
Chris@439 203 return list;
Chris@439 204 }
Chris@439 205
Chris@439 206 int resultCount = 0;
Chris@439 207 int resultTotal = rasqal_query_results_get_count(results); // probably wrong
Chris@439 208 m_cancelled = false;
Chris@439 209
Chris@439 210 while (!rasqal_query_results_finished(results)) {
Chris@439 211
Chris@439 212 int count = rasqal_query_results_get_bindings_count(results);
Chris@439 213
Chris@439 214 KeyValueMap resultmap;
Chris@439 215
Chris@439 216 for (int i = 0; i < count; ++i) {
Chris@439 217
Chris@439 218 const unsigned char *name =
Chris@439 219 rasqal_query_results_get_binding_name(results, i);
Chris@439 220
Chris@439 221 rasqal_literal *literal =
Chris@439 222 rasqal_query_results_get_binding_value(results, i);
Chris@439 223
Chris@439 224 QString key = (const char *)name;
Chris@439 225
Chris@439 226 if (!literal) {
Chris@439 227 resultmap[key] = Value();
Chris@439 228 continue;
Chris@439 229 }
Chris@439 230
Chris@439 231 ValueType type = LiteralValue;
Chris@439 232 if (literal->type == RASQAL_LITERAL_URI) type = URIValue;
Chris@439 233 else if (literal->type == RASQAL_LITERAL_BLANK) type = BlankValue;
Chris@439 234
Chris@439 235 QString text = (const char *)rasqal_literal_as_string(literal);
Chris@439 236
Chris@449 237 std::cerr << i << ". " << key.toStdString() << " -> " << text.toStdString() << " (type " << type << ")" << std::endl;
Chris@449 238
Chris@439 239 resultmap[key] = Value(type, text);
Chris@439 240 }
Chris@439 241
Chris@439 242 list.push_back(resultmap);
Chris@439 243
Chris@439 244 rasqal_query_results_next(results);
Chris@439 245
Chris@439 246 resultCount++;
Chris@439 247
Chris@439 248 if (m_reporter) {
Chris@439 249 if (resultCount >= resultTotal) {
Chris@439 250 if (m_reporter->isDefinite()) m_reporter->setDefinite(false);
Chris@439 251 m_reporter->setProgress(resultCount);
Chris@439 252 } else {
Chris@439 253 m_reporter->setProgress((resultCount * 100) / resultTotal);
Chris@439 254 }
Chris@439 255
Chris@439 256 if (m_reporter->wasCancelled()) {
Chris@439 257 m_cancelled = true;
Chris@439 258 break;
Chris@439 259 }
Chris@439 260 }
Chris@439 261 }
Chris@439 262
Chris@439 263 rasqal_free_query_results(results);
Chris@439 264 rasqal_free_query(query);
Chris@439 265
Chris@439 266 return list;
Chris@439 267 }
Chris@440 268
Chris@440 269 SimpleSPARQLQuery::Value
Chris@440 270 SimpleSPARQLQuery::singleResultQuery(QString query, QString binding)
Chris@440 271 {
Chris@440 272 SimpleSPARQLQuery q(query);
Chris@440 273 ResultList results = q.execute();
Chris@440 274 if (!q.isOK()) {
Chris@440 275 cerr << "SimpleSPARQLQuery::singleResultQuery: ERROR: "
Chris@440 276 << q.getErrorString().toStdString() << endl;
Chris@440 277 return Value();
Chris@440 278 }
Chris@440 279 if (results.empty()) {
Chris@440 280 return Value();
Chris@440 281 }
Chris@440 282 for (int i = 0; i < results.size(); ++i) {
Chris@440 283 if (results[i].find(binding) != results[i].end() &&
Chris@440 284 results[i][binding].type != NoValue) {
Chris@440 285 return results[i][binding];
Chris@440 286 }
Chris@440 287 }
Chris@440 288 return Value();
Chris@440 289 }
Chris@440 290
Chris@440 291
Chris@440 292