And just to make sure everyone gets credit where it's due, most of the code
for the error handler was taken from Michael Peppler's work on DBD::Sybase.
The async stuff was just a kludge so I could get status messages while the
query is still running.

On Wed, Aug 28, 2002 at 08:40:14AM -0400, Jeff Urlwin <[EMAIL PROTECTED]> wrote:
> Steve -- thanks -- but please credit David L. Good for the async processing
> and the error handler (among other things)!  I just incorporated his work.
> 
> Nice script and thanks for posting.  I've taken the liberty of cross-posting
> to [EMAIL PROTECTED] where that group may find this interesting, also.  I
> really like the use of the closure, too.
> 
> Regards,
> 
> Jeff
> 
> >
> > Thanks to the excellent work of Mr. Urlwin in providing us an
> > error checker
> > in DBD::ODBC where we can get back all informational messages
> > from commands
> > (such as dbcc), I can get rid of all those old OSQL scripts for
> > maintenance,
> > and I can overcome another difficulty - multiple "Very Large" databases on
> > servers that all must be maintained in a small maintenance window
> > allowed by
> > our contract. By using a Perl fork, and Mr. Urlwin's error checker, I can
> > turn my maintenance jobs into an organized, multi-threaded process which
> > will greatly reduce the amount of time required to perform the
> > maintenance,
> > and log the results, and condense the logs into our web-page (that our DBA
> > staff looks at to see all the servers, and all the databases' maintenance)
> > database all in one nice step.
> >
> > I know I am not the only DBA that has problems of large databases - small
> > maintenance windows, and single threads on high-performance
> > multi-processor,
> > multi-raid 0+1 machines, so I thought I would post a short example here of
> > how to multi-thread the maintenance, and handle the output. I am posting
> > just in hope that someone will find this helpful.
> >
> > Note, however, that if you shouldn't do this if you use Win32, or
> > any of its
> > sub-components anywhere in your script (unless you know something
> > I don't).
> > I have never been able to make Win32 and fork play nicely
> > together. Whenever
> > I absolutely must use Win32, I can simulate this by arranging the code so
> > that I can open multiple process pipes (I've read the documentation for
> > Win32::Process which sounds like it would operate like pipes with a few
> > extra nice features, but I have never used that module).
> >
> > Anyway, enough talk, here is the example I wanted to post for
> > whomever might
> > find it useful:
> >
> >
> >
> > #! perl -w
> >
> > use strict;
> >
> > # pretend like I'm going to process large databases:
> >
> > my @databases = qw(northwind pubs master);
> >
> > # I need to track what PIDS I fork.
> > my @pids;
> >
> > # spawn a separate thread for each database to be processed:
> >
> > foreach (0 .. $#databases)
> > {
> >     my $pid = fork();
> >
> >     # using fork, the spun off pid is returned to the parent proccess.
> >     # therefore, if pid has a value, this is the parent process
> >     # if it does not, it is the child process, and we need it to get to
> > work:
> >
> >     CheckDb($databases[$_]) if ! $pid;
> >
> >     # child processes should never arrive here. They will exit in the
> > subroutine.
> >     # keep track of all pids for whose finish we will need to wait.
> >
> >     push (@pids, $pid);
> > }
> >
> > # only the parent process should arrive here.
> > # child processes should exit at the end of the subroutine.
> >
> > # cleanup nicely before exiting:
> >
> > waitpid($_, 0) foreach @pids;
> >
> > # show a finish message:
> >
> > die "Complete";
> >
> >
> > sub CheckDb
> > {
> >     # only the child processes should arrive here.
> >     use DBI;
> >     my $dbh = DBI->connect('DBI:ODBC:northwind', 'sa', 'changed');
> >
> >     # initialize the closure with our database name, and it will
> > return the
> > reference
> >     # to the error handler subroutine with our database name as
> > part of the
> > error msg.
> >
> >     $dbh->{odbc_err_handler} = err_handler($_[0]);
> >     $dbh->{odbc_async_exec} = 1;
> >
> >     # execute the checkdb on this database:
> >
> >     my $sth = $dbh->prepare("DBCC CHECKDB('$_[0]')");
> >     $sth->execute();
> >
> >
> >     # failure to explicitly disconnect when running multiple threads
> > sometimes
> >     # causes a runtime memory read/write error.
> >     $dbh->disconnect();
> >
> >
> >     # we do not want a child process to return. We want them to exit here.
> >
> >     exit (0);
> >
> > }
> >
> >
> > # use a closure to initialize the data such as what database is being
> > processed.
> > # the error_handler wants a reference to a subroutine, and a closure will
> > return
> > # a reference to a subroutine, initialized with the data we passed in
> > calling the
> > # outer subroutine.
> >
> > sub err_handler {
> >     my $db = $_[0];
> >     use DBI;
> >     my $dbh = DBI->connect('DBI:ODBC:WebSite', 'MaintJob', 'changed');
> >
> >     # ODBC RPC to a stored procedure which will compare this message
> >     # with our normalmessages table, and record it in the
> > logmessages table
> >     # if we have not already identified this pattern as a normal or "info
> > only"
> >     # message.
> >
> >     my $sth = $dbh->prepare(qq/{Call ProcessMessage(?, ?)}/);
> >     # we have our data prepared. now return a reference to an anonymous
> > subroutine
> >     # which will actually be the error handler.
> >     return sub
> >     {
> >         my ($state, $msg) = @_;
> >         # Strip out all of the driver ID stuff
> >         $msg =~ s/^(\[[\w\s]*\])+//;
> >         # for our use here, display the message that will be logged:
> >         print "$db: $msg\n";
> >         # for to be condensed onto our website so our DBA's can review
> >         # when they arrive in the morning:
> >         $sth->execute($db, $msg);
> >         return 0;
> >     }
> > }
> >
> >
> >
> > _______________________________________________
> > Perl-Win32-Database mailing list
> > [EMAIL PROTECTED]
> > To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
> >
> 

-- 
David Good                                                    [EMAIL PROTECTED]

                 This space intentionally left blank.

Reply via email to