Multiple threads accessing UniData from UniObjects.NET throws UNI RPC error

2.1k views Asked by At

We've been using UniObjects.NET without issue until we started using it with BizTalk which is a multithreaded product. The issue is the error below. This error only happens on the 2nd thread (and probably 3rd, 4th etc. threads). The 1st thread connects and is able to retreive data from UniData just fine. The error doesn't say much and a search only returns one result not dealing with our particular issue. Does anyone have an anwser or can point me in the right direction? This error is without connection pooling turned on and we aren't using connection pooling as that throws other errors.

Another thing to note is that is that during debugging we wrote some code that each thread would write to a seperate file some debugging information. Just the act of writing debug info to a file made both threads work correctly. I don't believe this is a connection timing issue (i.e. opening the UniSession at the same time) as it only fails at the point of accessing the UniData File at the same time (assuming at the same time).

The UniObjects.NET document for the 2.2.3.7377 (May 2010) file version of UniObjects.NET we are using. UniData version is 7.2.

UPDATE: Also tried with UniObjects.NET version 2.2.5.7463 and it still throws same exception.

Inner exception: GetX - Error with file 'MYFILEX'. [IBM U2][UODOTNET - UNIRPC][ErrorCode=81004] An argument was requested from the RPC that was of an invalid type

Exception type: Exception
Source: MyBusinessObjects
Target Site: System.Collections.Generic.List`1[MyBusinessObjects.XResponse] GetX(System.Collections.Generic.List`1[MyBusinessObjects.Lookup])
The following is a stack trace that identifies the location where the exception occured
  at MyBusinessObjects.Lookups.GetX(List`1 Lookups)
  at MyBusinessObjects.Integration.GetXResponses(XmlDocument xml, String header, String gheader)
  at Orchestrations.XProcess.segment1(StopConditions stopOn)
  at Microsoft.XLANGs.Core.SegmentScheduler.RunASegment(Segment s, StopConditions stopCond, Exception& exp)

UPDATE: Same Error dealing with reading lists.

Inner exception: [IBM U2][UODOTNET - UNIRPC][ErrorCode=81004] An argument was requested from the RPC that was of an invalid type

Exception type: UniRPCPacketException
Source: 
UniRPCPacket Class
Target Site: Byte[] ReadByteArray(Int32)
The following is a stack trace that identifies the location where the exception occured

   at IBMU2.UODOTNET.UniRPCPMessage.ReadByteArray(Int32 anIndex)
   at IBMU2.UODOTNET.UniSelectList.ReadList()
   at IBMU2.UODOTNET.UniSelectList.ReadListAsStringArray()
   at MyBusinessObjects.Lookups.GetY()
   at MyBusinessObjects.Integration.GetResponses(XmlDocument xml, String header, String gsheader)
   at Orchestrations.Process.segment1(StopConditions stopOn)
   at Microsoft.XLANGs.Core.SegmentScheduler.RunASegment(Segment s, StopConditions stopCond, Exception& exp)
1

There are 1 answers

0
Rajan Kumar On

This problem is resolved. Now you can use latest UO.NET and I hope this issue is resolved. You can also use new Rocket Software Product called "U2 Toolkit for .NET". This is a integrated solution that contains ADO.NET, UO.NET and LINQ to Entity functionality. To test multi-threading, you can use the following code (instead of BiZtalk Server). We have used PLINQ and U2 Toolkit for .NET.

class Program
{
    static int NumberofThreads = 20;
    const string uniFileName = "PRODUCTS";
    static UniFile file = null;
    static UniSession session = GetUniSession();
    // setup ok/error counters
    static int ok = 0;
    static int error = 0;
    static void Main(string[] args)
    {
        // connect with no locks
        session.BlockingStrategy = UniObjectsTokens.UVT_WAIT_LOCKED;
        session.LockStrategy = UniObjectsTokens.UVT_NO_LOCKS;
        session.ReleaseStrategy = UniObjectsTokens.UVT_WRITE_RELEASE;
        Stopwatch watch = new Stopwatch();
        watch.Start();
        // take only 20 distinct record ids
        List<string> recordIds = new List<string>(RecordIds());
        // run as parallel
        Parallel.ForEach(recordIds, x =>
        {
            try
            {
                // connect to UniData CM file
                var file2 = session.CreateUniFile(uniFileName);
                // read individual record id
                file2.Read(x);
                file2.Close();
                Interlocked.Increment(ref ok);
                Console.WriteLine("rec id:" + x);
            }
            catch (Exception ex)
            {
                Interlocked.Increment(ref error);
                Console.WriteLine("Claim: {0}. Error: {1}", x, ex.Message);
            }
        });
        // set count & setup threads
        int count = 0;
        watch.Stop();
        // write error
        Console.WriteLine("Time: {2}, Count: {3}, OK: {0}, Error: {1}", ok, error, watch.Elapsed, count);
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }
    static UniSession GetUniSession()
    {
        U2ConnectionStringBuilder conn_str = new U2ConnectionStringBuilder();
        conn_str.UserID = "user";
        conn_str.Password = "pass";
        conn_str.Server = "localhost";
        conn_str.Database = "XDEMO";
        conn_str.ServerType = "UNIDATA";
        conn_str.AccessMode = "Native";   // FOR UO
        conn_str.RpcServiceType = "udcs"; // FOR UO
        conn_str.Pooling = false;
        string s = conn_str.ToString();
        U2Connection con = new U2Connection();
        con.ConnectionString = s;
        con.Open();
        Console.WriteLine("Connected.........................");
        U2.Data.Client.UO.UniSession us1 = con.UniSession;
        if (file == null)
        {
            file = us1.CreateUniFile(uniFileName);
        }
        return us1;
    }

    public static List<string> RecordIds()
    {
        List<string> lRECIDList = new List<string>();
        UniSelectList sl = session.CreateUniSelectList(2);

        // Select UniFile
        UniFile fl = session.CreateUniFile("PRODUCTS");
        sl.Select(fl);

        bool lLastRecord = sl.LastRecordRead;
        int lIndex = 0;
        while (!lLastRecord)
        {
            string s4 = sl.Next();
            lRECIDList.Add(s4);
            //Console.WriteLine("Record ID:" + s4);
            lLastRecord = sl.LastRecordRead;
            lIndex++;
            if (lIndex >= NumberofThreads)
            {
                break;
            }
        }
        return lRECIDList;

    }
}