subcycle.c
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 10k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. /*
  2.  * subcycle.c - Subtree cycle detection routines module.
  3.  */
  4. /* Headers
  5.  **********/
  6. #include "project.h"
  7. #pragma hdrstop
  8. #include "stub.h"
  9. #include "subcycle.h"
  10. /* Constants
  11.  ************/
  12. /* pointer array allocation constants */
  13. #define NUM_CYCLE_PTRS_TO_ADD          (16)
  14. /***************************** Private Functions *****************************/
  15. /* Module Prototypes
  16.  ********************/
  17. PRIVATE_CODE TWINRESULT CheckHalfForSubtreeCycle(HPTRARRAY, HPATH, HPATH, LPCTSTR);
  18. /*
  19. ** CheckHalfForSubtreeCycle()
  20. **
  21. ** Checks to see if half of a proposed new folder subtree twin would create one
  22. ** or more cycles of folder subtree twins.
  23. **
  24. ** Arguments:     hpaFolderPairs - handle to PTRARRAY containing pointers to
  25. **                                 folder pairs
  26. **                hpathStartFolder - root folder of initial half of proposed
  27. **                                   new folder pair
  28. **                hpathEndFolder - root folder of other half of proposed new
  29. **                                 folder pair
  30. **                pcszName - name specification of matching objects to be
  31. **                           included in proposed new folder subtree pair
  32. **
  33. ** Returns:       TWINRESULT
  34. **
  35. ** Side Effects:  none
  36. **
  37. ** N.b., this function should be called twice for each proposed new folder
  38. ** subtree pair.
  39. */
  40. PRIVATE_CODE TWINRESULT CheckHalfForSubtreeCycle(HPTRARRAY hpaFolderPairs,
  41.                                                  HPATH hpathStartFolder,
  42.                                                  HPATH hpathEndFolder,
  43.                                                  LPCTSTR pcszName)
  44. {
  45.    TWINRESULT tr;
  46.    ARRAYINDEX aicFolderPairs;
  47.    NEWPTRARRAY npa;
  48.    HPTRARRAY hpaFolders;
  49.    ASSERT(IS_VALID_HANDLE(hpaFolderPairs, PTRARRAY));
  50.    ASSERT(IS_VALID_HANDLE(hpathStartFolder, PATH));
  51.    ASSERT(IS_VALID_HANDLE(hpathEndFolder, PATH));
  52.    ASSERT(IS_VALID_STRING_PTR(pcszName, CSTR));
  53.    aicFolderPairs = GetPtrCount(hpaFolderPairs);
  54.    /*
  55.     * Try to create an unsorted pointer array to be used in checking for
  56.     * cycles.
  57.     */
  58.    npa.aicInitialPtrs = aicFolderPairs;
  59.    npa.aicAllocGranularity = NUM_CYCLE_PTRS_TO_ADD;
  60.    npa.dwFlags = 0;
  61.    if (CreatePtrArray(&npa, &hpaFolders))
  62.    {
  63.       ARRAYINDEX aicFolders;
  64.       ARRAYINDEX aiCurFolder;
  65.       HPATH hpathCurFolderRoot;
  66.       /* Search all folder pairs connected to the first new folder twin. */
  67.       /*
  68.        * Mark all folder twins unused.  A "used" folder twin is one that has
  69.        * already been visited while searching for subtree cycles.  I.e., a
  70.        * used folder subtree pair half intersected the first folder of the
  71.        * proposed new folder twin, and its other half was added to the list for
  72.        * later comparison.
  73.        */
  74.       ClearFlagInArrayOfStubs(hpaFolderPairs, STUB_FL_USED);
  75.       /*
  76.        * Loop to process entire graph of folder subtree twins connected to the
  77.        * first new folder twin.  Folder twins are only added to the hpaFolders
  78.        * array if they don't already intersect the second of the two proposed
  79.        * new folder subtree twins.
  80.        */
  81.       tr = TR_SUCCESS;
  82.       aicFolders = 0;
  83.       aiCurFolder = 0;
  84.       /* Begin with start folder. */
  85.       hpathCurFolderRoot = hpathStartFolder;
  86.       FOREVER
  87.       {
  88.          ARRAYINDEX aiCheckFolderRoot;
  89.          /*
  90.           * Loop to find all subtree folder pairs that intersect
  91.           * hpaFolders[aiCurFolder]'s subtree.
  92.           */
  93.          for (aiCheckFolderRoot = 0;
  94.               aiCheckFolderRoot < aicFolderPairs;
  95.               aiCheckFolderRoot++)
  96.          {
  97.             PFOLDERPAIR pfpCheck;
  98.             /* Get this subtree folder pair's root folder. */
  99.             pfpCheck = GetPtr(hpaFolderPairs, aiCheckFolderRoot);
  100.             ASSERT(IS_VALID_STRUCT_PTR(pfpCheck, CFOLDERPAIR));
  101.             /* Have we already visited this folder pair? */
  102.             if (IsStubFlagSet(&(pfpCheck->stub), STUB_FL_SUBTREE) &&
  103.                 IsStubFlagClear(&(pfpCheck->stub), STUB_FL_BEING_TRANSLATED) &&
  104.                 IsStubFlagClear(&(pfpCheck->stub), STUB_FL_USED) &&
  105.                 IsStubFlagClear(&(pfpCheck->pfpOther->stub), STUB_FL_USED))
  106.             {
  107.                /*
  108.                 * No.  Does this subtree folder pair intersect the current
  109.                 * folder pair node's subtree, and the objects named in the
  110.                 * proposed new folder subtree twin?
  111.                 */
  112.                ASSERT(IsStubFlagSet(&(pfpCheck->pfpOther->stub), STUB_FL_SUBTREE));
  113.                ASSERT(IsStubFlagClear(&(pfpCheck->pfpOther->stub), STUB_FL_BEING_TRANSLATED));
  114.                if (SubtreesIntersect(hpathCurFolderRoot, pfpCheck->hpath) &&
  115.                    NamesIntersect(GetString(pfpCheck->pfpd->hsName), pcszName))
  116.                {
  117.                   HPATH hpathOtherCheckFolderRoot;
  118.                   /* Yes.  Get the other side of the folder subtree pair. */
  119.                   hpathOtherCheckFolderRoot = pfpCheck->pfpOther->hpath;
  120.                   /*
  121.                    * Does this pair connect back to the other side of the
  122.                    * proposed new folder pair?
  123.                    */
  124.                   if (SubtreesIntersect(hpathOtherCheckFolderRoot,
  125.                                         hpathEndFolder))
  126.                   {
  127.                      /*
  128.                       * Yes.  Are the roots different parts of the common
  129.                       * subtree?
  130.                       */
  131.                      if (ComparePaths(hpathEndFolder,
  132.                                       hpathOtherCheckFolderRoot)
  133.                          != CR_EQUAL)
  134.                      {
  135.                         /* Yes.  Found a cycle.  Bail out. */
  136.                         WARNING_OUT((TEXT("CheckHalfForSubtreeCycle(): Subtree cycle found connecting folders %s and %s."),
  137.                                      DebugGetPathString(hpathStartFolder),
  138.                                      DebugGetPathString(hpathEndFolder)));
  139.                         tr = TR_SUBTREE_CYCLE_FOUND;
  140.                         break;
  141.                      }
  142.                      /*
  143.                       * We don't need to include this root in the search if it
  144.                       * is the same as the other side of the proposed new
  145.                       * folder pair since it will be covered during the other
  146.                       * call to CheckHalfForSubtreeCycle().
  147.                       */
  148.                   }
  149.                   else
  150.                   {
  151.                      /* Add this subtree as another node to be examined. */
  152.                      if (! InsertPtr(hpaFolders, NULL, aicFolders++,
  153.                                      (PCVOID)(pfpCheck->pfpOther)))
  154.                         tr = TR_OUT_OF_MEMORY;
  155.                   }
  156.                   /* Mark this folder twin as already visited. */
  157.                   if (tr == TR_SUCCESS)
  158.                      SetStubFlag(&(pfpCheck->stub), STUB_FL_USED);
  159.                   else
  160.                      break;
  161.                }
  162.             }
  163.          }
  164.          /* Any folder subtree twins left to investigate? */
  165.          if (aiCurFolder < aicFolders)
  166.          {
  167.             PFOLDERPAIR pfpCur;
  168.             /* Yes. */
  169.             pfpCur = GetPtr(hpaFolders, aiCurFolder++);
  170.             hpathCurFolderRoot = pfpCur->hpath;
  171.          }
  172.          else
  173.             /* No. */
  174.             break;
  175.       }
  176.       DestroyPtrArray(hpaFolders);
  177.    }
  178.    else
  179.       tr = TR_OUT_OF_MEMORY;
  180.    return(tr);
  181. }
  182. /****************************** Public Functions *****************************/
  183. /*
  184. ** BeginTranslateFolder()
  185. **
  186. **
  187. **
  188. ** Arguments:
  189. **
  190. ** Returns:
  191. **
  192. ** Side Effects:  none
  193. */
  194. PUBLIC_CODE void BeginTranslateFolder(PFOLDERPAIR pfp)
  195. {
  196.    ASSERT(IS_VALID_STRUCT_PTR(pfp, CFOLDERPAIR));
  197.    ASSERT(IsStubFlagClear(&(pfp->stub), STUB_FL_BEING_TRANSLATED));
  198.    ASSERT(IsStubFlagClear(&(pfp->pfpOther->stub), STUB_FL_BEING_TRANSLATED));
  199.    SetStubFlag(&(pfp->stub), STUB_FL_BEING_TRANSLATED);
  200.    SetStubFlag(&(pfp->pfpOther->stub), STUB_FL_BEING_TRANSLATED);
  201.    return;
  202. }
  203. /*
  204. ** EndTranslateFolder()
  205. **
  206. **
  207. **
  208. ** Arguments:
  209. **
  210. ** Returns:
  211. **
  212. ** Side Effects:  none
  213. */
  214. PUBLIC_CODE void EndTranslateFolder(PFOLDERPAIR pfp)
  215. {
  216.    ASSERT(IS_VALID_STRUCT_PTR(pfp, CFOLDERPAIR));
  217.    ASSERT(IsStubFlagSet(&(pfp->stub), STUB_FL_BEING_TRANSLATED));
  218.    ASSERT(IsStubFlagSet(&(pfp->pfpOther->stub), STUB_FL_BEING_TRANSLATED));
  219.    ClearStubFlag(&(pfp->stub), STUB_FL_BEING_TRANSLATED);
  220.    ClearStubFlag(&(pfp->pfpOther->stub), STUB_FL_BEING_TRANSLATED);
  221.    return;
  222. }
  223. /*
  224. ** CheckForSubtreeCycles()
  225. **
  226. ** Checks to see if a proposed new folder subtree twin would create one or more
  227. ** cycles of folder subtree twins.
  228. **
  229. ** Arguments:
  230. **
  231. ** Returns:       TWINRESULT
  232. **
  233. ** Side Effects:  none
  234. **
  235. ** N.b., TR_SUBTREE_CYCLE_FOUND is returned if the folder subtree roots of the
  236. ** proposed new folder subtree twin are the same.
  237. */
  238. PUBLIC_CODE TWINRESULT CheckForSubtreeCycles(HPTRARRAY hpaFolderPairs,
  239.                                              HPATH hpathFirstFolder,
  240.                                              HPATH hpathSecondFolder,
  241.                                              HSTRING hsName)
  242. {
  243.    TWINRESULT tr;
  244.    ASSERT(IS_VALID_HANDLE(hpaFolderPairs, PTRARRAY));
  245.    ASSERT(IS_VALID_HANDLE(hpathFirstFolder, PATH));
  246.    ASSERT(IS_VALID_HANDLE(hpathSecondFolder, PATH));
  247.    ASSERT(IS_VALID_HANDLE(hsName, STRING));
  248.    /* Are the folder twins cyclical on their own? */
  249.    if (SubtreesIntersect(hpathFirstFolder, hpathSecondFolder))
  250.    {
  251.       /* Yes. */
  252.       tr = TR_SUBTREE_CYCLE_FOUND;
  253.       WARNING_OUT((TEXT("CheckForSubtreeCycles(): Subtree cycle found connecting folders %s and %s."),
  254.                    DebugGetPathString(hpathFirstFolder),
  255.                    DebugGetPathString(hpathSecondFolder)));
  256.    }
  257.    else
  258.    {
  259.       LPCTSTR pcszName;
  260.       /* No.  Check for any indirect subtree cycle.  */
  261.       pcszName = GetString(hsName);
  262.       tr = CheckHalfForSubtreeCycle(hpaFolderPairs, hpathFirstFolder,
  263.                                     hpathSecondFolder, pcszName);
  264.       if (tr == TR_SUCCESS)
  265.          tr = CheckHalfForSubtreeCycle(hpaFolderPairs, hpathSecondFolder,
  266.                                        hpathFirstFolder, pcszName);
  267.    }
  268.    return(tr);
  269. }