public MissingBlockList(string volumename, System.Data.IDbConnection connection, System.Data.IDbTransaction transaction) { m_connection = connection; m_transaction = new TemporaryTransactionWrapper(m_connection, transaction); m_volumename = volumename; var tablename = "MissingBlocks-" + Library.Utility.Utility.ByteArrayAsHexString(Guid.NewGuid().ToByteArray()); using (var cmd = m_connection.CreateCommand()) { cmd.Transaction = m_transaction.Parent; cmd.ExecuteNonQuery(string.Format(@"CREATE TEMPORARY TABLE ""{0}"" (""Hash"" TEXT NOT NULL, ""Size"" INTEGER NOT NULL, ""Restored"" INTEGER NOT NULL) ", tablename)); m_tablename = tablename; var blockCount = cmd.ExecuteNonQuery(string.Format(@"INSERT INTO ""{0}"" (""Hash"", ""Size"", ""Restored"") SELECT DISTINCT ""Block"".""Hash"", ""Block"".""Size"", 0 AS ""Restored"" FROM ""Block"",""Remotevolume"" WHERE ""Block"".""VolumeID"" = ""Remotevolume"".""ID"" AND ""Remotevolume"".""Name"" = ? ", m_tablename), volumename); if (blockCount == 0) { throw new Exception(string.Format("Unexpected empty block volume: {0}", volumename)); } cmd.ExecuteNonQuery(string.Format(@"CREATE UNIQUE INDEX ""{0}-Ix"" ON ""{0}"" (""Hash"", ""Size"", ""Restored"")", tablename)); } m_insertCommand = m_connection.CreateCommand(); m_insertCommand.Transaction = m_transaction.Parent; m_insertCommand.CommandText = string.Format(@"UPDATE ""{0}"" SET ""Restored"" = ? WHERE ""Hash"" = ? AND ""Size"" = ? AND ""Restored"" = ? ", tablename); m_insertCommand.AddParameters(4); }
public long RegisterRemoteVolume(string name, RemoteVolumeType type, RemoteVolumeState state, TimeSpan deleteGraceTime, System.Data.IDbTransaction transaction) { using (var tr = new TemporaryTransactionWrapper(m_connection, transaction)) { m_createremotevolumeCommand.SetParameterValue(0, m_operationid); m_createremotevolumeCommand.SetParameterValue(1, name); m_createremotevolumeCommand.SetParameterValue(2, type.ToString()); m_createremotevolumeCommand.SetParameterValue(3, state.ToString()); m_createremotevolumeCommand.SetParameterValue(4, 0); if (deleteGraceTime.Ticks <= 0) { m_createremotevolumeCommand.SetParameterValue(5, 0); } else { m_createremotevolumeCommand.SetParameterValue(5, (DateTime.UtcNow + deleteGraceTime).Ticks); } m_createremotevolumeCommand.Transaction = tr.Parent; var r = m_createremotevolumeCommand.ExecuteScalarInt64(); tr.Commit(); return(r); } }
public void AppendFilesFromPreviousSet(System.Data.IDbTransaction transaction, IEnumerable <string> deleted, long filesetid, long prevId, DateTime timestamp) { using (var cmd = m_connection.CreateCommand()) using (var tr = new TemporaryTransactionWrapper(m_connection, transaction)) { long lastFilesetId = prevId < 0 ? GetPreviousFilesetID(cmd, timestamp, filesetid) : prevId; cmd.Transaction = tr.Parent; cmd.ExecuteNonQuery(@"INSERT INTO ""FilesetEntry"" (""FilesetID"", ""FileID"", ""Lastmodified"") SELECT ? AS ""FilesetID"", ""FileID"", ""Lastmodified"" FROM (SELECT DISTINCT ""FilesetID"", ""FileID"", ""Lastmodified"" FROM ""FilesetEntry"" WHERE ""FilesetID"" = ? AND ""FileID"" NOT IN (SELECT ""FileID"" FROM ""FilesetEntry"" WHERE ""FilesetID"" = ?)) ", filesetid, lastFilesetId, filesetid); if (deleted != null) { cmd.CommandText = @"DELETE FROM ""FilesetEntry"" WHERE ""FilesetID"" = ? AND ""FileID"" IN (SELECT ""ID"" FROM ""File"" WHERE ""Path"" = ?) "; cmd.AddParameter(filesetid); cmd.AddParameter(); foreach (string s in deleted) { cmd.SetParameterValue(1, s); cmd.ExecuteNonQuery(); } } tr.Commit(); } }
/// <summary> /// Adds a metadata set to the database, and returns a value indicating if the record was new /// </summary> /// <param name="hash">The metadata hash</param> /// <param name="metadataid">The id of the metadata set</param> /// <returns>True if the set was added to the database, false otherwise</returns> public bool AddMetadataset(string filehash, long size, int blocksize, IEnumerable <string> blockhashes, IEnumerable <string> blocklisthashes, out long metadataid, System.Data.IDbTransaction transaction = null) { if (size > 0) { m_findmetadatasetCommand.Transaction = transaction; metadataid = m_findmetadatasetCommand.ExecuteScalarInt64(null, -1, filehash, size); if (metadataid != -1) { return(false); } long blocksetid; AddBlockset(filehash, size, blocksize, blockhashes, blocklisthashes, out blocksetid, transaction); using (var tr = new TemporaryTransactionWrapper(m_connection, transaction)) { m_insertmetadatasetCommand.Transaction = tr.Parent; m_insertmetadatasetCommand.SetParameterValue(0, blocksetid); metadataid = m_insertmetadatasetCommand.ExecuteScalarInt64(); tr.Commit(); } return(true); } metadataid = -2; return(false); }
/// <summary> /// Adds a file record to the database /// </summary> /// <param name="filename">The path to the file</param> /// <param name="lastmodified">The time the file was modified</param> /// <param name="blocksetID">The ID of the hashkey for the file</param> /// <param name="metadataID">The ID for the metadata</param> /// <param name="transaction">The transaction to use for insertion, or null for no transaction</param> /// <param name="operationId">The operationId to use, or -1 to use the current operation</param> public void AddFile(string filename, DateTime lastmodified, long blocksetID, long metadataID, System.Data.IDbTransaction transaction) { var fileidobj = -1L; PathEntryKeeper entry = null; var entryFound = false; if (m_pathLookup != null) { if (entryFound = (m_pathLookup.TryFind(filename, out entry) && entry != null)) { var fid = entry.GetFilesetID(blocksetID, metadataID); if (fid >= 0) { fileidobj = fid; } } } else { m_findfilesetCommand.Transaction = transaction; m_findfilesetCommand.SetParameterValue(0, blocksetID); m_findfilesetCommand.SetParameterValue(1, metadataID); m_findfilesetCommand.SetParameterValue(2, filename); fileidobj = m_findfilesetCommand.ExecuteScalarInt64(); } if (fileidobj == -1) { using (var tr = new TemporaryTransactionWrapper(m_connection, transaction)) { m_insertfileCommand.Transaction = tr.Parent; m_insertfileCommand.SetParameterValue(0, filename); m_insertfileCommand.SetParameterValue(1, blocksetID); m_insertfileCommand.SetParameterValue(2, metadataID); fileidobj = m_insertfileCommand.ExecuteScalarInt64(); tr.Commit(); // We do not need to update this, because we will not ask for the same file twice if (m_pathLookup != null) { if (!entryFound) { entry = new PathEntryKeeper(-1, new DateTime(0, DateTimeKind.Utc), -1, null, -1); entry.AddFilesetID(blocksetID, metadataID, fileidobj); m_pathLookup.Insert(filename, entry); } else { entry.AddFilesetID(blocksetID, metadataID, fileidobj); } } } } m_insertfileOperationCommand.Transaction = transaction; m_insertfileOperationCommand.SetParameterValue(0, m_filesetId); m_insertfileOperationCommand.SetParameterValue(1, fileidobj); m_insertfileOperationCommand.SetParameterValue(2, lastmodified.ToUniversalTime().Ticks); m_insertfileOperationCommand.ExecuteNonQuery(); }
public void RemoveRemoteVolume(string name, System.Data.IDbTransaction transaction = null) { using (var tr = new TemporaryTransactionWrapper(m_connection, transaction)) using (var deletecmd = m_connection.CreateCommand()) { deletecmd.Transaction = tr.Parent; var volumeid = GetRemoteVolumeID(name, tr.Parent); // If the volume is a block volume, this will update the crosslink table, otherwise nothing will happen deletecmd.ExecuteNonQuery(@"DELETE FROM ""IndexBlockLink"" WHERE ""BlockVolumeID"" = ? ", volumeid); // If the volume is a fileset, this will remove the fileset, otherwise nothing will happen deletecmd.ExecuteNonQuery(@"DELETE FROM ""FilesetEntry"" WHERE ""FilesetID"" IN (SELECT ""ID"" FROM ""Fileset"" WHERE ""VolumeID"" = ?)", volumeid); deletecmd.ExecuteNonQuery(@"DELETE FROM ""Fileset"" WHERE ""VolumeID"" = ?", volumeid); var subQuery = @"(SELECT DISTINCT ""BlocksetEntry"".""BlocksetID"" FROM ""BlocksetEntry"", ""Block"" WHERE ""BlocksetEntry"".""BlockID"" = ""Block"".""ID"" AND ""Block"".""VolumeID"" = ?)"; deletecmd.ExecuteNonQuery(@"DELETE FROM ""File"" WHERE ""BlocksetID"" IN " + subQuery, volumeid); deletecmd.ExecuteNonQuery(@"DELETE FROM ""Metadataset"" WHERE ""BlocksetID"" IN " + subQuery, volumeid); deletecmd.ExecuteNonQuery(@"DELETE FROM ""Blockset"" WHERE ""ID"" IN " + subQuery, volumeid); deletecmd.ExecuteNonQuery(@"DELETE FROM ""BlocksetEntry"" WHERE ""BlocksetID"" IN " + subQuery, volumeid); deletecmd.ExecuteNonQuery(@"DELETE FROM ""Block"" WHERE ""VolumeID"" = ?", volumeid); deletecmd.ExecuteNonQuery(@"DELETE FROM ""DeletedBlock"" WHERE ""VolumeID"" = ?", volumeid); ((System.Data.IDataParameter)m_removeremotevolumeCommand.Parameters[0]).Value = name; m_removeremotevolumeCommand.Transaction = tr.Parent; m_removeremotevolumeCommand.ExecuteNonQuery(); tr.Commit(); } }
/// <summary> /// Adds a file record to the database /// </summary> /// <param name="filename">The path to the file</param> /// <param name="scantime">The time the file was scanned</param> /// <param name="blocksetID">The ID of the hashkey for the file</param> /// <param name="metadataID">The ID for the metadata</param> /// <param name="transaction">The transaction to use for insertion, or null for no transaction</param> /// <param name="operationId">The operationId to use, or -1 to use the current operation</param> public void AddFile(string filename, DateTime scantime, long blocksetID, long metadataID, System.Data.IDbTransaction transaction) { object fileidobj = null; PathEntryKeeper entry = null; bool entryFound = false; if (m_pathLookup != null) { if (entryFound = (m_pathLookup.TryFind(filename, out entry) && entry != null)) { var fid = entry.GetFilesetID(blocksetID, metadataID); if (fid >= 0) { fileidobj = fid; } } } else { m_findfilesetCommand.Transaction = transaction; m_findfilesetCommand.SetParameterValue(0, blocksetID); m_findfilesetCommand.SetParameterValue(1, metadataID); m_findfilesetCommand.SetParameterValue(2, filename); fileidobj = m_findfilesetCommand.ExecuteScalar(); } if (fileidobj == null || fileidobj == DBNull.Value) { using (var tr = new TemporaryTransactionWrapper(m_connection, transaction)) { m_insertfileCommand.Transaction = tr.Parent; m_insertfileCommand.SetParameterValue(0, filename); m_insertfileCommand.SetParameterValue(1, blocksetID); m_insertfileCommand.SetParameterValue(2, metadataID); fileidobj = Convert.ToInt64(m_insertfileCommand.ExecuteScalar()); tr.Commit(); // We do not need to update this, because we will not ask for the same file twice if (m_pathLookup != null) { if (!entryFound) { entry = new PathEntryKeeper(-1, DateTime.UtcNow); entry.AddFilesetID(blocksetID, metadataID, Convert.ToInt64(fileidobj)); m_pathLookup.Insert(filename, entry); } else { entry.AddFilesetID(blocksetID, metadataID, Convert.ToInt64(fileidobj)); } } } } m_insertfileOperationCommand.Transaction = transaction; m_insertfileOperationCommand.SetParameterValue(0, m_filesetId); m_insertfileOperationCommand.SetParameterValue(1, fileidobj); m_insertfileOperationCommand.SetParameterValue(2, NormalizeDateTimeToEpochSeconds(scantime)); m_insertfileOperationCommand.ExecuteNonQuery(); }
/// <summary> /// Creates a timestamped backup operation to correctly associate the fileset with the time it was created. /// </summary> /// <param name="volumeid">The ID of the fileset volume to update</param> /// <param name="timestamp">The timestamp of the operation to create</param> /// <param name="transaction">An optional external transaction</param> public virtual long CreateFileset(long volumeid, DateTime timestamp, System.Data.IDbTransaction transaction = null) { using (var cmd = m_connection.CreateCommand()) using (var tr = new TemporaryTransactionWrapper(m_connection, transaction)) { cmd.Transaction = tr.Parent; var id = Convert.ToInt64(cmd.ExecuteScalar(@"INSERT INTO ""Fileset"" (""OperationID"", ""Timestamp"", ""VolumeID"") VALUES (?, ?, ?); SELECT last_insert_rowid();", m_operationid, NormalizeDateTimeToEpochSeconds(timestamp), volumeid)); tr.Commit(); return(id); } }
public void SetDbOptions(IDictionary <string, string> options, System.Data.IDbTransaction transaction = null) { using (var tr = new TemporaryTransactionWrapper(m_connection, transaction)) using (var cmd = m_connection.CreateCommand()) { cmd.Transaction = tr.Parent; cmd.ExecuteNonQuery(@"DELETE FROM ""Configuration"" "); foreach (var kp in options) { cmd.ExecuteNonQuery(@"INSERT INTO ""Configuration"" (""Key"", ""Value"") VALUES (?, ?) ", kp.Key, kp.Value); } tr.Commit(); } }
public long RegisterRemoteVolume(string name, RemoteVolumeType type, RemoteVolumeState state, System.Data.IDbTransaction transaction = null) { using (var tr = new TemporaryTransactionWrapper(m_connection, transaction)) { m_createremotevolumeCommand.SetParameterValue(0, m_operationid); m_createremotevolumeCommand.SetParameterValue(1, name); m_createremotevolumeCommand.SetParameterValue(2, type.ToString()); m_createremotevolumeCommand.SetParameterValue(3, state.ToString()); m_createremotevolumeCommand.SetParameterValue(4, 0); m_createremotevolumeCommand.Transaction = tr.Parent; var r = Convert.ToInt64(m_createremotevolumeCommand.ExecuteScalar()); tr.Commit(); return(r); } }
/// <summary> /// Adds a metadata set to the database, and returns a value indicating if the record was new /// </summary> /// <param name="hash">The metadata hash</param> /// <param name="metadataid">The id of the metadata set</param> /// <returns>True if the set was added to the database, false otherwise</returns> public bool AddMetadataset(string filehash, long size, long blocksetid, out long metadataid, System.Data.IDbTransaction transaction = null) { if (GetMetadatasetID(filehash, size, out metadataid, transaction)) { return(false); } using (var tr = new TemporaryTransactionWrapper(m_connection, transaction)) { m_insertmetadatasetCommand.Transaction = tr.Parent; m_insertmetadatasetCommand.SetParameterValue(0, blocksetid); metadataid = m_insertmetadatasetCommand.ExecuteScalarInt64(); tr.Commit(); return(true); } }
/// <summary> /// Adds a metadata set to the database, and returns a value indicating if the record was new /// </summary> /// <param name="hash">The metadata hash</param> /// <param name="metadataid">The id of the metadata set</param> /// <returns>True if the set was added to the database, false otherwise</returns> public bool AddMetadataset(string hash, long size, out long metadataid, System.Data.IDbTransaction transaction = null) { if (size > 0) { if (m_metadataLookup != null) { if (m_metadataLookup.TryGet(hash, size, out metadataid)) { return(false); } } else { m_findmetadatasetProbeCommand.Transaction = transaction; var r = m_findmetadatasetProbeCommand.ExecuteScalar(null, hash, size); if (r != null && r != DBNull.Value) { m_findmetadatasetCommand.Transaction = transaction; m_findmetadatasetCommand.ExecuteScalar(null, hash, size); } } long blocksetid; AddBlockset(hash, size, (int)size, new string[] { hash }, null, out blocksetid, transaction); using (var tr = new TemporaryTransactionWrapper(m_connection, transaction)) { m_insertmetadatasetCommand.Transaction = tr.Parent; m_insertmetadatasetCommand.SetParameterValue(0, blocksetid); metadataid = Convert.ToInt64(m_insertmetadatasetCommand.ExecuteScalar()); tr.Commit(); if (m_metadataLookup != null) { m_metadataLookup.Add(hash, size, metadataid); } } return(true); } metadataid = -2; return(false); }
public void RenameRemoteFile(string oldname, string newname, System.Data.IDbTransaction transaction) { using (var tr = new TemporaryTransactionWrapper(m_connection, transaction)) using (var cmd = m_connection.CreateCommand()) { cmd.Transaction = tr.Parent; //Rename the old entry, to preserve ID links var c = cmd.ExecuteNonQuery(@"UPDATE ""Remotevolume"" SET ""Name"" = ? WHERE ""Name"" = ?", newname, oldname); if (c != 1) { throw new Exception(string.Format("Unexpected result from renaming \"{0}\" to \"{1}\", expected {2} got {3}", oldname, newname, 1, c)); } // Grab the type of entry var type = (RemoteVolumeType)Enum.Parse(typeof(RemoteVolumeType), cmd.ExecuteScalar(@"SELECT ""Type"" FROM ""Remotevolume"" WHERE ""Name"" = ?", newname).ToString(), true); //Create a fake new entry with the old name and mark as deleting // as this ensures we will remove it, if it shows up in some later listing RegisterRemoteVolume(oldname, type, RemoteVolumeState.Deleting, tr.Parent); tr.Commit(); } }
/// <summary> /// Adds a blockset to the database, returns a value indicating if the blockset is new /// </summary> /// <param name="filehash">The hash of the blockset</param> /// <param name="size">The size of the blockset</param> /// <param name="fragmentoffset">The fragmentoffset for the last block</param> /// <param name="fragmenthash">The hash of the fragment</param> /// <param name="hashes">The list of hashes</param> /// <param name="blocksetid">The id of the blockset, new or old</param> /// <returns>True if the blockset was created, false otherwise</returns> public bool AddBlockset(string filehash, long size, int blocksize, IEnumerable <string> hashes, IEnumerable <string> blocklistHashes, out long blocksetid, System.Data.IDbTransaction transaction = null) { m_findblocksetCommand.Transaction = transaction; blocksetid = m_findblocksetCommand.ExecuteScalarInt64(null, -1, filehash, size); if (blocksetid != -1) { return(false); //Found it } using (var tr = new TemporaryTransactionWrapper(m_connection, transaction)) { m_insertblocksetCommand.Transaction = tr.Parent; m_insertblocksetCommand.SetParameterValue(0, size); m_insertblocksetCommand.SetParameterValue(1, filehash); blocksetid = m_insertblocksetCommand.ExecuteScalarInt64(); long ix = 0; if (blocklistHashes != null) { m_insertblocklistHashesCommand.SetParameterValue(0, blocksetid); m_insertblocklistHashesCommand.Transaction = tr.Parent; foreach (var bh in blocklistHashes) { m_insertblocklistHashesCommand.SetParameterValue(1, ix); m_insertblocklistHashesCommand.SetParameterValue(2, bh); m_insertblocklistHashesCommand.ExecuteNonQuery(); ix++; } } m_insertblocksetentryCommand.SetParameterValue(0, blocksetid); m_insertblocksetentryCommand.Transaction = tr.Parent; m_insertblocksetentryFastCommand.SetParameterValue(0, blocksetid); m_insertblocksetentryFastCommand.Transaction = tr.Parent; ix = 0; long remainsize = size; foreach (var h in hashes) { var exsize = remainsize < blocksize ? remainsize : blocksize; m_insertblocksetentryCommand.SetParameterValue(1, ix); m_insertblocksetentryCommand.SetParameterValue(2, h); m_insertblocksetentryCommand.SetParameterValue(3, exsize); var c = m_insertblocksetentryCommand.ExecuteNonQuery(); if (c != 1) { m_result.AddError(string.Format("Checking errors, related to #1400. Unexpected result count: {0}, expected {1}, hash: {2}, size: {3}, blocksetid: {4}, ix: {5}, fullhash: {6}, fullsize: {7}", c, 1, h, exsize, blocksetid, ix, filehash, size), null); using (var cmd = m_connection.CreateCommand(tr.Parent)) { var bid = cmd.ExecuteScalarInt64(@"SELECT ""ID"" FROM ""Block"" WHERE ""Hash"" = ?", -1, h); if (bid == -1) { throw new Exception(string.Format("Could not find any blocks with the given hash: {0}", h)); } foreach (var rd in cmd.ExecuteReaderEnumerable(@"SELECT ""Size"" FROM ""Block"" WHERE ""Hash"" = ?", h)) { m_result.AddError(string.Format("Found block with ID {0} and hash {1} and size {2}", bid, h, rd.ConvertValueToInt64(0, -1)), null); } } throw new Exception(string.Format("Unexpected result count: {0}, expected {1}, check log for more messages", c, 1)); } ix++; remainsize -= blocksize; } tr.Commit(); } return(true); }
public FilteredFilenameTable(System.Data.IDbConnection connection, Library.Utility.IFilter filter, System.Data.IDbTransaction transaction) { m_connection = connection; Tablename = "Filenames-" + Library.Utility.Utility.ByteArrayAsHexString(Guid.NewGuid().ToByteArray()); var type = Library.Utility.FilterType.Regexp; if (filter is Library.Utility.FilterExpression) { type = ((Library.Utility.FilterExpression)filter).Type; } if (type == Library.Utility.FilterType.Regexp) { using (var cmd = m_connection.CreateCommand()) { cmd.Transaction = transaction; cmd.ExecuteNonQuery(string.Format(@"CREATE TEMPORARY TABLE ""{0}"" (""Path"" TEXT NOT NULL)", Tablename)); using (var tr = new TemporaryTransactionWrapper(m_connection, transaction)) { cmd.CommandText = string.Format(@"INSERT INTO ""{0}"" (""Path"") VALUES (?)", Tablename); cmd.AddParameter(); cmd.Transaction = tr.Parent; using (var c2 = m_connection.CreateCommand()) using (var rd = c2.ExecuteReader(@"SELECT DISTINCT ""Path"" FROM ""File"" ")) while (rd.Read()) { var p = rd.GetValue(0).ToString(); if (Library.Utility.FilterExpression.Matches(filter, p)) { cmd.SetParameterValue(0, p); cmd.ExecuteNonQuery(); } } tr.Commit(); } } } else { var sb = new StringBuilder(); var args = new List <object>(); foreach (var f in ((Library.Utility.FilterExpression)filter).GetSimpleList()) { if (f.Contains('*') || f.Contains('?')) { sb.Append(@"""Path"" LIKE ? OR "); args.Add(f.Replace('*', '%').Replace('?', '_')); } else { sb.Append(@"""Path"" = ? OR "); args.Add(f); } } sb.Length = sb.Length - " OR ".Length; using (var cmd = m_connection.CreateCommand()) using (var tr = new TemporaryTransactionWrapper(m_connection, transaction)) { cmd.Transaction = tr.Parent; cmd.ExecuteNonQuery(string.Format(@"CREATE TEMPORARY TABLE ""{0}"" (""Path"" TEXT NOT NULL)", Tablename)); cmd.ExecuteNonQuery(string.Format(@"INSERT INTO ""{0}"" SELECT DISTINCT ""Path"" FROM ""File"" WHERE " + sb.ToString(), Tablename), args.ToArray()); tr.Commit(); } } }
public MissingBlockList(string volumename, System.Data.IDbConnection connection, System.Data.IDbTransaction transaction) { m_connection = connection; m_transaction = new TemporaryTransactionWrapper(m_connection, transaction); m_volumename = volumename; var tablename = "MissingBlocks-" + Library.Utility.Utility.ByteArrayAsHexString(Guid.NewGuid().ToByteArray()); using(var cmd = m_connection.CreateCommand()) { cmd.Transaction = m_transaction.Parent; cmd.ExecuteNonQuery(string.Format(@"CREATE TEMPORARY TABLE ""{0}"" (""Hash"" TEXT NOT NULL, ""Size"" INTEGER NOT NULL, ""Restored"" INTEGER NOT NULL) ", tablename)); m_tablename = tablename; var blockCount = cmd.ExecuteNonQuery(string.Format(@"INSERT INTO ""{0}"" (""Hash"", ""Size"", ""Restored"") SELECT DISTINCT ""Block"".""Hash"", ""Block"".""Size"", 0 AS ""Restored"" FROM ""Block"",""Remotevolume"" WHERE ""Block"".""VolumeID"" = ""Remotevolume"".""ID"" AND ""Remotevolume"".""Name"" = ? ", m_tablename), volumename); if (blockCount == 0) throw new Exception(string.Format("Unexpected empty block volume: {0}", volumename)); cmd.ExecuteNonQuery(string.Format(@"CREATE UNIQUE INDEX ""{0}-Ix"" ON ""{0}"" (""Hash"", ""Size"", ""Restored"")", tablename)); } m_insertCommand = m_connection.CreateCommand(); m_insertCommand.Transaction = m_transaction.Parent; m_insertCommand.CommandText = string.Format(@"UPDATE ""{0}"" SET ""Restored"" = ? WHERE ""Hash"" = ? AND ""Size"" = ? AND ""Restored"" = ? ", tablename); m_insertCommand.AddParameters(4); }
/// <summary> /// Adds a blockset to the database, returns a value indicating if the blockset is new /// </summary> /// <param name="filehash">The hash of the blockset</param> /// <param name="size">The size of the blockset</param> /// <param name="fragmentoffset">The fragmentoffset for the last block</param> /// <param name="fragmenthash">The hash of the fragment</param> /// <param name="hashes">The list of hashes</param> /// <param name="blocksetid">The id of the blockset, new or old</param> /// <returns>True if the blockset was created, false otherwise</returns> public bool AddBlockset(string filehash, long size, int blocksize, IEnumerable <string> hashes, IEnumerable <string> blocklistHashes, out long blocksetid, System.Data.IDbTransaction transaction = null) { object r = null; if (m_fileHashLookup != null) { if (m_fileHashLookup.TryGet(filehash, size, out blocksetid)) { return(false); } } else { m_findblocksetCommand.Transaction = transaction; r = m_findblocksetCommand.ExecuteScalar(null, filehash, size); if (r != null && r != DBNull.Value) { blocksetid = Convert.ToInt64(r); return(false); //Found it } } using (var tr = new TemporaryTransactionWrapper(m_connection, transaction)) { m_insertblocksetCommand.Transaction = tr.Parent; m_insertblocksetCommand.SetParameterValue(0, size); m_insertblocksetCommand.SetParameterValue(1, filehash); blocksetid = Convert.ToInt64(m_insertblocksetCommand.ExecuteScalar()); if (m_fileHashLookup != null) { m_fileHashLookup.Add(filehash, size, blocksetid); } long ix = 0; if (blocklistHashes != null) { m_insertblocklistHashesCommand.SetParameterValue(0, blocksetid); m_insertblocklistHashesCommand.Transaction = tr.Parent; foreach (var bh in blocklistHashes) { m_insertblocklistHashesCommand.SetParameterValue(1, ix); m_insertblocklistHashesCommand.SetParameterValue(2, bh); m_insertblocklistHashesCommand.ExecuteNonQuery(); ix++; } } m_insertblocksetentryCommand.SetParameterValue(0, blocksetid); m_insertblocksetentryCommand.Transaction = tr.Parent; m_insertblocksetentryFastCommand.SetParameterValue(0, blocksetid); m_insertblocksetentryFastCommand.Transaction = tr.Parent; ix = 0; long remainsize = size; foreach (var h in hashes) { var exsize = remainsize < blocksize ? remainsize : blocksize; var found = false; if (m_blockHashLookup != null) { KeyValuePair <long, long> id; if (m_blockHashLookup.TryGet(h, exsize, out id) && id.Value == exsize) { m_insertblocksetentryFastCommand.SetParameterValue(1, ix); m_insertblocksetentryFastCommand.SetParameterValue(2, id.Key); var cx = m_insertblocksetentryFastCommand.ExecuteNonQuery(); if (cx != 1) { throw new Exception(string.Format("Unexpected result count: {0}, expected {1}", cx, 1)); } found = true; } } if (!found) { m_insertblocksetentryCommand.SetParameterValue(1, ix); m_insertblocksetentryCommand.SetParameterValue(2, h); m_insertblocksetentryCommand.SetParameterValue(3, exsize); var c = m_insertblocksetentryCommand.ExecuteNonQuery(); if (c != 1) { throw new Exception(string.Format("Unexpected result count: {0}, expected {1}", c, 1)); } } ix++; remainsize -= blocksize; } tr.Commit(); } return(true); }