/// <summary> /// Register the chunks in the given file to the DB. /// </summary> /// <param name="filePath">The file path.</param> /// <param name="chunks">The chunks.</param> public void AddChunks(string filePath, int[] chunks) { logger.DebugFormat("Adding chunks {0} for file {1}.", string.Join(",", System.Array.ConvertAll <int, string>(chunks, x => x.ToString())), filePath); var txnProvider = new NHTransactionProvider( new NHSessionProvider(_sessionFactory)); using (txnProvider) { using (var transaction = txnProvider.BeginTransaction()) { var helper = new ChunkDbHelper( txnProvider.SessionProvider.CurrentSession); ManagedFile file = helper.GetManagedFile(filePath); var chunkMap = file.ChunkMap; int numAlreadyExist = 0; foreach (var chunkIndex in chunks) { byte[] hash = chunkMap.HashAt(chunkIndex); var entry = new DataChunk { File = file, ChunkIndex = chunkIndex, Hash = hash, Count = 0 }; bool added = helper.AddChunkIfNotExists(entry); if (!added) { numAlreadyExist++; } } transaction.Commit(); logger.DebugFormat( "Chunks added. {0} out of {1} chunks already exist.", numAlreadyExist, chunks.Length); } } }
/// <summary> /// Adds a file to the Chunk DB. /// </summary> /// <param name="filePath">The file path.</param> /// <param name="forEachChunk">(index, hash)</param> /// <param name="forEofChunk">(index, chunk size)</param> void AddFileAllChunks(string filePath, Action <int, byte[]> forEachChunk, Action <int, int> forEofChunk) { var txnProvider = new NHTransactionProvider( new NHSessionProvider(_sessionFactory)); var session = txnProvider.SessionProvider.CurrentSession; ManagedFile file; // In a stateful session. using (txnProvider) { using (var transaction = txnProvider.BeginTransaction()) { var helper = new ChunkDbHelper(session); file = helper.CreateManagedFileFromLocalFile(filePath); // Have the file committed to DB. transaction.Commit(); } } // Choose stateless session for bulk insert. var statelessSession = _sessionFactory.OpenStatelessSession(); using (var transaction = statelessSession.BeginTransaction()) { SHA1 sha = new SHA1CryptoServiceProvider(); using (var stream = File.OpenRead(filePath)) { int chunkIndex = 0; var chunk = new byte[DataChunk.ChunkSize]; int duplicates = 0; bool isEofChunk = false; for (; ; chunkIndex++) { long offset = stream.Position; int readLength = stream.Read(chunk, 0, chunk.Length); if (readLength == 0) { if (forEofChunk != null) { forEofChunk(chunkIndex - 1, DataChunk.ChunkSize); } break; } if (readLength < DataChunk.ChunkSize) { // Last chunk. isEofChunk = true; // The rest of the buffer is padded with 0s. System.Array.Clear(chunk, readLength, chunk.Length - readLength); if (forEofChunk != null) { forEofChunk(chunkIndex, readLength); } } // Hash is computed over the full chunk buffer with // padding in case of a small chunk. byte[] hash = sha.ComputeHash(chunk); if (forEachChunk != null) { forEachChunk(chunkIndex, hash); } bool alreadyExists = ChunkDbHelper.AddChunkIfNotExists(statelessSession, new DataChunk { Hash = hash, File = file, ChunkIndex = chunkIndex, Count = 0 }); if (alreadyExists) { duplicates++; } if (isEofChunk) { break; } } transaction.Commit(); logger.DebugFormat("File {0} added to ChunkDb.", filePath); logger.DebugFormat("Number of duplicates {0}", duplicates); } } }