[PATCH] Run postinstall scripts in a thread with progress bars - take 3

Igor Pechtchanski pechtcha@cs.nyu.edu
Mon Mar 24 22:48:00 GMT 2003


On 21 Mar 2003, Robert Collins wrote:

> On Fri, 2003-03-21 at 08:49, Igor Pechtchanski wrote:
> > On 21 Mar 2003, Robert Collins wrote:
> >
> > > On Fri, 2003-03-21 at 04:49, Igor Pechtchanski wrote:
> > >
> > > > Same as above, but regenerated against HEAD.  ChangeLog is the same.
> > > > The only thing about this patch that really makes me uncomfortable is
> > > > having to run through iterators/FindVisitors twice.  Any suggestions for
> > > > improvement are welcome.
> > >
> > > Sight unseen - instead of counting in the visitor and iterators, push
> > > all the script details (and package references if appropriate) onto a
> > > list or vector first time through.
> > >
> > > Then, simply walk the list.
> > > Rob
>
> I've give a fuller review later. However:
>
> This code can be simplified:
> 1) iterate over the dependency ordered packages and push all their
> scripts into the 'to be run' collection. Save the current count of
> scripts.
> 2) iterate over the files in the directory.
> 3) subtract the count in 1) from the now total to get the total scripts
> to be run.
> 3a) optional: iterate forward through the scripts vector and remove any
> duplicates. There may even be an stl order preserving call to do this
> (removing the duplicates from pos->end()).
> 4) iterate through the scripts and run them.
>
> 3a) is optional because we don't error on missing scripts IIRC.

Rob,

I wanted (and still want) to keep the two bar progress on this.  The
second bar would show progress through packages, and the first - progress
through the scripts *in the current package*.

> Alteratively/also you could extract the script running and screen
> updating code to a new method.
> Rob

Done.  I've also done some restructuring of the Script class and enabled
the "#if 0"'d code from the previous patch, now that the progress bars
exist.

I've attached the next iteration.  Should apply cleanly to HEAD.
	Igor
==============================================================================
ChangeLog:
2003-03-24  Igor Pechtchanski <pechtcha@cs.nyu.edu>

	* threebar.h (WM_APP_START_POSTINSTALL): New message.
	(WM_APP_POSTINSTALL_THREAD_COMPLETE): New message.
	* threebar.cc (ThreeBarProgressPage::OnMessageApp):
	Add handling for WM_APP_START_POSTINSTALL and
	WM_APP_POSTINSTALL_THREAD_COMPLETE.
	* install.cc (do_install_thread): Set next_dialog to
	IDD_S_POSTINSTALL.
	* desktop.cc (DesktopSetupPage::OnFinish): Move the
	do_postinstall call to ThreeBarProgressPage::OnMessageApp.
	* script.h (Script::fullName): New member function.
	(Script::run): New member function.
	* script.cc (Script::fullName): Implement.
	(Script::run): Implement.
	(run): Enable "#if 0"'d code.
	* postinstall.cc (Progress): New extern variable.
	(RunFindVisitor::visitFile): Add script to vector
	instead of running.
	(RunFindVisitor::_scripts): New member variable.
	(run_package_scripts): New static function.
	(do_postinstall_thread): Rename do_postinstall to.  Add
	Progress bar and text setting.  Add package count.
	(do_postinstall_reflector): New static function.
	(do_postinstall): Rename to do_postinstall_thread.
	Create a thread instead.

-- 
				http://cs.nyu.edu/~pechtcha/
      |\      _,,,---,,_		pechtcha@cs.nyu.edu
ZZZzz /,`.-'`'    -.  ;-;;,_		igor@watson.ibm.com
     |,4-  ) )-,_. ,\ (  `'-'		Igor Pechtchanski
    '---''(_/--'  `-'\_) fL	a.k.a JaguaR-R-R-r-r-r-.-.-.  Meow!

Oh, boy, virtual memory! Now I'm gonna make myself a really *big* RAMdisk!
  -- /usr/games/fortune

-------------- next part --------------
Index: desktop.cc
===================================================================
RCS file: /cvs/cygwin-apps/setup/desktop.cc,v
retrieving revision 2.34
diff -u -p -r2.34 desktop.cc
--- desktop.cc	25 Nov 2002 22:12:08 -0000	2.34
+++ desktop.cc	24 Mar 2003 22:04:08 -0000
@@ -397,8 +397,6 @@ DesktopSetupPage::OnFinish ()
   HWND h = GetHWND ();
   save_dialog (h);
   do_desktop_setup ();
-  NEXT (IDD_S_POSTINSTALL);
-  do_postinstall (GetInstance (), h);
 
   return true;
 }
Index: install.cc
===================================================================
RCS file: /cvs/cygwin-apps/setup/install.cc,v
retrieving revision 2.60
diff -u -p -r2.60 install.cc
--- install.cc	17 Mar 2003 22:23:33 -0000	2.60
+++ install.cc	24 Mar 2003 22:04:08 -0000
@@ -455,7 +455,7 @@ do_install_thread (HINSTANCE h, HWND own
   num_installs = 0, num_uninstalls = 0, num_replacements = 0;
   rebootneeded = false;
 
-  next_dialog = IDD_DESKTOP;
+  next_dialog = IDD_S_POSTINSTALL;
 
   io_stream::mkpath_p (PATH_TO_DIR, String ("file://") + get_root_dir ());
 
Index: postinstall.cc
===================================================================
RCS file: /cvs/cygwin-apps/setup/postinstall.cc,v
retrieving revision 2.12
diff -u -p -r2.12 postinstall.cc
--- postinstall.cc	20 Mar 2003 10:02:51 -0000	2.12
+++ postinstall.cc	24 Mar 2003 22:04:08 -0000
@@ -29,40 +29,113 @@ static const char *cvsid =
 #include "FilterVisitor.h"
 #include "package_db.h"
 #include "package_meta.h"
+#include "resource.h"
+#include "threebar.h"
+
+extern ThreeBarProgressPage Progress;
 
 class RunFindVisitor : public FindVisitor
 {
 public:
-  RunFindVisitor (){}
+  RunFindVisitor (std::vector<Script> *scripts) : _scripts(scripts) {}
   virtual void visitFile(String const &basePath, const WIN32_FIND_DATA *theFile)
     {
-      run_script ("/etc/postinstall/", theFile->cFileName, TRUE);
+      String fn = String("/etc/postinstall/")+theFile->cFileName;
+      _scripts->push_back(Script (fn));
     }
   virtual ~ RunFindVisitor () {}
 protected:
   RunFindVisitor (RunFindVisitor const &);
   RunFindVisitor & operator= (RunFindVisitor const &);
+private:
+  std::vector<Script> *_scripts;
 };
-  
-void
-do_postinstall (HINSTANCE h, HWND owner)
+
+static void
+run_package_scripts (String const &packagename, std::vector<Script> &scripts)
 {
-  next_dialog = 0;
+  Progress.SetText2 (packagename.cstr_oneuse());
+  int numscr = scripts.size();
+  int s = 0;
+  Progress.SetBar1 (s, numscr);
+  for (std::vector<Script>::iterator script = scripts.begin();
+       script != scripts.end();
+       ++script) 
+    {
+      Progress.SetText3 (script->fullName().cstr_oneuse());
+      script->run(TRUE);
+      ++s;
+      Progress.SetBar1 (s, numscr);
+    }
+  Progress.SetText3 ("");
+}
+
+static void
+do_postinstall_thread (HINSTANCE h, HWND owner)
+{
+  next_dialog = IDD_DESKTOP;
+
+  Progress.SetText1 ("Running...");
+  Progress.SetText2 ("");
+  Progress.SetText3 ("");
+  Progress.SetBar1 (0, 1);
+  Progress.SetBar2 (0, 1);
+
   init_run_script ();
   SetCurrentDirectory (get_root_dir ().cstr_oneuse());
   packagedb db;
+  std::vector<packagemeta*> packages;
   PackageDBConnectedIterator i = db.connectedBegin ();
   while (i != db.connectedEnd ())
     {
       packagemeta & pkg = **i;
       if (pkg.installed)
-	for (std::vector<Script>::iterator script=pkg.installed.scripts().begin(); script != pkg.installed.scripts().end(); ++script) 
-	  run_script ("/etc/postinstall/", script->baseName(), TRUE);
+	packages.push_back(&pkg);
       ++i;
     }
-  RunFindVisitor myVisitor;
+  int numpkg = packages.size() + 1;
+  int k = 0;
+  for (i = packages.begin (); i != packages.end (); ++i)
+    {
+      packagemeta & pkg = **i;
+      run_package_scripts(pkg.name, pkg.installed.scripts());
+      ++k;
+      Progress.SetBar2 (k, numpkg);
+    }
   ExcludeNameFilter notDone("*.done");
-  FilterVisitor excludeDoneVisitor(&myVisitor, &notDone);
   String postinst = cygpath ("/etc/postinstall");
+  std::vector<Script> scripts;
+  RunFindVisitor myVisitor (&scripts);
+  FilterVisitor excludeDoneVisitor(&myVisitor, &notDone);
+  Progress.SetBar1 (0, 1);
   Find (postinst).accept (excludeDoneVisitor);
+  run_package_scripts("No package", scripts);
+  Progress.SetBar2 (numpkg, numpkg);
+}
+
+static DWORD WINAPI
+do_postinstall_reflector (void *p)
+{
+  HANDLE *context;
+  context = (HANDLE *) p;
+
+  do_postinstall_thread ((HINSTANCE) context[0], (HWND) context[1]);
+
+  // Tell the progress page that we're done running scripts
+  Progress.PostMessage (WM_APP_POSTINSTALL_THREAD_COMPLETE);
+
+  ExitThread(0);
 }
+
+static HANDLE context[2];
+
+void
+do_postinstall (HINSTANCE h, HWND owner)
+{
+  context[0] = h;
+  context[1] = owner;
+
+  DWORD threadID;
+  CreateThread (NULL, 0, do_postinstall_reflector, context, 0, &threadID);
+}
+
Index: script.cc
===================================================================
RCS file: /cvs/cygwin-apps/setup/script.cc,v
retrieving revision 2.7
diff -u -p -r2.7 script.cc
--- script.cc	20 Mar 2003 10:02:51 -0000	2.7
+++ script.cc	24 Mar 2003 22:04:08 -0000
@@ -182,13 +182,8 @@ run (const char *sh, const char *args, c
       si.hStdOutput = file_out.handle ();
       si.hStdError = file_out.handle ();
       si.dwFlags |= STARTF_USESHOWWINDOW;
-#if 0
       si.wShowWindow = SW_HIDE;
-      flags = CREATE_NO_WINDOW;  // Note: might not work on Win9x
-#else
-      // TODO: introduce a script progress tracker and use the above
-      si.wShowWindow = SW_MINIMIZE;
-#endif
+      flags = CREATE_NO_WINDOW;  // Note: this is ignored on Win9x
     }
 
   BOOL createSucceeded = CreateProcess (0, cmdline, 0, 0, inheritHandles,
@@ -250,11 +245,14 @@ try_run_script (String const &dir, Strin
     run_script (dir.cstr_oneuse(), (fname + ".bat").cstr_oneuse());
 }
 
+static const char etc_postinstall[] = "/etc/postinstall/";
+
 bool
 Script::isAScript (String const &file)
 {
     /* file may be /etc/postinstall or etc/postinstall */
-    if (file.casecompare ("/etc/postinstall/", 17) && file.casecompare ("etc/postinstall/", 16))
+    if (file.casecompare (etc_postinstall, sizeof(etc_postinstall)) &&
+	file.casecompare (etc_postinstall+1, sizeof(etc_postinstall)-1))
       return false;
     if (file.cstr_oneuse()[file.size() - 1] == '/')
       return false;
@@ -267,10 +265,23 @@ Script::Script (String const &fileName) 
 }
 
 String
-Script::baseName()const
+Script::baseName() const
 {
   String result = scriptName;
   while (result.find ('/'))
     result = result.substr(result.find ('/'));
   return result;
 }
+
+String
+Script::fullName() const
+{
+  return scriptName;
+}
+
+void
+Script::run(BOOL to_log) const
+{
+  run_script("", scriptName, to_log);
+}
+
Index: script.h
===================================================================
RCS file: /cvs/cygwin-apps/setup/script.h,v
retrieving revision 2.4
diff -u -p -r2.4 script.h
--- script.h	20 Mar 2003 10:02:51 -0000	2.4
+++ script.h	24 Mar 2003 22:04:08 -0000
@@ -33,7 +33,9 @@ class Script {
   public:
     static bool isAScript (String const &file);
     Script (String const &fileName);
-    String baseName()const;
+    String baseName() const;
+    String fullName() const;
+    void run(BOOL to_log = FALSE) const;
   private:
     String scriptName;
 };
Index: threebar.cc
===================================================================
RCS file: /cvs/cygwin-apps/setup/threebar.cc,v
retrieving revision 2.4
diff -u -p -r2.4 threebar.cc
--- threebar.cc	26 Jun 2002 21:35:16 -0000	2.4
+++ threebar.cc	24 Mar 2003 22:04:08 -0000
@@ -172,6 +172,18 @@ bool
       }
     case WM_APP_INSTALL_THREAD_COMPLETE:
       {
+	// Install is complete and we want to go on to the postinstall.
+	Window::PostMessage (WM_APP_START_POSTINSTALL);
+	break;
+      }
+    case WM_APP_START_POSTINSTALL:
+      {
+	// Start the postinstall script thread.
+	do_postinstall (GetInstance (), GetHWND ());
+	break;
+      }
+    case WM_APP_POSTINSTALL_THREAD_COMPLETE:
+      {
 	// Re-enable and "Push" the Next button
 	GetOwner ()->SetButtons (PSWIZB_NEXT);
 	GetOwner ()->PressButton (PSBTN_NEXT);
Index: threebar.h
===================================================================
RCS file: /cvs/cygwin-apps/setup/threebar.h,v
retrieving revision 2.4
diff -u -p -r2.4 threebar.h
--- threebar.h	21 Sep 2002 09:36:46 -0000	2.4
+++ threebar.h	24 Mar 2003 22:04:08 -0000
@@ -32,6 +32,8 @@
 #define WM_APP_START_SETUP_INI_DOWNLOAD    WM_APP+6
 #define WM_APP_SETUP_INI_DOWNLOAD_COMPLETE WM_APP+7
 // desktop.h: WM_APP_UNATTENDED_FINISH WM_APP+8
+#define WM_APP_START_POSTINSTALL           WM_APP+9
+#define WM_APP_POSTINSTALL_THREAD_COMPLETE WM_APP+10
 
 class ThreeBarProgressPage:public PropertyPage
 {


More information about the Cygwin-apps mailing list