예제 #1
0
            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);
            }
예제 #2
0
        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);
            }
        }
예제 #3
0
        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();
                }
        }
예제 #4
0
        /// <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);
        }
예제 #5
0
        /// <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();
        }
예제 #6
0
        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();
                }
        }
예제 #7
0
        /// <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();
        }
예제 #8
0
 /// <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);
         }
 }
예제 #9
0
        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();
                }
        }
예제 #10
0
 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);
     }
 }
예제 #11
0
        /// <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);
            }
        }
예제 #12
0
        /// <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);
        }
예제 #13
0
        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();
                }
        }
예제 #14
0
        /// <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);
        }
예제 #15
0
            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();
                        }
                }
            }
예제 #16
0
            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);
            }
예제 #17
0
        /// <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);
        }