| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| using System; |
| using System.Collections.Generic; |
| using System.Reflection; |
| using System.Text; |
| using System.Xml; |
| |
| namespace Apache.Geode.Client.FwkLib |
| { |
| using Apache.Geode.DUnitFramework; |
| |
| public class FwkTask |
| { |
| #region Private members |
| |
| private Delegate m_delegate; |
| private Delegate m_pushTaskNameDelegate; |
| private Delegate m_endDelegate; |
| private List<string> m_clients; |
| private TimeBomb m_timeBomb; |
| private string m_class; |
| private int m_timeoutMillis; |
| private int m_timesToRun; |
| private int m_threadCount; |
| private bool m_parallel; |
| private bool m_continueOnError; |
| private ClientGroup m_clientGroup; |
| private List<string> m_localDataNames; |
| private UnitFnMethod<FwkTask, ClientBase> m_taskStartedHandler; |
| private UnitFnMethod<FwkTask, ClientBase, Exception> m_taskDoneHandler; |
| private bool m_taskStatus; |
| |
| #endregion |
| |
| #region Private constants and static members |
| |
| private const string PushTaskNameMethod = "PushTaskName"; |
| private const string EndTaskMethod = "EndTask"; |
| private const int DefaultTimeoutMillis = 600000; |
| private static string[] ThreadCountKeys = { "threadCount", "numThreads" }; |
| private static Dictionary<string, int> m_GlobalTaskNames = |
| new Dictionary<string, int>(); |
| private static Dictionary<string, Assembly> m_AssemblyMap = |
| new Dictionary<string, Assembly>(); |
| private const string ClientCountKey = "clientCount"; |
| |
| private const string NameAttrib = "name"; |
| private const string MethodAttrib = "action"; |
| private const string ClassAttrib = "class"; |
| private const string ContainerAttrib = "container"; |
| private const string WaitTimeAttrib = "waitTime"; |
| private const string TimesToRunAttrib = "timesToRun"; |
| private const string ThreadCountAttrib = "threadCount"; |
| private const string ParallelAttrib = "parallel"; |
| private const string ContinueAttrib = "continueOnError"; |
| private const string ArgTypes = "argTypes"; |
| |
| #endregion |
| |
| #region Public accessors |
| |
| public static Dictionary<string, int> GlobalTaskNames |
| { |
| get |
| { |
| return m_GlobalTaskNames; |
| } |
| } |
| |
| public List<string> ClientNames |
| { |
| get |
| { |
| return m_clients; |
| } |
| } |
| |
| public string Name |
| { |
| get |
| { |
| return (m_timeBomb == null ? null : m_timeBomb.TaskName); |
| } |
| } |
| |
| public string Class |
| { |
| get |
| { |
| return m_class; |
| } |
| } |
| |
| public int Timeout |
| { |
| get |
| { |
| return m_timeoutMillis; |
| } |
| } |
| |
| public int TimesToRun |
| { |
| get |
| { |
| return m_timesToRun; |
| } |
| } |
| |
| public int ThreadCount |
| { |
| get |
| { |
| return m_threadCount; |
| } |
| } |
| |
| public bool Parallel |
| { |
| get |
| { |
| return m_parallel; |
| } |
| } |
| |
| public bool ContinueOnError |
| { |
| get |
| { |
| return m_continueOnError; |
| } |
| } |
| |
| #endregion |
| |
| #region Private methods |
| |
| private void HandleTaskStarted(ClientBase client) |
| { |
| if (m_taskStartedHandler != null) |
| { |
| m_taskStartedHandler(this, client); |
| } |
| } |
| |
| private void HandleTaskDone(ClientBase client, Exception ex) |
| { |
| if (m_taskDoneHandler != null) |
| { |
| m_taskStatus = (ex == null); |
| m_taskDoneHandler(this, client, ex); |
| } |
| } |
| |
| #endregion |
| |
| #region Public methods |
| |
| public FwkTask(XmlNode node, string testName, |
| UnitFnMethod<FwkTask, ClientBase> taskStartedHandler, |
| UnitFnMethod<FwkTask, ClientBase, Exception> taskDoneHandler) |
| { |
| if (node == null) |
| { |
| throw new IllegalArgException("Null node for FwkTask constructor."); |
| } |
| |
| #region Read the attributes |
| |
| string taskName = string.Empty; |
| string containerStr = null; |
| string methodName = null; |
| string typeAttrib = null; |
| m_timesToRun = 1; |
| m_threadCount = 1; |
| m_parallel = false; |
| m_timeoutMillis = DefaultTimeoutMillis; |
| m_continueOnError = false; |
| m_class = null; |
| |
| XmlAttributeCollection xmlAttribs = node.Attributes; |
| if (xmlAttribs != null) |
| { |
| foreach (XmlAttribute xmlAttrib in xmlAttribs) |
| { |
| switch (xmlAttrib.Name) |
| { |
| case NameAttrib: |
| taskName = xmlAttrib.Value; |
| break; |
| case ArgTypes: |
| typeAttrib = xmlAttrib.Value; |
| break; |
| case ContainerAttrib: |
| containerStr = xmlAttrib.Value; |
| break; |
| case MethodAttrib: |
| methodName = xmlAttrib.Value; |
| break; |
| case TimesToRunAttrib: |
| m_timesToRun = XmlNodeReaderWriter.String2Int(xmlAttrib.Value, 1); |
| break; |
| case ThreadCountAttrib: |
| m_threadCount = XmlNodeReaderWriter.String2Int(xmlAttrib.Value, 1); |
| break; |
| case ParallelAttrib: |
| m_parallel = XmlNodeReaderWriter.String2Bool(xmlAttrib.Value, false); |
| break; |
| case WaitTimeAttrib: |
| m_timeoutMillis = XmlNodeReaderWriter.String2Seconds(xmlAttrib.Value, |
| DefaultTimeoutMillis) * 1000; |
| break; |
| case ContinueAttrib: |
| m_continueOnError = XmlNodeReaderWriter.String2Bool(xmlAttrib.Value, false); |
| break; |
| case ClassAttrib: |
| m_class = xmlAttrib.Value; |
| break; |
| default: |
| throw new IllegalArgException("Unknown attribute '" + |
| xmlAttrib.Name + "' found in '" + node.Name + |
| "' node."); |
| } |
| } |
| } |
| int taskNum = 1; |
| if (m_GlobalTaskNames.ContainsKey(taskName)) |
| { |
| taskNum = m_GlobalTaskNames[taskName] + 1; |
| } |
| m_GlobalTaskNames[taskName] = taskNum; |
| taskName += '_' + taskNum.ToString(); |
| |
| #endregion |
| |
| m_timeBomb = new TimeBomb(); |
| m_timeBomb.TaskName = testName + '.' + taskName; |
| |
| #region Create a delegate by loading the assembly |
| |
| Assembly loadAssmb = null; |
| string typeName = null; |
| if (containerStr != null && methodName != null) |
| { |
| object inst = null; |
| int dotIndx; |
| if ((dotIndx = containerStr.IndexOf('.')) < 0) |
| { |
| Type myType = this.GetType(); |
| loadAssmb = myType.Assembly; |
| typeName = myType.Namespace + '.' + containerStr; |
| Util.Log(Util.LogLevel.Info, "Assembly {0} loaded and typename is {1}", loadAssmb, typeName); |
| } |
| else |
| { |
| string assmbName = containerStr.Substring(0, dotIndx); |
| if (!m_AssemblyMap.TryGetValue(assmbName, out loadAssmb)) |
| { |
| try |
| { |
| loadAssmb = Assembly.Load(assmbName); |
| Util.Log(Util.LogLevel.Info, "Assembly {0} loaded ", assmbName); |
| } |
| catch (Exception e) |
| { |
| throw new IllegalArgException("Cannot load assembly '" + |
| assmbName + "' for task: " + m_timeBomb.TaskName + |
| " exception: " + e); |
| } |
| m_AssemblyMap.Add(assmbName, loadAssmb); |
| } |
| typeName = containerStr.Substring(dotIndx + 1); |
| } |
| //string typeAttrib; |
| if (loadAssmb != null) |
| { |
| if (typeAttrib == null) |
| { |
| inst = loadAssmb.CreateInstance(typeName, true); |
| } |
| else |
| { |
| //typeAttrib = "Apache.Geode.Client.Tests.ArrayOfByte,Apache.Geode.Client.Tests.ArrayOfByte"; |
| //typeAttrib = "System.int,System.Int32"; |
| string[] typeNames = typeAttrib.Split(','); |
| string mangledName = typeName + "`" + typeNames.Length.ToString(); |
| |
| //Type type = loadAssmb.GetType(mangledName, true, true); |
| Type[] types = new Type[typeNames.Length]; |
| for (int index = 0; index < typeNames.Length; ++index) |
| { |
| string typName = typeNames[index].Trim(); |
| if (typName == "int" || typName == "Int32" || typName == "string" || |
| typName == "String" || typName == "byte[]" || typName == "Byte[]" |
| || typName == "string[]" || typName == "String[]" || typName == "Object" |
| || typName == "object") |
| { |
| if (typName.Equals("int")) |
| typName = "Int32"; |
| else if (typName.Equals("string")) |
| typName = "String"; |
| else if (typName.Equals("string[]")) |
| typName = "String[]"; |
| else if (typName.Equals("byte[]")) |
| typName = "Byte[]"; |
| else if (typName.Equals("object")) |
| typName = "Object"; |
| typName = "System." + typName; |
| //Util.Log("rjk: FwkTask: typeAttrib 33 argname {0}", typName); |
| types[index] = Type.GetType(typName.Trim()); |
| //Util.Log("rjk: FwkTask: typeAttrib 34 argname {0}", typName); |
| } |
| else |
| { |
| typName = "Apache.Geode.Client.Tests." + typName; |
| types[index] = loadAssmb.GetType(typName.Trim(), true, true); |
| //Util.Log("rjk: FwkTask: typeAttrib for userobject 34 argname {0}", typName); |
| } |
| } |
| |
| Type type = loadAssmb.GetType(mangledName, true, true).MakeGenericType(types); |
| inst = type.GetConstructor(System.Type.EmptyTypes).Invoke(null); |
| |
| } |
| |
| } |
| if (inst != null) |
| { |
| try |
| { |
| MethodInfo mInfo = inst.GetType().GetMethod(methodName, |
| BindingFlags.IgnoreCase | BindingFlags.Public | |
| BindingFlags.Static | BindingFlags.FlattenHierarchy | |
| BindingFlags.Instance); |
| m_delegate = Delegate.CreateDelegate(typeof(UnitFnMethod), inst, |
| mInfo, true); |
| } |
| catch (Exception ex) |
| { |
| throw new IllegalArgException( |
| "Exception while creating delegate [" + methodName + "]: " + ex); |
| } |
| m_pushTaskNameDelegate = Delegate.CreateDelegate( |
| typeof(UnitFnMethod<string>), inst, PushTaskNameMethod, true); |
| m_endDelegate = Delegate.CreateDelegate( |
| typeof(UnitFnMethod), inst, EndTaskMethod, true); |
| } |
| } |
| if (m_delegate == null) |
| { |
| throw new IllegalArgException("Cannot create delegate '" + |
| methodName + "' for task: " + m_timeBomb.TaskName); |
| } |
| |
| #endregion |
| |
| #region Add the clients |
| |
| m_clients = new List<string>(); |
| m_clientGroup = new ClientGroup(false); |
| m_clients = FwkClient.ReadClientNames(node, false); |
| List<ClientBase> clients = FwkClient.GetClients(m_clients); |
| m_clientGroup.Add(clients); |
| m_timeBomb.AddClients(new ClientBase[] { m_clientGroup }); |
| m_taskStartedHandler = taskStartedHandler; |
| m_taskDoneHandler = taskDoneHandler; |
| int clientCount = m_clients.Count; |
| |
| #endregion |
| |
| #region Add any data |
| |
| m_localDataNames = new List<string>(); |
| Dictionary<string, FwkData> data = FwkData.ReadDataNodes(node); |
| // Task specific data is written as <taskname>.<key> to avoid |
| // overwriting the global data, since that needs to be preserved |
| // across tasks. |
| if (m_threadCount > 1) |
| { |
| // We shall treat 'threadCount' and 'numThreads' as equivalent, |
| // i.e. if 'threadCount' is defined for a task then 'numThreads' |
| // shall also be written as data. |
| foreach (string threadKey in ThreadCountKeys) |
| { |
| m_localDataNames.Add(threadKey); |
| Util.BBSet(Name, threadKey, |
| new FwkData(m_threadCount.ToString(), null, DataKind.String)); |
| } |
| } |
| if (clientCount > 0) |
| { |
| // Overwrite the clientCount (if any) with the actual value. |
| Util.BBSet(Name, ClientCountKey, |
| new FwkData(clientCount.ToString(), null, DataKind.String)); |
| } |
| foreach (KeyValuePair<string, FwkData> pair in data) |
| { |
| m_localDataNames.Add(pair.Key); |
| Util.BBSet(Name, pair.Key, pair.Value); |
| } |
| |
| #endregion |
| } |
| |
| public void AddClients(params ClientBase[] clients) |
| { |
| m_clientGroup.Add(clients); |
| } |
| |
| public void SetClients(params ClientBase[] clients) |
| { |
| m_clientGroup.Clients.Clear(); |
| m_clientGroup.Add(clients); |
| } |
| |
| public bool Execute() |
| { |
| m_taskStatus = true; |
| m_timeBomb.Start(m_timeoutMillis); |
| try |
| { |
| if (m_pushTaskNameDelegate != null) |
| { |
| m_clientGroup.CallFn(m_pushTaskNameDelegate, |
| new object[] { m_timeBomb.TaskName }); |
| } |
| if (m_taskStartedHandler != null || m_taskDoneHandler != null) |
| { |
| m_clientGroup.AddTaskHandlers(HandleTaskStarted, HandleTaskDone); |
| } |
| FwkReadData read = new FwkReadData(); |
| read.PushTaskName(Name); |
| string appDomain = read.GetStringValue("appdomain"); |
| if (appDomain != null && appDomain.Length > 0) { |
| m_clientGroup.CallFn(m_delegate, new object[] { Util.AppDomainPrefix |
| + appDomain }); |
| } |
| else { |
| m_clientGroup.CallFn(m_delegate, null); |
| } |
| if (m_taskStartedHandler != null || m_taskDoneHandler != null) |
| { |
| m_clientGroup.RemoveTaskHandlers(HandleTaskStarted, HandleTaskDone); |
| } |
| } |
| finally |
| { |
| m_timeBomb.Diffuse(); |
| } |
| return m_taskStatus; |
| } |
| |
| public void ClearData() |
| { |
| foreach (string dataName in m_localDataNames) |
| { |
| Util.BBRemove(Name, dataName); |
| } |
| } |
| |
| public void EndTask() |
| { |
| if (m_endDelegate != null) |
| { |
| m_clientGroup.CallFn(m_endDelegate, null); |
| } |
| m_clientGroup.RemoveObject(m_delegate.Target); |
| } |
| |
| public void SetLogFile(string logPath) |
| { |
| m_clientGroup.SetNameLogFile(logPath); |
| } |
| |
| public void SetLogLevel(Util.LogLevel logLevel) |
| { |
| m_clientGroup.SetLogLevel(logLevel); |
| } |
| |
| public string Dump() |
| { |
| StringBuilder dumpStr = new StringBuilder(); |
| |
| dumpStr.Append(Environment.NewLine + "The task name is: " + |
| m_timeBomb.TaskName); |
| dumpStr.Append(string.Format("{0}The function to be executed: " + |
| "'{1}' in class '{2}'", Environment.NewLine, m_delegate.Method.Name, |
| m_delegate.Method.ReflectedType.FullName)); |
| dumpStr.Append(Environment.NewLine + "The class of the task: " + |
| m_class); |
| dumpStr.Append(Environment.NewLine + "The threadCount is: " + |
| m_threadCount); |
| dumpStr.Append(Environment.NewLine + "Parallel attribute is: " + |
| m_parallel); |
| dumpStr.Append(Environment.NewLine + "Times to run is: " + |
| m_timesToRun); |
| dumpStr.Append(Environment.NewLine + "The clients are: "); |
| foreach (string clientName in m_clients) |
| { |
| dumpStr.Append(Environment.NewLine + "\t" + clientName); |
| } |
| dumpStr.Append(Environment.NewLine + "Continue on error is: " + |
| m_continueOnError); |
| dumpStr.Append(Environment.NewLine + "The local data names are: "); |
| foreach (string dataName in m_localDataNames) |
| { |
| dumpStr.Append(Environment.NewLine + '\t' + dataName); |
| } |
| dumpStr.Append(Environment.NewLine + "The timeout is: " + |
| m_timeoutMillis); |
| return dumpStr.ToString(); |
| } |
| |
| #endregion |
| } |
| } |