blob: fe799600a3bb6e9b947ac8e4e3cee3bfa7429d0a [file] [log] [blame]
/*
* 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;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.Remoting.Channels;
using System.Text;
using System.Threading;
namespace Apache.Geode.Client.FwkClient
{
using Apache.Geode.DUnitFramework;
class ClientComm : MarshalByRefObject, IClientComm
{
private static Dictionary<string, object> m_InstanceMap =
new Dictionary<string, object>();
private static Dictionary<string, AppDomain> m_appDomainMap =
new Dictionary<string, AppDomain>();
private static volatile bool m_exiting = false;
private void CallP(int objectId, string assemblyName, string typeName,
string methodName, object[] paramList, ref object result)
{
if (m_exiting) {
return;
}
string objID = objectId.ToString();
object typeInst = null;
string appDomain = null;
// assume first argument to be the name of AppDomain
if (paramList != null && paramList.Length > 0) {
object param = paramList[paramList.Length - 1];
if (param is string && (appDomain = (string)param).StartsWith(
Util.AppDomainPrefix)) {
appDomain = appDomain.Substring(Util.AppDomainPrefix.Length);
if (appDomain.Length > 0) {
objID = Util.AppDomainPrefix + ":" + appDomain + objID;
object[] newParams = new object[paramList.Length - 1];
Array.Copy(paramList, 0, newParams, 0, paramList.Length - 1);
paramList = newParams;
}
else {
appDomain = null;
}
}
else {
appDomain = null;
}
}
lock (((ICollection)m_InstanceMap).SyncRoot) {
if (m_InstanceMap.ContainsKey(objID)) {
typeInst = m_InstanceMap[objID];
}
else if (appDomain != null)
{
AppDomain domain;
if (!m_appDomainMap.ContainsKey(appDomain)) {
domain = AppDomain.CreateDomain(appDomain);
CreateBBServerConnection urlConn = (CreateBBServerConnection)domain.
CreateInstanceAndUnwrap("FwkClient",
"Apache.Geode.Client.FwkClient.CreateBBServerConnection");
urlConn.OpenBBServerConnection(ClientProcess.bbUrl);
urlConn.SetLogFile(Util.LogFile);
Util.Log("Created app domain {0}",domain);
m_appDomainMap.Add(appDomain, domain);
}
else {
domain = m_appDomainMap[appDomain];
CreateBBServerConnection urlConn = (CreateBBServerConnection)domain.
CreateInstanceAndUnwrap("FwkClient",
"Apache.Geode.Client.FwkClient.CreateBBServerConnection");
urlConn.SetLogFile(Util.LogFile);
}
try {
typeInst = domain.CreateInstanceAndUnwrap(assemblyName, typeName);
} catch (Exception e) {
Util.Log("Exception thrown for app domain CreateInstanceAndUnwrap : {0} ", e.Message);
}
if (typeInst != null) {
m_InstanceMap[objID] = typeInst;
}
else {
throw new IllegalArgException(
"FATAL: Could not load class with name: " + typeName);
}
}
else {
Assembly assmb = null;
try {
assmb = Assembly.Load(assemblyName);
} catch (Exception) {
throw new IllegalArgException(
"FATAL: Could not load assembly: " + assemblyName);
}
typeInst = assmb.CreateInstance(typeName);
if (typeInst != null) {
m_InstanceMap[objID] = typeInst;
}
else {
throw new IllegalArgException(
"FATAL: Could not load class with name: " + typeName);
}
}
}
MethodInfo[] mInfos = typeInst.GetType().GetMethods(
BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public
| BindingFlags.NonPublic | BindingFlags.Static
| BindingFlags.FlattenHierarchy);
MethodInfo mInfo = null;
foreach (MethodInfo method in mInfos) {
if (method.Name.Equals(methodName,
StringComparison.CurrentCultureIgnoreCase)) {
ParameterInfo[] prms = method.GetParameters();
int paramLen = (paramList != null ? paramList.Length : 0);
if (paramLen == prms.Length) {
mInfo = method;
}
}
}
if (mInfo != null) {
Thread currentThread = Thread.CurrentThread;
lock (((ICollection)UnitThread.GlobalUnitThreads).SyncRoot) {
if (!UnitThread.GlobalUnitThreads.ContainsKey(currentThread)) {
UnitThread.GlobalUnitThreads.Add(currentThread, true);
}
}
if (result == null) {
try
{
mInfo.Invoke(typeInst, paramList);
}
catch (TargetInvocationException tie)
{
Util.Log(Util.LogLevel.Error, tie.InnerException.StackTrace.ToString());
throw tie;
}
}
else {
result = mInfo.Invoke(typeInst, paramList);
}
lock (((ICollection)UnitThread.GlobalUnitThreads).SyncRoot) {
if (!UnitThread.GlobalUnitThreads.ContainsKey(currentThread)) {
UnitThread.GlobalUnitThreads.Remove(currentThread);
}
}
}
else {
throw new IllegalArgException("FATAL: Could not load function with name: " +
methodName + ", in class: " + typeInst.GetType());
}
}
#region IClientComm Members
public void Call(int objectId, string assemblyName, string typeName,
string methodName, params object[] paramList)
{
object obj = null;
CallP(objectId, assemblyName, typeName, methodName, paramList, ref obj);
}
public object CallR(int objectId, string assemblyName, string typeName,
string methodName, params object[] paramList)
{
object obj = 0;
CallP(objectId, assemblyName, typeName, methodName, paramList, ref obj);
return obj;
}
public void RemoveObjectID(int objectId)
{
lock (((ICollection)m_InstanceMap).SyncRoot)
{
if (m_InstanceMap.ContainsKey(objectId.ToString()))
{
m_InstanceMap.Remove(objectId.ToString());
}
}
}
public void SetLogFile(string logFile)
{
Util.LogFile = logFile;
}
public void SetLogLevel(Util.LogLevel logLevel)
{
Util.CurrentLogLevel = logLevel;
}
public bool CreateNew(string clientId, int port)
{
string clientPath = Assembly.GetExecutingAssembly().Location;
string[] args = Environment.GetCommandLineArgs();
string argStr = string.Empty;
for (int i = 1; i < args.Length - 1; i++)
{
string arg = args[i];
if (arg.StartsWith("--id="))
{
argStr += ("\"--id=" + clientId + "\" ");
}
else
{
argStr += ('"' + arg + "\" ");
}
}
argStr += port.ToString();
Process proc;
return Util.StartProcess(clientPath, argStr, false, null,
false, false, false, out proc);
}
public void DumpStackTrace()
{
StringBuilder dumpStr = new StringBuilder();
try
{
dumpStr.Append(Util.MarkerString);
dumpStr.Append("Dumping managed stack for process [" + Util.PID + "]:");
dumpStr.Append(Util.MarkerString);
lock (((ICollection)UnitThread.GlobalUnitThreads).SyncRoot)
{
foreach (Thread thread in UnitThread.GlobalUnitThreads.Keys)
{
dumpStr.Append(UnitThread.GetStackTrace(thread));
dumpStr.Append(Environment.NewLine + Environment.NewLine);
}
}
dumpStr.Append(Util.MarkerString);
Util.Log(dumpStr.ToString());
dumpStr.Length = 0;
dumpStr.Append("Dumping native stack for process [" + Util.PID + "]:");
dumpStr.Append(Util.MarkerString);
Process cdbProc;
// Expect to find 'cdb.pl' in the same dir as FwkClient.exe
if (Util.StartProcess("perl", Util.AssemblyDir + "/cdb.pl " + Util.PID,
false, null, true, false, true, out cdbProc))
{
StreamReader cdbRead = cdbProc.StandardOutput;
StreamReader cdbReadErr = cdbProc.StandardError;
dumpStr.Append(cdbRead.ReadToEnd());
dumpStr.Append(cdbReadErr.ReadToEnd());
cdbProc.WaitForExit();
cdbRead.Close();
cdbReadErr.Close();
}
else
{
dumpStr.Append("Failed to start: perl ");
dumpStr.Append(Util.AssemblyDir + "/cdb.pl " + Util.PID);
}
}
catch (Exception ex)
{
dumpStr.Append("Exception while invoking cdb.pl: ");
dumpStr.Append(ex.ToString());
}
dumpStr.Append(Util.MarkerString + Environment.NewLine);
Util.Log(dumpStr.ToString());
}
public void TestCleanup()
{
foreach (UnitFnMethod deleg in Util.RegisteredTestCompleteDelegates)
{
try
{
Util.Log("Cleaning test on client [{0}]: Calling {1} :: {2}",
Util.ClientId, deleg.Method.DeclaringType, deleg.Method);
deleg();
}
catch (Exception ex)
{
Util.Log(Util.LogLevel.Error, ex.ToString());
}
}
}
public void Exit(bool force)
{
try
{
m_exiting = true;
if (!force)
{
foreach (UnitFnMethod deleg in Util.RegisteredTestCompleteDelegates)
{
try
{
Util.Log("Exiting client [{0}]: Calling {1} :: {2}", Util.ClientId,
deleg.Method.DeclaringType, deleg.Method);
deleg();
}
catch (Exception ex)
{
Util.Log(Util.LogLevel.Error, ex.ToString());
}
}
}
}
finally
{
Environment.Exit(0);
Util.Process.Kill();
}
}
public Process GetClientProcess()
{
return Util.Process;
}
#endregion
}
}