예제 #1
0
파일: DedupIndex.cs 프로젝트: radtek/BackO
        internal bool Contains(byte[] checksum, string chunkname, int posInChunk, int bufSize, uint storageNode, ref long dedupId)
        {
#if DEBUG
            BenchmarkStats.Instance().DedupLookups++;
#endif
            for (int j = 0; j < index.Count; j++)
            {
                if (UnsafeCompare(index[currentPos].Checksum, checksum))
                {
                    Interlocked.Increment(ref index[currentPos].RefCounts);                     // in case parallelism >1 and multiple accesses to the same checksum entry
#if DEBUG
                    if (j < (index.Count - currentPos) + 2)
                    {
                        BenchmarkStats.Instance().DedupHotFound++;
                    }
                    else
                    {
                        BenchmarkStats.Instance().DedupColdFound++;
                    }
#endif
                    dedupId = index[currentPos].ID;
                    j++;                     // move to next dedup entry, hoping that next request will match it
                    return(true);
                }
                if (currentPos == index.Count - 1)
                {
                    currentPos = 0;
                }
                else
                {
                    currentPos = j;
                }
                currentPos++;
            }
            // key not found, add it
            FullDedupedBlock newDdb = new FullDedupedBlock();
            newDdb.Checksum = new byte[20];
            Array.Copy(checksum, newDdb.Checksum, checksum.Length);
            newDdb.DataChunkName   = chunkname;
            newDdb.Length          = bufSize;
            newDdb.StartPos        = posInChunk;
            newDdb.StorageNodes[0] = storageNode;
            newDdb.RefCounts       = 1;
            Interlocked.Increment(ref maxId);
            newDdb.ID = maxId;
            addPending.Add(newDdb);
            Interlocked.Increment(ref pendingAddCount);
#if DEBUG
            BenchmarkStats.Instance().DedupAdd++;
#endif
            if (pendingAddCount > 2000)
            {
                MergePending();
            }
            dedupId = maxId;
            return(false);
        }
예제 #2
0
파일: DedupIndex.cs 프로젝트: radtek/BackO
 private IEnumerable <FullDedupedBlock> GetFullDbEnumerator()
 {
     using (FileStream fs = new FileStream(dedupDB, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)){
         FullDedupedBlock curBlock = null;
         while ((curBlock = Serializer.DeserializeWithLengthPrefix <FullDedupedBlock>(fs, PrefixStyle.Base128)) != null)
         {
             yield return(curBlock);
         }
     }
 }
예제 #3
0
파일: DedupIndex.cs 프로젝트: radtek/BackO
        /// <summary>
        /// Renames previous DB file and serializes current dedup blocks list.
        /// To be called after a  backup operation.
        /// Also empties the index list to allow content to be GCed.
        /// Counts & reports medium deduped block size and total deduped data
        /// </summary>
        private void Update()
        {
            //TODO : check if dedup index is used and exit

            Logger.Append(Severity.DEBUG, "Saving deduplication indexes database...");
            if (initializing)
            {
                Logger.Append(Severity.NOTICE, "Won't save deduplication DB, not initialized yet");
                return;
            }
            try{             // delete if exists (should not happen)
                File.Delete(dedupDB + ".new");
            }
            catch (FileNotFoundException) {}

            using (FileStream newDbFs = new FileStream(dedupDB + ".new", FileMode.Create, FileAccess.Write)){
                // dedup db metrics
                long totalDataSize = 0;
                long totalRefCount = 0;
                using (IEnumerator <FullDedupedBlock> fullBlocksRef = GetFullDbEnumerator().GetEnumerator()){
                    lock (index){
                        foreach (LightDedupedBlock ddb in index)
                        {
                            if (fullBlocksRef.MoveNext())
                            {
                                FullDedupedBlock fdb = fullBlocksRef.Current;
                                fdb.RefCounts  = ddb.RefCounts;
                                totalRefCount += fdb.RefCounts;
                                if (ddb.RefCounts == 0)                               // auto-clean db by pruning records not referenced anymore
                                {
                                    continue;
                                }
                                totalDataSize += fdb.Length;
                                Serializer.SerializeWithLengthPrefix <FullDedupedBlock>(newDbFs, fdb, PrefixStyle.Base128);
                            }
                        }
                        Logger.Append(Severity.INFO, "Saved " + index.Count + " deduplication records (previously " + oldCount + ") into database. ");
                        if (index.Count > 0)
                        {
                            Console.WriteLine("Total data size represented by deduplication : " + totalDataSize / 1024 / 1024 + "MB, medium block size=" + totalDataSize / index.Count / 1024 + "KB, medium refcount=" + totalRefCount / index.Count);
                        }
                        index = null;
                    }
                    currentBackupSet = 0;
                }
            }
            string ddbBackup = dedupDB.Replace(".idx", ".idx.bak");

            try{             // remove previous backup
                File.Delete(ddbBackup);
            }
            catch (FileNotFoundException) {}
            try{
                File.Move(dedupDB, ddbBackup);
            }
            catch (FileNotFoundException) { /*nothing wrong  :first use of the dedup db*/ }
            catch (Exception _e) {
                Logger.Append(Severity.ERROR, "Could not move old dedup DB to backup location: " + _e.Message);
                throw(_e);
            }
            try{
                File.Move(dedupDB + ".new", dedupDB);
            }
            catch (Exception f) {
                Logger.Append(Severity.ERROR, "Could not move new dedup DB to definitive location: " + f.Message);
                throw(f);
            }
        }