/// <summary> /// Called to open the file. /// </summary> /// <param name="node">The node that represents the file.</param> /// <param name="sessionID">The unique session ID.</param> protected void Open(BaseFileNode node, string sessionID) { SetupFileNames(node, sessionID); Log.log.Debug("Opening File {0} (OutFile Open)", file); try { FileInfo fi = new FileInfo(file); if (Store.IsEnterpriseServer || fi.Length > (1024 * 100000)) { workStream = new StreamStream(File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read)); workFile = null; } else { // This file is being pushed make a copy to work from. File.Copy(file, workFile, true); File.SetAttributes(workFile, FileAttributes.Normal); workStream = new StreamStream(File.Open(workFile, FileMode.Open, FileAccess.Read)); } } catch (FileNotFoundException e1) { // got an exception - mostly File not found Log.log.Info("IOException for file {2} \n.{0}--{1}, setting Stream to NULL", e1.Message, e1.StackTrace, file); workStream = null; workFile = null; } }
/// <summary> /// Called to close the file and cleanup. /// </summary> /// <param name="InFinalizer">true if called from the finalizer.</param> private void Close(bool InFinalizer) { if (!InFinalizer) { GC.SuppressFinalize(this); } if (workStream != null) { workStream.Close(); workStream = null; } // We need to delete the temp file. if (workFile != null) { File.Delete(workFile); } }
/// <summary> /// Called to cleanup any resources and close the file. /// </summary> /// <param name="InFinalizer"></param> /// <param name="commit"></param> private SyncNodeStatus Close(bool InFinalizer, bool commit) { if (!InFinalizer) { GC.SuppressFinalize(this); } SyncNodeStatus status = new SyncNodeStatus(); status.nodeID = node.ID; status.status = SyncStatus.ClientError; if (stream != null) { stream.Close(); stream = null; } if (workStream != null) { workStream.Close(); workStream = null; } if (commit) { // backup file for rolling back on failure string tmpFile = ""; if (File.Exists(file)) { tmpFile = file + ".~stmp"; File.Move(file, tmpFile); Log.log.Info("backing up {0}->{1}", file, tmpFile); } // first try to write the file try { Log.log.Info("trying to move {0}->{1}", workFile, file); File.Move(workFile, file); workFile = null; } catch { Log.log.Info("Couldn't move {0}->{1}", workFile, file); Log.log.Info("Restoring file {0}", file); try { if (File.Exists(file)) { File.Delete(file); // delete newly transferred file } if (File.Exists(tmpFile)) { File.Move(tmpFile, file); // restore backup file into place } } catch (Exception ex) { Log.log.Info("couldn't return to prior state{0}--{1}", ex.Message, ex.StackTrace); }; // DELETE HASHMAP ? throw; // and don't try to commit } // try to collection.commit() status.status = SyncStatus.Success; try { Log.log.Info("trying to commit collection"); collection.Commit(node); } catch (CollisionException ce) { commit = false; status.status = SyncStatus.UpdateConflict; Log.log.Info("Couldn't commit collection: UpdateConflict {0}--{1}", ce.Message, ce.StackTrace); } catch (Exception ex) { commit = false; status.status = SyncStatus.ServerFailure; Log.log.Info("Couldn't commit collection {0}--{1}", ex.Message, ex.StackTrace); } /* Note : Restore original file if collection.Commit fails. * Conflict is a valid case for failure. And do not remove * files in workarea as they are needed for conflict resolution. */ if (!commit && status.status != SyncStatus.UpdateConflict) { try { Log.log.Debug("Collection commit failed : Restoring backup file : {0}", file.ToString()); // Delete newly transferred file if (File.Exists(file)) { File.Delete(file); Log.log.Debug("-- Deleting file : {0}", file.ToString()); } // Restore backup file into place if (File.Exists(tmpFile)) { File.Move(tmpFile, file); Log.log.Debug("-- Restoring {0} to {1}", tmpFile.ToString(), file.ToString()); } // Fixme : Delete hashmap ? } catch (Exception ex) { Log.log.Info("File restore failed : Couldn't return to prior state {0}--{1}", ex.Message, ex.StackTrace); }; } else // commit successful, delete the temporary (.~stmp) file. { try { // restore backup file into place if (File.Exists(tmpFile)) { File.Delete(tmpFile); } } catch (Exception ex) { Log.log.Info("problem deleting .~stmp file {0}--{1}", ex.Message, ex.StackTrace); }; } if (commit) { FileInfo fi = new FileInfo(file); fi.LastWriteTime = node.LastWriteTime; fi.CreationTime = node.CreationTime; if (oldNode != null) { // Check if this was a rename. // If the old path does not equal the new path // Delete the old file. string oldPath = oldNode.GetFullPath(collection); try { Log.log.Info("{0} may have been moved to {1}", file, oldPath); if (MyEnvironment.Windows) { if (string.Compare(oldPath, file, true) != 0) { File.Delete(oldPath); } } else { if (oldPath != file) { File.Delete(oldPath); } } } catch {}; } } } // We need to delete the temp file if we are the master. // On the client leave for a delta sync. if (workFile != null) { if (collection.Role == SyncRoles.Master || (collection.Role == SyncRoles.Slave && File.Exists(file))) { File.Delete(workFile); } } if (partialFile != null) { File.Delete(partialFile); } return(status); }
/// <summary> /// Called to open the file. /// </summary> /// <param name="node">The node that represents the file.</param> protected void Open(BaseFileNode node) { SetupFileNames(node, ""); CheckForNameConflict(); Log.log.Debug("Opening File {0} (InFile Open)", file); // Open the file so that it cannot be modified. oldNode = collection.GetNodeByID(node.ID) as BaseFileNode; try { if (!NameConflict) { stream = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.None); } } catch (FileNotFoundException) { Log.log.Debug("file {0} not found", file); // Check to see if we have a partially downloaded file to delta sync with. if (collection.Role == SyncRoles.Slave && File.Exists(workFile)) { if (File.Exists(partialFile)) { File.Delete(partialFile); } partialFile = workFile + ".part"; try { File.Move(workFile, partialFile); } catch (Exception e) { try { Log.log.Debug("could not move the file, so copy/deleting the source file: {0}. Message: {1} stack: {2}", workFile, e.Message, e.StackTrace); File.Copy(workFile, partialFile); File.Delete(workFile); } catch { File.Delete(workFile); Log.log.Debug("exception while copying workfile so deleted."); //throw e; } } if (File.Exists(partialFile)) { stream = File.Open(partialFile, FileMode.Open, FileAccess.Read, FileShare.None); } Log.log.Debug("file {0} opened", partialFile); } else if (oldNode != null) { // The file may have been renamed. string oldPath = oldNode.GetFullPath(collection); if (oldPath != file) { stream = File.Open(oldPath, FileMode.Open, FileAccess.Read, FileShare.None); Log.log.Debug("file {0} opened", oldPath); isServerFileRenamed = true; } } else { Log.log.Debug("file not {0} opened", file); } } catch (IOException e1) { try { string Fullpath = file; string rootNode = collection.GetRootDirectory().GetFullPath(collection); rootNode = Path.GetDirectoryName(rootNode); int rootPathLength = rootNode.Length; //int fullPathLength = Fullpath.Length; string Relativepath = Fullpath.Substring(rootPathLength); //Relative Path excluding FileName Relativepath = Path.GetDirectoryName(Relativepath); //bool pathExists = false; bool pathCreated = false; //Array of relative parth directory char[] delimiterList = { '/' }; string[] dirArray = Relativepath.Split(delimiterList); string tempPath = rootNode; //Maintaining progressive relative path, starting from root string FsPath = null; //List of node matching the Search criteria ICSList nodeList = null; foreach (string dir in dirArray) { if (FsPath != null) { //Creating incremental path, starting form Parent, excluding system path FsPath = Path.Combine(FsPath, dir); } else { FsPath = dir; //Initilizing if atleast on directory exist pathCreated = true; } //Creating incremental path, including system path tempPath = Path.Combine(tempPath, dir); //Verify if Directory exists, starting for root parent if (!System.IO.Directory.Exists(tempPath)) { //Verify if directory node exisit, then only create actual directory nodeList = collection.Search(PropertyTags.FileSystemPath, FsPath, SearchOp.Equal); if (nodeList != null) { //Create directory as Node exist System.IO.Directory.CreateDirectory(tempPath); } else { pathCreated = false; Log.log.Debug("Node doesn't exist for path:{0}", FsPath); //As parent node doesn't exist, no need to iterate for child break; } } } if (pathCreated == true) { Log.log.Debug("Final path created is :{0}", tempPath); } } catch (Exception excep) { Log.log.Info("Exception while re-creating missing directory: message {0}-- stacktrace:{1}", excep.Message, excep.StackTrace); } //throw below exception to log the failure Log.log.Info("IOException.{0}--{1}. The file is already open by some other thread.", e1.Message, e1.StackTrace); throw; } // Create the file in the parent directory and then move to the work area. // This will insure that the proper attributes are set. // This was added to support EFS (Encrypted File System). string createName = Path.Combine(Path.GetDirectoryName(file), Path.GetFileName(workFile)); FileStream tmpStream = File.Open(createName, FileMode.Create, FileAccess.ReadWrite, FileShare.None); if (File.Exists(workFile)) { File.Delete(workFile); } // Make sure we have enough space for the file. try { tmpStream.SetLength(node.Length); tmpStream.Close(); tmpStream = null; #if MONO if (MyEnvironment.Unix) { if (node.Properties.GetSingleProperty(SyncFile.ModeProperty) != null) { // Get the posix mode flags for the file. Stat sStat; if (Syscall.stat(createName, out sStat) == 0) { // Now or in the execute bit and set it on the file. FilePermissions fp = sStat.st_mode | FilePermissions.S_IXUSR; Syscall.chmod(createName, fp); } } } #endif File.Move(createName, workFile); } catch (IOException) { if (tmpStream != null) { tmpStream.Close(); } throw new InsufficientStorageException(); } workStream = new StreamStream(File.Open(workFile, FileMode.Truncate, FileAccess.ReadWrite, FileShare.None)); }