Page 2 of 3 FirstFirst 1 2 3 LastLast
Results 11 to 20 of 26

Thread: E1 9.2.3 with 64-bit for client and server

  1. #11
    Brian,

    You can use that machine image to compile C code. I have a document about the C code changes, and gotchas. Shoot me an email and I'll send it your way.

    mark.dalton@autodeploy.net

  2. #12
    Member craig_welton's Avatar
    Join Date
    Oct 2000
    Location
    Litchfield, CT
    Posts
    961
    I guess it really depends on what the custom code does. Storing an HREQUEST (or any handle) in a GENLNG DS member would be an issue as the GENLNG is a long (32 bit) and the HREQUEST would now be 64bit. Any casting of pointers to 32bit values (int, long) in order to do arithmetic would now cause truncation. The compiler should catch some things with warnings. I don't have a 64bit porting gig on the radar, but it would cool if we shared issues in a common place. It was mentioned Oracle had a conversion tool, but I haven't been able to find it.
    Craig Welton
    PatWel Group Inc.
    http://www.patwel.com
    Home of the FREE JDE Object Browser, JDETrace and NERDup Tools

    E1 9.0 8.98.4.2 Wintel SQL 2008
    E1 9.2 9.2.1.4 iSeries

  3. #13
    New Member
    Join Date
    Jun 2005
    Location
    KS,USA
    Posts
    32
    Extract from Oracle Docs
    JD Edwards EnterpriseOne 64-bit Processing Frequently Asked Questions (Doc ID 2390692.1)

    How are customizations impacted if I transition to 64-bit processing?

    A: There is no impact to spec-based objects such as interactive applications, batch
    applications, named event rules, and other spec-based objects. Customized C business
    functions may need to be retrofitted for 64-bit processing. To simplify the retrofitting, Oracle
    has delivered an embedded utility to assist with converting customized C business functions
    to be 64-bit processing complian
    ----------------------------------------------
    JD Edwards XE B7333, EnterpriseOne 8.11, 9.0 and 9.1, BSSV, C, JAVA

  4. #14
    Senior Member
    Join Date
    Mar 2004
    Location
    Fort Worth, Texas
    Posts
    1,517
    How exactly is ID defined?

    This is kinda what I have feared for a while now when thinking about 64bit, how Oracle chooses to define ID. I have one very narrow use case that will probably need to be fixed. It will be easy to find and fix I just don't like the fix.

    Whenever I pass pointers from/to a BSFN I always use jdeStoreDataPtr/jdeRemoveDataPtr as recommended by Oracle. However, I try to avoid patterns that require it's use (i.e. I try to avoid passing pointers) as much as possible and have very strict rules I try to follow about how I use jdeStoreDataPtr. For example I try to make sure that if I pass a pointer handle it is immediatly retrieved/removed by the callee in one synchronous execution. This also means that I try not to have a situation where I pass a pointer handle back to ER code that requires a later user action to initiate code that retrieves/removes the handle (free's it). In other words I avoid situations that would result in leaving jdeStoreDataPtr handles allocated.

    The one flaw with jdeStoreDataPtr is that it only has a small fixed number of handles (1000 I think, maybe 10000) that can be allocated at any one point. The problem with this is that a bug in one little piece of code (ER, C code, or any other binding like BSSV or XML Call Object) that leaks handles can crash the entire user session or even Zombie the Call Object Kernel. Further more, a bug in one application can effect all other applications and it my not be easy to indentify which application has the bug. For example a bug that leaks handles in the PO Reciepts module could cause not only PO Reciepts to crash but also Load Build or General Ledger (any other application that uses jdeStoreDataPtr). This differs from other types of resource leaks which are often localized to the application with the bug. For example a bug that leaks jdeCache cursors in Sales Order Entry won't necessarily break Accounts Payble applications even if Accounts Payable also uses jdeCache and, depending on the jdeCache design pattern, wont necessarily break other running instances of the same application. Additionaly a bug like leaking jdeCache cursor handles may never even manifest itself.

    Because of this I have one use case where I intentionally did NOT use jdeStoreDataPtr. Iterating jdeCache records in ER code.

    Code:
    lpDS->idCursorHandle = (ID)hCursor;
    ...
    hCursor = (HJDECURSOR)lpDS->idCursorHandle;
    For starters I initially thought that HJDECURSOR was in fact a true opaque handle and not a memory address so initially I didn't realize I needed to use jdeStoreDataPtr. But beyond that, this is a case where I am generally passing out a cache cursor to ER code as I am iterating through jdeCache to fill a grid or something. With page-at-a-time processing this will, by design, leave cursors open until the end of the list is reached or the user presses find or closes the form, etc. And this is also the most likly use case to contain bugs by the caller that could, if I used jdeStoreDataPtr, leak jdeStoreDataPtr handles.

    The recomendation from Oracle is to replace the code above with:

    Code:
    lpDS->idCursorHandle = jdeStoreDataPtr(hUser, hCursor);
    ...
    hCursor = jdeRemoveDataPtr(hUser, lpDS->idCursorHandle);
    My fear is that this could cause bugs to suddenly manifest themselves that were previously, for all intensive purposes, innocuous. And these bugs are going to be EXTREMELY hard to track down.
    Brian Oster
    Application Development Manager
    E1: 9.0 (TR9.1.5.1) / 9.2 (TR9.2.2.2)
    JAS/BSSV: Weblogic 12.1.2 / Weblogic 12.2
    ES: Win2008 / Win2016
    DB: MSSQL 2014 / 2016
    WebDev Client: Win7Pro / Win10Pro

  5. #15
    Member
    Join Date
    Jun 2001
    Location
    Colorful Colorado
    Posts
    463
    Yeah. That won't work, ID is defined to be "unsigned int" in the new release which is always 32 bit, and HCURSOR is "void *". (ID was "unsigned long" but as their doc points out, long was 32 bits everywhere in 32-bit mode, but in 64-bit enabled code, long is 32 bits on IBMi and windows, and 64 bits on UNIXes).

    The thing is, that code of yours already wouldn't have worked on IBMi, as pointers there have always been 16 bytes (128 bits), and you would be truncating all but 32 bits of the pointer on the pre-9.2.3 releases as well.

    But I understand your concerns!
    Last edited by Segfault; 11-16-2018 at 02:55 PM.
    --john

  6. #16
    Member craig_welton's Avatar
    Join Date
    Oct 2000
    Location
    Litchfield, CT
    Posts
    961
    Very interesting point John, and thanks for that detail. I have been working on an iSeries for years and we have a couple of cases (pre 64bit JDE) where a handle is passed to a function, with no problems. I believe the issue is controlled by the nature of a "handle". It's an opaque pointer, my favourite description. It's not a pointer to any type or structure, and really just a slot in a table of pointers. This abstraction allows the system to manage the true size of the memory being pointed to. In fact, Windows stores handles to shared resources as 32bit values even in a 64bit OS (i.e. the first 32 bits are set to 0 in 64bit). Oracle is probably following the same pattern.

    Here's something to think about … you can declare a JDE variable as a "handle" to be used in table IO within an NER. That variable is declared as an ID (32 bit). The underlying code that opens the table/view stores the handle in the ID variable. I think the JDE API is ensuring these handle values are 32bit, just 0 filled in a 64bit arch.

    Craig
    Craig Welton
    PatWel Group Inc.
    http://www.patwel.com
    Home of the FREE JDE Object Browser, JDETrace and NERDup Tools

    E1 9.0 8.98.4.2 Wintel SQL 2008
    E1 9.2 9.2.1.4 iSeries

  7. #17
    Senior Member
    Join Date
    Mar 2004
    Location
    Fort Worth, Texas
    Posts
    1,517
    That's an interesting observation. So it could be that I could safely cast from HJDECURSOR to ID and back in a 64bit arch if HJDECURSOR is returning a handle using the same technique as HREQUEST i.e. a 32 bit value?
    Brian Oster
    Application Development Manager
    E1: 9.0 (TR9.1.5.1) / 9.2 (TR9.2.2.2)
    JAS/BSSV: Weblogic 12.1.2 / Weblogic 12.2
    ES: Win2008 / Win2016
    DB: MSSQL 2014 / 2016
    WebDev Client: Win7Pro / Win10Pro

  8. #18
    Member craig_welton's Avatar
    Join Date
    Oct 2000
    Location
    Litchfield, CT
    Posts
    961
    We can infer that is the case with the HREQUEST handle since generated NER stores the value in an ID. We can hope that the same holds true for all handles. Perhaps I'll create a test function that opens thousands of cursors and checks the status of the high 32 bits.
    Craig Welton
    PatWel Group Inc.
    http://www.patwel.com
    Home of the FREE JDE Object Browser, JDETrace and NERDup Tools

    E1 9.0 8.98.4.2 Wintel SQL 2008
    E1 9.2 9.2.1.4 iSeries

  9. #19
    Member
    Join Date
    Jun 2001
    Location
    Colorful Colorado
    Posts
    463
    Quote Originally Posted by craig_welton View Post
    We can infer that is the case with the HREQUEST handle since generated NER stores the value in an ID. We can hope that the same holds true for all handles. Perhaps I'll create a test function that opens thousands of cursors and checks the status of the high 32 bits.
    Can you provide an example of this (a JDE NER file name/function/line)? All generated NERs I've looked at looking for this so far are using HREQUESTS and not IDs.
    --john

  10. #20
    Senior Member
    Join Date
    Mar 2004
    Location
    Fort Worth, Texas
    Posts
    1,517
    This is from TR9.1 (32bit). It does look like maybe the actual HREQUEST is still stored in an HREQUEST variable (FILEIO_HANDLE_INFO zHndlInfo) and evt_HandleF0101 is a true handle to zHndInfo????

    ER Code
    Code:
    =======================================================================
         NAMED ER: zztest_TestTableHandle
    =======================================================================
         evt_HandleF0101
         evt_mnAddressNumber
         evt_szNameAlpha
         OPT: Using Defaults
    0001 VA evt_mnAddressNumber = "2000072"
    0002 VA evt_HandleF0101 = F0101.Open Handle
    0003 F0101(VA evt_HandleF0101).Fetch Single
            VA evt_mnAddressNumber =  TK Address Number
            VA evt_szNameAlpha <- TK Name - Alpha
    0004 F0101(VA evt_HandleF0101).Close

    Generated C code
    Code:
    JDEBFRTN(ID) JDEBFWINAPI
    zztest_TestTableHandle( LPBHVRCOM lpBhvrCom ,
        LPVOID lpVoid ,
        LPDSD58DUMMY lpDS )
    {
      /*****************************************************************
       *  Variable declarations
       *****************************************************************/
      ID idRtnVal = ER_SUCCESS;
      ID evt_HandleF0101 = 0;
      MATH_NUMERIC evt_mnAddressNumber = { 0 };
      JCHAR evt_szNameAlpha[41] = { 0 };
      JDEDB_RESULT iRtnJDB = JDEDB_ERROR;
    
      /*****************************************************************
       *  Declare structures
       *****************************************************************/
      F0101 zF0101_3 = { 0 };
      FILEIO_HANDLE_INFO zHndlInfo = { 0 };
      SELECTSTRUCT zSelect4[1] = { 0 };
      DBREF zDbRef5 = { 0 };
    
      /*****************************************************************
       *  Declare pointers
       *****************************************************************/
      LPJDEAPP lpObj = (LPJDEAPP)NULL;
      LPAPPVARIABLES pAppVars = (LPAPPVARIABLES)NULL;
      HENV hEnv = (HENV)NULL;
      JCHAR* pszEnvName = (JCHAR*)NULL;
      HUSER hUser = (HUSER)NULL;
      LPKEYINFO pKeyInfo = (LPKEYINFO)NULL;
      void* pKeyBuffer = NULL;
    
      /*****************************************************************
       *  Check for NULL pointers
       *****************************************************************/
      if ( ( lpBhvrCom == (LPBHVRCOM)NULL ) ||
          ( lpVoid == (LPVOID)NULL ) ||
          ( lpDS == (LPDSD58DUMMY)NULL ) )
      {
        jdeErrorSet( lpBhvrCom , lpVoid , 0L , _J("4363") , (LPVOID)NULL );
        return ER_ERROR;
      }
    
      /*****************************************************************
       *  Set pointers
       *****************************************************************/
      lpObj = lpBhvrCom->lpObj;
      pAppVars = lpObj->lpzAppVars;
      hEnv = lpBhvrCom->hEnv;
      pszEnvName = JDB_GetEnvironment( hEnv );
      iRtnJDB = JDB_InitBhvr( lpBhvrCom , &hUser , NULL , JDEDB_COMMIT_AUTO );
    
      /*****************************************************************
       *  Main processing
       *****************************************************************/
      zDbRef5.idInstance = 0L;
    
      /* VA evt_mnAddressNumber = "2000072" */
      ParseNumericStringEx( &evt_mnAddressNumber ,
          _J("2000072") , DEFAULT_SEPARATOR | CURRENCY_KEEP );
    
      /* VA evt_HandleF0101 = F0101.Open Handle */
      pAppVars->iTableRetCode = RTK_CER_FIOOpenHandle( hEnv, hUser ,
          _J("F0101") , pszEnvName , 1L ,  0 , &evt_HandleF0101 );
    
      /* F0101(VA evt_HandleF0101).Fetch Single */
      pKeyInfo = (LPKEYINFO)jdeAlloc(COMMON_POOL, 3 * sizeof(struct keyinfo), MEM_ZEROINIT);
      if ( RTK_CER_FIOGetHandleInfo( evt_HandleF0101 , &zHndlInfo ) )
      {
        pAppVars->iTableRetCode = ER_ERROR;
        if ( JDB_ClearSelection( zHndlInfo.hReqest ) == JDEDB_PASSED )
        {
          RTK_CER_FIOSelectInitH( zSelect4 , 1 , zHndlInfo.nType ,
              zHndlInfo.szFileName , 0L );
          jdeNIDcpy( zSelect4[0].Item1.szDict , _J("AN8") );
          if ( zHndlInfo.nType == FILEIO_TYPE_VIEW )
          {
            jdeNIDcpy( zSelect4[0].Item1.szTable , _J("F0101") );
            zSelect4[0].Item1.idInstance = 0L;
          }
          zSelect4[0].lpValue = (LPVOID)&evt_mnAddressNumber;
          jdeNIDcpy( zDbRef5.szTable , zHndlInfo.szFileName );
          jdeNIDcpy( zDbRef5.szDict , _J("AN8") );
          if(jdeK2AddtoKeyStruct(pKeyInfo, 0, zDbRef5, &evt_mnAddressNumber, 9, -1) == FALSE)
          {
            if(pKeyInfo)
            {
              jdeFree(pKeyInfo);
              pKeyInfo=NULL;
            }
          }
          if(pKeyInfo)
          {
            pKeyBuffer=JDB_BuildKeyBuffer(pKeyInfo,1);
            if ( JDB_FetchKeyed( zHndlInfo.hReqest , 1L , pKeyBuffer , 1, &zF0101_3 , 0 ) != JDEDB_PASSED )
            {
              JDB_ClearSelection( zHndlInfo.hReqest );
              JDB_ClearSequencing( zHndlInfo.hReqest );
            }
            else
            {
              jdeStrncpyTerminate( evt_szNameAlpha , zF0101_3.abalph ,
                  DIM( evt_szNameAlpha ) );
              pAppVars->iTableRetCode = ER_SUCCESS;
            }
          }
          else
          {
            RTK_CER_FIOSelect( zHndlInfo.hReqest , 1L , 1 , zSelect4 , 
                &pAppVars->iTableRetCode );
            if ( pAppVars->iTableRetCode == ER_SUCCESS )
            {
              pAppVars->iTableRetCode = ER_ERROR;
              if ( JDB_Fetch( zHndlInfo.hReqest , &zF0101_3 , 0 ) != JDEDB_PASSED )
              {
                JDB_ClearSelection( zHndlInfo.hReqest );
                JDB_ClearSequencing( zHndlInfo.hReqest );
              }
              else
              {
                jdeStrncpyTerminate( evt_szNameAlpha , zF0101_3.abalph ,
                    DIM( evt_szNameAlpha ) );
                pAppVars->iTableRetCode = ER_SUCCESS;
              }
            }
          }
        }
      }
      if ( pKeyInfo )
      {
        jdeFree( pKeyInfo );
        pKeyInfo=(LPKEYINFO)NULL;
      }
      if ( pKeyBuffer )
      {
        JDB_FreeKeyBuffer( pKeyBuffer );
        pKeyBuffer=NULL;
      }
    
      /* F0101(VA evt_HandleF0101).Close */
      pAppVars->iTableRetCode = RTK_CER_FIOCloseHandle( evt_HandleF0101 );
      pAppVars->iTableRetCode = RTK_CER_FIOCloseHandle( evt_HandleF0101 );
      if ( hUser ) { JDB_FreeBhvr( hUser ); }
    
      return idRtnVal;
    } /* end of zztest_TestTableHandle */
    Code:
    typedef struct tagFILEIO_HANDLE_INFO
    {
       HENV           hEnv;          /* environment associated with handle  */
       NID            szEnvName;     /* environment name                    */
       HUSER          hUSER;         /* user associated with handle         */
       NID            szFileName;    /* filename handle points to           */
       unsigned short nType;         /* 0/1 = table/view                    */
       unsigned long  nHandleValue;  /* Handle value                        */
       HREQUEST       hReqest;       /* the HREQUEST for this fileio handle */
    } FILEIO_HANDLE_INFO;
    Brian Oster
    Application Development Manager
    E1: 9.0 (TR9.1.5.1) / 9.2 (TR9.2.2.2)
    JAS/BSSV: Weblogic 12.1.2 / Weblogic 12.2
    ES: Win2008 / Win2016
    DB: MSSQL 2014 / 2016
    WebDev Client: Win7Pro / Win10Pro

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
The legal restrictions and terms of use applicable to this site are available here.
Use of this site signifies your agreement to the terms of use.
JDELIST is NOT affiliated with JD Edwards® & Company, Oracle or Peoplesoft. Contents of this site are neither endorsed nor approved by JD Edwards® & Company and, or Oracle.