1 /*
2  * Copyright © 2012 Canonical Ltd.
3  *             By Michal Hruby <michal.hruby@canonical.com>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  */
19 
20 #ifndef _ZGFTS_INDEXER_H_
21 #define _ZGFTS_INDEXER_H_
22 
23 #include <glib.h>
24 #include <glib-object.h>
25 #include <gio/gio.h>
26 #include <xapian.h>
27 
28 #include "zeitgeist-internal.h"
29 
30 namespace ZeitgeistFTS {
31 
32 const std::string INDEX_VERSION = "4";
33 
34 class Indexer
35 {
36 public:
37   typedef std::map<std::string, GAppInfo*> AppInfoMap;
38   typedef std::set<std::string> ApplicationSet;
39 
Indexer(ZeitgeistDbReader * reader)40   Indexer (ZeitgeistDbReader *reader)
41     : zg_reader (reader)
42     , db (NULL)
43     , query_parser (NULL)
44     , enquire (NULL)
45     , tokenizer (NULL)
46     , checksum (NULL)
47     , clear_failed_id (0)
48   {
49     const gchar *home_dir = g_get_home_dir ();
50     home_dir_path = home_dir != NULL ? home_dir : "/home";
51     blacklisting_enabled = g_getenv ("ZEITGEIST_FTS_DISABLE_EVENT_BLACKLIST") == NULL;
52   }
53 
~Indexer()54   ~Indexer ()
55   {
56     if (tokenizer) delete tokenizer;
57     if (enquire) delete enquire;
58     if (query_parser) delete query_parser;
59     if (db) delete db;
60     if (checksum) g_checksum_free (checksum);
61     if (uri_schemes_regex) g_regex_unref (uri_schemes_regex);
62 
63     for (AppInfoMap::iterator it = app_info_cache.begin ();
64          it != app_info_cache.end (); ++it)
65     {
66       g_object_unref (it->second);
67     }
68 
69     if (clear_failed_id != 0)
70     {
71       g_source_remove (clear_failed_id);
72     }
73   }
74 
75   void Initialize (GError **error);
76   bool CheckIndex ();
77   void DropIndex ();
78   void Commit ();
79 
80   void IndexEvent (ZeitgeistEvent *event);
81   void DeleteEvent (guint32 event_id);
82   void SetDbMetadata (std::string const& key, std::string const& value);
83   gint64 GetZeitgeistCreationDate ();
84 
85   GPtrArray* Search (const gchar *search,
86                      ZeitgeistTimeRange *time_range,
87                      GPtrArray *templates,
88                      guint offset,
89                      guint count,
90                      ZeitgeistResultType result_type,
91                      guint *matches,
92                      GError **error);
93   GPtrArray* SearchWithRelevancies (const gchar *search,
94                                     ZeitgeistTimeRange *time_range,
95                                     GPtrArray *templates,
96                                     ZeitgeistStorageState storage_state,
97                                     guint offset,
98                                     guint count,
99                                     ZeitgeistResultType result_type,
100                                     gdouble **relevancies,
101                                     gint *relevancies_size,
102                                     guint *matches,
103                                     GError **error);
104 
105 private:
106   std::string ExpandType (std::string const& prefix, const gchar* unparsed_uri);
107   std::string CompileEventFilterQuery (GPtrArray *templates);
108   std::string CompileTimeRangeFilterQuery (gint64 start, gint64 end);
109   std::string CompileQueryString (const gchar *search,
110                                   ZeitgeistTimeRange *time_range,
111                                   GPtrArray *templates);
112 
113   std::string PreprocessString (std::string const& input);
114 
115   void AddDocFilters (ZeitgeistEvent *event, Xapian::Document &doc);
116   void IndexText (std::string const& text);
117   bool IndexUri (std::string const& uri, std::string const& origin);
118   bool IndexActor (std::string const& actor, bool is_subject);
119 
120   gboolean ClearFailedLookupsCb ();
121 
122   ZeitgeistDbReader        *zg_reader;
123   Xapian::WritableDatabase *db;
124   Xapian::QueryParser      *query_parser;
125   Xapian::Enquire          *enquire;
126   Xapian::TermGenerator    *tokenizer;
127   AppInfoMap                app_info_cache;
128   ApplicationSet            failed_lookups;
129   GChecksum                *checksum;
130   GRegex                   *uri_schemes_regex;
131 
132   guint                     clear_failed_id;
133   std::string               home_dir_path;
134   bool                      blacklisting_enabled;
135 };
136 
137 }
138 
139 #endif /* _ZGFTS_INDEXER_H_ */
140