/////////////////////////////////////////////////////////////////////////// /** * Standard constructor */ public JobChannel( AgentGuid NewJobGuid, string ChannelName, string FullChannelName, EChannelFlags ChannelFlags ) : base(ChannelName, FullChannelName, ChannelFlags) { JobGuid = NewJobGuid; }
/////////////////////////////////////////////////////////////////////////// /** * Standard constructor */ public Channel( string ChannelName, string FullChannelName, EChannelFlags ChannelFlags ) { Name = ChannelName; Flags = ChannelFlags; FullName = FullChannelName; }
static int SwarmOpenChannel(IntPtr ChannelName, EChannelFlags ChannelFlags) { try { return GInstance.OpenChannel(FStringMarshaler.MarshalNativeToManaged(ChannelName), ChannelFlags); } catch(Exception Ex) { DebugLog.Write(Ex.Message + "\n" + Ex.ToString()); return 0; } }
/////////////////////////////////////////////////////////////////////////// public Int32 OpenChannel(Int32 ConnectionHandle, String ChannelName, EChannelFlags ChannelFlags) { OpenChannelDelegate DOpenChannel = Connection.OpenChannel; // Set up the versioned hashtable input parameters Hashtable InParameters = new Hashtable(); InParameters["Version"] = ESwarmVersionValue.VER_1_0; InParameters["ChannelName"] = ChannelName; InParameters["ChannelFlags"] = ChannelFlags; // Invoke the method, then wait for it to finish or to be notified that the connection dropped Hashtable OutParameters = null; IAsyncResult Result = DOpenChannel.BeginInvoke(ConnectionHandle, InParameters, ref OutParameters, null, null); WaitHandle.WaitAny(new WaitHandle[]{ Result.AsyncWaitHandle, ConnectionDroppedEvent }); // If the method completed normally, return the result if (Result.IsCompleted) { // If the invocation completed, success return DOpenChannel.EndInvoke(ref OutParameters, Result); } // Otherwise, error return Constants.ERROR_CONNECTION_DISCONNECTED; }
/* * Generates the full channel name, including Job path and staging area path if necessary */ String GenerateFullChannelName(String ManagedChannelName, EChannelFlags ChannelFlags) { if ((ChannelFlags & EChannelFlags.TYPE_PERSISTENT) != 0) { if ((ChannelFlags & EChannelFlags.ACCESS_WRITE) != 0) { // A persistent cache channel open for writing opens in the staging area String StagingAreaName = Path.Combine(AgentCacheFolder, "AgentStagingArea"); return Path.Combine(StagingAreaName, ManagedChannelName); } else if ((ChannelFlags & EChannelFlags.ACCESS_READ) != 0) { // A persistent cache channel open for reading opens directly in the cache return Path.Combine(AgentCacheFolder, ManagedChannelName); } } else if ((ChannelFlags & EChannelFlags.TYPE_JOB_ONLY) != 0) { AgentGuid JobGuid = ConnectionConfiguration.AgentJobGuid; if (JobGuid == null) { // If there's no Job associated with this connection at this point, provide // a default GUID for one for debugging access to the agent cache JobGuid = new AgentGuid(0x00000123, 0x00004567, 0x000089ab, 0x0000cdef); } // A Job Channel opens directly in the Job-specific directory String JobsFolder = Path.Combine(AgentCacheFolder, "Jobs"); String JobFolderName = Path.Combine(JobsFolder, "Job-" + JobGuid.ToString()); return Path.Combine(JobFolderName, ManagedChannelName); } return ""; }
/** * Opens a data channel for streaming data into the cache associated with an Agent * * @param ChannelName The name of the channel being opened * @param ChannelFlags The mode, access, and other attributes of the channel being opened * * @return A handle to the opened channel (< 0 is error) */ public virtual Int32 OpenChannel(String ChannelName, EChannelFlags ChannelFlags) { StartTiming("OpenChannel-Managed", true); Int32 ChannelHandle = Constants.INVALID; bool NewChannelSuccessfullyCreated = false; if (Connection != null) { try { // Ask the Agent if the file is safe to open, if required if (!ConnectionConfiguration.IsPureLocalConnection) { StartTiming("OpenChannel-Remote", false); ChannelHandle = Connection.OpenChannel(ConnectionHandle, ChannelName, (EChannelFlags)ChannelFlags); StopTiming(); } else { // If this is a pure local connection, then all we need to assure // if that the handle we generate here is unique to the connection ChannelHandle = Interlocked.Increment(ref BaseChannelHandle); } // If the channel is safe to open, open it up if (ChannelHandle >= 0) { // Track the newly created temp file ChannelInfo NewChannelInfo = new ChannelInfo(); NewChannelInfo.ChannelName = ChannelName; NewChannelInfo.ChannelFlags = ChannelFlags; NewChannelInfo.ChannelHandle = ChannelHandle; NewChannelInfo.ChannelFileStream = null; NewChannelInfo.ChannelData = null; NewChannelInfo.ChannelOffset = 0; // Determine the proper path name for the file String FullManagedName = GenerateFullChannelName(ChannelName, ChannelFlags); // Try to open the file if ((ChannelFlags & EChannelFlags.ACCESS_WRITE) != 0) { // Open the file stream NewChannelInfo.ChannelFileStream = new FileStream(FullManagedName, FileMode.Create, FileAccess.Write, FileShare.None); // Slightly different path for compressed files if ((ChannelFlags & EChannelFlags.MISC_ENABLE_COMPRESSION) != 0) { Stream NewChannelStream = NewChannelInfo.ChannelFileStream; NewChannelInfo.ChannelFileStream = new GZipStream(NewChannelStream, CompressionMode.Compress, false); } // If we were able to open the file, add it to the active channel list Monitor.Enter(FreeChannelWriteBuffers); try { // If available, take the next free write buffer from the list if (FreeChannelWriteBuffers.Count > 0) { NewChannelInfo.ChannelData = FreeChannelWriteBuffers.Pop(); } else { // Otherwise, allocate a new write buffer for this channel (default to 1MB) NewChannelInfo.ChannelData = new byte[1024 * 1024]; } } finally { Monitor.Exit( FreeChannelWriteBuffers ); } // Track the newly created file OpenChannels.Add(ChannelHandle, NewChannelInfo); NewChannelSuccessfullyCreated = true; } else if ((ChannelFlags & EChannelFlags.ACCESS_READ) != 0) { if (File.Exists(FullManagedName)) { // Slightly different paths for compressed and non-compressed files if ((ChannelFlags & EChannelFlags.MISC_ENABLE_COMPRESSION) != 0) { // Open the input stream, loading it entirely into memory byte[] RawCompressedData = File.ReadAllBytes(FullManagedName); // Allocate the destination buffer // The size of the uncompressed data is contained in the last four bytes of the file // http://www.ietf.org/rfc/rfc1952.txt?number=1952 Int32 UncompressedSize = BitConverter.ToInt32(RawCompressedData, RawCompressedData.Length - 4); NewChannelInfo.ChannelData = new byte[UncompressedSize]; // Open the decompression stream and decompress directly into the destination Stream DecompressionChannelStream = new GZipStream(new MemoryStream(RawCompressedData), CompressionMode.Decompress, false); DecompressionChannelStream.Read(NewChannelInfo.ChannelData, 0, UncompressedSize); DecompressionChannelStream.Close(); } else { // Simply read in the entire file in one go NewChannelInfo.ChannelData = File.ReadAllBytes(FullManagedName); } // Track the newly created channel OpenChannels.Add(ChannelHandle, NewChannelInfo); NewChannelSuccessfullyCreated = true; } else { // Failed to find the channel to read, return an error ChannelHandle = Constants.ERROR_CHANNEL_NOT_FOUND; } } } } catch (Exception Ex) { Log(EVerbosityLevel.Critical, ELogColour.Red, "[Interface:OpenChannel] Error: " + Ex.ToString()); ChannelHandle = Constants.ERROR_CONNECTION_DISCONNECTED; CleanupClosedConnection(); } // If we opened the channel on the agent, but failed to create // the file, close it on the agent if ((ChannelHandle >= 0) && (NewChannelSuccessfullyCreated == false)) { if (!ConnectionConfiguration.IsPureLocalConnection) { StartTiming("CloseChannel-Remote", false); try { Connection.CloseChannel(ConnectionHandle, ChannelHandle); } catch (Exception Ex) { Log(EVerbosityLevel.Critical, ELogColour.Red, "[Interface:OpenChannel] Cleanup error: " + Ex.Message); CleanupClosedConnection(); } StopTiming(); } ChannelHandle = Constants.ERROR_CHANNEL_IO_FAILED; } } else { ChannelHandle = Constants.ERROR_CONNECTION_NOT_FOUND; } StopTiming(); return ChannelHandle; }