예제 #1
0
 ///////////////////////////////////////////////////////////////////////////
 /**
  * Standard constructor
  */
 public JobChannel( AgentGuid NewJobGuid, string ChannelName, string FullChannelName, EChannelFlags ChannelFlags )
     : base(ChannelName, FullChannelName, ChannelFlags)
 {
     JobGuid = NewJobGuid;
 }
예제 #2
0
 ///////////////////////////////////////////////////////////////////////////
 /**
  * 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;
		}