public void Checkpoint() { lock (connection) { // Commit any outstanding changes and open a new transaction SqliteUtils.DoNonQuery(connection, "COMMIT"); SqliteUtils.DoNonQuery(connection, "BEGIN"); } }
private void MaybeStartTransaction_Unlocked() { if (transaction_state == TransactionState.Requested) { SqliteUtils.DoNonQuery(connection, "BEGIN"); } transaction_state = TransactionState.Started; }
public EvolutionSummaryTracker(string directory, string account_name, string folder_name) { // Make the on-disk files for folders have sane names folder_name = folder_name.Replace('/', '-'); folder_name = folder_name.Replace(':', '_'); folder_name = folder_name.Replace(',', ' '); // Causes problems with the ConnectionString otherwise string filename = Path.Combine(directory, String.Format("SummaryTracker-{0}-{1}.db", account_name, folder_name)); bool create_new_db = !File.Exists(filename); bool purge_old_db = false; connection = GetConnection(filename); try { connection.Open(); } catch (ApplicationException) { purge_old_db = true; } if (!create_new_db && !purge_old_db) { // Run a dummy SELECT statement to catch more errors // indicating sqlite version mismatches. using (SqliteCommand command = new SqliteCommand()) { command.Connection = connection; command.CommandText = "SELECT flags FROM mapping WHERE uid = 'fo/ky'"; SqliteDataReader reader; try { reader = SqliteUtils.ExecuteReaderOrWait(command); reader.Close(); } catch (ApplicationException) { purge_old_db = true; } } } if (purge_old_db) { connection.Dispose(); // Purge the old database and create a new one File.Delete(filename); connection = GetConnection(filename); connection.Open(); create_new_db = true; } if (create_new_db) { CreateDatabase(); } // Start a transaction for any updates SqliteUtils.DoNonQuery(connection, "BEGIN"); }
public void Remove(string uid) { lock (connection) { SqliteUtils.DoNonQuery(connection, "DELETE FROM mapping WHERE uid=@uid", new string [] { "@uid" }, new object [] { uid }); } }
public void AddLinks(Uri uri, IList <string> links) { lock (connection) { MaybeStartTransaction_Unlocked(); UpdateLinksCommand.Parameters.AddWithValue("@uri", UriToString(uri)); UpdateLinksCommand.Parameters.AddWithValue("@links", GetLinksText(links)); SqliteUtils.DoNonQuery(UpdateLinksCommand); } }
public void CommitTransaction() { if (transaction_state == TransactionState.Started) { lock (connection) SqliteUtils.DoNonQuery(connection, "COMMIT"); } transaction_state = TransactionState.None; }
public void Close() { lock (connection) { // Commit any outstanding changes SqliteUtils.DoNonQuery(connection, "COMMIT"); connection.Close(); connection = null; } }
private void Insert(Uri uri, string filename, byte[] data) { lock (connection) { MaybeStartTransaction_Unlocked(); InsertCommand.Parameters.AddWithValue("@uri", UriToString(uri)); InsertCommand.Parameters.AddWithValue("@filename", filename); InsertCommand.Parameters.AddWithValue("@data", data); SqliteUtils.DoNonQuery(InsertCommand); } }
public void Update(string uid, uint flags) { lock (connection) { SqliteUtils.DoNonQuery(connection, "INSERT OR REPLACE INTO mapping " + " (uid, flags, last_seen) " + " VALUES (@uid, @flags, @last_seen)", new string [] { "@uid", "@flags", "@last_seen" }, new object [] { uid, flags, StringFu.DateTimeToString(DateTime.UtcNow) }); } }
public void Flush() { lock (connection) { if (transaction_count > 0) { Logger.Log.Debug("Flushing requested -- committing sqlite transaction"); SqliteUtils.DoNonQuery(connection, "COMMIT"); transaction_count = 0; } } }
private void CreateDatabase() { SqliteUtils.DoNonQuery(connection, "CREATE TABLE mapping ( " + " uid TEXT UNIQUE, " + " flags INTEGER NOT NULL, " + " last_seen TEXT NOT NULL " + ")"); SqliteUtils.DoNonQuery(connection, "CREATE INDEX mapping_uid on mapping (uid)"); }
public void Delete(Uri uri) { lock (connection) { string path = LookupPathRawUnlocked(uri); if (path != null) { MaybeStartTransaction_Unlocked(); DeleteCommand.Parameters.AddWithValue("@uri", UriToString(uri)); SqliteUtils.DoNonQuery(DeleteCommand); if (path != SELF_CACHE_TAG && path != BLOB_TAG) { File.Delete(Path.Combine(text_cache_dir, path)); } } } }
public bool Write(FileAttributes fa) { SetPathFlag(fa.Path); int ret = 0; string filter_name; // We need to quote any 's that appear in the strings // (in particular, in the path) lock (connection) { // If a transaction has been requested, start it now. MaybeStartTransaction(); filter_name = fa.FilterName; if (filter_name == null) { filter_name = ""; } filter_name = filter_name.Replace("'", "''"); string[] param = new string [] { "@unique_id", "@directory", "@filename", "@last_mtime", "@last_attrtime", "@filter_name", "@filter_version" }; object[] vals = new object [] { GuidFu.ToShortString(fa.UniqueId), fa.Directory.Replace("'", "''"), fa.Filename.Replace("'", "''"), StringFu.DateTimeToString(fa.LastWriteTime), StringFu.DateTimeToString(fa.LastAttrTime), filter_name, fa.FilterVersion }; for (int i = 0; i < param.Length; i++) { InsertCommand.Parameters.AddWithValue(param[i], vals[i]); } ret = SqliteUtils.DoNonQuery(InsertCommand); } return(ret != 0); }
public void Drop(string path) { // Sanitize the path; remove the last '/' if (path != null && path != "/" && path.EndsWith("/")) { path = path.TrimEnd('/'); } // We don't want to "UnSetPathFlag" here, since we have no way of knowing // if another path hashes to the same value as this one. // We need to quote any 's that appear in the strings // (in particular, in the path) string directory = FileSystem.GetDirectoryNameRootOk(path).Replace("'", "''"); string filename = Path.GetFileName(path).Replace("'", "''"); lock (connection) { // If a transaction has been requested, start it now. MaybeStartTransaction(); DeleteCommand.Parameters.AddWithValue("@directory", directory); DeleteCommand.Parameters.AddWithValue("@filename", filename); SqliteUtils.DoNonQuery(DeleteCommand); } }
public TextCache(string storage_dir, bool read_only) { text_cache_dir = Path.Combine(storage_dir, "TextCache"); if (!Directory.Exists(text_cache_dir)) { Directory.CreateDirectory(text_cache_dir); // Create our cache subdirectories. for (int i = 0; i < 256; ++i) { string subdir = i.ToString("x"); if (i < 16) { subdir = "0" + subdir; } subdir = Path.Combine(text_cache_dir, subdir); Directory.CreateDirectory(subdir); } } // Create our Sqlite database string db_filename = Path.Combine(text_cache_dir, "TextCache.db"); bool create_new_db = false; if (!File.Exists(db_filename)) { create_new_db = true; } // Funky logic here to deal with sqlite versions. // // When sqlite 3 tries to open an sqlite 2 database, // it will throw an SqliteException with SqliteError // NOTADB when trying to execute a command. // // When sqlite 2 tries to open an sqlite 3 database, // it will throw an ApplicationException when it // tries to open the database. try { connection = Open(db_filename); } catch (ApplicationException) { Logger.Log.Warn("Likely sqlite database version mismatch trying to open {0}. Purging.", db_filename); create_new_db = true; } if (!create_new_db) { // Run a dummy query to see if we get a NOTADB error. Sigh. SqliteCommand command; SqliteDataReader reader = null; command = new SqliteCommand(); command.Connection = connection; command.CommandText = "SELECT filename FROM textcache_data WHERE uri='blah'"; try { reader = SqliteUtils.ExecuteReaderOrWait(command); } catch (ApplicationException ex) { Logger.Log.Warn("Likely sqlite database version mismatch trying to read from {0}. Purging.", db_filename); create_new_db = true; } catch (SqliteException ex) { // When the table name changed from 0.2.18 -> 0.3.0. Logger.Log.Warn("Sqlite error: {0}. Purging textcache.", ex.Message); create_new_db = true; } if (reader != null) { reader.Dispose(); } command.Dispose(); } if (create_new_db) { if (connection != null) { connection.Dispose(); } if (read_only) { throw new UnauthorizedAccessException(String.Format("Unable to create read only text cache {0}", db_filename)); } File.Delete(db_filename); try { connection = Open(db_filename); } catch (Exception e) { Log.Debug(e, "Exception opening text cache {0}", db_filename); } // Database schema: uri, filename, data SqliteUtils.DoNonQuery(connection, "CREATE TABLE textcache_data ( " + " uri TEXT UNIQUE NOT NULL, " + " filename TEXT NOT NULL, " + " data BLOB " + ")"); } #if ENABLE_RDF_ADAPTER try { SqliteUtils.DoNonQuery(connection, "CREATE TABLE IF NOT EXISTS links_data ( " + " uri TEXT UNIQUE NOT NULL, "+ " links TEXT "+ ")"); } catch (SqliteException) { } #endif this.InitCommands(); }
public FileAttributesStore_Sqlite(string directory, string index_fingerprint) { bool create_new_db = false; path_flags = new BitArray(65536); if (!File.Exists(GetDbPath(directory))) { create_new_db = true; } else { // Funky logic here to deal with sqlite versions. // // When sqlite 3 tries to open an sqlite 2 database, // it will throw an SqliteException with SqliteError // NOTADB when trying to execute a command. // // When sqlite 2 tries to open an sqlite 3 database, // it will throw an ApplicationException when it // tries to open the database. try { connection = Open(directory); } catch (ApplicationException) { Logger.Log.Warn("Likely sqlite database version mismatch trying to open {0}. Purging.", GetDbPath(directory)); create_new_db = true; } if (!create_new_db) { SqliteCommand command; SqliteDataReader reader = null; int stored_version = 0; string stored_fingerprint = null; command = new SqliteCommand(); command.Connection = connection; command.CommandText = "SELECT version, fingerprint FROM db_info"; try { reader = SqliteUtils.ExecuteReaderOrWait(command); } catch (Exception ex) { Logger.Log.Warn("Likely sqlite database version mismatch trying to read from {0}. Purging.", GetDbPath(directory)); create_new_db = true; } if (reader != null && !create_new_db) { if (SqliteUtils.ReadOrWait(reader)) { stored_version = reader.GetInt32(0); stored_fingerprint = reader.GetString(1); } reader.Close(); } command.Dispose(); if (VERSION != stored_version || (index_fingerprint != null && index_fingerprint != stored_fingerprint)) { create_new_db = true; } } } if (create_new_db) { if (connection != null) { connection.Dispose(); } File.Delete(GetDbPath(directory)); connection = Open(directory); SqliteUtils.DoNonQuery(connection, "CREATE TABLE db_info ( " + " version INTEGER NOT NULL, " + " fingerprint TEXT NOT NULL " + ")"); SqliteUtils.DoNonQuery(connection, "INSERT INTO db_info (version, fingerprint) VALUES (@version, @index_fingerprint)", new string [] { "@version", "@index_fingerprint" }, new object [] { VERSION, index_fingerprint }); SqliteUtils.DoNonQuery(connection, "CREATE TABLE file_attributes ( " + " unique_id TEXT NOT NULL, " + " directory TEXT NOT NULL, " + " filename TEXT NOT NULL, " + " last_mtime TEXT NOT NULL, " + " last_attrtime TEXT NOT NULL, " + " filter_name TEXT NOT NULL, " + " filter_version TEXT NOT NULL, " + " UNIQUE (directory, filename) " + ")"); } else { SqliteCommand command; SqliteDataReader reader; int count = 0; DateTime dt1 = DateTime.Now; // Select all of the files and use them to populate our bit-vector. command = new SqliteCommand(); command.Connection = connection; command.CommandText = "SELECT directory, filename FROM file_attributes"; reader = SqliteUtils.ExecuteReaderOrWait(command); while (SqliteUtils.ReadOrWait(reader)) { string dir = reader.GetString(0); string file = reader.GetString(1); string path = Path.Combine(dir, file); SetPathFlag(path); ++count; } reader.Close(); command.Dispose(); DateTime dt2 = DateTime.Now; Logger.Log.Debug("Loaded {0} records from {1} in {2:0.000}s", count, GetDbPath(directory), (dt2 - dt1).TotalSeconds); } ReadCommand = new SqliteCommand(this.connection); ReadCommand.CommandText = "SELECT unique_id, directory, filename, last_mtime, last_attrtime, filter_name, filter_version " + "FROM file_attributes WHERE directory=@dir AND filename=@fname"; InsertCommand = new SqliteCommand(this.connection); InsertCommand.CommandText = "INSERT OR REPLACE INTO file_attributes " + " (unique_id, directory, filename, last_mtime, last_attrtime, filter_name, filter_version) " + " VALUES (@unique_id, @directory, @filename, @last_mtime, @last_attrtime, @filter_name, @filter_version)"; DeleteCommand = new SqliteCommand(this.connection); DeleteCommand.CommandText = "DELETE FROM file_attributes WHERE directory=@directory AND filename=@filename"; }