comparison audioDB.cpp @ 469:d3afc91d205d api-inversion

Move audioDB::query over to audioDB.cpp At the same time, remove all the abstraction violations in audioDB::query, which came in two flavours: use of dbH->numFiles, which is dealt with by getting the database status instead (and is eventually unnecessary, being only needed now because reporters are implemented in terms of vectors indexed by ID), and use of fileTable in reporter's report functions (dealt with by passing in the adb instead). To actually implement reporting as of now, we continue to use stuff from audioDB-internals.h; maybe someday we will be clean and shiny.
author mas01cr
date Wed, 31 Dec 2008 15:44:16 +0000
parents 1030664df98c
children 8fb85fbcaba6
comparison
equal deleted inserted replaced
468:4dbd7917bf9e 469:d3afc91d205d
1 #include "audioDB.h" 1 #include "audioDB.h"
2 extern "C" { 2 extern "C" {
3 #include "audioDB_API.h" 3 #include "audioDB_API.h"
4 #include "audioDB-internals.h" 4 #include "audioDB-internals.h"
5 } 5 }
6 #include "reporter.h"
6 7
7 char* SERVER_ADB_ROOT; 8 char* SERVER_ADB_ROOT;
8 char* SERVER_ADB_FEATURE_ROOT; 9 char* SERVER_ADB_FEATURE_ROOT;
9 10
10 PointPair::PointPair(Uns32T a, Uns32T b, Uns32T c):trackID(a),qpos(b),spos(c){}; 11 PointPair::PointPair(Uns32T a, Uns32T b, Uns32T c):trackID(a),qpos(b),spos(c){};
820 821
821 // Report status 822 // Report status
822 status(dbName); 823 status(dbName);
823 } 824 }
824 825
826 void audioDB::query(const char* dbName, const char* inFile, adb__queryResponse *adbQueryResponse) {
827
828 if(!adb) {
829 if(!(adb = audiodb_open(dbName, O_RDWR))) {
830 error("failed to open database", dbName);
831 }
832 }
833
834 /* FIXME: we only need this for getting nfiles, which we only need
835 * because the reporters aren't desperately well implemented,
836 * relying on statically-sized vectors rather than adjustable data
837 * structures. Rework reporter.h to be less lame. */
838 adb_status_t status;
839 audiodb_status(adb, &status);
840 uint32_t nfiles = status.numFiles;
841
842 adb_query_spec_t qspec;
843 adb_datum_t datum = {0};
844
845 qspec.refine.flags = 0;
846 if(trackFile) {
847 qspec.refine.flags |= ADB_REFINE_INCLUDE_KEYLIST;
848 std::vector<const char *> v;
849 char *k = new char[MAXSTR];
850 trackFile->getline(k, MAXSTR);
851 while(!trackFile->eof()) {
852 v.push_back(k);
853 k = new char[MAXSTR];
854 trackFile->getline(k, MAXSTR);
855 }
856 delete [] k;
857 qspec.refine.include.nkeys = v.size();
858 qspec.refine.include.keys = new const char *[qspec.refine.include.nkeys];
859 for(unsigned int k = 0; k < qspec.refine.include.nkeys; k++) {
860 qspec.refine.include.keys[k] = v[k];
861 }
862 }
863 if(query_from_key) {
864 qspec.refine.flags |= ADB_REFINE_EXCLUDE_KEYLIST;
865 qspec.refine.exclude.nkeys = 1;
866 qspec.refine.exclude.keys = &key;
867 }
868 if(radius) {
869 qspec.refine.flags |= ADB_REFINE_RADIUS;
870 qspec.refine.radius = radius;
871 }
872 if(use_absolute_threshold) {
873 qspec.refine.flags |= ADB_REFINE_ABSOLUTE_THRESHOLD;
874 qspec.refine.absolute_threshold = absolute_threshold;
875 }
876 if(use_relative_threshold) {
877 qspec.refine.flags |= ADB_REFINE_RELATIVE_THRESHOLD;
878 qspec.refine.relative_threshold = relative_threshold;
879 }
880 if(usingTimes) {
881 qspec.refine.flags |= ADB_REFINE_DURATION_RATIO;
882 qspec.refine.duration_ratio = timesTol;
883 }
884 /* FIXME: not sure about this any more; maybe it belongs in
885 query_id? Or maybe we just don't need a flag for it? */
886 qspec.refine.hopsize = sequenceHop;
887 if(sequenceHop != 1) {
888 qspec.refine.flags |= ADB_REFINE_HOP_SIZE;
889 }
890
891 if(query_from_key) {
892 datum.key = key;
893 } else {
894 int fd;
895 struct stat st;
896
897 /* FIXME: around here there are all sorts of hideous leaks. */
898 fd = open(inFile, O_RDONLY);
899 if(fd < 0) {
900 error("failed to open feature file", inFile);
901 }
902 fstat(fd, &st);
903 read(fd, &datum.dim, sizeof(uint32_t));
904 datum.nvectors = (st.st_size - sizeof(uint32_t)) / (datum.dim * sizeof(double));
905 datum.data = (double *) malloc(st.st_size - sizeof(uint32_t));
906 read(fd, datum.data, st.st_size - sizeof(uint32_t));
907 close(fd);
908 if(usingPower) {
909 uint32_t one;
910 fd = open(powerFileName, O_RDONLY);
911 if(fd < 0) {
912 error("failed to open power file", powerFileName);
913 }
914 read(fd, &one, sizeof(uint32_t));
915 if(one != 1) {
916 error("malformed power file dimensionality", powerFileName);
917 }
918 datum.power = (double *) malloc(datum.nvectors * sizeof(double));
919 if(read(fd, datum.power, datum.nvectors * sizeof(double)) != (ssize_t) (datum.nvectors * sizeof(double))) {
920 error("malformed power file", powerFileName);
921 }
922 close(fd);
923 }
924 if(usingTimes) {
925 datum.times = (double *) malloc(2 * datum.nvectors * sizeof(double));
926 insertTimeStamps(datum.nvectors, timesFile, datum.times);
927 }
928 }
929
930 qspec.qid.datum = &datum;
931 qspec.qid.sequence_length = sequenceLength;
932 qspec.qid.flags = 0;
933 qspec.qid.flags |= usingQueryPoint ? 0 : ADB_QID_FLAG_EXHAUSTIVE;
934 qspec.qid.flags |= lsh_exact ? 0 : ADB_QID_FLAG_ALLOW_FALSE_POSITIVES;
935 qspec.qid.sequence_start = queryPoint;
936
937 switch(queryType) {
938 case O2_POINT_QUERY:
939 qspec.qid.sequence_length = 1;
940 qspec.params.accumulation = ADB_ACCUMULATION_DB;
941 qspec.params.distance = ADB_DISTANCE_DOT_PRODUCT;
942 qspec.params.npoints = pointNN;
943 qspec.params.ntracks = 0;
944 reporter = new pointQueryReporter< std::greater < NNresult > >(pointNN);
945 break;
946 case O2_TRACK_QUERY:
947 qspec.qid.sequence_length = 1;
948 qspec.params.accumulation = ADB_ACCUMULATION_PER_TRACK;
949 qspec.params.distance = ADB_DISTANCE_DOT_PRODUCT;
950 qspec.params.npoints = pointNN;
951 qspec.params.ntracks = trackNN;
952 reporter = new trackAveragingReporter< std::greater< NNresult > >(pointNN, trackNN, nfiles);
953 break;
954 case O2_SEQUENCE_QUERY:
955 case O2_N_SEQUENCE_QUERY:
956 qspec.params.accumulation = ADB_ACCUMULATION_PER_TRACK;
957 qspec.params.distance = no_unit_norming ? ADB_DISTANCE_EUCLIDEAN : ADB_DISTANCE_EUCLIDEAN_NORMED;
958 qspec.params.npoints = pointNN;
959 qspec.params.ntracks = trackNN;
960 switch(queryType) {
961 case O2_SEQUENCE_QUERY:
962 if(!(qspec.refine.flags & ADB_REFINE_RADIUS)) {
963 reporter = new trackAveragingReporter< std::less< NNresult > >(pointNN, trackNN, nfiles);
964 } else {
965 reporter = new trackSequenceQueryRadReporter(trackNN, nfiles);
966 }
967 break;
968 case O2_N_SEQUENCE_QUERY:
969 if(!(qspec.refine.flags & ADB_REFINE_RADIUS)) {
970 reporter = new trackSequenceQueryNNReporter< std::less < NNresult > >(pointNN, trackNN, nfiles);
971 } else {
972 reporter = new trackSequenceQueryRadNNReporter(pointNN, trackNN, nfiles);
973 }
974 break;
975 }
976 break;
977 case O2_ONE_TO_ONE_N_SEQUENCE_QUERY:
978 qspec.params.accumulation = ADB_ACCUMULATION_ONE_TO_ONE;
979 qspec.params.distance = ADB_DISTANCE_EUCLIDEAN_NORMED;
980 qspec.params.npoints = 0;
981 qspec.params.ntracks = 0;
982 break;
983 default:
984 error("unrecognized queryType");
985 }
986
987 adb_query_results_t *rs = audiodb_query_spec(adb, &qspec);
988
989 // FIXME: free bits of datum if !query_from_key
990
991 if(rs == NULL) {
992 error("audiodb_query_spec failed");
993 }
994
995 for(unsigned int k = 0; k < rs->nresults; k++) {
996 adb_result_t r = rs->results[k];
997 reporter->add_point(audiodb_key_index(adb, r.key), r.qpos, r.ipos, r.dist);
998 }
999 audiodb_query_free_results(adb, &qspec, rs);
1000
1001 reporter->report(adb, adbQueryResponse);
1002 }
1003
825 // This entry point is visited once per instance 1004 // This entry point is visited once per instance
826 // so it is a good place to set any global state variables 1005 // so it is a good place to set any global state variables
827 int main(const int argc, const char* argv[]){ 1006 int main(const int argc, const char* argv[]){
828 SERVER_ADB_ROOT = 0; // Server-side database root prefix 1007 SERVER_ADB_ROOT = 0; // Server-side database root prefix
829 SERVER_ADB_FEATURE_ROOT = 0; // Server-side features root prefix 1008 SERVER_ADB_FEATURE_ROOT = 0; // Server-side features root prefix