changeset 234:0ebbf9723930 refactoring

OAOO for the trackPointQuery and trackSequenceQueryNN Reporter classes. C++ has this marvellous thing called templates, which allows for almost 1% of the power of writing source code at compile-time; in this particular case, that 1% is enough, as it allows us to generalize over the predicate for ordering in queues with a template class. Move reporters into reporter.h. The template class needs to be in there anyway; the pointQueryReporter will soon gain a template class analogue for Ollie's use case; and then there's just the Radius reporter.
author mas01cr
date Wed, 12 Dec 2007 10:58:24 +0000
parents 542c22f4fadc
children 692e026947a8
files Makefile query.cpp reporter.h
diffstat 3 files changed, 287 insertions(+), 394 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Wed Dec 12 10:22:31 2007 +0000
+++ b/Makefile	Wed Dec 12 10:58:24 2007 +0000
@@ -27,7 +27,7 @@
 soapServer.cpp soapClient.cpp soapC.cpp adb.nsmap: audioDBws.h
 	${SOAPCPP2} audioDBws.h
 
-%.o: %.cpp audioDB.h adb.nsmap cmdline.h
+%.o: %.cpp audioDB.h adb.nsmap cmdline.h reporter.h
 	g++ -c ${CFLAGS} ${GSOAP_INCLUDE} -Wall -Werror $<
 
 OBJS=insert.o create.o common.o dump.o query.o soap.o audioDB.o
--- a/query.cpp	Wed Dec 12 10:22:31 2007 +0000
+++ b/query.cpp	Wed Dec 12 10:58:24 2007 +0000
@@ -1,9 +1,6 @@
 #include "audioDB.h"
 
-#include <utility>
-#include <queue>
-#include <set>
-#include <functional>
+#include "reporter.h"
 
 #define VERB_LOG(vv, ...) \
   if(verbosity > vv) { \
@@ -11,393 +8,6 @@
     fflush(stderr); \
   }
 
-typedef struct nnresult {
-  unsigned int trackID;
-  double dist;
-  unsigned int qpos;
-  unsigned int spos;
-} NNresult;
-
-typedef struct radresult {
-  unsigned int trackID;
-  unsigned int count;
-} Radresult;
-
-bool operator< (const NNresult &a, const NNresult &b) {
-  return a.dist < b.dist;
-}
-
-bool operator> (const NNresult &a, const NNresult &b) {
-  return a.dist > b.dist;
-}
-
-bool operator<= (const NNresult &a, const NNresult &b) {
-  return a.dist <= b.dist;
-}
-
-bool operator< (const Radresult &a, const Radresult &b) {
-  return a.count < b.count;
-}
-
-class Reporter {
-public:
-  virtual ~Reporter() {};
-  virtual void add_point(unsigned int trackID, unsigned int qpos, unsigned int spos, double dist) = 0;
-  // FIXME: this interface is a bit wacky: a relic of previous, more
-  // confused times.  Really it might make sense to have separate
-  // reporter classes for WS and for stdout, rather than passing this
-  // adbQueryResponse thing everywhere; the fileTable argument is
-  // there solely for convertion trackIDs into names.  -- CSR,
-  // 2007-12-10.
-  virtual void report(char *fileTable, adb__queryResponse *adbQueryResponse) = 0;
-};
-
-class pointQueryReporter : public Reporter {
-public:
-  pointQueryReporter(unsigned int pointNN);
-  ~pointQueryReporter();
-  void add_point(unsigned int trackID, unsigned int qpos, unsigned int spos, double dist);
-  void report(char *fileTable, adb__queryResponse *adbQueryResponse);
-private:
-  unsigned int pointNN;
-  std::priority_queue< NNresult, std::vector< NNresult >, std::greater< NNresult > > *queue;
-};
-
-pointQueryReporter::pointQueryReporter(unsigned int pointNN)
-  : pointNN(pointNN) {
-  queue = new std::priority_queue< NNresult, std::vector< NNresult >, std::greater< NNresult > >;
-}
-
-pointQueryReporter::~pointQueryReporter() {
-  delete queue;
-}
-
-void pointQueryReporter::add_point(unsigned int trackID, unsigned int qpos, unsigned int spos, double dist) {
-  NNresult r;
-  r.trackID = trackID;
-  r.qpos = qpos;
-  r.spos = spos;
-  r.dist = dist;
-  queue->push(r);
-  if(queue->size() > pointNN) {
-    queue->pop();
-  }
-}
-
-void pointQueryReporter::report(char *fileTable, adb__queryResponse *adbQueryResponse) {
-  NNresult r;
-  std::vector<NNresult> v;
-  unsigned int size = queue->size();
-  for(unsigned int k = 0; k < size; k++) {
-    r = queue->top();
-    v.push_back(r);
-    queue->pop();
-  }
-  std::vector<NNresult>::reverse_iterator rit;
-      
-  if(adbQueryResponse==0) {
-    for(rit = v.rbegin(); rit < v.rend(); rit++) {
-      r = *rit;
-      std::cout << fileTable + r.trackID*O2_FILETABLESIZE << " ";
-      std::cout << r.dist << " " << r.qpos << " " << r.spos << std::endl;
-    }
-  } else {
-    adbQueryResponse->result.__sizeRlist=size;
-    adbQueryResponse->result.__sizeDist=size;
-    adbQueryResponse->result.__sizeQpos=size;
-    adbQueryResponse->result.__sizeSpos=size;
-    adbQueryResponse->result.Rlist= new char*[size];
-    adbQueryResponse->result.Dist = new double[size];
-    adbQueryResponse->result.Qpos = new unsigned int[size];
-    adbQueryResponse->result.Spos = new unsigned int[size];
-    unsigned int k = 0;
-    for(rit = v.rbegin(); rit < v.rend(); rit++, k++) {
-      r = *rit;
-      adbQueryResponse->result.Rlist[k] = new char[O2_MAXFILESTR];
-      adbQueryResponse->result.Dist[k] = r.dist;
-      adbQueryResponse->result.Qpos[k] = r.qpos;
-      adbQueryResponse->result.Spos[k] = r.spos;
-      snprintf(adbQueryResponse->result.Rlist[k], O2_MAXFILESTR, "%s", fileTable+r.trackID*O2_FILETABLESIZE);
-    }
-  }
-}
-
-// FIXME: this trackPointQueryReporter is actually an almost
-// word-for-word copy of trackSequenceQueryNNReporter, below: the only
-// difference is that all priority queues use std::greater<NNresult>,
-// rather than the implicit default std::less<NNresult>.  There's
-// probably some clever C++ way of expressing that; find out and
-// delete one copy of the code.
-class trackPointQueryReporter : public Reporter {
-public:
-  trackPointQueryReporter(unsigned int pointNN, unsigned int trackNN, unsigned int numFiles);
-  ~trackPointQueryReporter();
-  void add_point(unsigned int trackID, unsigned int qpos, unsigned int spos, double dist);
-  void report(char *fileTable, adb__queryResponse *adbQueryResponse);
-private:
-  unsigned int pointNN;
-  unsigned int trackNN;
-  unsigned int numFiles;
-  std::priority_queue< NNresult, std::vector< NNresult>, std::greater< NNresult > > *queues;
-};
-
-trackPointQueryReporter::trackPointQueryReporter(unsigned int pointNN, unsigned int trackNN, unsigned int numFiles)
-  : pointNN(pointNN), trackNN(trackNN), numFiles(numFiles) {
-  queues = new std::priority_queue< NNresult, std::vector< NNresult>, std::greater< NNresult > >[numFiles];
-}
-
-trackPointQueryReporter::~trackPointQueryReporter() {
-  delete [] queues;
-}
-
-void trackPointQueryReporter::add_point(unsigned int trackID, unsigned int qpos, unsigned int spos, double dist) {
-  NNresult r;
-  r.trackID = trackID;
-  r.qpos = qpos;
-  r.spos = spos;
-  r.dist = dist;
-  queues[trackID].push(r);
-  if(queues[trackID].size() > pointNN) {
-    queues[trackID].pop();
-  }
-}
-
-void trackPointQueryReporter::report(char *fileTable, adb__queryResponse *adbQueryResponse) {
-  std::priority_queue < NNresult, std::vector< NNresult>, std::greater< NNresult > > result;
-  for (int i = numFiles-1; i >= 0; i--) {
-    unsigned int size = queues[i].size();
-    if (size > 0) {
-      NNresult r;
-      double dist = 0;
-      NNresult oldr = queues[i].top();
-      for (unsigned int j = 0; j < size; j++) {
-        r = queues[i].top();
-        dist += r.dist;
-        queues[i].pop();
-        if (r.dist == oldr.dist) {
-          r.qpos = oldr.qpos;
-          r.spos = oldr.spos;
-        } else {
-          oldr = r;
-        }
-      }
-      dist /= size;
-      r.dist = dist; // trackID, qpos and spos are magically right already.
-      result.push(r);
-      if (result.size() > trackNN) {
-        result.pop();
-      }
-    }
-  }
-
-  NNresult r;
-  std::vector<NNresult> v;
-  unsigned int size = result.size();
-  for(unsigned int k = 0; k < size; k++) {
-    r = result.top();
-    v.push_back(r);
-    result.pop();
-  }
-  std::vector<NNresult>::reverse_iterator rit;
-      
-  if(adbQueryResponse==0) {
-    for(rit = v.rbegin(); rit < v.rend(); rit++) {
-      r = *rit;
-      std::cout << fileTable + r.trackID*O2_FILETABLESIZE << " ";
-      std::cout << r.dist << " " << r.qpos << " " << r.spos << std::endl;
-    }
-  } else {
-    adbQueryResponse->result.__sizeRlist=size;
-    adbQueryResponse->result.__sizeDist=size;
-    adbQueryResponse->result.__sizeQpos=size;
-    adbQueryResponse->result.__sizeSpos=size;
-    adbQueryResponse->result.Rlist= new char*[size];
-    adbQueryResponse->result.Dist = new double[size];
-    adbQueryResponse->result.Qpos = new unsigned int[size];
-    adbQueryResponse->result.Spos = new unsigned int[size];
-    unsigned int k = 0;
-    for(rit = v.rbegin(); rit < v.rend(); rit++, k++) {
-      r = *rit;
-      adbQueryResponse->result.Rlist[k] = new char[O2_MAXFILESTR];
-      adbQueryResponse->result.Dist[k] = r.dist;
-      adbQueryResponse->result.Qpos[k] = r.qpos;
-      adbQueryResponse->result.Spos[k] = r.spos;
-      snprintf(adbQueryResponse->result.Rlist[k], O2_MAXFILESTR, "%s", fileTable+r.trackID*O2_FILETABLESIZE);
-    }
-  }
-}
-
-class trackSequenceQueryNNReporter : public Reporter {
-public:
-  trackSequenceQueryNNReporter(unsigned int pointNN, unsigned int trackNN, unsigned int numFiles);
-  ~trackSequenceQueryNNReporter();
-  void add_point(unsigned int trackID, unsigned int qpos, unsigned int spos, double dist);
-  void report(char *fileTable, adb__queryResponse *adbQueryResponse);
-private:
-  unsigned int pointNN;
-  unsigned int trackNN;
-  unsigned int numFiles;
-  std::priority_queue< NNresult > *queues;
-};
-
-trackSequenceQueryNNReporter::trackSequenceQueryNNReporter(unsigned int pointNN, unsigned int trackNN, unsigned int numFiles)
-  : pointNN(pointNN), trackNN(trackNN), numFiles(numFiles) {
-  queues = new std::priority_queue< NNresult >[numFiles];
-}
-
-trackSequenceQueryNNReporter::~trackSequenceQueryNNReporter() {
-  delete [] queues;
-}
-
-void trackSequenceQueryNNReporter::add_point(unsigned int trackID, unsigned int qpos, unsigned int spos, double dist) {
-  NNresult r;
-  r.trackID = trackID;
-  r.qpos = qpos;
-  r.spos = spos;
-  r.dist = dist;
-  queues[trackID].push(r);
-  if(queues[trackID].size() > pointNN) {
-    queues[trackID].pop();
-  }
-}
-
-void trackSequenceQueryNNReporter::report(char *fileTable, adb__queryResponse *adbQueryResponse) {
-  std::priority_queue < NNresult > result;
-  for (int i = numFiles-1; i >= 0; i--) {
-    unsigned int size = queues[i].size();
-    if (size > 0) {
-      NNresult r;
-      double dist = 0;
-      NNresult oldr = queues[i].top();
-      for (unsigned int j = 0; j < size; j++) {
-        r = queues[i].top();
-        dist += r.dist;
-        queues[i].pop();
-        if (r.dist == oldr.dist) {
-          r.qpos = oldr.qpos;
-          r.spos = oldr.spos;
-        } else {
-          oldr = r;
-        }
-      }
-      dist /= size;
-      r.dist = dist; // trackID, qpos and spos are magically right already.
-      result.push(r);
-      if (result.size() > trackNN) {
-        result.pop();
-      }
-    }
-  }
-
-  NNresult r;
-  std::vector<NNresult> v;
-  unsigned int size = result.size();
-  for(unsigned int k = 0; k < size; k++) {
-    r = result.top();
-    v.push_back(r);
-    result.pop();
-  }
-  std::vector<NNresult>::reverse_iterator rit;
-      
-  if(adbQueryResponse==0) {
-    for(rit = v.rbegin(); rit < v.rend(); rit++) {
-      r = *rit;
-      std::cout << fileTable + r.trackID*O2_FILETABLESIZE << " ";
-      std::cout << r.dist << " " << r.qpos << " " << r.spos << std::endl;
-    }
-  } else {
-    adbQueryResponse->result.__sizeRlist=size;
-    adbQueryResponse->result.__sizeDist=size;
-    adbQueryResponse->result.__sizeQpos=size;
-    adbQueryResponse->result.__sizeSpos=size;
-    adbQueryResponse->result.Rlist= new char*[size];
-    adbQueryResponse->result.Dist = new double[size];
-    adbQueryResponse->result.Qpos = new unsigned int[size];
-    adbQueryResponse->result.Spos = new unsigned int[size];
-    unsigned int k = 0;
-    for(rit = v.rbegin(); rit < v.rend(); rit++, k++) {
-      r = *rit;
-      adbQueryResponse->result.Rlist[k] = new char[O2_MAXFILESTR];
-      adbQueryResponse->result.Dist[k] = r.dist;
-      adbQueryResponse->result.Qpos[k] = r.qpos;
-      adbQueryResponse->result.Spos[k] = r.spos;
-      snprintf(adbQueryResponse->result.Rlist[k], O2_MAXFILESTR, "%s", fileTable+r.trackID*O2_FILETABLESIZE);
-    }
-  }
-}
-
-class trackSequenceQueryRadReporter : public Reporter { 
-public:
-  trackSequenceQueryRadReporter(unsigned int trackNN, unsigned int numFiles);
-  ~trackSequenceQueryRadReporter();
-  void add_point(unsigned int trackID, unsigned int qpos, unsigned int spos, double dist);
-  void report(char *fileTable, adb__queryResponse *adbQueryResponse);
-private:
-  unsigned int trackNN;
-  unsigned int numFiles;
-  std::set<std::pair<unsigned int, unsigned int> > *set;
-  unsigned int *count;
-};
-
-trackSequenceQueryRadReporter::trackSequenceQueryRadReporter(unsigned int trackNN, unsigned int numFiles):
-  trackNN(trackNN), numFiles(numFiles) {
-  set = new std::set<std::pair<unsigned int, unsigned int> >;
-  count = new unsigned int[numFiles];
-  for (unsigned i = 0; i < numFiles; i++) {
-    count[i] = 0;
-  }
-}
-
-trackSequenceQueryRadReporter::~trackSequenceQueryRadReporter() {
-  delete set;
-  delete [] count;
-}
-
-void trackSequenceQueryRadReporter::add_point(unsigned int trackID, unsigned int qpos, unsigned int spos, double dist) {
-  std::set<std::pair<unsigned int, unsigned int> >::iterator it;
-  std::pair<unsigned int, unsigned int> pair = std::make_pair(trackID, qpos);
-  it = set->find(pair);
-  if (it == set->end()) {
-    set->insert(pair);
-    count[trackID]++;
-  }
-}
-
-void trackSequenceQueryRadReporter::report(char *fileTable, adb__queryResponse *adbQueryResponse) {
-  std::priority_queue < Radresult > result;
-  // KLUDGE: doing this backwards in an attempt to get the same
-  // tiebreak behaviour as before.
-  for (int i = numFiles-1; i >= 0; i--) {
-    Radresult r;
-    r.trackID = i;
-    r.count = count[i];
-    if(r.count > 0) {
-      result.push(r);
-      if (result.size() > trackNN) {
-        result.pop();
-      }
-    }
-  }
-
-  Radresult r;
-  std::vector<Radresult> v;
-  unsigned int size = result.size();
-  for(unsigned int k = 0; k < size; k++) {
-    r = result.top();
-    v.push_back(r);
-    result.pop();
-  }
-  std::vector<Radresult>::reverse_iterator rit;
-      
-  if(adbQueryResponse==0) {
-    for(rit = v.rbegin(); rit < v.rend(); rit++) {
-      r = *rit;
-      std::cout << fileTable + r.trackID*O2_FILETABLESIZE << " " << r.count << std::endl;
-    }
-  } else {
-  }
-}
-
 bool audioDB::powers_acceptable(double p1, double p2) {
   if (use_absolute_threshold) {
     if ((p1 < absolute_threshold) || (p2 < absolute_threshold)) {
@@ -424,11 +34,11 @@
   case O2_TRACK_QUERY:
     sequenceLength = 1;
     normalizedDistance = false;
-    r = new trackPointQueryReporter(pointNN, trackNN, dbH->numFiles);
+    r = new trackAveragingReporter<std::greater < NNresult > >(pointNN, trackNN, dbH->numFiles);
     break;
   case O2_SEQUENCE_QUERY:
     if(radius == 0) {
-      r = new trackSequenceQueryNNReporter(pointNN, trackNN, dbH->numFiles);
+      r = new trackAveragingReporter<std::less < NNresult > >(pointNN, trackNN, dbH->numFiles);
     } else {
       r = new trackSequenceQueryRadReporter(trackNN, dbH->numFiles);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/reporter.h	Wed Dec 12 10:58:24 2007 +0000
@@ -0,0 +1,283 @@
+#include <utility>
+#include <queue>
+#include <set>
+#include <functional>
+
+typedef struct nnresult {
+  unsigned int trackID;
+  double dist;
+  unsigned int qpos;
+  unsigned int spos;
+} NNresult;
+
+typedef struct radresult {
+  unsigned int trackID;
+  unsigned int count;
+} Radresult;
+
+bool operator< (const NNresult &a, const NNresult &b) {
+  return a.dist < b.dist;
+}
+
+bool operator> (const NNresult &a, const NNresult &b) {
+  return a.dist > b.dist;
+}
+
+bool operator< (const Radresult &a, const Radresult &b) {
+  return a.count < b.count;
+}
+
+class Reporter {
+public:
+  virtual ~Reporter() {};
+  virtual void add_point(unsigned int trackID, unsigned int qpos, unsigned int spos, double dist) = 0;
+  // FIXME: this interface is a bit wacky: a relic of previous, more
+  // confused times.  Really it might make sense to have separate
+  // reporter classes for WS and for stdout, rather than passing this
+  // adbQueryResponse thing everywhere; the fileTable argument is
+  // there solely for convertion trackIDs into names.  -- CSR,
+  // 2007-12-10.
+  virtual void report(char *fileTable, adb__queryResponse *adbQueryResponse) = 0;
+};
+
+class pointQueryReporter : public Reporter {
+public:
+  pointQueryReporter(unsigned int pointNN);
+  ~pointQueryReporter();
+  void add_point(unsigned int trackID, unsigned int qpos, unsigned int spos, double dist);
+  void report(char *fileTable, adb__queryResponse *adbQueryResponse);
+private:
+  unsigned int pointNN;
+  std::priority_queue< NNresult, std::vector< NNresult >, std::greater< NNresult > > *queue;
+};
+
+pointQueryReporter::pointQueryReporter(unsigned int pointNN)
+  : pointNN(pointNN) {
+  queue = new std::priority_queue< NNresult, std::vector< NNresult >, std::greater< NNresult > >;
+}
+
+pointQueryReporter::~pointQueryReporter() {
+  delete queue;
+}
+
+void pointQueryReporter::add_point(unsigned int trackID, unsigned int qpos, unsigned int spos, double dist) {
+  NNresult r;
+  r.trackID = trackID;
+  r.qpos = qpos;
+  r.spos = spos;
+  r.dist = dist;
+  queue->push(r);
+  if(queue->size() > pointNN) {
+    queue->pop();
+  }
+}
+
+void pointQueryReporter::report(char *fileTable, adb__queryResponse *adbQueryResponse) {
+  NNresult r;
+  std::vector<NNresult> v;
+  unsigned int size = queue->size();
+  for(unsigned int k = 0; k < size; k++) {
+    r = queue->top();
+    v.push_back(r);
+    queue->pop();
+  }
+  std::vector<NNresult>::reverse_iterator rit;
+      
+  if(adbQueryResponse==0) {
+    for(rit = v.rbegin(); rit < v.rend(); rit++) {
+      r = *rit;
+      std::cout << fileTable + r.trackID*O2_FILETABLESIZE << " ";
+      std::cout << r.dist << " " << r.qpos << " " << r.spos << std::endl;
+    }
+  } else {
+    adbQueryResponse->result.__sizeRlist=size;
+    adbQueryResponse->result.__sizeDist=size;
+    adbQueryResponse->result.__sizeQpos=size;
+    adbQueryResponse->result.__sizeSpos=size;
+    adbQueryResponse->result.Rlist= new char*[size];
+    adbQueryResponse->result.Dist = new double[size];
+    adbQueryResponse->result.Qpos = new unsigned int[size];
+    adbQueryResponse->result.Spos = new unsigned int[size];
+    unsigned int k = 0;
+    for(rit = v.rbegin(); rit < v.rend(); rit++, k++) {
+      r = *rit;
+      adbQueryResponse->result.Rlist[k] = new char[O2_MAXFILESTR];
+      adbQueryResponse->result.Dist[k] = r.dist;
+      adbQueryResponse->result.Qpos[k] = r.qpos;
+      adbQueryResponse->result.Spos[k] = r.spos;
+      snprintf(adbQueryResponse->result.Rlist[k], O2_MAXFILESTR, "%s", fileTable+r.trackID*O2_FILETABLESIZE);
+    }
+  }
+}
+
+template <class T> class trackAveragingReporter : public Reporter {
+ public:
+  trackAveragingReporter(unsigned int pointNN, unsigned int trackNN, unsigned int numFiles);
+  ~trackAveragingReporter();
+  void add_point(unsigned int trackID, unsigned int qpos, unsigned int spos, double dist);
+  void report(char *fileTable, adb__queryResponse *adbQueryResponse);
+ private:
+  unsigned int pointNN;
+  unsigned int trackNN;
+  unsigned int numFiles;
+  std::priority_queue< NNresult, std::vector< NNresult>, T > *queues;  
+};
+
+template <class T> trackAveragingReporter<T>::trackAveragingReporter(unsigned int pointNN, unsigned int trackNN, unsigned int numFiles) 
+  : pointNN(pointNN), trackNN(trackNN), numFiles(numFiles) {
+  queues = new std::priority_queue< NNresult, std::vector< NNresult>, T >[numFiles];
+}
+
+template <class T> trackAveragingReporter<T>::~trackAveragingReporter() {
+  delete [] queues;
+}
+
+template <class T> void trackAveragingReporter<T>::add_point(unsigned int trackID, unsigned int qpos, unsigned int spos, double dist) {
+  NNresult r;
+  r.trackID = trackID;
+  r.qpos = qpos;
+  r.spos = spos;
+  r.dist = dist;
+  queues[trackID].push(r);
+  if(queues[trackID].size() > pointNN) {
+    queues[trackID].pop();
+  }
+}
+
+template <class T> void trackAveragingReporter<T>::report(char *fileTable, adb__queryResponse *adbQueryResponse) {
+  std::priority_queue < NNresult, std::vector< NNresult>, T> result;
+  for (int i = numFiles-1; i >= 0; i--) {
+    unsigned int size = queues[i].size();
+    if (size > 0) {
+      NNresult r;
+      double dist = 0;
+      NNresult oldr = queues[i].top();
+      for (unsigned int j = 0; j < size; j++) {
+        r = queues[i].top();
+        dist += r.dist;
+        queues[i].pop();
+        if (r.dist == oldr.dist) {
+          r.qpos = oldr.qpos;
+          r.spos = oldr.spos;
+        } else {
+          oldr = r;
+        }
+      }
+      dist /= size;
+      r.dist = dist; // trackID, qpos and spos are magically right already.
+      result.push(r);
+      if (result.size() > trackNN) {
+        result.pop();
+      }
+    }
+  }
+
+  NNresult r;
+  std::vector<NNresult> v;
+  unsigned int size = result.size();
+  for(unsigned int k = 0; k < size; k++) {
+    r = result.top();
+    v.push_back(r);
+    result.pop();
+  }
+  std::vector<NNresult>::reverse_iterator rit;
+      
+  if(adbQueryResponse==0) {
+    for(rit = v.rbegin(); rit < v.rend(); rit++) {
+      r = *rit;
+      std::cout << fileTable + r.trackID*O2_FILETABLESIZE << " ";
+      std::cout << r.dist << " " << r.qpos << " " << r.spos << std::endl;
+    }
+  } else {
+    adbQueryResponse->result.__sizeRlist=size;
+    adbQueryResponse->result.__sizeDist=size;
+    adbQueryResponse->result.__sizeQpos=size;
+    adbQueryResponse->result.__sizeSpos=size;
+    adbQueryResponse->result.Rlist= new char*[size];
+    adbQueryResponse->result.Dist = new double[size];
+    adbQueryResponse->result.Qpos = new unsigned int[size];
+    adbQueryResponse->result.Spos = new unsigned int[size];
+    unsigned int k = 0;
+    for(rit = v.rbegin(); rit < v.rend(); rit++, k++) {
+      r = *rit;
+      adbQueryResponse->result.Rlist[k] = new char[O2_MAXFILESTR];
+      adbQueryResponse->result.Dist[k] = r.dist;
+      adbQueryResponse->result.Qpos[k] = r.qpos;
+      adbQueryResponse->result.Spos[k] = r.spos;
+      snprintf(adbQueryResponse->result.Rlist[k], O2_MAXFILESTR, "%s", fileTable+r.trackID*O2_FILETABLESIZE);
+    }
+  }
+}
+
+class trackSequenceQueryRadReporter : public Reporter { 
+public:
+  trackSequenceQueryRadReporter(unsigned int trackNN, unsigned int numFiles);
+  ~trackSequenceQueryRadReporter();
+  void add_point(unsigned int trackID, unsigned int qpos, unsigned int spos, double dist);
+  void report(char *fileTable, adb__queryResponse *adbQueryResponse);
+private:
+  unsigned int trackNN;
+  unsigned int numFiles;
+  std::set<std::pair<unsigned int, unsigned int> > *set;
+  unsigned int *count;
+};
+
+trackSequenceQueryRadReporter::trackSequenceQueryRadReporter(unsigned int trackNN, unsigned int numFiles):
+  trackNN(trackNN), numFiles(numFiles) {
+  set = new std::set<std::pair<unsigned int, unsigned int> >;
+  count = new unsigned int[numFiles];
+  for (unsigned i = 0; i < numFiles; i++) {
+    count[i] = 0;
+  }
+}
+
+trackSequenceQueryRadReporter::~trackSequenceQueryRadReporter() {
+  delete set;
+  delete [] count;
+}
+
+void trackSequenceQueryRadReporter::add_point(unsigned int trackID, unsigned int qpos, unsigned int spos, double dist) {
+  std::set<std::pair<unsigned int, unsigned int> >::iterator it;
+  std::pair<unsigned int, unsigned int> pair = std::make_pair(trackID, qpos);
+  it = set->find(pair);
+  if (it == set->end()) {
+    set->insert(pair);
+    count[trackID]++;
+  }
+}
+
+void trackSequenceQueryRadReporter::report(char *fileTable, adb__queryResponse *adbQueryResponse) {
+  std::priority_queue < Radresult > result;
+  // KLUDGE: doing this backwards in an attempt to get the same
+  // tiebreak behaviour as before.
+  for (int i = numFiles-1; i >= 0; i--) {
+    Radresult r;
+    r.trackID = i;
+    r.count = count[i];
+    if(r.count > 0) {
+      result.push(r);
+      if (result.size() > trackNN) {
+        result.pop();
+      }
+    }
+  }
+
+  Radresult r;
+  std::vector<Radresult> v;
+  unsigned int size = result.size();
+  for(unsigned int k = 0; k < size; k++) {
+    r = result.top();
+    v.push_back(r);
+    result.pop();
+  }
+  std::vector<Radresult>::reverse_iterator rit;
+      
+  if(adbQueryResponse==0) {
+    for(rit = v.rbegin(); rit < v.rend(); rit++) {
+      r = *rit;
+      std::cout << fileTable + r.trackID*O2_FILETABLESIZE << " " << r.count << std::endl;
+    }
+  } else {
+    // FIXME
+  }
+}