/// <summary>
        /// Calculates the sequence in which files should be deleted based on their releations.
        /// </summary>
        /// <returns>The deletable volumes.</returns>
        /// <param name="deleteableVolumes">Block volumes slated for deletion.</param>
        public IEnumerable <IRemoteVolume> GetDeletableVolumes(IEnumerable <IRemoteVolume> deleteableVolumes, System.Data.IDbTransaction transaction)
        {
            using (var cmd = m_connection.CreateCommand())
            {
                // Although the generated index volumes are always in pairs,
                // this code handles many-to-many relations between
                // index files and block volumes, should this be added later
                var lookupBlock      = new Dictionary <string, List <IRemoteVolume> >();
                var lookupIndexfiles = new Dictionary <string, List <string> >();

                cmd.Transaction = transaction;

                using (var rd = cmd.ExecuteReader(@"SELECT ""C"".""Name"", ""B"".""Name"", ""B"".""Hash"", ""B"".""Size"" FROM ""IndexBlockLink"" A, ""RemoteVolume"" B, ""RemoteVolume"" C WHERE ""A"".""IndexVolumeID"" = ""B"".""ID"" AND ""A"".""BlockVolumeID"" = ""C"".""ID"" AND ""B"".""Hash"" IS NOT NULL AND ""B"".""Size"" IS NOT NULL "))
                    while (rd.Read())
                    {
                        var name = rd.GetValue(0).ToString();
                        List <IRemoteVolume> indexfileList;
                        if (!lookupBlock.TryGetValue(name, out indexfileList))
                        {
                            indexfileList = new List <IRemoteVolume>();
                            lookupBlock.Add(name, indexfileList);
                        }

                        var v = new RemoteVolume(rd.GetString(1), rd.GetString(2), rd.GetInt64(3));
                        indexfileList.Add(v);

                        List <string> blockList;
                        if (!lookupIndexfiles.TryGetValue(v.Name, out blockList))
                        {
                            blockList = new List <string>();
                            lookupIndexfiles.Add(v.Name, blockList);
                        }
                        blockList.Add(name);
                    }

                foreach (var r in deleteableVolumes.Distinct())
                {
                    // Return the input
                    yield return(r);

                    List <IRemoteVolume> indexfileList;
                    if (lookupBlock.TryGetValue(r.Name, out indexfileList))
                    {
                        foreach (var sh in indexfileList)
                        {
                            List <string> backref;
                            if (lookupIndexfiles.TryGetValue(sh.Name, out backref))
                            {
                                //If this is the last reference,
                                // remove the index file as well
                                if (backref.Remove(r.Name) && backref.Count == 0)
                                {
                                    yield return(sh);
                                }
                            }
                        }
                    }
                }
            }
        }
示例#2
0
		/// <summary>
		/// Calculates the sequence in which files should be deleted based on their releations.
		/// </summary>
		/// <returns>The deletable volumes.</returns>
		/// <param name="deleteableVolumes">Block volumes slated for deletion.</param>
		public IEnumerable<IRemoteVolume> GetDeletableVolumes(IEnumerable<IRemoteVolume> deleteableVolumes, System.Data.IDbTransaction transaction)
		{
			using(var cmd = m_connection.CreateCommand())
			{
				// Although the generated index volumes are always in pairs,
				// this code handles many-to-many relations between
				// index files and block volumes, should this be added later
				var lookupBlock = new Dictionary<string, List<IRemoteVolume>>();
				var lookupIndexfiles = new Dictionary<string, List<string>>();
				
				cmd.Transaction = transaction;
                
				using(var rd = cmd.ExecuteReader(@"SELECT ""C"".""Name"", ""B"".""Name"", ""B"".""Hash"", ""B"".""Size"" FROM ""IndexBlockLink"" A, ""RemoteVolume"" B, ""RemoteVolume"" C WHERE ""A"".""IndexVolumeID"" = ""B"".""ID"" AND ""A"".""BlockVolumeID"" = ""C"".""ID"" AND ""B"".""Hash"" IS NOT NULL AND ""B"".""Size"" IS NOT NULL "))
					while(rd.Read())
					{
						var name = rd.GetValue(0).ToString();
						List<IRemoteVolume> indexfileList;
						if (!lookupBlock.TryGetValue(name, out indexfileList))
						{	
							indexfileList = new List<IRemoteVolume>();
							lookupBlock.Add(name, indexfileList);
						}
						
						var v = new RemoteVolume(rd.GetValue(1).ToString(), rd.GetValue(2).ToString(), Convert.ToInt64(rd.GetValue(3)));
						indexfileList.Add(v);

						List<string> blockList;
						if (!lookupIndexfiles.TryGetValue(v.Name, out blockList))
						{	
							blockList = new List<string>();
							lookupIndexfiles.Add(v.Name, blockList);
						}
						blockList.Add(name);
					}

				foreach(var r in deleteableVolumes.Distinct())
				{
					// Return the input
					yield return r;
					List<IRemoteVolume> indexfileList;
					if (lookupBlock.TryGetValue(r.Name, out indexfileList))
						foreach(var sh in indexfileList)
						{
							List<string> backref;
							if (lookupIndexfiles.TryGetValue(sh.Name, out backref))
							{
								//If this is the last reference, 
								// remove the index file as well
								if (backref.Remove(r.Name) && backref.Count == 0)
									yield return sh;
							}
						}
				}
			}
		}