From: miker Date: Thu, 16 Oct 2008 19:29:12 +0000 (+0000) Subject: branching version 1.0 X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=72b771ce3b0007a692b9ed464d5a6393c8a7f3df;p=OpenSRF.git branching version 1.0 git-svn-id: svn://svn.open-ils.org/OpenSRF/branches/rel_1_0@1453 9efc2488-bf62-4759-914b-345cdb29e865 --- diff --git a/trunk/AUTHORS b/trunk/AUTHORS new file mode 100644 index 0000000..5650c91 --- /dev/null +++ b/trunk/AUTHORS @@ -0,0 +1 @@ +#AUTHORS diff --git a/trunk/COPYING b/trunk/COPYING new file mode 100644 index 0000000..6235a64 --- /dev/null +++ b/trunk/COPYING @@ -0,0 +1,17 @@ + Copyright (C) 2005-2007, Georgia Public Library Service and others + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, + MA 02111-1307 USA + diff --git a/trunk/ChangeLog b/trunk/ChangeLog new file mode 100644 index 0000000..3323187 --- /dev/null +++ b/trunk/ChangeLog @@ -0,0 +1 @@ +#ChangeLog diff --git a/trunk/DCO-1.1.txt b/trunk/DCO-1.1.txt new file mode 100644 index 0000000..c729097 --- /dev/null +++ b/trunk/DCO-1.1.txt @@ -0,0 +1,29 @@ + +Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +(b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. + +Signed-off-by: [submitter's name and email address here] + diff --git a/trunk/INSTALL b/trunk/INSTALL new file mode 100644 index 0000000..d3c5b40 --- /dev/null +++ b/trunk/INSTALL @@ -0,0 +1,237 @@ +Installation Instructions +************************* + +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, +2006, 2007 Free Software Foundation, Inc. + +This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + +Basic Installation +================== + +Briefly, the shell commands `./configure; make; make install' should +configure, build, and install this package. The following +more-detailed instructions are generic; see the `README' file for +instructions specific to this package. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. Caching is +disabled by default to prevent problems with accidental use of stale +cache files. + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You need `configure.ac' if +you want to change it or regenerate `configure' using a newer version +of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. + + Running `configure' might take a while. While running, it prints + some messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + + 6. Often, you can also type `make uninstall' to remove the installed + files again. + +Compilers and Options +===================== + +Some systems require unusual options for compilation or linking that the +`configure' script does not know about. Run `./configure --help' for +details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c99 CFLAGS=-g LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + +You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you can use GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + With a non-GNU `make', it is safer to compile the package for one +architecture at a time in the source code directory. After you have +installed the package for one architecture, use `make distclean' before +reconfiguring for another architecture. + +Installation Names +================== + +By default, `make install' installs the package's commands under +`/usr/local/bin', include files under `/usr/local/include', etc. You +can specify an installation prefix other than `/usr/local' by giving +`configure' the option `--prefix=PREFIX'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +pass the option `--exec-prefix=PREFIX' to `configure', the package uses +PREFIX as the prefix for installing programs and libraries. +Documentation and other data files still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=DIR' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + +Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + +There may be some features `configure' cannot figure out automatically, +but needs to determine by the type of machine the package will run on. +Usually, assuming the package is built to be run on the _same_ +architectures, `configure' can figure that out, but if it prints a +message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the option `--target=TYPE' to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + +If you want to set default values for `configure' scripts to share, you +can create a site shell script called `config.site' that gives default +values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + +Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +causes the specified `gcc' to be used as the C compiler (unless it is +overridden in the site shell script). + +Unfortunately, this technique does not work for `CONFIG_SHELL' due to +an Autoconf bug. Until the bug is fixed you can use this workaround: + + CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash + +`configure' Invocation +====================== + +`configure' recognizes the following options to control how it operates. + +`--help' +`-h' + Print a summary of the options to `configure', and exit. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/trunk/LICENSE.txt b/trunk/LICENSE.txt new file mode 100644 index 0000000..113c29b --- /dev/null +++ b/trunk/LICENSE.txt @@ -0,0 +1,340 @@ +GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/trunk/Makefile.am b/trunk/Makefile.am new file mode 100644 index 0000000..bf334d2 --- /dev/null +++ b/trunk/Makefile.am @@ -0,0 +1,123 @@ +# Copyright (C) 2008 Equinox Software, Inc. +# Kevin Beswick +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + + +if !DEBUG +MAYBE_DEBUG = -DNDEBUG +endif + +export PREFIX = @prefix@ +export TMP = @TMP@ +export LIBXML2_HEADERS = @LIBXML2_HEADERS@ +export APR_HEADERS = @APR_HEADERS@ +export ETCDIR = @sysconfdir@ +export APXS2 = @APXS2@ +export APACHE2_HEADERS = @APACHE2_HEADERS@ +export DEF_CFLAGS = -D_LARGEFILE64_SOURCE $(MAYBE_DEBUG) -pipe -g -Wall -O2 -fPIC -I@abs_top_srcdir@/include/ -I$(LIBXML2_HEADERS) -I$(APACHE2_HEADERS) -I$(APR_HEADERS) @INCLUDES@ +export DEF_LDLIBS = -lopensrf +export VAR = @localstatedir@ +export PID = @localstatedir@/run/opensrf +export SOCK = @localstatedir@/lock/opensrf +export LOG = @localstatedir@/log/opensrf +export srcdir = @srcdir@ + +AM_CFLAGS = $(DEF_CFLAGS) + +DOC_FILES = @srcdir@/doc/Application-HOWTO.txt \ + @srcdir@/doc/dokuwiki-doc-stubber.pl \ + @srcdir@/doc/OpenSRF-Messaging-Protocol.html \ + @srcdir@/doc/Persist-API.html \ + @srcdir@/doc/Roadmap.txt + +EXAMPLES_FILES = @srcdir@/examples/fieldmapper2cdbi.xsl \ + @srcdir@/examples/fieldmapper2javascript.xsl \ + @srcdir@/examples/fieldmapper2perl.xsl \ + @srcdir@/examples/gen-fieldmapper.xml \ + @srcdir@/examples/math_bench.pl \ + @srcdir@/examples/multisession-test.pl \ + @srcdir@/examples/register.pl \ + @srcdir@/examples/srfsh_config.xsd \ + @srcdir@/examples/math_xul_client/math \ + @srcdir@/examples/math_xul_client/install.js + +strn_compat_FILES = @srcdir@/src/ports/strn_compat/strndup.c \ + @srcdir@/src/ports/strn_compat/strndup.h \ + @srcdir@/src/ports/strn_compat/strnlen.c \ + @srcdir@/src/ports/strn_compat/strnlen.h + +python_FILES = @srcdir@/src/python/opensrf.py \ + @srcdir@/src/python/setup.py \ + @srcdir@/src/python/srfsh.py \ + @srcdir@/src/python/osrf + +java_FILES = @srcdir@/src/java/deps.inc \ + @srcdir@/src/java/deps.sh \ + @srcdir@/src/java/org + +libosrf_FILES = @srcdir@/src/libopensrf/basic_client.c \ + @srcdir@/src/libopensrf/osrf_big_hash.c \ + @srcdir@/src/libopensrf/osrf_big_list.c \ + @srcdir@/src/libopensrf/osrfConfig.c + + +EXTRA_DIST = $(DOC_FILES) $(EXAMPLES_FILES) $(libosrf_FILES) $(strn_compat_FILES) $(python_FILES) $(java_FILES) @srcdir@/autogen.sh @srcdir@/src/extras @srcdir@/DCO-1.1.txt @srcdir@/LICENSE.txt @srcdir@/src/perl @srcdir@/src/javascript + +opensrfincludedir = @includedir@/opensrf + +OSRFINC=@srcdir@/include/opensrf + +opensrfinclude_HEADERS = $(OSRFINC)/log.h \ + $(OSRFINC)/md5.h \ + $(OSRFINC)/osrf_application.h \ + $(OSRFINC)/osrf_app_session.h \ + $(OSRFINC)/osrf_big_hash.h \ + $(OSRFINC)/osrf_big_list.h \ + $(OSRFINC)/osrf_cache.h \ + $(OSRFINC)/osrfConfig.h \ + $(OSRFINC)/osrf_hash.h \ + $(OSRFINC)/osrf_json.h \ + $(OSRFINC)/osrf_json_utils.h \ + $(OSRFINC)/osrf_json_xml.h \ + $(OSRFINC)/osrf_legacy_json.h \ + $(OSRFINC)/osrf_list.h \ + $(OSRFINC)/osrf_message.h \ + $(OSRFINC)/osrf_prefork.h \ + $(OSRFINC)/osrf_settings.h \ + $(OSRFINC)/osrf_stack.h \ + $(OSRFINC)/osrf_system.h \ + $(OSRFINC)/osrf_transgroup.h \ + $(OSRFINC)/sha.h \ + $(OSRFINC)/socket_bundle.h \ + $(OSRFINC)/string_array.h \ + $(OSRFINC)/transport_client.h \ + $(OSRFINC)/transport_message.h \ + $(OSRFINC)/transport_session.h \ + $(OSRFINC)/utils.h \ + $(OSRFINC)/xml_utils.h + + + +SUBDIRS = src + +jserver: + make -s -C src jserver + +jserver-install: + make -s -C src jserver-install + +javascript-install: + make -s -C src javascript-install + +install-data-hook: + cp @srcdir@/src/gateway/apachetools.h @includedir@/opensrf/apachetools.h + diff --git a/trunk/NEWS b/trunk/NEWS new file mode 100644 index 0000000..2aafebb --- /dev/null +++ b/trunk/NEWS @@ -0,0 +1 @@ +#NEWS diff --git a/trunk/README b/trunk/README new file mode 100644 index 0000000..267b3c6 --- /dev/null +++ b/trunk/README @@ -0,0 +1,51 @@ +README for OpenSRF 1.0 RC + +Installing prerequisites: +======================== + +OpenSRF has a number of prerequisite packages that must be installed +before you can successfully configure, compile, and install OpenSRF. +On Debian and Ubuntu, the easiest way to install these prerequisites +is to use the Makefile.install prerequisite installer for Evergreen. + +Issue the following commands as the root user to install prerequisites +using the Makefile.install prerequisite installer, substituting "debian" +or "ubuntu" for below: + +aptitude install wget make +wget http://svn.open-ils.org/trac/ILS/export/10741/trunk/Open-ILS/src/extras/Makefile.install +make -f Makefile.install + +Note: You may also be able to use "centos" to install the OpenSRF +prerequisites for CentOS 5 and RHEL 5, or "gentoo" for Gentoo - but +these are less tested distributions. Your patches and suggestions for +improvement are welcome! + +Configuration and compilation instructions: +========================================== + +For the time being, we are still installing everything in the /openils/ +directory (with the exception of the Perl modules, which are installed +into system directories). Issue the following commands to configure and +build OpenSRF: + +./configure --with-prefix=/openils --with-sysconfdir=/openils/conf +make + +Installation instructions: +========================= + +Once you have configured and compiled OpenSRF, issue the following +command as the root user to install OpenSRF: + +make install + +This will install OpenSRF, including example configuration files in +/openils/conf/ that you can use as templates for your own configuration files. + +Getting help: +============ + +Need help installing or using OpenSRF? Join the mailing lists at +http://evergreen-ils.org/listserv.php or contact us on the Freenode +IRC network on the #evergreen channel. diff --git a/trunk/autogen.sh b/trunk/autogen.sh new file mode 100755 index 0000000..1a8d53f --- /dev/null +++ b/trunk/autogen.sh @@ -0,0 +1,43 @@ +#!/bin/sh +# autogen.sh - generates configure using the autotools + +OS=`uname` +if [ "$OS" = "Darwin" ]; then + : ${LIBTOOLIZE=glibtoolize} +elif [ "$OS" = "Linux" ]; then + : ${LIBTOOLIZE=libtoolize} +fi + +: ${ACLOCAL=aclocal} +: ${AUTOHEADER=autoheader} +: ${AUTOMAKE=automake} +: ${AUTOCONF=autoconf} + + +${LIBTOOLIZE} --force --copy +${ACLOCAL} +${AUTOMAKE} --add-missing + + +${AUTOCONF} + +SILENT=`which ${LIBTOOLIZE} ${ACLOCAL} ${AUTOHEADER} ${AUTOMAKE} ${AUTOCONF}` +case "$?" in + 0 ) + echo All build tools found. + ;; + 1) + echo + echo "--------------------------------------------------------------" + echo " >>> Some build tools are missing! <<<" + echo Please make sure your system has the GNU autoconf and automake + echo toolchains installed. + echo "--------------------------------------------------------------" + exit + ;; +esac + +echo +echo "---------------------------------------------" +echo "autogen finished running, now run ./configure" +echo "---------------------------------------------" diff --git a/trunk/bin/opensrf-perl.pl b/trunk/bin/opensrf-perl.pl new file mode 100755 index 0000000..d66d19f --- /dev/null +++ b/trunk/bin/opensrf-perl.pl @@ -0,0 +1,250 @@ +#!/usr/bin/perl +# --------------------------------------------------------------- +# Copyright (C) 2008 Georgia Public Library Service +# Bill Erickson +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# --------------------------------------------------------------- +use strict; use warnings; +use Getopt::Long; +use Net::Domain qw/hostfqdn/; +use POSIX qw/setsid :sys_wait_h/; +use OpenSRF::Utils::Logger q/$logger/; +use OpenSRF::System; +use OpenSRF::Transport::PeerHandle; +use OpenSRF::Utils::SettingsClient; +use OpenSRF::Transport::Listener; +use OpenSRF::Utils; +use OpenSRF::Utils::Config; + +my $opt_action = undef; +my $opt_service = undef; +my $opt_config = undef; +my $opt_pid_dir = '/tmp'; +my $opt_no_daemon = 0; +my $opt_settings_pause = 0; +my $opt_help = 0; +my $verbose = 0; +my $sclient; +my $hostname = hostfqdn(); +my @hosted_services; + +GetOptions( + 'action=s' => \$opt_action, + 'service=s' => \$opt_service, + 'config=s' => \$opt_config, + 'pid-dir=s' => \$opt_pid_dir, + 'no-daemon' => \$opt_no_daemon, + 'settings-startup-pause=i' => \$opt_settings_pause, + 'help' => \$opt_help, + 'verbose' => \$verbose, +); + + +sub haltme { + kill('INT', -$$); #kill all in process group + exit; +}; +$SIG{INT} = \&haltme; +$SIG{TERM} = \&haltme; + +sub get_pid_file { + my $service = shift; + return "$opt_pid_dir/$service.pid"; +} + +# stop a specific service +sub do_stop { + my $service = shift; + my $pid_file = get_pid_file($service); + if(-e $pid_file) { + my $pid = `cat $pid_file`; + chomp $pid; + msg("stopping servivce pid=$pid $service", 1); + kill('INT', $pid); + waitpid($pid, 0); + unlink $pid_file; + } else { + msg("$service not running"); + } + return 1; +} + +sub do_init { + OpenSRF::System->bootstrap_client(config_file => $opt_config); + die "Unable to bootstrap client for requests\n" + unless OpenSRF::Transport::PeerHandle->retrieve; + + load_settings(); # load the settings config if we can + + my $sclient = OpenSRF::Utils::SettingsClient->new; + my $apps = $sclient->config_value("activeapps", "appname"); + + # disconnect the top-level network handle + OpenSRF::Transport::PeerHandle->retrieve->disconnect; + + if($apps) { + $apps = [$apps] unless ref $apps; + for my $app (@$apps) { + push(@hosted_services, $app) + if $sclient->config_value('apps', $app, 'language') =~ /perl/i; + } + } + return 1; +} + +# start a specific service +sub do_start { + my $service = shift; + if(-e get_pid_file($service)) { + msg("$service is already running"); + return; + } + + load_settings() if $service eq 'opensrf.settings'; + + my $sclient = OpenSRF::Utils::SettingsClient->new; + my $apps = $sclient->config_value("activeapps", "appname"); + OpenSRF::Transport::PeerHandle->retrieve->disconnect; + + if(grep { $_ eq $service } @hosted_services) { + return unless do_daemon($service); + launch_net_server($service); + launch_listener($service); + $0 = "OpenSRF controller [$service]"; + while(my $pid = waitpid(-1, 0)) { + $logger->debug("Cleaning up Perl $service process $pid"); + } + } + + msg("$service is not configured to run on $hostname"); + return 1; +} + +sub do_start_all { + msg("starting all services for $hostname", 1); + if(grep {$_ eq 'opensrf.settings'} @hosted_services) { + do_start('opensrf.settings'); + # in batch mode, give opensrf.settings plenty of time to start + # before any non-Perl services try to connect + sleep $opt_settings_pause if $opt_settings_pause; + } + for my $service (@hosted_services) { + do_start($service) unless $service eq 'opensrf.settings'; + } + return 1; +} + +sub do_stop_all { + msg("stopping all services for $hostname", 1); + do_stop($_) for @hosted_services; + return 1; +} + +# daemonize us. return true if we're the child, false if parent +sub do_daemon { + return 1 if $opt_no_daemon; + my $service = shift; + my $pid_file = get_pid_file($service); + #exit if OpenSRF::Utils::safe_fork(); + return 0 if OpenSRF::Utils::safe_fork(); + msg("starting servivce pid=$$ $service", 1); + chdir('/'); + setsid(); + close STDIN; + close STDOUT; + close STDERR; + `echo $$ > $pid_file`; + return 1; +} + +# parses the local settings file +sub load_settings { + my $conf = OpenSRF::Utils::Config->current; + my $cfile = $conf->bootstrap->settings_config; + return unless $cfile; + my $parser = OpenSRF::Utils::SettingsParser->new(); + $parser->initialize( $cfile ); + $OpenSRF::Utils::SettingsClient::host_config = + $parser->get_server_config($conf->env->hostname); +} + +# starts up the unix::server master process +sub launch_net_server { + my $service = shift; + push @OpenSRF::UnixServer::ISA, 'Net::Server::PreFork'; + unless(OpenSRF::Utils::safe_fork()) { + $0 = "OpenSRF Drone [$service]"; + OpenSRF::UnixServer->new($service)->serve; + exit; + } + return 1; +} + +# starts up the inbound listener process +sub launch_listener { + my $service = shift; + unless(OpenSRF::Utils::safe_fork()) { + $0 = "OpenSRF listener [$service]"; + OpenSRF::Transport::Listener->new($service)->initialize->listen; + exit; + } + return 1; +} + +sub msg { + my $m = shift; + my $v = shift; + print "* $m\n" unless $v and not $verbose; +} + +sub do_help { + print < + Actions include start, stop, restart, and start_all, stop_all, and restart_all + + --service + Specifies which OpenSRF service to control + + --config + OpenSRF configuration file + + --pid-dir + Directory where process-specific PID files are kept + + --no-daemon + Do not detach and run as a daemon process. Useful for debugging. + + --settings-startup-pause + How long to give the opensrf.settings server to start up when running + in batch mode (start_all). The purpose is to give plenty of time for + the settings server to be up and active before any non-Perl services + attempt to connect. + + --help + Print this help message +HELP +exit; +} + + +do_help() if $opt_help or not $opt_action; +do_init() and do_start($opt_service) if $opt_action eq 'start'; +do_stop($opt_service) if $opt_action eq 'stop'; +do_init() and do_stop($opt_service) and do_start($opt_service) if $opt_action eq 'restart'; +do_init() and do_start_all() if $opt_action eq 'start_all'; +do_init() and do_stop_all() if $opt_action eq 'stop_all'; +do_init() and do_stop_all() and do_start_all() if $opt_action eq 'restart_all'; + + diff --git a/trunk/bin/osrf_config.in b/trunk/bin/osrf_config.in new file mode 100644 index 0000000..70b5c38 --- /dev/null +++ b/trunk/bin/osrf_config.in @@ -0,0 +1,133 @@ +# Copyright (C) 2008 Equinox Software, Inc. +# Kevin Beswick +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# + +# Shows configuration options of OSRF + +prefix=@prefix@ +exec_prefix=@prefix@ +datarootdir=@datarootdir@ + +function showInstalled { + JAVA=@OSRF_INSTALL_JAVA@ + PYTHON=@OSRF_INSTALL_PYTHON@ + if test "$JAVA" = "true"; then + echo "OSRF_JAVA" + fi + if test "$PYTHON" = "true"; then + echo "OSRF_PYTHON" + fi +} + +function showAll { + echo @PACKAGE_STRING@ + echo PREFIX=@prefix@ + echo BINDIR=@bindir@ + echo LIBDIR=@libdir@ + echo TMP=@TMP@ + echo INCLUDEDIR=@includedir@ + echo SYSCONFDIR=@sysconfdir@ + echo APXS2=@APXS2@ + echo APACHE2_HEADERS=@APACHE2_HEADERS@ + echo APR_HEADERS=@APR_HEADERS@ + echo LIBXML2_HEADERS=@LIBXML2_HEADERS@ + echo + echo "Installed modules:" + showInstalled; +} + +function cconfig { + +sed -e 's|osrf|@abs_top_srcdir@/src/python/osrf|g' \ + -e 's|srfsh\.py|@abs_top_srcdir@/src/python/srfsh.py|g' @srcdir@/src/python/setup.py.in > @srcdir@/src/python/setup.py +} + +function showHelp { + echo + echo "------------------------------------------------------------" + echo " osrf_config " + echo " Shows configuration of opensrf " + echo "------------------------------------------------------------" + echo + echo "Usage: osrf_config [--option]" + echo + echo "Options: " + echo + echo "--help displays help" + echo "--version displays version number of osrf" + echo "--installed displays options that were installed" + echo "--prefix displays prefix" + echo "--bindir displays bindir" + echo "--libdir displays libdir" + echo "--tmp displays tmp" + echo "--includedir displays includedir" + echo "--sysconfdir displays sysconfdir" + echo "--apxs displays location of apxs" + echo "--apache displays location of apache2 headers" + echo "--apr displays location of apr headers" + echo "--libxml displays location of libxml2 headers" + echo +} + +case "$1" in + --installed) + showInstalled; + ;; + --cconfig) cconfig; + ;; + --libxml) + echo @LIBXML2_HEADERS@; + ;; + --apr) + echo @APR_HEADERS@; + ;; + --apache) + echo @APACHE2_HEADERS@; + ;; + --prefix) + echo @prefix@ + ;; + --version) + echo @PACKAGE_STRING@; + ;; + --bindir) + echo @bindir@ + ;; + --libdir) + echo @libdir@; + ;; + --sysconfdir) + echo @sysconfdir@; + ;; + --localstatedir) + echo @localstatedir@; + ;; + --tmpdir) + echo @TMP@; + ;; + --apxs) + echo @APXS2@; + ;; + --includedir) + echo @includedir@; + ;; + --docdir) + echo @docdir@; + ;; + --help) + showHelp; + ;; + *) + showAll; + ;; +esac diff --git a/trunk/bin/osrf_ctl.sh b/trunk/bin/osrf_ctl.sh new file mode 100755 index 0000000..f696dc9 --- /dev/null +++ b/trunk/bin/osrf_ctl.sh @@ -0,0 +1,219 @@ +#!/bin/bash +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + + +OPT_ACTION="" +OPT_CONFIG="" +OPT_PID_DIR="" + +# --------------------------------------------------------------------------- +# Make sure we're running as the correct user +# --------------------------------------------------------------------------- +[ $(whoami) != 'opensrf' ] && echo 'Must run as user "opensrf"' && exit; + + +function usage { + echo ""; + echo "usage: $0 [OPTION]... -c -a "; + echo ""; + echo "Mandatory parameters:"; + echo -e " -a\t\taction to perform"; + echo ""; + echo "Optional parameters:"; + echo -e " -c\t\tfull path to C configuration file (opensrf_core.xml)"; + echo -e " -d\t\tstore PID files in this directory"; + echo -e " -l\t\taccept 'localhost' as the fully-qualified domain name"; + echo ""; + echo "Actions include:"; + echo -e "\tstart_router" + echo -e "\tstop_router" + echo -e "\trestart_router" + echo -e "\tstart_perl" + echo -e "\tstop_perl" + echo -e "\trestart_perl" + echo -e "\tstart_c" + echo -e "\tstop_c" + echo -e "\trestart_c" + echo -e "\tstart_osrf" + echo -e "\tstop_osrf" + echo -e "\trestart_osrf" + echo -e "\tstop_all" + echo -e "\tstart_all" + echo -e "\trestart_all" + echo ""; + echo "Examples:"; + echo " $0 -a restart_all"; + echo " $0 -l -c opensrf_core.xml -a restart_all"; + echo ""; + exit; +} + +# Get root directory of this script +function basepath { + BASEDIR="" + script_path="$1" + IFS="/" + for p in $script_path + do + if [ -z "$BASEDIR" ] && [ -n "$p" ]; then + BASEDIR="$p" + fi; + done + BASEDIR="/$BASEDIR" + IFS= +} + +basepath $0 + +# --------------------------------------------------------------------------- +# Load the command line options and set the global vars +# --------------------------------------------------------------------------- +while getopts "a:d:c:lh" flag; do + case $flag in + "a") OPT_ACTION="$OPTARG";; + "c") OPT_CONFIG="$OPTARG";; + "d") OPT_PID_DIR="$OPTARG";; + "l") export OSRF_HOSTNAME="localhost";; + "h"|*) usage;; + esac; +done + +OSRF_CONFIG=`find $BASEDIR -name osrf_config` + +[ -z "$OPT_CONFIG" ] && OPT_CONFIG=`$OSRF_CONFIG --sysconfdir`/opensrf_core.xml; +if [ ! -r "$OPT_CONFIG" ]; then + echo "Please specify the location of the opensrf_core.xml file using the -c flag"; + exit 1; +fi; +[ -z "$OPT_PID_DIR" ] && OPT_PID_DIR=`$OSRF_CONFIG --localstatedir`/run; +[ -z "$OPT_ACTION" ] && usage; + +PID_ROUTER="$OPT_PID_DIR/router.pid"; +PID_OSRF_PERL="$OPT_PID_DIR/osrf_perl.pid"; +PID_OSRF_C="$OPT_PID_DIR/osrf_c.pid"; + + +# --------------------------------------------------------------------------- +# Utility code for checking the PID files +# --------------------------------------------------------------------------- +function do_action { + + action="$1"; + pidfile="$2"; + item="$3"; + + if [ $action == "start" ]; then + + if [ -e $pidfile ]; then + pid=$(cat $pidfile); + echo "$item already started : $pid"; + return 0; + fi; + echo "Starting $item"; + fi; + + if [ $action == "stop" ]; then + + if [ ! -e $pidfile ]; then + echo "$item not running"; + return 0; + fi; + + while read pid; do + echo "Stopping $item process $pid..." + kill -s INT $pid + done < $pidfile; + rm -f $pidfile; + + fi; + + return 0; +} + + +# --------------------------------------------------------------------------- +# Start / Stop functions +# --------------------------------------------------------------------------- + + +function start_router { + do_action "start" $PID_ROUTER "OpenSRF Router"; + opensrf_router $OPT_CONFIG routers + pid=$(ps ax | grep "OpenSRF Router" | grep -v grep | awk '{print $1}') + echo $pid > $PID_ROUTER; + return 0; +} + +function stop_router { + do_action "stop" $PID_ROUTER "OpenSRF Router"; + return 0; +} + +function start_perl { + echo "Starting OpenSRF Perl"; + opensrf-perl.pl --pid-dir $OPT_PID_DIR \ + --config $OPT_CONFIG --action start_all --settings-startup-pause 3 + return 0; +} + +function stop_perl { + echo "Stopping OpenSRF Perl"; + opensrf-perl.pl --pid-dir $OPT_PID_DIR --config $OPT_CONFIG --action stop_all + sleep 1; + return 0; +} + +function start_c { + host=$OSRF_HOSTNAME + if [ "_$host" == "_" ]; then + host=$(perl -MNet::Domain=hostfqdn -e 'print hostfqdn()'); + fi; + + do_action "start" $PID_OSRF_C "OpenSRF C (host=$host)"; + opensrf-c $host $OPT_CONFIG opensrf; + pid=$(ps ax | grep "OpenSRF System-C" | grep -v grep | awk '{print $1}') + echo $pid > "$PID_OSRF_C"; + return 0; +} + +function stop_c { + do_action "stop" $PID_OSRF_C "OpenSRF C"; + sleep 1; + return 0; +} + + + +# --------------------------------------------------------------------------- +# Do the requested action +# --------------------------------------------------------------------------- +case $OPT_ACTION in + "start_router") start_router;; + "stop_router") stop_router;; + "restart_router") stop_router; start_router;; + "start_perl") start_perl;; + "stop_perl") stop_perl;; + "restart_perl") stop_perl; start_perl;; + "start_c") start_c;; + "stop_c") stop_c;; + "restart_c") stop_c; start_c;; + "start_osrf") start_perl; start_c;; + "stop_osrf") stop_perl; stop_c;; + "restart_osrf") stop_perl; stop_c; start_perl; start_c;; + "stop_all") stop_c; stop_perl; stop_router;; + "start_all") start_router; start_perl; start_c;; + "restart_all") stop_c; stop_perl; stop_router; start_router; start_perl; start_c;; + *) usage;; +esac; + + + diff --git a/trunk/configure.ac b/trunk/configure.ac new file mode 100644 index 0000000..4b9e62c --- /dev/null +++ b/trunk/configure.ac @@ -0,0 +1,294 @@ +# Copyright (C) 2008 Equinox Software, Inc. +# Kevin Beswick +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# Process this file with autoconf to produce a configure script. + + +#------------------------------- +# Initialization +#------------------------------- + +export PATH=${PATH}:/usr/sbin +AC_PREREQ(2.59) +AC_INIT([OpenSRF],[trunk],[open-ils-dev@list.georgialibraries.org]) +AM_INIT_AUTOMAKE([OpenSRF], [trunk]) +AC_REVISION($Revision: 0.1 $) +AC_CONFIG_SRCDIR([configure.ac]) +AC_PREFIX_DEFAULT([/opensrf/]) + + +AC_SUBST(prefix) +AC_SUBST(sysconfdir) + + +AC_DEFUN([AC_PYTHON_MOD],[ + if test -z $PYTHON; + then + PYTHON="python" + fi + AC_MSG_CHECKING($PYTHON_NAME module: $1) + $PYTHON -c "import $1" 2>/dev/null + if test $? -eq 0; + then + AC_MSG_RESULT(yes) + eval AS_TR_CPP(HAVE_PYMOD_$1)=yes + else + AC_MSG_ERROR(failed to find required module $1) + exit 1 + fi +]) + + + +#------------------------------- +# Installation options +#------------------------------- + +# build and install the java libs? +AC_ARG_ENABLE([java], +[ --enable-java enable building and installing the java libraries], +[case "${enableval}" in + yes) OSRF_INSTALL_JAVA=true ;; + no) OSRF_INSTALL_JAVA=false ;; + *) AC_MSG_ERROR([please choose another value for --enable-java (supported values are yes or no)]) ;; +esac], +[OSRF_INSTALL_JAVA=false]) + +AM_CONDITIONAL([BUILDJAVA], [test x$OSRF_INSTALL_JAVA = xtrue]) +AC_SUBST([OSRF_INSTALL_JAVA]) + +# build and install the python modules +AC_ARG_ENABLE([python], +[ --enable-python enable building and installing python modules], +[case "${enableval}" in + yes) OSRF_INSTALL_PYTHON=true ;; + no) OSRF_INSTALL_PYTHON=false ;; + *) AC_MSG_ERROR([please choose another value for --enable-python (supported values are yes or no)]) ;; +esac], +[OSRF_INSTALL_PYTHON=false]) + +AM_CONDITIONAL([BUILDPYTHON], [test x$OSRF_INSTALL_PYTHON = xtrue]) +AC_SUBST([OSRF_INSTALL_PYTHON]) + +# enable debug? + +AC_ARG_ENABLE(debug, +[ --enable-debug Turn on debugging], +[case "${enableval}" in + yes) debug=true ;; + no) debug=false ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-debug) ;; +esac],[debug=false]) +AM_CONDITIONAL(DEBUG, test x$debug = xtrue) + + +# path to the directory containing the java dependency jar files (included if java installs) +if test $OSRF_INSTALL_JAVA; then + AC_SUBST([OSRF_JAVA_DEPSDIR], [/opt/java]) +fi + + + +#-------------------------------- +# Checks for programs. +#-------------------------------- + +AC_PROG_LIBTOOL +AC_PROG_AWK +AC_PROG_CC +AC_PROG_INSTALL +AC_PROG_MAKE_SET + +#------------------------------ +# Set install path variables +#------------------------------ +AC_ARG_WITH([tmp], +[ --with-tmp=path location for the tmp dir for openSRF (default is /tmp)], +[TMP=${withval}], +[TMP=/tmp]) +AC_SUBST([TMP]) + +AC_ARG_WITH([apxs], +[ --with-apxs=path location of apxs (default is /usr/bin/apxs2)], +[APXS2=${withval}], +[APXS2=/usr/bin/apxs2]) +AC_SUBST([APXS2]) + +AC_ARG_WITH([apache], +[ --with-apache=path location of the apache headers (default is /usr/include/apache2)], +[APACHE2_HEADERS=${withval}], +[APACHE2_HEADERS=/usr/include/apache2]) +AC_SUBST([APACHE2_HEADERS]) + +AC_ARG_WITH([apr], +[ --with-apr=path location of the apr headers (default is /usr/include/apr-1.0/)], +[APR_HEADERS=${withval}], +[APR_HEADERS=/usr/include/apr-1.0]) +AC_SUBST([APR_HEADERS]) + +AC_ARG_WITH([libxml], +[ --with-libxml=path location of the libxml headers (default is /usr/include/libxml2/))], +[LIBXML2_HEADERS=${withval}], +[LIBXML2_HEADERS=/usr/include/libxml2/]) +AC_SUBST([LIBXML2_HEADERS]) + +AC_ARG_WITH([includes], +[ --with-includes=DIRECTORIES a colon-separated list of directories that will be added to the list the compiler searches for header files (Example: --with-includes=/path/headers:/anotherpath/moreheaders)], +[EXTRA_USER_INCLUDES=${withval}]) + +AC_ARG_WITH([libraries], +[ --with-libraries=DIRECTORIES a colon-separated list of directories to search for libraries (Example: --with-libraries=/lib:/usr/lib)], +[EXTRA_USER_LIBRARIES=${withval}]) + +# Change these lists to proper compiler/linker options + +IFSBAK=${IFS} +IFS="${IFS}:" + +for dir in $EXTRA_USER_INCLUDES; do + if test -d "$dir"; then + INCLUDES="$INCLUDES -I$dir" + else + AC_MSG_WARN([*** Include directory $dir does not exist.]) + fi +done +AC_SUBST(INCLUDES) + +for dir in $EXTRA_USER_LIBRARIES; do + if test -d "$dir"; then + LIBDIRS="$LIBDIRS -L$dir" + else + AC_MSG_WARN([*** Library directory $dir does not exist.]) + fi +done +AC_SUBST(LIBDIRS) + +IFS=${IFSBAK} + +#-------------------------------- +# Check for dependencies. +#-------------------------------- + +#APACHE PREFORK DEV TEST +AC_MSG_CHECKING([APXS]) +if test -f "${APXS2}"; then +AC_MSG_RESULT([yes]) +else +AC_MSG_ERROR([*** apxs not found, aborting]) +fi + +#PYTHON TESTS +if test x$OSRF_INSTALL_PYTHON = xtrue; then + AC_CHECK_PROG([HAVE_PYTHON],python,yes,no) + if test $HAVE_PYTHON = "no"; then + AC_MSG_ERROR([*** python not found, aborting]) + fi + AC_PYTHON_MOD([setuptools]) +fi + + +#----------------------------- +# Checks for libraries. +#----------------------------- + +AC_CHECK_LIB([dl], [dlerror], [],AC_MSG_ERROR(***OpenSRF requires libdl)) +AC_SEARCH_LIBS([mc_req_free], [memcache], [], AC_MSG_ERROR(***OpenSRF requires memcache development headers)) +AC_CHECK_LIB([ncurses], [initscr], [], AC_MSG_ERROR(***OpenSRF requires ncurses development headers)) +AC_CHECK_LIB([readline], [readline], [], AC_MSG_ERROR(***OpenSRF requires readline development headers)) +AC_CHECK_LIB([xml2], [xmlAddID], [], AC_MSG_ERROR(***OpenSRF requires xml2 development headers)) + + + +#----------------------------- +# Checks for header files. +#----------------------------- + +AC_HEADER_STDC +AC_HEADER_SYS_WAIT +AC_CHECK_HEADERS([arpa/inet.h fcntl.h limits.h malloc.h netdb.h netinet/in.h stdlib.h string.h strings.h sys/socket.h sys/time.h sys/timeb.h syslog.h unistd.h]) + +#------------------------------------------------------------------ +# Checks for typedefs, structures, and compiler characteristics. +#------------------------------------------------------------------ + +AC_C_CONST +AC_C_INLINE +AC_TYPE_PID_T +AC_TYPE_SIZE_T +AC_HEADER_TIME +AC_STRUCT_TM + +#---------------------------------- +# Checks for library functions. +#---------------------------------- + +AC_FUNC_FORK +AC_FUNC_MALLOC +AC_FUNC_SELECT_ARGTYPES +AC_TYPE_SIGNAL +AC_FUNC_STRFTIME +AC_FUNC_STRTOD +AC_FUNC_VPRINTF +AC_CHECK_FUNCS([bzero dup2 gethostbyname gethostname gettimeofday memset select socket strcasecmp strchr strdup strerror strncasecmp strndup strrchr strtol]) + +#------------------------------------ +# Configuration and output +#------------------------------------ + +AC_CONFIG_FILES([Makefile + examples/math_xul_client/Makefile + src/Makefile + src/c-apps/Makefile + src/gateway/Makefile + src/java/Makefile + src/jserver/Makefile + src/libopensrf/Makefile + src/ports/strn_compat/Makefile + src/python/Makefile + src/router/Makefile + src/srfsh/Makefile + bin/osrf_config], [if test -e "./bin/osrf_config"; then chmod 755 bin/osrf_config; fi]) + + +AC_OUTPUT + +bin/osrf_config --cconfig + +AC_MSG_RESULT([]) +AC_MSG_RESULT([--------------------- Configuration options: -----------------------]) + +if test "$OSRF_INSTALL_JAVA" = "true" ; then + AC_MSG_RESULT([OSRF install java?: yes]) + AC_MSG_RESULT([Java deps dir: $OSRF_JAVA_DEPSDIR]) +else + AC_MSG_RESULT([OSRF install java?: no]) +fi + +if test "$OSRF_INSTALL_PYTHON" = "true" ; then + AC_MSG_RESULT([OSRF install python?: yes]) +else + AC_MSG_RESULT([OSRF install python?: no]) +fi + + AC_MSG_RESULT(Installation directory prefix: ${prefix}) + AC_MSG_RESULT(Tmp dir location: ${TMP}) + AC_MSG_RESULT(APXS2 location: ${APXS2}) + AC_MSG_RESULT(Apache headers location: ${APACHE2_HEADERS}) + AC_MSG_RESULT(APR headers location: ${APR_HEADERS}) + AC_MSG_RESULT(libxml2 headers location: ${LIBXML2_HEADERS}) + + + + + +AC_MSG_RESULT([----------------------------------------------------------------------]) diff --git a/trunk/doc/Application-HOWTO.txt b/trunk/doc/Application-HOWTO.txt new file mode 100644 index 0000000..41deae1 --- /dev/null +++ b/trunk/doc/Application-HOWTO.txt @@ -0,0 +1,95 @@ +OpenSRF Application development API +----------------------------------- + +OpenSRF offers a very simple Application development API to users of the +framework. All that is required is to create a Perl module that subclasses +the OpenSRF::Application package and register it's methods with the +Method Dispatcher framework. + +Each method executes in the OpenSRF::Application namespace as an instance of +the custom Application. There are some instance methods on this object which +can be used by the method to alter the behavior or response that the method +sends to the client: + + $self->api_name # returns the name of the method as called by the client + + $self->method # returns the actual perl name of the sub implementing the + # method + + my $meth = $self->method_lookup( 'api_name' ) + # constructs a new instance object implementing another + # method in the same Application package as a subrequest + + my ($subresult) = $meth->run( @params ) + # runs the subrequest method and returns the array of + # results + + +The method is also handed an OpenSRF::AppRequest object that has been +constructed for the client request that generated the call to the method. +This OpenSRF::AppRequest object is used to communicate back to the client, +passing status messages or streaming response packets. + +All that is required to register an Application with OpenSRF is to place a +setting in the configuration file that names the module that implements the +new Application, and to add the new Application's symbolic name to the list of +servers that should be started by OpenSRF. + + Example Application + ------------------- + + # Perl module and package implementing an math server. + package MyMathServer; + use OpenSRF::Application; + use base 'OpenSRF::Application'; + + sub do_math { + my $self = shift; # instance of MyMathServer + + my $client = shift; # instance of OpenSRF::AppRequest connected + # to the client + + my $left_side = shift; + my $op = shift; + my $right_side = shift; + + return eval "$left_side $op $right_side"; + } + + __PACKAGE__->register_method( + api_name => 'useless.do_math', + argc => 3, + method => 'do_math' + ); + + 1; + + + + # Another Perl module and package implementing a square-root server on top + # of the previous math server + package MySquareRootServer; + use OpenSRF::Application; + use base 'OpenSRF::Application'; + use MyMathServer; + + sub sqrt_math { + my $self = shift; # instance of MySquareRootServer + + my $client = shift; # instance of OpenSRF::AppRequest connected + # to the client + + my $math_method = $self->method_lookup('useless.do_math'); + my ($result) = $math_method->run( @_ ); + + return sqrt( $result ); + } + + __PACKAGE__->register_method( + api_name => 'simple.sqrt', + argc => 3, + method => 'sqrt_math' + ); + + 1; + diff --git a/trunk/doc/OpenSRF-Messaging-Protocol.html b/trunk/doc/OpenSRF-Messaging-Protocol.html new file mode 100644 index 0000000..1eeff04 --- /dev/null +++ b/trunk/doc/OpenSRF-Messaging-Protocol.html @@ -0,0 +1,297 @@ + + + + + OILS Messaging + + + + + + +

Abstract

+ +

+ + The OpenSRF messaging system works on two different primary layers: the transport layer and the + application layer. The transport layer manages virtual connections between client and server, + while the application layer manages user/application level messages. + + All messages must declare which protocol version they are requesting. The current protocol level + is 1. + +

Transport Layer

+ +

+ There are currently three types of messages in the transport layer: CONNECT, STATUS, and + DISCONNECT. + +

+ STATUS messages provide general information to the transport layer and are used in different + ways throughout the system. They are sent primarily by the server in response to client requests. + Each message comes with + a status and statusCode. The actual status part of the STATUS message is just a helpful message + (mostly for debugging). The + statusCode is an integer representing the exact status this message represents. The status codes + are modeled after HTTP status codes. Currently used codes consist of the following: + +

+		100	STATUS_CONTINUE
+		200	STATUS_OK	
+		205	STATUS_COMPLETE
+		307	STATUS_REDIRECTED
+		400	STATUS_BADREQUEST
+		404	STATUS_NOTFOUND
+		408	STATUS_TIMEOUT
+		417	STATUS_EXPFAILED
+		
+ +

+ This list is likely to change at least a little. + + +

+ The CONNECT message initiates the virtual connection for a client and expects a STATUS + in return. If the connection is successful, the statusCode for the STATUS message shall be + STATUS_OK. + +

+ If at any point the client sends a non-connect message to the server when the client is not connected or the + connection has timed out, the STATUS that is returned shall have statusCode STATUS_EXPFAILED. + +

+ The DISCONNECT message is sent by the client to the server to end the virtual session. The server + shall not respond to any disconnect messages. + + +

Message Layer

+ +

+ There are currently two types of message layer messages: REQUEST and RESULT. REQUEST + messages represent application layer requests made by a client and RESULT messages are the servers + response to such REQUEST's. + +

+ By design, all CONNECT and REQUEST messages sent by a client will be acknowledged by one or + more responses from the server. This is much like the SYN-ACK philosophy of TCP, however different in many + ways. The only guarantees made by the server are 1. you will know that we received your request and 2. you + will know the final outcome of your request. It is the responsibility of the actual application to send + the requested application data (e.g. RESULT messages, intermediate STATUS messages). + + +

+ The server responses are matched to client requests by a threadTrace. A threadTrace is simply a + number and all application layer messages and STATUS messages are required to have one. (Note that the + threadTrace contained within a STATUS message sent in response to a CONNECT will be ignored). Currently, + there is no restriction on the number other than it shall be unique within a given virtual connection. + When the server receives a REQUEST message, it extracts the threadTrace from the message + and all responses to that request will contain the same threadTrace. + +

+ As mentioned above, every CONNECT message will be acknowledged by a single + STATUS message. REQUEST's are a little more complex, however. A REQUEST + will receive one or more RESULT's if the REQUEST warrants such a response. A REQUEST + may even receive one or more intermediate STATUS's (e.g. STATUS_CONTINUE). (Consult the + documentation on the application request the client is requesting for more information on the number and + type of responses to that request). All REQUEST's, however, regardless of other response types, + shall receieve as the last response a STATUS message with statusCode STATUS_COMPLETE. This + allows the client to wait for REQUEST "completeness" as opposed to waiting on or calculating individual + responses. + + +

Client Pseudocode

+ +
+
+send CONNECT
+
+msg = recv()
+
+if ( msg.statusCode == STATUS_OK ) 
+
+	OK. continue
+
+while ( more requests ) {
+
+	/* you may send multiple requests before processing any responses.  For the sake
+		of this example, we will only walk through a single client request */
+
+	send REQUEST with threadTrace X 
+
+	while ( response = recv ) { 
+
+		if (  response.threadTrace != X ) 
+
+			continue/ignore
+
+		if ( response.type == STATUS )
+		
+			if (  response.statusCode == STATUS_TIMEOUT		or
+					response.statusCode == STATUS_REDIRECTED	or
+					response.statusCode == STATUS_EXPFAILED)
+
+				resend the the request with threadTrace X because it was not honored.
+
+			if ( response.statusCode == STATUS_COMPLETE ) 
+
+				the request is now complete, nothing more to be done with this request
+				break out of loop
+	
+		if ( response.typ == RESULT )
+
+			pass result to the application layer for processing
+
+	} // receiving
+
+} // sending
+
+
+		
+ +
+

Server Pseudocode

+ +
+
+while( message = recv() ) {
+
+	if( message.type != CONNECT )
+
+		return a STATUS with statusCode STATUS_EXPFAILED
+		start loop over
+
+	if ( message.type == CONNECT )
+
+		return STATUS with statusCode STATUS_OK and continue
+
+	while ( msg = recv() and virtual session is active ) {
+
+
+		if ( msg.type == REQUEST )
+
+			Record the threadTrace.  Pass the REQUEST to the application layer for processing.
+			When the application layer has completed processing, respond to the client
+			with a STATUS message with statusCode STATUS_COMPLETE and threadTrace matching
+			the threadTrace of the REQUEST.  Once the final STATUS_COMPLETE message is sent,
+			the session is over.  Return to outer server loop. 
+
+			/* Note: during REQUEST processing by the application layer, the application may 
+				opt to send RESULT and/or STATUS messages to the client.  The server side
+				transport mechanism is not concerned with these messages.  The server only 
+				needs to be notified when the REQUEST has been sucessfully completed. */
+
+		if( message.type == DISCONNECT )
+
+			Virtual session has ended. Return to outer loop.
+
+
+	} // Sessin loop
+
+} // Main server loop
+
+
+
+		
+ + +
+

XML Examples

+
+ + +

Protocol Element

+ +
+
+<oils:domainObjectAttr value="1" name="protocol"/>
+
+		
+ +

threadTrace Element

+ +
+
+<oils:domainObjectAttr value="1" name="threadTrace"/>
+
+		
+ +

CONNECT Message

+ +
+
+<oils:domainObject name="oilsMessage">
+	<oils:domainObjectAttr value="CONNECT" name="type"/>
+	<oils:domainObjectAttr value="1" name="threadTrace"/>
+	<oils:domainObjectAttr value="1" name="protocol"/>
+</oils:domainObject>
+
+		
+ + +

DISCONNECT Message

+ +
+
+<oils:domainObject name="oilsMessage">
+	<oils:domainObjectAttr value="DISCONNECT" name="type"/>
+	<oils:domainObjectAttr value="0" name="threadTrace"/>
+	<oils:domainObjectAttr value="1" name="protocol"/>
+</oils:domainObject>
+
+		
+ +

STATUS Message

+ +
+
+<oils:domainObject name="oilsMessage">
+	<oils:domainObjectAttr value="STATUS" name="type"/>
+	<oils:domainObjectAttr value="0" name="threadTrace"/>
+	<oils:domainObjectAttr value="1" name="protocol"/>
+	<oils:domainObject name="oilsConnectStatus">
+		<oils:domainObjectAttr value="Connection Successful" name="status"/>
+		<oils:domainObjectAttr value="200" name="statusCode"/>
+	</oils:domainObject>
+</oils:domainObject>
+
+		
+ +

REQUEST Message

+ +
+
+<oils:domainObject name="oilsMessage">
+	<oils:domainObjectAttr value="REQUEST" name="type"/>
+	<oils:domainObjectAttr value="4" name="threadTrace"/>
+	<oils:domainObjectAttr value="1" name="protocol"/>
+	<oils:domainObject name="oilsMethod">
+		<oils:domainObjectAttr value="mult" name="method"/>
+		<oils:params>[1, 2]</oils:params>
+	</oils:domainObject>
+</oils:domainObject>
+
+		
+ +

RESULT Message

+ +
+
+<oils:domainObject name="oilsMessage">
+	<oils:domainObjectAttr value="RESULT" name="type"/>
+	<oils:domainObjectAttr value="4" name="threadTrace"/>
+	<oils:domainObjectAttr value="1" name="protocol"/>
+	<oils:domainObject name="oilsResult">
+		<oils:domainObjectAttr value="OK" name="status"/>
+		<oils:domainObjectAttr value="200" name="statusCode"/>
+		<oils:domainObject name="oilsScalar">2</oils:domainObject>
+	</oils:domainObject>
+</oils:domainObject>
+
+		
+ + + + + + + diff --git a/trunk/doc/Persist-API.html b/trunk/doc/Persist-API.html new file mode 100644 index 0000000..657e206 --- /dev/null +++ b/trunk/doc/Persist-API.html @@ -0,0 +1,651 @@ + + + OpenSRF Persistence Application API-Namespace + + + + +
+

OpenSRF Persistence Application API-Namespace

+
+
+ +
+ The Persistence Application provides other OpenSRF Applications with a standard API for + sharing and caching data. These data are stored in Slots, and there are three basic + interfaces for interacting with Slots: QUEUEs, STACKs and OBJECTs. +
+ +
    +
  • General Persistence Slot methods

    + + Methods used to create, set up and destroy slots. +

    + +
    +
    opensrf.persist.slot.create( slot_name )
    + + Creates a Persistence Slot. + +
    Parameters:
    +
    slot_name (optional)
    +
    + The name of the Persistence Slot to create. If a name is not specified + then the Slot is given a generic, unique name. Automatically named Slots + are destroyed as soon as they are empty. +
    + + +
    Returns:
    + +
    Success
    +
    The name of the Slot that was created.
    + +
    Failure
    +
    An empty (NULL) result.
    +
    + +
    +
    opensrf.persist.slot.create_expirable( slot_name, expire_interval )
    + + Creates a Persistence Slot that is automatically destroyed after the specified interval. + +
    Parameters:
    +
    slot_name
    +
    The name of the Persistence Slot to create.
    +
    expire_interval
    +
    + An interval describing how long to wait after an access has + occured on the Slot before automatically destroying it. The interval + can be specified using a fairly complex, human readable format, or as + a number of seconds. For example: +
      +
    • 1 day, 2 hours and 35 minutes
    • +
    • +2h
    • +
    • 1 week
    • +
    • 300
    • +
    + + A setting of 0 (zero) disables automatic expiration for a Slot. +
    + + +
    Returns:
    + +
    Success
    +
    The name of the Slot that was created.
    + +
    Failure
    +
    An empty (NULL) result.
    +
    + +
    +
    opensrf.persist.slot.set_expire( slot_name, expire_interval )
    + + Sets or disables the expiration interval on an existing Persistence Slot. + +
    Parameters:
    +
    slot_name
    +
    The name of the Persistence Slot to update.
    +
    expire_interval
    +
    + An interval describing how long to wait after an access has + occured on the Slot before automatically destroying it. The interval + can be specified using a fairly complex, human readable format, or as + a number of seconds. For example: +
      +
    • 1 day, 2 hours and 35 minutes
    • +
    • +2h
    • +
    • 1 week
    • +
    • 300
    • +
    + + A setting of 0 (zero) disables automatic expiration for a Slot. +
    + + +
    Returns:
    + +
    Success
    +
    The number of seconds the requested interval represents.
    + +
    Failure
    +
    An empty (NULL) result.
    +
    + +
    +
    opensrf.persist.slot.destroy( slot_name )
    + + Destroys a Persistence Slot. + +
    Parameters:
    +
    slot_name
    +
    The name of the Persistence Slot to destroy.
    + + +
    Returns:
    + +
    Success
    +
    The name of the Slot that was destroyed.
    + +
    Failure
    +
    An empty (NULL) result.
    +
    + +
    +
  • + +
  • QUEUE API-Namespace Slot methods

    + + Uses the Slot in FIFO mode, pushing values onto one end an pulling them off the other. + The QUEUE API-Namespace is useful for creating an ordered message passing access point. + +

    + +
    +
    opensrf.persist.queue.push( slot_name, object )
    + + Adds an object to a Slot in FIFO order. + +
    Parameters:
    + +
    slot_name
    +
    The name of the Persistence Slot to use for storing the object.
    + +
    object
    +
    The object that should be pushed onto the front of the QUEUE.
    + + +
    Returns:
    + +
    Success
    +
    The name of the Slot that was used.
    + +
    Failure
    +
    An empty (NULL) result.
    +
    + +
    +
    opensrf.persist.queue.pop( slot_name )
    + + Removes and returns the next value in a QUEUE type Slot. + +
    Parameters:
    + +
    slot_name
    +
    + The name of the Persistence Slot from which an object should be retrieved. +
    + + +
    Returns:
    + +
    Success
    +
    + The next object on the QUEUE Slot, or an empty + (NULL) result if the Slot is empty. +
    + +
    Failure
    +
    An empty (NULL) result.
    +
    + +
    +
    opensrf.persist.queue.peek( slot_name )
    + + Returns the next value in a QUEUE type Slot without removing it. + +
    Parameters:
    + +
    slot_name
    +
    + The name of the Persistence Slot from which an object should be retrieved. +
    + + +
    Returns:
    + +
    Success
    +
    + The next object on the QUEUE Slot, or an empty + (NULL) result if the Slot is empty. +
    + +
    Failure
    +
    An empty (NULL) result.
    +
    + +
    +
    opensrf.persist.queue.peek.all( slot_name )
    + + Returns all values in a QUEUE type Slot without removing them. + +
    Parameters:
    + +
    slot_name
    +
    + The name of the Persistence Slot from which the objects should be retrieved. +
    + + +
    Returns:
    + +
    Success
    +
    + A stream of all objects on the QUEUE Slot, or an empty + (NULL) result if the Slot is empty. +
    + +
    Failure
    +
    An empty (NULL) result.
    +
    + +
    +
    opensrf.persist.queue.peek.all.atomic( slot_name )
    + + Returns all values in a QUEUE type Slot without removing them. + +
    Parameters:
    + +
    slot_name
    +
    + The name of the Persistence Slot from which the objects should be retrieved. +
    + + +
    Returns:
    + +
    Success
    +
    + A single array of all objects on the QUEUE Slot, or an empty + array if the Slot is empty. +
    + +
    Failure
    +
    An empty (NULL) result.
    +
    + +
    +
    opensrf.persist.queue.length( slot_name )
    + + Returns the number of objects in the QUEUE type Slot. + +
    Parameters:
    + +
    slot_name
    +
    + The name of the Persistence Slot in question. +
    + + +
    Returns:
    + +
    Success
    +
    The number of objects in the Persistence Slot.
    + +
    Failure
    +
    An empty (NULL) result.
    +
    + +
    +
    opensrf.persist.queue.size( slot_name )
    + + Returns the number bytes taken up by the JSON encoded version of + the objects in the QUEUE type Slot. + +
    Parameters:
    + +
    slot_name
    +
    + The name of the Persistence Slot in question. +
    + + +
    Returns:
    + +
    Success
    +
    + The space, in bytes, used by the JSON encoded + objects in the Persistence Slot. +
    + +
    Failure
    +
    An empty (NULL) result.
    +
    + +
    +
  • + +
  • STACK style Slot methods

    + + Uses the Slot in FILO mode, pushing and pulling objects at the same end of a list. + The STACK API-Namespace is useful for creating a global Application context stack. + +

    + +
    +
    opensrf.persist.stack.push( slot_name, object )
    + + Adds an object to a Slot in FILO order. + +
    Parameters:
    + +
    slot_name
    +
    The name of the Persistence Slot to use for storing the object.
    + +
    object
    +
    The object that should be pushed onto the front of the STACK.
    + + +
    Returns:
    + +
    Success
    +
    The name of the Slot that was used.
    + +
    Failure
    +
    An empty (NULL) result.
    +
    + +
    +
    opensrf.persist.stack.pop( slot_name )
    + + Removes and returns the next value in a STACK type Slot. + +
    Parameters:
    + +
    slot_name
    +
    + The name of the Persistence Slot from which an object should be retrieved. +
    + + +
    Returns:
    + +
    Success
    +
    + The next object on the STACK Slot, or an empty + (NULL) result if the Slot is empty. +
    + +
    Failure
    +
    An empty (NULL) result.
    +
    + +
    +
    opensrf.persist.stack.peek( slot_name )
    + + Returns the next value in a STACK type Slot without removing it. + +
    Parameters:
    + +
    slot_name
    +
    + The name of the Persistence Slot from which an object should be retrieved. +
    + + +
    Returns:
    + +
    Success
    +
    + The next object on the STACK Slot, or an empty + (NULL) result if the Slot is empty. +
    + +
    Failure
    +
    An empty (NULL) result.
    +
    + +
    +
    opensrf.persist.stack.peek.all( slot_name )
    + + Returns all values in a STACK type Slot without removing them. + +
    Parameters:
    + +
    slot_name
    +
    + The name of the Persistence Slot from which the objects should be retrieved. +
    + + +
    Returns:
    + +
    Success
    +
    + A stream of all objects on the STACK Slot, or an empty + (NULL) result if the Slot is empty. +
    + +
    Failure
    +
    An empty (NULL) result.
    +
    + +
    +
    opensrf.persist.stack.peek.all.atomic( slot_name )
    + + Returns all values in a STACK type Slot without removing them. + +
    Parameters:
    + +
    slot_name
    +
    + The name of the Persistence Slot from which the objects should be retrieved. +
    + + +
    Returns:
    + +
    Success
    +
    + A single array of all objects on the STACK Slot, or an empty + array if the Slot is empty. +
    + +
    Failure
    +
    An empty (NULL) result.
    +
    + +
    +
    opensrf.persist.stack.depth( slot_name )
    + + Returns the number of objects in the STACK type Slot. + +
    Parameters:
    + +
    slot_name
    +
    + The name of the Persistence Slot in question. +
    + + +
    Returns:
    + +
    Success
    +
    The number of objects in the Persistence Slot.
    + +
    Failure
    +
    An empty (NULL) result.
    +
    + +
    +
    opensrf.persist.stack.size( slot_name )
    + + Returns the number bytes taken up by the JSON encoded version of + the objects in the STACK type Slot. + +
    Parameters:
    + +
    slot_name
    +
    + The name of the Persistence Slot in question. +
    + + +
    Returns:
    + +
    Success
    +
    + The space, in bytes, used by the JSON encoded + objects in the Persistence Slot. +
    + +
    Failure
    +
    An empty (NULL) result.
    +
    + +
    +
  • + +
  • OBJECT style Slot methods

    + + Uses the Slot in Single Object mode, storing a single object in the Slot. + +

    + + The OBJECT API-Namespace is useful for globally caching unique objects. + +

    + +
    +
    opensrf.persist.object.set( slot_name, object )
    + + Sets the value of a Slot. If the Slot has been used in STACK or QUEUE + mode and opensrf.persist.object.set is called then all objects currently + in the Slot will be lost. + +
    Parameters:
    + +
    slot_name
    +
    The name of the Persistence Slot to use for storing the object.
    + +
    object
    +
    The object that should be set as the one object in the Slot.
    + + +
    Returns:
    + +
    Success
    +
    The name of the Slot that was used.
    + +
    Failure
    +
    An empty (NULL) result.
    +
    + +
    +
    opensrf.persist.object.get( slot_name )
    + + Removes and returns the value in an OBJECT type Slot. + +
    Parameters:
    + +
    slot_name
    +
    + The name of the Persistence Slot from which the object should be retrieved. +
    + + +
    Returns:
    + +
    Success
    +
    + The object in the OBJECT Slot, or an empty + (NULL) result if the Slot is empty. +
    + +
    Failure
    +
    An empty (NULL) result.
    +
    + +
    +
    opensrf.persist.object.peek( slot_name )
    + + Returns the value in an OBJECT type Slot without removing it. + +
    Parameters:
    + +
    slot_name
    +
    + The name of the Persistence Slot from which the object should be retrieved. +
    + + +
    Returns:
    + +
    Success
    +
    + The object on the OBJECT Slot, or an empty + (NULL) result if the Slot is empty. +
    + +
    Failure
    +
    An empty (NULL) result.
    +
    + +
    +
    opensrf.persist.object.size( slot_name )
    + + Returns the number bytes taken up by the JSON encoded version of + the object in the OBJECT type Slot. + +
    Parameters:
    + +
    slot_name
    +
    + The name of the Persistence Slot in question. +
    + + +
    Returns:
    + +
    Success
    +
    + The space, in bytes, used by the JSON encoded + object in the Persistence Slot. +
    + +
    Failure
    +
    An empty (NULL) result.
    +
    + +
  • +
+ + diff --git a/trunk/doc/Roadmap.txt b/trunk/doc/Roadmap.txt new file mode 100644 index 0000000..f86ccd0 --- /dev/null +++ b/trunk/doc/Roadmap.txt @@ -0,0 +1,51 @@ +Roadmap for OpenSRF === The high points as of Febuary 2005 +---------------------------------------------------------- + +We will attempt to keep this file up to date as requirements for +Open-ILS change over time, as they are certain to... + +========== + +# Version 0.1 (January 2005) -- Evolving CVS version ... stay tuned + + * Session failure recovery + * Initial specification for Application API + * Basic Application support + * Sub-requests within one Application + +# Version 0.2 (Febuary/March 2005) -- First full release as a package + + * Centralized Application configuration management + * Automatic cross-server API discovery + * Transparent remote server sub-requests + * Object Persistence Application implementing Stacks, Queues + and Object Stores based on SQLite + +# Version 0.3 (March/April 2005) -- Version for use in the Alpha + release of Open-ILS + + * Partial implementation of a BROADCAST mode for addressing all + Servers of a particular Class on one Router + * Distributed version of the Object Persistence Application + +# Version 0.5 (July/August 2005) + + * Full implementation of a BROADCAST mode for addressing all + Servers of any number of Classes on any number of Routers + * Client side use of transparent API discovery; the client + libraries will automatically discover and use the correct + Server for any valid method request + +# Version 0.7 (October/November 2005) + + * Basic inter-server session migration support in addition + to session failure recovery due to server failure + +# Version 0.9 (Some time in 2006) + + * Built in distributed transaction support. + +# Version 1.0 (in the future) + + * Who knows? + diff --git a/trunk/doc/dokuwiki-doc-stubber.pl b/trunk/doc/dokuwiki-doc-stubber.pl new file mode 100755 index 0000000..c098cc8 --- /dev/null +++ b/trunk/doc/dokuwiki-doc-stubber.pl @@ -0,0 +1,114 @@ +#!/usr/bin/perl -w +use OpenSRF::System qw(SYSCONFDIR/opensrf_core.xml); +use Getopt::Long + +$| = 1; + +my $cvs_base = 'http://open-ils.org/cgi-bin/viewcvs.cgi/ILS/Open-ILS/src/perlmods/'; +my $nest = 0; +my $service; +my $filter; +my $sort_ignore; + +GetOptions( 'cvs_base=s' => \$cvs_base, + 'nest' => \$nest, + 'service=s' => \$service, + 'ignore=s' => \$sort_ignore, + 'filter=s' => \$filter, +); + +unless( $service ) { + print "usage: $0 -s [-c -f -n]\n"; + exit; +} + +OpenSRF::System->bootstrap_client(); +my $session = OpenSRF::AppSession->create( $service ); + +my $req; +if ($filter) { + $req = $session->request('opensrf.system.method', $filter); +} else { + $req = $session->request('opensrf.system.method.all'); +} + +my $count = 1; +my %m; +while( my $meth = $req->recv(60) ) { + $meth = $meth->content; + + $api_name = $meth->{api_name}; + + $m{$api_name}{api_name} = $meth->{api_name}; + + $m{$api_name}{package} = $meth->{package}; + $m{$api_name}{method} = $meth->{method}; + + $m{$api_name}{api_level} = int $meth->{api_level}; + $m{$api_name}{server_class} = $meth->{server_class} || '**ALL**'; + $m{$api_name}{stream} = int($meth->{stream} || 0); + $m{$api_name}{cachable} = int($meth->{cachable} || 0); + + $m{$api_name}{note} = $meth->{note} || 'what I do'; + ($m{$api_name}{cvs} = $m{$api_name}{package}) =~ s/::/\//go; + + $m{$api_name}{stream} = $m{$api_name}{stream}?'Yes':'No'; + $m{$api_name}{cachable} = $m{$api_name}{cachable}?'Yes':'No'; + + print STDERR "." unless ($count % 10); + + $count++; +} + +warn "\nThere are ".scalar(keys %m)." methods published by $service\n"; + +my @m_list; +if (!$sort_ignore) { + @m_list = sort keys %m; +} else { + @m_list = + map { ($$_[0]) } + sort { + $$a[1] cmp $$b[1] + || + length($$b[0]) <=> length($$a[0]) + } map { + [$_ => + do { + (my $x = $_) =~ s/^$sort_ignore//go; + $x; + } ] + } keys %m; +} + +for my $meth ( @m_list ) { + + my $pad = 0; + my $header = '====='; + if ($nest) { + no warnings; + (my $x = $meth) =~ s/\./$pad++;$1/eg; + } + $pad = ' 'x$pad; + + print <<" METHOD"; +$pad$header $meth $header + +$m{$meth}{note} + + * [[osrf-devel:terms#opensrf_api-level|API Level]]: $m{$meth}{api_level} + * [[osrf-devel:terms#opensrf_server_class|Server Class]]: $m{$meth}{server_class} + * Implementation Method: [[$cvs_base/$m{$meth}{cvs}.pm|$m{$meth}{package}\::$m{$meth}{method}]] + * Streaming [[osrf-devel:terms#opensrf_method|Method]]: $m{$meth}{stream} + * Cachable [[osrf-devel:terms#opensrf_method|Method]]: $m{$meth}{cachable} + + * **Parameters:** + * //param1//\\\\ what it is... + * **Returns:** + * //Success//\\\\ successful format + * //Failure//\\\\ failure format (exception, etc) + + + METHOD +} + diff --git a/trunk/examples/fieldmapper2cdbi.xsl b/trunk/examples/fieldmapper2cdbi.xsl new file mode 100644 index 0000000..f6ad904 --- /dev/null +++ b/trunk/examples/fieldmapper2cdbi.xsl @@ -0,0 +1,79 @@ + + + + + + +1; + + + + + + + + + + + + + + + + + #------------------------------------------------------------------------------- + # Class definition for "" () + #------------------------------------------------------------------------------- + package ; + use base ''; + + __PACKAGE__->table(""); + + __PACKCAGE__->sequence(""); + + + __PACKAGE__->columns(Primary => ); + + __PACKAGE__->columns( + Essential => + ); + + + __PACKAGE__->columns( + Others => + ); + + + + + + + + + + + + '', + + + + + + + ->( + => '' + ); + + + + diff --git a/trunk/examples/fieldmapper2javascript.xsl b/trunk/examples/fieldmapper2javascript.xsl new file mode 100644 index 0000000..e2f8e1d --- /dev/null +++ b/trunk/examples/fieldmapper2javascript.xsl @@ -0,0 +1,297 @@ + + + + + + +// support functions + +var IE = false; +var unit_test = false; + +function instanceOf(object, constructorFunction) { + if(!IE) { + while (object != null) { + if (object == constructorFunction.prototype) + return true; + object = object.__proto__; + } + } else { + while(object != null) { + if( object instanceof constructorFunction ) + return true; + object = object.__proto__; + } + } + return false; +} + +// Top level superclass +function Fieldmapper(array) { + this.array = []; + if(array) { + if (array.constructor == Array) { + this.array = array; + } else if ( instanceOf( array, String ) || instanceOf( array, Number ) ) { + + var obj = null; + if (this.cacheable) { + try { + obj = this.baseClass.obj_cache[this.classname][array]; + } catch (E) {}; + } + + if (!obj) { + obj = user_request( + 'open-ils.proxy', + 'open-ils.proxy.proxy', + [ + mw.G.auth_ses[0], + 'open-ils.storage', + 'open-ils.storage.direct.' + this.db_type + '.retrieve', + array + ] + )[0]; + + if (this.cacheable) { + if (this.baseClass.obj_cache[this.classname] == null) + this.baseClass.obj_cache[this.classname] = {}; + + this.baseClass.obj_cache[this.classname][obj.id()] = obj; + } + } + this.array = obj.array; + + } else { + throw new FieldmapperException( "Attempt to build fieldmapper object with something wierd"); + } + } +} +Fieldmapper.prototype.baseClass = Fieldmapper; +Fieldmapper.prototype.obj_cache = {}; + +Fieldmapper.prototype.search function (type,field,value) { + + var list = user_request( + 'open-ils.proxy', + 'open-ils.proxy.proxy', + [ + mw.G.auth_ses[0], + 'open-ils.storage', + 'open-ils.storage.direct.' + type.db_type + '.search.' + field, + array + ] + )[0]; + if (type.cacheable) { + if (type.baseClass.obj_cache[type.classname] == null) + type.baseClass.obj_cache[type.classname] = {}; + for (var i in list) { + type.baseClass.obj_cache[type.classname][list[i].id()] = list[i]; + } + } + return list; +} + +Fieldmapper.prototype.clone = function() { + var obj = new this.constructor(); + + for( var i in this.array ) { + var thing = this.array[i]; + if(thing == null) continue; + + if( thing._isfieldmapper ) { + obj.array[i] = thing.clone(); + } else { + + if(instanceOf(thing, Array)) { + obj.array[i] = new Array(); + + for( var j in thing ) { + + if( thing[j]._isfieldmapper ) + obj.array[i][j] = thing[j].clone(); + else + obj.array[i][j] = thing[j]; + } + } else { + obj.array[i] = thing; + } + } + } + return obj; +} + +function FieldmapperException(message) { + this.message = message; +} + +FieldmapperException.toString = function() { + return "FieldmapperException: " + this.message + "\n"; + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// Class definition for "" + +function (array) { + + if (!instanceOf(this, )) + return new (array); + + this.baseClass.call(this,array); + this.classname = ""; + this._isfieldmapper = true; + this.uber = .baseClass.prototype; +} + +.prototype = new (); +.prototype.constructor = ; +.baseClass = ; +.prototype.cachable = true; +.prototype.fields = []; +.last_real_field = 2; + + +.prototype.db_type = ""; + +.prototype.isnew = function(new_value) { + if(arguments.length == 1) { this.array[0] = new_value; } + return this.array[0]; +} + +.prototype.ischanged = function(new_value) { + if(arguments.length == 1) { this.array[1] = new_value; } + return this.array[1]; +} + +.prototype.isdeleted = function(new_value) { + if(arguments.length == 1) { this.array[2] = new_value; } + return this.array[2]; +} + + + + + + + + + + + + + + + +// Accessor/mutator for .: +.last_real_field++; +.prototype.fields.push(""); +.prototype. = function (new_value) { + if(arguments.length == 1) { this.array[] = new_value; } + + + + + + var val = this.array[]; + + if (!instanceOf(this.array[], )) { + if (this.array[] != null) { + this.array[] = new (val); + } + } + + return this.array[]; +} + + + + + + + + + + + + + + + +// accessor for : +.prototype. = function () { + + var _pos = .last_real_field + ; + + if (!instanceOf(this.array[_pos], Array)) { + this.array[_pos] = []; + + if (this.array[_pos].length == 0) { + /* get the real thing. + * search where .() + * equals this.(); + */ + this.array[_pos] = this.uber.search( + , + "", + this.() + ); + } + + return this.array[_pos]; +} + + + + + + + + diff --git a/trunk/examples/fieldmapper2perl.xsl b/trunk/examples/fieldmapper2perl.xsl new file mode 100644 index 0000000..8ef601e --- /dev/null +++ b/trunk/examples/fieldmapper2perl.xsl @@ -0,0 +1,225 @@ + + + + + + +package Fieldmapper; +use OpenSRF::Utils::JSON; +use Data::Dumper; +use base 'OpenSRF::Application'; + +use OpenSRF::Utils::Logger; +my $log = 'OpenSRF::Utils::Logger'; + +sub new { + my $self = shift; + my $value = shift; + if (defined $value) { + if (!ref($value) or ref($value) ne 'ARRAY') { + # go fetch the object by id... + } + } else { + $value = []; + } + return bless $value => $self->class_name; +} + +sub decast { + my $self = shift; + return [ @$self ]; +} + +sub DESTROY {} + +sub class_name { + my $class_name = shift; + return ref($class_name) || $class_name; +} + +sub isnew { return $_[0][0]; } +sub ischanged { return $_[0][1]; } +sub isdeleted { return $_[0][2]; } + + + + +1; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +#------------------------------------------------------------------------------- +# Class definition for "" +#------------------------------------------------------------------------------- + +package ; +use base ""; + +{ my @real; + sub real_fields { + push @real, @_ if (@_); + return @real; + } +} + +{ my $last_real; + sub last_real_field : lvalue { + $last_real; + } +} + + +sub cdbi { + return ""; +} + + +sub json_hint { + return ""; +} + + +sub is_virtual { + + + return 1; + + + return 0; + + +} + + + + + + + + + + + + + + + + +# Accessor/mutator for ::: +__PACKAGE__->last_real_field()++; +__PACKAGE__->real_fields(""); +sub { + my $self = shift; + my $new_val = shift; + $self->[] = $new_val if (defined $new_val); + + + + + + + my $val = $self->[]; + + if (defined $self->[]) { + if (!UNIVERSAL::isa($self->[], )) { + $self->[] = ->new($val); + } + } + + + return $self->[]; +} + + +sub clear_ { + my $self = shift; + $self->[] = undef; + return 1; +} + + + + + + + + + + + + + + + + + + +# accessor for ::: +sub { + my $self = shift; + + my $_pos = ->last_real_field + ; + + if (!ref($self->[$_pos]) ne 'ARRAY') { + $self->[$_pos] = []; + + if (@{$self->[$_pos]} == 0) { + # get the real thing. + # search where -> == $self->; + } + + return $self->[$_pos]; +} + + + + + + + + diff --git a/trunk/examples/gen-fieldmapper.xml b/trunk/examples/gen-fieldmapper.xml new file mode 100644 index 0000000..2695030 --- /dev/null +++ b/trunk/examples/gen-fieldmapper.xml @@ -0,0 +1,327 @@ + + + + + + + + + + action.survey_response + action.survey_response_id_seq + + + action_survey_response + + + Fieldmapper + Fieldmapper + OpenILS::Storage::CDBI + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + action.survey_question + action.survey_question_id_seq + + + action_survey_question + + + Fieldmapper + Fieldmapper + OpenILS::Storage::CDBI + + + + + + + + + + + + + + + + + + + action.survey_answer + action.survey_answer_id_seq + + + action_survey_answer + + + Fieldmapper + Fieldmapper + OpenILS::Storage::CDBI + + + + + + + + + + + + + + + + + + + actor.org_unit + actor.org_unit_id_seq + + + actor_org_unit + + + Fieldmapper + Fieldmapper + OpenILS::Storage::CDBI + + + + + + + + + + action.survey + action.survey_id_seq + + + action_survey + + + Fieldmapper + Fieldmapper + OpenILS::Storage::CDBI + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/trunk/examples/math_bench.pl b/trunk/examples/math_bench.pl new file mode 100755 index 0000000..6dd94ac --- /dev/null +++ b/trunk/examples/math_bench.pl @@ -0,0 +1,77 @@ +#!/usr/bin/perl +use strict; use warnings; +use OpenSRF::System; +use Time::HiRes qw/time/; +use OpenSRF::Utils::Logger; +my $log = "OpenSRF::Utils::Logger"; + +# Test script which runs queries agains the opensrf.math service and reports on +# the average round trip time of the requests. + +# how many batches of 4 requests do we send +my $count = $ARGV[0]; +print "usage: $0 \n" and exit unless $count; + +# * connect to the Jabber network +OpenSRF::System->bootstrap_client( config_file => "SYSCONFDIR/opensrf_core.xml" ); +$log->set_service('math_bench'); + +# * create a new application session for the opensrf.math service +my $session = OpenSRF::AppSession->create( "opensrf.math" ); + +my @times; # "delta" times for each round trip + +# we're gonna call methods "add", "sub", "mult", and "div" with +# params 1, 2. The hash below maps the method name to the +# expected response value +my %vals = ( add => 3, sub => -1, mult => 2, div => 0.5 ); + +# print the counter grid +for my $x (1..100) { + if( $x % 10 ) { print ".";} + else{ print $x/10; }; +} +print "\n"; + +my $c = 0; + +for my $scale ( 1..$count ) { + for my $mname ( keys %vals ) { # cycle through add, sub, mult, and div + + my $starttime = time(); + + # * Fires the request and gathers the response object, which in this case + # is just a string + my $resp = $session->request( $mname, 1, 2 )->gather(1); + push @times, time() - $starttime; + + + if( "$resp" eq $vals{$mname} ) { + # we got the response we expected + print "+"; + + } elsif($resp) { + # we got some other response + print "\n* BAD Data: $resp\n"; + + } else { + # we got no data + print "Received nothing\n"; + } + + $c++; + + } + + print " [$c] \n" unless $scale % 25; +} + +my $total = 0; + +$total += $_ for (@times); + +$total /= scalar(@times); + +print "\n\n\tAverage Round Trip Time: $total Seconds\n"; + + diff --git a/trunk/examples/math_xul_client/Makefile.in b/trunk/examples/math_xul_client/Makefile.in new file mode 100644 index 0000000..41ac95c --- /dev/null +++ b/trunk/examples/math_xul_client/Makefile.in @@ -0,0 +1,19 @@ +all: clean client + @echo + +client: + @echo We need the OpenSRF javascript code... + mkdir math/content/OpenSRF/ + cp ../../src/javascript/*.js math/content/OpenSRF/ + @echo We need a log directory... + mkdir math/content/log + touch math/content/log/preserve.directory.when.zipping + @echo We also need a math/content/conf/client_config.xml pointing to a running OpenSRF Math application. + @echo Then we package this into a Mozilla XPI file... + zip -q -r math.xpi install.js math/ + @echo After installing the XPI, use the chrome URL: + @echo chrome://math/content/ + +clean: + @echo Removing the OpenSRF javascript code, the log directory, and math.xpi... + rm -rf math/content/OpenSRF/ math/content/log math.xpi diff --git a/trunk/examples/math_xul_client/install.js b/trunk/examples/math_xul_client/install.js new file mode 100644 index 0000000..0b10d3d --- /dev/null +++ b/trunk/examples/math_xul_client/install.js @@ -0,0 +1,98 @@ +// ripped from Evergreen installation file + +/* We'll want to make this more flexible later */ + +install(); + +// ---------------------------------------------------------------------------- +// Performs the install +// ---------------------------------------------------------------------------- +function install() { + + // ---------------------------------------------------------------------------- + var _authors = "PINES"; + var _package = "math"; + var _packg_l = "math"; + var _version = "0.0.1"; + // ---------------------------------------------------------------------------- + + var err; // track the error + + err = initInstall( _package, "/"+_authors+"/"+_package, _version ); + if( err != 0 ) { return warn( "initInstall: " + err );} + + // ---------------------------------------------------------------------------- + // Discovers the path to the install directory + // ---------------------------------------------------------------------------- + install_dir = getFolder("Chrome", _packg_l ); + logComment( "Installing to: " + install_dir ); + + // ---------------------------------------------------------------------------- + // Directory where the 'content' is stored + // ---------------------------------------------------------------------------- + content_dir = getFolder( install_dir, "content" ); + if( err != 0 ) { return warn("getFolder:content_dir: " + err);} + + // ---------------------------------------------------------------------------- + // Directory where the skins are stored + // ---------------------------------------------------------------------------- + skin_dir = getFolder( install_dir, "skin" ); + if( err != 0 ) { return warn("getFolder:skin: " + err);} + + // ---------------------------------------------------------------------------- + // Directory where the local data is stored + // ---------------------------------------------------------------------------- + locale_dir = getFolder( install_dir, "locale" ); + if( err != 0 ) { return warn("getFolder:locale: " + err);} + + // ---------------------------------------------------------------------------- + // Sets the install directory for Evergreen + // ---------------------------------------------------------------------------- + err = setPackageFolder(install_dir); + if( err != 0 ) { return warn("setPackageFolder: " + err);} + + // ---------------------------------------------------------------------------- + // Searches the .xpi file for the directory name stored in _packg_l and + // copies that directory from the .xpi into Mozilla's chrome directory. + // In this case, we are copying over the entire evergreen folder + // ---------------------------------------------------------------------------- + err = addDirectory( _packg_l ) + if( err != 0 ) { return warn("addDirectory: " + err);} + + + // ---------------------------------------------------------------------------- + // Register the content directory + // The final argument is where Mozilla should expect to find the contents.rdf + // file *after* installation for the CONTENT portion of the package + // ---------------------------------------------------------------------------- + err = registerChrome( Install.CONTENT, content_dir ); + if( err != 0 ) { return warn("registerChrome:content " + err );} + + // ---------------------------------------------------------------------------- + // Register the skin directory + // ---------------------------------------------------------------------------- + err = registerChrome( Install.SKIN, skin_dir ); + if( err != 0 ) { return warn("registerChrome:skin " + err );} + + // ---------------------------------------------------------------------------- + // Register the locale directory + // ---------------------------------------------------------------------------- + //err = registerChrome( Install.LOCALE, locale_dir ); + //if( err != 0 ) { return warn("registerChrome:locale " + err );} + + err = registerChrome( Install.LOCALE, getFolder(locale_dir, "en-US") ); + if( err != 0 ) { return warn("registerChrome:locale " + err );} + + // ---------------------------------------------------------------------------- + // Do it. + // ---------------------------------------------------------------------------- + performInstall(); + +} + +function warn( message ) { + alert( message ); + logComment( message ); + return; +} + diff --git a/trunk/examples/math_xul_client/math/content/conf/client_config.xml b/trunk/examples/math_xul_client/math/content/conf/client_config.xml new file mode 100644 index 0000000..0dc75a9 --- /dev/null +++ b/trunk/examples/math_xul_client/math/content/conf/client_config.xml @@ -0,0 +1,53 @@ + + + + + + + + myhostname + + + 0 + + + 0 + + + + + + + debug.log + transport.log + error.log + + + + + + router@localhost/math + router@localhost/mathdb + router@localhost/storage + + + + + + jabber_connection + + + 15 + math_user + math_user_password + localhost + 5222 + 0 + + + diff --git a/trunk/examples/math_xul_client/math/content/contents.rdf b/trunk/examples/math_xul_client/math/content/contents.rdf new file mode 100644 index 0000000..7a8fb13 --- /dev/null +++ b/trunk/examples/math_xul_client/math/content/contents.rdf @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/trunk/examples/math_xul_client/math/content/math.xul b/trunk/examples/math_xul_client/math/content/math.xul new file mode 100644 index 0000000..d6a1371 --- /dev/null +++ b/trunk/examples/math_xul_client/math/content/math.xul @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + +