public bool CheckUnitID(RfcServerContextInfo serverContext, RfcUnitID tid) { Console.WriteLine(); Console.Write("bgRFC: Checking unit ID {0} --> ", tid.Uuid.ToString("N").ToUpper()); TidStatus status = unitIDStore.CreateEntry(tid.Uuid.ToString("N").ToUpper()); switch (status) { case TidStatus.Created: case TidStatus.RolledBack: // In these case we have to execute the bgRFC LUW. Console.WriteLine("New unit or one that had failed previously"); return(true); default: // In the remaining cases we have already executed this LUW successfully, so we // can (or rather have to) skip a second execution and send an OK code to R/3 immediately. Console.WriteLine("Already executed successfully"); return(false); } // "true" means that NCo will now execute the transaction, "false" means // that we have already executed this transaction previously, so NCo will // skip the function execution step and will immediately return an OK code to R/3. // In a real life scenario, if DB is down/unavailable, throw an exception at this point. // The .Net Connector will then abort the current bgRFC request and the R/3 backend will // try again later. // }
public void SetStatus(String tid, TidStatus tidStatus, String errorMessage) { lock (this) { StoreEntry entry = null; if (!table.TryGetValue(tid, out entry)) { throw new ArgumentException("Invalid TID"); } entry.status = tidStatus; bw.Seek(entry.index + idSize, SeekOrigin.Begin); bw.Write((byte)tidStatus); if (errorMessage != null) { byte[] err = Encoding.UTF8.GetBytes(errorMessage); int result = err.Length < REMAINDER_SIZE ? err.Length : REMAINDER_SIZE; bw.Write(err, 0, result); if (result < REMAINDER_SIZE) { bw.Write((byte)0); } } bw.Flush(); } }
// Prints a list of all existing entries to the console. public void PrintOverview() { if (table.Count == 0) { if (idSize == TID_SIZE) { Console.WriteLine("No tRFC LUWs received yet\n"); } else { Console.WriteLine("No bgRFC LUWs received yet\n"); } return; } lock (this) { string format = "{0,10} {1,-24} {2,-20} {3}"; if (idSize == GUID_SIZE) { format = "{0,10} {1,-32} {2,-20} {3}"; } Console.WriteLine("\n" + format, "Index", idSize == GUID_SIZE ? "GUID" : "TID", "Status", "Error message\n"); string errorMessage = ""; br.BaseStream.Seek(sizeof(int), SeekOrigin.Begin); for (int i = 0; i < slots; ++i) { char[] temp = br.ReadChars(idSize); if (temp[0] == 0) { br.BaseStream.Seek(1 + REMAINDER_SIZE, SeekOrigin.Current); continue; } TidStatus status = (TidStatus)br.ReadByte(); if (status == TidStatus.RolledBack) { byte[] byteBuf = br.ReadBytes(REMAINDER_SIZE); int result = 0; while (result < byteBuf.Length && byteBuf[result] != 0) { ++result; } errorMessage = Encoding.UTF8.GetString(byteBuf, 0, result); } Console.WriteLine(format, i, new String(temp), status, errorMessage); } } }
// Clean up the resources. Backend will never send this LUW again, so no need to // protect against it any longer. public void ConfirmUnitID(RfcServerContextInfo serverContext, RfcUnitID tid) { Console.WriteLine(); Console.WriteLine("TRFC: Confirm unit ID {0}", tid.Uuid.ToString("N").ToUpper()); try { // Our implementation keeps the ones that failed, so an admin can later view error messages. String error = ""; TidStatus status = unitIDStore.GetStatus(tid.Uuid.ToString("N").ToUpper(), out error); if (status == TidStatus.RolledBack) { return; } unitIDStore.DeleteEntry(tid.Uuid.ToString("N").ToUpper()); } catch (Exception) { } }
// Clean up the resources. Backend will never send this transaction again, so no need to // protect against it any longer. public void ConfirmTransactionID(RfcServerContextInfo serverContext, RfcTID tid) { Console.WriteLine(); Console.WriteLine("TRFC: Confirm transaction ID {0}", tid.TID); try { // Our implementation keeps the ones that failed, so an admin can later view error messages. string error = ""; TidStatus status = tidStore.GetStatus(tid.TID, out error); if (status == TidStatus.RolledBack) { return; } tidStore.DeleteEntry(tid.TID); } catch (Exception) { } }
// The backend's bgRFC runtime may at certain points ask us about the status of a bgRFC unit. public RfcUnitState GetUnitState(RfcServerContextInfo serverContext, RfcUnitID tid) { Console.WriteLine(); Console.WriteLine("bgRFC: Get unit state for unit ID {0}", tid.Uuid.ToString("N").ToUpper()); try { String error = ""; TidStatus status = unitIDStore.GetStatus(tid.Uuid.ToString("N").ToUpper(), out error); switch (status) { case TidStatus.Confirmed: return(RfcUnitState.CONFIRMED); case TidStatus.Committed: return(RfcUnitState.COMMITTED); case TidStatus.RolledBack: return(RfcUnitState.ROLLED_BACK); default: return(RfcUnitState.IN_PROCESS); } } catch (ArgumentException) { return(RfcUnitState.NOT_FOUND); } }
public TidStatus GetStatus(String tid, out String errorMessage) { TidStatus tidStatus = TidStatus.Created; lock (this) { errorMessage = ""; StoreEntry entry = null; if (!table.TryGetValue(tid, out entry)) { throw new ArgumentException("Invalid TID"); } tidStatus = entry.status; if (tidStatus == TidStatus.RolledBack) { br.BaseStream.Seek(entry.index + idSize + 1, SeekOrigin.Begin); byte[] err = br.ReadBytes(REMAINDER_SIZE); errorMessage = Encoding.UTF8.GetString(err); } } return(tidStatus); }