Page 1 of 2 12>
Topic Options
#182046 - 2007-10-29 03:10 PM multi threading
vroedie Offline
Fresh Scripter

Registered: 2006-10-05
Posts: 30
Hi,

I was trying to create a script that could multitask. I would like to perform some tasks using psexec but psexec executes every command for every pc one by one. So I started with the follwing testscript:

rem.kix
 Code:
 
break on

$x = 15

global $t

for $y = 0 TO $x STEP 1
? "y = $y"
$t = 0
while $t < 6 AND $y =< $x

call tst.kix
$t = $t + 1

? "t = $t"

loop

sleep 5

next


tst.kix
 Code:
 
break on

sleep 3

$t = $t - 1

exit


but since call executes and then returnes to the script, the counter doesn't work.

any idea's?

regards,

jeroen

Top
#182051 - 2007-10-29 04:14 PM Re: multi threading [Re: vroedie]
Shawn Administrator Offline
Administrator
*****

Registered: 1999-08-13
Posts: 8611
You would have to RUN a seperate instance of kix32.exe to achieve true multi-tasking, like maybe:

RUN "kix32.exe sub.kix"

Here's the challenge though - your instances have no easy way of comunicating back to your main thread, like with using $vars etc. What I've seen done, is to use the registry for this purpose... example:

1) Create your own little subkey somewhere
2) Have each child report a status back to the main thread, using its own value under this subkey.
3) Each child would need some kind of unique identifier so that it will create it own status value (PID?)
4) What happens when the main script dies. The child scripts should terminate if it looses contact with the parent.

All-in-all tricky business - but powerful.

Top
#182055 - 2007-10-29 04:27 PM Re: multi threading [Re: Shawn]
Glenn Barnas Administrator Offline
KiX Supporter
*****

Registered: 2003-01-28
Posts: 4402
Loc: New Jersey
I have a process that kicks off about 50 Kix32 processes via Run. Each process is passed an argument that it uses to create an INI file with it's status & results. (that arg becomes the INI file name.) The child processes create the INI file in the TEMP folder, updating it as they process their task. When the process is done, the last thing id does is to move the INI file to a folder where the parent process is watching for the files to appear. It reads the INI file, updates the common database, and then deletes the file. If there are more systems to process, it spawns off another child task.

I limit the number of child processes to 50, which (in my environment) ramps the CPU utilization to 100%. I process data collection from about 300 servers in about 15 minutes this way. There are a few older systems that take longer, but the bulk are completed quickly.

FWIW - my "parent" process is actually a kix script configured as a system service using SrvAny.

Glenn
_________________________
Actually I am a Rocket Scientist! \:D

Top
#182057 - 2007-10-29 04:43 PM Re: multi threading [Re: Glenn Barnas]
vroedie Offline
Fresh Scripter

Registered: 2006-10-05
Posts: 30
this sounds like the thing I need! what shawn suggested is a "little" over my head! ;\)
any case that you could post this script, Glenn?

regards,

jeroen

Top
#182058 - 2007-10-29 05:58 PM Re: multi threading [Re: vroedie]
Glenn Barnas Administrator Offline
KiX Supporter
*****

Registered: 2003-01-28
Posts: 4402
Loc: New Jersey
The script is proprietary, so can't post it. I can get back here tonight and post some snippets to get you going in the right direction, though.

Glenn
_________________________
Actually I am a Rocket Scientist! \:D

Top
#182062 - 2007-10-29 09:36 PM Re: multi threading [Re: vroedie]
Glenn Barnas Administrator Offline
KiX Supporter
*****

Registered: 2003-01-28
Posts: 4402
Loc: New Jersey
OK - here's a sample of "parent.kix" and "child.kix" that illustrates one way to do this - first, the PARENT script:


; PARENT.KIX ====================================================== 
Break On
; Will spawn off 10 child processes. Each child will take two arguments. The first arg will be 
; the child's ID, the second represents something to do.. 
; The child will perform a task, write the answer to a temporary INI file, then rename the ini 
; file before exiting (simulating lots of work being done by the child, writing much data to the ini file) 
 
; The parent will monitor the folder for the INI files, read them when they appear, and 
; consolidate the data. The INI files will be deleted by the parent process when complete. 
 
$ = SetOption('NoVarsInStrings', 'On')
 
Del '.\Summary.txt'		; start with a fresh "central database" for logging the results 
 
$Data = ' AaAbAcAdAeBaBbBcBdBeCaCbCcCdCeDaDbDcDdDe'
 
$Count = 1				; count of tasks to process 
$Workers = 0				; count of active workers 
 
While $Count < 16			; max of 15 
 
  ; limit number of child processes 
  If $Workers < 10
    ; fewer than 10 workers - start one! 
    ; just a silly command here to pass the count and two characters from the data string 
    ; in real world, A1 would be an ID (as it is here) and A2 might be the name of the remote system 
    ; that the child should interrogate 
    $Command = 'kix32.exe .\child.kix $A1=' + $Count + ' $A2="' + SubStr($Data, $Count * 2, 2) + '"'
    Run $Command			; run asynchronously 
    $Workers = $Workers + 1		; increment the worker count 
    $Count = $Count + 1			; increment the process count 
  EndIF
 
 
  ; Process completed work, allowing more children to run 
  ; any INI files found? 
  $File = Dir('*.ini')
  While $File <> "" and @ERROR = 0
    ; Yes! 
    $Workers = $Workers - 1		; worker completed, reduce the active count 
 
    ; write the data from the child's INI file to the "central database" 
    $ = RedirectOutput('.\summary.txt')
    $File ', '
    ReadProfileString('.\' + $File, 'Common', 'Arg') ?
    $ = RedirectOutput('')
 
    ; remove the worker file 
    Del '.\' + $File
 
    ; check for more as long as we're here.. 
    $File = Dir()  ; retrieve next file 
  Loop
 
  ; display status 
  ' Count: ' $Count ',  Workers: ' $Workers '   ' Chr(13)
 
Loop
 
; no more children to run, need to process remaining files that are waiting for completion 
While $Workers > 0
  $File = Dir('*.ini')
  While $File <> "" and @ERROR = 0
 
    ; found a file - that means a worker completed it's task 
    $Workers = $Workers - 1
 
    ; update the "central database" 
    $ = RedirectOutput('.\summary.txt')
    $File ', '
    ReadProfileString('.\' + $File, 'Common', 'Arg') ?
    $ = RedirectOutput('')
 
    ; delete the worker file 
    Del '.\' + $File
 
    ; Status display 
    ' Count: ' $Count ',  Workers: ' $Workers '   ' Chr(13)
    Sleep 0.2
 
    ; any more files ready? 
    $File = Dir()  ; retrieve next file 
  Loop
Loop
 
?
' Displaying results:' ?
Display 'Summary.txt' ?
 
quit 0
 
 
 

And the CHILD script:


; CHILD.KIX ======================================================= 
; simple example of a child process 
Break On
 
; Args are $A1 and $A2 
 
SRnd(@TICKS)
; simulate doing lots of work... Wait a random amount of time, between 0 and 4 seconds 
Sleep Rnd(4)
 
$IniFile = '.\file_' + $A1
$TmpFile = $IniFile + '.tmp'
$IniFile = $IniFile + '.ini'
 
$ = WriteProfileString($TmpFile, 'common', 'Arg', $A2)
 
; simulate doing more work... 
Sleep Rnd(4)
 
; work is done, no more updates to the INI file, rename it so the Parent will find it 
Move $TmpFile $IniFile
 
; exit success! 
Exit 0
 

The CHILD waits 0-4 seconds, then creates a .TMP file, waits an additional 0-4 seconds (to simulate work communicating to a remote system) and then renames the TMP file to INI before exiting.

PARENT quickly spawns off 10 children, then waits for INI files to appear. Each INI that appears reduces the worker count, allowing more children to be run, until all 15 have completed. The status line shows the count grow from 1-15, and the workers increase to 10, then decrease/increase until all 15 tasks have been initiated, and finally workers decreases to zero.

Again, it's a simple, silly example that illustrates the concept, but should be able to form the building block of what you need. You should probably incorporate a max time limit that you wait for workers to complete, or use some type of process interrogation so you don't wait for children that die before completing their tasks. Unlikely, but possible.

Hope this gets you going in the right direction! I tested this, and it should work to illustrate the concept just fine - using Kix 4.60 here..

Glenn

_________________________
Actually I am a Rocket Scientist! \:D

Top
#182068 - 2007-10-30 12:57 AM Re: multi threading [Re: Glenn Barnas]
Shawn Administrator Offline
Administrator
*****

Registered: 1999-08-13
Posts: 8611
Glenn, should the children worry about the parent dying ? Or should they just carry-on until done. Guess it depends on what whats being done. Never tried but do processes started with RUN terminate when the main script ends ? My guess would be ... not.
Top
#182070 - 2007-10-30 02:26 AM Re: multi threading [Re: Shawn]
Glenn Barnas Administrator Offline
KiX Supporter
*****

Registered: 2003-01-28
Posts: 4402
Loc: New Jersey
I've always written these scripts such that the children are independent of the parent. They carry on even if the parent dies. I don't think it's like Unix, where the child processes don't survive the parent unless started with Exec.

In my example, the children will collect the data even if the parent dies. The next cycle, the parent will most likely simply clean up after the prior process if anything remained. Of course, the new parent could also assume that the prior parent didn't succeed, and could process the files present before creating its own offspring.

Since we don't have the luxury of signals and IPC (that I know of, at least!) within Kix, I just write simple processes. Most are non-critical, so a parent dying would result in no data collection that day - not a crisis. My primary use of this technology is the nightly query of about 300 servers - we gather disk space info, summarize event log warnings/errors, verify scheduled tasks, and a couple of other "server health" items. All gets collected with one collection script per server, run 50 at a time, scheduled similarly to what I illustrated above. 90% of the collection runs in 15 minutes, but we have a few ancient systems that take about 30-40 minutes to complete.

My Kix-based software deployment system works in a similar fashion - a KF GUI is used to stage a web content release - moving files from the dev fileserver to a deployment server (code freeze). Another person runs the KF GUI that initiates the deployment - it takes the GUI input, generates a (temp) INI file with the instructions, and then drops the INII file into a queue folder. The person doing the deploy has A-D rights to run the deploy to QA or PROD, but no logon or share access to the web servers.

The service running on the deploy server sees the new INI file in the queue, determines which environment it is being deployed to, and creates a scheduled event (task, but no trigger) using the appropriate credentials. This is a modification of the "run" concept above, since we need to use an alternate ID. (tried RunNas, but no joy) The service then triggers the task with a RunNow action, starting the actual deploy process. I can kick off about 3 deployments per minute - different releases, different "products", and different environments.

The Staging process is self-contained, but the Deploy GUI, scheduling service, and deploy-job processor all communicate with each other via the job INI file - even to the point of passing interactive status messages back to the GUI. The end-result is then passed back to a status file that the Staging tool can interrogate, displaying the status (pending, queued, success, or failure) of the staged job. As complex as this is, it's tolerant of any component failure - if the service fails, the jobs hold in the queue. If the deploy process fails, the job can be requeued. If the deployment itself fails, the modified files are restored from the ZIP backup.

I'd really like to play with some type of IPC, so two independent processes could more readily commnuicate - in this case, the Deploy Console and the deploy service, then the deploy service and the deploy-job processor. KF sockets, maybe?

G-

PS - aren't ya glad you asked a simple question? ;\)
_________________________
Actually I am a Rocket Scientist! \:D

Top
#182077 - 2007-10-30 09:33 AM Re: multi threading [Re: Glenn Barnas]
vroedie Offline
Fresh Scripter

Registered: 2006-10-05
Posts: 30
Thanks Glenn, this should get me started. Nice!
thank you very much!

regards,

jeroen

Top
#182078 - 2007-10-30 09:59 AM Re: multi threading [Re: vroedie]
vroedie Offline
Fresh Scripter

Registered: 2006-10-05
Posts: 30
one question so far... the parent starts the child processes hidden. Is there a way to have the parent start new windows so I can see the progress of the child processes? I've tried setting the SETCONSOLE("SHOW") option, but no luck.

regards,

jeroen

Top
#182080 - 2007-10-30 10:11 AM Re: multi threading [Re: vroedie]
Richard H. Administrator Offline
Administrator
*****

Registered: 2000-01-24
Posts: 4946
Loc: Leatherhead, Surrey, UK
Try using "%CMD% /C START SEPARATE" in your command line to force a new console.
Top
#182081 - 2007-10-30 10:29 AM Re: multi threading [Re: Richard H.]
NTDOC Administrator Offline
Administrator
*****

Registered: 2000-07-28
Posts: 11631
Loc: CA
 Originally Posted By: Richard H.
Try using "%CMD% /C START SEPARATE" in your command line to force a new console.


Think Richard means

 Code:
"%comspec% /C START SEPARATE"

Top
#182082 - 2007-10-30 10:31 AM Re: multi threading [Re: Richard H.]
vroedie Offline
Fresh Scripter

Registered: 2006-10-05
Posts: 30
thanks. it was "CMD /C START /SEPARATE" though. ;\)

regards,
jeroen

Top
#182084 - 2007-10-30 10:34 AM Re: multi threading [Re: vroedie]
NTDOC Administrator Offline
Administrator
*****

Registered: 2000-07-28
Posts: 11631
Loc: CA
Well forgot the switch / and you can use a direct CMD but using the var %comspec% would be a better practice than a direct call of the name
Top
#182090 - 2007-10-30 12:24 PM Re: multi threading [Re: NTDOC]
vroedie Offline
Fresh Scripter

Registered: 2006-10-05
Posts: 30
I've tried to combine some scripts, so I could read a file with hosts, put those host in an array and then start a child process for each host in the file. Now the script seems to run the script for just the first entry in the file.

 Code:
 
; PARENT.KIX ====================================================== 
Break On
; Will spawn off 10 child processes. Each child will take two arguments. The first arg will be 
; the child's ID, the second represents something to do.. 
; The child will perform a task, write the answer to a temporary INI file, then rename the ini 
; file before exiting (simulating lots of work being done by the child, writing much data to the ini file) 
 
; The parent will monitor the folder for the INI files, read them when they appear, and 
; consolidate the data. The INI files will be deleted by the parent process when complete. 
 
$ = SetOption('NoVarsInStrings', 'On')
 
Del '.\Summary.txt'		; start with a fresh "central database" for logging the results 
 
If Not IsDeclared($Arg) 
	"You must supply a file containing a list of hosts"+@CRLF       
	" Usage: kix32 "+@SCRIPTNAME+" $$Arg=file (in same directory)"+@CRLF        
	Exit 0
EndIf

DIM $list[0]
DIM $ctr, $ctr2
$ctr = 0

IF Open(3, ".\" + $Arg)  = 0

	Dim $x

	$x = ReadLine(3)
				
	   WHILE @ERROR = 0
		
		redim preserve $list[$ctr]
	   	$list[$ctr] = $x
		$ctr = $ctr + 1	
		$x = ReadLine(3)
		
	   LOOP
   
Else 
	"Cannot find file " + $Arg + @CRLF

ENDIF

;$Data = ' AaAbAcAdAeBaBbBcBdBeCaCbCcCdCeDaDbDcDdDe'
 
$Count = 1				; count of tasks to process 
$Workers = 0				; count of active workers 
$ctr2 = $ctr + 1

For Each $Entry in $list
? $Entry + @CRLF
Next

For Each $Entry in $list
 
While $Count < $ctr2			; max of 15 
 

  ; limit number of child processes 
  If $Workers < 10
    ; fewer than 10 workers - start one! 
    ; just a silly command here to pass the count and two characters from the data string 
    ; in real world, A1 would be an ID (as it is here) and A2 might be the name of the remote system 
    ; that the child should interrogate 
		
		;? "Line read: [" + $Entry + "]"
		$Command = '%comspec% /C START /SEPARATE kix32.exe .\child.kix $A1=' + $Count + ' $A2="' + $Entry + '"'
	
    
    Run $Command			; run asynchronously 
    $Workers = $Workers + 1		; increment the worker count 
    $Count = $Count + 1			; increment the process count 
  EndIF

 
  ; Process completed work, allowing more children to run 
  ; any INI files found? 
  $File = Dir('*.ini')
  While $File <> "" and @ERROR = 0
    ; Yes! 
    $Workers = $Workers - 1		; worker completed, reduce the active count 
 
    ; write the data from the child's INI file to the "central database" 
    $ = RedirectOutput('.\summary.txt')
    $File ', '
    ReadProfileString('.\' + $File, 'Common', 'Arg') ?
    $ = RedirectOutput('')
 
    ; remove the worker file 
    Del '.\' + $File
 
    ; check for more as long as we're here.. 
    $File = Dir()  ; retrieve next file 
  Loop
 

 
  ; display status 
  ' Count: ' $Count ',  Workers: ' $Workers '   ' Chr(13)
 
Loop
 
; no more children to run, need to process remaining files that are waiting for completion 
While $Workers > 0
  $File = Dir('*.ini')
  While $File <> "" and @ERROR = 0
 
    ; found a file - that means a worker completed it's task 
    $Workers = $Workers - 1
 
    ; update the "central database" 
    $ = RedirectOutput('.\summary.txt')
    $File ', '
    ReadProfileString('.\' + $File, 'Common', 'Arg') ?
    $ = RedirectOutput('')
 
    ; delete the worker file 
    Del '.\' + $File
 
    ; Status display 
    ' Count: ' $Count ',  Workers: ' $Workers '   ' Chr(13)
    Sleep 0.2
 
    ; any more files ready? 
    $File = Dir()  ; retrieve next file 
  Loop
Loop
 
Next

?
' Displaying results:' ?
Display 'Summary.txt' ?
 
quit 0

Top
#182092 - 2007-10-30 12:53 PM Re: multi threading [Re: vroedie]
Glenn Barnas Administrator Offline
KiX Supporter
*****

Registered: 2003-01-28
Posts: 4402
Loc: New Jersey
Not tested, but try this - simplify! I'll leave it up to you to add some diagnostic messages so you can see what's going on.

Glenn
 Code:
 
; PARENT.KIX ====================================================== 
Break On
; Will spawn off 10 child processes. Each child will take two arguments. The first arg will be 
; the child's ID, the second represents something to do.. 
; The child will perform a task, write the answer to a temporary INI file, then rename the ini 
; file before exiting (simulating lots of work being done by the child, writing much data to the ini file) 
 
; The parent will monitor the folder for the INI files, read them when they appear, and 
; consolidate the data. The INI files will be deleted by the parent process when complete. 
 
$ = SetOption('NoVarsInStrings', 'On')
 
Del '.\Summary.txt'		; start with a fresh "central database" for logging the results 
 
If Not IsDeclared($Arg) 
	"You must supply a file containing a list of hosts"+@CRLF       
	" Usage: kix32 "+@SCRIPTNAME+" $$Arg=file (in same directory)"+@CRLF        
	Exit 0
EndIf

DIM $list[0]
DIM $ctr, $ctr2
$ctr = 0
 
$Count = 1				; count of tasks to process 
$Workers = 0				; count of active workers 
$ctr2 = $ctr + 1


IF Open(3, ".\" + $Arg)  = 0
  $Entry = ReadLine(3)
  WHILE Not @ERROR
 
    ; limit number of child processes 
    If $Workers < 10
      ; fewer than 10 workers - start one! 
      ; just a silly command here to pass the count and two characters from the data string 
      ; in real world, A1 would be an ID (as it is here) and A2 might be the name of the remote system 
      ; that the child should interrogate 
		
      ;? "Line read: [" + $Entry + "]"
      $Command = '%comspec% /C START /SEPARATE kix32.exe .\child.kix $A1=' + $Count + ' $A2="' + $Entry + '"'
	
    
      Run $Command			; run asynchronously 
      $Workers = $Workers + 1		; increment the worker count 
      $Count = $Count + 1			; increment the process count 
    EndIF

 
    ; Process completed work, allowing more children to run 
    ; any INI files found? 
    $File = Dir('*.ini')
    While $File <> "" and @ERROR = 0
      ; Yes! 
      $Workers = $Workers - 1		; worker completed, reduce the active count 
 
      ; write the data from the child's INI file to the "central database" 
      $ = RedirectOutput('.\summary.txt')
      $File ', '
      ReadProfileString('.\' + $File, 'Common', 'Arg') ?
      $ = RedirectOutput('')
 
      ; remove the worker file 
      Del '.\' + $File
 
      ; check for more as long as we're here.. 
      $File = Dir()  ; retrieve next file 
    Loop
 

 
    ; display status 
    ' Count: ' $Count ',  Workers: ' $Workers '   ' Chr(13)
 

    $Entry = ReadLine(3)
		
  LOOP
   
Else 
  "Cannot find file " + $Arg + @CRLF
ENDIF





 
; no more children to run, need to process remaining files that are waiting for completion 
While $Workers > 0
  $File = Dir('*.ini')
  While $File <> "" and @ERROR = 0
 
    ; found a file - that means a worker completed it's task 
    $Workers = $Workers - 1
 
    ; update the "central database" 
    $ = RedirectOutput('.\summary.txt')
    $File ', '
    ReadProfileString('.\' + $File, 'Common', 'Arg') ?
    $ = RedirectOutput('')
 
    ; delete the worker file 
    Del '.\' + $File
 
    ; Status display 
    ' Count: ' $Count ',  Workers: ' $Workers '   ' Chr(13)
    Sleep 0.2
 
    ; any more files ready? 
    $File = Dir()  ; retrieve next file 
  Loop
Loop
 
Next

?
' Displaying results:' ?
Display 'Summary.txt' ?
 
quit 0
_________________________
Actually I am a Rocket Scientist! \:D

Top
#182093 - 2007-10-30 01:09 PM Re: multi threading [Re: Glenn Barnas]
vroedie Offline
Fresh Scripter

Registered: 2006-10-05
Posts: 30
But don't you remove the limit of 15 with this?
Is there a way to do both?
I've tried:

WHILE Not @ERROR
WHILE $Count < $ctr2 OR $Count < 16
code

Loop
Loop

But it keeps the worker on 10.

Jeroen

Top
#182095 - 2007-10-30 02:23 PM Re: multi threading [Re: vroedie]
Glenn Barnas Administrator Offline
KiX Supporter
*****

Registered: 2003-01-28
Posts: 4402
Loc: New Jersey
You don't want a limit of 15 actions, do you? You want to process every element. In my example, I had 15 elements - it was easier to hard-code the elements than to try and provide a data file for you to read, too..

The line
If $Workers < 10
is what controls the number of child worker threads. Change it to
If $Workers < $MaxWorkers
and Dim/define $MaxWorkers at the beginning to limit the number of concurrent child processes running. Like I said, I have it set to 50, which runs the server at 100% CPU load for 10-12 minutes. It's trial and error - My server is dedicated to this task at the time it runs, so, I fully load it to get the job done. If your server is shared, you can keep increasing the MaxWorkers value until you hit 50% load or so .

Bottom line - my "first" outer loop has been modified to run once for each value read from the file, which is what you need in order to process a random number of elements. The middle loop keeps reading the data, and the innermost loop simply keeps the number of child processes at 10 (or, better yet, $MaxWorkers).

Glenn
_________________________
Actually I am a Rocket Scientist! \:D

Top
#182096 - 2007-10-30 02:40 PM Re: multi threading [Re: Glenn Barnas]
Richard H. Administrator Offline
Administrator
*****

Registered: 2000-01-24
Posts: 4946
Loc: Leatherhead, Surrey, UK
Here is another multi-threading example (now with max child control Glenn ;))

This example has the parent and child code in the same script, and takes a list of hosts from the command line and/or a file.

The child code just does a ping on each host and returns the ping time to the parent. The parent displays the colour-coded ping time.

The parent monitors the child and will detect when one takes too long to start (10 seconds) - I haven't included any checks to determine if a child has exited unexpectedly, though you can use the child PID as a lookup in the process table if that is important to you.



Break ON
$=SetOption("Explicit","ON")

; YAPP.kix - Yet Another Parallel Pinger
;
; Pass a comma seperated lists of hostsnames / IP addresses or a list in a file.
; The hosts will be pinged asynchronously, and the results displayed.

; $iMaxChild may also be set on the command line to change the limit of child
; processes which may be active at any time.

; Amendment History
; -----------------
; 20071030.13:00 R. Howarth <rhowarth@harsco.com>
; Added code to limit active child processes.
; Allow debug state to be set on command line.
; Allow maxchild to be set on command line.

If Not IsDeclared($DEBUG)
GLOBAL $DEBUG $DEBUG=0
EndIf
If Not IsDeclared($DEBUG)
Global $iMaxChild $iMaxChild=20
EndIf

Dim $sINI,$sHost,$iChildActive,$vChildPID,$vResponseTime,$vStatusCode,$iStartTicks
Dim $iMaxTicks $iMaxTicks=5000
Dim $iInterval $iInterval="0.1"
Dim $iLastHost
Dim $sActiveList
Dim $sNewList

Dim $sErrorColour, $sNormColour, $sColour

Dim $aiTime $aiTime= Split("-1,100,250,500",",")
Dim $aiColour $aiColour=Split("g+/n,y+/n,y/n,r+/n",",")

Dim $iTimeout $iTimeout=10000 ; Wait 10 seconds for a response

$sErrorColour="r+/n"
$sNormColour="w/n"

Color $sNormColour

If IsDeclared($iParentPID)
; -------------------------------------------------
; CHILD PAYLOAD - code executed for child process
; -------------------------------------------------
$sHost=$sHostList
myDEBUG("Child started for "+$sHostList)
$sINI=@SCRIPTDIR+"\YAPP_"+$iParentPID+".ini"
myDEBUG("Child started for "+$sHostList+", INI="+$sINI)
$=WriteProfileString($sINI,$sHost,"PID",@PID)
$vResponseTime=wmiPing($sHostList,$iTimeout)
$vStatusCode=@ERROR
If $vStatusCode
$vStatusCode=$vResponseTime
$vResponseTime=(-1)
EndIf
$=WriteProfileString($sINI,$sHost,"ResponseTime",$vResponseTime)
$=WriteProfileString($sINI,$sHost,"StatusCode",$vStatusCode)
Else
; -------------------------------------------------
; PARENT PAYLOAD - code executed for parent process
; -------------------------------------------------
$sINI=@SCRIPTDIR+"\YAPP_"+@PID+".ini"
Del $sINI
If Not IsDeclared($sHostList) AND Not IsDeclared($sFile)
"You must supply a comma seperated list of hosts to ping or a file containing a list"+@CRLF
" Usage: kix32 "+@SCRIPTNAME+" [$$DEBUG=0|1] [$$iMaxChild=20] $$sHostList=hostname[,hostname...] $$sFile=path_to_file"+@CRLF
Exit 0
EndIf
If Not IsDeclared($sHostLIst) Global $sHostList EndIf
If IsDeclared($sFile)
Dim $fhFile
$fhFile=FreeFileHandle()
If Open($fhFile,$sFile)
"Cannot open "+$sFile+" for reading"+@CRLF
Exit 1
EndIf
$sHost=ReadLine($fhFile)
While Not @ERROR
$sHostList=$sHostList+","+$sHost
$sHost=ReadLine($fhFile)
Loop
EndIf
$sHostList=Split($sHostList,",")
While $iChildActive OR $iLastHost<UBound($sHostList)
If ($iChildActive<$iMaxChild) AND $iLastHost<UBound($sHostList)
$iLastHost=$iLastHost+1
$sHost=$sHostList[$iLastHost]
If $sHost
myDEBUG("Starting "+$sHost)
$=WriteProfileString($sINI,$sHost,"PID","Pending")
$=WriteProfileString($sINI,$sHost,"StartTicks",@TICKS)
RUN @SCRIPTEXE+" "+@SCRIPTNAME+" $$iParentPID="+@PID+" $$sHostList="+$sHost
$iChildActive=$iChildActive+1
$sActiveList=$sActiveList+","+$sHost
EndIf
EndIf
myDEBUG("Active list: "+$sActiveList)
$sNewList=""
For Each $sHost in Split(SubStr($sActiveList,2),",")
If $sHost
$vStatusCode=ReadProfileString($sINI,$sHost,"StatusCode")
$vResponseTime=ReadProfileString($sINI,$sHost,"ResponseTime")
$vChildPID=ReadProfileString($sINI,$sHost,"PID")
$iStartTicks=ReadProfileString($sINI,$sHost,"StartTicks")
myDEBUG($sHost+": Status "+$vStatusCode)
myDEBUG($sHost+": Response "+$vResponseTime)
myDEBUG($sHost+": PID "+$vChildPID)
Select
Case $vChildPID="Completed"
; No action for completed processes
Case $vChildPID="Pending" AND (@TICKS-$iStartTicks)>$iMaxTicks
Color $sErrorColour "Child process for "+$sHost+" has failed to start in time" Color $sNormColour @CRLF
$iChildActive=$iChildActive-1
$=WriteProfileString($sINI,$sHost,"PID","Completed")
Case $vChildPID<>"0" AND $vStatusCode<>""
$=WriteProfileString($sINI,$sHost,"PID","Completed")
$iChildActive=$iChildActive-1
If $vStatusCode="0"
$sColour=$aiColour[0]
For $ = 0 To UBound($aiTime)
If CINT($vResponseTime)>=$aiTime[$] $sColour=$aiColour[$] EndIf
Next
Color $sColour $sHost+" responded in "+$vResponseTime+" ms" Color $sNormColour @CRLF
Else
Color $sErrorColour $sHost+" failed to respond, error code is "+$vStatusCode Color $sNormColour @CRLF
EndIf
Case "StillRunningOrPending"
$sNewList=$sNewList+","+$sHost
EndSelect
EndIf
Next
$sActiveList=$sNewList
If $iChildActive Sleep($iInterval) EndIf
Loop
Del $sINI
EndIf

Exit 0

Function wmiPing($sHost,Optional $Timeout)
Dim $sQuery,$oWMI,$oItem,$cItems
$sQuery = "Select ResponseTime,StatusCode From Win32_PingStatus where Address='" + $sHost + "'"
If $Timeout
$sQuery = $sQuery + " And TimeOut=" + $Timeout
EndIf
$oWMI = GetObject("winmgmts:root\cimv2")
$cItems = $oWMI.ExecQuery($sQuery)
For Each $oItem In $cItems
If (VarTypeName($oItem.StatusCode) = 'Null') $wmiPing=1 Exit 1 EndIf
If $oItem.StatusCode $wmiPing=$oItem.StatusCode Exit 1 EndIf
$wmiPing = $oItem.ResponseTime
Next
Exit 0
EndFunction

Function myDEBUG($s)
If $DEBUG "DEBUG: "+$s+@CRLF EndIf
EndFunction
; vim: sw=4 ts=4


Top
#182100 - 2007-10-30 04:59 PM Re: multi threading [Re: Glenn Barnas]
vroedie Offline
Fresh Scripter

Registered: 2006-10-05
Posts: 30
ok, I thought the "While $Count < 16 ; max of 15 " part was for the max number of processes. the problem I'm having, when I remove this part, is that only 10 processes run. even when the other processes stop, no new processes are started.

regards,

jeroen

Top
Page 1 of 2 12>


Moderator:  Glenn Barnas, NTDOC, Arend_, Jochen, Radimus, Allen, ShaneEP, Ruud van Velsen, Mart 
Hop to:
Shout Box

Who's Online
0 registered and 580 anonymous users online.
Newest Members
Sir_Barrington, batdk82, StuTheCoder, M_Moore, BeeEm
17886 Registered Users

Generated in 0.074 seconds in which 0.024 seconds were spent on a total of 14 queries. Zlib compression enabled.

Search the board with:
superb Board Search
or try with google:
Google
Web kixtart.org