home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / opendc12.zip / od124os2.exe / od12osr1.exe / src / ilinksrc.cpp < prev    next >
C/C++ Source or Header  |  1997-03-21  |  107KB  |  3,304 lines

  1. /* @(#)Z 1.7 os2/src/storage/ilinksrc.cpp, oddataxfer, od96os2, odos29712d 97/03/21 17:38:53 (96/10/01 12:46:24) */
  2. //====START_GENERATED_PROLOG======================================
  3. //
  4. //
  5. //   COMPONENT_NAME: oddataxfer
  6. //
  7. //   CLASSES: none
  8. //
  9. //   ORIGINS: 82,27
  10. //
  11. //
  12. //   (C) COPYRIGHT International Business Machines Corp. 1995,1996
  13. //   All Rights Reserved
  14. //   Licensed Materials - Property of IBM
  15. //   US Government Users Restricted Rights - Use, duplication or
  16. //   disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  17. //       
  18. //   IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  19. //   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  20. //   PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  21. //   CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
  22. //   USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  23. //   OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
  24. //   OR PERFORMANCE OF THIS SOFTWARE.
  25. //
  26. //====END_GENERATED_PROLOG========================================
  27. //
  28.  
  29.  
  30. #ifdef _PLATFORM_OS2_
  31. #include <odpagtun.h>
  32. #endif
  33.  
  34. #ifdef _PLATFORM_OS2_
  35. #ifndef SOM_Module_ILinkSrc_Source
  36. #define SOM_Module_ILinkSrc_Source
  37. #endif
  38. #define IODLinkSource_Class_Source
  39.  
  40. #define METHOD_MACROS
  41. #define VARIABLE_MACROS
  42. #include <Builtin.h>
  43. #include <barray.h>
  44. #include <process.h>
  45. #include <limits.h>
  46.  
  47. #ifndef _ITEXT_
  48. #include <IText.h>
  49. #endif
  50.  
  51. #include <ISOStr.h>
  52. #include <IODDefs.xh>
  53. #include <ICIDItr.xh>
  54. #define INCL_DOSSEMAPHORES
  55. #define INCL_ODAPI
  56. #include <os2.h>
  57. #include <bsedos.h>
  58.  
  59. #ifndef _OPENHASH_
  60.   #include <OpenHash.h>
  61. #endif
  62.  
  63. #ifndef _EXCEPT_
  64.   #include <Except.h>
  65. #endif
  66.  
  67. #ifndef _STDTYPIO_
  68.   #include <StdTypIO.h>
  69. #endif
  70.  
  71. #ifndef _STORUTIL_
  72.   #include <storutil.h>
  73. #endif
  74.  
  75. #ifdef _PLATFORM_OS2_
  76. #include <ODPagtun.h>
  77. #endif
  78.  
  79. #ifndef SOM_Module_StdTypes_OpenDoc_StdTypes_defined
  80.   #include <StdTypes.xh>
  81. #endif
  82.  
  83.  
  84. #ifndef SOM_ODDraft_xh
  85.   #include <Draft.xh>
  86. #endif
  87.  
  88. #ifndef SOM_ODFrame_xh
  89.   #include <Frame.xh>
  90. #endif
  91.  
  92. #ifndef SOM_ODStorageUnit_xh
  93.   #include <StorageU.xh>
  94. #endif
  95.  
  96. #ifndef SOM_IODLinkTarget_xh
  97.   #include <ILnkTrgt.xh>
  98. #endif
  99.  
  100. #ifndef SOM_IODMutex_xh
  101.   #include <IODMutex.xh>
  102. #endif
  103.  
  104. #ifndef SOM_ODLink_xh
  105.   #include <link.xh>
  106. #endif
  107.  
  108. #ifndef SOM_ODLinkspec_xh
  109.   #include <linkspec.xh>
  110. #endif
  111.  
  112. #include <lmgrdefs.h>
  113.  
  114. #include <somd.xh>
  115.  
  116. #include "ILinkSrc.xih"
  117.  
  118. const ODULong kODInitialNumEntries = 8;
  119. const kODOS2 = 1;
  120.  
  121. #define SET_SOM_EV \
  122.   ODSetSOMException(ev, ErrorCode(), ErrorMessage())
  123.  
  124. //Structure of an entry in the fLinkInfos hash table where the key is
  125. //   the connection ID
  126. typedef struct LinkInfo {
  127.   ODLinkConnectionData trgtPartDesc;
  128.   ODLinkConnectionID    trgtID;
  129.   IODLinkTarget*     linkTrgt;
  130.   ODBoolean          isAlive;
  131.   ODBoolean          isRegistered;
  132. } LinkInfo;
  133.  
  134.  
  135. /* ************************************************************************* */
  136. /* The following are copied from FEB13 build in file:                        */
  137. /* opendoc\src\opendoc\common\include\IText.h.                               */
  138. /* Otto and Chris are working on NLS design and the following                */
  139. /* might need to be redesigned when they are done. 5/14/96                   */
  140. /* ************************************************************************* */
  141. // typedef unsigned long CodePage;                      // (defined in odosacom.h)
  142. // typedef CodePage      ODCodePage;
  143. // ODCodePage APIENTRY GetITextCodePage(ODIText*);
  144. // void       APIENTRY SetITextCodePage(ODIText*, ODCodePage);
  145.  
  146.  
  147. /*
  148.  *=============================================================================
  149.  * Local function to free a lock wait element
  150.  *
  151.  * <1> destroy mutex
  152.  * <2> close event
  153.  * <3> free structure
  154.  *
  155.  *=============================================================================
  156. */
  157. void FreeLWE  (LockWaitElement* LWE)
  158. {
  159.   delete LWE->mutex;
  160.   APIRET rc = DosCloseEventSem(LWE->event);
  161.   delete LWE;
  162. }
  163.  
  164. /*
  165.  *=============================================================================
  166.  * Local function for getting a ISO string from the storage unit.
  167.  *
  168.  * <1>  Focus to the given property and value.
  169.  * <2>  Get string length by getting the size of the focused value.
  170.  * <3>  Allocate memory for the out parameter isoStr.
  171.  * <4>  Read the value of isoStr from the storage unit.
  172.  * <5>  Set string terminator.
  173.  *=============================================================================
  174. */
  175.  
  176. void GetISOStrProp (Environment *ev,
  177.                     ODStorageUnit *su,
  178.                     ODPropertyName prop,
  179.                     ODValueType val,
  180.                     ODISOStr &isoStr)
  181. {
  182.     ODULong strLength;
  183.  
  184.     //---<1>
  185.     if (ODSUExistsThenFocus(ev, su, prop, val))
  186.     {
  187.       //---<2>
  188.       strLength = su->GetSize(ev);
  189.  
  190.       //---<3>
  191.       isoStr = (ODISOStr)ODNewPtr(strLength+1, kDefaultHeapID);
  192.  
  193.       //---<4>
  194.       StorageUnitGetValue(su, ev, strLength, (ODValue)isoStr);
  195.  
  196.       //---<5>
  197.       isoStr[strLength] = '\0';
  198.     }
  199. }
  200.  
  201. /*
  202.  *=============================================================================
  203.  * Local function for locking the content SU of this LinkSource:
  204.  *
  205.  * <1> Grab the mutex
  206.  * <2> Try to get the lock.
  207.  *    <2a> succeeds (was unlocked and call to parent succeeded)
  208.  *         <2a1> marked locked
  209.  *         <2a2> release mutex
  210.  *         <2a3> return success
  211.  *    <2b> fails hopelessly (was unlocked but call to parent failed
  212.  *                          or was broken)
  213.  *         <2b1> release mutex
  214.  *         <2b2> return failure
  215.  *    <2c> fails hopefully (was locked)
  216.  *         <2c1> create a lock wait element:
  217.  *               new mutex;
  218.  *               new event;
  219.  *               not broken
  220.  *               not timedout
  221.  *         <2c2> queue it at the end of the FIFO
  222.  *         <2c3> release the mutex
  223.  *         <2c4> wait for the event
  224.  *         <2c5> grab the mutex in the LWE
  225.  *         <2c6> Determine whether you succeeded:
  226.  *               <2c6a> broken -- release mutex, free lock wait element
  227.  *                      and return failure
  228.  *                      Don't touch object --- it might have been freed
  229.  *               <2c6b> !broken&&!timeoutreturn -- release mutex,
  230.  *                      free lock wait element, and return key, failure if !=0
  231.  *               <2c6c> !broken&&timeoutreturn -- set timedout,
  232.  *                      release mutex, and return failure
  233.  *                      but don't free LWE because UNLOCK will free it.
  234.  *
  235.  *=============================================================================
  236. */
  237. ODBoolean WaitForLock  (IODLinkSource *somSelf,
  238.                         Environment *ev,
  239.                         ODULong wait,
  240.                         ODLinkKey* key,
  241.                         LockState* lockstate,
  242.                         IODMutex* mutex,
  243.                         LockWaitElement** first,
  244.                         LockWaitElement** last)
  245. {
  246. ODBoolean success;
  247. LockWaitElement* myLWE;
  248.  
  249. // 1.
  250.    mutex->Acquire(ev);
  251.  
  252. // 2.
  253.    if (*lockstate == IODLinkSource_UNLOCKED)
  254.      {
  255.        // 2a or 2b.
  256.        success = kODTrue;
  257.        *key = 1;
  258.        if (success)
  259.          {
  260.            *lockstate = IODLinkSource_LOCKED;
  261.          }
  262.        mutex->Release(ev);
  263.        return (success);
  264.      }
  265.    else if (*lockstate == IODLinkSource_BROKEN) {
  266.        // 2b.
  267.        mutex->Release(ev);
  268.        *key = 0;
  269.        return (kODFalse);
  270.      }
  271.    else {
  272.      // 2c.1
  273.      myLWE = new LockWaitElement;
  274.      myLWE->mutex = new IODMutex;
  275.      APIRET rc = DosCreateEventSem( (PSZ)kODNULL,
  276.                                     &myLWE->event,
  277.                                     0,
  278.                                     FALSE);
  279.      if (rc != 0) {
  280.        delete myLWE->mutex;
  281.        delete myLWE;
  282.        *key = 0;
  283.        return (kODFalse);
  284.        }
  285.  
  286.      ODULong usedwait = wait;
  287.      #if 0
  288.      usedwait = ULONG_MAX;
  289.      #endif
  290.  
  291.      if (usedwait == ULONG_MAX) {
  292.        usedwait = -1;
  293.      }
  294.  
  295.      myLWE->timedout = kODFalse;
  296.      myLWE->broken = kODFalse;
  297.  
  298.      // 2c.2.
  299.      myLWE->next = kODNULL;
  300.      if (*last == kODNULL) {
  301.        *first = myLWE;
  302.        *last = myLWE;
  303.      }
  304.      else {
  305.        (*last)->next = myLWE;
  306.      }
  307.  
  308.      // 2c.3
  309.      mutex->Release(ev);
  310.  
  311.      // 2c.4
  312.      APIRET rc2 = DosWaitEventSem(myLWE->event, usedwait);
  313.  
  314.      // 2c.5
  315.      myLWE->mutex->Acquire(ev);
  316.  
  317.      // 2c.6
  318.      if (myLWE->broken) {
  319.        // 2c.6.a.
  320.        myLWE->mutex->Release(ev);
  321.        *key = 0;
  322.        FreeLWE(myLWE);
  323.        return (kODFalse);
  324.      }
  325.      else if (rc2 == 0) {
  326.        // 2c.6.b.
  327.        myLWE->mutex->Release(ev);
  328.        *key = myLWE->key;
  329.        FreeLWE(myLWE);
  330.        return ((ODBoolean) (*key > 0));
  331.      }
  332.      else {
  333.        // 2c.6.c.
  334.        myLWE->timedout = kODTrue;
  335.        myLWE->mutex->Release(ev);
  336.        *key = 0;
  337.        return (kODFalse);
  338.      }
  339.    }
  340. }
  341.  
  342. /*
  343.  *=============================================================================
  344.  * Local function for writing a hashtable of LinkInfo to the
  345.  * storage unit.
  346.  *
  347.  * <1>  Focus to the given property and value.
  348.  * <2>  Reserve space to write the number of elements in the hashtable.
  349.  * <3>  Iterate thru each element of the hash table.
  350.  * <4>  Write the trgtID, isAlive and isRegistered fields of linkInfo.
  351.  * <5>  The hashtable is for local linkInfo:
  352.  *      Retreive the SUID of the LinkTarget.
  353.  *      Get a weak SU reference from the SUID.
  354.  *      Write the weak SU reference.
  355.  * <6>  The hashtable is for remote linkInfo.
  356.  *      Ask SOM to convert the LinkTarget proxy reference to a SOM externalized
  357.  *      ID.
  358.  *      Get the string length of the SOM externalized ID.
  359.  *      Write the string length.
  360.  *      Write the SOM externalized ID.
  361.  *      Free the ID.
  362.  *      XXXXX Use SOMFree or ORDFree to free the ID ?????
  363.  * <7>  Write the trgtPartDesc field of linkInfo.
  364.  *      The trgtPartDesc is a struct consists of three fields: hostName,
  365.  *      docName and linkdesc, each of which is an ODIText string.
  366.  * <8>  Count the number of elements in the hashtable.
  367.  * <9>  After iterating thru the hashtable, refocus to the given property and
  368.  *      value.
  369.  *      Write the total number of elements in the hashtable in the space
  370.  *      reseved at <2>.
  371.  *=============================================================================
  372. */
  373.  
  374. void SetLinkInfosProp (Environment *ev,
  375.                        ODStorageUnit *su,
  376.                        ODPropertyName prop,
  377.                        ODValueType val,
  378.                        OpenHashTable &linkInfos)
  379. {
  380.     ODLinkConnectionID  key;
  381.     LinkInfo*        linkInfo;
  382.     ODULong          numOfElmnts = 0;
  383.     ODULong          newSize;
  384.     ODULong          oldSize;
  385.     ODISOStr         remoteTrgtID;
  386.     ODULong          strLength;
  387.     ODID             trgtSUID;
  388.     ODStorageUnitRef trgtSURef;
  389.  
  390.     //---<1>
  391.     ODSUForceFocus(ev, su, prop, val);
  392.  
  393.     //---<2>
  394.     StorageUnitSetValue(su, ev, sizeof(ODULong), (ODValue)&numOfElmnts);
  395.  
  396.     //---<3>
  397.     OpenHashTableIterator infos(&linkInfos);
  398.     for (infos.First(&key, &linkInfo);
  399.          infos.IsNotComplete();
  400.          infos.Next(&key, &linkInfo))
  401.     {
  402.       //---<4>
  403.       StorageUnitSetValue(su,
  404.                           ev,
  405.                           sizeof(ODLinkConnectionID),
  406.                           (ODValue)&(linkInfo->trgtID));
  407.       StorageUnitSetValue(su,
  408.                           ev,
  409.                           sizeof(ODBoolean),
  410.                           (ODValue)&(linkInfo->isAlive));
  411.       StorageUnitSetValue(su,
  412.                           ev,
  413.                           sizeof(ODBoolean),
  414.                           (ODValue)&(linkInfo->isRegistered));
  415.  
  416.       if (ODISOStrEqual(prop, kODPropLocalLinkInfos))
  417.       {
  418.         //---<5>
  419.         trgtSUID = linkInfo->linkTrgt->GetStorageUnit(ev)->GetID(ev);
  420.         su->GetWeakStorageUnitRef(ev, trgtSUID, trgtSURef);
  421.         StorageUnitSetValue(su,
  422.                             ev,
  423.                             sizeof(ODStorageUnitRef),
  424.                             (ODValue)&trgtSURef);
  425.       }
  426.       else
  427.       {
  428.         //---<6>
  429.         remoteTrgtID = SOMD_ObjectMgr->
  430.                          somdGetIdFromObject(ev, linkInfo->linkTrgt);
  431.         strLength = ODISOStrLength(remoteTrgtID);
  432.  
  433.         StorageUnitSetValue(su, ev, sizeof(ODULong), (ODValue)&strLength);
  434.         StorageUnitSetValue(su, ev, strLength+1, (ODValue)remoteTrgtID);
  435.         SOMFree(remoteTrgtID);
  436.       }
  437.  
  438.       //---<7>
  439.       {
  440.       char* istring; /* string part of itext */
  441. //      ODCodePage scode; /* script code part of itext */
  442.       ODScriptCode scode;
  443.       ODLangCode lcode; /* language code partof itext */
  444.  
  445.       istring = GetCStringFromIText(&linkInfo->trgtPartDesc.HostName);
  446. //      scode = GetITextCodePage(&linkInfo->trgtPartDesc.HostName);
  447.       scode = GetITextScriptCode(&linkInfo->trgtPartDesc.HostName);
  448.       lcode = GetITextLangCode(&linkInfo->trgtPartDesc.HostName);
  449.       strLength = strlen(istring);
  450. //      StorageUnitSetValue(su, ev, sizeof(ODCodePage), (ODValue) &scode);
  451.       StorageUnitSetValue(su, ev, sizeof(ODScriptCode), (ODValue) &scode);
  452.       StorageUnitSetValue(su, ev, sizeof(ODLangCode), (ODValue) &lcode);
  453.       StorageUnitSetValue(su, ev, sizeof(ODULong), (ODValue)&strLength);
  454.       StorageUnitSetValue(su,
  455.                           ev,
  456.                           strLength+1,
  457.                           (ODValue)istring);
  458.       delete istring;
  459.  
  460.       istring = GetCStringFromIText(&linkInfo->trgtPartDesc.DocumentName);
  461. //      scode = GetITextCodePage(&linkInfo->trgtPartDesc.DocumentName);
  462.       scode = GetITextScriptCode(&linkInfo->trgtPartDesc.DocumentName);
  463.       lcode = GetITextLangCode(&linkInfo->trgtPartDesc.DocumentName);
  464.       strLength = strlen(istring);
  465. //      StorageUnitSetValue(su, ev, sizeof(ODCodePage), (ODValue) &scode);
  466.       StorageUnitSetValue(su, ev, sizeof(ODScriptCode), (ODValue) &scode);
  467.       StorageUnitSetValue(su, ev, sizeof(ODLangCode), (ODValue) &lcode);
  468.       StorageUnitSetValue(su, ev, sizeof(ODULong), (ODValue)&strLength);
  469.       StorageUnitSetValue(su,
  470.                           ev,
  471.                           strLength+1,
  472.                           (ODValue)istring);
  473.       delete istring;
  474.  
  475.       istring = GetCStringFromIText(&linkInfo->trgtPartDesc.LinkDesc);
  476. //      scode = GetITextCodePage(&linkInfo->trgtPartDesc.LinkDesc);
  477.       scode = GetITextScriptCode(&linkInfo->trgtPartDesc.LinkDesc);
  478.       lcode = GetITextLangCode(&linkInfo->trgtPartDesc.LinkDesc);
  479.       strLength = strlen(istring);
  480. //     StorageUnitSetValue(su, ev, sizeof(ODCodePage), (ODValue) &scode);
  481.       StorageUnitSetValue(su, ev, sizeof(ODScriptCode), (ODValue) &scode);
  482.       StorageUnitSetValue(su, ev, sizeof(ODLangCode), (ODValue) &lcode);
  483.       StorageUnitSetValue(su, ev, sizeof(ODULong), (ODValue)&strLength);
  484.       StorageUnitSetValue(su,
  485.                           ev,
  486.                           strLength+1,
  487.                           (ODValue)istring);
  488.       delete istring;
  489.  
  490.       }
  491.       //---<8>
  492.       numOfElmnts++;
  493.     }
  494.  
  495.     //---<9>
  496.     su->Focus(ev, prop, kODPosSame, val, 0, kODPosSame);
  497.     StorageUnitSetValue(su, ev, sizeof(ODULong), (ODValue)&numOfElmnts);
  498. }
  499.  
  500. /*
  501.  *=============================================================================
  502.  * Local function for reading a hashtable of LinkInfo from a
  503.  * storage unit.
  504.  *
  505.  * <1>  Focus to the given property and value.
  506.  * <2>  Read the total number of elements in the hashtable into numOfElemnts.
  507.  * <3>  Loop to read in each element of the hashtable.
  508.  * <4>  Create a new linkInfo.
  509.  * <5>  Read in the trgtID, isAlive and isRegistered sub fields of linkInfo.
  510.  * <6>  The hashtable is for local linkInfo.
  511.  *      Read in the LinkTarget's SU reference.
  512.  *      Retrieve the SU ID from the SU reference.
  513.  *      Ask the Draft for an object reference of the LinkTarget from the SU ID.
  514.  * <7>  The hashtable is for remote linkInfo.
  515.  *      Read in the string length of the SOM externalized ID.
  516.  *      Allocate memory for remoteTrgtID as read buffer.
  517.  *      Read in the SOM externalized ID.
  518.  *      Ask SOM to convert the ID to a LinkTarget Proxy reference.
  519.  *      Free the SOM externalized ID.
  520.  * <8>  Read in the trgtPartDesc field of linkInfo.
  521.  * <9>  Add linkInfo to the hashtable.
  522.  *=============================================================================
  523. */
  524.  
  525. void GetLinkInfosProp (Environment *ev,
  526.                        ODStorageUnit *su,
  527.                        ODPropertyName prop,
  528.                        ODValueType val,
  529.                        OpenHashTable &linkInfos)
  530. {
  531.     ODULong          i;
  532.     LinkInfo*        linkInfo;
  533.     ODULong          numOfElmnts;
  534.     ODISOStr         remoteTrgtID;
  535.     ODULong          strLength;
  536.     ODID             trgtSUID;
  537.     ODStorageUnitRef trgtSURef;
  538.  
  539.     //---<1>
  540.     if (ODSUExistsThenFocus(ev, su, prop, val))
  541.     {
  542.       //---<2>
  543.       StorageUnitGetValue(su, ev, sizeof(ODULong), (ODValue)&numOfElmnts);
  544.  
  545.       //---<3>
  546.       for (i = 0; i < numOfElmnts; i++)
  547.       {
  548.         //---<4>
  549.         linkInfo = new LinkInfo;
  550.  
  551.         //---<5>
  552.         StorageUnitGetValue(su,
  553.                             ev,
  554.                             sizeof(ODLinkConnectionID),
  555.                             (ODValue)&(linkInfo->trgtID));
  556.         StorageUnitGetValue(su,
  557.                             ev,
  558.                             sizeof(ODBoolean),
  559.                             (ODValue)&(linkInfo->isAlive));
  560.         StorageUnitGetValue(su,
  561.                             ev,
  562.                             sizeof(ODBoolean),
  563.                             (ODValue)&(linkInfo->isRegistered));
  564.  
  565.         if (ODISOStrEqual(prop, kODPropLocalLinkInfos))
  566.         {
  567.           //---<6>
  568.           StorageUnitGetValue(su,
  569.                               ev,
  570.                               sizeof(ODStorageUnitRef),
  571.                               (ODValue)&trgtSURef);
  572.           if (su->IsValidStorageUnitRef(ev, trgtSURef))
  573.           {
  574.             trgtSUID = su->GetIDFromStorageUnitRef(ev, trgtSURef);
  575.             if (trgtSUID != 0)
  576.             {
  577.               linkInfo->linkTrgt = (IODLinkTarget*)
  578.                                    su->GetDraft(ev)->
  579.                                          AcquireLink(ev,
  580.                                                      trgtSUID,
  581.                                                      (ODLinkSpec*)kODNULL);
  582.             }
  583.             else
  584.             {
  585.               //XXXXX Should raise exception here
  586.             continue;
  587.             }
  588.           }
  589.           else
  590.           {
  591.             //XXXXX Should raise exception here
  592.             continue;
  593.           }
  594.         }
  595.         else
  596.         {
  597.           //---<7>
  598.           StorageUnitGetValue(su, ev, sizeof(ODULong), (ODValue)&strLength);
  599.           remoteTrgtID = (ODISOStr)SOMMalloc(strLength+1);
  600.  
  601.           StorageUnitGetValue(su, ev, strLength+1, (ODValue)remoteTrgtID);
  602.           linkInfo->linkTrgt = (IODLinkTarget*)
  603.                                SOMD_ObjectMgr->
  604.                                  somdGetObjectFromId(ev, remoteTrgtID);
  605.           SOMFree(remoteTrgtID);
  606.         }
  607.  
  608.         //---<8>
  609.         {
  610.         char* istring; /* string part of itext */
  611. //        ODCodePage scode; /* script code part of itext */
  612.         ODScriptCode scode; /* script code part of itext */
  613.         ODLangCode lcode; /* language code part of itext */
  614.  
  615.         StorageUnitGetValue(su, ev, sizeof(ODScriptCode), (ODValue)&scode);
  616.         StorageUnitGetValue(su, ev, sizeof(ODLangCode), (ODValue)&lcode);
  617.         StorageUnitGetValue(su, ev, sizeof(ODULong), (ODValue)&strLength);
  618.         istring = new char[strLength+1];
  619.         istring[strLength] = '\0';
  620.         StorageUnitGetValue(su,
  621.                             ev,
  622.                             strLength+1,
  623.                             (ODValue)istring);
  624.         linkInfo->trgtPartDesc.HostName.format = kODIBMCodePageText;
  625.         linkInfo->trgtPartDesc.HostName.text._buffer = kODNULL;
  626.         SetITextCString(&linkInfo->trgtPartDesc.HostName, istring);
  627.         SetITextLangCode(&linkInfo->trgtPartDesc.HostName, lcode);
  628. //        SetITextCodePage(&linkInfo->trgtPartDesc.HostName, scode);
  629.         SetITextScriptCode(&linkInfo->trgtPartDesc.HostName, scode);
  630.         delete istring;
  631.  
  632. //        StorageUnitGetValue(su, ev, sizeof(ODCodePage), (ODValue)&scode);
  633.         StorageUnitGetValue(su, ev, sizeof(ODScriptCode), (ODValue)&scode);
  634.         StorageUnitGetValue(su, ev, sizeof(ODLangCode), (ODValue)&lcode);
  635.         StorageUnitGetValue(su, ev, sizeof(ODULong), (ODValue)&strLength);
  636.         istring = new char[strLength+1];
  637.         istring[strLength] = '\0';
  638.         StorageUnitGetValue(su,
  639.                             ev,
  640.                             strLength+1,
  641.                             (ODValue)istring);
  642.         linkInfo->trgtPartDesc.DocumentName.format = kODIBMCodePageText;
  643.         linkInfo->trgtPartDesc.DocumentName.text._buffer = kODNULL;
  644.         SetITextCString(&linkInfo->trgtPartDesc.DocumentName, istring);
  645.         SetITextLangCode(&linkInfo->trgtPartDesc.DocumentName, lcode);
  646. //        SetITextCodePage(&linkInfo->trgtPartDesc.DocumentName, scode);
  647.         SetITextScriptCode(&linkInfo->trgtPartDesc.DocumentName, scode);
  648.         delete istring;
  649.  
  650. //        StorageUnitGetValue(su, ev, sizeof(ODCodePage), (ODValue)&scode);
  651.         StorageUnitGetValue(su, ev, sizeof(ODScriptCode), (ODValue)&scode);
  652.         StorageUnitGetValue(su, ev, sizeof(ODLangCode), (ODValue)&lcode);
  653.         StorageUnitGetValue(su, ev, sizeof(ODULong), (ODValue)&strLength);
  654.         istring = new char[strLength+1];
  655.         istring[strLength] = '\0';
  656.         StorageUnitGetValue(su,
  657.                             ev,
  658.                             strLength+1,
  659.                             (ODValue)istring);
  660.         linkInfo->trgtPartDesc.LinkDesc.format = kODIBMCodePageText;
  661.         linkInfo->trgtPartDesc.LinkDesc.text._buffer = kODNULL;
  662.         SetITextCString(&linkInfo->trgtPartDesc.LinkDesc, istring);
  663.         SetITextLangCode(&linkInfo->trgtPartDesc.LinkDesc, lcode);
  664. //       SetITextCodePage(&linkInfo->trgtPartDesc.LinkDesc, scode);
  665.         SetITextScriptCode(&linkInfo->trgtPartDesc.LinkDesc, scode);
  666.         delete istring;
  667.  
  668.         }
  669.         //---<9>
  670.         linkInfos.ReplaceEntry(&(linkInfo->trgtID), &linkInfo);
  671.       }
  672.     }
  673. }
  674.  
  675. /*
  676.  *=============================================================================
  677.  * Local function for cloning a hashtable of LinkInfo to another
  678.  * storage unit.
  679.  *
  680.  * <1>  Focus to the given property and value.
  681.  * <2>  Reserve space to write the number of elements in the hashtable.
  682.  * <3>  Iterate thru each element of the hash table.
  683.  * <4>  Write the trgtID, isAlive and isRegistered fields of linkInfo.
  684.  * <5>  The hashtable is for local linkInfo:
  685.  *      Ask the Draft to weak clone the LinkTarget and obtain a cloned SUID.
  686.  *      Get a weak SU reference from the cloned SUID.
  687.  *      Write the weak SU reference.
  688.  * <6>  The hashtable is for remote linkInfo:
  689.  *      Ask SOM to convert the LinkTarget proxy reference to a SOM externalized
  690.  *      ID.
  691.  *      Get the string length of the SOM externalized ID.
  692.  *      Write the string length.
  693.  *      Write the SOM externalized ID.
  694.  *      Free the ID.
  695.  *      XXXXX Use SOMFree or ORDFree to free the ID ?????
  696.  * <7>  Write the trgtPartDesc field of linkInfo.
  697.  *      The trgtPartDesc is a struct consists of three fields: hostName,
  698.  *      docName and linkdesc, each of which is an ODIText string.
  699.  * <8>  Count the number of elements in the hashtable.
  700.  * <9>  After iterating thru the hashtable, refocus to the given property and
  701.  *      value.
  702.  *      Write the total number of elements in the hashtable to the space
  703.  *      reseved at <2>.
  704.  *=============================================================================
  705. */
  706.  
  707. void CloneLinkInfosProp (Environment *ev,
  708.                          ODStorageUnit *su,
  709.                          ODPropertyName prop,
  710.                          ODValueType val,
  711.                          ODDraft* draft,
  712.                          ODDraftKey draftKey,
  713.                          ODFrame *scopeFrame,
  714.                          OpenHashTable &linkInfos)
  715. {
  716.     ODLinkConnectionID  key;
  717.     LinkInfo*        linkInfo;
  718.     ODULong          numOfElmnts = 0;
  719.     ODISOStr         remoteTrgtID;
  720.     ODULong          strLength;
  721.     ODID             trgtSUID;
  722.     ODStorageUnitRef trgtSURef;
  723.  
  724.     //---<1>
  725.     ODSUForceFocus(ev, su, prop, val);
  726.  
  727.     //---<2>
  728.     StorageUnitSetValue(su, ev, sizeof(ODULong), (ODValue)&numOfElmnts);
  729.  
  730.     //---<3>
  731.     OpenHashTableIterator infos(&linkInfos);
  732.     for (infos.First(&key, &linkInfo);
  733.          infos.IsNotComplete();
  734.          infos.Next(&key, &linkInfo))
  735.     {
  736.       //---<4>
  737.       StorageUnitSetValue(su,
  738.                           ev,
  739.                           sizeof(ODLinkConnectionID),
  740.                           (ODValue)&(linkInfo->trgtID));
  741.       StorageUnitSetValue(su,
  742.                           ev,
  743.                           sizeof(ODBoolean),
  744.                           (ODValue)&(linkInfo->isAlive));
  745.       StorageUnitSetValue(su,
  746.                           ev,
  747.                           sizeof(ODBoolean),
  748.                           (ODValue)&(linkInfo->isRegistered));
  749.  
  750.       if (ODISOStrEqual(prop, kODPropLocalLinkInfos))
  751.       {
  752.         //---<5>
  753.         trgtSUID = draft->WeakClone(ev,
  754.                                     draftKey,
  755.                                     linkInfo->linkTrgt->GetID(ev),
  756.                                     0,
  757.                                     (scopeFrame ? scopeFrame->GetID(ev) : 0));
  758.         su->GetWeakStorageUnitRef(ev, trgtSUID, trgtSURef);
  759.         StorageUnitSetValue(su,
  760.                             ev,
  761.                             sizeof(ODStorageUnitRef),
  762.                             (ODValue)&trgtSURef);
  763.       }
  764.       else
  765.       {
  766.         //---<6>
  767.         remoteTrgtID = SOMD_ObjectMgr->
  768.                          somdGetIdFromObject(ev, linkInfo->linkTrgt);
  769.         strLength = ODISOStrLength(remoteTrgtID);
  770.  
  771.         StorageUnitSetValue(su, ev, sizeof(ODULong), (ODValue)&strLength);
  772.         StorageUnitSetValue(su, ev, strLength+1, (ODValue)remoteTrgtID);
  773.         SOMFree(remoteTrgtID);
  774.       }
  775.  
  776.       //---<7>
  777.       {
  778.       char* istring; /* string part of itext */
  779. //      ODCodePage scode; /* script code part of itext */
  780.       ODScriptCode scode; /* script code part of itext */
  781.       ODLangCode lcode; /* language code partof itext */
  782.  
  783.       istring = GetCStringFromIText(&linkInfo->trgtPartDesc.HostName);
  784. //      scode = GetITextCodePage(&linkInfo->trgtPartDesc.HostName);
  785.       scode = GetITextScriptCode(&linkInfo->trgtPartDesc.HostName);
  786.       lcode = GetITextLangCode(&linkInfo->trgtPartDesc.HostName);
  787.       strLength = strlen(istring);
  788. //      StorageUnitSetValue(su, ev, sizeof(ODCodePage), (ODValue) &scode);
  789.       StorageUnitSetValue(su, ev, sizeof(ODScriptCode), (ODValue) &scode);
  790.       StorageUnitSetValue(su, ev, sizeof(ODLangCode), (ODValue) &lcode);
  791.       StorageUnitSetValue(su, ev, sizeof(ODULong), (ODValue)&strLength);
  792.       StorageUnitSetValue(su,
  793.                           ev,
  794.                           strLength+1,
  795.                           (ODValue)istring);
  796.       delete istring;
  797.  
  798.       istring = GetCStringFromIText(&linkInfo->trgtPartDesc.DocumentName);
  799. //      scode = GetITextCodePage(&linkInfo->trgtPartDesc.DocumentName);
  800.       scode = GetITextScriptCode(&linkInfo->trgtPartDesc.DocumentName);
  801.       lcode = GetITextLangCode(&linkInfo->trgtPartDesc.DocumentName);
  802.       strLength = strlen(istring);
  803. //      StorageUnitSetValue(su, ev, sizeof(ODCodePage), (ODValue) &scode);
  804.       StorageUnitSetValue(su, ev, sizeof(ODScriptCode), (ODValue) &scode);
  805.       StorageUnitSetValue(su, ev, sizeof(ODLangCode), (ODValue) &lcode);
  806.       StorageUnitSetValue(su, ev, sizeof(ODULong), (ODValue)&strLength);
  807.       StorageUnitSetValue(su,
  808.                           ev,
  809.                           strLength+1,
  810.                           (ODValue)istring);
  811.       delete istring;
  812.  
  813.       istring = GetCStringFromIText(&linkInfo->trgtPartDesc.LinkDesc);
  814. //      scode = GetITextCodePage(&linkInfo->trgtPartDesc.LinkDesc);
  815.       scode = GetITextScriptCode(&linkInfo->trgtPartDesc.LinkDesc);
  816.       lcode = GetITextLangCode(&linkInfo->trgtPartDesc.LinkDesc);
  817.       strLength = strlen(istring);
  818. //      StorageUnitSetValue(su, ev, sizeof(ODCodePage), (ODValue) &scode);
  819.       StorageUnitSetValue(su, ev, sizeof(ODScriptCode), (ODValue) &scode);
  820.       StorageUnitSetValue(su, ev, sizeof(ODLangCode), (ODValue) &lcode);
  821.       StorageUnitSetValue(su, ev, sizeof(ODULong), (ODValue)&strLength);
  822.       StorageUnitSetValue(su,
  823.                           ev,
  824.                           strLength+1,
  825.                           (ODValue)istring);
  826.       delete istring;
  827.  
  828.      }
  829.  
  830.       //---<8>
  831.       numOfElmnts++;
  832.     }
  833.  
  834.     //---<9>
  835.     su->Focus(ev, prop, kODPosSame, val, 0, kODPosSame);
  836.     StorageUnitSetValue(su, ev, sizeof(ODULong), (ODValue)&numOfElmnts);
  837. }
  838.  
  839. /*
  840.  *=============================================================================
  841.  * Local function for writing a ODLinkConnectionData structure to the storage
  842.  * unit.
  843.  *
  844.  * <1>  Focus to the given property and value.
  845.  * <2>  Write the hostName, docName and LinkDesc fields of the structure.
  846.  *      These three fields are all ODIText types, therefore their string
  847.  *      length, langcode, and scriptcode must be written before the string.
  848.  *=============================================================================
  849.  */
  850.  
  851. void SetPartDescriptionProp (Environment *ev,
  852.                              ODStorageUnit *su,
  853.                              ODPropertyName prop,
  854.                              ODValueType val,
  855.                              ODLinkConnectionData &partDesc)
  856. {
  857.     ODULong strLength;
  858.       char* istring; /* string part of itext */
  859. //      ODCodePage scode; /* script code part of itext */
  860.       ODScriptCode scode; /* script code part of itext */
  861.       ODLangCode lcode; /* language code part of itext */
  862.  
  863.     //---<1>
  864.     ODSUForceFocus(ev, su, prop, val);
  865.  
  866.     //---<2>
  867.       istring = GetCStringFromIText(&partDesc.HostName);
  868. //     scode = GetITextCodePage(&partDesc.HostName);
  869.       scode = GetITextScriptCode(&partDesc.HostName);
  870.       lcode = GetITextLangCode(&partDesc.HostName);
  871.       strLength = strlen(istring);
  872. //      StorageUnitSetValue(su, ev, sizeof(ODCodePage), (ODValue) &scode);
  873.       StorageUnitSetValue(su, ev, sizeof(ODScriptCode), (ODValue) &scode);
  874.       StorageUnitSetValue(su, ev, sizeof(ODLangCode), (ODValue) &lcode);
  875.       StorageUnitSetValue(su, ev, sizeof(ODULong), (ODValue)&strLength);
  876.       StorageUnitSetValue(su,
  877.                           ev,
  878.                           strLength+1,
  879.                           (ODValue)istring);
  880.       delete istring;
  881.  
  882.       istring = GetCStringFromIText(&partDesc.DocumentName);
  883. //      scode = GetITextCodePage(&partDesc.DocumentName);
  884.       scode = GetITextScriptCode(&partDesc.DocumentName);
  885.       lcode = GetITextLangCode(&partDesc.DocumentName);
  886.       strLength = strlen(istring);
  887. //      StorageUnitSetValue(su, ev, sizeof(ODCodePage), (ODValue) &scode);
  888.       StorageUnitSetValue(su, ev, sizeof(ODScriptCode), (ODValue) &scode);
  889.       StorageUnitSetValue(su, ev, sizeof(ODLangCode), (ODValue) &lcode);
  890.       StorageUnitSetValue(su, ev, sizeof(ODULong), (ODValue)&strLength);
  891.       StorageUnitSetValue(su,
  892.                           ev,
  893.                           strLength+1,
  894.                           (ODValue)istring);
  895.       delete istring;
  896.  
  897.       istring = GetCStringFromIText(&partDesc.LinkDesc);
  898. //      scode = GetITextCodePage(&partDesc.LinkDesc);
  899.       scode = GetITextScriptCode(&partDesc.LinkDesc);
  900.       lcode = GetITextLangCode(&partDesc.LinkDesc);
  901.       strLength = strlen(istring);
  902. //      StorageUnitSetValue(su, ev, sizeof(ODCodePage), (ODValue) &scode);
  903.       StorageUnitSetValue(su, ev, sizeof(ODScriptCode), (ODValue) &scode);
  904.       StorageUnitSetValue(su, ev, sizeof(ODLangCode), (ODValue) &lcode);
  905.       StorageUnitSetValue(su, ev, sizeof(ODULong), (ODValue)&strLength);
  906.       StorageUnitSetValue(su,
  907.                           ev,
  908.                           strLength+1,
  909.                           (ODValue)istring);
  910.       delete istring;
  911.  
  912.  
  913. }
  914.  
  915. /*
  916.  *=============================================================================
  917.  * Local function for reading a ODLinkConnectionData structure from the storage
  918.  * unit.
  919.  *
  920.  * <1>  Focus to the given property and value.
  921.  * <2>  Read in the hostName, docName and comm fields of the structure.
  922.  *      These three fields are all ODItext types, therefore their string
  923.  *      length must be read first in order to read the string itself.
  924.  *=============================================================================
  925.  */
  926.  
  927. void GetPartDescriptionProp (Environment *ev,
  928.                              ODStorageUnit *su,
  929.                              ODPropertyName prop,
  930.                              ODValueType val,
  931.                              ODLinkConnectionData &partDesc)
  932. {
  933.     ODULong strLength;
  934.  
  935.     //---<1>
  936.     if (ODSUExistsThenFocus(ev, su, prop, val))
  937.     {
  938.       //---<2>
  939.         char* istring; /* string part of itext */
  940. //        ODCodePage scode; /* script code part of itext */
  941.         ODScriptCode scode; /* script code part of itext */
  942.         ODLangCode lcode; /* language code part of itext */
  943.  
  944.         StorageUnitGetValue(su, ev, sizeof(ODScriptCode), (ODValue)&scode);
  945.         StorageUnitGetValue(su, ev, sizeof(ODLangCode), (ODValue)&lcode);
  946.         StorageUnitGetValue(su, ev, sizeof(ODULong), (ODValue)&strLength);
  947.         istring = new char[strLength+1];
  948.         istring[strLength] = '\0';
  949.         StorageUnitGetValue(su,
  950.                             ev,
  951.                             strLength+1,
  952.                             (ODValue)istring);
  953.         partDesc.HostName.format = kODIBMCodePageText;
  954.         partDesc.HostName.text._buffer = kODNULL;
  955.         SetITextCString(&partDesc.HostName, istring);
  956.         SetITextLangCode(&partDesc.HostName, lcode);
  957.         SetITextScriptCode(&partDesc.HostName, scode);
  958.         delete istring;
  959.  
  960.         StorageUnitGetValue(su, ev, sizeof(ODScriptCode), (ODValue)&scode);
  961.         StorageUnitGetValue(su, ev, sizeof(ODLangCode), (ODValue)&lcode);
  962.         StorageUnitGetValue(su, ev, sizeof(ODULong), (ODValue)&strLength);
  963.         istring = new char[strLength+1];
  964.         istring[strLength] = '\0';
  965.         StorageUnitGetValue(su,
  966.                             ev,
  967.                             strLength+1,
  968.                             (ODValue)istring);
  969.         partDesc.DocumentName.format = kODIBMCodePageText;
  970.         partDesc.DocumentName.text._buffer = kODNULL;
  971.         SetITextCString(&partDesc.DocumentName, istring);
  972.         SetITextLangCode(&partDesc.DocumentName, lcode);
  973.         SetITextScriptCode(&partDesc.DocumentName, scode);
  974.         delete istring;
  975.  
  976.         StorageUnitGetValue(su, ev, sizeof(ODScriptCode), (ODValue)&scode);
  977.         StorageUnitGetValue(su, ev, sizeof(ODLangCode), (ODValue)&lcode);
  978.         StorageUnitGetValue(su, ev, sizeof(ODULong), (ODValue)&strLength);
  979.         istring = new char[strLength+1];
  980.         istring[strLength] = '\0';
  981.         StorageUnitGetValue(su,
  982.                             ev,
  983.                             strLength+1,
  984.                             (ODValue)istring);
  985.         partDesc.LinkDesc.format = kODIBMCodePageText;
  986.         partDesc.LinkDesc.text._buffer = kODNULL;
  987.         SetITextCString(&partDesc.LinkDesc, istring);
  988.         SetITextLangCode(&partDesc.LinkDesc, lcode);
  989.         SetITextScriptCode(&partDesc.LinkDesc, scode);
  990.         delete istring;
  991.  
  992.     }
  993. }
  994.  
  995. /*
  996.  *=============================================================================
  997.  * Local function for copying ODLinkConnectionData structure
  998.  *
  999.  * <1>  Allocate memory for the hostName field and copy from the source.
  1000.  * <2>  Allocate memory for the docName field and copy from the source.
  1001.  * <3>  Allocate memory for the linkdesc field and copy from the source.
  1002.  *=============================================================================
  1003.  */
  1004.  
  1005. void CopyPartDescription(ODLinkConnectionData &dest,
  1006.                          ODLinkConnectionData &src)
  1007. {
  1008.     //---<1>
  1009.     dest.HostName = CopyITextStruct(&src.HostName);
  1010.  
  1011.     //---<2>
  1012.     dest.DocumentName = CopyITextStruct(&src.DocumentName);
  1013.  
  1014.     //---<3>
  1015.     dest.LinkDesc = CopyITextStruct(&src.LinkDesc);
  1016. }
  1017.  
  1018. /*
  1019.  *=============================================================================
  1020.  * Local function for cleaning up ODLinkConnectionData structure
  1021.  *
  1022.  * <1>  Free hostName, docName and comm field of partDesc.
  1023.  *=============================================================================
  1024.  */
  1025.  
  1026. void CleanupPartDescription (ODLinkConnectionData &partDesc)
  1027. {
  1028.     int i;
  1029.  
  1030.     //---<1>
  1031.     DisposeITextStruct(partDesc.LinkDesc);
  1032.     DisposeITextStruct(partDesc.DocumentName);
  1033.     DisposeITextStruct(partDesc.HostName);
  1034. }
  1035.  
  1036. /*
  1037.  *=============================================================================
  1038.  * Called by source Part or source Draft
  1039.  *   to retrieve the description of the
  1040.  *   given LinkTarget.
  1041.  *
  1042.  * <1>  Make sure current state is not EMPTY.
  1043.  * <2>  Acquire fMutex before accessing fLinkInfos.
  1044.  * <3>  Retrieve linkInfo associated with trgtID from fLinkInfos.
  1045.  * <4>  Allocate memory for the out parameter trgtPartDesc.
  1046.  *      If the link target is local, it has the same hostname and docname
  1047.  *      as the link source.
  1048.  *      Otherwise copy the trgtPartDesc field of linkInfo into the out
  1049.  *      parameter trgtPartDesc.
  1050.  *      Release fMutex and return.
  1051.  * <5>  An exception is caught.
  1052.  *      Release fMutex.
  1053.  *      Cleanup out trgtPartDesc.
  1054.  *      Set SOM exception and return.
  1055.  *=============================================================================
  1056.  */
  1057. SOM_Scope void  SOMLINK GetLinkConnectionData(IODLinkSource *somSelf,
  1058.                                                Environment *ev,
  1059.                                               ODLinkConnectionID connID,
  1060.                                               ODLinkConnectionData** ConnData)
  1061. {
  1062.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  1063.     IODLinkSourceMethodDebug("IODLinkSource","DescribeLinkTarget");
  1064.  
  1065.     LinkInfo *linkInfo = kODNULL;
  1066.     ODBoolean isLocal = kODFalse;
  1067.  
  1068.     // Out parameter
  1069.     *ConnData = kODNULL;
  1070.  
  1071.     //---<1>
  1072.     if (_fState == IODLinkSource_EMPTY)
  1073.     {
  1074.       ODSetSOMException(ev, kODErrLinkSourceIsEmpty);
  1075.       return;
  1076.     }
  1077.  
  1078.     //---<2>
  1079.     _fMutex->Acquire(ev);
  1080.     if (ODGetSOMException(ev) != kODNoError)
  1081.     {
  1082.       return;
  1083.     }
  1084.  
  1085.     //---<3>
  1086.     if (_fLocalLinkInfos->GetValue(&connID, &linkInfo) != kODTrue)
  1087.     {
  1088.       if (_fRemoteLinkInfos->GetValue(&connID, &linkInfo) != kODTrue)
  1089.       {
  1090.         ODSetSOMException(ev, kODErrInvalidTargetID);
  1091.         _fMutex->Release(ev);
  1092.         return;
  1093.       }
  1094.     }
  1095.     else
  1096.     {
  1097.       isLocal = kODTrue;
  1098.     }
  1099.  
  1100.     TRY
  1101.  
  1102.       //---<4>
  1103.       *ConnData = new ODLinkConnectionData;
  1104.       THROW_IF_NULL(*ConnData);
  1105.  
  1106.       if (isLocal)
  1107.       {
  1108.         (**ConnData).HostName = CopyITextStruct(&_fSrcConnData.HostName);
  1109.         (**ConnData).DocumentName = CopyITextStruct(&_fSrcConnData.DocumentName);
  1110.         (**ConnData).LinkDesc = CopyITextStruct(&linkInfo->trgtPartDesc.LinkDesc);
  1111.       }
  1112.       else
  1113.       {
  1114.         CopyPartDescription(**ConnData, linkInfo->trgtPartDesc);
  1115.       }
  1116.  
  1117.       _fMutex->Release(ev);
  1118.  
  1119.     CATCH_ALL
  1120.  
  1121.       //---<5>
  1122.       _fMutex->Release(ev);
  1123.  
  1124.       if (*ConnData != kODNULL)
  1125.       {
  1126.         CleanupPartDescription(**ConnData);
  1127.         delete *ConnData;
  1128.         *ConnData = kODNULL;
  1129.       }
  1130.  
  1131.       SET_SOM_EV;
  1132.  
  1133.     ENDTRY
  1134. }
  1135.  
  1136. /*
  1137.  *=============================================================================
  1138.  * Called by source Part to obtain the list of LinkTarget
  1139.  *   connection ID's in the LinkSource.
  1140.  *
  1141.  * <1>  Make sure current state is not EMPTY.
  1142.  * <2>  Acquire fMutex before accessing fLinkInfos.
  1143.  * <3>  Allocate memory for trgtIDs.
  1144.  * <4>  Retrieve all connection ID's from fLinkInfos and add them to trgtIDs.
  1145.  *      Release fMutex and return.
  1146.  * <5>  An exception is caught.
  1147.  *      Release fMutex.
  1148.  *      Cleanup trgtIDs.
  1149.  *      Set SOM exception and return.
  1150.  *=============================================================================
  1151.  */
  1152. SOM_Scope void  SOMLINK GetLinkConnections(IODLinkSource *somSelf,
  1153.                                             Environment *ev,
  1154.                                            _IDL_SEQUENCE_unsigned_long* connIDs)
  1155. {
  1156.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  1157.     IODLinkSourceMethodDebug("IODLinkSource","GetLinkTargets");
  1158.  
  1159.     ODLinkConnectionID id;
  1160.     LinkInfo*       linkInfo = kODNULL;
  1161.  
  1162.  
  1163.     //---<1>
  1164.     if (_fState == IODLinkSource_EMPTY)
  1165.     {
  1166.       ODSetSOMException(ev, kODErrLinkSourceIsEmpty);
  1167.       return;
  1168.     }
  1169.  
  1170.     //---<2>
  1171.     _fMutex->Acquire(ev);
  1172.     if (ODGetSOMException(ev) != kODNoError)
  1173.     {
  1174.       return;
  1175.     }
  1176.  
  1177.     TRY
  1178.  
  1179.       //---<3>
  1180.       (connIDs) -> _maximum = _fLocalLinkInfos->Count() + _fRemoteLinkInfos->Count();
  1181.       (connIDs) -> _length = 0;
  1182.       (connIDs) -> _buffer = (ODLinkConnectionID*) SOMMalloc(sizeof(ODLinkConnectionID) * (connIDs) -> _maximum);
  1183.  
  1184.       //---<4>
  1185.       OpenHashTableIterator lInfos(_fLocalLinkInfos);
  1186.       for (lInfos.First(&id, &linkInfo);
  1187.            lInfos.IsNotComplete();
  1188.            lInfos.Next(&id, &linkInfo))
  1189.       {
  1190.         (connIDs) -> _buffer[((connIDs)->_length)++] = id;
  1191.       }
  1192.  
  1193.       OpenHashTableIterator rInfos(_fRemoteLinkInfos);
  1194.       for (rInfos.First(&id, &linkInfo);
  1195.            rInfos.IsNotComplete();
  1196.            rInfos.Next(&id, &linkInfo))
  1197.       {
  1198.         (connIDs) -> _buffer[((connIDs)->_length)++] = id;
  1199.       }
  1200.  
  1201.       _fMutex->Release(ev);
  1202.  
  1203.     CATCH_ALL
  1204.  
  1205.       //---<5>
  1206.       _fMutex->Release(ev);
  1207.  
  1208.     SET_SOM_EV;
  1209.  
  1210.     ENDTRY
  1211. }
  1212.  
  1213. /*
  1214.  *=============================================================================
  1215.  * Called by Part after creation to initialize the mode of tracking
  1216.  *   LinkTargets.
  1217.  * By default LinkSource only tracks local or registered LinkTargets.
  1218.  *
  1219.  * <1>  Make sure current state is not CONNECTED.
  1220.  *      Once it is connected fTrackTrgts can not be changed.
  1221.  * <2>  Save the call back mode.
  1222.  *=============================================================================
  1223.  */
  1224.  
  1225. SOM_Scope void
  1226. SOMLINK InitCallBackMode(IODLinkSource *somSelf,
  1227.                          Environment *ev,
  1228.                          ODBoolean trackTrgts)
  1229. {
  1230.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  1231.     IODLinkSourceMethodDebug("IODLinkSource","InitCallBackMode");
  1232.  
  1233.     //---<1>
  1234.     if (_fState == IODLinkSource_CONNECTED)
  1235.     {
  1236.       ODSetSOMException(ev, kODErrLinkSourceConnected);
  1237.       return;
  1238.     }
  1239.  
  1240.     //---<2>
  1241.     _fTrackTrgts = trackTrgts;
  1242. }
  1243.  
  1244. /*
  1245.  *=============================================================================
  1246.  * Called by source Part to break the link with the given LinkTarget.
  1247.  *
  1248.  * <1>  Make sure current state is not EMPTY.
  1249.  * <2>  Acquire fMutex before accessing fLinkInfos.
  1250.  * <3>  Retrieve linkInfo associated with trgtID from fLinkInfos.
  1251.  *      Remove linkInfo from fLinkInfos if found.
  1252.  * <4>  Release fMutex.
  1253.  * <5>  Inform LinkTarget that its link is broken (oneway message).
  1254.  * <6>  Delete linkInfo.
  1255.  *=============================================================================
  1256.  */
  1257.  
  1258. SOM_Scope void
  1259. SOMLINK BreakLinkConnection(IODLinkSource *somSelf,
  1260.                          Environment *ev,
  1261.                          ODLinkConnectionID connID)
  1262. {
  1263.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  1264.     IODLinkSourceMethodDebug("IODLinkSource","RemoveLinkTarget");
  1265.  
  1266.     ODBoolean isLocal = kODTrue;
  1267.     LinkInfo *linkInfo = kODNULL;
  1268.  
  1269.     //---<1>
  1270.     if (_fState == IODLinkSource_EMPTY)
  1271.     {
  1272.       ODSetSOMException(ev, kODErrLinkSourceIsEmpty);
  1273.       return;
  1274.     }
  1275.  
  1276.     //---<2>
  1277.     _fMutex->Acquire(ev);
  1278.     if (ODGetSOMException(ev) != kODNoError)
  1279.     {
  1280.       return;
  1281.     }
  1282.  
  1283.     //---<3>
  1284.     if (_fLocalLinkInfos->GetValue(&connID, &linkInfo) != kODTrue)
  1285.     {
  1286.       if (_fRemoteLinkInfos->GetValue(&connID, &linkInfo) != kODTrue)
  1287.       {
  1288.         ODSetSOMException(ev, kODErrInvalidTargetID);
  1289.         _fMutex->Release(ev);
  1290.         return;
  1291.       }
  1292.       else
  1293.       {
  1294.         _fRemoteLinkInfos->RemoveEntry(&connID);
  1295.         isLocal = kODFalse;
  1296.       }
  1297.     }
  1298.     else _fLocalLinkInfos->RemoveEntry(&connID);
  1299.  
  1300.     //----<4>
  1301.     _fMutex->Release(ev);
  1302.  
  1303.     //---<5>
  1304.     if (isLocal)
  1305.     {
  1306.       linkInfo->linkTrgt->Release(ev);
  1307.     }
  1308.     linkInfo->linkTrgt->RemoveLink(ev);
  1309.  
  1310.     //---<6>
  1311.     CleanupPartDescription(linkInfo->trgtPartDesc);
  1312.     delete linkInfo;
  1313. }
  1314.  
  1315. /*
  1316.  *=============================================================================
  1317.  * Called by source Part to get its commentary.
  1318.  *
  1319.  * <1>  Make sure current state is not EMPTY.
  1320.  * <2>  Acquire fMutex before accessing fSrcConnData.
  1321.  * <3>  Copy commentary.
  1322.  * <4>  Release fMutex.
  1323.  *=============================================================================
  1324.  */
  1325. SOM_Scope void  SOMLINK GetDescription(IODLinkSource *somSelf,
  1326.                                         Environment *ev,
  1327.                                         ODLinkDescription* desc)
  1328. {
  1329.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  1330.     IODLinkSourceMethodDebug("IODLinkSource","SetSourcePartCommentary");
  1331.  
  1332.  
  1333.     //---<1>
  1334.     if (_fState == IODLinkSource_EMPTY)
  1335.     {
  1336.       ODSetSOMException(ev, kODErrLinkSourceIsEmpty);
  1337.       return;
  1338.     }
  1339.  
  1340.     //---<2>
  1341.     _fMutex->Acquire(ev);
  1342.     if (ODGetSOMException(ev) != kODNoError)
  1343.     {
  1344.       return;
  1345.     }
  1346.  
  1347.     //---<3>
  1348.  
  1349.     //---<4>
  1350.     *desc = CopyITextStruct(&_fSrcConnData.LinkDesc);
  1351.  
  1352.     //---<5>
  1353.     _fMutex->Release(ev);
  1354. }
  1355.  
  1356. /*
  1357.  *=============================================================================
  1358.  * Called by source Part to set its commentary.
  1359.  *
  1360.  * <1>  Make sure current state is not EMPTY.
  1361.  * <2>  Acquire fMutex before accessing fSrcConnData.
  1362.  * <3>  Copy commentary.
  1363.  * <4>  Save new commentary.
  1364.  * <5>  Release fMutex.
  1365.  *=============================================================================
  1366.  */
  1367.  
  1368. SOM_Scope void
  1369. SOMLINK SetDescription(IODLinkSource *somSelf,
  1370.                        Environment *ev,
  1371.                        ODLinkDescription* desc)
  1372. {
  1373.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  1374.     IODLinkSourceMethodDebug("IODLinkSource","SetSourcePartCommentary");
  1375.  
  1376.     //---<1>
  1377.     if (_fState == IODLinkSource_EMPTY)
  1378.     {
  1379.       ODSetSOMException(ev, kODErrLinkSourceIsEmpty);
  1380.       return;
  1381.     }
  1382.  
  1383.     //---<2>
  1384.     _fMutex->Acquire(ev);
  1385.     if (ODGetSOMException(ev) != kODNoError)
  1386.     {
  1387.       return;
  1388.     }
  1389.  
  1390.     //---<3>
  1391.        DisposeITextStruct(_fSrcConnData.LinkDesc);
  1392.  
  1393.     //---<4>
  1394.     _fSrcConnData.LinkDesc = CopyITextStruct(desc);
  1395.  
  1396.     //---<5>
  1397.     _fMutex->Release(ev);
  1398. }
  1399.  
  1400. /*
  1401.  *=============================================================================
  1402.  * called:
  1403.  * (1) when a persistent linkspec is made from a linksource
  1404.  * (2) when a linktarget is copied together with its
  1405.  * linksource and the linktarget needs to get the
  1406.  * new linkinfo for the copied linksource
  1407.  *
  1408.  * (1) return the instance variables _fLinkID and _fASName
  1409.  *=============================================================================
  1410.  */
  1411.  
  1412. SOM_Scope void
  1413. SOMLINK GetPersistentLinkInfo(IODLinkSource *somSelf,
  1414.                               Environment *ev,
  1415.                              ODLinkID *linkID,
  1416.                               ODISOStr *ASName)
  1417.  
  1418. {
  1419.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  1420.     IODLinkSourceMethodDebug("IODLinkSource","GetPersistentLinkInfo");
  1421.  
  1422.     *linkID = _fLinkID;
  1423.     *ASName = ODISOStrFromCStr(_fASName);
  1424. }
  1425.  
  1426. /*
  1427.  *=============================================================================
  1428.  * Called in Draft::CreateLinkSource to initialize the LinkSource after
  1429.  *    it is created.
  1430.  *
  1431.  * <1>  Make sure current state is EMPTY.
  1432.  * <2>  Create fMutex.
  1433.  * <3>  Create and initialize the hashtables to store the local and remote
  1434.  *      link infos.
  1435.  * <4>  Save the input hostName and docName into fSrcConnData.
  1436.  *      Set the comm field of fSrcConnData to NULL for now.
  1437.  * <5>  Init BaseLinkSource.
  1438.  * <6>  Set the current state to INITED.
  1439.  *      Save the flinkID as 0 -- will be set at Complete.
  1440.  *      Set fIDCounter to 0.
  1441.  *      Set fTrackTrgts to false.
  1442.  *      Set fLockState to UNLOCKED.
  1443.  * <7>  An exception is caught.
  1444.  *      Delete fMutex.
  1445.  *      Cleanup fSrcConnData.
  1446.  *      Delete fLocalInfos and fRemoteInfos.
  1447.  *      Set SOM exception and return.
  1448.  * <8>  Add properties and values in storage unit to externalize the following
  1449.  *      variables:
  1450.  *        ODLinkID           fLinkID;
  1451.  *        OpenHashTable*       fLocalLinkInfos;
  1452.  *        ODLinkConnectionData fSrcConnData;
  1453.  *        State              fState;
  1454.  *        ODBoolean          fTrackTrgts;
  1455.  *        ODULong            fVersion;
  1456.  *        ODLinkConnectionID    fIDCounter;
  1457.  *        OpenHashTable*       fRemoteLinkInfos;
  1458.  * <9>  Externalize so that complete will find the data
  1459.  *=============================================================================
  1460.  */
  1461.  
  1462. SOM_Scope void
  1463. SOMLINK InitILinkSource(IODLinkSource *somSelf,
  1464.                         Environment *ev,
  1465.                         ODStorageUnit* su,
  1466.                         ODPart* srcPart,
  1467.                         ODISOStr hostName,
  1468.                         ODISOStr docName)
  1469. {
  1470.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  1471.     IODLinkSourceMethodDebug("IODLinkSource","InitILinkSource");
  1472.  
  1473.     //---<1>
  1474.     if (_fState != IODLinkSource_EMPTY)
  1475.     {
  1476.       ODSetSOMException(ev, kODErrLinkSourceAlreadyInited);
  1477.       return;
  1478.     }
  1479.  
  1480.     TRY
  1481.  
  1482.       //---<2>
  1483.       _fMutex = new IODMutex;
  1484.       THROW_IF_NULL(_fMutex);
  1485.  
  1486.       //---<3>
  1487.       _fLocalLinkInfos = new OpenHashTable;
  1488.       THROW_IF_NULL(_fLocalLinkInfos);
  1489.       _fLocalLinkInfos->Initialize(kODInitialNumEntries,
  1490.                                    sizeof(ODLinkConnectionID),
  1491.                                    sizeof(LinkInfo*),
  1492.                                    kODFalse);
  1493.  
  1494.       _fRemoteLinkInfos = new OpenHashTable;
  1495.       THROW_IF_NULL(_fRemoteLinkInfos);
  1496.       _fRemoteLinkInfos->Initialize(kODInitialNumEntries,
  1497.                                     sizeof(ODLinkConnectionID),
  1498.                                     sizeof(LinkInfo*),
  1499.                                     kODFalse);
  1500.  
  1501.       //---<4>
  1502.       _fSrcConnData.HostName.format = kODIBMCodePageText;
  1503.       _fSrcConnData.HostName.text._buffer = kODNULL;
  1504.       SetITextCString(&_fSrcConnData.HostName, (char*)hostName);
  1505.       SetITextLangCode(&_fSrcConnData.HostName, 0);
  1506.       SetITextScriptCode(&_fSrcConnData.HostName, 0);
  1507.  
  1508.       _fSrcConnData.DocumentName.format = kODIBMCodePageText;
  1509.       _fSrcConnData.DocumentName.text._buffer = kODNULL;
  1510.       SetITextCString(&_fSrcConnData.DocumentName, (char*)docName);
  1511.       SetITextLangCode(&_fSrcConnData.DocumentName, 0);
  1512.       SetITextScriptCode(&_fSrcConnData.DocumentName, 0);
  1513.  
  1514.       _fSrcConnData.LinkDesc.format = kODIBMCodePageText;
  1515.       _fSrcConnData.LinkDesc.text._buffer = kODNULL;
  1516.       SetITextCString(&_fSrcConnData.LinkDesc, (char*)"");
  1517.       SetITextLangCode(&_fSrcConnData.LinkDesc, 0);
  1518.       SetITextScriptCode(&_fSrcConnData.LinkDesc, 0);
  1519.       //---<5>
  1520.       _InitBaseLinkSource(ev, su, srcPart);
  1521.  
  1522.       //---<6>
  1523.       _fState = IODLinkSource_INITED;
  1524.       _fLinkID = 0; /* linkID will not be known until Complete */
  1525.       _fIDCounter = 0;
  1526.       _fTrackTrgts = kODFalse;
  1527.       _fLockState = IODLinkSource_UNLOCKED;
  1528.  
  1529.     CATCH_ALL
  1530.  
  1531.       //---<7>
  1532.       if (_fMutex != kODNULL)
  1533.       {
  1534.         delete _fMutex;
  1535.         _fMutex = (IODMutex*)kODNULL;
  1536.       }
  1537.  
  1538.       CleanupPartDescription(_fSrcConnData);
  1539.  
  1540.       if (_fLocalLinkInfos != kODNULL)
  1541.       {
  1542.         delete _fLocalLinkInfos;
  1543.         _fLocalLinkInfos = kODNULL;
  1544.       }
  1545.  
  1546.       if (_fRemoteLinkInfos != kODNULL)
  1547.       {
  1548.         delete _fRemoteLinkInfos;
  1549.         _fRemoteLinkInfos = kODNULL;
  1550.       }
  1551.  
  1552.       SET_SOM_EV;
  1553.  
  1554.     ENDTRY
  1555.  
  1556.     //---<8>
  1557.     ODSUAddPropValue(ev, su, kODPropLinkID, kODULong);
  1558.     ODSUAddPropValue(ev, su, kODPropLocalLinkInfos, kODHashTable);
  1559.     ODSUAddPropValue(ev, su, kODPropPartDescription, kODPartDescription);
  1560.     ODSUAddPropValue(ev, su, kODPropLinkSourceState, kODULong);
  1561.     ODSUAddPropValue(ev, su, kODPropLinkSourceTrackMode, kODBoolean);
  1562.  
  1563.     ODSUAddPropValue(ev, su, kODPropVersion, kODULong);
  1564.     ODSUAddPropValue(ev, su, kODPropIDCounter, kODULong);
  1565.     ODSUAddPropValue(ev, su, kODPropRemoteLinkInfos, kODHashTable);
  1566.  
  1567.     //---<9>
  1568.     somSelf->Externalize(ev);
  1569.  
  1570. }
  1571.  
  1572. /*
  1573.  *=============================================================================
  1574.  * Called in Draft::CreateLinkSource to initialize the LinkSource from
  1575.  *    a pre-existing storage unit.
  1576.  *
  1577.  * <1>  Make sure current state is EMPTY.
  1578. * <2>  ... moved to Complete
  1579.  * <3>  Init BaseLinkSource from storage.
  1580.  * <4>  Create a new fMutex.
  1581.  * <5>  Internalize the following variable from the given SU:
  1582.  *        ODLinkID           fLinkID;
  1583.  * <6)  Return fLinkID
  1584.  * XXXXX Should catch exception in the future
  1585.  *=============================================================================
  1586.  */
  1587.  
  1588. SOM_Scope ODLinkID
  1589. SOMLINK InitILinkSourceFromStorage(IODLinkSource *somSelf,
  1590.                                    Environment *ev,
  1591.                                    ODStorageUnit* su)
  1592. {
  1593.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  1594.     IODLinkSourceMethodDebug("IODLinkSource","InitILinkSourceFromStorage");
  1595.  
  1596.     //---<1>
  1597.     if (_fState != IODLinkSource_EMPTY)
  1598.     {
  1599.       ODSetSOMException(ev, kODErrLinkSourceAlreadyInited);
  1600.       return 0;
  1601.     }
  1602.  
  1603.     //---<2>
  1604.     _InitBaseLinkSourceFromStorage(ev, su);
  1605.  
  1606.     //---<3>
  1607.    // ..  moved to Complete
  1608.  
  1609.     //---<4>
  1610.     _fMutex = new IODMutex;
  1611.  
  1612.     //---<5>
  1613.     _fLinkID = ODGetULongProp(ev,su, kODPropLinkID, kODULong);
  1614.  
  1615.     _fLocalLinkInfos = new OpenHashTable;
  1616.     _fLocalLinkInfos->Initialize(kODInitialNumEntries,
  1617.                                  sizeof(ODLinkConnectionID),
  1618.                                  sizeof(LinkInfo*),
  1619.                                  kODFalse);
  1620.  
  1621.     _fRemoteLinkInfos = new OpenHashTable;
  1622.     _fRemoteLinkInfos->Initialize(kODInitialNumEntries,
  1623.                                   sizeof(ODLinkConnectionID),
  1624.                                   sizeof(LinkInfo*),
  1625.                                   kODFalse);
  1626.  
  1627.     return _fLinkID;
  1628. }
  1629.  
  1630. /*
  1631.  *=============================================================================
  1632.  * called after InitILinkSource or InitILinkSourceFromStorage
  1633.  * linkIDIFNew will always be supplied (nonzero) for a brand new link source
  1634.  * linkIDIfNew will be supplied for a previously stored link source
  1635.  *     only if the draft determines that this link source is
  1636.  *     a copy in which case a new linkid will be supplied
  1637.  *
  1638.  * <1> If linkIDIFNew is nonzero, replace the linkID
  1639.  * <2>  Save asName
  1640.  * <3>  If auxState is non-null retrieve the following properties
  1641.  *        PropVersion, PropIDCounter and PropRemoteLinkInfos
  1642.  *      from auxState and write them to the given SU and to memory.
  1643.  * <4>  Save isLocked.
  1644.  * <5>  Internalize the following variables from the given SU:
  1645.  *        OpenHashTable*       fLocalLinkInfos;
  1646.  *        ODLinkConnectionData fSrcConnData;
  1647.  *        State              fState;
  1648.  *        ODBoolean          fTrackTrgts;
  1649.  *=============================================================================
  1650.  */
  1651.  
  1652. SOM_Scope void
  1653. SOMLINK CompleteInitILinkSource(IODLinkSource *somSelf,
  1654.                                    Environment *ev,
  1655.                                    ODStorageUnit* su,
  1656.                                    ODLinkID linkIDIfNew,
  1657.                                    IODAuxiliaryState* auxState,
  1658.                                    ODBoolean isLocked,
  1659.                                    ODISOStr ASName)
  1660. {
  1661.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  1662.     IODLinkSourceMethodDebug("IODLinkSource","CompleteInitILinkSource");
  1663.  
  1664. /* eventually add a state and check that not fully init until complete called */
  1665.  
  1666.     // 1.
  1667.     if (linkIDIfNew != (ODLinkID)0)
  1668.       {
  1669.         _fLinkID = linkIDIfNew;
  1670.       }
  1671.  
  1672.     // 2.
  1673.      _fASName = ODISOStrFromCStr(ASName);
  1674.  
  1675.     // 3.
  1676.     // eventually we should merge auxstates
  1677.     if (auxState != (IODAuxiliaryState*)kODNULL)
  1678.     {
  1679.       ODSetULongProp(ev,su, kODPropVersion, kODULong, auxState->version);
  1680.       ODSetULongProp(ev,su, kODPropIDCounter, kODULong, auxState->idCounter);
  1681.  
  1682.       ODSUForceFocus(ev, su, kODPropRemoteLinkInfos, kODHashTable);
  1683.       su->SetValue(ev, &(auxState->remoteLinkInfos));
  1684.       _fVersion = ODGetULongProp(ev,su, kODPropVersion, kODULong);
  1685.  
  1686.       _fIDCounter = ODGetULongProp(ev,su, kODPropIDCounter, kODULong);
  1687.       GetLinkInfosProp(ev,
  1688.                        su,
  1689.                        kODPropRemoteLinkInfos,
  1690.                        kODHashTable,
  1691.                        *_fRemoteLinkInfos);
  1692.     }
  1693.  
  1694.  
  1695.     // 4.
  1696.     if (isLocked) _fLockState = IODLinkSource_LOCKEDINAS;
  1697.  
  1698.     // 5.
  1699.     GetLinkInfosProp(ev,
  1700.                      su,
  1701.                      kODPropLocalLinkInfos,
  1702.                      kODHashTable,
  1703.                      *_fLocalLinkInfos);
  1704.  
  1705.     GetPartDescriptionProp(ev,
  1706.                            su,
  1707.                            kODPropPartDescription,
  1708.                            kODPartDescription,
  1709.                            _fSrcConnData);
  1710.  
  1711.     _fState = ODGetULongProp(ev,su, kODPropLinkSourceState, kODULong);
  1712.  
  1713.     _fTrackTrgts = ODGetBooleanProp(ev,su,
  1714.                                     kODPropLinkSourceTrackMode,
  1715.                                     kODBoolean);
  1716.  
  1717.  
  1718. }
  1719.  
  1720. /*
  1721.  *=============================================================================
  1722.  * <1>  Retrieve the SU of the LinkSource.
  1723.  * <2>  Retrieve the following properties
  1724.  *        PropVersion, PropIDCounter and PropRemoteLinkInfos
  1725.  *      from the LinkSource and write them into its SU.
  1726.  * <3>  Retrieve the following properties
  1727.  *        PropVersion, PropIDCounter and PropRemoteLinkInfos
  1728.  *      from the SU of the LinkSource and save them in auxState.
  1729.  *=============================================================================
  1730.  */
  1731.  
  1732. SOM_Scope void
  1733. SOMLINK GetAuxState(IODLinkSource *somSelf,
  1734.                     Environment *ev,
  1735.                     IODAuxiliaryState** auxState)
  1736. {
  1737.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  1738.     IODLinkSourceMethodDebug("IODLinkSource","GetAuxState");
  1739.  
  1740.     //---<1>
  1741.     ODStorageUnit *su = _GetStorageUnit(ev);
  1742.  
  1743.     //---<2>
  1744.     ODSetULongProp(ev,su, kODPropVersion, kODULong, _fVersion);
  1745.     ODSetULongProp(ev,su, kODPropIDCounter, kODULong, _fIDCounter);
  1746.     SetLinkInfosProp(ev,
  1747.                      su,
  1748.                      kODPropRemoteLinkInfos,
  1749.                      kODHashTable,
  1750.                      *_fRemoteLinkInfos);
  1751.  
  1752.     //---<3>
  1753.     (*auxState)->version = ODGetULongProp(ev,su, kODPropVersion, kODULong);
  1754.     (*auxState)->idCounter = ODGetULongProp(ev,su, kODPropIDCounter, kODULong);
  1755.     if (ODSUExistsThenFocus(ev, su, kODPropRemoteLinkInfos, kODHashTable))
  1756.     {
  1757.       long size = su->GetSize(ev);
  1758.       (*auxState)->remoteLinkInfos = CreateEmptyByteArrayStruct(size);
  1759.       (*auxState)->remoteLinkInfos._length = size;
  1760.       su->GetValue(ev,size, &((*auxState)->remoteLinkInfos));
  1761.     }
  1762.    else{
  1763.       (*auxState)->remoteLinkInfos = CreateEmptyByteArrayStruct(0);
  1764.     }
  1765. }
  1766.  
  1767. /*
  1768.  *=============================================================================
  1769.  * <1>  Retrieve the SU of the LinkSource.
  1770.  * <2>  If auxState is non-null retrieve the following properties
  1771.  *        PropVersion, PropIDCounter and PropRemoteLinkInfos
  1772.  *      from auxState and write them into the SU of the LinkSource.
  1773.  * <3>  Delete old fRemoteLinkInfos hashtable.
  1774.  * <4>  Reinternalize
  1775.  *        IODULong        fVersion;
  1776.  *        ODLinkConnectionID fIDCounter;
  1777.  *        OpenHashTable*    fRemoteLinkInfos;
  1778.  *=============================================================================
  1779.  */
  1780.  
  1781. SOM_Scope void
  1782. SOMLINK ResetAuxState(IODLinkSource *somSelf,
  1783.                       Environment *ev,
  1784.                       IODAuxiliaryState* auxState)
  1785. {
  1786.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  1787.     IODLinkSourceMethodDebug("IODLinkSource","ResetAuxState");
  1788.  
  1789.     //---<1>
  1790.     ODStorageUnit *su = _GetStorageUnit(ev);
  1791.  
  1792.     if (auxState != (IODAuxiliaryState*)kODNULL)
  1793.     {
  1794.       //---<2>
  1795.       ODSetULongProp(ev,su, kODPropVersion, kODULong, auxState->version);
  1796.       ODSetULongProp(ev,su, kODPropIDCounter, kODULong, auxState->idCounter);
  1797.  
  1798.       ODSUForceFocus(ev, su, kODPropRemoteLinkInfos, kODHashTable);
  1799.       su->SetValue(ev, &(auxState->remoteLinkInfos));
  1800.  
  1801.       //--<3>
  1802.       ODLinkConnectionID id;
  1803.       LinkInfo*       linkInfo;
  1804.       OpenHashTableIterator rInfos(_fRemoteLinkInfos);
  1805.       for (rInfos.First(&id, &linkInfo);
  1806.            rInfos.IsNotComplete();
  1807.            rInfos.Next(&id, &linkInfo))
  1808.       {
  1809.         CleanupPartDescription(linkInfo->trgtPartDesc);
  1810.         if (linkInfo->linkTrgt != kODNULL)
  1811.         {
  1812.           if (((SOMDObject*)(linkInfo->linkTrgt))->is_proxy(ev))
  1813.           {
  1814.             SOMD_ObjectMgr->somdReleaseObject(ev, linkInfo->linkTrgt);
  1815.           }
  1816.         }
  1817.         delete linkInfo;
  1818.       }
  1819.       delete _fRemoteLinkInfos;
  1820.       _fRemoteLinkInfos = kODNULL;
  1821.  
  1822.       //---<4>
  1823.       _fVersion = ODGetULongProp(ev,su, kODPropVersion, kODULong);
  1824.       _fIDCounter = ODGetULongProp(ev,su, kODPropIDCounter, kODULong);
  1825.  
  1826.       _fRemoteLinkInfos = new OpenHashTable;
  1827.       _fRemoteLinkInfos->Initialize(kODInitialNumEntries,
  1828.                                     sizeof(ODLinkConnectionID),
  1829.                                     sizeof(LinkInfo*),
  1830.                                     kODFalse);
  1831.       GetLinkInfosProp(ev,
  1832.                        su,
  1833.                        kODPropRemoteLinkInfos,
  1834.                        kODHashTable,
  1835.                        *_fRemoteLinkInfos);
  1836.     }
  1837. }
  1838.  
  1839.  
  1840.     // eventually this method will be moved to ODLinkSource and
  1841.     // will become public.
  1842.     // This writes out a linkspec giving rights to link to this linksource
  1843.  
  1844. /*
  1845.  * eventually this method will be moved to ODLinkSource and
  1846.  * will become public.
  1847.  * This writes out a linkspec giving rights to link to this linksource
  1848.  */
  1849.  
  1850. SOM_Scope void
  1851. SOMLINK WritePersistentLinkSpec(IODLinkSource *somSelf,
  1852.                                    Environment *ev,
  1853.                                   ODStorageUnit* su)
  1854.  
  1855. // Write version, Persistent, LinkID, ASName
  1856.  
  1857. {
  1858.     const kODULongLen = 4 ;
  1859.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  1860.     IODLinkSourceMethodDebug("IODLinkSource","WritePersistentLinkSpec");
  1861.     ODULong version = kODOS2;
  1862.       ODULong subVersion;
  1863.       ODLinkID linkID;
  1864.       ODISOStr asName;
  1865.       ODStorageUnitID sourcePartSUID;
  1866.       TRY
  1867.         StorageUnitSetValue(su, ev, sizeof(ODULong), (ODValue) &version);
  1868.         subVersion = ODLinkSpec_PERSISTENT_LINKSPEC_VALUE;
  1869.         StorageUnitSetValue(su, ev, sizeof(ODULong), (ODValue) &subVersion);
  1870.         linkID = _fLinkID;
  1871.         StorageUnitSetValue(su, ev, sizeof(ODLinkID), (ODValue) &linkID);
  1872.         asName = _fASName;
  1873.         ODULong strLength = strlen(asName) + 1;/* length of string + null terminator */
  1874.         StorageUnitSetValue(su, ev, kODULongLen, (ODValue)&strLength);
  1875.         StorageUnitSetValue(su,
  1876.                             ev,
  1877.                             strLength,
  1878.                             (ODValue)asName);
  1879.       CATCH_ALL
  1880.         su->Remove(ev);    //??????
  1881.         RERAISE;
  1882.       ENDTRY
  1883.  
  1884. }
  1885.  
  1886.  
  1887. /*
  1888.  *=============================================================================
  1889.  *=============================================================================
  1890.  */
  1891.  
  1892.  
  1893.  
  1894.  
  1895.  
  1896. SOM_Scope void
  1897. SOMLINK somInit(IODLinkSource *somSelf)
  1898. {
  1899.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  1900.     IODLinkSourceMethodDebug("IODLinkSource","somInit");
  1901.  
  1902.     IODLinkSource_parent_ODLinkSource_somInit(somSelf);
  1903.     IODLinkSource_parent_IODLinkTargetToLinkSource_somInit(somSelf);
  1904.  
  1905.     _fMutex = (IODMutex*)kODNULL;
  1906.     _fIDCounter = 0;
  1907.     _fLinkID = 0;
  1908.     _fLocalLinkInfos = (OpenHashTable*)kODNULL;
  1909.     _fRemoteLinkInfos = (OpenHashTable*)kODNULL;
  1910.     _fSrcConnData.LinkDesc.text._buffer = kODNULL;
  1911.     _fSrcConnData.DocumentName.text._buffer = kODNULL;
  1912.     _fSrcConnData.HostName.text._buffer = kODNULL;
  1913.     _fState = IODLinkSource_EMPTY;
  1914.     _fTrackTrgts = kODFalse;
  1915.     _fLockState = IODLinkSource_UNLOCKED;
  1916.     _fPID = _getpid();
  1917.     _fVersion = 0;
  1918.     #ifdef _PLATFORM_OS2_
  1919.       _fFirstWE = (LockWaitElement*) kODNULL;
  1920.       _fLastWE = (LockWaitElement*) kODNULL;
  1921.    #endif/* _PLATFORM_OS2_ */
  1922.  
  1923. }
  1924.  
  1925. /*
  1926.  *=============================================================================
  1927.  *=============================================================================
  1928.  */
  1929.  
  1930. SOM_Scope void
  1931. SOMLINK somUninit(IODLinkSource *somSelf)
  1932. {
  1933.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  1934.     IODLinkSourceMethodDebug("IODLinkSource","somUninit");
  1935.  
  1936.     IODLinkSource_parent_ODLinkSource_somUninit(somSelf);
  1937.     IODLinkSource_parent_IODLinkTargetToLinkSource_somUninit(somSelf);
  1938. }
  1939.  
  1940. /*
  1941.  *=============================================================================
  1942.  * Called in LinkService::EstablishLinkFromTSpec (which is called
  1943.  *   in LinkSpec::EstablishLink) or
  1944.  *   PersistentLinkSpec::EstablishLink to add a new LinkTarget to the
  1945.  *   LinkSource.
  1946.  *
  1947.  * <1>  Make sure current state is note EMPTY.
  1948.  * <2>  Determine the locality of the LinkTarget
  1949.  * <3>  For case where LinkTargets are being tracked or the LinkTarget is
  1950.  *      local.
  1951.  * <4>  Acquire fMutex before accessing fLinkInfos.
  1952.  * <5>  Allocate memory for a new linkInfo.
  1953.  * <6>  Fill in each field of linkInfo.
  1954.  * <7>  Add linkInfo to fLinkInfos.
  1955.  * <8>  Fill in out parameters.
  1956.  *      Set current state to CONNECTED.
  1957.  *      Release fMutex and return.
  1958.  * <9>  An exception is caught.
  1959.  *      Release fMutex.
  1960.  *      Cleanup linkInfo.
  1961.  *      Set SOM exception and return.
  1962.  * <10> For case where LinkTargets are not tracked and the LinkTarget is
  1963.  *      remote just fill in out parameters.
  1964.  *=============================================================================
  1965.  */
  1966.  
  1967. SOM_Scope void
  1968. SOMLINK AddLinkTarget(IODLinkSource *somSelf,
  1969.                       Environment *ev,
  1970.                       ODLinkID linkid,
  1971.                       ODULong pid,
  1972.                       ODLinkConnectionData* trgtPartDesc,
  1973.                       IODLinkTarget* linkTrgt,
  1974.                      ODStorageUnitID* sourceSUID,
  1975.                       ODLinkConnectionID* trgtID,
  1976.                       ODBoolean* isLocal,
  1977.                       ODBoolean* trackTrgt)
  1978. {
  1979.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  1980.     IODLinkSourceMethodDebug("IODLinkSource","AddLinkTarget");
  1981.     LinkInfo *linkInfo = kODNULL;
  1982.  
  1983.     //---<1>
  1984.     if (_fState == IODLinkSource_EMPTY)
  1985.     {
  1986.       ODSetSOMException(ev, kODErrLinkSourceIsEmpty);
  1987.       return;
  1988.     }
  1989.  
  1990.     //---<2>
  1991.     //*isLocal = ODISOStrEqual(_fSrcPartDesc.docName, trgtPartDesc->docName);
  1992.     if ((_fPID == pid)
  1993.         &&
  1994.         (strcmp(GetCStringFromIText(&_fSrcConnData.HostName),
  1995.                 GetCStringFromIText(&trgtPartDesc->HostName))==0))
  1996.     {
  1997.  
  1998.       *isLocal = kODTrue;
  1999.     }
  2000.     else
  2001.     {
  2002.       *isLocal = kODFalse;
  2003.     }
  2004.  
  2005.     //---<3>
  2006.     if (_fTrackTrgts || *isLocal) {
  2007.       TRY
  2008.  
  2009.         //---<4>
  2010.         _fMutex->Acquire(ev);
  2011.         if (ODGetSOMException(ev) != kODNoError)
  2012.         {
  2013.           return;
  2014.         }
  2015.  
  2016.         //---<5>
  2017.         linkInfo = new LinkInfo;
  2018.         THROW_IF_NULL(linkInfo);
  2019.  
  2020.         //---<6>
  2021.         CopyPartDescription(linkInfo->trgtPartDesc, *trgtPartDesc);
  2022.  
  2023.         linkInfo->trgtID = ++_fIDCounter;
  2024.         linkInfo->linkTrgt = linkTrgt;
  2025.         linkInfo->isAlive = kODTrue;
  2026.         linkInfo->isRegistered = kODFalse;
  2027.  
  2028.         //---<7>
  2029.         if (*isLocal)
  2030.         {
  2031.           linkTrgt->Acquire(ev);
  2032.           _fLocalLinkInfos->ReplaceEntry(&(linkInfo->trgtID), &linkInfo);
  2033.         }
  2034.         else
  2035.         {
  2036.           _fRemoteLinkInfos->ReplaceEntry(&(linkInfo->trgtID), &linkInfo);
  2037.         }
  2038.  
  2039.         //---<8>
  2040.         *trgtID = linkInfo->trgtID;
  2041.         *trackTrgt = kODTrue;
  2042.        *sourceSUID = somSelf->GetID(ev);
  2043.         _fState = IODLinkSource_CONNECTED;
  2044.         _fMutex->Release(ev);
  2045.  
  2046.       CATCH_ALL
  2047.  
  2048.         //---<9>
  2049.         _fMutex->Release(ev);
  2050.  
  2051.         if (linkInfo != kODNULL)
  2052.         {
  2053.           CleanupPartDescription(linkInfo->trgtPartDesc);
  2054.           delete linkInfo;
  2055.         }
  2056.  
  2057.         SET_SOM_EV;
  2058.  
  2059.       ENDTRY
  2060.     }
  2061.     else
  2062.     {
  2063.       //---<10>
  2064.       *trgtID = 0;
  2065.       *trackTrgt = kODFalse;
  2066.  
  2067.       _fState = IODLinkSource_CONNECTED;
  2068.     }
  2069.  
  2070. }
  2071.  
  2072. /*
  2073.  *=============================================================================
  2074.  * <1>  Make sure this object is not already cloned in the toSU.
  2075.  * <2>  Invoke parent's CloneInto method.
  2076.  * <3>  Clone the following variables into the toSU:
  2077.  *        ODLinkConnectionID    fIDCounter;
  2078.  *        ODLinkID           fLinkID;
  2079.  *        OpenHashTable        *fLocalLinkInfos;
  2080.  *        OpenHashTable        *fRemoteLinkInfos;
  2081.  *        ODLinkConnectionData fSrcConnData;
  2082.  *        State              fState;
  2083.  *        ODBoolean          fTrackTrgts;
  2084.  *=============================================================================
  2085.  */
  2086.  
  2087. SOM_Scope void
  2088. SOMLINK CloneInto(IODLinkSource *somSelf,
  2089.                   Environment *ev,
  2090.                   ODDraftKey draftKey,
  2091.                   ODStorageUnit* toSU,
  2092.                   ODFrame* scopeFrame)
  2093. {
  2094.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  2095.     IODLinkSourceMethodDebug("IODLinkSource","CloneInto");
  2096.  
  2097.     ODDraft *draft = _GetStorageUnit(ev)->GetDraft(ev);
  2098.  
  2099.     //---<1>
  2100.     if (toSU->Exists(ev, kODPropIDCounter, kODULong, 0)) return;
  2101.  
  2102.     //---<2>
  2103.     IODLinkSource_parent_ODLinkSource_CloneInto(somSelf,
  2104.                                                 ev,
  2105.                                                 draftKey,
  2106.                                                 toSU,
  2107.                                                 scopeFrame);
  2108.  
  2109.     //---<3>
  2110.     ODSetULongProp(ev,toSU, kODPropIDCounter, kODULong, _fIDCounter);
  2111.  
  2112.     ODSetULongProp(ev,toSU, kODPropLinkID, kODULong, _fLinkID);
  2113.  
  2114.     CloneLinkInfosProp(ev,
  2115.                        toSU,
  2116.                        kODPropLocalLinkInfos,
  2117.                        kODHashTable,
  2118.                        draft,
  2119.                        draftKey,
  2120.                        scopeFrame,
  2121.                        *_fLocalLinkInfos);
  2122.  
  2123.     CloneLinkInfosProp(ev,
  2124.                        toSU,
  2125.                        kODPropRemoteLinkInfos,
  2126.                        kODHashTable,
  2127.                        draft,
  2128.                        draftKey,
  2129.                        scopeFrame,
  2130.                        *_fRemoteLinkInfos);
  2131.  
  2132.     SetPartDescriptionProp(ev,
  2133.                            toSU,
  2134.                            kODPropPartDescription,
  2135.                            kODPartDescription,
  2136.                            _fSrcConnData);
  2137.  
  2138.     ODSetULongProp(ev,toSU, kODPropLinkSourceState, kODULong, _fState);
  2139.  
  2140.     ODSetBooleanProp(ev,toSU,
  2141.                      kODPropLinkSourceTrackMode,
  2142.                      kODBoolean,
  2143.                      _fTrackTrgts);
  2144. }
  2145.  
  2146. /*
  2147.  *=============================================================================
  2148.  * <1>  Invoke parent's Externalize method.
  2149.  * <2>  Externalize the following variables to the storage unit:
  2150.  *        ODLinkConnectionID    fIDCounter;
  2151.  *        ODLinkID           fLinkID;
  2152.  *        OpenHashTable        *fLocalLinkInfos;
  2153.  *        OpenHashTable        *fRemoteLinkInfos;
  2154.  *        ODLinkConnectionData fSrcConnData;
  2155.  *        State              fState;
  2156.  *        ODBoolean          fTrackTrgts;
  2157.  *=============================================================================
  2158.  */
  2159.  
  2160. SOM_Scope void
  2161. SOMLINK Externalize(IODLinkSource *somSelf,
  2162.                     Environment *ev)
  2163. {
  2164.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  2165.     IODLinkSourceMethodDebug("IODLinkSource","Externalize");
  2166.  
  2167.     ODStorageUnit *su = _GetStorageUnit(ev);
  2168.  
  2169.     //---<1>
  2170.     IODLinkSource_parent_ODLinkSource_Externalize(somSelf, ev);
  2171.  
  2172.     //---<2>
  2173.     ODSetULongProp(ev,su, kODPropIDCounter, kODULong, _fIDCounter);
  2174.  
  2175.     ODSetULongProp(ev,su, kODPropLinkID, kODULong, _fLinkID);
  2176.  
  2177.     SetLinkInfosProp(ev,
  2178.                      su,
  2179.                      kODPropLocalLinkInfos,
  2180.                      kODHashTable,
  2181.                      *_fLocalLinkInfos);
  2182.  
  2183.     SetLinkInfosProp(ev,
  2184.                      su,
  2185.                      kODPropRemoteLinkInfos,
  2186.                      kODHashTable,
  2187.                      *_fRemoteLinkInfos);
  2188.  
  2189.     SetPartDescriptionProp(ev,
  2190.                            su,
  2191.                            kODPropPartDescription,
  2192.                            kODPartDescription,
  2193.                            _fSrcConnData);
  2194.  
  2195.     ODSetULongProp(ev,su, kODPropLinkSourceState, kODULong, _fState);
  2196.  
  2197.     ODSetBooleanProp(ev,su,
  2198.                      kODPropLinkSourceTrackMode,
  2199.                      kODBoolean,
  2200.                      _fTrackTrgts);
  2201. }
  2202.  
  2203. /*
  2204.  *=============================================================================
  2205.  *=============================================================================
  2206.  */
  2207.  
  2208. SOM_Scope ODUpdateID
  2209. SOMLINK ForwardGetUpdateID(IODLinkSource *somSelf,
  2210.                            Environment *ev,
  2211.                            ODLinkID linkID)
  2212. {
  2213.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  2214.     IODLinkSourceMethodDebug("IODLinkSource","ForwardGetUpdateID");
  2215.  
  2216.     return _GetUpdateID(ev);
  2217. }
  2218.  
  2219. /*
  2220.  *=============================================================================
  2221.  *=============================================================================
  2222.  */
  2223.  
  2224. SOM_Scope ODTime
  2225. SOMLINK ForwardGetChangeTime(IODLinkSource *somSelf,
  2226.                              Environment *ev,
  2227.                              ODLinkID linkID)
  2228. {
  2229.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  2230.     IODLinkSourceMethodDebug("IODLinkSource","ForwardGetChangeTime");
  2231.  
  2232.     return _GetChangeTime(ev);
  2233. }
  2234.  
  2235. /*
  2236.  *=============================================================================
  2237.  *=============================================================================
  2238.  */
  2239.  
  2240. SOM_Scope ODStorageUnit*
  2241. SOMLINK ForwardGetContentStorageUnit(IODLinkSource *somSelf,
  2242.                                      Environment *ev,
  2243.                                      ODLinkID linkID,
  2244.                                      ODLinkKey key)
  2245. {
  2246.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  2247.     IODLinkSourceMethodDebug("IODLinkSource","ForwardGetContentStorageUnit");
  2248.  
  2249.     return _GetContentStorageUnit(ev, key);
  2250. }
  2251.  
  2252. /*
  2253.  *=============================================================================
  2254.  *=============================================================================
  2255.  */
  2256.  
  2257. SOM_Scope ODBoolean
  2258. SOMLINK ForwardLock(IODLinkSource *somSelf,
  2259.                     Environment *ev,
  2260.                     ODLinkID linkID,
  2261.                     ODULong wait,
  2262.                     ODLinkKey* key)
  2263. {
  2264.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  2265.     IODLinkSourceMethodDebug("IODLinkSource","ForwardLock");
  2266.  
  2267. #ifdef _PLATFORM_OS2_
  2268.     return (WaitForLock(somSelf,
  2269.                         ev,
  2270.                         wait,
  2271.                         key,
  2272.                         &_fLockState,
  2273.                         _fMutex,
  2274.                         &_fFirstWE,
  2275.                         &_fLastWE));
  2276. #else
  2277.     if (_fLockState == IODLinkSource_UNLOCKED)
  2278.     {
  2279.       ODBoolean success =  _Lock(ev, wait, key);
  2280.       if(success)
  2281.       {
  2282.        _fLockState = IODLinkSource_LOCKED;
  2283.       }
  2284.       return (success);
  2285.     }
  2286.     else
  2287.     {
  2288.       return kODFalse;
  2289.     }
  2290. #endif
  2291. }
  2292.  
  2293. /*
  2294.  *=============================================================================
  2295.  *=============================================================================
  2296.  */
  2297.  
  2298. SOM_Scope ODBoolean
  2299. SOMLINK Lock(IODLinkSource *somSelf,
  2300.                     Environment *ev,
  2301.                     ODULong wait,
  2302.                     ODLinkKey* key)
  2303. {
  2304.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  2305.     IODLinkSourceMethodDebug("IODLinkSource","ForwardLock");
  2306.  
  2307. #ifdef _PLATFORM_OS2_
  2308.     return (WaitForLock(somSelf,
  2309.                         ev,
  2310.                         wait,
  2311.                         key,
  2312.                         &_fLockState,
  2313.                         _fMutex,
  2314.                         &_fFirstWE,
  2315.                         &_fLastWE));
  2316. #else
  2317.   return (IODLinkSource_parent_ODLinkSource_Lock(somSelf, ev, wait, key));
  2318. #endif
  2319. }
  2320.  
  2321. /*
  2322.  *=============================================================================
  2323.  *=============================================================================
  2324.  */
  2325.  
  2326. SOM_Scope void
  2327. SOMLINK ForwardUnlock(IODLinkSource *somSelf,
  2328.                       Environment *ev,
  2329.                       ODLinkID linkID,
  2330.                       ODLinkKey key,
  2331.                       ODBoolean isLocal)
  2332. {
  2333.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  2334.     IODLinkSourceMethodDebug("IODLinkSource","ForwardUnlock");
  2335.  
  2336.     switch (_fLockState)
  2337.     {
  2338.       case IODLinkSource_UNLOCKED:
  2339.         ODSetSOMException(ev, kODErrInvalidLinkKey);
  2340.         return;
  2341.  
  2342.       case IODLinkSource_LOCKED:
  2343.         _Unlock(ev, key);  /* on OS2 this will set fLockState */
  2344.        #ifndef _PLATFORM_OS2_
  2345.         _fLockState = IODLinkSource_UNLOCKED;
  2346.         #endif
  2347.         return;
  2348.  
  2349.       case IODLinkSource_LOCKEDINAS:
  2350.         if (isLocal)
  2351.         {
  2352.           ODSetSOMException(ev, kODErrInvalidLinkKey);
  2353.           return;
  2354.         }
  2355.         _fLockState = IODLinkSource_UNLOCKED;
  2356.         return;
  2357.     }
  2358. }
  2359.  
  2360. /*
  2361.  *=============================================================================
  2362.  *=============================================================================
  2363.  */
  2364.  
  2365. SOM_Scope ODLink*
  2366. SOMLINK GetLink(IODLinkSource *somSelf,
  2367.                 Environment *ev)
  2368. {
  2369.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  2370.     IODLinkSourceMethodDebug("IODLinkSource","GetLink");
  2371.  
  2372.     //---<1>
  2373.     return kODNULL;
  2374. }
  2375.  
  2376. /*
  2377.  *=============================================================================
  2378.  * <1>  Make sure the current state is not EMPTY.
  2379.  * <2>  Acquire fMutex before accessing fSrcConnData.
  2380.  * <3>  Allocate memory for the out parameter srcPartDesc.
  2381.  *      Copy the source part description to the out parameter srcPartDesc.
  2382.  *      Release fMutex and return.
  2383.  * <4>  An exception is caught.
  2384.  *      Release fMutex.
  2385.  *      Cleanup srcPartDesc.
  2386.  *      Set SOM exception and return.
  2387.  *=============================================================================
  2388.  */
  2389.  
  2390. SOM_Scope void
  2391. SOMLINK GetSourcePartDescription(IODLinkSource *somSelf,
  2392.                                  Environment *ev,
  2393.                                  ODLinkID linkID,
  2394.                                  ODLinkConnectionData** srcPartDesc)
  2395. {
  2396.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  2397.     IODLinkSourceMethodDebug("IODLinkSource","GetSourcePartDescription");
  2398.  
  2399.     // Out parameter
  2400.     *srcPartDesc = kODNULL;
  2401.  
  2402.     //---<1>
  2403.     if (_fState == IODLinkSource_EMPTY)
  2404.     {
  2405.       ODSetSOMException(ev, kODErrLinkSourceIsEmpty);
  2406.       return;
  2407.     }
  2408.  
  2409.     //---<2>
  2410.     _fMutex->Acquire(ev);
  2411.     if (ODGetSOMException(ev) != kODNoError)
  2412.     {
  2413.       return;
  2414.     }
  2415.  
  2416.     TRY
  2417.  
  2418.       //---<3>
  2419.       *srcPartDesc = new ODLinkConnectionData;
  2420.       THROW_IF_NULL(*srcPartDesc);
  2421.  
  2422.       CopyPartDescription(**srcPartDesc, _fSrcConnData);
  2423.       _fMutex->Release(ev);
  2424.  
  2425.     CATCH_ALL
  2426.  
  2427.       //---<4>
  2428.       _fMutex->Release(ev);
  2429.  
  2430.       if (*srcPartDesc != kODNULL)
  2431.       {
  2432.         CleanupPartDescription(**srcPartDesc);
  2433.         delete *srcPartDesc;
  2434.         *srcPartDesc = kODNULL;
  2435.       }
  2436.  
  2437.       SET_SOM_EV;
  2438.  
  2439.     ENDTRY
  2440. }
  2441.  
  2442.  
  2443. /*
  2444.  *=============================================================================
  2445.  * <1>  Make sure the current state is not EMPTY.
  2446.  * <2>  Acquire fMutex before accessing fSrcConnData.
  2447.  * <3>  Allocate memory for the out parameter srcPartDesc.
  2448.  *      Copy the source part description to the out parameter srcPartDesc.
  2449.  *      Release fMutex and return.
  2450.  * <4>  An exception is caught.
  2451.  *      Release fMutex.
  2452.  *      Cleanup srcPartDesc.
  2453.  *      Set SOM exception and return.
  2454.  *=============================================================================
  2455.  */
  2456.  
  2457. SOM_Scope void
  2458. SOMLINK GetConnectionData(IODLinkSource *somSelf,
  2459.                      Environment *ev,
  2460.                      ODLinkConnectionData** srcConnData)
  2461. {
  2462.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  2463.     IODLinkSourceMethodDebug("IODLinkSource","GetSourcePartDescription");
  2464.  
  2465.     // Out parameter
  2466.     *srcConnData = kODNULL;
  2467.  
  2468.     //---<1>
  2469.     if (_fState == IODLinkSource_EMPTY)
  2470.     {
  2471.       ODSetSOMException(ev, kODErrLinkSourceIsEmpty);
  2472.       return;
  2473.     }
  2474.  
  2475.     //---<2>
  2476.     _fMutex->Acquire(ev);
  2477.     if (ODGetSOMException(ev) != kODNoError)
  2478.     {
  2479.       return;
  2480.     }
  2481.  
  2482.     TRY
  2483.  
  2484.       //---<3>
  2485.       *srcConnData = new ODLinkConnectionData;
  2486.       THROW_IF_NULL(*srcConnData);
  2487.  
  2488.       CopyPartDescription(**srcConnData, _fSrcConnData);
  2489.       _fMutex->Release(ev);
  2490.  
  2491.     CATCH_ALL
  2492.  
  2493.       //---<4>
  2494.       _fMutex->Release(ev);
  2495.  
  2496.       if (*srcConnData != kODNULL)
  2497.       {
  2498.         CleanupPartDescription(**srcConnData);
  2499.         delete *srcConnData;
  2500.         *srcConnData = kODNULL;
  2501.       }
  2502.  
  2503.       SET_SOM_EV;
  2504.  
  2505.     ENDTRY
  2506. }
  2507.  
  2508. /*
  2509.  *=============================================================================
  2510.  * <1>  Make sure the current state is not EMPTY.
  2511.  * <2>  Acquire fMutex before accessing fLinkInfos.
  2512.  * <3>  Retrieve linkInfo associated with trgtID from fLinkInfos.
  2513.  * <4>  Set the isAlive field of linkInfo to false.
  2514.  *      Release fMutex.
  2515.  *=============================================================================
  2516.  */
  2517.  
  2518. SOM_Scope void
  2519. SOMLINK LinkTargetClosed(IODLinkSource *somSelf,
  2520.                          Environment *ev,
  2521.                          ODLinkID linkID,
  2522.                          ODLinkConnectionID trgtID,
  2523.                          ODBoolean isLocal)
  2524. {
  2525.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  2526.     IODLinkSourceMethodDebug("IODLinkSource","LinkTargetClosed");
  2527.  
  2528.     LinkInfo *linkInfo = kODNULL;
  2529.     OpenHashTable *linkInfos = isLocal ? _fLocalLinkInfos : _fRemoteLinkInfos;
  2530.  
  2531.     //---<1>
  2532.     if (_fState == IODLinkSource_EMPTY)
  2533.     {
  2534.       ODSetSOMException(ev, kODErrLinkSourceIsEmpty);
  2535.       return;
  2536.     }
  2537.  
  2538.     //---<2>
  2539.     _fMutex->Acquire(ev);
  2540.     if (ODGetSOMException(ev) != kODNoError)
  2541.     {
  2542.       return;
  2543.     }
  2544.  
  2545.     //---<3>
  2546.     if (linkInfos->GetValue(&trgtID, &linkInfo) != kODTrue)
  2547.     {
  2548.       ODSetSOMException(ev, kODErrInvalidTargetID);
  2549.       _fMutex->Release(ev);
  2550.       return;
  2551.     }
  2552.  
  2553.     //---<4>
  2554.     linkInfo->isAlive = kODFalse;
  2555.     _fMutex->Release(ev);
  2556. }
  2557.  
  2558. /*
  2559.  *=============================================================================
  2560.  * <1>  Make sure the current state is not EMPTY.
  2561.  * <2>  Acquire fMutex before accessing fLinkInfos.
  2562.  * <3>  Retrieve linkInfo associated with trgtID from fLinkInfos.
  2563.  * <4>  Remove linkInfo from fLinkInfos.
  2564.  *      Release fMutex.
  2565.  * <5>  Delete linkInfo.
  2566.  *=============================================================================
  2567.  */
  2568.  
  2569. SOM_Scope void
  2570. SOMLINK LinkTargetRemoved(IODLinkSource *somSelf,
  2571.                           Environment *ev,
  2572.                           ODLinkID linkID,
  2573.                           ODLinkConnectionID trgtID,
  2574.                           ODBoolean isLocal)
  2575. {
  2576.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  2577.     IODLinkSourceMethodDebug("IODLinkSource","LinkTargetRemoved");
  2578.  
  2579.     LinkInfo *linkInfo = kODNULL;
  2580.     OpenHashTable *linkInfos = isLocal ? _fLocalLinkInfos : _fRemoteLinkInfos;
  2581.  
  2582.     //---<1>
  2583.     if (_fState == IODLinkSource_EMPTY)
  2584.     {
  2585.       ODSetSOMException(ev, kODErrLinkSourceIsEmpty);
  2586.       return;
  2587.     }
  2588.  
  2589.     //---<2>
  2590.     _fMutex->Acquire(ev);
  2591.     if (ODGetSOMException(ev) != kODNoError)
  2592.     {
  2593.       return;
  2594.     }
  2595.  
  2596.     //---<3>
  2597.     if (linkInfos->GetValue(&trgtID, &linkInfo) != kODTrue)
  2598.     {
  2599.       ODSetSOMException(ev, kODErrInvalidTargetID);
  2600.       _fMutex->Release(ev);
  2601.       return;
  2602.     }
  2603.  
  2604.     //---<4>
  2605.     linkInfos->RemoveEntry(&trgtID);
  2606.  
  2607.     //---<5>
  2608.     CleanupPartDescription(linkInfo->trgtPartDesc);
  2609.     delete linkInfo;
  2610. }
  2611.  
  2612. /*
  2613.  *=============================================================================
  2614.  * <1>  Make sure the current state is not EMPTY.
  2615.  * <2>  Determine the new locality of the LinkTarget.
  2616.  * <3>  Acquire fMutex before accessing fLinkInfos.
  2617.  * <4>  Retrieve linkInfo associated with trgtID from fLinkInfos.
  2618.  * <5>  Delete old target part description.
  2619.  * <6>  Fill in linkInfo with new information.
  2620.  * <7>  If locality of LinkTarget has been changed then move linkInfo to
  2621.  *      the corresponding hashtable.
  2622.  * <8>  Release fMutex and return.
  2623.  * <9>  An exception is caught.
  2624.  *      Release fMutex.
  2625.  *      Cleanup linkInfo->trgtPartDesc.
  2626.  *      Set SOM exception and return.
  2627.  *=============================================================================
  2628.  */
  2629.  
  2630. SOM_Scope void
  2631. SOMLINK LinkTargetReopened(IODLinkSource *somSelf,
  2632.                            Environment *ev,
  2633.                            ODLinkID linkID,
  2634.                            ODLinkConnectionID trgtID,
  2635.                            ODULong pid,
  2636.                            ODLinkConnectionData* trgtPartDesc,
  2637.                            IODLinkTarget* linkTrgt,
  2638.                            ODBoolean* isLocal)
  2639. {
  2640.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  2641.     IODLinkSourceMethodDebug("IODLinkSource","LinkTargetReopened");
  2642.  
  2643.     LinkInfo *linkInfo = kODNULL;
  2644.     OpenHashTable *linkInfos = (*isLocal) ? _fLocalLinkInfos : _fRemoteLinkInfos;
  2645.     ODBoolean wasLocal = *isLocal;
  2646.  
  2647.     //---<1>
  2648.     if (_fState == IODLinkSource_EMPTY)
  2649.     {
  2650.       ODSetSOMException(ev, kODErrLinkSourceIsEmpty);
  2651.       return;
  2652.     }
  2653.  
  2654.     //---<2>
  2655.     //*isLocal = ODISOStrEqual(_fSrcPartDesc.docName, trgtPartDesc->docName);
  2656.     *isLocal = (_fPID == pid) ? kODTrue : kODFalse;
  2657.  
  2658.     //---<3>
  2659.     _fMutex->Acquire(ev);
  2660.     if (ODGetSOMException(ev) != kODNoError)
  2661.     {
  2662.       return;
  2663.     }
  2664.  
  2665.     //---<4>
  2666.     if (linkInfos->GetValue(&trgtID, &linkInfo) != kODTrue)
  2667.     {
  2668.       ODSetSOMException(ev, kODErrInvalidTargetID);
  2669.       _fMutex->Release(ev);
  2670.       return;
  2671.     }
  2672.  
  2673.     TRY
  2674.  
  2675.       //---<5>
  2676.       CleanupPartDescription(linkInfo->trgtPartDesc);
  2677.  
  2678.       //---<6>
  2679.       CopyPartDescription(linkInfo->trgtPartDesc, *trgtPartDesc);
  2680.  
  2681.       linkInfo->linkTrgt = linkTrgt;
  2682.       linkInfo->isAlive = kODTrue;
  2683.  
  2684.       //---<7>
  2685.       if (wasLocal != *isLocal)
  2686.       {
  2687.         linkInfos->RemoveEntry(&trgtID);
  2688.         if (*isLocal)
  2689.         {
  2690.           _fLocalLinkInfos->ReplaceEntry(&trgtID, &linkInfo);
  2691.         }
  2692.         else
  2693.         {
  2694.           _fRemoteLinkInfos->ReplaceEntry(&trgtID, &linkInfo);
  2695.         }
  2696.       }
  2697.  
  2698.       //---<8>
  2699.       _fMutex->Release(ev);
  2700.  
  2701.     CATCH_ALL
  2702.  
  2703.       //---<9>
  2704.       _fMutex->Release(ev);
  2705.  
  2706.       CleanupPartDescription(linkInfo->trgtPartDesc);
  2707.  
  2708.       SET_SOM_EV;
  2709.  
  2710.     ENDTRY
  2711. }
  2712.  
  2713. /*
  2714.  *=============================================================================
  2715.  * No op for now
  2716.  *=============================================================================
  2717.  */
  2718.  
  2719. SOM_Scope void
  2720. SOMLINK LockToRead(IODLinkSource *somSelf,
  2721.                    Environment *ev,
  2722.                    ODLinkID linkID,
  2723.                    ODULong wait,
  2724.                    ODLinkKey* key)
  2725. {
  2726.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  2727.     IODLinkSourceMethodDebug("IODLinkSource","LockToRead");
  2728.  
  2729.     IODLinkSource_parent_IODLinkTargetToLinkSource_LockToRead(somSelf,
  2730.                                                               ev,
  2731.                                                               linkID,
  2732.                                                               wait,
  2733.                                                               key);
  2734. }
  2735.  
  2736. /*
  2737.  *=============================================================================
  2738.  * <1>  Invoke parent's Release method.
  2739.  * <2>  If LinkSource's reference count goes down to zero inform the Draft
  2740.  *      to release the LinkSource.
  2741.  *=============================================================================
  2742.  */
  2743.  
  2744. SOM_Scope void
  2745. SOMLINK Release(IODLinkSource *somSelf,
  2746.                 Environment *ev)
  2747. {
  2748.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  2749.     IODLinkSourceMethodDebug("IODLinkSource","Release");
  2750.  
  2751.     //---<1>
  2752.     IODLinkSource_parent_ODLinkSource_Release(somSelf, ev);
  2753.  
  2754.     //---<2>
  2755.     if (_GetRefCount(ev) == 0)
  2756.     {
  2757.       _GetStorageUnit(ev)->GetDraft(ev)->ReleaseLinkSource(ev, somSelf);
  2758.     }
  2759. }
  2760.  
  2761. /*
  2762.  *=============================================================================
  2763.  * <1>  Invoke parent's ReleaseAll method.
  2764.  * <2>  Delete fMutex.
  2765.  * <3>  Reset fIDCounter to zero.
  2766.  * <4>  Reset fLinkID to zero.
  2767.  * <5>  Delete fLocalLinkInfos and fRemoteLinkInfos.
  2768.  * <6>  Free each fields of fSrcConnData.
  2769.  * <7>  Reset current state to EMPTY.
  2770.  * <8>  Reset fTrackTrgts to false.
  2771.  *=============================================================================
  2772.  */
  2773.  
  2774. SOM_Scope void
  2775. SOMLINK ReleaseAll(IODLinkSource *somSelf,
  2776.                    Environment *ev)
  2777. {
  2778.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  2779.     IODLinkSourceMethodDebug("IODLinkSource","ReleaseAll");
  2780.  
  2781.     ODLinkConnectionID id;
  2782.     LinkInfo *linkInfo = kODNULL;
  2783.  
  2784.     //---<1>
  2785.     IODLinkSource_parent_ODLinkSource_ReleaseAll(somSelf, ev);
  2786.  
  2787.     //---<2>
  2788.     delete _fMutex;
  2789.  
  2790.     //---<3>
  2791.     _fIDCounter = 0;
  2792.  
  2793.     //---<4>
  2794.     _fLinkID = 0;
  2795.  
  2796.     //---<5>
  2797.     if (_fLocalLinkInfos!=kODNULL)
  2798.      {
  2799.        OpenHashTableIterator lInfos(_fLocalLinkInfos);
  2800.        for (lInfos.First(&id, &linkInfo);
  2801.             lInfos.IsNotComplete();
  2802.             lInfos.Next(&id, &linkInfo))
  2803.          {
  2804.           CleanupPartDescription(linkInfo->trgtPartDesc);
  2805.           linkInfo->linkTrgt->Release(ev);
  2806.           delete linkInfo;
  2807.           }
  2808.  
  2809.        delete _fLocalLinkInfos;
  2810.        _fLocalLinkInfos = kODNULL;
  2811.      } //_fLocalLinkInfos != kODNULL
  2812.  
  2813.     if (_fRemoteLinkInfos!=kODNULL)
  2814.      {
  2815.        OpenHashTableIterator rInfos(_fRemoteLinkInfos);
  2816.        for (rInfos.First(&id, &linkInfo);
  2817.             rInfos.IsNotComplete();
  2818.             rInfos.Next(&id, &linkInfo))
  2819.          {
  2820.           CleanupPartDescription(linkInfo->trgtPartDesc);
  2821.           delete linkInfo;
  2822.          }
  2823.  
  2824.        delete _fRemoteLinkInfos;
  2825.        _fRemoteLinkInfos = kODNULL;
  2826.      } //_fRemoteLinkInfos != kODNULL
  2827.  
  2828.     //---<6>
  2829.     CleanupPartDescription(_fSrcConnData);
  2830.  
  2831.     //---<7>
  2832.     _fState = IODLinkSource_EMPTY;
  2833.  
  2834.     //---<8>
  2835.     _fTrackTrgts = kODFalse;
  2836.  
  2837. }
  2838.  
  2839. /*
  2840.  *=============================================================================
  2841.  * <1>  Make sure the current state is not EMPTY.
  2842.  * <2>  Acquire fMutex before accessing fLinkInfos.
  2843.  * <3>  Retrieve linkInfo associated with trgtID from fLinkInfos.
  2844.  * <4>  Set the isRegistered field of linkInfo to true.
  2845.  *      Release fMutex.
  2846.  *=============================================================================
  2847.  */
  2848.  
  2849. SOM_Scope void
  2850. SOMLINK RegisterTrackedLinkTarget(IODLinkSource *somSelf,
  2851.                                   Environment *ev,
  2852.                                   ODLinkID linkID,
  2853.                                   ODLinkConnectionID trgtID,
  2854.                                   ODBoolean isLocal)
  2855. {
  2856.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  2857.     IODLinkSourceMethodDebug("IODLinkSource","RegisterTrackedLinkTarget");
  2858.  
  2859.     LinkInfo *linkInfo = kODNULL;
  2860.     OpenHashTable *linkInfos = isLocal ? _fLocalLinkInfos : _fRemoteLinkInfos;
  2861.  
  2862.     //---<1>
  2863.     if (_fState == IODLinkSource_EMPTY)
  2864.     {
  2865.       ODSetSOMException(ev, kODErrLinkSourceIsEmpty);
  2866.       return;
  2867.     }
  2868.  
  2869.     //---<2>
  2870.     _fMutex->Acquire(ev);
  2871.     if (ODGetSOMException(ev) != kODNoError)
  2872.     {
  2873.       return;
  2874.     }
  2875.  
  2876.     //---<3>
  2877.     if (linkInfos->GetValue(&trgtID, &linkInfo) != kODTrue)
  2878.     {
  2879.       ODSetSOMException(ev, kODErrInvalidTargetID);
  2880.       _fMutex->Release(ev);
  2881.       return;
  2882.     }
  2883.  
  2884.     //---<4>
  2885.     linkInfo->isRegistered = kODTrue;
  2886.     _fMutex->Release(ev);
  2887. }
  2888.  
  2889. /*
  2890.  *=============================================================================
  2891.  * <1>  Make sure the current state is not EMPTY.
  2892.  * <2>  Acquire fMutex before accessing fLinkInfos.
  2893.  * <3>  Allocate a new linkInfo.
  2894.  * <4>  Fill in each field of linkInfo.
  2895.  * <5>  Add linkInfo to fLinkInfos.
  2896.  *      Release fMutex.
  2897.  *      Return the connection ID to caller.
  2898.  * <6>  An exception is caught.
  2899.  *      Release fMutex.
  2900.  *      Cleanup linkInfo.
  2901.  *      Set SOM exception and return.
  2902.  *=============================================================================
  2903.  */
  2904.  
  2905. SOM_Scope void
  2906. SOMLINK RegisterUntrackedLinkTarget(IODLinkSource *somSelf,
  2907.                                     Environment *ev,
  2908.                                     ODLinkID linkID,
  2909.                                     IODLinkTarget* linkTrgt,
  2910.                                     ODLinkConnectionData* trgtPartDesc,
  2911.                                     ODBoolean isLocal,
  2912.                                     ODLinkConnectionID* trgtID)
  2913. {
  2914.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  2915.     IODLinkSourceMethodDebug("IODLinkSource","RegisterUntrackedLinkTarget");
  2916.  
  2917.     LinkInfo *linkInfo = kODNULL;
  2918.     OpenHashTable *linkInfos = isLocal ? _fLocalLinkInfos : _fRemoteLinkInfos;
  2919.  
  2920.     //---<1>
  2921.     if (_fState == IODLinkSource_EMPTY)
  2922.     {
  2923.       ODSetSOMException(ev, kODErrLinkSourceIsEmpty);
  2924.       return;
  2925.     }
  2926.  
  2927.     //---<2>
  2928.     _fMutex->Acquire(ev);
  2929.     if (ODGetSOMException(ev) != kODNoError)
  2930.     {
  2931.       return;
  2932.     }
  2933.  
  2934.     TRY
  2935.  
  2936.       //---<3>
  2937.       linkInfo = new LinkInfo;
  2938.       THROW_IF_NULL(linkInfo);
  2939.  
  2940.       //---<4>
  2941.       if (isLocal)
  2942.       {
  2943.         linkTrgt->Acquire(ev);
  2944.       }
  2945.       linkInfo->trgtID = ++_fIDCounter;
  2946.       linkInfo->linkTrgt = linkTrgt;
  2947.       linkInfo->isAlive = kODTrue;
  2948.       linkInfo->isRegistered = kODTrue;
  2949.       CopyPartDescription(linkInfo->trgtPartDesc, *trgtPartDesc);
  2950.  
  2951.       //---<5>
  2952.       linkInfos->ReplaceEntry(&_fIDCounter, &linkInfo);
  2953.       _fMutex->Release(ev);
  2954.       *trgtID = linkInfo->trgtID;
  2955.       return;
  2956.  
  2957.     CATCH_ALL
  2958.  
  2959.       //---<6>
  2960.       _fMutex->Release(ev);
  2961.       delete linkInfo;
  2962.  
  2963.       SET_SOM_EV;
  2964.       return;
  2965.  
  2966.     ENDTRY
  2967. }
  2968.  
  2969. /*
  2970.  *=============================================================================
  2971.  * XXXXX For now:
  2972.  * <1>  Invoke parent's SetAutoUpdate method.
  2973.  *=============================================================================
  2974.  */
  2975.  
  2976. SOM_Scope void
  2977. SOMLINK SetAutoUpdate(IODLinkSource *somSelf,
  2978.                       Environment *ev,
  2979.                       ODBoolean automatic)
  2980. {
  2981.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  2982.     IODLinkSourceMethodDebug("IODLinkSource","SetAutoUpdate");
  2983.  
  2984.     //---<1>
  2985.     IODLinkSource_parent_ODLinkSource_SetAutoUpdate(somSelf, ev, automatic);
  2986. }
  2987.  
  2988.  
  2989. /*
  2990.  *=============================================================================
  2991.  * <1>  Invoke parent's ShowSourceContent method if caller is from the same
  2992.  *      host.
  2993.  *=============================================================================
  2994.  */
  2995.  
  2996. SOM_Scope void
  2997. SOMLINK ShowSourceContentFor(IODLinkSource *somSelf,
  2998.                              Environment *ev,
  2999.                              ODLinkID linkID,
  3000.                              string hostName)
  3001. {
  3002.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  3003.     IODLinkSourceMethodDebug("IODLinkSource","ShowSourceContentFor");
  3004.  
  3005.     //---<1>
  3006.     if (!strcmp(GetCStringFromIText(&_fSrcConnData.HostName), hostName))
  3007.       {
  3008.       _ShowSourceContent(ev);
  3009.       }
  3010.     else
  3011.       {
  3012.        ODSetSOMException(ev, kODErrSourceDocRemote);
  3013.       }
  3014. }
  3015. /*
  3016.  *=============================================================================
  3017.  * <1>  Make sure the current state is not EMPTY.
  3018.  * <2>  Acquire fMutex before accessing fLinkInfos.
  3019.  * <3>  Retrieve linkInfo associated with trgtID from fLinkInfos.
  3020.  * <4>  Delete old target part description.
  3021.  * <5>  Save new target part description.
  3022.  *      Release fMutex and return.
  3023.  * <6>  An exception is caught.
  3024.  *      Release fMutex.
  3025.  *      Cleanup linkInfo->trgPartDesc.
  3026.  *      Set SOM exception and return.
  3027.  *=============================================================================
  3028.  */
  3029.  
  3030. SOM_Scope void
  3031. SOMLINK TargetPartDescriptionChanged(IODLinkSource *somSelf,
  3032.                                      Environment *ev,
  3033.                                      ODLinkID linkID,
  3034.                                      ODLinkConnectionID trgtID,
  3035.                                      ODBoolean isLocal,
  3036.                                      ODLinkConnectionData* trgtPartDesc)
  3037. {
  3038.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  3039.     IODLinkSourceMethodDebug("IODLinkSource","TargetPartDescriptionChanged");
  3040.  
  3041.     LinkInfo *linkInfo = kODNULL;
  3042.     OpenHashTable *linkInfos = isLocal ? _fLocalLinkInfos : _fRemoteLinkInfos;
  3043.  
  3044.     //---<1>
  3045.     if (_fState == IODLinkSource_EMPTY)
  3046.     {
  3047.       ODSetSOMException(ev, kODErrLinkSourceIsEmpty);
  3048.       return;
  3049.     }
  3050.  
  3051.     //---<2>
  3052.     _fMutex->Acquire(ev);
  3053.     if (ODGetSOMException(ev) != kODNoError)
  3054.     {
  3055.       return;
  3056.     }
  3057.  
  3058.     //---<3>
  3059.     if (linkInfos->GetValue(&trgtID, &linkInfo) != kODTrue)
  3060.     {
  3061.       ODSetSOMException(ev, kODErrInvalidTargetID);
  3062.       _fMutex->Release(ev);
  3063.       return;
  3064.     }
  3065.  
  3066.     //---<4>
  3067.     CleanupPartDescription(linkInfo->trgtPartDesc);
  3068.  
  3069.     TRY
  3070.  
  3071.       //---<5>
  3072.       CopyPartDescription(linkInfo->trgtPartDesc, *trgtPartDesc);
  3073.       _fMutex->Release(ev);
  3074.  
  3075.     CATCH_ALL
  3076.  
  3077.       //---<6>
  3078.       _fMutex->Release(ev);
  3079.  
  3080.       CleanupPartDescription(linkInfo->trgtPartDesc);
  3081.  
  3082.       SET_SOM_EV;
  3083.  
  3084.     ENDTRY
  3085. }
  3086.  
  3087. /*
  3088.  *=============================================================================
  3089.  *=============================================================================
  3090.  */
  3091.  
  3092. SOM_Scope void
  3093. SOMLINK Unlock(IODLinkSource *somSelf,
  3094.                Environment *ev,
  3095.                ODLinkKey key)
  3096. {
  3097.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  3098.     IODLinkSourceMethodDebug("IODLinkSource","Unlock");
  3099.  
  3100.     ODUpdateID      changeIDold = _GetUpdateID(ev);
  3101.     ODLinkConnectionID id;
  3102.  
  3103. #if 0           // dr3
  3104.     ODBoolean       isChanged = _IsChanged(ev, key);
  3105. #endif
  3106.  
  3107.     LinkInfo*       linkInfo = kODNULL;
  3108.     ODBoolean       isChanged ;
  3109.  
  3110.     IODLinkSource_parent_ODLinkSource_Unlock(somSelf, ev, key);
  3111.  
  3112.     ODUpdateID      changeIDnew = _GetUpdateID(ev);
  3113.  
  3114. /*
  3115.      if ( changeID !=kODUnknownUpdate)
  3116.            isChanged = kODTrue;
  3117.      else
  3118.            isChanged = kODFalse;
  3119.  */
  3120.  
  3121.      if ( changeIDold != changeIDnew)
  3122.            isChanged = kODTrue;
  3123.      else
  3124.         {
  3125.            if (_GetUpdateContinue(ev)) {
  3126.              isChanged = kODTrue;
  3127.            } else {
  3128.              isChanged = kODFalse;
  3129.            } /* endif */
  3130.         }
  3131.  
  3132.     if (ev->_major) {
  3133.       ODSetSOMException(ev, kODNoError);
  3134.     }
  3135.  
  3136. #ifdef _PLATFORM_OS2_
  3137.     if (key != 1) {
  3138.       ODSetSOMException(ev, kODErrInvalidLinkKey);
  3139.       return;
  3140.       }
  3141. #endif /* _PLATFORM_OS2_ */
  3142.  
  3143.     _fMutex->Acquire(ev);
  3144.  
  3145.     if (ODGetSOMException(ev) != kODNoError)
  3146.     {
  3147.       return;
  3148.     }
  3149.  
  3150.    #ifdef _PLATFORM_OS2_
  3151.     // The following actions are taken to support waiting for unlock
  3152.     // 1. Dequeue and free any timed out LockWaitElements
  3153.     // 2. Dequeue first non-timed-out LockWaitElement, if any.
  3154.     // 3. If it exists,
  3155.     //    3.1. try to lock it
  3156.     //    3.2. if lock fails, save key as 0, wakeup and repeat 1.
  3157.     //    3.3. if lock succeeds, save key, wakeup leaving state LOCKED
  3158.     // 4. If it doesn't exist, leave state UNLOCKED
  3159.  
  3160.     // 1.
  3161.     _fLockState = IODLinkSource_UNLOCKED;
  3162.     for (LockWaitElement* LWE = _fFirstWE; LWE != kODNULL; LWE = _fFirstWE) {
  3163.       if (_fFirstWE == _fLastWE) {
  3164.         _fFirstWE = (LockWaitElement*) kODNULL;
  3165.         _fLastWE = (LockWaitElement*) kODNULL;
  3166.       } else {
  3167.         _fFirstWE = LWE->next;
  3168.       }
  3169.  
  3170.       if (LWE->timedout) {
  3171.         FreeLWE(LWE);
  3172.       } else {
  3173.         APIRET rc;
  3174.         // 3.1.
  3175.         ODBoolean success =
  3176.                   IODLinkSource_parent_ODLinkSource_Lock(somSelf,
  3177.                                                          ev,
  3178.                                                          0,
  3179.                                                          &LWE->key);
  3180.         if (success) {
  3181.           // 3.2.
  3182.           _fLockState = IODLinkSource_LOCKED;
  3183.           rc = DosPostEventSem(LWE->event);
  3184.           break;
  3185.         } else {
  3186.           // 3.3.
  3187.           LWE->key = 0;
  3188.           rc = DosPostEventSem(LWE->event);
  3189.         }
  3190.       }
  3191.     }
  3192.     // 4. (nop: we either left by successful WAIT or by end of list)
  3193.     #endif
  3194.  
  3195.     if (isChanged == kODTrue)
  3196.     {
  3197.       OpenHashTableIterator lInfos(_fLocalLinkInfos);
  3198.       for (lInfos.First(&id, &linkInfo);
  3199.            lInfos.IsNotComplete();
  3200.            lInfos.Next(&id, &linkInfo))
  3201.       {
  3202.         if (linkInfo->isRegistered)
  3203.         {
  3204.           linkInfo->linkTrgt->UpdateDependents(ev, changeIDold);
  3205.         }
  3206.       }
  3207.  
  3208.       OpenHashTableIterator rInfos(_fRemoteLinkInfos);
  3209.       for (rInfos.First(&id, &linkInfo);
  3210.            rInfos.IsNotComplete();
  3211.            rInfos.Next(&id, &linkInfo))
  3212.       {
  3213.         if (linkInfo->isRegistered)
  3214.         {
  3215.           SOM_TRY
  3216.             linkInfo->linkTrgt->UpdateDependents(ev, changeIDold);
  3217.           SOM_CATCH_ALL
  3218.             if (!_fTrackTrgts)
  3219.             {
  3220.               //XXXXX Should delete linkInfo->linkTrgt proxy
  3221.               _fRemoteLinkInfos->RemoveEntry(&id);
  3222.               delete linkInfo;
  3223.             }
  3224.             else
  3225.             {
  3226.               linkInfo->isRegistered = kODFalse;
  3227.               linkInfo->isAlive = kODFalse;
  3228.               //XXXXX Should delete linkInfo->linkTrgt proxy
  3229.             }
  3230.             ODSetSOMException(ev, kODNoError);
  3231.           SOM_ENDTRY;
  3232.         }
  3233.       }
  3234.     }
  3235.     _fMutex->Release(ev);
  3236. }
  3237.  
  3238. /*
  3239.  *=============================================================================
  3240.  * <1>  Make sure the current state is not EMPTY.
  3241.  * <2>  Acquire fMutex before accessing fLinkInfos.
  3242.  * <3>  Retrieve linkInfo associated with trgtID from fLinkInfos.
  3243.  * <4>  If caller is a untracked remote LinkTarget then remove its entry from
  3244.  *      fLinkInfos and delete linkInfo.
  3245.  * <5>  Otherwise set the isRegistered field of linkInfo to false.
  3246.  * <6>  Release fMutex.
  3247.  *=============================================================================
  3248.  */
  3249.  
  3250. SOM_Scope void
  3251. SOMLINK UnregisterLinkTarget(IODLinkSource *somSelf,
  3252.                              Environment *ev,
  3253.                              ODLinkID linkID,
  3254.                              ODLinkConnectionID trgtID,
  3255.                              ODBoolean isLocal)
  3256. {
  3257.     IODLinkSourceData *somThis = IODLinkSourceGetData(somSelf);
  3258.     IODLinkSourceMethodDebug("IODLinkSource","UnregisterLinkTarget");
  3259.  
  3260.     LinkInfo *linkInfo = kODNULL;
  3261.     OpenHashTable *linkInfos = isLocal ? _fLocalLinkInfos : _fRemoteLinkInfos;
  3262.  
  3263.     //---<1>
  3264.     if (_fState == IODLinkSource_EMPTY)
  3265.     {
  3266.       ODSetSOMException(ev, kODErrLinkSourceIsEmpty);
  3267.       return;
  3268.     }
  3269.  
  3270.     //---<2>
  3271.     _fMutex->Acquire(ev);
  3272.     if (ODGetSOMException(ev) != kODNoError)
  3273.     {
  3274.       return;
  3275.     }
  3276.  
  3277.     //---<3>
  3278.     if (linkInfos->GetValue(&trgtID, &linkInfo) != kODTrue)
  3279.     {
  3280.       ODSetSOMException(ev, kODErrInvalidTargetID);
  3281.       _fMutex->Release(ev);
  3282.       return;
  3283.     }
  3284.  
  3285.     if (!_fTrackTrgts && !isLocal)
  3286.     {
  3287.       //---<4>
  3288.       linkInfos->RemoveEntry(&trgtID);
  3289.  
  3290.       // No need to delete linkInfo->trgtPartDesc since it's NULL
  3291.       delete linkInfo;
  3292.     }
  3293.     else
  3294.     {
  3295.       //---<5>
  3296.       linkInfo->isRegistered = kODFalse;
  3297.     }
  3298.  
  3299.     //---<6>
  3300.      _fMutex->Release(ev);
  3301.     }
  3302.  
  3303. #endif
  3304.