suppress initial rescan completely, except for fresh installs
[disorder] / server / trackdb.c
index cb6b45a..c275f3c 100644 (file)
@@ -75,6 +75,9 @@ static int trackdb_expire_noticed_tid(time_t earliest, DB_TXN *tid);
 const struct cache_type cache_files_type = { 86400 };
 unsigned long cache_files_hits, cache_files_misses;
 
+/** @brief Set by trackdb_open() */
+int trackdb_existing_database;
+
 /* setup and teardown ********************************************************/
 
 static const char *home;                /* home had better not change */
@@ -306,7 +309,7 @@ static DB *open_db(const char *path,
  * - @p TRACKDB_OPEN_FOR_UPGRADE, if this is disorder-dbupgrade
  */
 void trackdb_open(int flags) {
-  int newdb, err;
+  int err;
   pid_t pid;
 
   /* sanity checks */
@@ -359,14 +362,14 @@ void trackdb_open(int flags) {
       /* This doesn't make any sense */
       fatal(0, "database is already at current version");
     }
-    newdb = 0;
+    trackdb_existing_database = 1;
   } else {
     if(flags & TRACKDB_OPEN_FOR_UPGRADE) {
       /* Cannot upgrade a new database */
       fatal(0, "cannot upgrade a database that does not exist");
     }
     /* This is a brand new database */
-    newdb = 1;
+    trackdb_existing_database = 0;
   }
   /* open the databases */
   trackdb_tracksdb = open_db("tracks.db",
@@ -379,7 +382,7 @@ void trackdb_open(int flags) {
   trackdb_globaldb = open_db("global.db", 0, DB_HASH, DB_CREATE, 0666);
   trackdb_noticeddb = open_db("noticed.db",
                              DB_DUPSORT, DB_BTREE, DB_CREATE, 0666);
-  if(newdb) {
+  if(!trackdb_existing_database) {
     /* Stash the database version */
     char buf[32];
 
@@ -637,6 +640,22 @@ static int tailor_underscore_Word_Break_Other(uint32_t c) {
   }
 }
 
+/** @brief Remove all combining characters in-place
+ * @param s Pointer to start of string
+ * @param ns Length of string
+ * @return New, possiblby reduced, length
+ */
+static size_t remove_combining_chars(uint32_t *s, size_t ns) {
+  uint32_t *start = s, *t = s, *end = s + ns;
+
+  while(s < end) {
+    const uint32_t c = *s++;
+    if(!utf32_combining_class(c))
+      *t++ = c;
+  }
+  return t - start;
+}
+
 /** @brief Normalize and split a string using a given tailoring */
 static void word_split(struct vector *v,
                        const char *s,
@@ -650,6 +669,8 @@ static void word_split(struct vector *v,
   /* Erase case distinctions */
   if(!(t32 = utf32_casefold_compat(t32, nt32, &nt32)))
     return;
+  /* Drop combining characters */
+  nt32 = remove_combining_chars(t32, nt32);
   /* Split into words, treating _ as a space */
   w32 = utf32_word_split(t32, nt32, &nw, pt);
   /* Convert words back to UTF-8 and append to result */
@@ -1816,11 +1837,20 @@ char **trackdb_search(char **wordlist, int nwordlist, int *ntracks) {
   const char *dbname;
 
   *ntracks = 0;                                /* for early returns */
-  /* casefold all the words */
+  /* normalize all the words */
   w = xmalloc(nwordlist * sizeof (char *));
   for(n = 0; n < nwordlist; ++n) {
+    uint32_t *w32;
+    size_t nw32;
+    
     w[n] = utf8_casefold_compat(wordlist[n], strlen(wordlist[n]), 0);
     if(checktag(w[n])) ++ntags;         /* count up tags */
+    /* Strip out combining characters (AFTER checking whether it's a tag) */
+    if(!(w32 = utf8_to_utf32(w[n], strlen(w[n]), &nw32)))
+      return 0;
+    nw32 = remove_combining_chars(w32, nw32);
+    if(!(w[n] = utf32_to_utf8(w32, nw32, 0)))
+      return 0;
   }
   /* find the longest non-stopword */
   for(n = 0; n < nwordlist; ++n)