+/**
+ * Iterate over the results that are "close" to a particular key in
+ * the datacache. "close" is defined as numerically larger than @a
+ * key (when interpreted as a circular address space), with small
+ * distance.
+ *
+ * @param cls closure (internal context for the plugin)
+ * @param key area of the keyspace to look into
+ * @param num_results number of results that should be returned to @a iter
+ * @param iter maybe NULL (to just count)
+ * @param iter_cls closure for @a iter
+ * @return the number of results found
+ */
+static unsigned int
+sqlite_plugin_get_closest (void *cls,
+ const struct GNUNET_HashCode *key,
+ unsigned int num_results,
+ GNUNET_DATACACHE_Iterator iter,
+ void *iter_cls)
+{
+ struct Plugin *plugin = cls;
+ uint32_t num_results32 = num_results;
+ struct GNUNET_TIME_Absolute now;
+ struct GNUNET_TIME_Absolute exp;
+ size_t size;
+ void *dat;
+ unsigned int cnt;
+ size_t psize;
+ uint32_t type;
+ struct GNUNET_HashCode hc;
+ struct GNUNET_PeerIdentity *path;
+ struct GNUNET_SQ_QueryParam params[] = {
+ GNUNET_SQ_query_param_auto_from_type (key),
+ GNUNET_SQ_query_param_absolute_time (&now),
+ GNUNET_SQ_query_param_uint32 (&num_results32),
+ GNUNET_SQ_query_param_end
+ };
+ struct GNUNET_SQ_ResultSpec rs[] = {
+ GNUNET_SQ_result_spec_variable_size (&dat,
+ &size),
+ GNUNET_SQ_result_spec_absolute_time (&exp),
+ GNUNET_SQ_result_spec_variable_size ((void **) &path,
+ &psize),
+ GNUNET_SQ_result_spec_uint32 (&type),
+ GNUNET_SQ_result_spec_auto_from_type (&hc),
+ GNUNET_SQ_result_spec_end
+ };
+
+ now = GNUNET_TIME_absolute_get ();
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Processing GET_CLOSEST for key `%s'\n",
+ GNUNET_h2s (key));
+ if (GNUNET_OK !=
+ GNUNET_SQ_bind (plugin->get_closest_stmt,
+ params))
+ {
+ LOG_SQLITE (plugin->dbh,
+ GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+ "sqlite3_bind_xxx");
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->get_closest_stmt);
+ return 0;
+ }
+ cnt = 0;
+ while (SQLITE_ROW ==
+ sqlite3_step (plugin->get_closest_stmt))
+ {
+ if (GNUNET_OK !=
+ GNUNET_SQ_extract_result (plugin->get_closest_stmt,
+ rs))
+ {
+ GNUNET_break (0);
+ break;
+ }
+ if (0 != psize % sizeof (struct GNUNET_PeerIdentity))
+ {
+ GNUNET_break (0);
+ psize = 0;
+ path = NULL;
+ }
+ psize /= sizeof (struct GNUNET_PeerIdentity);
+ cnt++;
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Found %u-byte result at %s when processing GET_CLOSE\n",
+ (unsigned int) size,
+ GNUNET_h2s (&hc));
+ if (GNUNET_OK != iter (iter_cls,
+ &hc,
+ size,
+ dat,
+ type,
+ exp,
+ psize,
+ path))
+ {
+ GNUNET_SQ_cleanup_result (rs);
+ break;
+ }
+ GNUNET_SQ_cleanup_result (rs);
+ }
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->get_closest_stmt);
+ return cnt;
+}
+
+