Jump to content

Recommended Posts

Posted (edited)

Pool provides multiple AutoIt processes with an infrastructure for exchanging messages, data, and remote-control instructions, on a single machine or on a local area network. It is modelled partly on HTCondor, but also incorporates user-defined messages (UDM), LANchat, mails, data Container shipping management, and remote power control and remote execution. That last feature means one process can send lines of AutoIt script to another process, and run it there (including batch control and synchronisation). Consider it my take on inter-process communication (IPC).
 
Pool incorporates many contributions (a few are included in the bundle, other tiny snippets are part of the main script), from other forum members without whom this project simply would never even have been conceivable. In particular, I hereby want to acknowledge the excellent work of Zatorg, wraithdu, W0uter, Ward, ValeryVal, spudw2k, trancexx, This-is-Me, Nomad, Nine, Manadar, LazyCat, Lakes, Kip, Kealper, Jos, Greencan, FredAI, evilertoaster, dragan, Chimp, and AdamUL. Some codes merely helped to clarify my novice understanding of various IPC issues, others have been gratefully integrated. Three contributors need special mention: Kip & Zatorg for event-driven TCP, and trancexx for MailSlot; together these form the backbone of everything else. The only reason I still dare to publish this under my own name is because I did add over ten thousand lines of code myself. Nevertheless, Pool may serve as a showcase for how various members' example scripts can be combined into a comprehensive environment. Many, many thanks to everyone involved! :thumbsup:
 
Pool is designed to be simple to use. Only a few functions are public, and of those, you really only need to study these four control UDFs:
_Pool_Send_Command(): Pool's Command & Control Centre (see list of commands below)
_Pool_Send_UserDefinedMsg(): define your own outgoing msgs
_Pool_Receive_UserDefinedMsg(): process your own incoming msgs
_Pool_Send_ExeQcall(): send one or more AutoIt instructions to target's Exe-Queue (ExeQ)
 
and these ones for data transfers:
_Pool_Container_Create(): associate shipping Container with data
_Pool_Container_Destroy(): release Container memory and all associated Sharing relations
_Pool_Container_CreateShare(): associate destination with Container
_Pool_Container_DestroyShare(): dissolve sharing association for destination
 
To get an idea of what _Pool_Send_Command() can do, here's the list of commands:
 

 

  Reveal hidden contents

* Pool Control

"Ping" ; test presence, determine Pool-Msg turnaround time
"StandBy" ; defer TODOlist/ExeQ processing
"Proceed" ; resume TODOlist/ExeQ processing
"SyncWait" ; PARAM=syncID; Standby until SYNC_RESUME with same syncID received
"SyncResume" ; PARAM=syncID; Standby until SYNC_RESUME with same syncID received
"Identify" ; tell msg recipient to mail its own PML entry to msg sender
"Uptime" ; return uptime
"Mute" ; PARAM=T/F; T: defer outgoing messages; F: resume
"LeaveNow" ; leave Pool immediately; Exit unless $_POOL_STATUS_STAYALIVE = True
"LeaveWhenDone" ; leave Pool once all current tasks are completed (no reverse transfers afterwards)
"CountMembers" ; update various PML-based membership counters
"ListLocalMembers" ; return entire PML
"AddMembers" ; PARAM=number; tell MGR to start N more default processes locally
"AddMaxMembers" ; tell MGR to start new default Pool processes up to the number of CPU cores
"RemoveMember" ; tell TARGET process(!) to tell all COLLECTORS

* Power-related

"MachineWakeUp" ; triggers Wake-on-LAN magicpacket (untested)
"MachineStandBy" ; place target's machine in StandBy mode
"MachineSuspend" ; place target's machine in Hibernation
"MachineShutDown" ; power down target's machine (target calls Pool_Closedown too)
"MachineReboot" ; reboot target's machine (target calls Pool_Closedown too)

* MailSlot-related (call _Pool_Send_Mail() to send your own, user-defined mails)

"MailTest" ; send a Mail (with double echo)
"Scan4MailSlots" ; detect new MailSlots on localhost
"DestroyMailSlot" ; close MailSlot
"CreateMailSlot" ; create a new MailSlot

* ExeQ-related (call _Pool_Send_ExeQcall() to parse a single cmd or multi-line batch job)

"ClearExeQ" ; release all ExeQ contents
"IamYourMaster" ; for BDSM lovers
"IamYourSlave" ; ditto
"IamNotYourSlave" ; for the rest of us
"ExeQReportState" ; returns IPTR/ExeQ size, stored in PML
"ExeQReportBatch" ; returns target's current batch markers, stored in $_POOL_STATUS_EXEQ_BATCH_START/END
"ExeQIgnoreErrors" ; PARAM = T/F; break ExeQ running on @error
"ExeQBatchStart" ; use this ONLY before supplying batch contents one line at a time
"ExeQBatchEnd" ; use this ONLY after supplying batch contents one line at a time
"Run" ; start/resume execution until end of ExeQueue/currently defined batch
"Break" ; interrupt batch execution a.s.a.p.
"RunNext" ; execute the contents of $_Pool_ExeQueue[$_POOL_STATUS_EXEQ_IPTR]
"RunBatch" ; execute all lines of a defined ExeQ batch
"RunFrom" ; execute from the specified ExeQ line to the end
"RunPrev" ; execute last-previously executed line again
"RunAll" ; (re)run from first line of ExeQ to the end
"SetExeQptr" ; PARAM low word = IPTR (ExeQ instruction pointer)

* Container-related (requires prior creation of data Container and at least one Share)

"RequestContainerID" ; ask local MGR to provide IDs before creating Containers (much faster)
"LoadContainer" ; PARAM = structID; tell CLN to load specified Container with associated data, but do not send it (yet)
"LoadSendContainer" ; PARAM = structID; tell CLN to load specified Container with associated data, and send it
; if targetID = Creator: send out to all defined shares
; if targetID = sharer: return data to Creator
"SendContainer" ; PARAM = structID; tell CLN to send specified Container without reloading it first
; if targetID = Creator: send out to all defined shares
; if targetID = sharer: return data to Creator
"SendContainerAsMail"; PARAM = structID; tell CLN to send specified TINY Container via MailSlot, without reloading it first
"LoadSendContainerAsMail" ; PARAM = structID; tell CLN to reload and send specified TINY Container via MailSlot
"PrepContainerTtransfers" ; PARAM = structID; tell CLN to (re)activate all Shares for specified Container (sets all Share Transfers as "pending")
"DestroyContainer" ; PARAM = structID; release specified Container only
"ReleaseAllContainers" ; release all Containers (variables themselves remain intact)

* TCP/UDP-related

"NewPort" ; PARAM=new port; assign new port for TCP/UDP (requires both protocols to be currently disabled)
"TCPconnect" ; for MGRs/testing only; NB this would be impossible to receive without the MailSlot alternative
"TCPdisconnect" ; for MGRs/testing only
"TCPmultiMsgDelay" ; PARAM = delay in ms; adjust target's $_POOL_STATUS_TCP_MULTIMSG_DELAY
"WMmultiMsgDelay" ; PARAM = delay in ms; adjust target's $_POOL_STATUS_WMULTIMSG_DELAY
"UDPconnect" ; for MGRs/testing only
"UDPdisconnect" ; for MGRs/testing only
"UDPbaseDelay" ; PARAM = delay in ms; adjust target's $_POOL_STATUS_UDP_BASEDELAY
"UDPstepDelay" ; PARAM = delay in ms; adjust target's $_POOL_STATUS_UDP_STEPDELAY
"UseTCPforDataTransfers" ; switch to TCP packets per target MGR for shipping Containers
"UseUDPforDataTransfers" ; switch to UDP packet broadcasting for shipping Containers


 
Pool is big. It has got many dozens of fixed and dynamic user-defined settings to create specific applications with (see #Region Globals). Please take the time to read the extensive Remarks section at the top of the main script (Pool.au3), including the warnings and limitations. Furthermore, I've provided two example environments in the subdir Examples in the bundle: CLNtest (messages and remote execution) and CLNmaster + CLNslave (data Container shipping). If you run these on a single machine, you'll need to start PostOffice_Solo; on multiple machines, one should start first with PostOffice_Server, the rest with PostOffice_Client, once the Server is initialised. See the readme.txt in the Examples subdir for additional help. Another example (multi-processing a la Condor) is shipped with release 2.4+ of Eigen4AutoIt.

Since this is an Example script, you can find a number of interesting design ideas in Pool:

 

 

  Reveal hidden contents

* Containers can be retrieved without ever having been sent out first

* TODO list processing can defer tasks with task-specific retry-expiry

* the three main Pool 2D arrays (PML, PSL, PSC) are accessed by column Name, without having to know the column index (like a database)

* you can switch between TCP (host-targeted) and UDP (broadcast) for data transfers

* handling of subnet masks other than 255.255.255.0 (look for _CIDR_PREFIX)

* using a hexstring for checksum bitflags (see _Pool_PrepChecksum, _Pool_SetChecksum, etc)

* TCP socket buffer + event processing can handle stacked and partial messages

* resend data slice msgs use slice multiplexing with data-dependent granularity

 

 Pool.v0.7.7z Pool bundle, second beta release, version 0.7

:construction:   IMPORTANT CAVEAT  :construction:

This is an experimental beta release. Some parts of Pool have never been tested, others only in the simplest possible setting (the largest network I ever tested comprised one desktop and three laptops (one with busted radio) on a crappy Wifi router; I've never tested it on a cabled network). The (W)LAN part still has many issues and may not be able to handle more than a few machines. There's no callstack error handler. Event-driven TCP remains glitchy, and some of my MailSlots keep malfunctioning. I also lack access to Windows 8.* test environments.

In addition, many issues you may encounter will be due to specific timings/event sequencing (which makes it hard to debug) and/or your specific infrastructure. That means that, most likely, I cannot recreate your Pool bugs (even with your scripts), so I cannot fix them either. Therefore, I will not be offering bug support for users at this point; there's still far too much I need to fix in my own environment to worry about yours, I'm sorry (also, I've been working on this for four months flat, and need a break from it). However, I am of course open to suggestions, remarks, criticism, and kind words (preferably the latter ;) ).

Finally, I will be exceptionally busy with work for the foreseeable future, so it may take me more time than in the past to respond to your posts.

Have fun playing in the Pool.

Edited by RTFC
  • 8 months later...
Posted

I was given the impression of late that Pool.au3 looks too complicated to engage with, so I thought I'd post one of the bundled examples, to show that it's actually really simple to use.

A Pool script consists of a few steps:

  1. define what type of Pool entity the script is going to be (a Post Office, client, master, slave...)
  2. call _Pool_StartUp()
  3. perform pool actions with _Pool_Send_Command ( $targetID, <pool command>, see full listing in Pool.au3 Remarks section)
  4. call _Pool_CloseDown()

Per machine, you need one Post Office script (already running), and as many Pool clients as you like.

Furthermore- if you wish to send data from one script to another (on the same machine or on a network), you additionally need to:

  1. create a shipping container for it (with _Pool_Container_Create());
  2. define a "Share" relationship for the Container, that is, tell Pool where it needs to go (with _Pool_Container_CreateShare()); and
  3. load the Container with data and send it, with _Pool_Send_Command ( $containerID, "LoadSendContainer")

That's basically it.

 

So here's a simple Pool client script (included in the bundle) that communicates with other Pool clients (start at least two instances of this), and which can send and remotely execute AutoIt calls at the destination. Below it you'll find a Post Office script that handles all comms between clients on a machine (with thanks to Melba23 for auxiliary function _MemoWrite).

  Reveal hidden contents

 

And the Post Office script:

  Reveal hidden contents

 

The master/slave example scripts in the bundle show how to parse variables, arrays, strings, structs, etc. between scripts.

Hope it helps.:closedeyes:

PS this project is still in developmental limbo, so the example scripts and Remarks still constitute my only support for this, sorry.:(

Posted

it fails and without support I'll find myself writing one from scratch based on your code.

---------------------------
AutoIt Error
---------------------------
Line 4490  (File "G:\au3s\Pool.v0.6\Pool\Pool.au3"):
$_Pool_MemberList[$memberindex][_Pool_GetPMLcol("Mail Errors")]=0
$_Pool_MemberList[^ ERROR
Error: Variable used without being declared.
---------------------------
OK   
---------------------------

=(

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Posted (edited)

Happy New Year, argumentum.:D

I've got to hand it to you, you're good at finding bugs in my code.:> You could earn good money with that kind of skill, you know? And because it's a special day today, and I'm feeling exceptionally generous, I've uploaded a bug-fixed beta version 0,7, (to be honest, it was a trivial oversight on my part, patched in 10 seconds).

 

Edited by RTFC
  • 7 years later...
Posted

At the moment I'm using the HTTPAPI server and have prescripted endpoints that I send requests to (each "agent" (slave in POOL terminology) computer on the LAN has the HTTPAPI server running as a service, and it catches the requests, adds them to queue.

Each request is a POST with a request body containing the AutoIt script I want to run as a string. The agent parses the request body, compiles it into an EXE file and 'RunWait's it. It sends the exit code and errors, if any, back as an HTTP response to the "master" system).

I've also figured out a way for the  "Master" to broadcast commands to all the systems on LAN (for example, to update an application) using ChildProc + HTTP requests (spawns a new process for each HTTP request).

How would POOL be an improvement over my rather rudimentary methods?

Posted
  On 10/3/2023 at 7:08 AM, noellarkin said:

are you still using/maintaining this UDF

Expand  

Errrm, not actively, no, sorry (not much community interest over the last few years either, until your post). I now require a much faster, secure, high-throughput data transfer utility across WAN, one that an AutoIt solution simply cannot provide (it needs to run across platforms, not just on Windows, and without a single authority), so I cobbled together a C++ P2P solution that I am unable to make available for general use at this time.:(

  On 10/3/2023 at 7:17 AM, noellarkin said:

How would POOL be an improvement over my rather rudimentary methods?

Expand  

POOL-parsed scripts do not need to be compiled, and don't spawn separate processes for each request (but maybe that's part of your requirements, in which case it's a feature Pool lacks, it all depends on your use case). And it doesn't sound like your methods are rudimentary at all, more like you've developed a completely different, sophisticated way to achieve your goals.:thumbsup:

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...