oood.py is a daemon, which controls a pool of 'anonymous' office instances (workers).
The workers can be used as backend for Java/python/C++ batch processes for document conversion, mail merges, etc. You don't need to rewrite your current scripts, a client connects to a daemon-controlled office just as if would connect to a normal office. Up to now, I only checked the functionality for batch clients, for server clients (e.g. a tomcat or zope), there may be some problems, you should simply try it.
The daemon ensures, that only one client at a time is connected to one OpenOffice instance (because one OOo instance in general can't cope with more than one scripter). Workers get restarted after a certain amount of uses or after office crashes.
A client can connect to a daemon as if it would connect to a normal 'non-daemoned' office, so you don't need to adapt your scripts.
oood.py has been implemented in pure python, but it uses some office components. This should make it easy to modify the daemon to your needs if desired.
Download: oood-0.1.0.zip (less than 10k):
The daemon and this document is targeted at experienced OOo script developers.
However, some simple limitations can be done.
(use 01 instead of XX)
$ setup -d /home/oood/ooo1.1_srvXX
from within the office/program directory. After the setup run, edit ~/.sversionrc file and replace "OpenOffice.org 1.1.0" with "OpenOffice.org 1.1.0_srvXX". . Repeat these steps with XX = 02, 03, ... . You need as many installations as you expect concurrent users. You may also start with a low number and add instances later on. Afterwards, your .sversionrc file should look like
[Versions] OpenOffice.org 1.1 srv01=file:///home/oood/ooo1.1_srv01 OpenOffice.org 1.1 srv02=file:///home/oood/ooo1.1_srv02 OpenOffice.org 1.1 srv03=file:///home/oood/ooo1.1_srv03
$ ./python oood-0.1.0/oood.py -c oood-0.1.0/oood-config.xml run
You get the log on the stdout blocking the shell. Depending on the number of workers you have configured, it may take quite a while to start. When you get aAccepting on <your-connection-string>
the daemon is ready to serve requests.$ ./python oood-0.1.0/bin/oood.py -c oood-0.1.0/config/oood-config.xml stop
Signals the daemon to terminate all running workers and itself. The daemon can only be stopped this way after a successful startup.
$ ./python oood-0.1.0/oood.py -c oood-0.1.0/oood-config.xml status
Gives you a list of workers and their state.
The daemon delegates your request to one of its worker offices. For the time of usage, this worker office is exclusively used by your client program. The end of usage is detected by the daemon through a breakdown of the interprocess bridge (which occurs, when the last reference is gone, the client explicitly disposes the remote bridge or the client process terminates).
There is 3 log levels.
SERIOUS | Only startup information and errors get written into the log |
INFO | information about every connect and disconnect get logged (default) |
DETAIL | Log level mostly sensible for debugging |
Level INFO includes SERIOUS, DETAIL includes INFO and HIGH.
current-time [loglevel] : LogtextThe numbers in curly brackets (e.g. {2/5}) in the logtext signals the free/total number of worker processes in the pool .
Wed Nov 26 19:11:19 2003 [SERIOUS]: Started on pid 674 Wed Nov 26 19:11:19 2003 [INFO ]: Starting office workers ... Wed Nov 26 19:11:19 2003 [INFO ]: Worker-0:<oood.OfficeProcess file:///home/joergl/OpenOffice.org1.1.0_instance-0; pid=692;connectStr=pipe,name=oood-instance-0,usage=0> started Wed Nov 26 19:11:59 2003 [INFO ]: {2/2} WorkerAll instances started Wed Nov 26 19:11:59 2003 [SERIOUS]: Accepting on socket,host=localhost,port=2002;urpFirst line gives the pid of the daemon process (in case you want to terminate the process during startup). Then follows for every worker process, that gets started a line showing the used home directory and connection string.
Wed Nov 26 19:24:02 2003 [INFO ]: {1/2} -> Worker-0(1 uses) serves localhost:32770 Wed Nov 26 19:24:13 2003 [INFO ]: localhost:32770 disconnects from Worker-0(1 uses) (used for 10.7s) Wed Nov 26 19:24:13 2003 [INFO ]: {2/2} <- Worker-0(1 uses) reenters poolFirst line states that out of the pool Worker-0 1is used to serve the incoming request from localhost:32770. The {1/2} indicates, that there one free worker left is in the pool. Second line states, that the interprocess bridge between the daemon and the requesting process has broken down. Additionally, the number of uses and the duration of the last use in seconds is shown. In case, the number of uses is less than the max-usage-count-per-instance, the process is simply added to the pool of available offices again (as it documented by the third line. The {2/2} states, that there are now exactly two workers in the pool again. In case the max-usage-count-per-instance is exceeded, this worker instance is automatically terminated and a fresh instance is restarted. This shall tide up memory leaks. When there is no free worker left anymore and a client request comes in, the request is rejected and a line like the following gets logged:
Sat May 22 22:28:46 2004 [SERIOUS]: {0/2} localhost:32776 rejectedThe client script simply gets a empty reference instead of the requested object.
Note: Preferably it would receive a RuntimeException with an appropriate message, but a bug somewhere around pyuno, the scripting components and the remote bridge currently prevents this (the daemons crashes quite fast).
Sat May 22 22:33:00 2004 [SERIOUS]: Accepting on socket,host=localhost,port=2002;urp stopped, waiting for shutdownthread Sat May 22 22:33:00 2004 [INFO ]: Admin thread terminating Sat May 22 22:33:00 2004 [INFO ]: terminating Worker-0(1 uses) Sat May 22 22:33:00 2004 [INFO ]: Worker-0(1 uses) terminated Sat May 22 22:33:00 2004 [INFO ]: terminating Worker-1(1 uses) Sat May 22 22:33:00 2004 [INFO ]: Worker-1(1 uses) terminated Sat May 22 22:33:00 2004 [SERIOUS]: Terminating normally
Note: Preferably it would receive a RuntimeException with an appropriate message, but a bug somewhere around pyuno, the scripting components and the remote bridge currently prevents this (the daemons crashes quite fast).
The connection attempt gets logged appropriately.
The check is currently quite rudimentary, it may be improved in future.