summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSeif Lotfy <seif@lotfy.com>2013-01-10 17:06:07 +0100
committerSeif Lotfy <seif@lotfy.com>2013-01-10 17:06:07 +0100
commitb85ffe30301a4ac0ee430330f12932757a018234 (patch)
tree84da74d9cde8d98aad17e3521aa2d5dd85bfb153
parent769a5e311a1e5024703091018a6d66e26a5c5f12 (diff)
downloadzeitgeist-b85ffe30301a4ac0ee430330f12932757a018234.tar.gz
Work on 0.9.5 update
-rw-r--r--src/engine.vala186
1 files changed, 134 insertions, 52 deletions
diff --git a/src/engine.vala b/src/engine.vala
index 77e711c5..58a5bc0d 100644
--- a/src/engine.vala
+++ b/src/engine.vala
@@ -1,6 +1,6 @@
/* engine.vala
*
- * Copyright © 2011 Collabora Ltd.
+ * Copyright © 2011-2012 Collabora Ltd.
* By Siegfried-Angel Gevatter Pujals <siegfried@gevatter.com>
* By Seif Lotfy <seif@lotfy.com>
*
@@ -76,6 +76,7 @@ public class Engine : DbReader
database.begin_transaction ();
try
{
+ insert_event_data (events);
for (int i = 0; i < events.length; ++i)
{
if (events[i] != null)
@@ -96,14 +97,31 @@ public class Engine : DbReader
private void preprocess_event (Event event) throws EngineError
{
+ if (is_empty_string (event.interpretation)
+ || is_empty_string (event.manifestation)
+ || is_empty_string (event.actor))
+ {
+ throw new EngineError.INVALID_ARGUMENT (
+ "Incomplete event: interpretation, manifestation and actor " +
+ "are required");
+ }
+
// Iterate through subjects and check for validity
- for (int i = 0; i < event.num_subjects(); ++i)
+ for (int i = 0; i < event.num_subjects (); ++i)
{
unowned Subject subject = event.subjects[i];
- // If current_uri is unset, give it the same value as URI
+ if (is_empty_string (subject.uri))
+ {
+ throw new EngineError.INVALID_ARGUMENT (
+ "Incomplete event: subject without URI");
+ }
+
+ // If current_{uri,origin} are unset, set them to the same as URI
if (is_empty_string (subject.current_uri))
subject.current_uri = subject.uri;
+ if (is_empty_string (subject.current_origin))
+ subject.current_origin = subject.origin;
if (event.interpretation == ZG.MOVE_EVENT
&& subject.uri == subject.current_uri)
@@ -121,6 +139,14 @@ public class Engine : DbReader
"'MOVE_EVENT' then subject.uri and " +
"subject.current_uri have to be the same");
}
+ if (event.interpretation != ZG.MOVE_EVENT
+ && subject.origin != subject.current_origin)
+ {
+ throw new EngineError.INVALID_ARGUMENT (
+ "Illegal event: unless event.interpretation is " +
+ "'MOVE_EVENT' then subject.origin and " +
+ "subject.current_origin have to be the same");
+ }
// If subject manifestation and interpretation are not set,
// we try to automatically determine them from the other data.
@@ -141,37 +167,83 @@ public class Engine : DbReader
}
}
- private uint32 insert_event (Event event) throws EngineError
- requires (event.id == 0)
- requires (event.num_subjects () > 0)
+ private class DataInserter
{
- event.id = ++last_id;
+ // This is the maximum number of "unions" SQLite supports
+ private static const int MAX_PARAMETERS = 500;
+
+ private Database database;
+ private string type;
+ private GenericArray<string> data;
+
+ public DataInserter (Database db, string data_type)
+ {
+ database = db;
+ type = data_type;
+ data = new GenericArray<string> ();
+ }
+
+ ~DataInserter ()
+ {
+ if (data.length > 0)
+ warning ("DataInserter: destroyed with unflushed data");
+ }
+
+ public void add (string val) throws EngineError
+ {
+ if (data.length == MAX_PARAMETERS)
+ flush ();
+ data.add (val);
+ }
+
+ public void flush () throws EngineError
+ {
+ if (data.length > 0)
+ {
+ database.insert_or_ignore_into_table (type, data);
+ data = new GenericArray<string> ();
+ }
+ }
+ }
+
+ /**
+ * Makes sure all the URIs, texts and storage values used
+ * by the given events are in the database.
+ */
+ private void insert_event_data (GenericArray<Event> events)
+ throws EngineError
+ {
+ var uris = new DataInserter (database, "uri");
+ var texts = new DataInserter (database, "text");
+ var storages = new DataInserter (database, "storage");
- // Make sure all the URIs, texts and storage are inserted
+ for (int j = 0; j < events.length; ++j)
{
- var uris = new GenericArray<string> ();
- var texts = new GenericArray<string> ();
- var storages = new GenericArray<string> ();
+ if (events[j] == null) continue;
+
+ Event event = events[j];
var subj_uris = new SList<string> ();
if (!is_empty_string (event.origin))
uris.add (event.origin);
// Iterate through subjects and check for validity
- for (int i = 0; i < event.num_subjects(); ++i)
+ for (int i = 0; i < event.num_subjects (); ++i)
{
unowned Subject subject = event.subjects[i];
- if (subj_uris.find_custom(subject.uri, strcmp) != null)
+ if (subj_uris.find_custom (subject.uri, strcmp) != null)
{
// Events with two subjects with the same URI are not supported.
- warning ("Events with two subjects with the same URI are not supported");
- return 0;
+ throw new EngineError.INVALID_EVENT (
+ "Events with two subjects with the same URI are not supported");
}
subj_uris.append (subject.uri);
uris.add (subject.uri);
if (subject.uri != subject.current_uri)
uris.add (subject.current_uri);
+ if (subject.origin != subject.current_origin)
+ uris.add (subject.current_origin);
if (!is_empty_string (subject.origin))
uris.add (subject.origin);
@@ -180,23 +252,28 @@ public class Engine : DbReader
if (!is_empty_string(subject.storage))
storages.add (subject.storage);
}
-
- try
- {
- if (uris.length > 0)
- database.insert_or_ignore_into_table ("uri", uris);
- if (texts.length > 0)
- database.insert_or_ignore_into_table ("text", texts);
- if (storages.length > 0)
- database.insert_or_ignore_into_table ("storage", storages);
- }
- catch (EngineError e)
- {
- warning ("Can't insert data for event: " + e.message);
- return 0;
- }
}
+ uris.flush ();
+ texts.flush ();
+ storages.flush ();
+ }
+
+ private void bind_cached_reference (Sqlite.Statement stmt,
+ int position, TableLookup table, string? value_) throws EngineError
+ {
+ if (value_ != null)
+ stmt.bind_int64 (position, table.id_for_string (value_));
+ else
+ stmt.bind_null (position);
+ }
+
+ private uint32 insert_event (Event event) throws EngineError
+ requires (event.id == 0)
+ requires (event.num_subjects () > 0)
+ {
+ event.id = ++last_id;
+
var payload_id = store_payload (event);
// FIXME: Should we add something just like TableLookup but with LRU
@@ -211,11 +288,11 @@ public class Engine : DbReader
insert_stmt.bind_int64 (1, event.id);
insert_stmt.bind_int64 (2, event.timestamp);
- insert_stmt.bind_int64 (3,
- interpretations_table.id_for_string (event.interpretation));
- insert_stmt.bind_int64 (4,
- manifestations_table.id_for_string (event.manifestation));
- insert_stmt.bind_int64 (5, actors_table.id_for_string (event.actor));
+ bind_cached_reference (insert_stmt, 3, interpretations_table,
+ event.interpretation);
+ bind_cached_reference (insert_stmt, 4, manifestations_table,
+ event.manifestation);
+ bind_cached_reference (insert_stmt, 5, actors_table, event.actor);
insert_stmt.bind_text (6, event.origin);
insert_stmt.bind_int64 (7, payload_id);
@@ -227,16 +304,17 @@ public class Engine : DbReader
insert_stmt.bind_text (8, subject.uri);
insert_stmt.bind_text (9, subject.current_uri);
- insert_stmt.bind_int64 (10,
- interpretations_table.id_for_string (subject.interpretation));
- insert_stmt.bind_int64 (11,
- manifestations_table.id_for_string (subject.manifestation));
+ bind_cached_reference (insert_stmt, 10, interpretations_table,
+ subject.interpretation);
+ bind_cached_reference (insert_stmt, 11, manifestations_table,
+ subject.manifestation);
insert_stmt.bind_text (12, subject.origin);
- insert_stmt.bind_int64 (13,
- mimetypes_table.id_for_string (subject.mimetype));
- insert_stmt.bind_text (14, subject.text);
+ insert_stmt.bind_text (13, subject.current_origin);
+ bind_cached_reference (insert_stmt, 14, mimetypes_table,
+ subject.mimetype);
+ insert_stmt.bind_text (15, subject.text);
// FIXME: Consider a storages_table table. Too dangerous?
- insert_stmt.bind_text (15, subject.storage);
+ insert_stmt.bind_text (16, subject.storage);
if ((rc = insert_stmt.step()) != Sqlite.DONE) {
if (rc != Sqlite.CONSTRAINT)
@@ -255,11 +333,12 @@ public class Engine : DbReader
retrieval_stmt.reset ();
retrieval_stmt.bind_int64 (1, event.timestamp);
- retrieval_stmt.bind_int64 (2,
- interpretations_table.id_for_string (event.interpretation));
- retrieval_stmt.bind_int64 (3,
- manifestations_table.id_for_string (event.manifestation));
- retrieval_stmt.bind_int64 (4, actors_table.id_for_string (event.actor));
+ bind_cached_reference (retrieval_stmt, 2,
+ interpretations_table, event.interpretation);
+ bind_cached_reference (retrieval_stmt, 3,
+ manifestations_table, event.manifestation);
+ bind_cached_reference (retrieval_stmt, 4,
+ actors_table, event.actor);
if ((rc = retrieval_stmt.step ()) != Sqlite.ROW) {
database.assert_not_corrupt (rc);
@@ -275,7 +354,9 @@ public class Engine : DbReader
{
handle_move_event (event);
}
-
+ // After every 1000 events we analyze the queries
+ if (event.id % 1000 == 0)
+ Idle.add((SourceFunc)database.analyze);
return event.id;
}
@@ -336,9 +417,10 @@ public class Engine : DbReader
unowned Sqlite.Statement move_stmt = database.move_handling_stmt;
move_stmt.reset();
move_stmt.bind_text (1, subject.current_uri);
- move_stmt.bind_text (2, subject.uri);
- move_stmt.bind_text (3, event.interpretation);
- move_stmt.bind_int64 (4, event.timestamp);
+ move_stmt.bind_text (2, subject.current_origin);
+ move_stmt.bind_text (3, subject.uri);
+ move_stmt.bind_text (4, event.interpretation);
+ move_stmt.bind_int64 (5, event.timestamp);
if ((rc = move_stmt.step()) != Sqlite.DONE) {
if (rc != Sqlite.CONSTRAINT)
{