info-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Patch to better handle deeply nested module definitions


From: Shane Turner
Subject: Patch to better handle deeply nested module definitions
Date: Wed, 28 Nov 2001 09:20:35 -0400

Hi,

Here at InfoInterActive we've gotten into the habit of defining modules
for each library so when that library module is checked out, all of the
library modules that it depends on are also checked out. The problem
with this is when the same module ends up included more than once. When
accessing the repository on the local disk everything looks fine. When
you use ssh, things get wierd. After a given module is checked out for
the first time, every instance after that results in compaints because
it tried to check out the files all over again.

Here's an example of a the type of module definitions we use:

App -a Basics WunderLogLib FooLib BarLib AppDir

WunderLogLib -a Basics WunderLogLibDir

FooLib -a Basics WunderLogLib FooLibDir

BarLib -a Basics WunderLogLib FooLib BarLibDir

Basics -a BasicsDir

The unpatched cvs-1.11.1p1 would check out the following:
BasicsDir
BasicsDir
WunderLogLibDir
BasicsDir
BasicsDir
WunderLogLibDir
FooLibDir
BasicsDir
BasicsDir
WunderLogLibDir
BasicsDir
BasicsDir
WunderLogLibDir
FooLibDir
BarLibDir
AppDir

As you can see things get a little redundant.

To solve the problem, a couple of the other developers (Brad Spencer and
David Benoit) got sufficiently annoyed and wrote a little patch that
lets the server remember what modules it has already checked out.

We couldn't think of a better test for this new feature than the ones
that already test the module handling, so there isn't one.

I've submitted this patch to devel-cvs in the past, but I never did get
a response. I figure it's been working fine for us for months (and we
really push the envelope for modules) so it's safe for public
consumption.

Have fun and feel free to contact me if you have any questions or
suggestions.

Shane

--
Shane Turner, Senior Software Engineer
InfoInterActive Corp. (An AOL Company) www.infointeractive.com
E address@hidden V 902-832-2633 F 902-832-1015
AIM iiaShane
-----BEGIN GEEK CODE BLOCK-----
GCS d-(+) s: a- C++$ ULS++ P+(++) L++ E@ W+ N o? K? w O M- V !PS !PE Y+
PGP
t++@ 5+ X+ R tv b+ DI+ D+ G e++ h--- r+++ y+++
-----END GEEK CODE BLOCK-----

*** modules.c.orig      Thu May 10 11:28:41 2001
--- modules.c   Fri May 11 14:20:11 2001
***************
*** 53,60 ****
--- 53,170 ----
  static int sort_order PROTO((const PTR l, const PTR r));
  static void save_d PROTO((char *k, int ks, char *d, int ds));
  
+ /*
+  * Remember what modules we've processed before so we don't duplicate a _lot_
+  * of effort.  This saves an amazing amount of time with highly recursive
+  * module definitions.  This should perhaps be a hash of some form, but
+  * writing complex data structures in C is just too quaint.
+  *
+  * GOTCHA: This assumes that only one (top-level) do_module is called per
+  * instance.  If this isn't true, reset the table first.  FIXME: It leaks.
+  */
  
+ /* Extra diagnostics */
+ #define CVSMODULE_PRINT_MODULE_MEMORY 1
+ 
+ /* Right now, it's just a linked list. */
+ struct MemoryNode {
+   struct MemoryNode *next;
+   char data[1];
+ };
+ static struct MemoryNode *st_list = NULL;
+ static unsigned int st_memoryHits = 0;
+ 
  /*
+  * Ask if the specified module is in module memory or not.
+  */
+ static int
+ module_memory_hit(char *mname)
+ {
+   /* The current list */
+   struct MemoryNode *start = st_list;
+ 
+   /* Start at the front and see if it's there.  If not, add it. */
+   while(start != NULL) {
+     if(strcmp(start->data, mname) == 0) {
+       /* Found it. */
+       st_memoryHits++;
+       return 1;
+     }
+     start = start->next;
+   }
+   return 0;
+ }
+ 
+ /*
+  * Add a specified module to module memory.  Returns 1 if it was already 
there,
+  * or 0 if it wasn't.
+  */
+ static int
+ module_memory(char *mname)
+ {
+   /* The current list */
+   struct MemoryNode *node;
+ 
+   if(module_memory_hit(mname) == 1) {
+     return 1;
+   }
+   
+   /*
+    * Make a new node that will go on the front of the list.  We've got the +1
+    * in the data[1].
+   */ 
+   node = (struct MemoryNode *)xmalloc(sizeof(struct MemoryNode)
+                                      + strlen(mname));
+   node->next = st_list;
+   strcpy(node->data, mname);
+   st_list = node;
+ 
+ #if CVSMODULE_PRINT_MODULE_MEMORY
+   if(trace) {
+     cvs_outerr(CLIENT_SERVER_STR, 0);
+     cvs_outerr("-> Added module `", 0);
+     cvs_outerr(mname, 0);
+     cvs_outerr("' to module memory\n", 0);
+   }
+ #endif /* CVSMODULE_PRINT_MODULE_MEMORY */      
+   
+   /* We added it, so it wasn't there */
+   return 0;
+ }
+ 
+ /*
+  * Forget all current module memory
+  */
+ 
+ static void
+ module_memory_forget(void)
+ {
+   struct MemoryNode *node = st_list;
+   struct MemoryNode *next;
+ 
+   /* Delete all nodes */
+   while(node != NULL) {
+     next = node->next;
+     free(node);
+     node = next;
+   }
+   /* Mark the list as empty */
+   st_list = NULL;
+   st_memoryHits = 0;
+ 
+ #if CVSMODULE_PRINT_MODULE_MEMORY
+   if(trace) {
+     char buff[17];
+     cvs_outerr(CLIENT_SERVER_STR, 0);
+     cvs_outerr("-> Cleared module memory (", 0);
+     sprintf(buff, "%u", st_memoryHits);
+     cvs_outerr(buff, 0);
+     cvs_outerr(" hits)\n", 0);
+   }
+ #endif /* CVSMODULE_PRINT_MODULE_MEMORY */      
+ }
+ 
+ /*
   * Open the modules file, and die if the CVSROOT environment variable
   * was not set.  If the modules file does not exist, that's fine, and
   * a warning message is displayed and a NULL is returned.
***************
*** 89,94 ****
--- 199,207 ----
  {
      if (db != NULL)
        dbm_close (db);
+ 
+     /* Forget all memorized modules */
+     module_memory_forget();
  }
  
  /*
***************
*** 295,305 ****
            if (save_cwd (&cwd))
                error_exit ();
            cwd_saved = 1;
  
-           err += callback_proc (modargc, modargv, where, mwhere, mfile,
-                                 shorten,
-                                 local_specified, mname, msg);
- 
            free_names (&modargc, modargv);
  
            /* cd back to where we started.  */
--- 408,420 ----
            if (save_cwd (&cwd))
                error_exit ();
            cwd_saved = 1;
+           
+           if(module_memory(mname) == 0) {
+             err += callback_proc (modargc, modargv, where, mwhere, mfile,
+                                   shorten, 
+                                   local_specified, mname, msg);
+           }
  
            free_names (&modargc, modargv);
  
            /* cd back to where we started.  */
***************
*** 503,512 ****
                error (0, 0,
                       "module `%s' in modules file contains infinite loop",
                       mname);
!           else
                err += do_module (db, modargv[i], m_type, msg, callback_proc,
                                  where, shorten, local_specified,
                                  run_module_prog, build_dirs, extra_arg);
        }
        goto do_module_return;
      }
--- 618,628 ----
                error (0, 0,
                       "module `%s' in modules file contains infinite loop",
                       mname);
!           else if(module_memory_hit(modargv[i]) == 0) {
                err += do_module (db, modargv[i], m_type, msg, callback_proc,
                                  where, shorten, local_specified,
                                  run_module_prog, build_dirs, extra_arg);
+           }
        }
        goto do_module_return;
      }
***************
*** 523,530 ****
      /* otherwise, process this module */
      if (modargc > 0)
      {
!       err += callback_proc (modargc, modargv, where, mwhere, mfile, shorten,
!                             local_specified, mname, msg);
      }
      else
      {
--- 639,648 ----
      /* otherwise, process this module */
      if (modargc > 0)
      {
!       if(module_memory(mname) == 0) {
!       err += callback_proc(modargc, modargv, where, mwhere, mfile, shorten,
!                            local_specified, mname, msg);
!       }
      }
      else
      {

reply via email to

[Prev in Thread] Current Thread [Next in Thread]