Commit de9a13c0 authored by Yoshinori Okuji's avatar Yoshinori Okuji

Initial import


git-svn-id: https://svn.erp5.org/repos/neo/trunk@1 71dcc9de-d417-0410-9af5-da40c76e7ee4
parents
Aur?lien Calonne <aurel@nexedi.com>
Yoshinori Okuji <yo@nexedi.com>
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.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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.
<signature of Ty Coon>, 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.
2005-07-01 Aurelien Calonne <aurel@nexedi.com>
* src/master_node.c (h_beginTrans):
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
Foundation, Inc.
This file is free documentation; the Free Software Foundation gives
unlimited permission to copy, distribute and modify it.
Basic Installation
==================
These are generic installation instructions.
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 only 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. If you're
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
Running `configure' takes awhile. 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.
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=c89 CFLAGS=-O2 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 must use a version of `make' that
supports the `VPATH' variable, such as 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 `..'.
If you have to use a `make' that does not support the `VPATH'
variable, you have 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' will install the package's files in
`/usr/local/bin', `/usr/local/man', etc. You can specify an
installation prefix other than `/usr/local' by giving `configure' the
option `--prefix=PATH'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
give `configure' the option `--exec-prefix=PATH', the package will use
PATH as the prefix for installing programs and libraries.
Documentation and other data files will still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=PATH' 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 `--target=TYPE' option 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
will cause the specified gcc to be used as the C compiler (unless it is
overridden in the site shell script).
`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.
SUBDIRS = include lib master storage test doc client
# Makefile.in generated by automake 1.7.9 from Makefile.am.
# @configure_input@
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
# Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = .
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
ACLOCAL = @ACLOCAL@
AMDEP_FALSE = @AMDEP_FALSE@
AMDEP_TRUE = @AMDEP_TRUE@
AMTAR = @AMTAR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
MAKEINFO = @MAKEINFO@
MYSQL_CONFIG = @MYSQL_CONFIG@
MYSQL_INCLUDE = @MYSQL_INCLUDE@
MYSQL_LDFLAGS = @MYSQL_LDFLAGS@
MYSQL_LIBS = @MYSQL_LIBS@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PYTHON = @PYTHON@
PYTHON_BASECFLAGS = @PYTHON_BASECFLAGS@
PYTHON_CC = @PYTHON_CC@
PYTHON_CCSHARED = @PYTHON_CCSHARED@
PYTHON_INCLUDE = @PYTHON_INCLUDE@
PYTHON_LDSHARED = @PYTHON_LDSHARED@
PYTHON_OPT = @PYTHON_OPT@
PYTHON_SO = @PYTHON_SO@
RANLIB = @RANLIB@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
ac_ct_CC = @ac_ct_CC@
ac_ct_RANLIB = @ac_ct_RANLIB@
ac_ct_STRIP = @ac_ct_STRIP@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
bindir = @bindir@
build_alias = @build_alias@
datadir = @datadir@
exec_prefix = @exec_prefix@
host_alias = @host_alias@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localstatedir = @localstatedir@
mandir = @mandir@
oldincludedir = @oldincludedir@
prefix = @prefix@
program_transform_name = @program_transform_name@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
SUBDIRS = include lib master storage test doc client
subdir = .
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = config.h
CONFIG_CLEAN_FILES =
DIST_SOURCES =
RECURSIVE_TARGETS = info-recursive dvi-recursive pdf-recursive \
ps-recursive install-info-recursive uninstall-info-recursive \
all-recursive install-data-recursive install-exec-recursive \
installdirs-recursive install-recursive uninstall-recursive \
check-recursive installcheck-recursive
DIST_COMMON = README $(srcdir)/Makefile.in $(srcdir)/configure AUTHORS \
COPYING ChangeLog INSTALL Makefile.am NEWS aclocal.m4 \
config.h.in configure configure.ac depcomp install-sh missing \
mkinstalldirs
DIST_SUBDIRS = $(SUBDIRS)
all: config.h
$(MAKE) $(AM_MAKEFLAGS) all-recursive
.SUFFIXES:
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
configure.lineno
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4)
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu Makefile
Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)
$(top_builddir)/config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
$(SHELL) ./config.status --recheck
$(srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(srcdir)/configure.ac $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
cd $(srcdir) && $(AUTOCONF)
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ configure.ac
cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
config.h: stamp-h1
@if test ! -f $@; then \
rm -f stamp-h1; \
$(MAKE) stamp-h1; \
else :; fi
stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
@rm -f stamp-h1
cd $(top_builddir) && $(SHELL) ./config.status config.h
$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(top_srcdir)/configure.ac $(ACLOCAL_M4)
cd $(top_srcdir) && $(AUTOHEADER)
touch $(srcdir)/config.h.in
distclean-hdr:
-rm -f config.h stamp-h1
uninstall-info-am:
# This directory's subdirectories are mostly independent; you can cd
# into them and run `make' without going through this Makefile.
# To change the values of `make' variables: instead of editing Makefiles,
# (1) if the variable is set in `config.status', edit `config.status'
# (which will cause the Makefiles to be regenerated when you run `make');
# (2) otherwise, pass the desired values on the `make' command line.
$(RECURSIVE_TARGETS):
@set fnord $$MAKEFLAGS; amf=$$2; \
dot_seen=no; \
target=`echo $@ | sed s/-recursive//`; \
list='$(SUBDIRS)'; for subdir in $$list; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
dot_seen=yes; \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
done; \
if test "$$dot_seen" = "no"; then \
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
fi; test -z "$$fail"
mostlyclean-recursive clean-recursive distclean-recursive \
maintainer-clean-recursive:
@set fnord $$MAKEFLAGS; amf=$$2; \
dot_seen=no; \
case "$@" in \
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
*) list='$(SUBDIRS)' ;; \
esac; \
rev=''; for subdir in $$list; do \
if test "$$subdir" = "."; then :; else \
rev="$$subdir $$rev"; \
fi; \
done; \
rev="$$rev ."; \
target=`echo $@ | sed s/-recursive//`; \
for subdir in $$rev; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
done && test -z "$$fail"
tags-recursive:
list='$(SUBDIRS)'; for subdir in $$list; do \
test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
done
ctags-recursive:
list='$(SUBDIRS)'; for subdir in $$list; do \
test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
done
ETAGS = etags
ETAGSFLAGS =
CTAGS = ctags
CTAGSFLAGS =
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
mkid -fID $$unique
TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
if (etags --etags-include --version) >/dev/null 2>&1; then \
include_option=--etags-include; \
else \
include_option=--include; \
fi; \
list='$(SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test -f $$subdir/TAGS && \
tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
fi; \
done; \
list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)$$tags$$unique" \
|| $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique
ctags: CTAGS
CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$tags $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& cd $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) $$here
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
top_distdir = .
distdir = $(PACKAGE)-$(VERSION)
am__remove_distdir = \
{ test ! -d $(distdir) \
|| { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \
&& rm -fr $(distdir); }; }
GZIP_ENV = --best
distuninstallcheck_listfiles = find . -type f -print
distcleancheck_listfiles = find . -type f -print
distdir: $(DISTFILES)
$(am__remove_distdir)
mkdir $(distdir)
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
list='$(DISTFILES)'; for file in $$list; do \
case $$file in \
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
esac; \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkinstalldirs) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
list='$(SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test -d $(distdir)/$$subdir \
|| mkdir $(distdir)/$$subdir \
|| exit 1; \
(cd $$subdir && \
$(MAKE) $(AM_MAKEFLAGS) \
top_distdir="$(top_distdir)" \
distdir=../$(distdir)/$$subdir \
distdir) \
|| exit 1; \
fi; \
done
-find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
! -type d ! -perm -400 -exec chmod a+r {} \; -o \
! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \
|| chmod -R a+r $(distdir)
dist-gzip: distdir
$(AMTAR) chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
$(am__remove_distdir)
dist dist-all: distdir
$(AMTAR) chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
$(am__remove_distdir)
# This target untars the dist file and tries a VPATH configuration. Then
# it guarantees that the distribution is self-contained by making another
# tarfile.
distcheck: dist
$(am__remove_distdir)
GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(AMTAR) xf -
chmod -R a-w $(distdir); chmod a+w $(distdir)
mkdir $(distdir)/_build
mkdir $(distdir)/_inst
chmod a-w $(distdir)
dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
&& dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
&& cd $(distdir)/_build \
&& ../configure --srcdir=.. --prefix="$$dc_install_base" \
$(DISTCHECK_CONFIGURE_FLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
&& $(MAKE) $(AM_MAKEFLAGS) check \
&& $(MAKE) $(AM_MAKEFLAGS) install \
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
&& $(MAKE) $(AM_MAKEFLAGS) uninstall \
&& $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
distuninstallcheck \
&& chmod -R a-w "$$dc_install_base" \
&& ({ \
(cd ../.. && $(mkinstalldirs) "$$dc_destdir") \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
} || { rm -rf "$$dc_destdir"; exit 1; }) \
&& rm -rf "$$dc_destdir" \
&& $(MAKE) $(AM_MAKEFLAGS) dist-gzip \
&& rm -f $(distdir).tar.gz \
&& $(MAKE) $(AM_MAKEFLAGS) distcleancheck
$(am__remove_distdir)
@echo "$(distdir).tar.gz is ready for distribution" | \
sed 'h;s/./=/g;p;x;p;x'
distuninstallcheck:
@cd $(distuninstallcheck_dir) \
&& test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
|| { echo "ERROR: files left after uninstall:" ; \
if test -n "$(DESTDIR)"; then \
echo " (check DESTDIR support)"; \
fi ; \
$(distuninstallcheck_listfiles) ; \
exit 1; } >&2
distcleancheck: distclean
@if test '$(srcdir)' = . ; then \
echo "ERROR: distcleancheck can only run from a VPATH build" ; \
exit 1 ; \
fi
@test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
|| { echo "ERROR: files left in build directory after distclean:" ; \
$(distcleancheck_listfiles) ; \
exit 1; } >&2
check-am: all-am
check: check-recursive
all-am: Makefile config.h
installdirs: installdirs-recursive
installdirs-am:
install: install-recursive
install-exec: install-exec-recursive
install-data: install-data-recursive
uninstall: uninstall-recursive
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-recursive
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-recursive
clean-am: clean-generic mostlyclean-am
distclean: distclean-recursive
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -f Makefile
distclean-am: clean-am distclean-generic distclean-hdr distclean-tags
dvi: dvi-recursive
dvi-am:
info: info-recursive
info-am:
install-data-am:
install-exec-am:
install-info: install-info-recursive
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-recursive
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -rf $(top_srcdir)/autom4te.cache
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-recursive
mostlyclean-am: mostlyclean-generic
pdf: pdf-recursive
pdf-am:
ps: ps-recursive
ps-am:
uninstall-am: uninstall-info-am
uninstall-info: uninstall-info-recursive
.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am clean \
clean-generic clean-recursive ctags ctags-recursive dist \
dist-all dist-gzip distcheck distclean distclean-generic \
distclean-hdr distclean-recursive distclean-tags distcleancheck \
distdir distuninstallcheck dvi dvi-am dvi-recursive info \
info-am info-recursive install install-am install-data \
install-data-am install-data-recursive install-exec \
install-exec-am install-exec-recursive install-info \
install-info-am install-info-recursive install-man \
install-recursive install-strip installcheck installcheck-am \
installdirs installdirs-am installdirs-recursive \
maintainer-clean maintainer-clean-generic \
maintainer-clean-recursive mostlyclean mostlyclean-generic \
mostlyclean-recursive pdf pdf-am pdf-recursive ps ps-am \
ps-recursive tags tags-recursive uninstall uninstall-am \
uninstall-info-am uninstall-info-recursive uninstall-recursive
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
Nexedi Enterprise Objects
# generated automatically by aclocal 1.7.9 -*- Autoconf -*-
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002
# Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
# Do all the work for Automake. -*- Autoconf -*-
# This macro actually does too much some checks are only needed if
# your package does certain things. But this isn't really a big deal.
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
# Free Software Foundation, Inc.
# 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, 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.
# serial 10
AC_PREREQ([2.54])
# Autoconf 2.50 wants to disallow AM_ names. We explicitly allow
# the ones we care about.
m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
# AM_INIT_AUTOMAKE([OPTIONS])
# -----------------------------------------------
# The call with PACKAGE and VERSION arguments is the old style
# call (pre autoconf-2.50), which is being phased out. PACKAGE
# and VERSION should now be passed to AC_INIT and removed from
# the call to AM_INIT_AUTOMAKE.
# We support both call styles for the transition. After
# the next Automake release, Autoconf can make the AC_INIT
# arguments mandatory, and then we can depend on a new Autoconf
# release and drop the old call support.
AC_DEFUN([AM_INIT_AUTOMAKE],
[AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
AC_REQUIRE([AC_PROG_INSTALL])dnl
# test to see if srcdir already configured
if test "`cd $srcdir && pwd`" != "`pwd`" &&
test -f $srcdir/config.status; then
AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
fi
# test whether we have cygpath
if test -z "$CYGPATH_W"; then
if (cygpath --version) >/dev/null 2>/dev/null; then
CYGPATH_W='cygpath -w'
else
CYGPATH_W=echo
fi
fi
AC_SUBST([CYGPATH_W])
# Define the identity of the package.
dnl Distinguish between old-style and new-style calls.
m4_ifval([$2],
[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
AC_SUBST([PACKAGE], [$1])dnl
AC_SUBST([VERSION], [$2])],
[_AM_SET_OPTIONS([$1])dnl
AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
_AM_IF_OPTION([no-define],,
[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
# Some tools Automake needs.
AC_REQUIRE([AM_SANITY_CHECK])dnl
AC_REQUIRE([AC_ARG_PROGRAM])dnl
AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
AM_MISSING_PROG(AUTOCONF, autoconf)
AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
AM_MISSING_PROG(AUTOHEADER, autoheader)
AM_MISSING_PROG(MAKEINFO, makeinfo)
AM_MISSING_PROG(AMTAR, tar)
AM_PROG_INSTALL_SH
AM_PROG_INSTALL_STRIP
# We need awk for the "check" target. The system "awk" is bad on
# some platforms.
AC_REQUIRE([AC_PROG_AWK])dnl
AC_REQUIRE([AC_PROG_MAKE_SET])dnl
AC_REQUIRE([AM_SET_LEADING_DOT])dnl
_AM_IF_OPTION([no-dependencies],,
[AC_PROVIDE_IFELSE([AC_PROG_CC],
[_AM_DEPENDENCIES(CC)],
[define([AC_PROG_CC],
defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
AC_PROVIDE_IFELSE([AC_PROG_CXX],
[_AM_DEPENDENCIES(CXX)],
[define([AC_PROG_CXX],
defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
])
])
# When config.status generates a header, we must update the stamp-h file.
# This file resides in the same directory as the config header
# that is generated. The stamp files are numbered to have different names.
# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
# loop where config.status creates the headers, so we can generate
# our stamp files there.
AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
[# Compute $1's index in $config_headers.
_am_stamp_count=1
for _am_header in $config_headers :; do
case $_am_header in
$1 | $1:* )
break ;;
* )
_am_stamp_count=`expr $_am_stamp_count + 1` ;;
esac
done
echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count])
# Copyright 2002 Free Software Foundation, Inc.
# 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, 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
# AM_AUTOMAKE_VERSION(VERSION)
# ----------------------------
# Automake X.Y traces this macro to ensure aclocal.m4 has been
# generated from the m4 files accompanying Automake X.Y.
AC_DEFUN([AM_AUTOMAKE_VERSION],[am__api_version="1.7"])
# AM_SET_CURRENT_AUTOMAKE_VERSION
# -------------------------------
# Call AM_AUTOMAKE_VERSION so it can be traced.
# This function is AC_REQUIREd by AC_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
[AM_AUTOMAKE_VERSION([1.7.9])])
# Helper functions for option handling. -*- Autoconf -*-
# Copyright 2001, 2002 Free Software Foundation, Inc.
# 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, 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.
# serial 2
# _AM_MANGLE_OPTION(NAME)
# -----------------------
AC_DEFUN([_AM_MANGLE_OPTION],
[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
# _AM_SET_OPTION(NAME)
# ------------------------------
# Set option NAME. Presently that only means defining a flag for this option.
AC_DEFUN([_AM_SET_OPTION],
[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
# _AM_SET_OPTIONS(OPTIONS)
# ----------------------------------
# OPTIONS is a space-separated list of Automake options.
AC_DEFUN([_AM_SET_OPTIONS],
[AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
# -------------------------------------------
# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
AC_DEFUN([_AM_IF_OPTION],
[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
#
# Check to make sure that the build environment is sane.
#
# Copyright 1996, 1997, 2000, 2001 Free Software Foundation, Inc.
# 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, 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.
# serial 3
# AM_SANITY_CHECK
# ---------------
AC_DEFUN([AM_SANITY_CHECK],
[AC_MSG_CHECKING([whether build environment is sane])
# Just in case
sleep 1
echo timestamp > conftest.file
# Do `set' in a subshell so we don't clobber the current shell's
# arguments. Must try -L first in case configure is actually a
# symlink; some systems play weird games with the mod time of symlinks
# (eg FreeBSD returns the mod time of the symlink's containing
# directory).
if (
set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
if test "$[*]" = "X"; then
# -L didn't work.
set X `ls -t $srcdir/configure conftest.file`
fi
rm -f conftest.file
if test "$[*]" != "X $srcdir/configure conftest.file" \
&& test "$[*]" != "X conftest.file $srcdir/configure"; then
# If neither matched, then we have a broken ls. This can happen
# if, for instance, CONFIG_SHELL is bash and it inherits a
# broken ls alias from the environment. This has actually
# happened. Such a system could not be considered "sane".
AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
alias in your environment])
fi
test "$[2]" = conftest.file
)
then
# Ok.
:
else
AC_MSG_ERROR([newly created file is older than distributed files!
Check your system clock])
fi
AC_MSG_RESULT(yes)])
# -*- Autoconf -*-
# Copyright 1997, 1999, 2000, 2001 Free Software Foundation, Inc.
# 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, 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.
# serial 3
# AM_MISSING_PROG(NAME, PROGRAM)
# ------------------------------
AC_DEFUN([AM_MISSING_PROG],
[AC_REQUIRE([AM_MISSING_HAS_RUN])
$1=${$1-"${am_missing_run}$2"}
AC_SUBST($1)])
# AM_MISSING_HAS_RUN
# ------------------
# Define MISSING if not defined so far and test if it supports --run.
# If it does, set am_missing_run to use it, otherwise, to nothing.
AC_DEFUN([AM_MISSING_HAS_RUN],
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
# Use eval to expand $SHELL
if eval "$MISSING --run true"; then
am_missing_run="$MISSING --run "
else
am_missing_run=
AC_MSG_WARN([`missing' script is too old or missing])
fi
])
# AM_AUX_DIR_EXPAND
# Copyright 2001 Free Software Foundation, Inc.
# 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, 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.
# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to
# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
#
# Of course, Automake must honor this variable whenever it calls a
# tool from the auxiliary directory. The problem is that $srcdir (and
# therefore $ac_aux_dir as well) can be either absolute or relative,
# depending on how configure is run. This is pretty annoying, since
# it makes $ac_aux_dir quite unusable in subdirectories: in the top
# source directory, any form will work fine, but in subdirectories a
# relative path needs to be adjusted first.
#
# $ac_aux_dir/missing
# fails when called from a subdirectory if $ac_aux_dir is relative
# $top_srcdir/$ac_aux_dir/missing
# fails if $ac_aux_dir is absolute,
# fails when called from a subdirectory in a VPATH build with
# a relative $ac_aux_dir
#
# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
# are both prefixed by $srcdir. In an in-source build this is usually
# harmless because $srcdir is `.', but things will broke when you
# start a VPATH build or use an absolute $srcdir.
#
# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
# iff we strip the leading $srcdir from $ac_aux_dir. That would be:
# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
# and then we would define $MISSING as
# MISSING="\${SHELL} $am_aux_dir/missing"
# This will work as long as MISSING is not called from configure, because
# unfortunately $(top_srcdir) has no meaning in configure.
# However there are other variables, like CC, which are often used in
# configure, and could therefore not use this "fixed" $ac_aux_dir.
#
# Another solution, used here, is to always expand $ac_aux_dir to an
# absolute PATH. The drawback is that using absolute paths prevent a
# configured tree to be moved without reconfiguration.
# Rely on autoconf to set up CDPATH properly.
AC_PREREQ([2.50])
AC_DEFUN([AM_AUX_DIR_EXPAND], [
# expand $ac_aux_dir to an absolute path
am_aux_dir=`cd $ac_aux_dir && pwd`
])
# AM_PROG_INSTALL_SH
# ------------------
# Define $install_sh.
# Copyright 2001 Free Software Foundation, Inc.
# 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, 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.
AC_DEFUN([AM_PROG_INSTALL_SH],
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
install_sh=${install_sh-"$am_aux_dir/install-sh"}
AC_SUBST(install_sh)])
# AM_PROG_INSTALL_STRIP
# Copyright 2001 Free Software Foundation, Inc.
# 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, 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.
# One issue with vendor `install' (even GNU) is that you can't
# specify the program used to strip binaries. This is especially
# annoying in cross-compiling environments, where the build's strip
# is unlikely to handle the host's binaries.
# Fortunately install-sh will honor a STRIPPROG variable, so we
# always use install-sh in `make install-strip', and initialize
# STRIPPROG with the value of the STRIP variable (set by the user).
AC_DEFUN([AM_PROG_INSTALL_STRIP],
[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
# Installed binaries are usually stripped using `strip' when the user
# run `make install-strip'. However `strip' might not be the right
# tool to use in cross-compilation environments, therefore Automake
# will honor the `STRIP' environment variable to overrule this program.
dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
if test "$cross_compiling" != no; then
AC_CHECK_TOOL([STRIP], [strip], :)
fi
INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s"
AC_SUBST([INSTALL_STRIP_PROGRAM])])
# -*- Autoconf -*-
# Copyright (C) 2003 Free Software Foundation, Inc.
# 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, 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.
# serial 1
# Check whether the underlying file-system supports filenames
# with a leading dot. For instance MS-DOS doesn't.
AC_DEFUN([AM_SET_LEADING_DOT],
[rm -rf .tst 2>/dev/null
mkdir .tst 2>/dev/null
if test -d .tst; then
am__leading_dot=.
else
am__leading_dot=_
fi
rmdir .tst 2>/dev/null
AC_SUBST([am__leading_dot])])
# serial 5 -*- Autoconf -*-
# Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
# 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, 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.
# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
# written in clear, in which case automake, when reading aclocal.m4,
# will think it sees a *use*, and therefore will trigger all it's
# C support machinery. Also note that it means that autoscan, seeing
# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
# _AM_DEPENDENCIES(NAME)
# ----------------------
# See how the compiler implements dependency checking.
# NAME is "CC", "CXX", "GCJ", or "OBJC".
# We try a few techniques and use that to set a single cache variable.
#
# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
# dependency, and given that the user is not expected to run this macro,
# just rely on AC_PROG_CC.
AC_DEFUN([_AM_DEPENDENCIES],
[AC_REQUIRE([AM_SET_DEPDIR])dnl
AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
AC_REQUIRE([AM_MAKE_INCLUDE])dnl
AC_REQUIRE([AM_DEP_TRACK])dnl
ifelse([$1], CC, [depcc="$CC" am_compiler_list=],
[$1], CXX, [depcc="$CXX" am_compiler_list=],
[$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
[$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'],
[depcc="$$1" am_compiler_list=])
AC_CACHE_CHECK([dependency style of $depcc],
[am_cv_$1_dependencies_compiler_type],
[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
# We make a subdir and do the tests there. Otherwise we can end up
# making bogus files that we don't know about and never remove. For
# instance it was reported that on HP-UX the gcc test will end up
# making a dummy file named `D' -- because `-MD' means `put the output
# in D'.
mkdir conftest.dir
# Copy depcomp to subdir because otherwise we won't find it if we're
# using a relative directory.
cp "$am_depcomp" conftest.dir
cd conftest.dir
# We will build objects and dependencies in a subdirectory because
# it helps to detect inapplicable dependency modes. For instance
# both Tru64's cc and ICC support -MD to output dependencies as a
# side effect of compilation, but ICC will put the dependencies in
# the current directory while Tru64 will put them in the object
# directory.
mkdir sub
am_cv_$1_dependencies_compiler_type=none
if test "$am_compiler_list" = ""; then
am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
fi
for depmode in $am_compiler_list; do
# Setup a source with many dependencies, because some compilers
# like to wrap large dependency lists on column 80 (with \), and
# we should not choose a depcomp mode which is confused by this.
#
# We need to recreate these files for each test, as the compiler may
# overwrite some of them when testing with obscure command lines.
# This happens at least with the AIX C compiler.
: > sub/conftest.c
for i in 1 2 3 4 5 6; do
echo '#include "conftst'$i'.h"' >> sub/conftest.c
: > sub/conftst$i.h
done
echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
case $depmode in
nosideeffect)
# after this tag, mechanisms are not by side-effect, so they'll
# only be used when explicitly requested
if test "x$enable_dependency_tracking" = xyes; then
continue
else
break
fi
;;
none) break ;;
esac
# We check with `-c' and `-o' for the sake of the "dashmstdout"
# mode. It turns out that the SunPro C++ compiler does not properly
# handle `-M -o', and we need to detect this.
if depmode=$depmode \
source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
$SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
>/dev/null 2>conftest.err &&
grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
${MAKE-make} -s -f confmf > /dev/null 2>&1; then
# icc doesn't choke on unknown options, it will just issue warnings
# (even with -Werror). So we grep stderr for any message
# that says an option was ignored.
if grep 'ignoring option' conftest.err >/dev/null 2>&1; then :; else
am_cv_$1_dependencies_compiler_type=$depmode
break
fi
fi
done
cd ..
rm -rf conftest.dir
else
am_cv_$1_dependencies_compiler_type=none
fi
])
AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
AM_CONDITIONAL([am__fastdep$1], [
test "x$enable_dependency_tracking" != xno \
&& test "$am_cv_$1_dependencies_compiler_type" = gcc3])
])
# AM_SET_DEPDIR
# -------------
# Choose a directory name for dependency files.
# This macro is AC_REQUIREd in _AM_DEPENDENCIES
AC_DEFUN([AM_SET_DEPDIR],
[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
])
# AM_DEP_TRACK
# ------------
AC_DEFUN([AM_DEP_TRACK],
[AC_ARG_ENABLE(dependency-tracking,
[ --disable-dependency-tracking Speeds up one-time builds
--enable-dependency-tracking Do not reject slow dependency extractors])
if test "x$enable_dependency_tracking" != xno; then
am_depcomp="$ac_aux_dir/depcomp"
AMDEPBACKSLASH='\'
fi
AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
AC_SUBST([AMDEPBACKSLASH])
])
# Generate code to set up dependency tracking. -*- Autoconf -*-
# Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
# 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, 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.
#serial 2
# _AM_OUTPUT_DEPENDENCY_COMMANDS
# ------------------------------
AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
[for mf in $CONFIG_FILES; do
# Strip MF so we end up with the name of the file.
mf=`echo "$mf" | sed -e 's/:.*$//'`
# Check whether this is an Automake generated Makefile or not.
# We used to match only the files named `Makefile.in', but
# some people rename them; so instead we look at the file content.
# Grep'ing the first line is not enough: some people post-process
# each Makefile.in and add a new line on top of each file to say so.
# So let's grep whole file.
if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then
dirpart=`AS_DIRNAME("$mf")`
else
continue
fi
grep '^DEP_FILES *= *[[^ @%:@]]' < "$mf" > /dev/null || continue
# Extract the definition of DEP_FILES from the Makefile without
# running `make'.
DEPDIR=`sed -n -e '/^DEPDIR = / s///p' < "$mf"`
test -z "$DEPDIR" && continue
# When using ansi2knr, U may be empty or an underscore; expand it
U=`sed -n -e '/^U = / s///p' < "$mf"`
test -d "$dirpart/$DEPDIR" || mkdir "$dirpart/$DEPDIR"
# We invoke sed twice because it is the simplest approach to
# changing $(DEPDIR) to its actual value in the expansion.
for file in `sed -n -e '
/^DEP_FILES = .*\\\\$/ {
s/^DEP_FILES = //
:loop
s/\\\\$//
p
n
/\\\\$/ b loop
p
}
/^DEP_FILES = / s/^DEP_FILES = //p' < "$mf" | \
sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
# Make sure the directory exists.
test -f "$dirpart/$file" && continue
fdir=`AS_DIRNAME(["$file"])`
AS_MKDIR_P([$dirpart/$fdir])
# echo "creating $dirpart/$file"
echo '# dummy' > "$dirpart/$file"
done
done
])# _AM_OUTPUT_DEPENDENCY_COMMANDS
# AM_OUTPUT_DEPENDENCY_COMMANDS
# -----------------------------
# This macro should only be invoked once -- use via AC_REQUIRE.
#
# This code is only required when automatic dependency tracking
# is enabled. FIXME. This creates each `.P' file that we will
# need in order to bootstrap the dependency handling code.
AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
[AC_CONFIG_COMMANDS([depfiles],
[test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
[AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
])
# Check to see how 'make' treats includes. -*- Autoconf -*-
# Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
# 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, 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.
# serial 2
# AM_MAKE_INCLUDE()
# -----------------
# Check to see how make treats includes.
AC_DEFUN([AM_MAKE_INCLUDE],
[am_make=${MAKE-make}
cat > confinc << 'END'
am__doit:
@echo done
.PHONY: am__doit
END
# If we don't find an include directive, just comment out the code.
AC_MSG_CHECKING([for style of include used by $am_make])
am__include="#"
am__quote=
_am_result=none
# First try GNU make style include.
echo "include confinc" > confmf
# We grep out `Entering directory' and `Leaving directory'
# messages which can occur if `w' ends up in MAKEFLAGS.
# In particular we don't look at `^make:' because GNU make might
# be invoked under some other name (usually "gmake"), in which
# case it prints its new name instead of `make'.
if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then
am__include=include
am__quote=
_am_result=GNU
fi
# Now try BSD make style include.
if test "$am__include" = "#"; then
echo '.include "confinc"' > confmf
if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
am__include=.include
am__quote="\""
_am_result=BSD
fi
fi
AC_SUBST([am__include])
AC_SUBST([am__quote])
AC_MSG_RESULT([$_am_result])
rm -f confinc confmf
])
# AM_CONDITIONAL -*- Autoconf -*-
# Copyright 1997, 2000, 2001 Free Software Foundation, Inc.
# 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, 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.
# serial 5
AC_PREREQ(2.52)
# AM_CONDITIONAL(NAME, SHELL-CONDITION)
# -------------------------------------
# Define a conditional.
AC_DEFUN([AM_CONDITIONAL],
[ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
[$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
AC_SUBST([$1_TRUE])
AC_SUBST([$1_FALSE])
if $2; then
$1_TRUE=
$1_FALSE='#'
else
$1_TRUE='#'
$1_FALSE=
fi
AC_CONFIG_COMMANDS_PRE(
[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
AC_MSG_ERROR([conditional "$1" was never defined.
Usually this means the macro was only invoked conditionally.])
fi])])
# Add --enable-maintainer-mode option to configure.
# From Jim Meyering
# Copyright 1996, 1998, 2000, 2001, 2002 Free Software Foundation, Inc.
# 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, 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.
# serial 2
AC_DEFUN([AM_MAINTAINER_MODE],
[AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
dnl maintainer-mode is disabled by default
AC_ARG_ENABLE(maintainer-mode,
[ --enable-maintainer-mode enable make rules and dependencies not useful
(and sometimes confusing) to the casual installer],
USE_MAINTAINER_MODE=$enableval,
USE_MAINTAINER_MODE=no)
AC_MSG_RESULT([$USE_MAINTAINER_MODE])
AM_CONDITIONAL(MAINTAINER_MODE, [test $USE_MAINTAINER_MODE = yes])
MAINT=$MAINTAINER_MODE_TRUE
AC_SUBST(MAINT)dnl
]
)
AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE])
#! /bin/sh
set -x
aclocal
autoheader
automake -a -c
autoconf
# Makefile.in generated by automake 1.7.9 from Makefile.am.
# @configure_input@
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
# Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
ACLOCAL = @ACLOCAL@
AMDEP_FALSE = @AMDEP_FALSE@
AMDEP_TRUE = @AMDEP_TRUE@
AMTAR = @AMTAR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
MAKEINFO = @MAKEINFO@
MYSQL_CONFIG = @MYSQL_CONFIG@
MYSQL_INCLUDE = @MYSQL_INCLUDE@
MYSQL_LDFLAGS = @MYSQL_LDFLAGS@
MYSQL_LIBS = @MYSQL_LIBS@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PYTHON = @PYTHON@
PYTHON_BASECFLAGS = @PYTHON_BASECFLAGS@
PYTHON_CC = @PYTHON_CC@
PYTHON_CCSHARED = @PYTHON_CCSHARED@
PYTHON_INCLUDE = @PYTHON_INCLUDE@
PYTHON_LDSHARED = @PYTHON_LDSHARED@
PYTHON_OPT = @PYTHON_OPT@
PYTHON_SO = @PYTHON_SO@
RANLIB = @RANLIB@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
ac_ct_CC = @ac_ct_CC@
ac_ct_RANLIB = @ac_ct_RANLIB@
ac_ct_STRIP = @ac_ct_STRIP@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
bindir = @bindir@
build_alias = @build_alias@
datadir = @datadir@
exec_prefix = @exec_prefix@
host_alias = @host_alias@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localstatedir = @localstatedir@
mandir = @mandir@
oldincludedir = @oldincludedir@
prefix = @prefix@
program_transform_name = @program_transform_name@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
SUBDIRS = NEO
subdir = client
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
DIST_SOURCES =
RECURSIVE_TARGETS = info-recursive dvi-recursive pdf-recursive \
ps-recursive install-info-recursive uninstall-info-recursive \
all-recursive install-data-recursive install-exec-recursive \
installdirs-recursive install-recursive uninstall-recursive \
check-recursive installcheck-recursive
DIST_COMMON = $(srcdir)/Makefile.in Makefile.am
DIST_SUBDIRS = $(SUBDIRS)
all: all-recursive
.SUFFIXES:
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4)
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu client/Makefile
Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
uninstall-info-am:
# This directory's subdirectories are mostly independent; you can cd
# into them and run `make' without going through this Makefile.
# To change the values of `make' variables: instead of editing Makefiles,
# (1) if the variable is set in `config.status', edit `config.status'
# (which will cause the Makefiles to be regenerated when you run `make');
# (2) otherwise, pass the desired values on the `make' command line.
$(RECURSIVE_TARGETS):
@set fnord $$MAKEFLAGS; amf=$$2; \
dot_seen=no; \
target=`echo $@ | sed s/-recursive//`; \
list='$(SUBDIRS)'; for subdir in $$list; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
dot_seen=yes; \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
done; \
if test "$$dot_seen" = "no"; then \
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
fi; test -z "$$fail"
mostlyclean-recursive clean-recursive distclean-recursive \
maintainer-clean-recursive:
@set fnord $$MAKEFLAGS; amf=$$2; \
dot_seen=no; \
case "$@" in \
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
*) list='$(SUBDIRS)' ;; \
esac; \
rev=''; for subdir in $$list; do \
if test "$$subdir" = "."; then :; else \
rev="$$subdir $$rev"; \
fi; \
done; \
rev="$$rev ."; \
target=`echo $@ | sed s/-recursive//`; \
for subdir in $$rev; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
done && test -z "$$fail"
tags-recursive:
list='$(SUBDIRS)'; for subdir in $$list; do \
test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
done
ctags-recursive:
list='$(SUBDIRS)'; for subdir in $$list; do \
test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
done
ETAGS = etags
ETAGSFLAGS =
CTAGS = ctags
CTAGSFLAGS =
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
mkid -fID $$unique
TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
if (etags --etags-include --version) >/dev/null 2>&1; then \
include_option=--etags-include; \
else \
include_option=--include; \
fi; \
list='$(SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test -f $$subdir/TAGS && \
tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
fi; \
done; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)$$tags$$unique" \
|| $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique
ctags: CTAGS
CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$tags $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& cd $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) $$here
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
top_distdir = ..
distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
list='$(DISTFILES)'; for file in $$list; do \
case $$file in \
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
esac; \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkinstalldirs) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
list='$(SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test -d $(distdir)/$$subdir \
|| mkdir $(distdir)/$$subdir \
|| exit 1; \
(cd $$subdir && \
$(MAKE) $(AM_MAKEFLAGS) \
top_distdir="$(top_distdir)" \
distdir=../$(distdir)/$$subdir \
distdir) \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-recursive
all-am: Makefile
installdirs: installdirs-recursive
installdirs-am:
install: install-recursive
install-exec: install-exec-recursive
install-data: install-data-recursive
uninstall: uninstall-recursive
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-recursive
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-recursive
clean-am: clean-generic mostlyclean-am
distclean: distclean-recursive
-rm -f Makefile
distclean-am: clean-am distclean-generic distclean-tags
dvi: dvi-recursive
dvi-am:
info: info-recursive
info-am:
install-data-am:
install-exec-am:
install-info: install-info-recursive
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-recursive
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-recursive
mostlyclean-am: mostlyclean-generic
pdf: pdf-recursive
pdf-am:
ps: ps-recursive
ps-am:
uninstall-am: uninstall-info-am
uninstall-info: uninstall-info-recursive
.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am clean \
clean-generic clean-recursive ctags ctags-recursive distclean \
distclean-generic distclean-recursive distclean-tags distdir \
dvi dvi-am dvi-recursive info info-am info-recursive install \
install-am install-data install-data-am install-data-recursive \
install-exec install-exec-am install-exec-recursive \
install-info install-info-am install-info-recursive install-man \
install-recursive install-strip installcheck installcheck-am \
installdirs installdirs-am installdirs-recursive \
maintainer-clean maintainer-clean-generic \
maintainer-clean-recursive mostlyclean mostlyclean-generic \
mostlyclean-recursive pdf pdf-am pdf-recursive ps ps-am \
ps-recursive tags tags-recursive uninstall uninstall-am \
uninstall-info-am uninstall-info-recursive uninstall-recursive
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
PYTHON_PY_FILES = __init__.py config.py neostorage.py mq.py
PYTHON_C_FILES = neoclient.c neoclient_wrap.c
ZOPE_DATA_FILES = component.xml
# XXX this should be configurable.
NEO_DIR = /usr/lib/zope/lib/python/NEO
EXTRA_DIST = $(PYTHON_PY_FILES) $(PYTHON_C_FILES) $(ZOPE_DATA_FILES)
PYTHON_EXTENSIONS = neoclient$(PYTHON_SO)
neoclient_OBJ_FILES = neoclient_wrap.$(OBJEXT) neoclient.$(OBJEXT)
BUILT_SOURCES = $(PYTHON_EXTENSIONS)
CLEANFILES = $(PYTHON_EXTENSIONS) $(neoclient_OBJ_FILES)
PYTHON_CCOMPILE = $(PYTHON_CC) $(PYTHON_CCSHARED) $(PYTHON_BASECFLAGS) \
$(PYTHON_OPT) -Wall -W -I$(PYTHON_INCLUDE) -I$(top_srcdir)/include
neoclient$(PYTHON_SO): $(neoclient_OBJ_FILES) ../../lib/libneo.a
$(PYTHON_LDSHARED) -o $@ $(neoclient_OBJ_FILES) -L../../lib -lneo
neoclient_wrap.$(OBJEXT): neoclient_wrap.c
$(PYTHON_CCOMPILE) -c $< -o $@
neoclient.$(OBJEXT): neoclient.c
$(PYTHON_CCOMPILE) -c $< -o $@
install-data-local: $(PYTHON_EXTENSIONS) $(PYTHON_PY_FILES) $(ZOPE_DATA_FILES)
$(mkinstalldirs) $(DESTDIR)$(NEO_DIR)
for file in $?; do $(INSTALL_DATA) $$file $(DESTDIR)$(NEO_DIR); done
uninstall-local:
for file in $(PYTHON_EXTENSIONS) $(PYTHON_PY_FILES) $(ZOPE_DATA_FILES); do \
rm -f $(DESTDIR)$(NEO_DIR)/$$file; \
done
# Makefile.in generated by automake 1.7.9 from Makefile.am.
# @configure_input@
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
# Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ../..
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
ACLOCAL = @ACLOCAL@
AMDEP_FALSE = @AMDEP_FALSE@
AMDEP_TRUE = @AMDEP_TRUE@
AMTAR = @AMTAR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
MAKEINFO = @MAKEINFO@
MYSQL_CONFIG = @MYSQL_CONFIG@
MYSQL_INCLUDE = @MYSQL_INCLUDE@
MYSQL_LDFLAGS = @MYSQL_LDFLAGS@
MYSQL_LIBS = @MYSQL_LIBS@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PYTHON = @PYTHON@
PYTHON_BASECFLAGS = @PYTHON_BASECFLAGS@
PYTHON_CC = @PYTHON_CC@
PYTHON_CCSHARED = @PYTHON_CCSHARED@
PYTHON_INCLUDE = @PYTHON_INCLUDE@
PYTHON_LDSHARED = @PYTHON_LDSHARED@
PYTHON_OPT = @PYTHON_OPT@
PYTHON_SO = @PYTHON_SO@
RANLIB = @RANLIB@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
ac_ct_CC = @ac_ct_CC@
ac_ct_RANLIB = @ac_ct_RANLIB@
ac_ct_STRIP = @ac_ct_STRIP@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
bindir = @bindir@
build_alias = @build_alias@
datadir = @datadir@
exec_prefix = @exec_prefix@
host_alias = @host_alias@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localstatedir = @localstatedir@
mandir = @mandir@
oldincludedir = @oldincludedir@
prefix = @prefix@
program_transform_name = @program_transform_name@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
PYTHON_PY_FILES = __init__.py config.py neostorage.py mq.py
PYTHON_C_FILES = neoclient.c neoclient_wrap.c
ZOPE_DATA_FILES = component.xml
# XXX this should be configurable.
NEO_DIR = /usr/lib/zope/lib/python/NEO
EXTRA_DIST = $(PYTHON_PY_FILES) $(PYTHON_C_FILES) $(ZOPE_DATA_FILES)
PYTHON_EXTENSIONS = neoclient$(PYTHON_SO)
neoclient_OBJ_FILES = neoclient_wrap.$(OBJEXT) neoclient.$(OBJEXT)
BUILT_SOURCES = $(PYTHON_EXTENSIONS)
CLEANFILES = $(PYTHON_EXTENSIONS) $(neoclient_OBJ_FILES)
PYTHON_CCOMPILE = $(PYTHON_CC) $(PYTHON_CCSHARED) $(PYTHON_BASECFLAGS) \
$(PYTHON_OPT) -Wall -W -I$(PYTHON_INCLUDE) -I$(top_srcdir)/include
subdir = client/NEO
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
DIST_SOURCES =
DIST_COMMON = $(srcdir)/Makefile.in Makefile.am
all: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) all-am
.SUFFIXES:
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4)
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu client/NEO/Makefile
Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
uninstall-info-am:
tags: TAGS
TAGS:
ctags: CTAGS
CTAGS:
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
top_distdir = ../..
distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
list='$(DISTFILES)'; for file in $$list; do \
case $$file in \
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
esac; \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkinstalldirs) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) check-am
all-am: Makefile
installdirs:
install: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
-rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
clean: clean-am
clean-am: clean-generic mostlyclean-am
distclean: distclean-am
-rm -f Makefile
distclean-am: clean-am distclean-generic
dvi: dvi-am
dvi-am:
info: info-am
info-am:
install-data-am: install-data-local
install-exec-am:
install-info: install-info-am
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-generic
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-info-am uninstall-local
.PHONY: all all-am check check-am clean clean-generic distclean \
distclean-generic distdir dvi dvi-am info info-am install \
install-am install-data install-data-am install-data-local \
install-exec install-exec-am install-info install-info-am \
install-man install-strip installcheck installcheck-am \
installdirs maintainer-clean maintainer-clean-generic \
mostlyclean mostlyclean-generic pdf pdf-am ps ps-am uninstall \
uninstall-am uninstall-info-am uninstall-local
neoclient$(PYTHON_SO): $(neoclient_OBJ_FILES) ../../lib/libneo.a
$(PYTHON_LDSHARED) -o $@ $(neoclient_OBJ_FILES) -L../../lib -lneo
neoclient_wrap.$(OBJEXT): neoclient_wrap.c
$(PYTHON_CCOMPILE) -c $< -o $@
neoclient.$(OBJEXT): neoclient.c
$(PYTHON_CCOMPILE) -c $< -o $@
install-data-local: $(PYTHON_EXTENSIONS) $(PYTHON_PY_FILES) $(ZOPE_DATA_FILES)
$(mkinstalldirs) $(DESTDIR)$(NEO_DIR)
for file in $?; do $(INSTALL_DATA) $$file $(DESTDIR)$(NEO_DIR); done
uninstall-local:
for file in $(PYTHON_EXTENSIONS) $(PYTHON_PY_FILES) $(ZOPE_DATA_FILES); do \
rm -f $(DESTDIR)$(NEO_DIR)/$$file; \
done
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
<component prefix="NEO.config">
<sectiontype name="NEO" datatype=".neostorage"
implements="ZODB.storage">
<description>
A scalable storage for Zope
</description>
<key name="master" required="yes">
<description>
Give the ip of the master node
</description>
</key>
</sectiontype>
</component>
from ZODB.config import BaseConfig
class neostorage(BaseConfig):
def open(self):
from neostorage import neostorage
return neostorage(master = self.config.master)
##############################################################################
#
# Copyright (c) 2005 Nexedi SARL and Contributors. All Rights Reserved.
# Yoshinori Okuji <yo@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# 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.
#
##############################################################################
"""
Multi-Queue Cache Algorithm.
"""
from math import log
class Element:
"""
This class defines an element of a FIFO buffer.
"""
pass
class FIFO:
"""
This class implements a FIFO buffer.
"""
def __init__(self):
self._head = None
self._tail = None
self._len = 0
def __len__(self):
return self._len
def append(self):
element = Element()
element.next = None
element.prev = self._tail
if self._tail is not None:
self._tail.next = element
self._tail = element
if self._head is None:
self._head = element
self._len += 1
return element
def head(self):
return self._head
def tail(self):
return self._tail
def shift(self):
element = self._head
if element is None:
return None
del self[element]
return element
def __delitem__(self, element):
if element.next is None:
self._tail = element.prev
else:
element.next.prev = element.prev
if element.prev is None:
self._head = element.next
else:
element.prev.next = element.next
self._len -= 1
class Data:
"""
Data for each element in a FIFO buffer.
"""
pass
class MQ:
"""
This class manages cached data by a variant of Multi-Queue.
This class caches various sizes of objects. Here are some considerations:
- Expired objects are not really deleted immediately. But if GC is invoked too often,
it degrades the performance significantly.
- If large objects are cached, the number of cached objects decreases. This might affect
the cache hit ratio. It might be better to tweak a buffer level according to the size of
an object.
- Stored values must be strings.
- The size calculation is not accurate.
"""
def __init__(self, life_time=10000, buffer_levels=9, max_history_size=100000, max_size=20*1024*1024):
self._history_buffer = FIFO()
self._cache_buffers = []
for level in range(buffer_levels):
self._cache_buffers.append(FIFO())
self._data = {}
self._time = 0
self._life_time = life_time
self._buffer_levels = buffer_levels
self._max_history_size = max_history_size
self._max_size = max_size
self._size = 0
def has_key(self, id):
if id in self._data:
data = self._data[id]
if data.level >= 0:
return 1
return 0
__contains__ = has_key
def fetch(self, id):
"""
Fetch a value associated with the id.
"""
if id in self._data:
data = self._data[id]
if data.level >= 0:
del self._cache_buffers[data.level][data.element]
value = data.value
self._size -= len(value) # XXX inaccurate
self.store(id, value)
return value
raise KeyError, "%s was not found in the cache" % id
__getitem__ = fetch
def get(self, id, d=None):
try:
return self.fetch(id)
except KeyError:
return d
def _evict(self, id):
"""
Evict an element to the history buffer.
"""
data = self._data[id]
self._size -= len(data.value) # XXX inaccurate
del self._cache_buffers[data.level][data.element]
element = self._history_buffer.append()
data.level = -1
data.element = element
delattr(data, 'value')
delattr(data, 'expire_time')
element.data = data
if len(self._history_buffer) > self._max_history_size:
element = self._history_buffer.shift()
del self._data[element.data.id]
def store(self, id, value):
if id in self._data:
data = self._data[id]
level, element, counter = data.level, data.element, data.counter + 1
if level >= 0:
del self._cache_buffers[level][element]
else:
del self._history_buffer[element]
else:
counter = 1
# XXX It might be better to adjust the level according to the object size.
level = int(log(counter, 2))
if level >= self._buffer_levels:
level = self._buffer_levels - 1
element = self._cache_buffers[level].append()
data = Data()
data.id = id
data.expire_time = self._time + self._life_time
data.level = level
data.element = element
data.value = value
data.counter = counter
element.data = data
self._data[id] = data
self._size += len(value) # XXX inaccurate
# Expire old elements.
for level in range(self._buffer_levels):
cache_buffer = self._cache_buffers[level]
head = cache_buffer.head()
if head is not None and head.data.expire_time < self._time:
del cache_buffer[head]
data = head.data
if level > 0:
new_level = level - 1
element = cache_buffer[new_level].append()
element.data = data
data.expire_time = self._time + self._life_time
data.level = new_level
data.element = element
else:
self._evict(data.id)
# Limit the size.
size = self._size
max_size = self._max_size
if size > max_size:
for cache_buffer in self._cache_buffers:
while size > max_size:
element = cache_buffer.shift()
if element is None:
break
data = element.data
del self._data[data.id]
size -= len(data.value) # XXX inaccurate
if size <= max_size:
break
self._size = size
__setitem__ = store
def invalidate(self, id):
if id in self._data:
data = self._data[id]
if data.level >= 0:
del self._cache_buffers[data.level][data.element]
self._evict(id)
return
raise KeyError, "%s was not found in the cache" % id
__delitem__ = invalidate
# Here is a test.
if __name__ == '__main__':
cache = MQ()
cache[1] = "1"
cache[2] = "2"
assert cache.get(1) == "1", 'cannot get 1'
assert cache.get(2) == "2", 'cannot get 2'
assert cache.get(3) == None, 'can get 3!'
del cache[1]
assert cache.get(1) == None, 'can get 1!'
\ No newline at end of file
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <uuid/uuid.h>
#include <syslog.h>
#include <Python.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "neo_socket.h"
#include "neo_struct.h"
/* generate client id */
int
generate_id (char **ID)
{
uuid_t client_id;
uuid_generate (client_id);
*ID = (char *) malloc (UUID_LEN + 1);
memset (*ID, 0, UUID_LEN + 1);
uuid_unparse (client_id, *ID);
return 0;
}
/* send broadcast message to find where is the master */
int
search_master (int method, char **master_ip)
{
int soc, bd = 1, size;
char send_buf[HEADER_LEN], rcv_buf[RHEADER_LEN + 1], rflags[FLAG_LEN];
struct sockaddr_in addr;
u_int16_t meth, return_code;
u_int32_t data_len;
size_t send, received;
soc = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);
setsockopt (soc, SOL_SOCKET, SO_BROADCAST, (int *) &bd, sizeof (bd));
addr.sin_family = AF_INET;
addr.sin_port = htons (10825);
addr.sin_addr.s_addr = htonl (INADDR_BROADCAST);
/* create packet */
meth = htons (method);
data_len = htonl (0);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
send = sendto (soc, (char *)send_buf, HEADER_LEN, 0, (struct sockaddr *)&addr, sizeof(addr));
/* wait for a response */
size = sizeof (addr);
memset (rcv_buf, 0, RHEADER_LEN);
received = recvfrom (soc, (char *)rcv_buf, RHEADER_LEN, 0, (struct sockaddr *)&addr, &size);
/* check response */
if ((ntohs (*((u_int16_t *) (rcv_buf)))) != method)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_WARNING), "return method error");
return METHOD_ERROR;
}
memcpy (rflags, rcv_buf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (rcv_buf + INT16_LEN + FLAG_LEN)));
return_code =
ntohs (*((u_int16_t *) (rcv_buf + INT16_LEN + FLAG_LEN + INT32_LEN)));
if (return_code != 0)
return return_code;
/* get master ip */
*master_ip = (char *) malloc(strlen(inet_ntoa(addr.sin_addr))+1);
memset (*master_ip, 0, strlen(inet_ntoa(addr.sin_addr))+1);
memcpy (*master_ip, inet_ntoa(addr.sin_addr), strlen(inet_ntoa(addr.sin_addr))+1);
close(soc);
return 0;
}
/* Master call */
int
getObjectByOid (int conn, int method, u_int64_t oid, PyObject ** resultlist)
{
u_int64_t n_oid, serial;
u_int32_t buf_len = 0, data_len = 0, len = 0, storage_nb, nb;
u_int16_t meth, return_code = 0;
char buf[BUF_SIZE], rflags[FLAG_LEN], storage_id[UUID_LEN + 1];
char *send_buf;
/* send request to master */
meth = htons (method);
data_len = htonl (INT64_LEN);
send_buf = (char *) malloc (HEADER_LEN + INT64_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
/* data */
n_oid = htonll (oid);
memcpy (send_buf + HEADER_LEN, &n_oid, INT64_LEN);
if (!send_all (conn, send_buf, HEADER_LEN + INT64_LEN))
{
free (send_buf);
return CONNECTION_FAILURE;
}
free (send_buf);
/* Wait for response */
if (!wait_packet (conn, buf, &buf_len, RHEADER_LEN))
return CONNECTION_FAILURE;
/* header */
if ((ntohs (*((u_int16_t *) (buf)))) != method)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_WARNING), "return method error");
return METHOD_ERROR;
}
memcpy (rflags, buf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (buf + INT16_LEN + FLAG_LEN)));
return_code =
ntohs (*((u_int16_t *) (buf + INT16_LEN + FLAG_LEN + INT32_LEN)));
len = buf_len - RHEADER_LEN;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
return CONNECTION_FAILURE;
}
if (return_code != 0)
return return_code;
/* data */
len = 0;
serial = ntohll (*((u_int64_t *) (buf)));
len += INT64_LEN;
storage_nb = ntohl (*((u_int32_t *) (buf + len)));
len += INT32_LEN;
/* construct list of storage id */
*resultlist = PyList_New (0);
/* add serial */
PyList_Append (*resultlist, PyLong_FromUnsignedLongLong (serial));
/* add storage */
memset (storage_id, 0, UUID_LEN + 1);
for (nb = 0; nb < storage_nb; nb++)
{
memcpy (storage_id, buf + len, UUID_LEN);
len += UUID_LEN;
PyList_Append (*resultlist, PyString_FromString (storage_id));
}
return return_code;
}
int
getObjectBySerial (int conn, int method, u_int64_t oid, u_int64_t serial,
PyObject ** resultlist)
{
u_int64_t n_oid, n_serial;
u_int32_t buf_len = 0, data_len = 0, storage_nb = 0, len = 0, nb;
u_int16_t meth, return_code = 0;
char buf[BUF_SIZE], rflags[FLAG_LEN], storage_id[UUID_LEN + 1];
char *send_buf;
/* send request to master */
meth = htons (method);
data_len = htonl (INT64_LEN * 2);
send_buf = (char *) malloc (HEADER_LEN + INT64_LEN * 2);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
/* data */
n_oid = htonll (oid);
memcpy (send_buf + HEADER_LEN, &n_oid, INT64_LEN);
n_serial = htonll (serial);
memcpy (send_buf + HEADER_LEN + INT64_LEN, &n_serial, INT64_LEN);
if (!send_all (conn, send_buf, HEADER_LEN + INT64_LEN * 2))
{
free (send_buf);
return CONNECTION_FAILURE;
}
free (send_buf);
/* Wait for response */
if (!wait_packet (conn, buf, &buf_len, RHEADER_LEN))
return CONNECTION_FAILURE;
/* header */
if ((ntohs (*((u_int16_t *) (buf)))) != method)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_WARNING),
"BySerial return method error %d instead of %d",
ntohs (*((u_int16_t *) (buf))), method);
return METHOD_ERROR;
}
memcpy (rflags, buf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (buf + INT16_LEN + FLAG_LEN)));
return_code =
ntohs (*((u_int16_t *) (buf + INT16_LEN + FLAG_LEN + INT32_LEN)));
len = buf_len - RHEADER_LEN;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
return CONNECTION_FAILURE;
}
if (return_code != 0)
return return_code;
/* data */
storage_nb = ntohl (*((u_int32_t *) (buf)));
len = INT32_LEN;
/* construct list of storage id */
*resultlist = PyList_New (0);
memset (storage_id, 0, UUID_LEN + 1);
for (nb = 0; nb < storage_nb; nb++)
{
memcpy (storage_id, buf + len, UUID_LEN);
len += UUID_LEN;
PyList_Append (*resultlist, PyString_FromString (storage_id));
}
return return_code;
}
int
getSerial (int conn, int method, u_int64_t oid, u_int64_t * serial)
{
u_int64_t n_oid;
u_int32_t buf_len = 0, data_len = 0, len = 0;
u_int16_t meth, return_code;
char buf[BUF_SIZE], rflags[FLAG_LEN];
char *send_buf;
/* send request to master */
meth = htons (method);
data_len = htonl (INT64_LEN);
send_buf = (char *) malloc (HEADER_LEN + INT64_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
/* data */
n_oid = htonll (oid);
memcpy (send_buf + HEADER_LEN, &n_oid, INT64_LEN);
if (!send_all (conn, send_buf, HEADER_LEN + INT64_LEN))
{
free (send_buf);
return CONNECTION_FAILURE;
}
free (send_buf);
/* Wait for response */
if (!wait_packet (conn, buf, &buf_len, RHEADER_LEN))
return CONNECTION_FAILURE;
/* header */
if ((ntohs (*((u_int16_t *) (buf)))) != method)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_WARNING), "return method error");
return METHOD_ERROR;
}
memcpy (rflags, buf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (buf + INT16_LEN + FLAG_LEN)));
return_code =
ntohs (*((u_int16_t *) (buf + INT16_LEN + FLAG_LEN + INT32_LEN)));
len = buf_len - RHEADER_LEN;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
return 7;
}
if (return_code != 0)
return return_code;
/* data */
*serial = ntohll (*((u_int64_t *) (buf)));
return return_code;
}
int
getLastTransaction (int conn, int method, u_int64_t * tid)
{
u_int32_t data_len = 0, buf_len = 0, len = 0;
u_int16_t meth, return_code;
char buf[BUF_SIZE], rflags[FLAG_LEN];
char *send_buf;
/* send request to master */
meth = htons (method);
data_len = 0;
send_buf = (char *) malloc (HEADER_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
/* no data */
if (!send_all (conn, send_buf, HEADER_LEN))
{
free (send_buf);
return CONNECTION_FAILURE;
}
free (send_buf);
/* Wait for response */
if (!wait_packet (conn, buf, &buf_len, RHEADER_LEN))
return CONNECTION_FAILURE;
/* header */
if ((ntohs (*((u_int16_t *) (buf)))) != method)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_WARNING), "return method error");
return METHOD_ERROR;
}
memcpy (rflags, buf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (buf + INT16_LEN + FLAG_LEN)));
return_code =
ntohs (*((u_int16_t *) (buf + INT16_LEN + FLAG_LEN + INT32_LEN)));
len = buf_len - RHEADER_LEN;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
return CONNECTION_FAILURE;
}
if (return_code != 0)
return return_code;
/* transaction id */
*tid = ntohll (*((u_int64_t *) (buf)));
return return_code;
}
int
getOid (int conn, int method, u_int16_t nb_oid, PyObject ** list)
{
u_int32_t buf_len = 0, data_len = 0, len = 0;
u_int16_t meth, return_code, ascii, i, j, n_nb_oid;
char buf[BUF_SIZE], rflags[FLAG_LEN];
char *send_buf;
PyObject *ss_tuple;
/* send request to master */
meth = htons (method);
data_len = htonl (INT16_LEN);
send_buf = (char *) malloc (HEADER_LEN + INT16_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
/* data */
n_nb_oid = htons (nb_oid);
memcpy (send_buf + HEADER_LEN, &n_nb_oid, INT16_LEN);
if (!send_all (conn, send_buf, HEADER_LEN + INT16_LEN))
{
free (send_buf);
return CONNECTION_FAILURE;
}
free (send_buf);
/* Wait for response */
if (!wait_packet (conn, buf, &buf_len, RHEADER_LEN))
return CONNECTION_FAILURE;
/* header */
if ((ntohs (*((u_int16_t *) (buf)))) != method)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_WARNING), "return method error");
return METHOD_ERROR;
}
memcpy (rflags, buf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (buf + INT16_LEN + FLAG_LEN)));
return_code =
ntohs (*((u_int16_t *) (buf + INT16_LEN + FLAG_LEN + INT32_LEN)));
len = buf_len - RHEADER_LEN;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
return CONNECTION_FAILURE;
}
if (return_code != 0)
return return_code;
/* data */
nb_oid = ntohs (*((u_int16_t *) (buf)));
*list = PyList_New (0);
len = INT16_LEN;
/* list of oid */
for (j = 0; j < nb_oid; j++)
{
ss_tuple = PyList_New (0);
for (i = 0; i < ID_LEN; i++)
{
ascii = ntohs (*((u_int16_t *) (buf + len)));
len += INT16_LEN;
PyList_Append (ss_tuple, PyInt_FromLong (ascii));
}
PyList_Append (*list, ss_tuple);
Py_XDECREF (ss_tuple);
}
return return_code;
}
int
clientStart (int conn, int method, char id[UUID_LEN], char ip[IP_LEN],
u_int16_t port, PyObject ** list)
{
u_int32_t buf_len = 0, data_len = 0, len = 0;
u_int16_t meth, n_port, return_code, bool;
char buf[BUF_SIZE], rflags[FLAG_LEN];;
char *send_buf, *data;
/* send request to master */
meth = htons (method);
data_len = htonl (UUID_LEN + IP_LEN + INT16_LEN);
send_buf = (char *) malloc (HEADER_LEN + UUID_LEN + IP_LEN + INT16_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
/* data */
memcpy (send_buf + HEADER_LEN, id, UUID_LEN);
memcpy (send_buf + HEADER_LEN + UUID_LEN, ip, IP_LEN);
n_port = htons (port);
memcpy (send_buf + HEADER_LEN + UUID_LEN + IP_LEN, &n_port, INT16_LEN);
if (!send_all (conn, send_buf, HEADER_LEN + UUID_LEN + IP_LEN + INT16_LEN))
{
free (send_buf);
return CONNECTION_FAILURE;
}
free (send_buf);
/* Wait for response */
if (!wait_packet (conn, buf, &buf_len, RHEADER_LEN))
return CONNECTION_FAILURE;
/* header */
if ((ntohs (*((u_int16_t *) (buf)))) != method)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_WARNING), "return method error");
return METHOD_ERROR;
}
memcpy (rflags, buf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (buf + INT16_LEN + FLAG_LEN)));
return_code =
ntohs (*((u_int16_t *) (buf + INT16_LEN + FLAG_LEN + INT32_LEN)));
len = buf_len - RHEADER_LEN;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
return CONNECTION_FAILURE;
}
if (return_code != 0)
return return_code;
/* data */
len = 0;
/* get info about storage and it into a list */
*list = PyList_New (0);
/* name */
data_len = ntohs (*((u_int16_t *) (buf + len)));
data = (char *) malloc (data_len + 1);
memset (data, 0, data_len + 1);
len += INT16_LEN;
memcpy (data, buf + len, data_len);
len += data_len;
PyList_Append (*list, PyString_FromString (data));
free (data);
/* support version */
bool = ntohs (*((u_int16_t *) (buf + len)));
PyList_Append (*list, PyInt_FromLong (bool));
len += INT16_LEN;
/* support undo */
bool = ntohs (*((u_int16_t *) (buf + len)));
PyList_Append (*list, PyInt_FromLong (bool));
len += INT16_LEN;
/* support trans undo */
bool = ntohs (*((u_int16_t *) (buf + len)));
PyList_Append (*list, PyInt_FromLong (bool));
len += INT16_LEN;
/* read only */
bool = ntohs (*((u_int16_t *) (buf + len)));
PyList_Append (*list, PyInt_FromLong (bool));
len += INT16_LEN;
/* extension */
data_len = ntohs (*((u_int16_t *) (buf + len)));
data = (char *) malloc (data_len + 1);
memset (data, 0, data_len + 1);
len += INT16_LEN;
memcpy (data, buf + len, data_len);
PyList_Append (*list, PyString_FromString (data));
free (data);
return return_code;
}
int
getTransSN (int conn, int method, int16_t first, int16_t last,
PyObject ** list)
{
u_int64_t tid;
u_int32_t buf_len = 0, data_len = 0, len = 0, storage_nb;
u_int16_t meth, return_code, trans_nb, nb, i;
int16_t n_first, n_last;
char hbuf[RHEADER_LEN], rflags[FLAG_LEN], storage_id[UUID_LEN + 1], *buf;
char *send_buf;
PyObject *ss_tuple;
/* send request to master */
meth = htons (method);
data_len = htonl (INT16_LEN * 2);
send_buf = (char *) malloc (HEADER_LEN + INT16_LEN * 2);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
/* data */
n_first = htons (first);
memcpy (send_buf + HEADER_LEN, &n_first, INT16_LEN);
n_last = htons (last);
memcpy (send_buf + HEADER_LEN + INT16_LEN, &n_last, INT16_LEN);
if (!send_all (conn, send_buf, HEADER_LEN + INT16_LEN * 2))
{
free (send_buf);
return CONNECTION_FAILURE;
}
free (send_buf);
/* Wait for response */
if (!wait_packet (conn, hbuf, &buf_len, RHEADER_LEN))
return CONNECTION_FAILURE;
/* header */
if ((ntohs (*((u_int16_t *) (hbuf)))) != method)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_WARNING), "return method error");
return METHOD_ERROR;
}
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
return_code =
ntohs (*((u_int16_t *) (hbuf + INT16_LEN + FLAG_LEN + INT32_LEN)));
/* len = buf_len - RHEADER_LEN; */
buf = (char *) malloc (data_len + 1);
memset (buf, 0, data_len + 1);
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
{
free (buf);
return CONNECTION_FAILURE;
}
}
if (return_code != 0)
{
free(buf);
return return_code;
}
/* get tid and storage node for each transaction */
trans_nb = ntohs (*((u_int16_t *) (buf)));
*list = PyList_New (0);
len = INT16_LEN;
memset (storage_id, 0, UUID_LEN + 1);
for (nb = 0; nb < trans_nb; nb++)
{
/* create a new tuple */
ss_tuple = PyList_New (0);
tid = ntohll (*((u_int64_t *) (buf + len)));
len += INT64_LEN;
/* add tid */
PyList_Append (ss_tuple, PyLong_FromUnsignedLongLong (tid));
/* get storages infos */
storage_nb = ntohl (*((u_int32_t *) (buf + len)));
len += INT32_LEN;
/* get storages */
for (i = 0; i < storage_nb; i++)
{
memcpy (storage_id, buf + len, UUID_LEN);
len += UUID_LEN;
PyList_Append (ss_tuple, PyString_FromString (storage_id));
}
/* add tuple to result list */
PyList_Append (*list, ss_tuple);
Py_XDECREF (ss_tuple);
}
free(buf);
return return_code;
}
int
getObjectHist (int conn, int method, u_int64_t oid, u_int16_t hist_length,
PyObject ** list)
{
u_int64_t n_oid, serial;
u_int32_t buf_len = 0, data_len = 0, len = 0, storage_nb, i;
u_int16_t return_code, meth, n_hist_length, serial_nb, nb;
char hbuf[RHEADER_LEN], rflags[FLAG_LEN], storage_id[UUID_LEN + 1], *buf;
char *send_buf;
PyObject *ss_tuple;
/* send request to master */
meth = htons (method);
data_len = htonl (INT64_LEN + INT16_LEN);
send_buf = (char *) malloc (HEADER_LEN + INT64_LEN + INT16_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
/* data */
n_oid = htonll (oid);
memcpy (send_buf + HEADER_LEN, &n_oid, INT64_LEN);
n_hist_length = htons (hist_length);
memcpy (send_buf + HEADER_LEN + INT64_LEN, &n_hist_length, INT16_LEN);
if (!send_all (conn, send_buf, HEADER_LEN + INT64_LEN + INT16_LEN))
{
free (send_buf);
return CONNECTION_FAILURE;
}
free (send_buf);
/* Wait for response */
if (!wait_packet (conn, hbuf, &buf_len, RHEADER_LEN))
return CONNECTION_FAILURE;
/* header */
if ((ntohs (*((u_int16_t *) (hbuf)))) != method)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_WARNING), "return method error");
return METHOD_ERROR;
}
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
return_code =
ntohs (*((u_int16_t *) (hbuf + INT16_LEN + FLAG_LEN + INT32_LEN)));
buf = (char *) malloc (data_len + 1);
memset (buf, 0, data_len + 1);
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
{
free(buf);
return CONNECTION_FAILURE;
}
}
if (return_code != 0)
{
free(buf);
return return_code;
}
memset (storage_id, 0, UUID_LEN + 1);
/* data */
serial_nb = ntohs (*((u_int16_t *) (buf)));
*list = PyList_New (0);
len = INT16_LEN;
for (nb = 0; nb < serial_nb; nb++)
{
/* create a new tuple for the version of the object */
ss_tuple = PyList_New (0);
/* get serial */
serial = ntohll (*((u_int64_t *) (buf + len)));
len += INT64_LEN;
PyList_Append (ss_tuple, PyLong_FromUnsignedLongLong (serial));
/* get number of storages */
storage_nb = ntohl (*((u_int32_t *) (buf + len)));
len += INT32_LEN;
/* get storages id */
for (i = 0; i < storage_nb; i++)
{
memcpy (storage_id, buf + len, UUID_LEN);
len += UUID_LEN;
PyList_Append (ss_tuple, PyString_FromString (storage_id));
}
PyList_Append (*list, ss_tuple);
Py_XDECREF (ss_tuple);
}
free(buf);
return return_code;
}
int
undoTrans (int conn, int method, u_int64_t tid, PyObject ** list)
{
u_int64_t n_tid;
u_int32_t buf_len = 0, data_len = 0, len = 0, storage_nb, nb;
u_int16_t meth, return_code;
char hbuf[RHEADER_LEN], rflags[FLAG_LEN], storage_id[UUID_LEN + 1];
char *send_buf, *buf;
/* send request to master */
meth = htons (method);
data_len = htonl (INT64_LEN);
send_buf = (char *) malloc (HEADER_LEN + INT64_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
/* data */
n_tid = htonll (tid);
memcpy (send_buf + HEADER_LEN, &n_tid, INT64_LEN);
if (!send_all (conn, send_buf, HEADER_LEN + INT64_LEN))
{
free (send_buf);
return CONNECTION_FAILURE;
}
free (send_buf);
/* Wait for response */
if (!wait_packet (conn, hbuf, &buf_len, RHEADER_LEN))
return CONNECTION_FAILURE;
/* header */
if ((ntohs (*((u_int16_t *) (hbuf)))) != method)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_WARNING), "return method error");
return METHOD_ERROR;
}
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
return_code =
ntohs (*((u_int16_t *) (hbuf + INT16_LEN + FLAG_LEN + INT32_LEN)));
buf = (char *)malloc (data_len + 1);
memset (buf, 0, data_len + 1);
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
{
free (buf);
return CONNECTION_FAILURE;
}
}
if (return_code != 0)
{
free (buf);
return return_code;
}
/* data */
storage_nb = ntohl (*((u_int32_t *) (buf)));
len = INT32_LEN;
/* build a list of storage id */
*list = PyList_New (0);
memset (storage_id, 0, UUID_LEN + 1);
for (nb = 0; nb < storage_nb; nb++)
{
memcpy (storage_id, buf + len, UUID_LEN);
len += UUID_LEN;
PyList_Append (*list, PyString_FromString (storage_id));
}
free(buf);
return return_code;
}
int
beginTrans (int conn, int method, u_int64_t tid, PyObject ** list)
{
u_int64_t n_tid;
u_int32_t buf_len = 0, data_len = 0, len = 0, nb, storage_nb;
u_int16_t meth, i, id, return_code = 0;
char buf[BUF_SIZE], rflags[FLAG_LEN], storage_id[UUID_LEN + 1];
char *send_buf;
PyObject *ss_tuple;
/* send request to master */
meth = htons (method);
data_len = htonl (INT64_LEN);
send_buf = (char *) malloc (HEADER_LEN + INT64_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
/* data */
n_tid = htonll (tid);
memcpy (send_buf + HEADER_LEN, &n_tid, INT64_LEN);
if (!send_all (conn, send_buf, HEADER_LEN + INT64_LEN))
{
free (send_buf);
return CONNECTION_FAILURE;
}
free (send_buf);
/* wait for response */
if (!wait_packet (conn, buf, &buf_len, RHEADER_LEN))
return CONNECTION_FAILURE;
/* header */
if ((ntohs (*((u_int16_t *) (buf)))) != method)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_WARNING), "return method error");
return METHOD_ERROR;
}
memcpy (rflags, buf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (buf + INT16_LEN + FLAG_LEN)));
return_code =
ntohs (*((u_int16_t *) (buf + INT16_LEN + FLAG_LEN + INT32_LEN)));
len = buf_len - RHEADER_LEN;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
return CONNECTION_FAILURE;
}
if (return_code != 0)
return return_code;
/* data */
len = 0;
*list = PyList_New (0);
ss_tuple = PyList_New (0);
/* get tid */
for (i = 0; i < ID_LEN; i++)
{
id = ntohs (*((u_int16_t *) (buf + len)));
len += INT16_LEN;
PyList_Append (ss_tuple, PyInt_FromLong (id));
}
PyList_Append (*list, ss_tuple);
Py_XDECREF (ss_tuple);
/* get storage list */
storage_nb = ntohl (*((u_int32_t *) (buf + len)));
len += INT32_LEN;
memset (storage_id, 0, UUID_LEN + 1);
for (nb = 0; nb < storage_nb; nb++)
{
memcpy (storage_id, buf + len, UUID_LEN);
len += UUID_LEN;
PyList_Append (*list, PyString_FromString (storage_id));
}
return return_code;
}
int
endTrans (int conn, int method, u_int64_t tid, PyObject * oid_list,
PyObject * storage_list)
{
u_int64_t n_tid, n_oid, n_serial, oid, serial;
u_int32_t buf_len = 0, data_len = 0, len =
0, n_nb_oid, nb_oid, nb_storage, n_nb_storage, i;
u_int16_t meth, return_code = 0;
char buf[BUF_SIZE], rflags[FLAG_LEN];
char *send_buf, *storage_id;
PyObject *ntuple, *nlist;
/* send request to master */
meth = htons (method);
nb_oid = PyTuple_Size (oid_list);
nb_storage = PyTuple_Size (storage_list);
data_len =
htonl (nb_oid * 2 * INT64_LEN + 2 * INT32_LEN + nb_storage * UUID_LEN +
INT64_LEN);
buf_len = HEADER_LEN + ntohl (data_len);
send_buf = (char *) malloc (buf_len);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
/* data */
n_tid = htonll (tid);
memcpy (send_buf + HEADER_LEN, &n_tid, INT64_LEN);
len = HEADER_LEN + INT64_LEN;
n_nb_storage = htonl (nb_storage);
/* send list of storages */
memcpy (send_buf + len, &n_nb_storage, INT32_LEN);
len += INT32_LEN;
for (i = 0; i < nb_storage; i++)
{
ntuple = PyTuple_GetItem (storage_list, i);
nlist = PySequence_Tuple (ntuple);
PyArg_ParseTuple (nlist, (char *) "s", &storage_id);
Py_XDECREF (nlist);
memcpy (send_buf + len, storage_id, UUID_LEN);
len += UUID_LEN;
}
n_nb_oid = htonl (nb_oid);
/* send list of oid and serial */
memcpy (send_buf + len, &n_nb_oid, INT32_LEN);
len += INT32_LEN;
for (i = 0; i < nb_oid; i++)
{
ntuple = PyTuple_GetItem (oid_list, i);
nlist = PySequence_Tuple (ntuple);
PyArg_ParseTuple (nlist, (char *) "LL", &oid, &serial);
Py_XDECREF (nlist);
/* oid */
n_oid = htonll (oid);
memcpy (send_buf + len, &n_oid, INT64_LEN);
len += INT64_LEN;
/* serial */
n_serial = htonll (serial);
memcpy (send_buf + len, &n_serial, INT64_LEN);
len += INT64_LEN;
}
if (!send_all (conn, send_buf, buf_len))
{
free (send_buf);
return CONNECTION_FAILURE;
}
free (send_buf);
/* Wait for response */
buf_len = 0;
if (!wait_packet (conn, buf, &buf_len, RHEADER_LEN))
return CONNECTION_FAILURE;
/* header */
if ((ntohs (*((u_int16_t *) (buf)))) != method)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_WARNING), "return method error");
return METHOD_ERROR;
}
memcpy (rflags, buf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (buf + INT16_LEN + FLAG_LEN)));
return_code =
ntohs (*((u_int16_t *) (buf + INT16_LEN + FLAG_LEN + INT32_LEN)));
len = buf_len - RHEADER_LEN;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
return CONNECTION_FAILURE;
}
return return_code;
}
int
getAllSN (int conn, int method, PyObject ** list)
{
u_int32_t buf_len = 0, data_len = 0, len = 0, storage_nb, nb;
u_int16_t port, return_code, meth;
char hbuf[RHEADER_LEN], rflags[FLAG_LEN], id[UUID_LEN + 1], ip[IP_LEN + 1];
char *send_buf, *buf;
PyObject *ss_tuple;
/* send request to master */
meth = htons (method);
data_len = 0;
send_buf = (char *) malloc (HEADER_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
/* no data */
if (!send_all (conn, send_buf, HEADER_LEN))
{
free (send_buf);
return CONNECTION_FAILURE;
}
free (send_buf);
/* Wait for response */
if (!wait_packet (conn, hbuf, &buf_len, RHEADER_LEN))
return CONNECTION_FAILURE;
/* header */
if ((ntohs (*((u_int16_t *) (hbuf)))) != method)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_WARNING), "return method error");
return METHOD_ERROR;
}
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
return_code =
ntohs (*((u_int16_t *) (hbuf + INT16_LEN + FLAG_LEN + INT32_LEN)));
buf = (char *)malloc (data_len + 1);
memset (buf, 0, data_len + 1);
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
{
free (buf);
return CONNECTION_FAILURE;
}
}
if (return_code != 0)
{
free (buf);
return return_code;
}
/* data */
/* store storages infos in a list */
memset (id, 0, UUID_LEN + 1);
memset (ip, 0, IP_LEN + 1);
*list = PyList_New (0);
storage_nb = ntohl (*((u_int32_t *) (buf)));
len = INT32_LEN;
for (nb = 0; nb < storage_nb; nb++)
{
/* make a tuple for each storage */
ss_tuple = PyList_New (0);
/* id */
memcpy (id, buf + len, UUID_LEN);
len += UUID_LEN;
PyList_Append (ss_tuple, PyString_FromString (id));
memcpy (ip, buf + len, IP_LEN);
len += IP_LEN;
PyList_Append (ss_tuple, PyString_FromString (ip));
port = ntohs (*((u_int16_t *) (buf + len)));
len += INT16_LEN;
PyList_Append (ss_tuple, PyInt_FromLong (port));
/* add tuple to list */
PyList_Append (*list, ss_tuple);
Py_XDECREF (ss_tuple);
}
free (buf);
return return_code;
}
int
getAllCN (int conn, int method, PyObject ** list)
{
u_int32_t buf_len = 0, data_len = 0, len = 0, client_nb, nb;
u_int16_t return_code, port, meth;
char hbuf[RHEADER_LEN], rflags[FLAG_LEN], id[UUID_LEN + 1], ip[IP_LEN + 1];
char *send_buf, *buf;
PyObject *ss_tuple;
/* send request to master */
meth = htons (method);
data_len = 0;
send_buf = (char *) malloc (HEADER_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
/* no data */
if (!send_all (conn, send_buf, HEADER_LEN))
{
free (send_buf);
return CONNECTION_FAILURE;
}
free (send_buf);
/* Wait for response */
if (!wait_packet (conn, hbuf, &buf_len, RHEADER_LEN))
return CONNECTION_FAILURE;
/* header */
if ((ntohs (*((u_int16_t *) (hbuf)))) != method)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_WARNING), "return method error");
return METHOD_ERROR;
}
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
return_code =
ntohs (*((u_int16_t *) (hbuf + INT16_LEN + FLAG_LEN + INT32_LEN)));
buf = (char *)malloc (data_len + 1);
memset (buf, 0, data_len + 1);
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
{
free (buf);
return CONNECTION_FAILURE;
}
}
if (return_code != 0)
{
free (buf);
return return_code;
}
/* data */
client_nb = ntohl (*((u_int32_t *) (buf)));
*list = PyList_New (0);
len = INT32_LEN;
memset (id, 0, UUID_LEN + 1);
memset (ip, 0, IP_LEN + 1);
for (nb = 0; nb < client_nb; nb++)
{
ss_tuple = PyList_New (0);
memcpy (id, buf + len, UUID_LEN); /* id */
len += UUID_LEN;
PyList_Append (ss_tuple, PyString_FromString (id));
memcpy (ip, buf + len, IP_LEN); /* ip */
len += IP_LEN;
PyList_Append (ss_tuple, PyString_FromString (ip));
port = ntohs (*((u_int16_t *) (buf + len)));
len += INT16_LEN;
PyList_Append (ss_tuple, PyInt_FromLong (port));
PyList_Append (*list, ss_tuple);
Py_XDECREF (ss_tuple);
}
free (buf);
return return_code;
}
int
failure (int conn, int method, char sn[UUID_LEN])
{
u_int32_t data_len, meth;
char *send_buf;
/* send request to master */
meth = htons (method);
data_len = htonl (UUID_LEN);
send_buf = (char *) malloc (HEADER_LEN + UUID_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
/* data */
memcpy (send_buf + HEADER_LEN, sn, UUID_LEN);
if (!send_all (conn, send_buf, HEADER_LEN + UUID_LEN))
{
free (send_buf);
return CONNECTION_FAILURE;
}
free (send_buf);
return 0;
}
/* Storage call */
int
transaction (int conn, int method, char *user, char *desc,
char *ext, u_int64_t tid, unsigned long total_object_data_size,
PyObject * list, char **mmsg)
{
u_int64_t oid, serial, n_oid, n_serial, n_tid, data_size;
u_int32_t buf_len = 0, data_len = 0, nb_obj, n_nb_obj, len = 0, i;
int32_t crc, n_crc;
u_int16_t meth, user_len, desc_len, ext_len, return_code;
char buf[BUF_SIZE], rflags[FLAG_LEN];
char *send_buf, *data;
PyObject *nlist, *ntuple;
/* send request to master */
meth = htons (method);
user_len = htons (strlen (user));
desc_len = htons (strlen (desc));
ext_len = htons (strlen (ext));
nb_obj = PyTuple_Size (list);
data_len = htonl (INT64_LEN + 3 * INT16_LEN + strlen (user)
+ strlen (desc) + strlen (ext) + INT32_LEN
+ nb_obj * (3 * INT64_LEN + INT32_LEN) +
total_object_data_size);
buf_len = HEADER_LEN + ntohl (data_len);
send_buf = (char *) malloc (buf_len);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
/* data */
len += HEADER_LEN;
n_tid = htonll (tid);
memcpy (send_buf + len, &n_tid, INT64_LEN);
len += INT64_LEN;
/* len and data about transaction */
memcpy (send_buf + len, &user_len, INT16_LEN);
len += INT16_LEN;
memcpy (send_buf + len, &desc_len, INT16_LEN);
len += INT16_LEN;
memcpy (send_buf + len, &ext_len, INT16_LEN);
len += INT16_LEN;
memcpy (send_buf + len, user, strlen (user));
len += strlen (user);
memcpy (send_buf + len, desc, strlen (desc));
len += strlen (desc);
memcpy (send_buf + len, ext, strlen (ext));
len += strlen (ext);
/* object list */
n_nb_obj = htonl (nb_obj);
memcpy (send_buf + len, &n_nb_obj, INT32_LEN);
len += INT32_LEN;
for (i = 0; i < nb_obj; i++)
{
ntuple = PyTuple_GetItem (list, i);
nlist = PySequence_Tuple (ntuple);
/* XXX maybe use s# in case of null byte in data */
PyArg_ParseTuple (nlist, (char *) "LLsl", &oid, &serial, &data, &crc);
Py_XDECREF (nlist);
/* oid */
n_oid = htonll (oid);
memcpy (send_buf + len, &n_oid, INT64_LEN);
len += INT64_LEN;
/* serial */
n_serial = htonll (serial);
memcpy (send_buf + len, &n_serial, INT64_LEN);
len += INT64_LEN;
/* data */
data_size = htonll (strlen (data)); /* must be 64int */
memcpy (send_buf + len, &data_size, INT64_LEN);
len += INT64_LEN;
memcpy (send_buf + len, data, strlen (data));
len += strlen (data);
/* crc */
n_crc = htonl (crc);
memcpy (send_buf + len, &n_crc, INT32_LEN);
len += INT32_LEN;
}
if (!send_all (conn, send_buf, buf_len))
{
free (send_buf);
return CONNECTION_FAILURE;
}
free (send_buf);
/* Wait for response */
buf_len = 0;
if (!wait_packet (conn, buf, &buf_len, RHEADER_LEN))
return CONNECTION_FAILURE;
/* header */
if ((ntohs (*((u_int16_t *) (buf)))) != method)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_WARNING), "return method error");
return METHOD_ERROR;
}
memcpy (rflags, buf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (buf + INT16_LEN + FLAG_LEN)));
return_code =
ntohs (*((u_int16_t *) (buf + INT16_LEN + FLAG_LEN + INT32_LEN)));
len = buf_len - RHEADER_LEN;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
return CONNECTION_FAILURE;
}
if (return_code != 0)
return return_code;
/* data */
/* msg_len = ntohs (*((u_int16_t *) (buf))); */
/* *mmsg = (char *) malloc (msg_len + 1); */
/* memset (*mmsg, 0, msg_len + 1); */
/* memcpy (*mmsg, buf + 2, msg_len); */
return return_code;
}
int
undo (int conn, int method, u_int64_t tid, PyObject ** list)
{
u_int64_t n_tid, oid;
u_int32_t buf_len = 0, data_len = 0, len = 0, nb_oid, nb;
u_int16_t meth, return_code;
char buf[BUF_SIZE], rflags[FLAG_LEN];
char *send_buf;
/* send request to master */
meth = htons (method);
data_len = htonl (INT64_LEN);
send_buf = (char *) malloc (HEADER_LEN + INT64_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
/* data */
n_tid = htonll (tid);
memcpy (send_buf + HEADER_LEN, &n_tid, INT64_LEN);
if (!send_all (conn, send_buf, HEADER_LEN + INT64_LEN))
{
free (send_buf);
return CONNECTION_FAILURE;
}
free (send_buf);
/* Wait for response */
if (!wait_packet (conn, buf, &buf_len, RHEADER_LEN))
return CONNECTION_FAILURE;
/* header */
if ((ntohs (*((u_int16_t *) (buf)))) != method)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_WARNING), "return method error");
return METHOD_ERROR;
}
memcpy (rflags, buf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (buf + INT16_LEN + FLAG_LEN)));
return_code =
ntohs (*((u_int16_t *) (buf + INT16_LEN + FLAG_LEN + INT32_LEN)));
len = buf_len - RHEADER_LEN;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
return CONNECTION_FAILURE;
}
if (return_code != 0)
return return_code;
/* data */
/* get list of oid that have been undone */
nb_oid = ntohl (*((u_int32_t *) (buf)));
len = INT32_LEN;
*list = PyList_New (0);
for (nb = 0; nb < nb_oid; nb++)
{
oid = ntohll (*((u_int64_t *) (buf + len)));
len += INT64_LEN;
PyList_Append (*list, PyLong_FromUnsignedLongLong (oid));
}
return return_code;
}
int
histInfo (int conn, int method, u_int64_t oid, u_int64_t serial,
PyObject ** list)
{
u_int64_t n_oid, n_serial, object_size;
u_int32_t buf_len = 0, data_len = 0, len = 0;
u_int16_t meth, return_code;
char buf[BUF_SIZE], rflags[FLAG_LEN];
char *data, *send_buf;
/* send request to master */
meth = htons (method);
data_len = htonl (2 * INT64_LEN);
send_buf = (char *) malloc (HEADER_LEN + 2 * INT64_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
/* data */
len = HEADER_LEN;
n_oid = htonll (oid);
memcpy (send_buf + len, &n_oid, INT64_LEN);
len += INT64_LEN;
n_serial = htonll (serial);
memcpy (send_buf + len, &n_serial, INT64_LEN);
len += INT64_LEN;
if (!send_all (conn, send_buf, HEADER_LEN + 2 * INT64_LEN))
{
free (send_buf);
return CONNECTION_FAILURE;
}
free (send_buf);
/* Wait for response */
if (!wait_packet (conn, buf, &buf_len, RHEADER_LEN))
return CONNECTION_FAILURE;
/* header */
if ((ntohs (*((u_int16_t *) (buf)))) != method)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_WARNING), "return method error");
return METHOD_ERROR;
}
memcpy (rflags, buf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (buf + INT16_LEN + FLAG_LEN)));
return_code =
ntohs (*((u_int16_t *) (buf + INT16_LEN + FLAG_LEN + INT32_LEN)));
len = buf_len - RHEADER_LEN;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
return CONNECTION_FAILURE;
}
if (return_code != 0)
return return_code;
/* data */
*list = PyList_New (0);
len = 0;
/* time */
data_len = ntohs (*((u_int16_t *) (buf + len)));
len += INT16_LEN;
data = (char *) malloc (data_len + 1);
memset (data, 0, data_len + 1);
memcpy (data, buf + len, data_len);
PyList_Append (*list, PyString_FromString (data));
len += data_len;
free (data);
/* user */
data_len = ntohs (*((u_int16_t *) (buf + len)));
len += INT16_LEN;
data = (char *) malloc (data_len + 1);
memset (data, 0, data_len + 1);
memcpy (data, buf + len, data_len);
PyList_Append (*list, PyString_FromString (data));
len += data_len;
free (data);
/* description */
data_len = ntohs (*((u_int16_t *) (buf + len)));
len += INT16_LEN;
data = (char *) malloc (data_len + 1);
memset (data, 0, data_len + 1);
memcpy (data, buf + len, data_len);
PyList_Append (*list, PyString_FromString (data));
len += data_len;
free (data);
/* serial */
serial = ntohll (*((u_int64_t *) (buf + len)));
PyList_Append (*list, PyLong_FromUnsignedLongLong (serial));
len += INT64_LEN;
/* size */
object_size = ntohll (*((u_int64_t *) (buf + len)));
PyList_Append (*list, PyLong_FromUnsignedLongLong (object_size));
return return_code;
}
int
undoInfo (int conn, int method, u_int64_t tid, PyObject ** list)
{
u_int64_t n_tid, id;
u_int32_t buf_len = 0, data_len = 0, len = 0;
u_int16_t meth, return_code;
char buf[BUF_SIZE], rflags[FLAG_LEN];
char *send_buf, *data;
/* send request to master */
meth = htons (method);
data_len = htonl (INT64_LEN);
send_buf = (char *) malloc (HEADER_LEN + INT64_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
/* data */
n_tid = htonll (tid);
memcpy (send_buf + HEADER_LEN, &n_tid, INT64_LEN);
if (!send_all (conn, send_buf, HEADER_LEN + INT64_LEN))
{
free (send_buf);
return CONNECTION_FAILURE;
}
free (send_buf);
/* Wait for response */
if (!wait_packet (conn, buf, &buf_len, RHEADER_LEN))
return CONNECTION_FAILURE;
/* header */
if ((ntohs (*((u_int16_t *) (buf)))) != method)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_WARNING), "return method error");
return METHOD_ERROR;
}
memcpy (rflags, buf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (buf + INT16_LEN + FLAG_LEN)));
return_code =
ntohs (*((u_int16_t *) (buf + INT16_LEN + FLAG_LEN + INT32_LEN)));
len = buf_len - RHEADER_LEN;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
return CONNECTION_FAILURE;
}
if (return_code != 0)
return return_code;
/* data */
*list = PyList_New (0);
len = 0;
/* time */
data_len = ntohs (*((u_int16_t *) (buf + len)));
len += INT16_LEN;
data = (char *) malloc (data_len + 1);
memset (data, 0, data_len + 1);
memcpy (data, buf + len, data_len);
PyList_Append (*list, PyString_FromString (data));
len += data_len;
free (data);
/* user */
data_len = ntohs (*((u_int16_t *) (buf + len)));
len += INT16_LEN;
data = (char *) malloc (data_len + 1);
memset (data, 0, data_len + 1);
memcpy (data, buf + len, data_len);
PyList_Append (*list, PyString_FromString (data));
len += data_len;
free (data);
/* desc */
data_len = ntohs (*((u_int16_t *) (buf + len)));
len += INT16_LEN;
data = (char *) malloc (data_len + 1);
memset (data, 0, data_len + 1);
memcpy (data, buf + len, data_len);
PyList_Append (*list, PyString_FromString (data));
len += data_len;
free (data);
/* id */
id = ntohll (*((u_int64_t *) (buf + len)));
PyList_Append (*list, PyLong_FromUnsignedLongLong (id));
return return_code;
}
int
load (int conn, int method, u_int64_t oid, u_int64_t serial,
PyObject ** object)
{
u_int64_t n_oid, n_serial, object_len;
u_int32_t buf_len = 0, data_len = 0, len = 0;
u_int16_t meth, return_code;
int32_t crc;
char *buf, rflags[FLAG_LEN], hbuf[RHEADER_LEN];
char *send_buf, *data;
/* send request to master */
meth = htons (method);
data_len = htonl (2 * INT64_LEN);
send_buf = (char *) malloc (HEADER_LEN + 2 * INT64_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
/* data */
n_oid = ntohll (oid);
memcpy (send_buf + HEADER_LEN, &n_oid, INT64_LEN);
n_serial = ntohll (serial);
memcpy (send_buf + HEADER_LEN + INT64_LEN, &n_serial, INT64_LEN);
if (!send_all (conn, send_buf, HEADER_LEN + 2 * INT64_LEN))
{
free (send_buf);
return CONNECTION_FAILURE;
}
free (send_buf);
/* Wait for response */
if (!wait_packet (conn, hbuf, &buf_len, RHEADER_LEN))
return CONNECTION_FAILURE;
/* header */
if ((ntohs (*((u_int16_t *) (hbuf)))) != method)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_WARNING), "return method error");
return METHOD_ERROR;
}
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
return_code =
ntohs (*((u_int16_t *) (hbuf + INT16_LEN + FLAG_LEN + INT32_LEN)));
len = buf_len - RHEADER_LEN;
buf = (char *) malloc (data_len+1);
memset (buf, 0, data_len+1);
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
{
free (buf);
return CONNECTION_FAILURE;
}
}
if (return_code != 0)
{
free (buf);
return return_code;
}
/* data */
object_len = ntohll (*((u_int64_t *) (buf)));
data = (char *) malloc (object_len + 1);
memset (data, 0, object_len + 1);
memcpy (data, buf + INT64_LEN, object_len);
/* crc */
crc = ntohl (*((u_int32_t *) (buf + INT64_LEN + object_len)));
*object = PyList_New (0);
PyList_Append (*object, PyString_FromString (data));
PyList_Append (*object, PyLong_FromLong (crc));
free (data);
free (buf);
return return_code;
}
int
getSize (int conn, int method, u_int64_t * size)
{
u_int32_t buf_len = 0, data_len = 0, len = 0;
u_int16_t meth, return_code;
char buf[BUF_SIZE], rflags[FLAG_LEN];
char *send_buf;
/* send request to master */
meth = htons (method);
data_len = 0;
send_buf = (char *) malloc (HEADER_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
/* no data */
if (!send_all (conn, send_buf, HEADER_LEN))
{
free (send_buf);
return CONNECTION_FAILURE;
}
free (send_buf);
/* Wait for response */
if (!wait_packet (conn, buf, &buf_len, RHEADER_LEN))
return CONNECTION_FAILURE;
/* header */
if ((ntohs (*((u_int16_t *) (buf)))) != method)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_WARNING), "return method error");
return METHOD_ERROR;
}
memcpy (rflags, buf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (buf + INT16_LEN + FLAG_LEN)));
return_code =
ntohs (*((u_int16_t *) (buf + INT16_LEN + FLAG_LEN + INT32_LEN)));
len = buf_len - RHEADER_LEN;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
return CONNECTION_FAILURE;
}
close (conn);
if (return_code != 0)
return return_code;
/* data */
*size = ntohll (*((u_int64_t *) (buf)));
return return_code;
}
/* Other client call */
int
checkCache (int method, u_int64_t serial, PyObject * oid, PyObject * client)
{
u_int64_t n_serial, n_oid, id;
u_int32_t buf_len = 0, data_len = 0, nb_oid, n_nb_oid, len = 0, i;
u_int16_t meth, conn, port, client_nb;
char *send_buf, *ip;
PyObject *ntuple, *nlist;
/* send request to master */
meth = htons (method);
nb_oid = PyTuple_Size (oid);
data_len = htonl (nb_oid * INT64_LEN + INT64_LEN + INT32_LEN);
buf_len = HEADER_LEN + nb_oid * INT64_LEN + INT64_LEN + INT32_LEN;
send_buf = (char *) malloc (buf_len);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
/* data */
n_serial = htonll (serial);
memcpy (send_buf + HEADER_LEN, &n_serial, INT64_LEN);
len = HEADER_LEN + INT64_LEN;
n_nb_oid = htonl (nb_oid);
memcpy (send_buf + len, &n_nb_oid, INT32_LEN);
len += INT32_LEN;
for (i = 0; i < nb_oid; i++)
{
ntuple = PyTuple_GetItem (oid, i);
nlist = PySequence_Tuple (ntuple);
PyArg_ParseTuple (nlist, (char *) "L", &id);
Py_XDECREF (nlist);
n_oid = ntohll (id);
memcpy (send_buf + len, &n_oid, INT64_LEN);
len += INT64_LEN;
}
/* send message to each client */
client_nb = PyTuple_Size (client);
for (i = 0; i < client_nb; i++)
{
ntuple = PyTuple_GetItem (client, i);
nlist = PySequence_Tuple (ntuple);
PyArg_ParseTuple (nlist, (char *) "si", &ip, &port);
Py_XDECREF (nlist);
/* establish connection */
if (!(conn = connectTo (ip, port)))
continue;
if (!send_all (conn, send_buf, buf_len))
continue;
close (conn);
}
free (send_buf);
return 0;
}
/* XXX dont use for the moment */
int
getSNInfo (int conn, int method, char *id, struct node *sn)
{
u_int32_t buf_len, data_len;
u_int16_t meth, id_len;
char buf[BUF_SIZE];
u_int16_t return_code, addr_len;
u_int32_t len = 0;
char rflags[2];
char *send_buf;
/* send request to master */
meth = htons (method);
data_len = htonl (2 + strlen (id));
id_len = htons (strlen (id));
buf_len = HEADER_LEN + ntohl (data_len);
send_buf = (char *) malloc (buf_len);
/* header */
memcpy (send_buf, &meth, 2);
memcpy (send_buf + 2, flags, 2);
memcpy (send_buf + 4, &data_len, 4);
/* data */
memcpy (send_buf + 8, &id_len, 2);
memcpy (send_buf + 10, id, strlen (id));
if (!send_all (conn, send_buf, buf_len))
{
free (send_buf);
return 7;
}
free (send_buf);
/* Wait for response */
buf_len = 0, data_len = 0;
if (!wait_packet (conn, buf, &buf_len, RHEADER_LEN))
return 7;
/* header */
if ((ntohs (*((u_int16_t *) (buf)))) != method)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_WARNING), "return method error");
return 8;
}
memcpy (rflags, buf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (buf + INT16_LEN + FLAG_LEN)));
return_code =
ntohs (*((u_int16_t *) (buf + INT16_LEN + FLAG_LEN + INT32_LEN)));
len = buf_len - RHEADER_LEN;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
return 7;
}
if (return_code != 0)
return return_code;
/* data */
/* Wait for response */
data_len = 0;
buf_len = 0;
if (!wait_packet (conn, buf, &buf_len, RHEADER_LEN))
return 7;
if ((ntohs (*((u_int16_t *) (buf)))) != method)
{
perror ("receive");
return 8;
}
memcpy (rflags, buf + 2, 2);
data_len = ntohl (*((u_int32_t *) (buf + 4)));
return_code = ntohs (*((u_int16_t *) (buf + 8)));
len = buf_len - 10;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
return 7;
}
if (return_code != 0)
return return_code;
len = 0;
/* id */
id_len = ntohs (*((u_int16_t *) (buf + len)));
len += 2;
sn->id = (char *) malloc (id_len + 1);
memset (sn->id, 0, id_len + 1);
memcpy (sn->id, buf + len, id_len);
len += id_len;
/* ip */
addr_len = ntohs (*((u_int16_t *) (buf + len)));
len += 2;
sn->addr = (char *) malloc (addr_len + 1);
memset (sn->addr, 0, addr_len + 1);
memcpy (sn->addr, buf + len, addr_len);
len += addr_len;
/* port */
memcpy (&(sn->port), buf + len, 2);
return return_code;
}
/* method called by client server to wait for a message */
int
wait_msg (int conn, PyObject ** list)
{
u_int64_t serial, oid;
char buf[BUF_SIZE];
u_int32_t len = 0, data_len = 0, buf_len = 0, oid_nb, nb;
u_int16_t method, port;
char rflags[FLAG_LEN];
char id[UUID_LEN + 1], ip[IP_LEN + 1];
/* Wait for response */
if (!wait_packet (conn, buf, &buf_len, HEADER_LEN))
return CONNECTION_FAILURE;
/* header */
method = ntohs (*((u_int16_t *) (buf)));
memcpy (rflags, buf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (buf + INT16_LEN + FLAG_LEN)));
len = buf_len - HEADER_LEN;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
return CONNECTION_FAILURE;
}
printf ("receive mesage with method %d, data len %d\n", method, data_len);
/* data */
len = 0;
*list = PyList_New (0);
PyList_Append (*list, PyInt_FromLong (method));
if (method == 19) /* check cache message */
{
/* get tid */
serial = ntohll (*((u_int64_t *) (buf)));
PyList_Append (*list, PyLong_FromUnsignedLongLong (serial));
len += INT64_LEN;
/* get list of oid */
oid_nb = ntohl (*((u_int32_t *) (buf + len)));
len += INT32_LEN;
for (nb = 0; nb < oid_nb; nb++)
{
oid = ntohll (*((u_int64_t *) (buf + len)));
PyList_Append (*list, PyLong_FromUnsignedLongLong (oid));
len += INT64_LEN;
}
return method;
}
else if (method == 13 || method == 14 || method == 32) /* add node message or change master */
{
/* id */
memset (id, 0, UUID_LEN + 1);
memcpy (id, buf + len, UUID_LEN);
PyList_Append (*list, PyString_FromString (id));
len += UUID_LEN;
/* ip */
memset (ip, 0, IP_LEN + 1);
memcpy (ip, buf + len, IP_LEN);
PyList_Append (*list, PyString_FromString (ip));
len += IP_LEN;
/* port */
port = ntohs (*((u_int16_t *) (buf + len)));
PyList_Append (*list, PyInt_FromLong (port));
return method;
}
else if (method == 15 || method == 16 || method == 33 || method == 28) /* del node message or failure node */
{
/* id */
memset (id, 0, UUID_LEN + 1);
memcpy (id, buf + len, UUID_LEN);
PyList_Append (*list, PyString_FromString (id));
return method;
}
return 0;
}
int
clientClose (int conn, int method, char id[UUID_LEN])
{
u_int32_t data_len;
u_int16_t meth;
char *send_buf;
/* send request to master */
meth = htons (method);
data_len = htonl (UUID_LEN);
send_buf = (char *) malloc (HEADER_LEN + UUID_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
/* data */
memcpy (send_buf + HEADER_LEN, id, UUID_LEN);
if (!send_all (conn, send_buf, HEADER_LEN + UUID_LEN))
{
free (send_buf);
return CONNECTION_FAILURE;
}
free (send_buf);
return 0;
}
int
replyClose (int conn, int method, char id[UUID_LEN])
{
u_int32_t data_len;
u_int16_t meth, return_code = 0;
char *send_buf;
/* send request to master */
meth = htons (method);
data_len = htonl (UUID_LEN);
send_buf = (char *) malloc (UUID_LEN + RHEADER_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN + INT32_LEN, &return_code,
FLAG_LEN);
/* data */
memcpy (send_buf + RHEADER_LEN, id, UUID_LEN);
if (!send_all (conn, send_buf, UUID_LEN + RHEADER_LEN))
{
free (send_buf);
return 7;
}
free (send_buf);
return 0;
}
#include <Python.h>
#include "neo_struct.h"
extern int search_master (int, char **);
extern int generate_id (char **);
extern int getObjectByOid (int, int, u_int64_t, PyObject **);
extern int getObjectBySerial (int, int, u_int64_t, u_int64_t, PyObject **);
extern int getSerial (int, int, u_int64_t, u_int64_t *);
extern int getLastTransaction (int, int, u_int64_t *);
extern int getOid (int, int, u_int16_t, PyObject **);
extern int clientStart (int, int, char *, char *, u_int16_t, PyObject **);
extern int getTransSN (int, int, int16_t, int16_t, PyObject **);
extern int getObjectHist (int, int, u_int64_t, u_int16_t, PyObject **);
extern int undoTrans (int, int, u_int64_t, PyObject **);
extern int beginTrans (int, int, u_int64_t, PyObject **);
extern int endTrans (int, int, u_int64_t, PyObject *, PyObject *);
extern int failure (int, int, char[UUID_LEN]);
extern int transaction (int, int, char *, char *, char *, u_int64_t,
unsigned long, PyObject *, char **);
extern int undo (int, int, u_int64_t, PyObject **);
extern int histInfo (int, int, u_int64_t, u_int64_t, PyObject **);
extern int undoInfo (int, int, u_int64_t, PyObject **);
extern int load (int, int, u_int64_t, u_int64_t, PyObject **);
extern int getSize (int, int, u_int64_t *);
extern int checkCache (int, u_int64_t, PyObject *, PyObject *);
extern int getSNInfo (int, int, char *, struct node *);
extern int getAllSN (int, int, PyObject **);
extern int getAllCN (int, int, PyObject **);
extern int wait_msg (int, PyObject **);
extern int clientClose (int, int, char *);
extern int replyClose (int, int, char *);
static int
handleError (int rcode)
{
switch (rcode)
{
case TMP_FAILURE:
PyErr_SetString (PyExc_SystemError, "temporary failure");
break;
case OID_NOT_FOUND:
PyErr_SetString (PyExc_ValueError, "oid not found");
break;
case SERIAL_NOT_FOUND:
PyErr_SetString (PyExc_ValueError, "serial not found");
break;
case TRANS_NOT_FOUND:
PyErr_SetString (PyExc_ValueError, "transaction not found");
break;
case ABORT_TRANS:
PyErr_SetString (PyExc_RuntimeError, "abort transaction");
break;
case TRANS_NOT_VALID:
PyErr_SetString (PyExc_RuntimeError, "transaction not valid");
break;
case CONNECTION_FAILURE:
PyErr_SetString (PyExc_SystemError, "connection failure");
break;
case METHOD_ERROR:
PyErr_SetString (PyExc_SystemError, "wrong message");
break;
case NOT_READY:
PyErr_SetString (PyExc_RuntimeError, "master not ready");
break;
}
return 0;
}
static PyObject *
_wrap_generate_id (PyObject * self, PyObject * args)
{
PyObject *resultobj;
char *result;
int rcode;
rcode = generate_id (&result);
if (rcode != 0) /* raise exception */
{
handleError (rcode);
return NULL;
}
resultobj =
result ? PyString_FromString (result) : Py_BuildValue ((char *) "");
free (result);
return resultobj;
}
static PyObject *
_wrap_search_master (PyObject * self, PyObject * args)
{
PyObject *resultobj;
int method;
char *result;
int rcode;
if (!PyArg_ParseTuple
(args, (char *) "i:search_master", &method))
goto fail;
rcode = search_master (method, &result);
if (rcode != 0) /* raise exception */
{
handleError (rcode);
return NULL;
}
resultobj =
result ? PyString_FromString (result) : Py_BuildValue ((char *) "");
free (result);
return resultobj;
fail:
return NULL;
}
static PyObject *
_wrap_getObjectByOid (PyObject * self, PyObject * args)
{
int conn, method;
u_int64_t oid;
u_int16_t rcode;
PyObject *resultlist;
if (!PyArg_ParseTuple
(args, (char *) "iiK:getObjectByOid", &conn, &method, &oid))
goto fail;
rcode = getObjectByOid (conn, method, oid, &resultlist);
if (rcode != 0)
{
handleError (rcode);
return NULL;
}
return resultlist;
fail:
return NULL;
}
static PyObject *
_wrap_getObjectBySerial (PyObject * self, PyObject * args)
{
PyObject *resultlist;
int conn, method;
u_int64_t oid, serial;
int rcode;
if (!PyArg_ParseTuple
(args, (char *) "iiKK:getObjectBySerial", &conn, &method, &oid,
&serial))
goto fail;
rcode = getObjectBySerial (conn, method, oid, serial, &resultlist);
if (rcode != 0)
{
handleError (rcode);
return NULL;
}
return resultlist;
fail:
return NULL;
}
static PyObject *
_wrap_getSerial (PyObject * self, PyObject * args)
{
int conn, method;
u_int64_t oid, serial;
int rcode;
if (!PyArg_ParseTuple
(args, (char *) "iiK:getSerial", &conn, &method, &oid))
goto fail;
rcode = getSerial (conn, method, oid, &serial);
if (rcode != 0)
{
handleError (rcode);
return NULL;
}
return PyLong_FromUnsignedLongLong (serial);
fail:
return NULL;
}
static PyObject *
_wrap_getLastTransaction (PyObject * self, PyObject * args)
{
int conn, method;
u_int64_t tid;
int rcode;
if (!PyArg_ParseTuple
(args, (char *) "ii:getLastTransaction", &conn, &method))
goto fail;
rcode = getLastTransaction (conn, method, &tid);
if (rcode != 0)
{
handleError (rcode);
return NULL;
}
return PyLong_FromUnsignedLongLong (tid);
fail:
return NULL;
}
static PyObject *
_wrap_getOid (PyObject * self, PyObject * args)
{
PyObject *resultlist;
int conn, method;
u_int16_t rcode, nb_oid;
if (!PyArg_ParseTuple
(args, (char *) "iiH:getOid", &conn, &method, &nb_oid))
goto fail;
rcode = getOid (conn, method, nb_oid, &resultlist);
if (rcode != 0)
{
handleError (rcode);
return NULL;
}
return resultlist;
fail:
return NULL;
}
static PyObject *
_wrap_clientStart (PyObject * self, PyObject * args)
{
PyObject *resultlist;
int conn, method;
char *id, *ip;
u_int16_t port;
int rcode;
if (!PyArg_ParseTuple
(args, (char *) "iissH:clientStart", &conn, &method, &id, &ip, &port))
goto fail;
rcode = clientStart (conn, method, id, ip, port, &resultlist);
if (rcode != 0)
{
handleError (rcode);
return NULL;
}
return resultlist;
fail:
return NULL;
}
static PyObject *
_wrap_getTransSN (PyObject * self, PyObject * args)
{
PyObject *resultlist;
int conn, method;
int16_t rcode, first, last;
if (!PyArg_ParseTuple
(args, (char *) "iihh:getTransSN", &conn, &method, &first, &last))
goto fail;
rcode = getTransSN (conn, method, first, last, &resultlist);
if (rcode != 0)
{
handleError (rcode);
return NULL;
}
return resultlist;
fail:
return NULL;
}
static PyObject *
_wrap_getObjectHist (PyObject * self, PyObject * args)
{
PyObject *resultlist;
int conn, method;
u_int64_t oid;
u_int16_t length;
u_int16_t rcode;
if (!PyArg_ParseTuple
(args, (char *) "iiKH:getObjectHist", &conn, &method, &oid, &length))
goto fail;
rcode = getObjectHist (conn, method, oid, length, &resultlist);
if (rcode != 0)
{
handleError (rcode);
return NULL;
}
return resultlist;
fail:
return NULL;
}
static PyObject *
_wrap_undoTrans (PyObject * self, PyObject * args)
{
PyObject *resultlist;
int conn, method;
u_int64_t tid;
u_int16_t rcode;
if (!PyArg_ParseTuple
(args, (char *) "iiK:undoTrans", &conn, &method, &tid))
goto fail;
rcode = (int) undoTrans (conn, method, tid, &resultlist);
if (rcode != 0)
{
handleError (rcode);
return NULL;
}
return resultlist;
fail:
return NULL;
}
static PyObject *
_wrap_beginTrans (PyObject * self, PyObject * args)
{
int conn, method;
u_int64_t tid;
u_int16_t rcode;
PyObject *resultlist;
if (!PyArg_ParseTuple
(args, (char *) "iiK:beginTrans", &conn, &method, &tid))
goto fail;
rcode = beginTrans (conn, method, tid, &resultlist);
if (rcode != 0)
{
handleError (rcode);
return NULL;
}
return resultlist;
fail:
return NULL;
}
static PyObject *
_wrap_endTrans (PyObject * self, PyObject * args)
{
int conn, method, rcode = 0;
u_int64_t tid;
PyObject *oid_list, *oid_obj, *storage_obj, *storage_list;
if (!PyArg_ParseTuple
(args, (char *) "iiKOO", &conn, &method, &tid, &oid_obj, &storage_obj))
goto fail;
oid_list = PyTuple_New (1);
oid_list = PySequence_Tuple (oid_obj);
storage_list = PyTuple_New (1);
storage_list = PySequence_Tuple (storage_obj);
rcode = (int) endTrans (conn, method, tid, oid_list, storage_list);
Py_XDECREF (oid_list);
Py_XDECREF (storage_list);
if (rcode != 0)
{
handleError (rcode);
return NULL;
}
return PyInt_FromLong ((long) rcode);
fail:
return NULL;
}
static PyObject *
_wrap_failure (PyObject * self, PyObject * args)
{
PyObject *resultobj;
int conn, method;
char *storage_id;
int rcode;
if (!PyArg_ParseTuple
(args, (char *) "iis:failure", &conn, &method, &storage_id))
goto fail;
rcode = (int) failure (conn, method, storage_id);
if (rcode != 0)
{
handleError (rcode);
return NULL;
}
resultobj = PyInt_FromLong ((long) rcode);
return resultobj;
fail:
return NULL;
}
static PyObject *
_wrap_transaction (PyObject * self, PyObject * args)
{
int method, rcode = 0, conn;
char *user, *desc, *ext, *result;
unsigned long data_size;
u_int64_t tid;
PyObject *tuple, *list;
if (!PyArg_ParseTuple
(args, (char *) "iisssKkO", &conn, &method, &user, &desc, &ext,
&tid, &data_size, &tuple))
goto fail;
list = PyTuple_New (1);
list = PySequence_Tuple (tuple);
rcode =
(int) transaction (conn, method, user, desc, ext, tid, data_size,
list, &result);
Py_XDECREF (list);
if (rcode != 0)
{
handleError (rcode);
return NULL;
}
return PyInt_FromLong ((long) rcode);
fail:
return NULL;
}
static PyObject *
_wrap_undo (PyObject * self, PyObject * args)
{
PyObject *resultlist;
int method, conn;
u_int64_t tid;
u_int16_t rcode;
if (!PyArg_ParseTuple (args, (char *) "iiK:undo", &conn, &method, &tid))
goto fail;
rcode = (int) undo (conn, method, tid, &resultlist);
if (rcode != 0)
{
handleError (rcode);
return NULL;
}
return resultlist;
fail:
return NULL;
}
static PyObject *
_wrap_histInfo (PyObject * self, PyObject * args)
{
PyObject *resultobj;
int method, conn;
u_int64_t oid, serial;
int rcode;
if (!PyArg_ParseTuple
(args, (char *) "iiKK:histInfo", &conn, &method, &oid, &serial))
goto fail;
rcode = histInfo (conn, method, oid, serial, &resultobj);
if (rcode != 0)
{
handleError (rcode);
return NULL;
}
return resultobj;
fail:
return NULL;
}
static PyObject *
_wrap_undoInfo (PyObject * self, PyObject * args)
{
PyObject *resultobj;
int method, conn;
u_int64_t tid;
int rcode;
if (!PyArg_ParseTuple (args, (char *) "iiK:undoInfo", &conn, &method, &tid))
goto fail;
rcode = undoInfo (conn, method, tid, &resultobj);
if (rcode != 0)
{
handleError (rcode);
return NULL;
}
return resultobj;
fail:
return NULL;
}
static PyObject *
_wrap_load (PyObject * self, PyObject * args)
{
PyObject *resultobj;
int conn, method;
u_int64_t oid, serial;
int rcode;
if (!PyArg_ParseTuple
(args, (char *) "iiKK:load", &conn, &method, &oid, &serial))
goto fail;
rcode = load (conn, method, oid, serial, &resultobj);
if (rcode != 0)
{
handleError (rcode);
return NULL;
}
return resultobj;
fail:
return NULL;
}
static PyObject *
_wrap_getSize (PyObject * self, PyObject * args)
{
PyObject *resultobj;
int conn, method;
u_int64_t result;
int rcode;
if (!PyArg_ParseTuple (args, (char *) "ii:getSize", &conn, &method))
goto fail;
rcode = (int) getSize (conn, method, &result);
if (rcode != 0)
{
handleError (rcode);
return NULL;
}
resultobj = PyLong_FromUnsignedLongLong ((long long) result);
return resultobj;
fail:
return NULL;
}
static PyObject *
_wrap_checkCache (PyObject * self, PyObject * args)
{
int method, rcode;
u_int64_t serial;
PyObject *oid, *client, *resultobj, *oid_list, *client_list;
if (!PyArg_ParseTuple
(args, (char *) "iKOO", &method, &serial, &oid, &client))
goto fail;
oid_list = PyTuple_New (1);
oid_list = PySequence_Tuple (oid);
client_list = PyTuple_New (1);
client_list = PySequence_Tuple (client);
rcode = (int) checkCache (method, serial, oid_list, client_list);
resultobj = PyInt_FromLong ((long) rcode);
return resultobj;
fail:
return NULL;
}
static PyObject *
_wrap_getSNInfo (PyObject * self, PyObject * args)
{
PyObject *resultobj;
int arg1;
int arg2;
char *arg3;
struct node result;
int rcode;
if (!PyArg_ParseTuple (args, (char *) "iis:getSNInfo", &arg1, &arg2, &arg3))
goto fail;
rcode = getSNInfo (arg1, arg2, arg3, &result);
if (rcode != 0)
{
handleError (rcode);
return NULL;
}
resultobj = Py_BuildValue ("ssi", result.id, result.addr, result.port);
return resultobj;
fail:
return NULL;
}
static PyObject *
_wrap_getAllSN (PyObject * self, PyObject * args)
{
PyObject *resultlist;
int arg1;
int arg2;
u_int16_t rcode;
if (!PyArg_ParseTuple (args, (char *) "ii:getAllSN", &arg1, &arg2))
goto fail;
rcode = getAllSN (arg1, arg2, &resultlist);
if (rcode != 0)
{
handleError (rcode);
return NULL;
}
return resultlist;
fail:
return NULL;
}
static PyObject *
_wrap_getAllCN (PyObject * self, PyObject * args)
{
PyObject *resultlist;
int arg1;
int arg2;
u_int16_t rcode;
if (!PyArg_ParseTuple (args, (char *) "ii:getAllCN", &arg1, &arg2))
goto fail;
rcode = getAllCN (arg1, arg2, &resultlist);
if (rcode != 0)
{
handleError (rcode);
return NULL;
}
return resultlist;
fail:
return NULL;
}
static PyObject *
_wrap_clientClose (PyObject * self, PyObject * args)
{
PyObject *resultobj;
int arg1;
int arg2;
char *arg3;
int rcode;
if (!PyArg_ParseTuple
(args, (char *) "iis:clientClose", &arg1, &arg2, &arg3))
goto fail;
rcode = clientClose (arg1, arg2, arg3);
if (rcode != 0)
{
handleError (rcode);
return NULL;
}
resultobj = PyInt_FromLong ((long) rcode);
return resultobj;
fail:
return NULL;
}
static PyObject *
_wrap_replyClose (PyObject * self, PyObject * args)
{
PyObject *resultobj;
int conn, method;
char *id;
int rcode;
if (!PyArg_ParseTuple
(args, (char *) "iis:clientClose", &conn, &method, &id))
goto fail;
rcode = replyClose (conn, method, id);
if (rcode != 0)
{
handleError (rcode);
return NULL;
}
resultobj = PyInt_FromLong ((long) rcode);
return resultobj;
fail:
return NULL;
}
static PyObject *
_wrap_wait (PyObject * self, PyObject * args)
{
PyObject *resultlist;
int arg1;
u_int16_t rcode;
if (!PyArg_ParseTuple (args, (char *) "i:wait", &arg1))
goto fail;
rcode = wait_msg (arg1, &resultlist);
if (rcode != 0)
return resultlist;
fail:
return NULL;
}
static PyMethodDef SwigMethods[] = {
{(char *) "generate_id", _wrap_generate_id, METH_VARARGS},
{(char *) "search_master", _wrap_search_master, METH_VARARGS},
{(char *) "getObjectByOid", _wrap_getObjectByOid, METH_VARARGS},
{(char *) "getObjectBySerial", _wrap_getObjectBySerial, METH_VARARGS},
{(char *) "getSerial", _wrap_getSerial, METH_VARARGS},
{(char *) "getLastTransaction", _wrap_getLastTransaction, METH_VARARGS},
{(char *) "getOid", _wrap_getOid, METH_VARARGS},
{(char *) "clientStart", _wrap_clientStart, METH_VARARGS},
{(char *) "getTransSN", _wrap_getTransSN, METH_VARARGS},
{(char *) "getObjectHist", _wrap_getObjectHist, METH_VARARGS},
{(char *) "undoTrans", _wrap_undoTrans, METH_VARARGS},
{(char *) "beginTrans", _wrap_beginTrans, METH_VARARGS},
{(char *) "endTrans", _wrap_endTrans, METH_VARARGS},
{(char *) "failure", _wrap_failure, METH_VARARGS},
{(char *) "transaction", _wrap_transaction, METH_VARARGS},
{(char *) "undo", _wrap_undo, METH_VARARGS},
{(char *) "histInfo", _wrap_histInfo, METH_VARARGS},
{(char *) "undoInfo", _wrap_undoInfo, METH_VARARGS},
{(char *) "load", _wrap_load, METH_VARARGS},
{(char *) "getSize", _wrap_getSize, METH_VARARGS},
{(char *) "checkCache", _wrap_checkCache, METH_VARARGS},
{(char *) "getSNInfo", _wrap_getSNInfo, METH_VARARGS},
{(char *) "getAllSN", _wrap_getAllSN, METH_VARARGS},
{(char *) "getAllCN", _wrap_getAllCN, METH_VARARGS},
{(char *) "clientClose", _wrap_clientClose, METH_VARARGS},
{(char *) "wait", _wrap_wait, METH_VARARGS},
{(char *) "replyClose", _wrap_replyClose, METH_VARARGS},
{NULL, NULL}
};
void
initneoclient ()
{
(void) Py_InitModule ("neoclient", SwigMethods);
}
from mq import MQ
from ZODB import POSException, Transaction
from ZODB.utils import oid_repr, p64, u64, U64
from threading import Thread, Lock, Condition
from cPickle import dumps, loads
from zlib import crc32
from time import gmtime, localtime
import neoclient
import socket
import signal
import random
import gc
import syslog
import sys
import os, time
from ZODB.BaseStorage import BaseStorage
from ZODB.TimeStamp import TimeStamp
from DateTime import DateTime
import traceback
MASTER_PORT = 10823
CLIENT_PORT = 11111
MAX_STORAGE_CONNECTION = 5
debug = 0
# Client cache using mutli-queue algorithm
# the key is the oid, and the value is a tuple
# containing the serial number and object's data
cache = MQ()
cache_lock = Lock()
# storage dict : id -> (ipv4addr, port); and client dict (idem)
storages = {}
clients = {}
# storage connection list : storage id -> file descriptor for connection
storages_connection = {}
# XXX master connection must be global too...
id = None
class neostorage_server_thread(Thread):
""" class handle each client connection from other client """
def __init__(self, socket, **kw):
Thread.__init__(self, **kw)
self.socket = socket
self.cache_lock = cache_lock
self.methods = {19:self.checkCache,
13:self.addSN,
14:self.addCN,
15:self.delSN,
16:self.delCN,
28:self.masterClose,
32:self.masterChange,
33:self.unreliableStorage,
}
if debug : print '*** New Client Server thread running ***'
def run(self):
while 1: # connection layer return a tuple, first item is method id
data = neoclient.wait(self.socket.fileno())
if debug : print 'neoclient : data received with key %d' %data[0]
# waitMsg
if self.methods.has_key(data[0]):
self.methods[data[0]](data[1:])
self.socket.close()
return
def checkCache(self, ob):
""" invalidate list of objects send by other client """
print 'check cache for oid %r' %(ob,)
for oid in ob:
self.cache_lock.acquire()
try:
if p64(long(oid)) in cache:
try:
del cache[oid]
except:
pass
finally:
self.cache_lock.release()
print 'check done'
def addSN(self,sn):
print 'add sn'
storages[sn[0]] = (sn[1], sn[2])
if debug : print storages
def addCN(self,cn):
print 'add cn'
clients[cn[0]] = (cn[1], cn[2])
if debug : print clients
def delSN(self,sn):
try:
if debug : print 'neoclient : delSN : sn %r' %(sn)
storages_connection[sn[0]][0].close()
storages_connection[sn[0]][1].close()
del storages_connection[sn[0]]
del storages[sn[0]]
except:
raise
if debug : print storages, storages_connection
def delCN(self,cn):
if debug : print 'del cn %r' (clients[cn[0]],)
try:
del clients[cn[0]]
except:
pass
if debug : print clients
def unreliableStorage(self, cn):
pass
def masterClose(self, mid):
if debug : print "neoclient : Master %s closed" %mid[0]
neoclient.replyClose (self.socket.fileno(), 28, id)
## pid = os.getpid()
## os.kill(pid, signal.SIGTERM)
def masterChange(self, mn):
if debug : print 'neoclient : new master %s, %s, %d' %(sn[0], sn[1], sn[2])
def __del__(self):
print 'the end'
class neostorage_server(Thread):
""" client server accepting connection from other client """
def __init__(self):
Thread.__init__(self)
print '********** neostorage server init ************'
if debug : print 'neoclient : init Client Server'
server_started = 1
# create server
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
global CLIENT_PORT
while 1:
try:
self.sock.bind(('127.0.0.1',CLIENT_PORT))
break
except:
CLIENT_PORT += 1
if debug : print 'neoclient : client server port %d' % CLIENT_PORT
self.sock.listen(5)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
def run(self):
if debug : print 'neoclient : server starting..'
# wait connection and handle it with ClientNodeServerThread
while 1:
conn, addr = self.sock.accept()
thread = neostorage_server_thread(socket=conn)
print 'thread new created'
thread.start()
print 'thread started'
def __del__(self):
print 'the end of server'
self.sock.close()
## self.stop()
class neostorage(BaseStorage):
""" Storage interface for the NEO """
def __init__(self, create=0, read_only=0, master=None):
BaseStorage.__init__(self, 'NEO')
self.read_only = read_only
self.cache = cache
# Lock for transaction
self.txn_cond = Condition()
# Lock for cache
self.cache_lock = cache_lock
# Lock for new oid
self.oid_lock = Lock()
# Lock for load
self.load_lock = Lock()
# another lock for bootstrap
self.lock = Lock()
# init some variable
self.txnStorages = []
self.txn = None
self.tmpStore = {}
self.serial = None
self.master = master
self.oidl = []
self.__name__ = 'NEO'
self.infos = {}
self.infos['name'] = 'NEO (not connected)'
self.infos['supportsVersion'] = 0
self.infos['supportsUndo'] = 0
self.infos['supportsTransUndo'] = 0
self.read_only = read_only
self.infos['extension'] = ''
syslog.openlog('neoclient')
self._storage = "Neo"
self._db = None
# gc.set_debug(gc.DEBUG_LEAK)
# create client server
# XXX lmuqt only creates one !!
self.lock.acquire()
self.server = neostorage_server()
self.lock.release()
self.server.start()
# generate identifiant
self.id = neoclient.generate_id()
global id
id = self.id
syslog.syslog("neoclient id")
syslog.syslog(self.id)
if debug : print "neoclient : id %s" %self.id
# connection to master...
self.MasterSock = None
self.Master_fd = None
self.connected = 0;
while not self.connected: # wait for a connection
self.connected = self.connectToMaster()
time.sleep(5)
if debug : print 'neoclient : connected to master'
self.started = 0;
self.lock.acquire()
try:
while not self.started:
self.started = self.clientStart()
time.sleep(15)
if debug : print 'neoclient : client starting...'
# get list of all clients and storages
try:
storageslist = neoclient.getAllSN(self.MasterSock.fileno(), 11)
for storage in storageslist:
storages[storage[0]] = (storage[1], storage[2])
except SystemError:
raise
if debug : print storages
try:
clientslist = neoclient.getAllCN(self.MasterSock.fileno(), 12)
for client in clientslist:
if client[0] != self.id:
clients[client[0]] = (client[1], client[2])
except SystemError:
raise
if debug : print clients
finally:
self.lock.release()
if debug :
print 'neoclient : client started'
def __del__(self):
print 'the end'
if debug : print 'neoclient : close'
self.close()
def close(self):
if debug : print 'neoclient : closing neostorage...'
if self.MasterSock is not None:
try:
neoclient.clientClose(self.Master_fd, 26, self.id)
except SystemError:
raise
except:
raise
self.MasterSock.close()
self.MasterSock = None
## self.server.stop()
if debug : print 'neoclient : client closed'
# try with self.server.stop()
pid = os.getpid()
os.kill(pid, signal.SIGTERM)
def connectToMaster(self):
try:
# find the master
self.master = neoclient.search_master(38)
print 'master found on %s' %(self.master,)
# connect to it
self.MasterSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.MasterSock.connect((self.master, MASTER_PORT))
self.Master_fd = self.MasterSock.makefile().fileno()
return 1
except:
return 0
def connectToStorage(self, id):
""" connect to a storage """
# A list of opened connection is keep in order to not
# always reconnect to storages
self.lock.acquire()
try:
if storages_connection.has_key(id):
return (storages_connection[id][1]).fileno()
if len(storages_connection) == MAX_STORAGE_CONNECTION:
# too many connection, close one
(fd, sock) = storages_connection.pop()
fd.close()
sock.close()
# create new connection
storage_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
storage_sock.connect((storages[id][0], storages[id][1]))
storage_fd = storage_sock.makefile()
storages_connection[id] = (storage_fd, storage_sock)
if debug : print 'neoclient : connected to storage with %d' % storage_sock.fileno()
return storage_sock.fileno()
finally:
self.lock.release()
def closeStorageConnection(self):
""" close all connection to storages nodes """
global storages_connection
print storages_connection
for s in storages_connection:
storages_connection[s][0].close()
storages_connection[s][1].close()
def getSnInfos(self,id): # XXX not used
""" get addr and port for the given storage id """
try:
node = neoclient.getSNInfo(self.Master_fd, 17, id)
storages[node[0]] = (node[1], node[2])
except:
raise
def clientStart(self):
""" try to start and get information from the master before any work """
if debug : print 'neoclient : client starting'
try:
self.ip = socket.gethostbyname('127.0.0.1') # socket.gethostname()
infos = neoclient.clientStart(self.Master_fd, 31, self.id, str(self.ip), CLIENT_PORT)
self.infos['name'] = infos[0]
self.infos['supportsVersion'] = infos[1]
self.infos['supportsUndo'] = infos[2]
self.infos['supportsTransUndo'] = infos[3]
self.read_only = infos[4]
self.infos['extension'] = infos[5]
return 1
except SystemError:
if str(sys.exc_value) == 'temporary failure':
print 'master node is not running'
return 0
else:
raise
except RuntimeError:
if str(sys.exc_value) == 'master not ready':
print 'system not ready to handle request'
return 0
else:
raise
def checkCache(self, objects):
""" send list of invalidated bject to ohter client """
if debug : print 'neoclient : checkCache'
if len(clients) == 0:
return
oids = []
for ob in objects: # construct list of oid
tuple = [U64(ob)]
oids.append(tuple)
client = []
for c in clients: # construct list of client : (ip, port)
tuple = [clients[c][0], int(clients[c][1])]
client.append(tuple)
try:
print 'send check cache message for oids %r to clients %r' %(oids,client)
neoclient.checkCache(19, U64(self.serial), oids, client)
except SystemError:
print 'system error in sending check cache'
# Storage API...
def __len__(self):
if debug : print 'neoclient : return __len__'
return self.cache._size
def sortKey(self):
if debug : print 'neoclient : sortkey'
return '%s:%s' % ('Cluster Storage' , self.master)
def isReadOnly(self):
""" Storage API: return whether we are in read-only mode. """
if debug : print 'neoclient : isReadOnly'
return self.read_only
def registerDB(self, db, limit):
if debug : print 'neoclient : registerDB'
self._db = db
def getName(self):
""" Storage API: return the storage name as a string. """
if debug : print 'neoclient : getName'
return "%s" % self.infos['name']
def getExtensionMethods(self):
""" StorageAPI : return extension methods support by storage. """
if debug : print 'getExtensionMethods'
return self.infos['extension']
def supportsUndo(self):
""" Storage API: return whether we support undo. """
if debug : print 'neoclient : upportsUndo %d' %self.infos['supportsUndo']
return self.infos['supportsUndo']
def supportsTransactionalUndo(self):
""" Storage API: return whether we support transactional undo."""
if debug : print 'neoclient : support Trans Undo %d' %self.infos['supportsTransUndo']
return self.infos['supportsTransUndo']
def supportsVersions(self):
""" Storage API: return whether we support versions. """
if debug : print 'neoclient : supportsVersion %d' %self.infos['supportsVersion']
return self.infos['supportsVersion']
def pack(self, *d, **kw):
if self.read_only:
raise POSException.ReadOnlyError()
return
def getSerial(self, oid):
if debug : print 'neoclient : getSerial'
self.cache_lock.acquire()
try:
# XXX maybe dont try in cache, may have change on master...
if oid in self.cache:
return p64(long(cache[oid][0]))
finally:
self.cache_lock.release()
try: # otherwise get from master
serial = neoclient.getSerial(self.Master_fd, 3, U64(oid))
return p64(long(serial))
except SystemError:
raise
except ValueError:
raise POSException.POSKeyError(oid)
def lastTransaction(self):
""" Storage API: return last transaction id """
if debug : 'neoclient : get last transaction'
try:
ltid = neoclient.getLastTransaction(self.Master_fd, 4)
return p64(long(ltid))
except systemError:
raise
def new_oid(self):
""" Storage API: return a new object identifier. """
if debug : print 'neoclient : new_oid'
if self.read_only:
raise POSException.ReadOnlyError()
self.oid_lock.acquire()
try:
if len(self.oidl) == 0:
# get 20 oids by default from master
# XXX must lock to avoid many request for new oid
self.lock.acquire()
try:
oid_list = neoclient.getOid(self.Master_fd, 5, 20)
except SystemError:
raise
# for each oid create the string representation
for noid in oid_list:
oid = '\0\0\0\0\0\0\0\0'
for i in xrange(8):
oid = oid[:i]+chr(noid[i])
self.oidl.append(oid)
self.oidl.reverse()
self.lock.release()
self._oid = self.oidl.pop()
if debug : print 'neoclient : new oid %d' %U64(self._oid)
return self._oid
finally:
self.oid_lock.release()
def loadSerial(self, oid, serial):
""" Storage API: load a historical revision of an object. """
if debug: print 'neoclient : load serial'
self.cache_lock.acquire()
try: # try in cache
if oid in self.cache:
if self.cache[oid][0] == U64(serial):
if debug : print 'neoclient : load serial from cache'
return loads(self.cache[oid][1])
finally:
self.cache_lock.release()
self.load_lock.acquire()
try:
try: # otherwise get storages from master
load_storages = neoclient.getObjectBySerial(self.Master_fd, 2, U64(oid), U64(serial))
except ValueError: # serial or oid not found
raise POSException.POSKeyError (oid,serial)
except SystemError:
raise
load_storages = list(load_storages)
while 1:
if len(load_storages) == 0:
# no more storage and we don't get the object
raise RuntimeError
s = random.choice(load_storages)
# s = load_storages[0]
load_storages.remove(s)
if storages.has_key(s) is False:
continue
try:
conn = self.connectToStorage(s)
data = neoclient.load(conn, 24, U64(oid), U64(serial))
# check crc
if crc32(data[0]) != data[1]:
print 'neoclient : load serial : crc check failed for oid %d' %U64(oid)
continue
else:
break
except SystemError: # XXX report failure and try with another storage
neoclient.failure(self.Master_fd, 18, s)
except ValueError: # XXX not on this storage! strange but try with anther one
continue
# XXX must store in cache ??
if debug : print 'neoclient : load serial from storage'
return loads(data[0])
finally:
self.load_lock.release()
def load(self, oid, version=None):
""" Storage API: return the data for a given object. """
if debug : print 'neoclient : load object %d' %U64(oid)
self.cache_lock.acquire()
try:
# try in cache
if oid in self.cache:
if debug : print 'neoclient : load object %d from cache' %U64(oid)
return loads(self.cache[oid][1]), p64(self.cache[oid][0])
finally:
self.cache_lock.release()
# otherwise get storages from master
self.load_lock.acquire()
try:
try:
data = neoclient.getObjectByOid(self.Master_fd, 1, U64(oid))
except ValueError:
if debug : print 'neoclient : load -> object not found'
raise POSException.POSKeyError (oid)
except SystemError:
raise
# get data from storage
serial = data[0]
load_storages = list(data[1:])
while 1:
if len(load_storages) == 0:
# no more storage and we don't get the object
raise RuntimeError
s = random.choice(load_storages)
load_storages.remove(s)
if storages.has_key(s) is False:
continue
try:
conn = self.connectToStorage(s)
data = neoclient.load(conn, 24, U64(oid), serial)
# check crc
if crc32(data[0]) != data[1]:
print 'neoclient : error in crc check for object %d' %U64(oid)
continue # XXX maybe report error ??
else:
break
except ValueError:
continue
except SystemError:
neoclient.failure(self.Master_fd, 18, s)
# store object in cache
self.cache_lock.acquire()
cache[oid] = (serial, data[0])
self.cache_lock.release()
return loads(data[0]), p64(serial)
finally:
self.load_lock.release()
def getSize(self):
""" Storage API: an approximate size of the database, in bytes. """
if debug : print 'neoclient : getsize'
# size = 0
# for storage in storages:
# try:
# conn = self.connectToStorage(storage)
# size += neoclient.getSize (conn, 25)
# except SystemError: # notify failure to master
# neoclient.failure(self.Master_fd, 18, storage)
# except:
# continue
# if size == 0:
# return self.cache._size
# return size
return self.cache._size
def undo(self, *d, **kw):
""" Deprecated, use undoTransactional instead"""
if debug : print 'neoclient : undo'
if self.read_only:
raise POSException.ReadOnlyError()
raise POSException.UndoError, 'non-undoable transaction'
def undoLog(self, *d, **kw):
""" Deprecated, use undoInfo instead """
if debug : print 'neoclient : undo log'
return ()
def undoInfo(self, first=0, last=-20, specification=None):
""" Storage API: return undo information. """
if debug : print 'neoclient : undo info, first %d, last %d' %(first, last)
try:
tlist = neoclient.getTransSN(self.Master_fd, 6, first, last)
except SystemError:
raise
undoInfo = []
for trans in tlist:
undo_storages = list(trans[1:])
while 1:
if len(undo_storages) == 0:
break # or raise error
s = random.choice(undo_storages) # choose a random storage and remove it from list
undo_storages.remove(s)
try:
conn = self.connectToStorage(s)
data = neoclient.undoInfo(conn, 23, trans[0])
info = {}
info['time'] = TimeStamp(p64(long(data[3]))).timeTime()
info['username'] = data[1]
info['description'] = data[2]
info['id'] = p64(long(data[3]))
undoInfo.append(info)
break
except SystemError:
neoclient.failure(self.Master_fd, 18, s)
except ValueError:
raise POSException.UndoError('invalid transaction id', trans[0])
return undoInfo
def history(self, oid, version=None, length=1):
""" Storage API: return a sequence of HistoryEntry objects. """
if debug : print 'neoclient : history'
histInfo = []
try:
t = time.time()
slist = neoclient.getObjectHist(self.Master_fd, 7, U64(oid), length)
t = time.time() - t
print 'neoclient : master time : %.4f' %t
except SystemError:
raise
except ValueError:
raise POSException.POSKeyError(oid)
for serial in slist:
hist_storages = list(serial[1:])
while 1:
if len(hist_storages) == 0:
break # or raise error
s = random.choice(hist_storages) # choose a random storage and remove it from list
# s = hist_storages[0]
if debug : print 'get info from %s for %s' %(s, serial[0])
hist_storages.remove(s)
try:
conn = self.connectToStorage(s)
t = time.time()
data = neoclient.histInfo(conn, 22, U64(oid), serial[0])
t = time.time() - t
print 'storage time : %.4f' %t
hist = {}
# hist['time'] = float(data[0])
hist['time'] = TimeStamp(p64(long(data[3]))).timeTime()
hist['user_name'] = data[1]
hist['description'] = data[2]
hist['serial'] = p64(long(data[3]))
hist['version'] = None
hist['size'] = data[4]
histInfo.append(hist)
break
except SystemError:
neoclient.failure(self.Master_fd, 18, s)
except ValueError:
continue
return histInfo
# method following are for transaction
def transactionalUndo(self, tid, txn=None):
""" Storage API: undo a transaction in context of a transaction. """
if debug :
print 'neoclient : transactional undo'
if self.read_only:
raise POSException.ReadOnlyError()
if txn is not self.txn:
raise POSException.StorageTransactionError(self, transaction)
# XXX think we must only mark the transaction as undone onto the master
# and let it remaining on storage node
try:
# get storages from master
try:
undo_storages = neoclient.undoTrans(self.Master_fd, 8, U64(tid));
except ValueError: # trans not found
raise POSException.UndoError (tid)
except SystemError:
raise
# undo trans on storages
undo_storages = list(undo_storages)
for s in undo_storages:
try:
conn = self.connectToStorage(s)
data = neoclient.undo(conn, 21, U64(tid))
break
except SystemError:
neoclient.failure(self.Master_fd, 18, s)
except ValueError:
continue
# must check its own and the other client cache
oid_list = []
self.cache_lock.acquire()
for oid in data:
# invalidate cache
if p64(oid) in self.cache:
print 'neoclient : del in cache'
del cache[p64(oid)]
# construct list of oid for zope
oid_list.append(p64(oid))
self.cache_lock.release()
return oid_list
finally:
pass
def tpc_begin(self, transaction, tid=None, status=' '):
""" Storage API: begin a transaction. """
if debug :
print 'neoclient : tpc_begin'
if self.read_only:
raise POSException.ReadOnlyError()
# get transaction
self.txn_cond.acquire()
while self.txn is not None:
if self.txn == transaction:
self.txn_cond.release()
return
self.txn_cond.wait(30)
self.txn = transaction
self.txn_cond.release()
# begin it
try:
data = neoclient.beginTrans(self.Master_fd, 9, 0);
except SystemError:
raise
# generate the new tid if no tid given
if tid is None:
tid = '\0\0\0\0\0\0\0\0'
for i in xrange(8): # construct tid in 8 byte-string
tid = tid[:i]+chr(data[0][i])
self.serial = self._ts = tid # tid
self.txnStorages = data[1:] # list of storages
if debug :
print "neoclient : begin transaction %s" %U64(self.serial)
print self.txnStorages
# return self.serial
def store(self, oid, serial, data, version, transaction):
"""Storage API: store data for an object."""
if debug : print 'neoclient : store, oid %d' %U64(oid)
if self.read_only:
raise POSException.ReadOnlyError()
if self.txn is not transaction:
raise POSException.StorageTransactionError(self, transaction)
# store object in temporary buffer
if serial is None:
serial = '\0\0\0\0\0\0\0\0'
if oid in self.cache:
serial = p64(self.cache[oid][0])
self.tmpStore[oid] = (U64(serial), dumps(data))
return serial
def tpc_vote(self, transaction):
"""Storage API: vote on a transaction."""
if debug : print 'neoclient : tpc_vote'
if self.read_only:
raise POSException.ReadOnlyError()
if self.txn is not transaction:
raise POSException.StorageTransactionError(self, transaction)
# construct list of object to be stored
arg = []
size = 0
for ob in self.tmpStore:
crc = crc32(self.tmpStore[ob][1])
tuple = [U64(ob), U64(self.serial), self.tmpStore[ob][1], crc]
# oid , serial , data , crc
size += len(self.tmpStore[ob][1]) # data size
arg.append (tuple)
# check if transaction argument are not None otherwise put empty string instead
if self.txn.user is None:
self.txn.user = ""
if self.txn.description is None:
self.txn.description = ""
if self.txn._extension is None:
self.txn._extension = ""
# send objects in transaction to all storages nodes
for s in self.txnStorages:
try:
if debug :
print 'neoclient : send transaction to storage %s, %d' %(storages[s][0], storages[s][1])
# send transaction to storage
conn = self.connectToStorage(s)
neoclient.transaction(conn, 20, self.txn.user, self.txn.description, self.txn._extension, U64(self.serial), size, arg)
if debug : print "neoclient : transaction stored!"
except SystemError:
neoclient.failure(self.Master_fd, 18, s)
continue
except RuntimeError: # must abort transaction
print 'RuntTimeError in tpc_vote for storage '
# construct list of oid-serial for validation
oid = []
for ob in self.tmpStore:
tuple = [U64(ob)]
# must send the last serial of the object in order
# to make the transaction validated by master
if self.tmpStore[ob][0] is None:
tuple.append(" ")
else:
tuple.append(self.tmpStore[ob][0])
oid.append(tuple)
# construct list of storages
storage = []
for s in self.txnStorages:
tuple = [s]
storage.append(tuple)
# validate transaction by master
try:
neoclient.endTrans(self.Master_fd, 10, U64(self.serial), oid, storage)
if debug : print 'neoclient : transaction validated!!'
except RuntimeError: # transaction not validated by master, must abort...
print 'RuntTimeError in tpc_vote for master'
raise POSException.ReadConflictError
except SystemError:
print 'SystemError in tpc_vote for master'
raise
return # XXX return nothing otherwise ZODB raise assertion error in check serial
def tpc_finish(self, transaction, f=None):
""" Storage API: finish a transaction. """
if debug : print 'neoclient : tpc_finish'
self.load_lock.acquire()
if self.read_only:
raise POSException.ReadOnlyError()
if self.txn is not transaction:
raise POSException.StorageTransactionError(self, transaction)
try:
if f is not None:
f()
# update cache
self.cache_lock.acquire()
for ob in self.tmpStore:
cache[ob] = (U64(self.serial), self.tmpStore[ob][1]) # put data in cache
self.cache_lock.release()
# invalidate other clients cache
try:
self.checkCache(self.tmpStore)
except:
raise
# reset transaction data
self.txnStorages = []
self.tmpStore = {}
self.serial = None
self.txn_cond.acquire()
self.txn = None
self.txn_cond.notify()
self.txn_cond.release()
if debug : print 'neoclient : transaction ended!, txn = %r' %(self.txn,)
return
finally:
self.load_lock.release()
def tpc_abort(self, transaction):
""" Storage API: abort a transaction. """
if debug :
print 'neoclient : tpc_abort'
if self.read_only:
raise POSException.ReadOnlyError()
if self.txn is not transaction:
raise POSException.StorageTransactionError(self, transaction)
# called because vote failed, so just do undoTrans on storages, master already known failure
for s in self.txnStorages:
try:
conn = self.connectToStorage(s)
list = neoclient.undo(conn, 21, U64(self.serial))
except SystemError:
neoclient.failure(self.Master_fd, 18, s)
except ValueError:
print 'abort : Value Error'
raise
# clear data for transaction
self.txn_cond.acquire()
self.txnStorages = []
self.tmpStore = {}
self.serial = None
self.txn = None
self.txn_cond.notify()
self.txn_cond.release()
# all methods about version, we don't care
def versionEmpty(self, version):
""" Storage API: return whether the version has no transactions. """
if debug : print 'neoclient : version empty'
return 1
def versions(self, max=None):
""" Storage API: return a sequence of versions in the storage. """
if debug : print 'neoclient : versions'
return ()
def abortVersion(self, version, transaction):
""" Storage API: clear any changes made by the given version. """
if debug : print 'neoclient : abortversion'
return ()
def commitVersion(self, source, destination, transaction):
""" Storage API: commit the source version in the destination. """
if debug : print "neoclient : commit Version"
return ()
def modifiedInVersion(self, oid):
""" Storage API: return the version, if any, that modfied an object. """
if debug : print ' neoclient : modified in version'
return ''
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if you have the <arpa/inet.h> header file. */
#undef HAVE_ARPA_INET_H
/* Define to 1 if you have the `bzero' function. */
#undef HAVE_BZERO
/* Define to 1 if you have the `gethostbyname' function. */
#undef HAVE_GETHOSTBYNAME
/* Define to 1 if you have the `inet_ntoa' function. */
#undef HAVE_INET_NTOA
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the `pthread' library (-lpthread). */
#undef HAVE_LIBPTHREAD
/* Define to 1 if you have the `ssl' library (-lssl). */
#undef HAVE_LIBSSL
/* Define to 1 if you have the `uuid' library (-luuid). */
#undef HAVE_LIBUUID
/* Define to 1 if you have the `z' library (-lz). */
#undef HAVE_LIBZ
/* Define to 1 if long double works and has more range or precision than
double. */
#undef HAVE_LONG_DOUBLE
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
to 0 otherwise. */
#undef HAVE_MALLOC
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the `memset' function. */
#undef HAVE_MEMSET
/* Define to 1 if you have the <netdb.h> header file. */
#undef HAVE_NETDB_H
/* Define to 1 if you have the <netinet/in.h> header file. */
#undef HAVE_NETINET_IN_H
/* Define to 1 if you have the `socket' function. */
#undef HAVE_SOCKET
/* Define to 1 if stdbool.h conforms to C99. */
#undef HAVE_STDBOOL_H
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the `stpcpy' function. */
#undef HAVE_STPCPY
/* Define to 1 if you have the `strerror' function. */
#undef HAVE_STRERROR
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the `strtol' function. */
#undef HAVE_STRTOL
/* Define to 1 if you have the <syslog.h> header file. */
#undef HAVE_SYSLOG_H
/* Define to 1 if you have the <sys/socket.h> header file. */
#undef HAVE_SYS_SOCKET_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if the system has the type `_Bool'. */
#undef HAVE__BOOL
/* Name of package */
#undef PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define as the return type of signal handlers (`int' or `void'). */
#undef RETSIGTYPE
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define to 1 if your <sys/time.h> declares `struct tm'. */
#undef TM_IN_SYS_TIME
/* Version number of package */
#undef VERSION
/* Define to rpl_malloc if the replacement function should be used. */
#undef malloc
/* Define to `unsigned' if <sys/types.h> does not define. */
#undef size_t
This source diff could not be displayed because it is too large. You can view the blob instead.
dnl -*- Autoconf -*-
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ(2.5)
AC_INIT([Nexedi Enterprise Objects], [0.1], [aurel@nexedi.com], [NEO])
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([master/master_node.c])
AC_CONFIG_HEADER([config.h])
AC_ARG_WITH([mysql_config],
AS_HELP_STRING([--with-mysql_config=PATH],
[specify mysql_config]),
[MYSQL_CONFIG=="$withval" ]
)
dnl Checks for programs.
AC_PROG_CC
AC_PROG_RANLIB
AC_C_LONG_DOUBLE
AM_MAINTAINER_MODE
dnl Checks for libraries.
AC_CHECK_LIB([pthread], [pthread_mutex_init],,[AC_MSG_ERROR(libpthread not found)])
AC_CHECK_LIB([uuid], [uuid_parse],,[AC_MSG_ERROR(libuuid not found)])
AC_CHECK_LIB([z], [crc32],,[AC_MSG_ERROR(libz not found)])
AC_CHECK_LIB([ssl], [SSL_library_init],,[AC_MSG_ERROR(libssl not found)])
dnl Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS([arpa/inet.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h syslog.h unistd.h])
dnl Checks for typedefs, structures, and compiler characteristics.
AC_HEADER_STDBOOL
AC_TYPE_SIZE_T
AC_STRUCT_TM
dnl Checks for library functions.
AC_FUNC_MALLOC
AC_TYPE_SIGNAL
AC_CHECK_FUNCS([bzero gethostbyname inet_ntoa memset socket stpcpy strerror strtol])
dnl check for python.
if test x = "x$PYTHON"; then
AC_CHECK_PROGS([PYTHON], [python2 python])
if test x = "x$PYTHON"; then
AC_MSG_ERROR([cannot find python])
fi
else
AC_MSG_CHECKING([python])
AC_CHECK_FILE([$PYTHON], , AC_MSG_ERROR([cannot find python]))
AC_MSG_RESULT([$PYTHON])
fi
PYTHON_INCLUDE=`$PYTHON -c "from distutils import sysconfig; print sysconfig.get_python_inc()"`
AC_SUBST(PYTHON_INCLUDE)
PYTHON_OPT=`$PYTHON -c "from distutils import sysconfig; print sysconfig.get_config_var('OPT')"`
AC_SUBST(PYTHON_OPT)
PYTHON_BASECFLAGS=`$PYTHON -c "from distutils import sysconfig; print sysconfig.get_config_var('BASECFLAGS')"`
AC_SUBST(PYTHON_BASECFLAGS)
PYTHON_CCSHARED=`$PYTHON -c "from distutils import sysconfig; print sysconfig.get_config_var('CCSHARED')"`
AC_SUBST(PYTHON_CCSHARED)
PYTHON_LDSHARED=`$PYTHON -c "from distutils import sysconfig; print sysconfig.get_config_var('LDSHARED')"`
AC_SUBST(PYTHON_LDSHARED)
PYTHON_SO=`$PYTHON -c "from distutils import sysconfig; print sysconfig.get_config_var('SO')"`
AC_SUBST(PYTHON_SO)
PYTHON_CC=`$PYTHON -c "from distutils import sysconfig; print sysconfig.get_config_var('CC')"`
AC_SUBST(PYTHON_CC)
dnl check for mysql_config.
if test x = "x$MYSQL_CONFIG"; then
AC_CHECK_PROGS([MYSQL_CONFIG], [mysql_config])
if test x = "x$MYSQL_CONFIG"; then
AC_MSG_ERROR([cannot find mysql_config])
fi
else
AC_MSG_CHECKING([mysql_config])
AC_CHECK_FILE([$MYSQL_CONFIG], , AC_MSG_ERROR([cannot find mysql_config]))
AC_MSG_RESULT([$MYSQL_CONFIG])
fi
MYSQL_LDFLAGS="" # XXX mysql_config does not separate -L.
MYSQL_INCLUDE=`$MYSQL_CONFIG --include`
MYSQL_LIBS=`$MYSQL_CONFIG --libmysqld-libs`
AC_SUBST(MYSQL_LDFLAGS)
AC_SUBST(MYSQL_INCLUDE)
AC_SUBST(MYSQL_LIBS)
AC_CONFIG_FILES([Makefile master/Makefile storage/Makefile
include/Makefile lib/Makefile doc/Makefile
test/Makefile client/Makefile client/NEO/Makefile])
AC_OUTPUT
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
# Copyright 1999, 2000, 2003 Free Software Foundation, Inc.
# 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, 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.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
echo "depcomp: Variables source, object and depmode must be set" 1>&2
exit 1
fi
# `libtool' can also be set to `yes' or `no'.
if test -z "$depfile"; then
base=`echo "$object" | sed -e 's,^.*/,,' -e 's,\.\([^.]*\)$,.P\1,'`
dir=`echo "$object" | sed 's,/.*$,/,'`
if test "$dir" = "$object"; then
dir=
fi
# FIXME: should be _deps on DOS.
depfile="$dir.deps/$base"
fi
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
rm -f "$tmpdepfile"
# Some modes work just like other modes, but use different flags. We
# parameterize here, but still list the modes in the big case below,
# to make depend.m4 easier to write. Note that we *cannot* use a case
# here, because this file can only contain one case statement.
if test "$depmode" = hp; then
# HP compiler uses -M and no extra arg.
gccflag=-M
depmode=gcc
fi
if test "$depmode" = dashXmstdout; then
# This is just like dashmstdout with a different argument.
dashmflag=-xM
depmode=dashmstdout
fi
case "$depmode" in
gcc3)
## gcc 3 implements dependency tracking that does exactly what
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
## it if -MD -MP comes after the -MF stuff. Hmm.
"$@" -MT "$object" -MD -MP -MF "$tmpdepfile"
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
mv "$tmpdepfile" "$depfile"
;;
gcc)
## There are various ways to get dependency output from gcc. Here's
## why we pick this rather obscure method:
## - Don't want to use -MD because we'd like the dependencies to end
## up in a subdir. Having to rename by hand is ugly.
## (We might end up doing this anyway to support other compilers.)
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
## -MM, not -M (despite what the docs say).
## - Using -M directly means running the compiler twice (even worse
## than renaming).
if test -z "$gccflag"; then
gccflag=-MD,
fi
"$@" -Wp,"$gccflag$tmpdepfile"
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
## The second -e expression handles DOS-style file names with drive letters.
sed -e 's/^[^:]*: / /' \
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
## This next piece of magic avoids the `deleted header file' problem.
## The problem is that when a header file which appears in a .P file
## is deleted, the dependency causes make to die (because there is
## typically no way to rebuild the header). We avoid this by adding
## dummy dependencies for each header file. Too bad gcc doesn't do
## this for us directly.
tr ' ' '
' < "$tmpdepfile" |
## Some versions of gcc put a space before the `:'. On the theory
## that the space means something, we add a space to the output as
## well.
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
sgi)
if test "$libtool" = yes; then
"$@" "-Wp,-MDupdate,$tmpdepfile"
else
"$@" -MDupdate "$tmpdepfile"
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
echo "$object : \\" > "$depfile"
# Clip off the initial element (the dependent). Don't try to be
# clever and replace this with sed code, as IRIX sed won't handle
# lines with more than a fixed number of characters (4096 in
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
# the IRIX cc adds comments like `#:fec' to the end of the
# dependency line.
tr ' ' '
' < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
tr '
' ' ' >> $depfile
echo >> $depfile
# The second pass generates a dummy entry for each header file.
tr ' ' '
' < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
>> $depfile
else
# The sourcefile does not contain any dependencies, so just
# store a dummy comment line, to avoid errors with the Makefile
# "include basename.Plo" scheme.
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
aix)
# The C for AIX Compiler uses -M and outputs the dependencies
# in a .u file. In older versions, this file always lives in the
# current directory. Also, the AIX compiler puts `$object:' at the
# start of each line; $object doesn't have directory information.
# Version 6 uses the directory in both cases.
stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'`
tmpdepfile="$stripped.u"
if test "$libtool" = yes; then
"$@" -Wc,-M
else
"$@" -M
fi
stat=$?
if test -f "$tmpdepfile"; then :
else
stripped=`echo "$stripped" | sed 's,^.*/,,'`
tmpdepfile="$stripped.u"
fi
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
if test -f "$tmpdepfile"; then
outname="$stripped.o"
# Each line is of the form `foo.o: dependent.h'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile"
sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile"
else
# The sourcefile does not contain any dependencies, so just
# store a dummy comment line, to avoid errors with the Makefile
# "include basename.Plo" scheme.
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
icc)
# Intel's C compiler understands `-MD -MF file'. However on
# icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
# ICC 7.0 will fill foo.d with something like
# foo.o: sub/foo.c
# foo.o: sub/foo.h
# which is wrong. We want:
# sub/foo.o: sub/foo.c
# sub/foo.o: sub/foo.h
# sub/foo.c:
# sub/foo.h:
# ICC 7.1 will output
# foo.o: sub/foo.c sub/foo.h
# and will wrap long lines using \ :
# foo.o: sub/foo.c ... \
# sub/foo.h ... \
# ...
"$@" -MD -MF "$tmpdepfile"
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each line is of the form `foo.o: dependent.h',
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
tru64)
# The Tru64 compiler uses -MD to generate dependencies as a side
# effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
# dependencies in `foo.d' instead, so we check for that too.
# Subdirectories are respected.
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
test "x$dir" = "x$object" && dir=
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
if test "$libtool" = yes; then
tmpdepfile1="$dir.libs/$base.lo.d"
tmpdepfile2="$dir.libs/$base.d"
"$@" -Wc,-MD
else
tmpdepfile1="$dir$base.o.d"
tmpdepfile2="$dir$base.d"
"$@" -MD
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile1" "$tmpdepfile2"
exit $stat
fi
if test -f "$tmpdepfile1"; then
tmpdepfile="$tmpdepfile1"
else
tmpdepfile="$tmpdepfile2"
fi
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
# That's a tab and a space in the [].
sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
else
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
#nosideeffect)
# This comment above is used by automake to tell side-effect
# dependency tracking mechanisms from slower ones.
dashmstdout)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout, regardless of -o.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test $1 != '--mode=compile'; do
shift
done
shift
fi
# Remove `-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
test -z "$dashmflag" && dashmflag=-M
# Require at least two characters before searching for `:'
# in the target name. This is to cope with DOS-style filenames:
# a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
"$@" $dashmflag |
sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
tr ' ' '
' < "$tmpdepfile" | \
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
dashXmstdout)
# This case only exists to satisfy depend.m4. It is never actually
# run, as this mode is specially recognized in the preamble.
exit 1
;;
makedepend)
"$@" || exit $?
# Remove any Libtool call
if test "$libtool" = yes; then
while test $1 != '--mode=compile'; do
shift
done
shift
fi
# X makedepend
shift
cleared=no
for arg in "$@"; do
case $cleared in
no)
set ""; shift
cleared=yes ;;
esac
case "$arg" in
-D*|-I*)
set fnord "$@" "$arg"; shift ;;
# Strip any option that makedepend may not understand. Remove
# the object too, otherwise makedepend will parse it as a source file.
-*|$object)
;;
*)
set fnord "$@" "$arg"; shift ;;
esac
done
obj_suffix="`echo $object | sed 's/^.*\././'`"
touch "$tmpdepfile"
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
sed '1,2d' "$tmpdepfile" | tr ' ' '
' | \
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile" "$tmpdepfile".bak
;;
cpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test $1 != '--mode=compile'; do
shift
done
shift
fi
# Remove `-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
"$@" -E |
sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
sed '$ s: \\$::' > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
cat < "$tmpdepfile" >> "$depfile"
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvisualcpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout, regardless of -o,
# because we must use -o when running libtool.
"$@" || exit $?
IFS=" "
for arg
do
case "$arg" in
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
set fnord "$@"
shift
shift
;;
*)
set fnord "$@" "$arg"
shift
shift
;;
esac
done
"$@" -E |
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
. "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
echo " " >> "$depfile"
. "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile"
rm -f "$tmpdepfile"
;;
none)
exec "$@"
;;
*)
echo "Unknown depmode $depmode" 1>&2
exit 1
;;
esac
exit 0
EXTRA_DIST = protocol.txt
# Makefile.in generated by automake 1.7.9 from Makefile.am.
# @configure_input@
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
# Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
ACLOCAL = @ACLOCAL@
AMDEP_FALSE = @AMDEP_FALSE@
AMDEP_TRUE = @AMDEP_TRUE@
AMTAR = @AMTAR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
MAKEINFO = @MAKEINFO@
MYSQL_CONFIG = @MYSQL_CONFIG@
MYSQL_INCLUDE = @MYSQL_INCLUDE@
MYSQL_LDFLAGS = @MYSQL_LDFLAGS@
MYSQL_LIBS = @MYSQL_LIBS@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PYTHON = @PYTHON@
PYTHON_BASECFLAGS = @PYTHON_BASECFLAGS@
PYTHON_CC = @PYTHON_CC@
PYTHON_CCSHARED = @PYTHON_CCSHARED@
PYTHON_INCLUDE = @PYTHON_INCLUDE@
PYTHON_LDSHARED = @PYTHON_LDSHARED@
PYTHON_OPT = @PYTHON_OPT@
PYTHON_SO = @PYTHON_SO@
RANLIB = @RANLIB@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
ac_ct_CC = @ac_ct_CC@
ac_ct_RANLIB = @ac_ct_RANLIB@
ac_ct_STRIP = @ac_ct_STRIP@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
bindir = @bindir@
build_alias = @build_alias@
datadir = @datadir@
exec_prefix = @exec_prefix@
host_alias = @host_alias@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localstatedir = @localstatedir@
mandir = @mandir@
oldincludedir = @oldincludedir@
prefix = @prefix@
program_transform_name = @program_transform_name@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
EXTRA_DIST = protocol.txt
subdir = doc
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
DIST_SOURCES =
DIST_COMMON = $(srcdir)/Makefile.in Makefile.am
all: all-am
.SUFFIXES:
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4)
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu doc/Makefile
Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
uninstall-info-am:
tags: TAGS
TAGS:
ctags: CTAGS
CTAGS:
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
top_distdir = ..
distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
list='$(DISTFILES)'; for file in $$list; do \
case $$file in \
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
esac; \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkinstalldirs) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic mostlyclean-am
distclean: distclean-am
-rm -f Makefile
distclean-am: clean-am distclean-generic
dvi: dvi-am
dvi-am:
info: info-am
info-am:
install-data-am:
install-exec-am:
install-info: install-info-am
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-generic
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-info-am
.PHONY: all all-am check check-am clean clean-generic distclean \
distclean-generic distdir dvi dvi-am info info-am install \
install-am install-data install-data-am install-exec \
install-exec-am install-info install-info-am install-man \
install-strip installcheck installcheck-am installdirs \
maintainer-clean maintainer-clean-generic mostlyclean \
mostlyclean-generic pdf pdf-am ps ps-am uninstall uninstall-am \
uninstall-info-am
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
Second prototype protocol and components
Here we choose to store all a transaction in the same Storage Node
(SN) to reduce the number of message sent. So the Master Node (MN)
must deal with this data structure :
list of object -- oid -> serial, list of SN id
list of transaction -- tid -> list of SN id
list of SN -- SN_id -> ipv4 address, port, status (status : u =
"unrelieable", r = "reliable")
list of Client Node (CN) -- CN_id -> ipv4 address, port
The list of SN and the list of CN with information are stored on disk because
they are only requested by few operations.
The CN cache must manage data about object. For each object it should
store oid(as key), status (v = 'valid', i = 'invalidate'), serial and data.
Before each request to master it must check in cache before to see of object is
existing in it and if it is valid before doing a transaction or a load.
The CN must map a list of SN. This mapped list is :
storage node id -> ipv4 address, port. Then when MN answers CN, it send back
only the SN id. If the client have'nt got the SN id mapping, it requests
information to MN with getSNInfo() method and map them for next use.
CN and SN address which are stored are ipv4 address.
Protocol overview
Start
At MN start, it generates its UUID or use the one stored on disk if it
have one and then wait for connection from SN and CN.
At a CN start, the CN generates an id and send the id to MN, the MN answers
information wich contains Name, supportsVersion, supportsUndo,
supportsTransactionalUndo, ReadOnly and ExtensionsMethod. the CN store this
information in
its cache.
At SN start, if it's the first start, the SN generates a UUID and send it to
MN to identify itself. The MN then asnwers with its own UUID and map the storage
information (UUID, ipv4 address and port). If it isn't the first time,the SN
have ever an UUID stored on disk, so it identify with this UUID to MN and then
MN send it information in order to make it synchronize its data with other SN.
When data are synchronized, SN send message to MN to tell it is ready to work.
The best way to start the system is to start MN first, then SN and then CN.
In order to provide other start order, if the MN is running, it should reply
with 'temporary failure' message to CN if there's none or not enought SN
running. If MN is not running, the CN or SN must try to connect again and again
until a MN is running.
Running
Methods like getSerial(), lastTransaction() and new_oid() only request
the MN. Serial and lastTransaction are read straight from cache. The
oid is generated by the MN to avoid duplicated ids.
For transactions, as ZODB manage transactions, there's only an abort if all
SN failed. So we can send all data and do all the transaction at the same time.
At tpc_begin(), CN get a new transaction id and list of SN id from MN. If
the client doesn't know the SN id, it get information (address and port) about
SN from MN.
At store() CN store objects in a temporary buffer and at tpc_vote() CN send
all data to SNs in a whole packet and it return transaction id, then CN send
data to MN for updating index and check the sanity of transaction (see furthe
r for explaination) and then confirm to zodb.
At tpc_finish() the CN send checkCache() message with the list of oid to make
invalidate objects in other clients'cache. The client list once it has been
requested is stored in cache by CN for future (we suppose list of CN constant
most of the time), if an new CN is added or deleted, the master send message to
all CN to update their list.
If all SNs fail, then CN abort transaction but if not all SNs fail, CN go on
the transaction and finish it normally and just notify the SN which failed to
MN.
UndoInfo() methods, same as undoLog() which is deprecated, request
informations about a given range of transactions, this informations are
stored on CN. So CN request the MN, the list of transation and their SNs,
then it ask SNs to give informations.
Undo() methods is deprecated, instead zodb use undoTransaction()
wich undo transaction in context of a transaction. This request MN to
give SNs for the given transaction, then CN undone transaction
on SNs and send cacheVerif message to all other clients.
For history() methods, informations requested are timestamp from
serial, user_name, description, serial, information and size. This
informations are stored on SNs and are requested for a given number of
entries. So CN ask MN the SNs for the number of serial for the object,
then CN ask SNs for informations
For load() and loadSerial(), CN ask MN the SNs for the given oid
(and serial), and then ask data to SNs.
And getSize() method need all SNs, so CN request list of all SNs to
MN and ask size to each SNs.
For all operations, if there's a failure in a SN, the CN must notify
failure to MN and go on with another SN if possible. Then MN must
check the SN and mark it as Unreliable.
If a CN is deconnected or a new CN is connected, the MN notify to all other
CN the new list of CN in asynchrone methods. We use he same way for the SN.
Transaction conflict
As we don't use version, the transaction id and the serial number of each
object in transaction are the same at the end of a transaction. In order to
resolve conflict, when CN commit a transaction (endTransaction) on MN, we
send the old serial number of each object whith their oid, MN checck it and if
the serial is not the same as the last serial store for this object, it means
that transaction has been done with old version of object, so transaction are
not sane. Then we send back an error messageto CN wich must undo transaction and
reply an exception to ZODB. This must be done when tpc_vote is called by ZODB
and not when tpc_finish is called because ZODB doens'nt care of tpc_finish
return. So the tpc_finish is only use to send the checkCache message to other
CN.
Shutdown
When a CN shutdown, there's nothing to do on the CN, we just send
deconnection message with client id to MN which remove client from its list and
send message to all other CN to make them remove CN from their list.
When a SN shutdown, it's waiting for all transactions on itself to be
finished, then send deconnection message to MN which mark the SN as unreliable
but still store it in its list for future restart.
If MN have to shutdown and we have no replicated MN, it send message to all
SN and CN to make them terminate their process, wait until they answer that
they have finished and then MN shutdown. If there's a replicated MN, we send
id, address and port of replicated MN and wait for all CN and SN to reply
they have finish their work.
List of methods
Methods called by CN on MN
getObjectByOid(oid) -- return SNs and serial for the given object
getObjectBySerial(oid, serial) -- return SNs for the given object with the serial
getSerial(oid) -- return serial number for the given oid
getLastTransaction() -- return last transaction id
getOid(n) -- return n new oids
clientStart(id) -- return list of informations : Name, supportsVersion,
supportsUndo,supportsTransactionalUndo and ExtensionsMethod
getTransSN(first, last) -- return list of transaction between first and last with their SNs
getObjectHist(oid, length) -- return list of serial for the oid with their SNs.
undoTrans(tid) -- mark transaction as undone and return SNs for the given transaction
beginTrans() -- return tid and SNs
endTrans(tid, oid1, oid2...) -- update cache and return confirmation
getAllSN() -- return list of all SN
getAllCN() -- return list of all CN
failure(SN) -- mark SN as unreliable
getSNInfo(SNid) -- return ip address and port for the given storage's id.
clientClose() -- close connection to MN
Method called by CN on CN
checkCache(oid1, oid2...) -- verif cache on client
Methods called by CN on SN
transaction(tid,txn.user, txn.desc, txn.ext, object1, object2...) -- store data in DB and return confirm or failure
undo(tid) -- undone the given transaction and return list of oid
histInfo(oid, serial) -- return history informations for the given object
undoInfo(tid) -- return informations for the given transaction
load(oid, serial) -- return data for the given oid and serial (use both by load() and loadSerial())
getSize() -- return size of storage file system
Methods called by SN on MN
storageClose(id) -- send deconnection message to MN
storageStart(id) -- send id to MN
storageReady(id) -- tell MN that SN is ready
Methods called by MN on SN and CN
masterClose() -- ask all CN and all SN to finish their process, wait for
response and then shutdown
masterChange(MNdata) --send information to all SN and all CN for making them
changing their MN
Methods called by MN on CN
addSN(id, addr, port) -- send information for new SN (id, ipv4 address, port)
addCN(id, addr, port) -- send information for new CN (id, ipv4 address, port)
delSN(id) -- tell CN to del SN from its list
delCN(id) -- tell CN to del CN from its list
Methods id definition
getObjectByOid 1
getObjectBySerial 2
getSerial 3
getLastTransaction 4
getOid 5
getTransSN 6
getObjectHist 7
undoTrans 8
beginTrans 9
endTrans 10
getAllSN 11
getAllCN 12
addSN 13
addCN 14
delSN 15
delCN 16
getSNInfo 17
failure 18
checkCache 19
transaction 20
undo 21
histInfo 22
undoInfo 23
load 24
getSize 25
clientClose 26
storageClose 27
masterClose 28
storageStart 29
storageReady 30
clientStart 31
masterChange 32
unreliableStorage 33
If the 15th bit of ID is set, it means a return message. If not, it means a
request message.
Return code definition
0 success
1 temporary failure (wait for SN to be ready, or MN is going to shutdown)
2 oid not found
3 serial not found
4 tid/transaction not found
5 abort transaction (SN cannot commit the transaction)
6 transaction not valid (send by MN at endTransaction if transaction not
sane)
Protocol for connection layer :
All integer are in network byte order.
Header for each request message :
2 byte unsigned integer -- method id
2 byte array of character -- flags (for future use)
4 byte unsigned integer -- message data length
Header for each return message :
2 byte unsigned integer -- method id
2 byte character -- flags (for future use)
4 byte unsigned integer -- message data length
2 byte unsigned integer -- return code
if return code = 0 : succes
if return code != 0 : failure, each failure have it's own return code (to be defined)
When there is a failure, message format for data is :
4 byte unsigned integer -- error message length
? byte array of character -- error message
Methods details
All method beginning with 'return' are the answer from request
getObjectByOid(oid)
8 byte unsigned integer -- object oid
returnGetObjectByOid()
8 byte unsigned integer -- object serial
4 byte unsigned integer -- number of storage nodes
UUID_LEN byte array of character -- first storage id
UUID_LEN byte array of character -- second storage id
...
getObjectBySerial(oid, serial)
8 byte unsigned integer -- object oid
8 byte unsigned integer -- object serial
returngetObjectBySerial()
4 byte unsigned integer -- number of storage nodes
UUID_LEN byte array of character -- first storage id
UUID_LEN byte array of character -- second storage id
...
getSerial(oid)
8 byte unsigned integer -- object oid
returnGetSerial() :
8 byte unsigned integer -- object serial number
getLastTransaction()
nothing
returnGetLastTransaction()
8 byte unsigned integer -- transaction tid
getOid(n)
2 byte unsigned integer -- number of new oid wanted : n
returnGetOid()
2 byte unsigned integer -- number of oid
8 byte array of 8 integer -- first oid
8 byte array of 8 integer -- second oid
...
clientStart()
UUID_LEN byte array of character -- client id
IP_LEN byte array of character -- client ip
2 byte unsigned integer -- client server port
returnClientStart()
2 byte unsigned integer -- name length
? byte array of character -- name
2 byte unsigned integer -- supportVersion
2 byte unsigned integer -- supportUndo
2 byte unsigned integer -- supportTransUndo
2 byte unsigned integer -- readOnly
2 byte unsigned integer -- extension length
? byte array of character -- extension
getTransSN(first, last)
2 byte unsigned integer -- first transaction position
2 byte unsigned integer -- last transaction position
returnGetTransSN()
2 byte unsigned integer -- number of transactions
8 byte unsigned integer -- transaction tid
4 byte unsigned integer -- number of storage nodes
UUID_LEN byte array of character -- first storage id
UUID_LEN byte array of character -- second storage id
...
8 byte unsigned integer -- second transaction tid
4 byte unsigned integer -- number of storage nodes
UUID_LEN byte array of character -- first storage id
UUID_LEN byte array of character -- second storage id
getObjectHist(oid, length)
8 byte unsigned integer -- object oid
2 byte unsigned integer -- length of history
returnGetObjectHist()
2 byte unsigned integer -- number of serial record
8 byte unsigned integer -- serial
4 byte unsigned integer -- number of storage nodes
UUID_LEN byte array of character -- first storage id
UUID_LEN byte array of character -- second storage id
...
8 byte unsigned integer -- second serial
4 byte unsigned integer -- number of storage nodes
UUID_LEN byte array of character -- first storage id
UUID_LEN byte array of character -- second storage id
...
undoTrans(tid)
8 byte unsigned integer -- transaction tid
returnUndoTrans()
4 byte unsigned integer -- number of storage nodes
UUID_LEN byte array of character -- first storage id
UUID_LEN byte array of character -- second storage id
...
beginTrans(tid)
8 byte unsigned integer -- transaction tid
returnBeginTrans()
8 byte array of 8 integer -- transaction tid
4 byte unsigned integer -- number of storage nodes
UUID_LEN byte array of character -- first storage id
UUID_LEN byte array of character -- second storage id
...
endTrans(tid, oid1, serial1, oid2, serial2,...)
8 byte unsigned integer -- transaction tid
4 byte unsigned integer -- number of storages
UUID_LEN byte array of character -- first storage id
UUID_LEN byte array of character -- second storage id
...
4 byte unsigned integer -- number of oid
8 byte unsigned integer -- first object oid
8 byte unsigned integer -- first object old serial
8 byte unsigned integer -- second object oid
8 byte unsigned integer -- second object old serial
...
returnEndTrans()
only message with either succes code or error code
getAllSN()
nothing
returnGetAllSN()
4 byte unsigned integer -- number of storage nodes
UUID_LEN byte array of character -- first storage id
IP_LEN byte array of character -- first storage ip
2 byte unsigned integer -- first storage port
UUID_LEN byte array of character -- second storage id
...
getAllCN()
nothing
returnGetAllCN()
4 byte unsigned integer -- number of client
UUID_LEN byte array of character -- first client id
IP_LEN byte array of character -- first client address
2 byte unsigned integer -- first client port
UUID_LEN byte array of character -- second client id
IP_LEN byte array of character -- second client address
2 byte unsgined integer -- second client port
...
failure(SN)
UUID_LEN byte array of character -- storage id
checkCache(oid1, serial1, oid2, serial2, ...)
8 byte unsigned integer -- serial number
4 byte unsigned integer -- number of oid
8 byte unsigned integer -- first oid
8 byte unsigned integer -- second oid
...
transaction(tid,txn.user, txn.desc, txn.ext, object1, object2...)
8 byte unsinged integer -- transaction tid
2 byte unsigned integer -- txn.user length
2 byte unsigned integer -- txn.desc length
2 byte unsigned integer -- txn.ext length
? byte array of character -- txn.user
? byte array of character -- txn.desc
? byte array of character -- txn.ext
4 byte unsigned integer -- number of objects in transaction
8 byte unsigned integer -- first object id
8 byte unsigned integer -- first object serial
8 byte unsigned integer -- first object data length
? byte array of character -- first object data
8 byte unsigned integer -- second object id
8 byte unsigned integer -- second object serial
8 byte unsigned integer -- second object data length
? byte array of character -- second object data
...
returnTransaction()
only check with the return code
undo(tid)
8 byte unsigned integer -- transaction tid
returnUndo()
4 byte unsigned integer -- number of oid
8 byte unsigned integer -- first oid
8 byte unsigned integer -- second oid
...
histInfo(oid, serial)
8 byte unsigned integer -- object oid
8 byte unsigned integer -- object serial
returnHistInfo()
2 byte unsigned integer -- time length
? byte array of character -- time
2 byte unsigned integer -- user length
? byte array of character -- user
2 byte unsigned integer -- desc length
? byte array of character -- desc
8 byte unsigned integer -- serial
8 byte unsigned integer -- object size
undoInfo(tid)
8 byte array of character -- transaction tid
returnUndoInfo()
2 byte unsigned integer -- time length
? byte array of character -- time
2 byte unsigned integer -- user length
? byte array of character -- user
2 byte unsigned integer -- desc length
? byte array of character -- desc
2 byte unsigned integer -- id length
? byte array of character -- id
load(oid, serial)
8 byte unsigned integer -- object oid
8 byte unsigned integer -- object serial
returnLoad() :
8 byte unsigned integer -- data length
? byte array of character -- data
getSize()
nothing
returnGetSize()
8 byte unsigned integer -- size of storage data
storageStart()
UUID_LEN byte array of character -- storage id
IP_LEN byte array of character -- storage ip
2 byte unsigned integer -- port
returnStorageStart()
UUID_LEN byte array of character -- master id
2 byte unsigned integer -- status
storageReady()
UUID_LEN byte array of character -- storage id
8 byte unsigned integer -- number of transaction
8 byte unsigned integer -- first transaction id
8 byte unsigned integer -- second transaction id
...
8 byte unsigned integer -- number of pair object-serial
8 byte array of character -- first object oid
8 byte array of character -- first object serial
8 byte array of character -- second object oid
8 byte array of character -- second object serial
...
masterClose()
UUID_LEN byte array of character -- master id
returnMasterClose()
UUID_LEN byte array of character -- node id
masterChange()
UUID_LEN byte array of character -- replicated master id
IP_LEN byte array of character -- replicated master address
2 byte unsigned integer-- replicated master port
returnMasterChange()
UUID_LEN byte array of character -- storage id
clientClose(id)
UUID_LEN byte array of character -- client id
storageClose(id)
UUID_LEN byte array of character -- storage id
getSNInfo(id)
2 byte unsigned integer -- length of storage id
? byte array of character -- storage id
returnGetSNInfo()
2 byte unsigned integer -- length of storage id
? byte array of character -- storage id
2 byte unsigned integer -- length of storage address
? byte array of character -- storage address
2 byte unsigned integer -- storage port
addSN(id, address, port)
UUID_LEN byte array of character -- storage id
IP_LEN byte array of character -- storage address
2 byte unsigned integer -- storage port
addCN(id, address, port)
UUID_LEN byte array of character -- client id
IP_LEN byte array of character -- client address
2 byte unsigned integer -- client port
delSN(id)
UUID_LEN byte array of character -- storage id
delCN(id)
UUID_LEN byte array of character -- client id
\ No newline at end of file
noinst_HEADERS = neo_mysql.h neo_socket.h neo_struct.h timestamp.h
# Makefile.in generated by automake 1.7.9 from Makefile.am.
# @configure_input@
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
# Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
ACLOCAL = @ACLOCAL@
AMDEP_FALSE = @AMDEP_FALSE@
AMDEP_TRUE = @AMDEP_TRUE@
AMTAR = @AMTAR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
MAKEINFO = @MAKEINFO@
MYSQL_CONFIG = @MYSQL_CONFIG@
MYSQL_INCLUDE = @MYSQL_INCLUDE@
MYSQL_LDFLAGS = @MYSQL_LDFLAGS@
MYSQL_LIBS = @MYSQL_LIBS@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PYTHON = @PYTHON@
PYTHON_BASECFLAGS = @PYTHON_BASECFLAGS@
PYTHON_CC = @PYTHON_CC@
PYTHON_CCSHARED = @PYTHON_CCSHARED@
PYTHON_INCLUDE = @PYTHON_INCLUDE@
PYTHON_LDSHARED = @PYTHON_LDSHARED@
PYTHON_OPT = @PYTHON_OPT@
PYTHON_SO = @PYTHON_SO@
RANLIB = @RANLIB@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
ac_ct_CC = @ac_ct_CC@
ac_ct_RANLIB = @ac_ct_RANLIB@
ac_ct_STRIP = @ac_ct_STRIP@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
bindir = @bindir@
build_alias = @build_alias@
datadir = @datadir@
exec_prefix = @exec_prefix@
host_alias = @host_alias@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localstatedir = @localstatedir@
mandir = @mandir@
oldincludedir = @oldincludedir@
prefix = @prefix@
program_transform_name = @program_transform_name@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
noinst_HEADERS = neo_mysql.h neo_socket.h neo_struct.h timestamp.h
subdir = include
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
DIST_SOURCES =
HEADERS = $(noinst_HEADERS)
DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.in Makefile.am
all: all-am
.SUFFIXES:
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4)
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu include/Makefile
Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
uninstall-info-am:
ETAGS = etags
ETAGSFLAGS =
CTAGS = ctags
CTAGSFLAGS =
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
mkid -fID $$unique
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)$$tags$$unique" \
|| $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$tags $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& cd $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) $$here
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
top_distdir = ..
distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
list='$(DISTFILES)'; for file in $$list; do \
case $$file in \
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
esac; \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkinstalldirs) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(HEADERS)
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic mostlyclean-am
distclean: distclean-am
-rm -f Makefile
distclean-am: clean-am distclean-generic distclean-tags
dvi: dvi-am
dvi-am:
info: info-am
info-am:
install-data-am:
install-exec-am:
install-info: install-info-am
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-generic
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-info-am
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic ctags \
distclean distclean-generic distclean-tags distdir dvi dvi-am \
info info-am install install-am install-data install-data-am \
install-exec install-exec-am install-info install-info-am \
install-man install-strip installcheck installcheck-am \
installdirs maintainer-clean maintainer-clean-generic \
mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \
uninstall uninstall-am uninstall-info-am
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
#ifndef neo_mysql_h
#define neo_mysql_h
#include <mysql/mysql.h>
#include "neo_struct.h"
struct database;
struct database_mysql
{
MYSQL *sql;
};
/* common functions */
int database_close (struct database *orig_db);
int database_thread_init (void);
void database_thread_end (void);
/* storage functions */
struct database *database_storage_open (int create);
int database_storage_get_object (struct database *orig_db, u_int64_t oid,
u_int64_t serial, void **object,
int32_t * crc);
int database_storage_get_trans_info (struct database *orig_db,
u_int64_t tid, struct undoInfo *info);
int database_storage_get_object_info (struct database *orig_db,
u_int64_t oid, u_int64_t serial,
struct hist *hist);
int database_storage_get_object_list (struct database *orig_db,
u_int64_t tid,
u_int64_t ** list, u_int32_t * nb_oid);
int database_storage_del_trans (struct database *orig_db, u_int64_t tid);
int database_storage_put_object (struct database *orig_db, u_int64_t oid,
u_int64_t serial, u_int64_t tid,
void *object, u_int32_t size, int32_t crc);
int database_storage_put_trans (struct database *orig_db, u_int64_t tid,
char *user, char *desc, char *ext);
int database_storage_get_index_list (struct database *orig_db,
struct stringList **oidl,
struct stringList **tidl);
int database_storage_get_trans_data (struct database *orig_db,
u_int64_t tid, char **user,
char **desc, char **ext,
struct objectList **list);
int database_storage_store_trans (struct database *orig_db, u_int64_t tid,
char *user, char *desc, char *ext);
int database_storage_trans_exist (struct database *orig_db, u_int64_t tid,
int *exist);
/* master functions */
struct database *database_master_open (int create);
int database_master_get_object_by_oid (struct database *orig_db,
u_int64_t oid, u_int64_t * serial,
struct stringList **list);
int database_master_get_object_by_serial (struct database *orig_db,
u_int64_t oid,
u_int64_t serial,
struct stringList **list);
int database_master_get_serial (struct database *orig_db, u_int64_t oid,
u_int64_t * serial);
int database_master_get_object_hist (struct database *orig_db,
u_int64_t oid, u_int16_t length,
struct tlist **list);
int database_master_undo_trans (struct database *orig_db, u_int64_t tid,
struct stringList **list);
int database_master_begin_trans (struct database *orig_db, u_int64_t tid,
u_int64_t ltid, struct stringList list);
int database_master_end_trans (struct database *orig_db, u_int64_t tid);
int database_master_remove_client (struct database *orig_db,
u_int16_t conn);
int database_master_delete_client (struct database *orig_db,
char id[UUID_LEN]);
int database_master_close_storage (struct database *orig_db,
char id[UUID_LEN]);
int database_master_storage_starting (struct database *orig_db,
char id[UUID_LEN], char ip[IP_LEN],
u_int16_t port, u_int16_t * status);
int database_master_get_storage_infos (struct database *orig_db,
char id[UUID_LEN], char **ip,
u_int16_t * port);
int database_master_start_client (struct database *orig_db, char id[UUID_LEN],
char ip[IP_LEN], u_int16_t port, u_int16_t conn);
int database_master_get_all_storages_infos (struct database *orig_db,
struct nlist **list);
int database_master_get_all_clients_infos (struct database *orig_db,
struct nlist **list);
int database_master_storage_ready (struct database *orig_db,
char id[UUID_LEN]);
int database_master_get_trans_storages (struct database *orig_db,
u_int64_t tid, int16_t first,
int16_t last, struct tlist **list);
int database_master_put_object (struct database *orig_db, u_int64_t tid,
u_int64_t oid, u_int64_t serial);
int database_master_delete_object (struct database *orig_db, u_int64_t oid,
u_int64_t serial);
int database_master_get_trans_list (struct database *orig_db,
char storage_id[UUID_LEN],
struct tlist **list);
int database_master_unreliable_storage (struct database *orig_db,
char id[UUID_LEN]);
int database_master_get_storage_index (struct database *orig_db,
char id[UUID_LEN],
struct transactionList **txn,
u_int64_t * nb_txn);
int database_master_create_storage_index (struct database *orig_db,
struct stringList **index);
int database_master_get_storages_for_trans (struct database *orig_db,
u_int64_t tid,
char storage_id[UUID_LEN],
struct stringList **list);
int database_storage_check_sanity (struct database *orig_db, u_int64_t tid,
u_int64_t oid);
int database_storage_get_db_size (struct database *orig_db, u_int64_t *size);
int database_master_all_objects_accessible(struct database *orig_db);
#endif
#ifndef neo_socket_h
#define neo_socket_h
#include "neo_struct.h"
int send_all (int conn, char *buf, size_t len);
int fill_buffer (int conn, char *buf, u_int32_t * len, u_int32_t max);
int wait_packet (int conn, char *buf, u_int32_t * len, u_int32_t max);
int connectTo (char ip[IP_LEN], u_int16_t port);
unsigned long long htonll (unsigned long long n);
unsigned long long ntohll (unsigned long long n);
int getIp (int ds, char **ip);
#endif
#ifndef neo_struct_h
#define neo_struct_h
/* define some constant */
#define ID_LEN 8
#define UUID_LEN 36
#define IP_LEN 15
#define HEADER_LEN 8 /* 2 byte : id, 2 byte : flag, 4 byte : data_len */
#define RHEADER_LEN 10 /* idem + 2 byte : return code */
#define BUF_SIZE 1024
#define flags " "
#define NDEBUG 0
#define MASTER_PORT 10823
#define FLAG_LEN 2
#define INT16_LEN 2
#define INT32_LEN 4
#define INT64_LEN 8
/* list of error */
enum error
{
TMP_FAILURE = 1,
OID_NOT_FOUND,
SERIAL_NOT_FOUND,
TRANS_NOT_FOUND,
ABORT_TRANS,
TRANS_NOT_VALID,
CONNECTION_FAILURE,
METHOD_ERROR,
NOT_READY,
};
/* list of function call */
enum functions
{
GET_OBJECT_BY_OID = 1,
GET_OBJECT_BY_SERIAL,
GET_SERIAL,
GET_LAST_TRANS,
GET_OID,
GET_TRANS_SN,
GET_OBJECT_HIST,
UNDO_TRANS,
BEGIN_TRANS,
END_TRANS, /* 10 */
GET_ALL_SN,
GET_ALL_CN,
ADD_SN,
ADD_CN,
DEL_SN,
DEL_CN,
GET_SN_INFO,
FAILURE,
CHECK_CACHE,
TRANSACTION, /* 20 */
UNDO,
HIST_INFO,
UNDO_INFO,
LOAD,
GET_SIZE,
CLIENT_CLOSE,
STORAGE_CLOSE,
MASTER_CLOSE,
STORAGE_START,
STORAGE_READY, /* 30 */
CLIENT_START,
MASTER_CHANGE,
UNRELIABLE_STORAGE,
SANITY_CHECK,
GET_TRANS_DATA,
STORAGE_INDEX,
GET_STORAGE_FOR_TRANS,
SEARCH_MASTER,
};
/* generic object for oid, storage and client */
struct cobject
{
char *data;
};
/* generic list for oid , storage and lcient list*/
struct list
{
u_int16_t len;
u_int32_t last;
struct cobject *objects;
};
/* structure for transaction */
struct trans
{
u_int64_t tid;
struct list list;
};
/* transaction, serial list */
struct tlist
{
u_int16_t len;
u_int32_t last;
struct trans *objects;
};
struct hist
{
float time;
char *user;
char *desc;
u_int64_t serial;
u_int64_t size;
};
struct undoInfo
{
float time;
char *user;
char *desc;
u_int64_t id;
};
struct storageInfo
{
u_int16_t supportVersion;
u_int16_t supportUndo;
u_int16_t supportTransUndo;
u_int16_t readOnly;
char *name;
char *ext;
};
struct node
{
char *id;
char *addr;
u_int16_t port;
};
/* node list */
struct nlist
{
u_int16_t len;
u_int32_t last;
struct node *objects;
};
/* structure for storage index in master node */
struct index
{
int len;
int last;
int id_size;
char *id;
};
struct oidList
{
int len;
int last;
int *list;
};
int oidList_New (struct oidList *o, int list_size);
int oidList_Append (struct oidList *o, int oid[8]);
int oidList_GetItem (struct oidList *o, int oid[8], int pos);
int oidList_Free (struct oidList *o);
int init_tlist (struct tlist *pl, u_int16_t size);
int add_trans (struct tlist **pl, u_int64_t tid, u_int16_t nb_s);
int free_tlist (struct tlist *pl);
int init_list (struct list *pl, u_int16_t size);
int add_cobject (struct list *pl, char *cdata, char *sdata);
int free_list (struct list *pl);
int init_nlist (struct nlist *pl, u_int16_t size);
int add_node (struct nlist *pl, char *id, char *addr, u_int16_t port);
int free_nlist (struct nlist *pl);
int init_index (struct index *i, u_int16_t id_size);
int index_add (struct index *i, char *id);
int index_get (struct index *i, char **id, int pos);
struct stringList
{
u_int32_t len;
u_int32_t last;
u_int32_t item_size;
char *list;
};
int stringList_New (struct stringList *o, u_int32_t list_size,
u_int32_t item_size);
int stringList_Append (struct stringList *o, char *item);
int stringList_GetItem (struct stringList *o, char **item, u_int32_t pos);
int stringList_Free (struct stringList *o);
struct object
{
u_int64_t oid;
u_int64_t serial;
char *data;
};
struct objectList
{
u_int32_t len;
u_int32_t last;
struct object *list;
};
struct transaction
{
u_int64_t tid;
struct objectList objects;
};
struct transactionList
{
u_int32_t len;
u_int32_t last;
struct transaction *txn;
};
int objectList_New (struct objectList *o, u_int32_t list_size);
int objectList_Append (struct objectList *o, u_int64_t oid,
u_int64_t serial, char *data);
int objectList_GetItem (struct objectList *o, u_int64_t * oid,
u_int64_t serial, char **data);
int objectList_Free (struct objectList *o);
/* int transaction_New (struct transaction *t, u_int64_t tid, u_int32_t nb_objects); */
/* int transaction_AppendObject (struct transaction *t, u_int64_t oid, u_int64_t serial); */
/* int transaction_Free (struct transaction *t); */
int transactionList_New (struct transactionList *t, u_int32_t nb_txn);
int transactionList_Append (struct transactionList *t, u_int64_t tid,
struct objectList object);
int transactionList_Free (struct transactionList *t);
#endif
#ifndef timestamp_h
#define timestamp_h
int generate_tid (u_int16_t ntid[ID_LEN], u_int16_t ltid[ID_LEN]);
#endif
#!/bin/sh
#
# install - install a program, script, or datafile
#
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
#
# Copyright (C) 1994 X Consortium
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of the X Consortium shall not
# be used in advertising or otherwise to promote the sale, use or other deal-
# ings in this Software without prior written authorization from the X Consor-
# tium.
#
#
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch. It can only install one file at a time, a restriction
# shared with many OS's install programs.
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
# put in absolute paths if you don't have them in your path; or use env. vars.
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"
transformbasename=""
transform_arg=""
instcmd="$mvprog"
chmodcmd="$chmodprog 0755"
chowncmd=""
chgrpcmd=""
stripcmd=""
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=""
dst=""
dir_arg=""
while [ x"$1" != x ]; do
case $1 in
-c) instcmd=$cpprog
shift
continue;;
-d) dir_arg=true
shift
continue;;
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
-s) stripcmd=$stripprog
shift
continue;;
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
shift
continue;;
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
shift
continue;;
*) if [ x"$src" = x ]
then
src=$1
else
# this colon is to work around a 386BSD /bin/sh bug
:
dst=$1
fi
shift
continue;;
esac
done
if [ x"$src" = x ]
then
echo "$0: no input file specified" >&2
exit 1
else
:
fi
if [ x"$dir_arg" != x ]; then
dst=$src
src=""
if [ -d "$dst" ]; then
instcmd=:
chmodcmd=""
else
instcmd=$mkdirprog
fi
else
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if [ -f "$src" ] || [ -d "$src" ]
then
:
else
echo "$0: $src does not exist" >&2
exit 1
fi
if [ x"$dst" = x ]
then
echo "$0: no destination specified" >&2
exit 1
else
:
fi
# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic
if [ -d "$dst" ]
then
dst=$dst/`basename "$src"`
else
:
fi
fi
## this sed command emulates the dirname command
dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
# Make sure that the destination directory exists.
# this part is taken from Noah Friedman's mkinstalldirs script
# Skip lots of stat calls in the usual case.
if [ ! -d "$dstdir" ]; then
defaultIFS='
'
IFS="${IFS-$defaultIFS}"
oIFS=$IFS
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
IFS=$oIFS
pathcomp=''
while [ $# -ne 0 ] ; do
pathcomp=$pathcomp$1
shift
if [ ! -d "$pathcomp" ] ;
then
$mkdirprog "$pathcomp"
else
:
fi
pathcomp=$pathcomp/
done
fi
if [ x"$dir_arg" != x ]
then
$doit $instcmd "$dst" &&
if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi
else
# If we're going to rename the final executable, determine the name now.
if [ x"$transformarg" = x ]
then
dstfile=`basename "$dst"`
else
dstfile=`basename "$dst" $transformbasename |
sed $transformarg`$transformbasename
fi
# don't allow the sed command to completely eliminate the filename
if [ x"$dstfile" = x ]
then
dstfile=`basename "$dst"`
else
:
fi
# Make a couple of temp file names in the proper directory.
dsttmp=$dstdir/_inst.$$_
rmtmp=$dstdir/_rm.$$_
# Trap to clean up temp files at exit.
trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
trap '(exit $?); exit' 1 2 13 15
# Move or copy the file name to the temp name
$doit $instcmd "$src" "$dsttmp" &&
# and set any options; do chmod last to preserve setuid bits
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $instcmd $src $dsttmp" command.
if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi &&
# Now remove or move aside any old file at destination location. We try this
# two ways since rm can't unlink itself on some systems and the destination
# file might be busy for other reasons. In this case, the final cleanup
# might fail but the new file should still install successfully.
{
if [ -f "$dstdir/$dstfile" ]
then
$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null ||
$doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null ||
{
echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
(exit 1); exit
}
else
:
fi
} &&
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
fi &&
# The final little trick to "correctly" pass the exit status to the exit trap.
{
(exit 0); exit
}
noinst_LIBRARIES = libneo.a
AM_CPPFLAGS = -I$(top_srcdir)/include
libneo_a_SOURCES = neo_mysql.c neo_socket.c neo_struct.c timestamp.c
# Makefile.in generated by automake 1.7.9 from Makefile.am.
# @configure_input@
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
# Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
ACLOCAL = @ACLOCAL@
AMDEP_FALSE = @AMDEP_FALSE@
AMDEP_TRUE = @AMDEP_TRUE@
AMTAR = @AMTAR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
MAKEINFO = @MAKEINFO@
MYSQL_CONFIG = @MYSQL_CONFIG@
MYSQL_INCLUDE = @MYSQL_INCLUDE@
MYSQL_LDFLAGS = @MYSQL_LDFLAGS@
MYSQL_LIBS = @MYSQL_LIBS@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PYTHON = @PYTHON@
PYTHON_BASECFLAGS = @PYTHON_BASECFLAGS@
PYTHON_CC = @PYTHON_CC@
PYTHON_CCSHARED = @PYTHON_CCSHARED@
PYTHON_INCLUDE = @PYTHON_INCLUDE@
PYTHON_LDSHARED = @PYTHON_LDSHARED@
PYTHON_OPT = @PYTHON_OPT@
PYTHON_SO = @PYTHON_SO@
RANLIB = @RANLIB@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
ac_ct_CC = @ac_ct_CC@
ac_ct_RANLIB = @ac_ct_RANLIB@
ac_ct_STRIP = @ac_ct_STRIP@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
bindir = @bindir@
build_alias = @build_alias@
datadir = @datadir@
exec_prefix = @exec_prefix@
host_alias = @host_alias@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localstatedir = @localstatedir@
mandir = @mandir@
oldincludedir = @oldincludedir@
prefix = @prefix@
program_transform_name = @program_transform_name@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
noinst_LIBRARIES = libneo.a
AM_CPPFLAGS = -I$(top_srcdir)/include
libneo_a_SOURCES = neo_mysql.c neo_socket.c neo_struct.c timestamp.c
subdir = lib
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
LIBRARIES = $(noinst_LIBRARIES)
libneo_a_AR = $(AR) cru
libneo_a_LIBADD =
am_libneo_a_OBJECTS = neo_mysql.$(OBJEXT) neo_socket.$(OBJEXT) \
neo_struct.$(OBJEXT) timestamp.$(OBJEXT)
libneo_a_OBJECTS = $(am_libneo_a_OBJECTS)
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/neo_mysql.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/neo_socket.Po ./$(DEPDIR)/neo_struct.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/timestamp.Po
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
DIST_SOURCES = $(libneo_a_SOURCES)
DIST_COMMON = $(srcdir)/Makefile.in Makefile.am
SOURCES = $(libneo_a_SOURCES)
all: all-am
.SUFFIXES:
.SUFFIXES: .c .o .obj
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4)
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu lib/Makefile
Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
AR = ar
clean-noinstLIBRARIES:
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
libneo.a: $(libneo_a_OBJECTS) $(libneo_a_DEPENDENCIES)
-rm -f libneo.a
$(libneo_a_AR) libneo.a $(libneo_a_OBJECTS) $(libneo_a_LIBADD)
$(RANLIB) libneo.a
mostlyclean-compile:
-rm -f *.$(OBJEXT) core *.core
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/neo_mysql.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/neo_socket.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/neo_struct.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timestamp.Po@am__quote@
.c.o:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
@am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \
@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
@am__fastdepCC_TRUE@ fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$<
.c.obj:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
@am__fastdepCC_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \
@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
@am__fastdepCC_TRUE@ fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`
uninstall-info-am:
ETAGS = etags
ETAGSFLAGS =
CTAGS = ctags
CTAGSFLAGS =
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
mkid -fID $$unique
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)$$tags$$unique" \
|| $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$tags $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& cd $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) $$here
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
top_distdir = ..
distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
list='$(DISTFILES)'; for file in $$list; do \
case $$file in \
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
esac; \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkinstalldirs) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(LIBRARIES)
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-am
dvi-am:
info: info-am
info-am:
install-data-am:
install-exec-am:
install-info: install-info-am
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-info-am
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
clean-noinstLIBRARIES ctags distclean distclean-compile \
distclean-generic distclean-tags distdir dvi dvi-am info \
info-am install install-am install-data install-data-am \
install-exec install-exec-am install-info install-info-am \
install-man install-strip installcheck installcheck-am \
installdirs maintainer-clean maintainer-clean-generic \
mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \
ps ps-am tags uninstall uninstall-am uninstall-info-am
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
#define _GNU_SOURCE
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <mysql/mysql.h>
#include <syslog.h>
#include "neo_struct.h"
#include "neo_mysql.h"
#include "neo_struct.h"
#include <time.h>
extern char database_dir[BUF_SIZE];
/* common functions */
int
database_thread_init ()
{
return mysql_thread_init ();
}
void
database_thread_end ()
{
return mysql_thread_end ();
}
int
database_close (struct database *orig_db)
{
struct database_mysql *db = (struct database_mysql *) orig_db;
mysql_close (db->sql);
free (db);
mysql_server_end ();
return 1;
}
/* part for the storage node */
struct database *
database_storage_open (int create)
{
struct database_mysql *db;
char datadir_opt[BUF_SIZE + 11];
memset(datadir_opt, 0, BUF_SIZE+11);
strncpy (datadir_opt, "--datadir=", 10);
strncat (datadir_opt, database_dir, BUF_SIZE);
char *server_args[] = {
"storage", /* this string is not used */
datadir_opt,
"--skip-innodb",
"--key-buffer=256M",
"--record-buffer=32M"
};
static char *server_groups[] = {
"embedded",
"server",
"storage_SERVER",
(char *) NULL
};
db = malloc (sizeof (struct database_mysql));
if (!db)
return 0;
mysql_server_init (sizeof (server_args) / sizeof (char *), server_args,
server_groups);
db->sql = mysql_init (NULL);
if (!db->sql)
return 0;
if (!mysql_real_connect (db->sql, NULL, "root", NULL, NULL, 0, NULL, 0))
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
if (mysql_query (db->sql, "CREATE DATABASE IF NOT EXISTS storage") != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
if (mysql_select_db (db->sql, "storage") != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
if (create)
{
if (mysql_query (db->sql, "DROP TABLE IF EXISTS object") != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
if (mysql_query (db->sql, "DROP TABLE IF EXISTS transaction") != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
if (mysql_query
(db->sql,
"CREATE TABLE transaction (tid BIGINT UNSIGNED NOT NULL, user VARCHAR(20), description VARCHAR(50), extension VARCHAR(100), PRIMARY KEY(tid)) TYPE=MYISAM")
!= 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
if (mysql_query
(db->sql,
"CREATE TABLE object (id BIGINT UNSIGNED NOT NULL, serial BIGINT UNSIGNED NOT NULL, tid BIGINT UNSIGNED NOT NULL, FOREIGN KEY (tid) REFERENCES transaction(tid) on delete cascade, crc INT NOT NULL, data TEXT NOT NULL, PRIMARY KEY(id,serial)) TYPE=MYISAM")
!= 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
}
return (struct database *) db;
}
int
database_storage_put_object (struct database *orig_db, u_int64_t oid,
u_int64_t serial, u_int64_t tid,
void *object, u_int32_t size, int32_t crc)
{
struct database_mysql *db = (struct database_mysql *) orig_db;
char *buf;
char *p;
/* allocate buffer for size of object + rest of the request */
/* size is * 2 for the mysql_real_escape_string (see mysql doc) */
buf = (char *) malloc (size * 2 + 500);
memset (buf, 0, size * 2 + 500);
p = buf;
p +=
sprintf (buf,
"INSERT INTO object VALUES ('%llu', '%llu', '%llu', '%d', '",
oid, serial, tid, crc);
p += mysql_real_escape_string (db->sql, p, object, size);
p = stpcpy (p, "')");
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : PutObject %s", buf);
if (mysql_real_query (db->sql, buf, p - buf) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s, size of object : %d, size of buffer %d, size of object %d",
mysql_error (db->sql), size, strlen(buf), strlen(object));
free (buf);
return 0;
}
free (buf);
return 1;
};
int
database_storage_put_trans (struct database *orig_db, u_int64_t tid,
char *user, char *desc, char *ext)
{
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000];
char *p;
p = buf;
memset (buf, 0, 4000);
p +=
sprintf (buf, "INSERT INTO transaction VALUES ('%llu', '%s', '%s', '%s')",
tid, user, desc, ext);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : PutTrans %s", buf);
if (mysql_real_query (db->sql, buf, p - buf) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
return 1;
};
int
database_storage_del_trans (struct database *orig_db, u_int64_t tid)
{
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000];
char *p;
memset (buf, 0, 4000);
p = buf;
p += sprintf (buf, "DELETE FROM transaction WHERE tid = '%llu'", tid);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : DeleteTrans %s", buf);
if (mysql_real_query (db->sql, buf, p - buf) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
return 1;
};
int
database_storage_store_trans (struct database *orig_db, u_int64_t tid,
char *user, char *desc, char *ext)
{
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000];
char *p;
p = buf;
memset (buf, 0, 4000);
/* delete trans */
database_storage_del_trans (orig_db, tid);
/* add new */
p +=
sprintf (buf, "INSERT INTO transaction VALUES ('%llu', '%s', '%s', '%s')",
tid, user, desc, ext);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : StoreTrans %s", buf);
if (mysql_real_query (db->sql, buf, p - buf) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
return 1;
};
int
database_storage_check_sanity (struct database *orig_db, u_int64_t tid,
u_int64_t oid)
{
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000];
char *p;
MYSQL_RES *res;
MYSQL_ROW row;
p = buf;
memset (buf, 0, 4000);
p +=
sprintf (buf,
"SELECT COUNT(*) FROM object WHERE id = '%llu' AND tid = '%llu' ",
oid, tid);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : check sanity %s", buf);
if (mysql_real_query (db->sql, buf, p - buf) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
res = mysql_store_result (db->sql);
if (!res)
return 0;
row = mysql_fetch_row (res);
if (!row)
return 0;
if (mysql_num_rows (res) == 0)
return 0;
mysql_free_result (res);
return 1;
};
int
database_storage_get_db_size (struct database *orig_db, u_int64_t *size)
{
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000];
unsigned long len;
MYSQL_RES *res;
MYSQL_ROW row;
memset (buf, 0, 4000);
/* XXX doesn't work */
len =
sprintf (buf, "SELECT SUM(len(data)) FROM object");
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : GetDBSize %s", buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
res = mysql_store_result (db->sql);
if (!res)
return 0;
row = mysql_fetch_row (res);
if (!row)
return 0;
sscanf (row[0], "%llu", size);
mysql_free_result (res);
return 1;
};
int
database_storage_get_object (struct database *orig_db, u_int64_t oid,
u_int64_t serial, void **object, int32_t * crc)
{
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000];
unsigned long len;
MYSQL_RES *res;
MYSQL_ROW row;
unsigned long *lengths;
memset (buf, 0, 4000);
len =
sprintf (buf,
"SELECT data, crc FROM object WHERE id = '%llu' AND serial = '%llu'",
oid, serial);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : GetObject %s", buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
res = mysql_store_result (db->sql);
if (!res)
return 0;
row = mysql_fetch_row (res);
if (!row)
return 0;
lengths = mysql_fetch_lengths (res);
len = lengths[0];
*object = malloc (len + 1);
memset (*object, 0, len + 1);
if (!*object)
return 0;
memcpy (*object, row[0], len);
sscanf (row[1], "%d", crc);
mysql_free_result (res);
return 1;
};
int
database_storage_get_trans_info (struct database *orig_db, u_int64_t tid,
struct undoInfo *hist)
{
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000];
char *p;
unsigned long long len;
MYSQL_RES *res;
MYSQL_ROW row;
unsigned long *lengths;
memset (buf, 0, 4000);
p = buf;
len =
sprintf (buf,
"SELECT user,description FROM transaction WHERE tid = '%llu'",
tid);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : GetTransInfo %s", buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
res = mysql_store_result (db->sql);
if (!res)
return 0;
row = mysql_fetch_row (res);
if (!row)
return 0;
lengths = mysql_fetch_lengths (res);
/* user */
len = lengths[0];
hist->user = (char *) malloc (len + 1);
memset (hist->user, 0, len + 1);
if (!hist->user)
return 0;
memcpy (hist->user, row[0], len);
/* desc */
len = lengths[1];
hist->desc = (char *) malloc (len + 1);
memset (hist->desc, 0, len + 1);
if (!hist->desc)
return 0;
memcpy (hist->desc, row[1], len);
mysql_free_result (res);
return 1;
};
int
database_storage_get_object_info (struct database *orig_db, u_int64_t oid,
u_int64_t serial, struct hist *hist)
{
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000];
char *p;
unsigned long long len;
MYSQL_RES *res;
MYSQL_ROW row;
unsigned long *lengths;
memset (buf, 0, 4000);
p = buf;
len =
sprintf (buf,
"SELECT transaction.user,transaction.description, object.data FROM object, transaction WHERE object.id = '%llu' AND object.serial = '%llu' AND transaction.tid = object.tid",
oid, serial);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : getObjectInfo %s", buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
res = mysql_store_result (db->sql);
if (!res)
return 0;
row = mysql_fetch_row (res);
if (!row)
return 0;
lengths = mysql_fetch_lengths (res);
/* user */
len = lengths[0];
hist->user = (char *) malloc (len + 1);
if (!hist->user)
return 0;
memset (hist->user, 0, len + 1);
memcpy (hist->user, row[0], len);
/* desc */
len = lengths[1];
hist->desc = (char *) malloc (len + 1);
if (!hist->desc)
return 0;
memset (hist->desc, 0, len + 1);
memcpy (hist->desc, row[1], len);
/* size */
hist->size = lengths[2];
mysql_free_result (res);
return 1;
};
int
database_storage_get_trans_data (struct database *orig_db, u_int64_t tid,
char **user, char **desc, char **ext,
struct objectList **list)
{
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000];
unsigned long len;
MYSQL_RES *res, *ress;
MYSQL_ROW row;
unsigned long *lengths;
u_int32_t size, nb_rows, i;
u_int64_t oid, serial;
memset (buf, 0, 4000);
len =
sprintf (buf,
"SELECT user, description, extension FROM transaction WHERE tid = '%llu'",
tid);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : getTransaData %s", buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
res = mysql_store_result (db->sql);
if (!res)
return 0;
row = mysql_fetch_row (res);
if (!row)
return 0;
/* return user descritpion and size for the object */
lengths = mysql_fetch_lengths (res);
/* user */
size = lengths[0];
*user = (char *) malloc (size + 1);
if (!*user)
return 0;
memset (*user, 0, size + 1);
memcpy (*user, row[0], size);
/* desc */
size = lengths[1];
*desc = (char *) malloc (size + 1);
if (!*desc)
return 0;
memset (*desc, 0, size + 1);
memcpy (*desc, row[1], size);
/* extension */
size = lengths[2];
*ext = (char *) malloc (size + 1);
if (!*ext)
return 0;
memset (*ext, 0, size + 1);
memcpy (*ext, row[2], size);
mysql_free_result (res);
/* now get list object with data... */
memset (buf, 0, 4000);
len =
sprintf (buf,
"SELECT id, serial, data FROM object WHERE tid = '%llu'", tid);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : getTransData %s", buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
ress = mysql_store_result (db->sql);
if (!ress)
return 0;
nb_rows = mysql_num_rows (ress);
/* init list */
*list = (struct objectList *) malloc (sizeof (struct objectList));
objectList_New (*list, nb_rows);
/* add oid, serial and data to list */
for (i = 0; i < nb_rows; i++)
{
/* get next row */
row = mysql_fetch_row (ress);
if (!row)
return 0;
sscanf (row[0], "%llu", &oid);
sscanf (row[1], "%llu", &serial);
objectList_Append (*list, oid, serial, row[2]);
}
mysql_free_result (ress);
return 1;
};
int
database_storage_get_object_list (struct database *orig_db, u_int64_t tid,
u_int64_t ** list, u_int32_t * nb_oid)
{
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000];
unsigned long len, nb_rows, i;
MYSQL_RES *res;
MYSQL_ROW row;
u_int64_t *oid;
*nb_oid = 0;
memset (buf, 0, 4000);
len = sprintf (buf, "SELECT id FROM object WHERE tid = '%llu'", tid);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : getObjectList %s", buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
res = mysql_store_result (db->sql);
if (!res)
return 0;
nb_rows = mysql_num_rows (res);
/* init list */
oid = (u_int64_t *) malloc (sizeof (u_int64_t) * nb_rows);
/* add oid to list */
for (i = 0; i < nb_rows; i++)
{
/* get next row */
row = mysql_fetch_row (res);
if (!row)
return 0;
sscanf (row[0], "%llu", &(oid[i]));
(*nb_oid)++;
}
mysql_free_result (res);
*list = oid;
return 1;
};
int
database_storage_trans_exist (struct database *orig_db, u_int64_t tid,
int *exist)
{
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000];
unsigned long len;
MYSQL_RES *res;
memset (buf, 0, 4000);
*exist = 0;
len = sprintf (buf, "SELECT user FROM transaction WHERE tid = '%llu'", tid);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : transExist %s", buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
res = mysql_store_result (db->sql);
if (!res)
return 0;
if (mysql_num_rows (res) != 0)
*exist = 1;
return 1;
};
/* part for the master node */
struct database *
database_master_open (int create)
{
struct database_mysql *db;
char datadir_opt[BUF_SIZE + 11];
memset(datadir_opt, 0, BUF_SIZE+11);
strncpy (datadir_opt, "--datadir=", 10);
strncat (datadir_opt, database_dir, BUF_SIZE);
char *server_args[] = {
"master",
datadir_opt,
"--skip-innodb",
"--key-buffer=256M",
"--record-buffer=32M",
};
static char *server_groups[] = {
"embedded",
"server",
"master_SERVER",
(char *) NULL
};
db = malloc (sizeof (struct database_mysql));
if (!db)
return 0;
mysql_server_init (sizeof (server_args) / sizeof (char *), server_args,
server_groups);
db->sql = mysql_init (NULL);
if (!db->sql)
return 0;
if (!mysql_real_connect (db->sql, NULL, "root", NULL, NULL, 0, NULL, 0))
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
if (mysql_query (db->sql, "CREATE DATABASE IF NOT EXISTS master") != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
if (mysql_select_db (db->sql, "master") != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
if (create) /* start with a new database */
{
if (mysql_query (db->sql, "DROP TABLE IF EXISTS object") != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
if (mysql_query (db->sql, "DROP TABLE IF EXISTS transaction") != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
if (mysql_query (db->sql, "DROP TABLE IF EXISTS storage") != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
if (mysql_query (db->sql, "DROP TABLE IF EXISTS client") != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
if (mysql_query (db->sql, "DROP TABLE IF EXISTS location") != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
if (mysql_query
(db->sql,
"CREATE TABLE transaction (tid BIGINT UNSIGNED NOT NULL, previous BIGINT UNSIGNED, status TINYINT UNSIGNED, PRIMARY KEY(tid)) TYPE=MYISAM")
!= 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
if (mysql_query
(db->sql,
"CREATE TABLE object (id BIGINT UNSIGNED NOT NULL, serial BIGINT UNSIGNED NOT NULL, tid BIGINT UNSIGNED NOT NULL, FOREIGN KEY (tid) REFERENCES transaction(tid) on delete cascade, PRIMARY KEY(id,serial)) TYPE=MYISAM")
!= 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
if (mysql_query
(db->sql,
"CREATE TABLE storage (id VARCHAR(36) NOT NULL, ip VARCHAR(15), port SMALLINT UNSIGNED, status TINYINT UNSIGNED, PRIMARY KEY(id)) TYPE=MYISAM")
!= 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
if (mysql_query
(db->sql,
"CREATE TABLE client (id VARCHAR(36) NOT NULL, ip VARCHAR(15), port SMALLINT UNSIGNED, connection_descriptor SMALLINT UNSIGNED, PRIMARY KEY(id)) TYPE=MYISAM")
!= 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
if (mysql_query
(db->sql,
"CREATE TABLE location (tid BIGINT UNSIGNED NOT NULL, sid VARCHAR(36) NOT NULL, FOREIGN KEY (tid) REFERENCES transaction(tid) on delete cascade, FOREIGN KEY (sid) REFERENCES storage(id)) TYPE=MYISAM")
!= 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : database recreated");
}
return (struct database *) db;
}
int
database_master_get_object_by_oid (struct database *orig_db, u_int64_t oid,
u_int64_t * serial,
struct stringList **list)
{
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000], id[UUID_LEN + 1];
int i, nb_storage_id = 0;
unsigned long len;
MYSQL_RES *res;
MYSQL_ROW row;
/* then get storages for the last serial of oid */
memset (buf, 0, 4000);
len =
sprintf (buf,
"SELECT object.serial, storage.id FROM object, location, storage WHERE object.id = '%llu' AND location.tid = object.tid AND storage.id = location.sid AND storage.status = 0 AND object.serial = (SELECT MAX(object.serial) FROM object, transaction WHERE object.id = '%llu' AND transaction.tid = object.tid AND transaction.status = 0)",
oid, oid);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : ObjectByOid %s", buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
res = mysql_store_result (db->sql);
if (!res)
return 0;
if ((nb_storage_id = mysql_num_rows (res)) == 0)
{
mysql_free_result (res);
return -1;
}
row = mysql_fetch_row (res);
if (!row)
return 0;
sscanf (row[0], "%llu", serial);
/* get storage id list */
*list = (struct stringList *) malloc (sizeof (struct stringList));
stringList_New (*list, nb_storage_id, UUID_LEN);
for (i = 0; i < nb_storage_id; i++)
{
memset (id, 0, UUID_LEN + 1);
memcpy (id, row[1], UUID_LEN);
stringList_Append (*list, id);
row = mysql_fetch_row (res);
if (!row)
break;
}
mysql_free_result (res);
return 1;
}
int
database_master_get_object_by_serial (struct database *orig_db,
u_int64_t oid, u_int64_t serial,
struct stringList **list)
{
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000], id[UUID_LEN + 1];
unsigned long len;
int i, nb_storage_id = 0;
MYSQL_RES *res;
MYSQL_ROW row;
memset (buf, 0, 4000);
len =
sprintf (buf,
"SELECT storage.id FROM object, transaction, location, storage WHERE object.id = '%llu' AND object.serial = '%llu' AND transaction.tid = object.tid AND location.tid = transaction.tid AND storage.id = location.sid AND storage.status = 0 AND transaction.status = 0",
oid, serial);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : ObjectBySerial %s", buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
res = mysql_store_result (db->sql);
if (!res)
return 0;
if ((nb_storage_id = mysql_num_rows (res)) == 0)
{
mysql_free_result (res);
return -1;
}
row = mysql_fetch_row (res);
if (!row)
return 0;
/* get storage id list */
*list = (struct stringList *) malloc (sizeof (struct stringList));
stringList_New (*list, nb_storage_id, UUID_LEN);
for (i = 0; i < nb_storage_id; i++)
{
memset (id, 0, UUID_LEN + 1);
memcpy (id, row[0], UUID_LEN);
stringList_Append (*list, id);
row = mysql_fetch_row (res);
if (!row)
break;
}
mysql_free_result (res);
return 1;
}
int
database_master_get_serial (struct database *orig_db, u_int64_t oid,
u_int64_t * serial)
{
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000];
unsigned long len;
MYSQL_RES *res;
MYSQL_ROW row;
memset (buf, 0, 4000);
len =
sprintf (buf, "SELECT MAX(serial) FROM object, transaction WHERE object.id = '%llu' AND transaction.tid = object.tid AND transaction.status = 0",
oid);
/* tester le null */
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : GetSerial %s", buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
res = mysql_store_result (db->sql);
if (!res)
return 0;
if (mysql_num_rows (res) == 0)
{
mysql_free_result (res);
return -1;
}
row = mysql_fetch_row (res);
if (!row)
return 0;
if (row[0] == NULL)
{
mysql_free_result (res);
return -1;
}
/* get serial */
sscanf (row[0], "%llu", serial);
mysql_free_result (res);
return 1;
}
int
database_master_get_trans_storages (struct database *orig_db,
u_int64_t tid, int16_t first,
int16_t last, struct tlist **list)
{
u_int64_t ltid;
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000], id[UUID_LEN + 1];
unsigned long len;
int16_t i = 0;
int nb_storage_id = 0, j, k = 0;
MYSQL_RES *res;
MYSQL_ROW row;
ltid = tid;
*list = (struct tlist *) malloc (sizeof (struct tlist));
init_tlist (*list, last - first);
while (i < last)
{
if (i < first)
{
/* only get the previous transaction id */
memset (buf, 0, 4000);
len =
sprintf (buf,
"SELECT previous FROM transaction WHERE tid = '%llu'",
ltid);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : GetTransSN %s",
buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
res = mysql_store_result (db->sql);
if (!res)
return 0;
row = mysql_fetch_row (res);
if (!row)
return 0;
sscanf (row[0], "%llu", &ltid);
mysql_free_result (res);
}
else if (i >= first)
{
/* get and add transaction and informations to list */
memset (buf, 0, 4000);
len =
sprintf (buf,
"SELECT transaction.previous, storage.id FROM transaction, location, storage WHERE location.tid = '%llu' AND transaction.tid = '%llu' AND storage.id = location.sid AND storage.status = 0",
ltid, ltid);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : GetTransSN %s",
buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
res = mysql_store_result (db->sql);
if (!res)
return 0;
/* add the current transaction */
nb_storage_id = mysql_num_rows (res);
add_trans (list, ltid, nb_storage_id);
for (j = 0; j < nb_storage_id; j++)
{
row = mysql_fetch_row (res);
if (!row)
return 0;
memset (id, 0, UUID_LEN + 1);
memcpy (id, row[1], UUID_LEN);
/* add storage id */
add_cobject (&((*list)->objects[k].list), id, "");
}
/* check for row here... */
sscanf (row[0], "%llu", &ltid);
k++;
mysql_free_result (res);
}
i++;
}
return 1;
}
int
database_master_get_object_hist (struct database *orig_db, u_int64_t oid,
u_int16_t length, struct tlist **list)
{
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000], id[UUID_LEN + 1];
unsigned long len;
u_int16_t i = 0, nb_storage_id = 0, j;
u_int64_t serial;
clock_t c1, c2;
float t;
static float time = 0;
MYSQL_RES *res, *result;
MYSQL_ROW row;
*list = (struct tlist *) malloc (sizeof (struct tlist));
init_tlist (*list, length);
/* get and add transaction and informations to list */
memset (buf, 0, 4000);
/* first get all serial ordered for the client */
len =
sprintf (buf,
"SELECT serial FROM object WHERE id = '%llu' ORDER BY serial DESC",
oid);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : GetObjectHist %s", buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
res = mysql_store_result (db->sql);
if (!res)
return 0;
if (mysql_num_rows (res) == 0)
return -1;
while (i < length)
{
/* get serial */
row = mysql_fetch_row (res);
if (!row)
break;
sscanf (row[0], "%llu", &serial);
/* get storage for this serial */
memset (buf, 0, 4000);
len =
sprintf (buf,
"SELECT storage.id, transaction.tid FROM object, transaction, location, storage WHERE object.id = '%llu' AND object.serial = '%llu' AND transaction.tid = object.tid AND transaction.status = 0 AND location.tid = transaction.tid AND storage.id = location.sid AND storage.status = 0",
oid, serial);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : GetObjectHist %s",
buf);
/* time */
c1 = clock();
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
/* time */
c2 = clock();
t = (float)(c2 - c1) / CLOCKS_PER_SEC;
if (t > 0)
{
time += t;
printf ("SQL time : %f, time %f\n", t, time);
}
result = mysql_store_result (db->sql);
if (!result)
continue;
if ((nb_storage_id = mysql_num_rows (result)) == 0)
continue; /* maybe an undone transaction */
add_trans (list, serial, nb_storage_id);
/* storage list */
for (j = 0; j < nb_storage_id; j++)
{
row = mysql_fetch_row (result);
if (!row)
break;
/* storage id */
memset (id, 0, UUID_LEN + 1);
memcpy (id, row[0], UUID_LEN);
add_cobject (&((*list)->objects[i].list), id, "");
}
i++;
mysql_free_result (result);
}
mysql_free_result (res);
return 1;
}
int
database_master_undo_trans (struct database *orig_db, u_int64_t tid,
struct stringList **list)
{
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000], id[UUID_LEN];
unsigned long len;
u_int16_t nb_storage_id, i;
int rows, changed, warn;
MYSQL_RES *res;
MYSQL_ROW row;
memset (buf, 0, 4000);
len =
sprintf (buf, "UPDATE transaction SET status = 1 WHERE tid = '%llu'",
tid);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : undoTrans %s", buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
/* check if something has been updated otherwise it is unknown transaction */
sscanf (mysql_info (db->sql), "Rows matched: %d Changed: %d Warnings: %d",
&rows, &changed, &warn);
if (rows == 0)
return -1;
/* also return a list of storages to undo transaction on them */
memset (buf, 0, 4000);
len =
sprintf (buf,
"SELECT storage.id FROM storage, location WHERE location.tid = '%llu' AND storage.id = location.sid AND storage.status = 0",
tid);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : undoTrans %s", buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
res = mysql_store_result (db->sql);
if (!res)
return 0;
if ((nb_storage_id = mysql_num_rows (res)) == 0)
return -1;
row = mysql_fetch_row (res);
if (!row)
return 0;
/* get storage id list */
*list = (struct stringList *) malloc (sizeof (struct stringList));
stringList_New (*list, nb_storage_id, UUID_LEN);
for (i = 0; i < nb_storage_id; i++)
{
memset (id, 0, UUID_LEN + 1);
memcpy (id, row[0], UUID_LEN);
stringList_Append (*list, id);
row = mysql_fetch_row (res);
if (!row)
break;
}
mysql_free_result (res);
return 1;
}
int
database_master_begin_trans (struct database *orig_db, u_int64_t tid,
u_int64_t ltid, struct stringList list)
{
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000];
u_int32_t i;
unsigned long len;
char *id;
memset (buf, 0, 4000);
/* insert new transaction in table */
/* transaction status : 0 : ok, 1 : undone, 2 : not validated */
len =
sprintf (buf, "INSERT INTO transaction VALUES ('%llu', '%llu', 2)", tid,
ltid);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : BeginTrans %s", buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
/* insert pair tid-storage_id into location table */
for (i = 0; i < list.last; i++)
{
memset (buf, 0, 4000);
stringList_GetItem (&list, &id, i);
len =
sprintf (buf, "INSERT INTO location VALUES ('%llu', '%s')", tid, id);
free (id);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : BeginTrans %s", buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
}
return 1;
}
int
database_master_put_object (struct database *orig_db, u_int64_t tid,
u_int64_t oid, u_int64_t serial)
{
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000];
unsigned long len;
u_int64_t last_serial;
int res;
memset (buf, 0, 4000);
/* check if serial is the last one for the object, if not client try to validate a too old version of version */
if ((res = database_master_get_serial (orig_db, oid, &last_serial)) == 0)
return 0;
else if (res == 1)
if (serial != last_serial)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_WARNING),
"SQL : Invalid transaction %llu for object %llu, serial %llu != %llu",
tid, oid, serial, last_serial);
return 0; /* transaction invalid */
}
/* insert new object into table */
len =
sprintf (buf, "INSERT INTO object VALUES ('%llu', '%llu', '%llu')", oid,
tid, tid);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : PutObject %s", buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
return 1;
}
int
database_master_end_trans (struct database *orig_db, u_int64_t tid)
{
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000];
unsigned long len;
/* update status of transaction */
memset (buf, 0, 4000);
len =
sprintf (buf, "UPDATE transaction SET status = 0 WHERE tid = '%llu'",
tid);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : EndTrans %s", buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
return 1;
}
int
database_master_delete_client (struct database *orig_db, char oid[UUID_LEN+1])
{
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000];
unsigned long len;
memset (buf, 0, 4000);
len = sprintf (buf, "DELETE FROM client WHERE id = '%s'", oid);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : DeleteClient %s", buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
return 1;
}
int
database_master_remove_client (struct database *orig_db, u_int16_t conn)
{
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000];
unsigned long len;
memset (buf, 0, 4000);
len = sprintf (buf, "DELETE FROM client WHERE connection_descriptor = '%d'", conn);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : Remove Client %s", buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
return 1;
}
int
database_master_delete_object (struct database *orig_db, u_int64_t oid,
u_int64_t serial)
{
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000];
unsigned long len;
memset (buf, 0, 4000);
len =
sprintf (buf, "DELETE FROM object WHERE id = '%llu' AND serial='%llu'",
oid, serial);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : DeleteObject %s", buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
return 1;
}
int
database_master_close_storage (struct database *orig_db, char id[UUID_LEN+1])
{
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000];
unsigned long len;
memset (buf, 0, 4000);
/* set status to close for the storage */
len = sprintf (buf, "UPDATE storage SET status = 1 WHERE id = '%s'", id);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : CloseStorage %s", buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
return 1;
}
int
database_master_unreliable_storage (struct database *orig_db,
char id[UUID_LEN+1])
{
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000];
unsigned long len;
memset (buf, 0, 4000);
/* set status to unreliable for the storage */
len = sprintf (buf, "UPDATE storage SET status = 2 WHERE id = '%s'", id);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : UnreliableStorage %s",
buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
return 1;
}
int
database_master_storage_ready (struct database *orig_db, char id[UUID_LEN+1])
{
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000];
unsigned long len;
memset (buf, 0, 4000);
/* set status to ready for the storage */
len = sprintf (buf, "UPDATE storage SET status = 0 WHERE id = '%s'", id);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : StorageReady %s", buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
return 1;
}
int
database_master_storage_starting (struct database *orig_db, char id[UUID_LEN+1],
char ip[IP_LEN], u_int16_t port,
u_int16_t * status)
{
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000];
unsigned long len;
MYSQL_RES *res;
MYSQL_ROW row;
/* status of storage node : 0 -> reliable, 1 -> closed, 2 -> unreliable, 3 -> starting */
memset (buf, 0, 4000);
/* try to get storage from database to see if already exists */
len = sprintf (buf, "SELECT status FROM storage WHERE id = '%s'", id);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : StorageStart %s", buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
res = mysql_store_result (db->sql);
if (mysql_num_rows (res) != 0)
{
/* get status */
row = mysql_fetch_row (res);
if (!row)
return 0;
sscanf (row[0], "%hu", status);
mysql_free_result (res);
/* storage ever exist in database, update information */
memset (buf, 0, 4000);
len =
sprintf (buf,
"UPDATE storage SET ip = '%s', port = %d, status = 0 WHERE id = '%s'",
ip, port, id);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : StorageStart %s",
buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
}
else
{
mysql_free_result (res);
/* storage doesn't exist in database, add it */
memset (buf, 0, 4000);
len =
sprintf (buf, "INSERT INTO storage VALUES ('%s', '%s', %d, 0)", id,
ip, port);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : StartStorage %s",
buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
}
return 1;
}
int
database_master_get_storage_infos (struct database *orig_db,
char id[UUID_LEN+1], char **ip,
u_int16_t * port)
{
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000];
unsigned long len;
MYSQL_RES *res;
MYSQL_ROW row;
memset (buf, 0, 4000);
len = sprintf (buf, "SELECT ip, port FROM storage WHERE id = '%s'", id);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : GetStorageInfo %s", buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
res = mysql_store_result (db->sql);
if (!res)
return 0;
row = mysql_fetch_row (res);
if (!row)
return 0;
/* get ip */
*ip = (char *) malloc (IP_LEN + 1);
memset (*ip, 0, IP_LEN + 1);
memcpy (*ip, row[0], IP_LEN);
/* get port */
*port = strtol (row[1], NULL, 10);
mysql_free_result (res);
return 1;
}
int
database_master_start_client (struct database *orig_db, char id[UUID_LEN+1],
char ip[IP_LEN], u_int16_t port, u_int16_t conn)
{
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000];
unsigned long len;
/* add client in database */
memset (buf, 0, 4000);
len =
sprintf (buf, "INSERT INTO client VALUES ('%s', '%s', %d, %d)", id, ip,
port, conn);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : StartClient %s", buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
return 1;
}
int
database_master_get_all_storages_infos (struct database *orig_db,
struct nlist **list)
{
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000];
int nb_storage_id, i, port;
unsigned long len;
MYSQL_RES *res;
MYSQL_ROW row;
char id[UUID_LEN + 1], ip[IP_LEN + 1];
memset (buf, 0, 4000);
len = sprintf (buf, "SELECT id, ip, port FROM storage WHERE status = 0");
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : GetAllStoragesInfo %s",
buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
res = mysql_store_result (db->sql);
if (!res)
return 0;
nb_storage_id = mysql_num_rows (res);
if (nb_storage_id == 0)
return -1;
row = mysql_fetch_row (res);
if (!row)
return 0;
/* get storage id list */
*list = (struct nlist *) malloc (sizeof (struct nlist));
init_nlist (*list, nb_storage_id);
for (i = 0; i < nb_storage_id; i++)
{
memset (id, 0, UUID_LEN + 1);
memset (ip, 0, IP_LEN + 1);
memcpy (id, row[0], UUID_LEN);
memcpy (ip, row[1], IP_LEN);
port = strtol (row[2], NULL, 10);
add_node (*list, id, ip, port);
row = mysql_fetch_row (res);
if (!row)
break;
}
mysql_free_result (res);
return 1;
}
int
database_master_get_all_clients_infos (struct database *orig_db,
struct nlist **list)
{
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000];
int nb_storage_id, i, port;
unsigned long len;
MYSQL_RES *res;
MYSQL_ROW row;
char id[UUID_LEN + 1], ip[IP_LEN + 1];
memset (buf, 0, 4000);
len = sprintf (buf, "SELECT id, ip, port FROM client");
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : GetAllClientsInfo %s",
buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
res = mysql_store_result (db->sql);
if (!res)
return 0;
if ((nb_storage_id = mysql_num_rows (res)) == 0)
{
mysql_free_result (res);
return -1;
}
row = mysql_fetch_row (res);
if (!row)
return 0;
/* get storage id list */
*list = (struct nlist *) malloc (sizeof (struct nlist));
init_nlist (*list, nb_storage_id);
for (i = 0; i < nb_storage_id; i++)
{
memset (id, 0, UUID_LEN + 1);
memset (ip, 0, IP_LEN + 1);
memcpy (id, row[0], UUID_LEN);
memcpy (ip, row[1], IP_LEN);
port = strtol (row[2], NULL, 10);
add_node (*list, id, ip, port);
row = mysql_fetch_row (res);
if (!row)
break;
}
mysql_free_result (res);
return 1;
}
int
database_master_get_trans_list (struct database *orig_db,
char storage_id[UUID_LEN+1],
struct tlist **list)
{
u_int64_t tid;
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000];
int nb_trans_id, i, j, nb_storage_id;
unsigned long len;
u_int16_t port;
MYSQL_RES *res, *result;
MYSQL_ROW row;
char ip[IP_LEN + 1], string_port[IP_LEN + 1];
memset (buf, 0, 4000);
len =
sprintf (buf,
"SELECT location.tid FROM location, transaction WHERE location.sid = '%s' AND transaction.tid = location.tid AND transaction.status = 0",
storage_id);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : GetTransList %s", buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
res = mysql_store_result (db->sql);
if (!res)
return 0;
nb_trans_id = mysql_num_rows (res);
*list = (struct tlist *) malloc (sizeof (struct tlist));
init_tlist (*list, nb_trans_id);
/* XXX just for test... */
if (nb_trans_id == 0)
return 1;
for (i = 0; i < nb_trans_id; i++)
{
/* get tid */
row = mysql_fetch_row (res);
if (!row)
return 0;
sscanf (row[0], "%llu", &tid);
/* get storage list for this trans */
memset (buf, 0, 4000);
len =
sprintf (buf,
"SELECT storage.ip, storage.port FROM location, storage WHERE location.tid = '%llu' AND location.sid != '%s' AND storage.id = location.sid AND storage.status = 0",
tid, storage_id);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : GetTranList %s", buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
result = mysql_store_result (db->sql);
if (!result)
return 0;
if ((nb_storage_id = mysql_num_rows (result)) == 0)
break; /* no storage for the tid */
add_trans (list, tid, nb_storage_id * 2); /* XXX hack for the moment to store ip and port */
/* storage list */
for (j = 0; j < nb_storage_id; j++)
{
row = mysql_fetch_row (result);
if (!row)
break;
/* storage ip & port */
memset (ip, 0, IP_LEN + 1);
memcpy (ip, row[0], IP_LEN);
memset (string_port, 0, IP_LEN + 1);
memcpy (string_port, row[1], IP_LEN);
port = strtol (row[1], NULL, 10);
add_cobject (&((*list)->objects[i].list), ip, "");
add_cobject (&((*list)->objects[i].list), string_port, "");
}
mysql_free_result (result);
}
mysql_free_result (res);
return 1;
}
int
database_master_get_storage_index (struct database *orig_db,
char storage_id[UUID_LEN+1],
struct transactionList **txn,
u_int64_t * nb_txn)
{
u_int64_t tid, object_id, i;
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000];
int j, nb_oid;
unsigned long len;
MYSQL_RES *res, *result;
MYSQL_ROW row;
struct objectList objects;
memset (buf, 0, 4000);
len =
sprintf (buf, "SELECT tid FROM location WHERE sid = '%s'", storage_id);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG),
"SQL : Get storage for index check %s", buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
res = mysql_store_result (db->sql);
if (!res)
return 0;
*nb_txn = mysql_num_rows (res);
*txn = (struct transactionList *) malloc (sizeof (struct transactionList));
transactionList_New (*txn, *nb_txn);
for (i = 0; i < *nb_txn; i++)
{
/* get tid */
row = mysql_fetch_row (res);
if (!row)
return 0;
sscanf (row[0], "%llu", &tid);
/* get list for this trans */
memset (buf, 0, 4000);
len = sprintf (buf, "SELECT id FROM object WHERE tid = '%llu'", tid);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG),
"SQL : GetTranList for index check %s", buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
result = mysql_store_result (db->sql);
if (!result)
return 0;
nb_oid = mysql_num_rows (result);
objectList_New (&objects, nb_oid);
/* get storage list */
for (j = 0; j < nb_oid; j++)
{
row = mysql_fetch_row (result);
if (!row)
break;
/* storage ip & port */
sscanf (row[0], "%llu", &object_id);
objectList_Append (&objects, object_id, tid, "");
}
transactionList_Append (*txn, tid, objects);
objectList_Free (&objects);
mysql_free_result (result);
}
mysql_free_result (res);
return 1;
}
int
database_master_create_storage_index (struct database *orig_db,
struct stringList **index)
{
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000];
int nb_storage_id, i;
unsigned long len;
MYSQL_RES *res;
MYSQL_ROW row;
char id[UUID_LEN + 1];
memset (buf, 0, 4000);
len = sprintf (buf, "SELECT id FROM storage WHERE status = 0");
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : create storage index %s",
buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
res = mysql_store_result (db->sql);
if (!res)
return 0;
nb_storage_id = mysql_num_rows (res);
stringList_New (*index, nb_storage_id, UUID_LEN);
if (nb_storage_id == 0)
return 1;
row = mysql_fetch_row (res);
if (!row)
{
mysql_free_result (res);
return 0;
}
/* get storage id list */
for (i = 0; i < nb_storage_id; i++)
{
memset (id, 0, UUID_LEN + 1);
memcpy (id, row[0], UUID_LEN);
stringList_Append (*index, id);
row = mysql_fetch_row (res);
if (!row)
break;
}
mysql_free_result (res);
return 1;
}
int
database_master_get_storages_for_trans (struct database *orig_db,
u_int64_t tid,
char storage_id[UUID_LEN+1],
struct stringList **list)
{
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000], ip[IP_LEN + 1], port[IP_LEN + 1];
unsigned long len;
int i, nb_storage_id = 0;
MYSQL_RES *res;
MYSQL_ROW row;
memset (buf, 0, 4000);
len =
sprintf (buf,
"SELECT storage.ip, storage.port FROM location, storage WHERE location.tid = '%llu' AND location.sid != '%s' AND storage.id = location.sid AND storage.status = 0",
tid, storage_id);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "SQL : get storage for trans %s",
buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
res = mysql_store_result (db->sql);
if (!res)
return 0;
if ((nb_storage_id = mysql_num_rows (res)) == 0)
{
/* maybe return error message to storage node instead */
*list = (struct stringList *) malloc (sizeof (struct stringList));
stringList_New (*list, nb_storage_id, UUID_LEN);
return 1;
}
row = mysql_fetch_row (res);
if (!row)
return 0;
/* get storage id list */
*list = (struct stringList *) malloc (sizeof (struct stringList));
stringList_New (*list, nb_storage_id * 2, UUID_LEN);
for (i = 0; i < nb_storage_id; i++)
{
memset (ip, 0, IP_LEN + 1);
memcpy (ip, row[0], IP_LEN);
memset (port, 0, IP_LEN + 1);
memcpy (port, row[1], IP_LEN);
stringList_Append (*list, ip);
stringList_Append (*list, port);
row = mysql_fetch_row (res);
if (!row)
break;
}
mysql_free_result (res);
return 1;
}
/**
* check if all objects stores by storage nodes are accessible
* if yes master can begin to handle client request
* otherwise must wait until another storage connect and redo the check
*/
int
database_master_all_objects_accessible (struct database *orig_db)
{
u_int64_t oid, serial, i, nb_objects;
struct database_mysql *db = (struct database_mysql *) orig_db;
char buf[4000];
unsigned long len;
MYSQL_RES *res, *result;
MYSQL_ROW row;
memset (buf, 0, 4000);
len =
sprintf (buf, "SELECT id, serial FROM object");
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG),
"SQL : all object accessible %s", buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
res = mysql_store_result (db->sql);
if (!res)
return 0;
nb_objects = mysql_num_rows (res);
for (i = 0; i < nb_objects; i++)
{
/* get tid */
row = mysql_fetch_row (res);
if (!row)
return 0;
sscanf (row[0], "%llu", &oid);
sscanf (row[1], "%llu", &serial);
/* get list for this trans */
memset (buf, 0, 4000);
len = sprintf (buf, "SELECT COUNT(*) FROM object, transaction, location, storage WHERE object.id = '%llu' AND object.serial = '%llu' AND transaction.tid = object.tid AND location.tid = transaction.tid AND storage.id = location.sid AND storage.status = 0", oid, serial);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG),
"SQL : Get sStorage for object %s", buf);
if (mysql_real_query (db->sql, buf, len) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "SQL Error : %s",
mysql_error (db->sql));
return 0;
}
result = mysql_store_result (db->sql);
if (!result)
return 0;
if (mysql_num_rows (result) == 0)
{
mysql_free_result (result);
mysql_free_result (res);
return 0;
}
mysql_free_result (result);
}
mysql_free_result (res);
return 1;
}
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <netdb.h>
#include "neo_socket.h"
#define NDEBUG 0
/**
* function that return the client ip for a given connection
* although clients give their ip, we prefer
* to get it from the socket connection
*/
int
getIp (int ds, char **ip)
{
struct sockaddr_in addr;
int size = sizeof (addr);
/* get remote address */
if (getpeername (ds, (struct sockaddr *) &addr, &size) < 0)
return 0;
*ip = (char *) malloc (IP_LEN);
*ip = (char *) inet_ntoa (addr.sin_addr);
if (*ip == NULL)
return 0;
return 1;
}
/**
* function that convert 64 byte integer in endian or byte order
*/
unsigned long long
ntohll (unsigned long long n)
{
#if __BYTE_ORDER == __BIG_ENDIAN
return n;
#else
return (((unsigned long long) ntohl (n)) << 32) + ntohl (n >> 32);
#endif
}
unsigned long long
htonll (unsigned long long n)
{
#if __BYTE_ORDER == __BIG_ENDIAN
return n;
#else
return (((unsigned long long) htonl (n)) << 32) + htonl (n >> 32);
#endif
}
int
send_all (int conn, char *buf, size_t len)
{
while (len > 0)
{
ssize_t size;
size = write (conn, buf, len);
if (size == 0)
{
/* fprintf (stderr, "unexpected EOF when writing\n"); */
return 0;
}
else if (size < 0)
{
if (errno == EINTR)
continue;
perror ("write");
return 0;
}
#if NDEBUG
fprintf (stdout, "sending %d bytes\n", size);
#endif
len -= (size_t) size;
buf += size;
}
return 1;
}
int
wait_packet (int conn, char *buf, u_int32_t * len, u_int32_t max)
{
while (1)
{
if (fill_buffer (conn, buf, len, max))
break;
else
return 0;
}
return 1;
}
int
fill_buffer (int conn, char *buf, u_int32_t * len, u_int32_t max)
{
ssize_t size;
again:
if (((max - *len) < 65635))
size = read (conn, buf + *len, max - *len);
else
size = read (conn, buf + *len, 65635);
if (size == 0)
{
/* fprintf (stderr, "unexpected EOF when reading\n"); */
return 0;
}
else if (size < 0)
{
/* printf ("read socket error %d\n", errno); */
if (errno == EINTR)
goto again;
if (errno == EAGAIN)
goto again;
perror ("read");
return 0;
}
*len += (u_int32_t) size;
#if NDEBUG
fprintf (stderr, "the buffer has %u bytes\n", *len);
#endif
return 1;
}
int
connectTo (char ip[IP_LEN], u_int16_t port)
{
int soc, rc;
struct sockaddr_in serv_addr;
struct hostent *server;
server = gethostbyname (ip);
bzero ((char *) &serv_addr, sizeof (serv_addr));
serv_addr.sin_family = AF_INET;
bcopy ((char *) server->h_addr, (char *) &serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons (port);
soc = socket (PF_INET, SOCK_STREAM, 0);
if (soc < 0)
return 0;
rc = connect (soc, (struct sockaddr *) &serv_addr, sizeof (serv_addr));
if (rc < 0)
return 0;
return soc;
}
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "neo_struct.h"
/* generic list use for storage, oid, and client*/
int
init_list (struct list *pl, u_int16_t size)
{
pl->len = size;
pl->last = 0;
pl->objects = (struct cobject *) malloc (sizeof (struct cobject) * pl->len);
return 1;
}
int
double_list (struct list *pl)
{
int i;
pl->len *= 2;
struct cobject *tmp;
tmp = (struct cobject *) malloc (sizeof (struct cobject) * pl->len);
for (i = 0; i < pl->len / 2; i++)
tmp[i] = pl->objects[i];
free (pl->objects);
pl->objects = tmp;
return 1;
}
int
add_cobject (struct list *pl, char *cdata, char *sdata)
{
if (pl->len == pl->last)
{
double_list (pl);
}
pl->objects[pl->last].data = (char *) malloc (strlen (cdata) + 1);
memset (pl->objects[pl->last].data, 0, strlen (cdata) + 1);
strncpy (pl->objects[pl->last].data, cdata, strlen (cdata));
pl->last++;
return 1;
}
int
free_list (struct list *pl)
{
free (pl->objects);
return 1;
}
/* function for transaction */
int
init_tlist (struct tlist *pl, u_int16_t size)
{
pl->len = size;
pl->last = 0;
pl->objects = (struct trans *) malloc (sizeof (struct trans) * pl->len);
return 1;
}
int
double_tlist (struct tlist *pl)
{
int i;
pl->len *= 2;
struct trans *tmp;
tmp = (struct trans *) malloc (sizeof (struct trans) * pl->len);
for (i = 0; i < pl->len / 2; i++)
tmp[i] = pl->objects[i];
free (pl->objects);
pl->objects = tmp;
return 1;
}
int
free_tlist (struct tlist *pl)
{
u_int16_t i;
for (i = 0; i < pl->last; i++)
free_list (&(pl->objects[i].list));
free (pl->objects);
return 1;
}
int
add_trans (struct tlist **pl, u_int64_t tid, u_int16_t nb_s)
{
if ((*pl)->len == (*pl)->last)
{
perror ("add object");
return 0;
}
(*pl)->objects[(*pl)->last].tid = tid;
init_list (&((*pl)->objects[(*pl)->last].list), nb_s);
(*pl)->last++;
return 1;
}
/* function for node list */
int
double_nlist (struct nlist *pl)
{
int i;
pl->len *= 2;
struct node *tmp;
tmp = (struct node *) malloc (sizeof (struct node) * pl->len);
for (i = 0; i < pl->len / 2; i++)
tmp[i] = pl->objects[i];
free (pl->objects);
pl->objects = tmp;
return 1;
}
int
add_node (struct nlist *pl, char *id, char *addr, u_int16_t port)
{
if (pl->len == pl->last)
{
double_nlist (pl);
}
pl->objects[pl->last].id = (char *) malloc (strlen (id) + 1);
pl->objects[pl->last].addr = (char *) malloc (strlen (addr) + 1);
memset (pl->objects[pl->last].id, 0, strlen (id) + 1);
memset (pl->objects[pl->last].addr, 0, strlen (addr) + 1);
strncpy (pl->objects[pl->last].id, id, strlen (id));
strncpy (pl->objects[pl->last].addr, addr, strlen (addr));
pl->objects[pl->last].port = port;
pl->last++;
return 1;
}
int
free_nlist (struct nlist *pl)
{
u_int32_t node_nb;
for (node_nb = 0; node_nb < pl->last; node_nb++)
{
free (pl->objects[node_nb].id);
free (pl->objects[node_nb].addr);
}
free (pl->objects);
return 1;
}
int
init_nlist (struct nlist *pl, u_int16_t size)
{
pl->len = size;
pl->last = 0;
pl->objects = (struct node *) malloc (sizeof (struct node) * pl->len);
return 1;
}
/* functions for index in master node */
int
double_index (struct index *i)
{
int j;
char *tmpid;
i->len = i->len * 2;
tmpid = (char *) malloc (i->id_size * i->len);
for (j = 0; j < (i->len) / 2; j++)
{
strcpy (&(tmpid[j * (i->id_size + 1)]), &(i->id[j * (i->id_size + 1)]));
}
free (i->id);
i->id = tmpid;
return 1;
}
int
init_index (struct index *i, u_int16_t id_size)
{
i->len = 5;
i->last = 0;
i->id_size = id_size;
i->id = (char *) malloc ((i->id_size + 1) * i->len);
memset (i->id, 0, (i->id_size + 1) * i->len);
return 1;
}
int
index_add (struct index *i, char *id)
{
if (i->len == i->last)
double_index (i);
strncpy (&(i->id[i->last * (i->id_size + 1)]), id, strlen (id));
i->last++;
printf ("cstruct : index add last = %d\n", i->last);
return 1;
}
int
index_get (struct index *i, char **id, int pos)
{
*id = (char *) malloc (strlen (&(i->id[pos * (i->id_size + 1)])) + 1);
memset (*id, 0, strlen (&(i->id[pos * (i->id_size + 1)])) + 1);
strncpy (*id, &(i->id[pos * (i->id_size + 1)]),
strlen (&(i->id[pos * (i->id_size + 1)])));
return 1;
}
/* special function for oid list */
int
oidList_New (struct oidList *o, int list_size)
{
o->last = 0;
o->len = list_size;
o->list = (int *) malloc (8 * o->len * sizeof (int));
return 1;
}
int
oidList_Append (struct oidList *o, int oid[8])
{
int i;
if (o->last > o->len)
return 0;
for (i = 0; i < 8; i++)
o->list[o->last * 8 + i] = oid[i];
o->last++;
return 1;
}
int
oidList_GetItem (struct oidList *o, int oid[8], int pos)
{
int i;
if (pos > o->last)
return 0;
for (i = 0; i < 8; i++)
oid[i] = o->list[pos * 8 + i];
return 1;
}
int
oidList_Free (struct oidList *o)
{
free (o->list);
return 1;
}
/* new structure function */
int
stringList_New (struct stringList *o, u_int32_t list_size,
u_int32_t item_size)
{
o->last = 0;
o->len = list_size;
o->item_size = item_size;
o->list = (char *) malloc (o->len * (o->item_size + 1));
memset (o->list, 0, o->len * (o->item_size + 1));
return 1;
}
int
stringList_Append (struct stringList *o, char *item)
{
if (o->last > o->len)
return 0;
strncpy (&(o->list[o->last * (o->item_size + 1)]), item, o->item_size);
o->last++;
return 1;
}
int
stringList_GetItem (struct stringList *o, char **item, u_int32_t pos)
{
if (pos > o->last)
return 0;
*item = (char *) malloc (o->item_size + 1);
memset (*item, 0, o->item_size + 1);
strncpy (*item, &(o->list[pos * (o->item_size + 1)]), o->item_size);
return 1;
}
int
stringList_Free (struct stringList *o)
{
if (o->list != NULL)
free (o->list);
return 1;
}
int
objectList_New (struct objectList *o, u_int32_t list_size)
{
o->len = list_size;
o->last = 0;
o->list = (struct object *) malloc (sizeof (struct object) * list_size);
return 1;
}
int
objectList_Append (struct objectList *o, u_int64_t oid,
u_int64_t serial, char *data)
{
o->list[o->last].oid = oid;
o->list[o->last].serial = serial;
o->list[o->last].data = (char *) malloc (strlen (data) + 1);
memset (o->list[o->last].data, 0, strlen (data) + 1);
strncpy (o->list[o->last].data, data, strlen (data));
o->last++;
return 1;
}
int
objectList_Free (struct objectList *o)
{
u_int32_t i;
for (i = 0; i < o->last; i++)
free (o->list[i].data);
free (o->list);
return 1;
}
int
transaction_New (struct transaction *t, u_int64_t tid, u_int32_t nb_objects)
{
printf ("sizeof %d, %d\n", sizeof (tid), sizeof (t->tid));
t->tid = tid;
objectList_New (&(t->objects), nb_objects);
return 1;
}
int
transaction_AppendObject (struct transaction *t, u_int64_t oid,
u_int64_t serial)
{
if (!objectList_Append (&(t->objects), oid, serial, ""))
return 0;
return 1;
}
int
transaction_Free (struct transaction *t)
{
objectList_Free (&(t->objects));
return 1;
}
/* list of transaction */
int
transactionList_New (struct transactionList *t, u_int32_t nb_txn)
{
t->len = nb_txn;
t->last = 0;
t->txn =
(struct transaction *) malloc (sizeof (struct transaction) * nb_txn);
return 1;
}
int
transactionList_Append (struct transactionList *t, u_int64_t tid,
struct objectList o)
{
u_int32_t object_nb;
t->txn[t->last].tid = tid;
objectList_New (&t->txn[t->last].objects, o.last);
for (object_nb = 0; object_nb < o.last; object_nb++)
objectList_Append (&t->txn[t->last].objects, o.list[object_nb].oid,
o.list[object_nb].serial, o.list[object_nb].data);
t->last++;
return 1;
}
int
transactionList_Free (struct transactionList *t)
{
u_int32_t txn_nb;
for (txn_nb = 0; txn_nb < t->last; txn_nb++)
objectList_Free (&t->txn[txn_nb].objects);
free (t->txn);
return 1;
}
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "neo_struct.h"
/* int */
/* inc_tid (u_int16_t tid[ID_LEN], int pos) */
/* { */
/* /\* printf ("inc_tid : pos %d, %d\n", pos, tid[pos]); *\/ */
/* tid[pos]++; */
/* /\* printf ("inc %d\n", tid[pos]); *\/ */
/* if (tid[pos] > 255) */
/* { */
/* tid[pos] = 0; */
/* if (pos >= 0) */
/* inc_tid (tid, pos - 1); */
/* else */
/* { */
/* printf ("no more tid left to generate\n"); */
/* return 0; */
/* } */
/* } */
/* return 1; */
/* } */
int
generate_tid (u_int16_t ntid[ID_LEN], u_int16_t ltid[ID_LEN])
{
int i;
time_t epoch_time;
struct tm *gm_time;
u_int32_t v;
double sconv = 0;
unsigned char new_tid[ID_LEN], last_tid[ID_LEN];
/* generate time */
time (&epoch_time);
gm_time = (struct tm *) malloc (sizeof (struct tm));
gm_time = gmtime (&epoch_time);
/* create an integer array */
v =
((((gm_time->tm_year) * 12 + gm_time->tm_mon) * 31 +
gm_time->tm_mday - 1) * 24 + gm_time->tm_hour) * 60 + gm_time->tm_min;
ntid[0] = v / 16777216;
ntid[1] = (v % 16777216) / 65536;
ntid[2] = (v % 65536) / 256;
ntid[3] = v % 256;
gm_time->tm_sec /= sconv;
v = (u_int32_t) epoch_time % 60;
ntid[4] = v / 16777216;
ntid[5] = (v % 16777216) / 65536;
ntid[6] = (v % 65536) / 256;
ntid[7] = v % 256;
compare:
/* create the string array */
for (i = 0; i < ID_LEN; i++)
{
new_tid[i] = (unsigned char)ntid[i];
last_tid[i] = (unsigned char)ltid[i];
}
if (memcmp (new_tid, last_tid, ID_LEN) > 0)
return 1;
for (i = ID_LEN - 1; i > 3; i--)
{
if (ntid[i] == 255)
ntid[i] = 0;
else
{
ntid[i]++;
goto compare;
}
}
printf ("oups must finish compare function...\n");
return 0;
}
MYSQL_LDFLAGS = @MYSQL_LDFLAGS@
MYSQL_INCLUDE = @MYSQL_INCLUDE@
MYSQL_LIBS = @MYSQL_LIBS@
AM_CFLAGS = -Wall -W
AM_CPPFLAGS = -I${top_srcdir}/include ${MYSQL_INCLUDE}
LDADD = -lneo -lstdc++ ${MYSQL_LIBS}
AM_LDFLAGS = ${MYSQL_LDFLAGS} -L../lib
bin_PROGRAMS = neomaster
neomaster_SOURCES = master_return.c master_request.c master_node.c \
master_return.h master_request.h
# Makefile.in generated by automake 1.7.9 from Makefile.am.
# @configure_input@
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
# Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
ACLOCAL = @ACLOCAL@
AMDEP_FALSE = @AMDEP_FALSE@
AMDEP_TRUE = @AMDEP_TRUE@
AMTAR = @AMTAR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
MAKEINFO = @MAKEINFO@
MYSQL_CONFIG = @MYSQL_CONFIG@
MYSQL_INCLUDE = @MYSQL_INCLUDE@
MYSQL_LDFLAGS = @MYSQL_LDFLAGS@
MYSQL_LIBS = @MYSQL_LIBS@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PYTHON = @PYTHON@
PYTHON_BASECFLAGS = @PYTHON_BASECFLAGS@
PYTHON_CC = @PYTHON_CC@
PYTHON_CCSHARED = @PYTHON_CCSHARED@
PYTHON_INCLUDE = @PYTHON_INCLUDE@
PYTHON_LDSHARED = @PYTHON_LDSHARED@
PYTHON_OPT = @PYTHON_OPT@
PYTHON_SO = @PYTHON_SO@
RANLIB = @RANLIB@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
ac_ct_CC = @ac_ct_CC@
ac_ct_RANLIB = @ac_ct_RANLIB@
ac_ct_STRIP = @ac_ct_STRIP@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
bindir = @bindir@
build_alias = @build_alias@
datadir = @datadir@
exec_prefix = @exec_prefix@
host_alias = @host_alias@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localstatedir = @localstatedir@
mandir = @mandir@
oldincludedir = @oldincludedir@
prefix = @prefix@
program_transform_name = @program_transform_name@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
AM_CFLAGS = -Wall -W
AM_CPPFLAGS = -I${top_srcdir}/include ${MYSQL_INCLUDE}
LDADD = -lneo -lstdc++ ${MYSQL_LIBS}
AM_LDFLAGS = ${MYSQL_LDFLAGS} -L../lib
bin_PROGRAMS = neomaster
neomaster_SOURCES = master_return.c master_request.c master_node.c \
master_return.h master_request.h
subdir = master
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
bin_PROGRAMS = neomaster$(EXEEXT)
PROGRAMS = $(bin_PROGRAMS)
am_neomaster_OBJECTS = master_return.$(OBJEXT) master_request.$(OBJEXT) \
master_node.$(OBJEXT)
neomaster_OBJECTS = $(am_neomaster_OBJECTS)
neomaster_LDADD = $(LDADD)
neomaster_DEPENDENCIES =
neomaster_LDFLAGS =
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/master_node.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/master_request.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/master_return.Po
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
DIST_SOURCES = $(neomaster_SOURCES)
DIST_COMMON = $(srcdir)/Makefile.in Makefile.am
SOURCES = $(neomaster_SOURCES)
all: all-am
.SUFFIXES:
.SUFFIXES: .c .o .obj
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4)
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu master/Makefile
Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
install-binPROGRAMS: $(bin_PROGRAMS)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(bindir)
@list='$(bin_PROGRAMS)'; for p in $$list; do \
p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
if test -f $$p \
; then \
f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) $$p $(DESTDIR)$(bindir)/$$f"; \
$(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) $$p $(DESTDIR)$(bindir)/$$f || exit 1; \
else :; fi; \
done
uninstall-binPROGRAMS:
@$(NORMAL_UNINSTALL)
@list='$(bin_PROGRAMS)'; for p in $$list; do \
f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
echo " rm -f $(DESTDIR)$(bindir)/$$f"; \
rm -f $(DESTDIR)$(bindir)/$$f; \
done
clean-binPROGRAMS:
-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
neomaster$(EXEEXT): $(neomaster_OBJECTS) $(neomaster_DEPENDENCIES)
@rm -f neomaster$(EXEEXT)
$(LINK) $(neomaster_LDFLAGS) $(neomaster_OBJECTS) $(neomaster_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT) core *.core
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/master_node.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/master_request.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/master_return.Po@am__quote@
.c.o:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
@am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \
@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
@am__fastdepCC_TRUE@ fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$<
.c.obj:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
@am__fastdepCC_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \
@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
@am__fastdepCC_TRUE@ fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`
uninstall-info-am:
ETAGS = etags
ETAGSFLAGS =
CTAGS = ctags
CTAGSFLAGS =
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
mkid -fID $$unique
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)$$tags$$unique" \
|| $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$tags $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& cd $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) $$here
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
top_distdir = ..
distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
list='$(DISTFILES)'; for file in $$list; do \
case $$file in \
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
esac; \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkinstalldirs) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(PROGRAMS)
installdirs:
$(mkinstalldirs) $(DESTDIR)$(bindir)
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-am
dvi-am:
info: info-am
info-am:
install-data-am:
install-exec-am: install-binPROGRAMS
install-info: install-info-am
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-binPROGRAMS uninstall-info-am
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
clean-generic ctags distclean distclean-compile \
distclean-generic distclean-tags distdir dvi dvi-am info \
info-am install install-am install-binPROGRAMS install-data \
install-data-am install-exec install-exec-am install-info \
install-info-am install-man install-strip installcheck \
installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
uninstall-am uninstall-binPROGRAMS uninstall-info-am
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
#include <pthread.h>
#include <stdio.h>
#include <sys/types.h>
#include <netdb.h>
#include <signal.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <uuid/uuid.h>
#include <time.h>
#include <syslog.h>
#include <getopt.h>
#include "neo_mysql.h"
#include "neo_socket.h"
#include "neo_struct.h"
#include "master_request.h"
#include "master_return.h"
#include "timestamp.h"
#define MASTER_ID_FILE "master_id.txt" /* file that store the master id */
#define MASTER_DATA_FILE "master_data.txt" /* file that store the last tid and oid generated by master */
#define DEFAULT_REPLICATION_NB 2
enum mutex
{
OID_GENERATION,
LTID,
STORAGES_IDX,
REPLICATION,
DB
};
static int master_ready = 0; /* boolean indicating if enought storage are ready to handle clients */
static int create_db = 0; /* flag to know if we must start with a new database */
static int ascii[ID_LEN]; /* last oid generated */
static int soc = -1;
static uuid_t master_id;
static char ID[UUID_LEN+1]; /* uuid is unparse into a 36 byte string */
static u_int64_t ltid; /* store last transaction id */
static u_int16_t last_generated_tid[ID_LEN]; /* last generated tid, use to check if tid increases */
static u_int16_t replication_nb = DEFAULT_REPLICATION_NB; /* number of replication for a transaction on storages nodes */
static u_int16_t last_storage_replication; /* id of the last storage node used for replication */
static struct storageInfo DBinfo; /* store informations about storage system */
static struct database *db;
static struct stringList *storage_index;
char database_dir[BUF_SIZE]; /* path to the mysql db dir */
/* definition and function for mutex */
static pthread_mutex_t mutex_storages_index = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t mutex_ltid = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t mutex_replication = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t mutex_db = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t mutex_oid = PTHREAD_MUTEX_INITIALIZER;
static int
init_mutex ()
{
pthread_mutex_init (&mutex_storages_index, NULL);
pthread_mutex_init (&mutex_ltid, NULL);
pthread_mutex_init (&mutex_replication, NULL);
pthread_mutex_init (&mutex_db, NULL);
pthread_mutex_init (&mutex_oid, NULL);
return 1;
}
static int
lock (int mutex)
{
if (mutex == STORAGES_IDX)
pthread_mutex_lock (&mutex_storages_index);
else if (mutex == LTID)
pthread_mutex_lock (&mutex_ltid);
else if (mutex == REPLICATION)
pthread_mutex_lock (&mutex_replication);
else if (mutex == DB)
pthread_mutex_lock (&mutex_db);
else if (mutex == OID_GENERATION)
pthread_mutex_lock (&mutex_oid);
else
{
perror ("mutex lock");
return 0;
}
return 1;
}
static int
unlock (int mutex)
{
if (mutex == STORAGES_IDX)
pthread_mutex_unlock (&mutex_storages_index);
else if (mutex == LTID)
pthread_mutex_unlock (&mutex_ltid);
else if (mutex == REPLICATION)
pthread_mutex_unlock (&mutex_replication);
else if (mutex == DB)
pthread_mutex_unlock (&mutex_db);
else if (mutex == OID_GENERATION)
pthread_mutex_unlock (&mutex_oid);
else
{
perror ("mutex unlock");
return 0;
}
return 1;
}
/* handler called when master close */
static void
cleanup_handler (int sig)
{
char *storage_id = NULL, *client_id = NULL;
struct nlist *lstorages = NULL, *lclients = NULL;
u_int32_t i;
FILE *fd;
/* must store last oid and tid */
fd = fopen (MASTER_DATA_FILE, "w");
fwrite (ascii, sizeof (int), 8, fd);
fwrite (last_generated_tid, sizeof (u_int16_t), 8, fd);
fclose (fd);
/* send message of master close to all storages first */
lock (DB);
if (database_master_get_all_storages_infos (db, &lstorages) == 1)
{
for (i = 0; i < lstorages->last; i++)
{
if (masterClose
(lstorages->objects[i].addr, lstorages->objects[i].port,
MASTER_CLOSE, ID, &storage_id))
{
database_master_close_storage (db, storage_id);
free (storage_id);
}
}
}
/* send to all clients too */
if (database_master_get_all_clients_infos (db, &lclients) == 1)
for (i = 0; i < lclients->last; i++)
{
if (masterClose (lclients->objects[i].addr, lclients->objects[i].port,
MASTER_CLOSE, ID, &client_id))
free (client_id);
}
database_close (db);
unlock (DB);
if (lstorages != NULL)
{
free_nlist (lstorages);
free (lstorages);
}
if (lclients != NULL)
{
free_nlist (lclients);
free (lclients);
}
free (DBinfo.ext);
if (soc >= 0)
close (soc);
syslog (LOG_MAKEPRI (LOG_USER, LOG_NOTICE), "Close master");
closelog ();
exit (0);
}
/**
* function that generates a new oid,
* in zope oid are 8-bytes string, each new oid
* increase the ascii code of this string.
* here we only use an integer array which store the ascii code,
* the translation in string is made by the client
*/
static int
generate_oid (int pos)
{
ascii[pos]++;
if (ascii[pos] > 255)
{
ascii[pos] = 0;
if (pos >= 0)
generate_oid (pos - 1);
else
return 0;
}
return 1;
}
/**
* function that return the list of all transaction and object
* stored by this storage as known by the master. Storage node
* check if all is Ok
*/
static int
send_storage_index (int conn, char id[UUID_LEN+1])
{
struct transactionList *txn = NULL;
u_int64_t nb_txn = 0;
/* XXX must return packet to storage even when sthong failed */
lock (DB);
if (!database_master_get_storage_index (db, id, &txn, &nb_txn))
{
unlock (DB);
return 0;
}
unlock (DB);
if (!returnStorageIndex (conn, STORAGE_INDEX, txn))
{
if (txn != NULL)
{
transactionList_Free (txn);
free (txn);
}
return 0;
}
if (txn != NULL)
{
transactionList_Free (txn);
free (txn);
}
return 1;
}
/**
* function that returns to the unreliable storage
* transactions id that were stored by this storage and
* the list of the others storages which stores the
* same transaction
*/
static int
make_storage_clean (int conn, char storage_id[UUID_LEN+1])
{
struct tlist *tid_list = NULL;
lock (DB);
if (!database_master_get_trans_list (db, storage_id, &tid_list))
{
unlock (DB);
return 0;
}
unlock (DB);
if (!returnStorageSanity (conn, SANITY_CHECK, *tid_list))
{
if (tid_list != NULL)
free_tlist (tid_list);
return 0;
}
if (tid_list != NULL)
free_tlist (tid_list);
return 1;
}
/**
* function that creates the storage index list used
* to give storage node for transaction
*/
static int
create_index (void)
{
/* free memory */
if (storage_index != NULL)
{
stringList_Free (storage_index);
free (storage_index);
storage_index = NULL;
}
/* create index */
storage_index = (struct stringList *) malloc (sizeof (struct stringList));
if (!storage_index)
return 0;
database_master_create_storage_index (db, &storage_index);
return 1;
}
/* functions calleb by clients or storages */
static int
h_getObjectByOid (int conn, char *hbuf)
{
char rflags[FLAG_LEN], *buf = NULL;
u_int64_t oid, serial;
u_int32_t len = 0, data_len = 0;
int res;
struct stringList *storages = NULL;
/* header */
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
buf = (char *) malloc (data_len);
if (!buf)
goto fail;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
goto fail;
}
oid = ntohll (*((u_int64_t *) (buf)));
lock (DB);
if ((res =
database_master_get_object_by_oid (db, oid, &serial, &storages)) == -1)
{ /* oid not found */
unlock (DB);
free (buf);
returnErrorMessage (conn, GET_OBJECT_BY_OID, OID_NOT_FOUND,
"not found");
return 1;
}
else if (res == 0)
{
unlock (DB);
goto fail;
}
unlock (DB);
if (!returnGetObjectByOid (conn, GET_OBJECT_BY_OID, serial, *storages))
goto fail;
if (storages != NULL)
{
stringList_Free (storages);
free (storages);
}
free (buf);
return 1;
fail:
if (storages != NULL)
{
stringList_Free (storages);
free (storages);
}
if (buf != NULL)
free (buf);
returnErrorMessage (conn, GET_OBJECT_BY_OID, TMP_FAILURE,
"Error on master node");
return 1;
}
static int
h_getObjectBySerial (int conn, char *hbuf)
{
u_int64_t oid, serial;
u_int32_t len = 0, data_len = 0;
char rflags[FLAG_LEN], *buf;
int res;
struct stringList *storages = NULL;
/* header */
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
buf = (char *) malloc (data_len);
if (!buf)
goto fail;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
goto fail;
}
oid = ntohll (*((u_int64_t *) (buf)));
serial = ntohll (*((u_int64_t *) (buf + INT64_LEN)));
lock (DB);
if ((res =
database_master_get_object_by_serial (db, oid, serial,
&storages)) == -1)
{ /* serial not found */
unlock (DB);
free (buf);
returnErrorMessage (conn, GET_OBJECT_BY_SERIAL, SERIAL_NOT_FOUND,
"not found");
return 1;
}
else if (res == 0)
{
unlock (DB);
goto fail;
}
unlock (DB);
if (!returnGetObjectBySerial (conn, GET_OBJECT_BY_SERIAL, *storages))
goto fail;
if (storages != NULL)
{
stringList_Free (storages);
free (storages);
}
free (buf);
return 1;
fail:
if (storages != NULL)
{
stringList_Free (storages);
free (storages);
}
if (buf != NULL)
free (buf);
returnErrorMessage (conn, GET_OBJECT_BY_SERIAL, TMP_FAILURE,
"Error on master node");
return 1;
}
static int
h_getSerial (int conn, char *hbuf)
{
u_int64_t oid, serial;
u_int32_t len = 0, data_len = 0;
int res;
char rflags[FLAG_LEN], *buf = NULL;
/* header */
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
buf = (char *) malloc (data_len);
if (!buf)
goto fail;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
goto fail;
}
oid = ntohll (*((u_int64_t *) (buf)));
lock (DB);
if ((res = database_master_get_serial (db, oid, &serial)) == -1)
{
unlock (DB);
free (buf);
returnErrorMessage (conn, GET_SERIAL, OID_NOT_FOUND, "not found");
return 1;
}
else if (res == 0)
{
unlock (DB);
goto fail;
}
unlock (DB);
if (!returnGetSerial (conn, GET_SERIAL, serial))
goto fail;
free (buf);
return 1;
fail:
if (buf != NULL)
free (buf);
returnErrorMessage (conn, GET_SERIAL, TMP_FAILURE, "Error on master node");
return 1;
}
static int
h_getLastTransaction (int conn, char *hbuf)
{
char rflags[FLAG_LEN], *buf = NULL;
u_int32_t len = 0, data_len = 0;
/* header */
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
buf = (char *) malloc (data_len);
if (!buf)
goto fail;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
goto fail;
}
lock (LTID);
if (!returnGetLastTransaction (conn, GET_LAST_TRANS, ltid))
goto fail;
unlock (LTID);
free (buf);
return 1;
fail:
unlock (LTID);
if (buf != NULL)
free (buf);
returnErrorMessage (conn, GET_LAST_TRANS, TMP_FAILURE,
"Error on master node");
return 1;
}
static int
h_getOid (int conn, char *hbuf)
{
struct oidList list;
u_int16_t oid_nb, i;
u_int32_t len = 0, data_len = 0;
char rflags[FLAG_LEN], *buf = NULL;
/* header */
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
buf = (char *) malloc (data_len);
if (!buf)
goto fail;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
goto fail;
}
oid_nb = ntohs (*((u_int16_t *) (buf)));
if (oid_nb > 20) /* limit number of oid send */
oid_nb = 20;
oidList_New (&list, oid_nb);
lock (OID_GENERATION);
for (i = 0; i < oid_nb; i++)
{
if (generate_oid (7))
oidList_Append (&list, ascii);
else
returnErrorMessage (conn, GET_OID, TMP_FAILURE, "No more oid left");
}
unlock (OID_GENERATION);
if (!returnGetOidInt (conn, GET_OID, list))
goto fail;
oidList_Free (&list);
free (buf);
return 1;
fail:
if (buf != NULL)
free (buf);
returnErrorMessage (conn, GET_OID, TMP_FAILURE, "Error on master node");
return 1;
}
static int
h_getTransSN (int conn, char *hbuf)
{
char rflags[FLAG_LEN], *buf = NULL;
int16_t first, last;
u_int32_t len = 0, data_len = 0;
struct tlist *tl = NULL;
/* header */
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
buf = (char *) malloc (data_len);
if (!buf)
goto fail;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
goto fail;
}
first = ntohs (*((int16_t *) (buf)));
last = ntohs (*((int16_t *) (buf + INT16_LEN)));
/* return list of storage for each trans between first and last */
lock (DB);
if (!database_master_get_trans_storages (db, ltid, first, last, &tl))
{
unlock (DB);
goto fail;
}
unlock (DB);
if (!returnGetTransSN (conn, GET_TRANS_SN, *tl))
goto fail;
if (tl != NULL)
{
free_tlist (tl);
free (tl);
}
free (buf);
return 1;
fail:
if (tl != NULL)
{
free_tlist (tl);
free (tl);
}
if (buf != NULL)
free (buf);
returnErrorMessage (conn, GET_TRANS_SN, TMP_FAILURE,
"Error on master node");
return 1;
}
static int
h_getObjectHist (int conn, char *hbuf)
{
u_int64_t oid;
u_int32_t len = 0, data_len = 0, length;
char rflags[FLAG_LEN], *buf = NULL;
struct tlist *hist = NULL;
clock_t c1, c2;
float t;
static float time = 0;
/* header */
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
buf = (char *) malloc (data_len);
if (!buf)
goto fail;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
goto fail;
}
oid = ntohll (*((u_int64_t *) (buf)));
length = ntohs (*((u_int16_t *) (buf + INT64_LEN)));
lock (DB);
if (!database_master_get_object_hist (db, oid, length, &hist))
{
unlock (DB);
goto fail;
}
unlock (DB);
c1 = clock();
if (!returnGetObjectHist (conn, GET_OBJECT_HIST, *hist))
goto fail;
c2 = clock();
t = (float)(c2 - c1) / CLOCKS_PER_SEC;
time += t;
if (t > 0)
printf ("return time : %f, time %f\n", t, time);
if (hist != NULL)
{
free_tlist (hist);
free (hist);
}
free (buf);
return 1;
fail:
if (buf != NULL)
free (buf);
if (hist != NULL)
{
free_tlist (hist);
free (hist);
}
returnErrorMessage (conn, GET_OBJECT_HIST, TMP_FAILURE,
"Error on master node");
return 1;
}
static int
h_undoTrans (int conn, char *hbuf)
{
u_int64_t tid;
u_int32_t len = 0, data_len = 0;
int res;
char rflags[FLAG_LEN], *buf = NULL;
struct stringList *storages = NULL;
/* header */
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
buf = (char *) malloc (data_len);
if (!buf)
goto fail;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
goto fail;
}
tid = ntohll (*((u_int64_t *) (buf)));
lock (DB);
if ((res = database_master_undo_trans (db, tid, &storages)) == 0)
{
unlock (DB);
goto fail;
}
else if (res == -1) /* unknown tid */
{
unlock (DB);
free (buf);
returnErrorMessage (conn, UNDO_TRANS, TRANS_NOT_FOUND, "tid not found");
return 1;
}
unlock (DB);
if (!returnUndoTrans (conn, UNDO_TRANS, *storages))
goto fail;
if (storages != NULL)
{
stringList_Free (storages);
free (storages);
}
free (buf);
return 1;
fail:
if (storages != NULL)
{
stringList_Free (storages);
free (storages);
}
if (buf != NULL)
free (buf);
returnErrorMessage (conn, UNDO_TRANS, TMP_FAILURE, "Error on master node");
return 1;
}
static int
h_beginTrans (int conn, char *hbuf)
{
u_int64_t tid;
u_int32_t len = 0, data_len = 0, i;
char rflags[FLAG_LEN], *buf = NULL, *id = NULL;
u_int16_t s[ID_LEN];
struct stringList storages;
/* header */
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
buf = (char *) malloc (data_len);
if (!buf)
goto fail;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
goto fail;
}
tid = ntohll (*((u_int64_t *) (buf)));
/* generate tid if tid is null... */
tid:
if (!generate_tid (s, last_generated_tid))
goto tid;
/* use rotation to generate the random storages list */
stringList_New (&storages, replication_nb, UUID_LEN);
lock (REPLICATION);
lock (STORAGES_IDX);
/* XXX must check len of storage index to avoid work without storage ready */
for (i = 0; i < replication_nb; i++)
{
stringList_GetItem (storage_index, &id, last_storage_replication);
/* add storage id to list */
stringList_Append (&storages, id);
free (id);
/* next storage */
last_storage_replication++;
if (last_storage_replication >= storage_index->last)
last_storage_replication = 0;
}
unlock (STORAGES_IDX);
unlock (REPLICATION);
if (!returnBeginTrans (conn, BEGIN_TRANS, s, storages))
goto fail;
/* save new tid */
for (i = 0; i < ID_LEN; i++)
last_generated_tid[i] = s[i];
stringList_Free (&storages);
free (buf);
return 1;
fail:
stringList_Free (&storages);
if (buf != NULL)
free (buf);
returnErrorMessage (conn, BEGIN_TRANS, TMP_FAILURE, "Error on master node");
return 1;
}
static int
h_endTrans (int conn, char *hbuf)
{
u_int64_t tid, oid, serial;
u_int32_t len = 0, data_len = 0, i, j, oid_nb, storage_nb;
char rflags[FLAG_LEN], storage_id[UUID_LEN + 1], *buf = NULL;
struct stringList storage;
/* header */
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
buf = (char *) malloc (data_len);
if (!buf)
goto fail;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
goto fail;
}
/* get tid */
tid = ntohll (*((u_int64_t *) (buf)));
len = INT64_LEN;
/* get list of storage */
storage_nb = ntohl (*((u_int32_t *) (buf + len)));
len += INT32_LEN;
if (storage_nb > replication_nb) /* strange */
return 1;
stringList_New (&storage, storage_nb, UUID_LEN);
memset (storage_id, 0, UUID_LEN + 1);
for (i = 0; i < storage_nb; i++)
{
memcpy (storage_id, buf + len, UUID_LEN);
len += UUID_LEN;
stringList_Append (&storage, storage_id);
}
/* store trans */
lock (DB);
if (!database_master_begin_trans (db, tid, ltid, storage))
{
unlock (DB);
stringList_Free (&storage);
goto fail;
}
unlock (DB);
stringList_Free (&storage);
oid_nb = ntohl (*((u_int32_t *) (buf + len)));
/* get oids for the transaction and store them */
len += INT32_LEN;
for (i = 0; i < oid_nb; i++)
{
oid = ntohll (*((u_int64_t *) (buf + len)));
len += INT64_LEN;
serial = ntohll (*((u_int64_t *) (buf + len)));
len += INT64_LEN;
/* add metadata for object into database */
lock (DB);
if (!(database_master_put_object (db, tid, oid, serial)))
{ /* transaction not valid */
len -= INT64_LEN * 2 * (i + 1); /* go back to the beginning of the oid list */
for (j = 0; j < i; j++) /* delete previous object we register */
{
oid = ntohll (*((u_int64_t *) (buf + len)));
len += INT64_LEN;
database_master_delete_object (db, oid, tid);
}
unlock (DB);
returnErrorMessage (conn, END_TRANS, TRANS_NOT_VALID,
"invalid version of object ");
return 1;
}
unlock (DB);
}
lock (DB);
/* change status for transaction */
if (!database_master_end_trans (db, tid))
{
unlock (DB);
goto fail;
}
unlock (DB);
/* update last tid */
lock (LTID);
ltid = tid;
unlock (LTID);
if (!returnEndTrans (conn, END_TRANS))
goto fail;
free (buf);
return 1;
fail:
if (buf != NULL)
free (buf);
returnErrorMessage (conn, END_TRANS, TMP_FAILURE, "Error on master node");
return 1;
}
static int
h_getAllSN (int conn, char *hbuf)
{
u_int32_t len = 0, data_len = 0;
int res;
char rflags[FLAG_LEN], *buf = NULL;
struct nlist *lnodes = NULL;
/* header */
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
buf = (char *) malloc (data_len);
if (!buf)
goto fail;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
goto fail;
}
lock (DB);
res = database_master_get_all_storages_infos (db, &lnodes);
if (res == 0)
{
unlock (DB);
goto fail;
}
else if (res == -1)
{
returnErrorMessage (conn, GET_ALL_SN, TMP_FAILURE, "No storage ready");
unlock (DB);
return 1;
}
unlock (DB);
if (!returnGetAllSN (conn, GET_ALL_SN, *lnodes))
goto fail;
free (buf);
if (lnodes != NULL)
{
free_nlist (lnodes);
free (lnodes);
}
return 1;
fail:
if (buf != NULL)
free (buf);
if (lnodes != NULL)
{
free_nlist (lnodes);
free (lnodes);
}
returnErrorMessage (conn, GET_ALL_SN, TMP_FAILURE, "Error on master node");
return 1;
}
static int
h_getAllCN (int conn, char *hbuf)
{
u_int32_t len = 0, data_len = 0;
char rflags[FLAG_LEN], *buf = NULL;
struct nlist *lnodes = NULL;
/* header */
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
buf = (char *) malloc (data_len);
if (!buf)
goto fail;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
goto fail;
}
lock (DB);
if (!database_master_get_all_clients_infos (db, &lnodes))
{
unlock (DB);
goto fail;
}
unlock (DB);
if (!returnGetAllCN (conn, GET_ALL_CN, *lnodes))
goto fail;
free (buf);
if (lnodes != NULL)
{
free_nlist (lnodes);
free (lnodes);
}
return 1;
fail:
if (buf != NULL)
free (buf);
if (lnodes != NULL)
{
free_nlist (lnodes);
free (lnodes);
}
returnErrorMessage (conn, GET_ALL_CN, TMP_FAILURE, "Error on master node");
return 1;
}
static int
h_getSNInfo (int conn, char *hbuf) /* XXX not used */
{
u_int32_t len = 0, data_len = 0;
char rflags[FLAG_LEN], *ip = NULL, *buf = NULL, id[UUID_LEN + 1];
u_int16_t port;
/* header */
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
buf = (char *) malloc (data_len);
if (!buf)
goto fail;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
goto fail;
}
memset (id, 0, UUID_LEN + 1);
memcpy (id, buf, UUID_LEN);
lock (DB);
if (!database_master_get_storage_infos (db, id, &ip, &port))
{
unlock (DB);
goto fail;
}
unlock (DB);
/* if (!returnGetSNInfo (conn, 17, ip, port)) */
/* goto fail; */
free (buf);
return 1;
fail:
if (buf != NULL)
free (buf);
returnErrorMessage (conn, GET_SN_INFO, TMP_FAILURE, "Error on master node");
return 1;
}
static int
h_failure (int conn, char *hbuf)
{
u_int32_t len = 0, data_len = 0, i;
char rflags[FLAG_LEN], id[UUID_LEN + 1], *buf;
struct nlist *lclients;
/* header */
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
buf = (char *) malloc (data_len);
if (!buf)
return 0;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
{
free (buf);
return 1; /* XXX what to do ? */
}
}
memset (id, 0, UUID_LEN + 1);
memcpy (id, buf, UUID_LEN);
free (buf);
/**
* either test to connect to storage,
* either trust client and mark storage as unreliable
*/
syslog (LOG_MAKEPRI (LOG_USER, LOG_WARNING),
"storage %s is reported as unreliable", id);
database_master_unreliable_storage (db, id);
/* send del storage to all clients */
lock (DB);
if (database_master_get_all_clients_infos (db, &lclients) == 1)
for (i = 0; i < lclients->last; i++)
delStorage (lclients->objects[i].addr, lclients->objects[i].port,
DEL_SN, id);
unlock (DB);
return 1;
}
static int
h_clientClose (int conn, char *hbuf) /* done */
{
u_int16_t i;
u_int32_t len = 0, data_len = 0;
char rflags[FLAG_LEN], id[UUID_LEN + 1], *buf = NULL;
struct nlist *lclients = NULL;
/* header */
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
buf = (char *) malloc (data_len);
if (!buf)
goto fail;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
goto fail;
}
memset (id, 0, UUID_LEN + 1);
memcpy (id, buf, UUID_LEN);
lock (DB);
if (!database_master_delete_client (db, id))
{
unlock (DB);
goto fail;
}
/* send message of del client to all other client */
if (database_master_get_all_clients_infos (db, &lclients) == 1)
{
unlock (DB);
for (i = 0; i < lclients->last; i++)
if (strncmp (lclients->objects[i].id, id, UUID_LEN) != 0)
delClient (lclients->objects[i].addr, lclients->objects[i].port,
DEL_CN, id);
}
else
unlock (DB);
/* XXX must change to test if error */
if (lclients != NULL)
{
free_nlist (lclients);
free (lclients);
}
free (buf);
return 1;
fail:
if (lclients != NULL)
{
free_nlist (lclients);
free (lclients);
}
if (buf != NULL)
free (buf);
returnErrorMessage (conn, CLIENT_CLOSE, TMP_FAILURE,
"Error on master node");
return 1;
}
static int
h_storageClose (int conn, char *hbuf)
{
u_int16_t i;
u_int32_t len = 0, data_len = 0;
char rflags[FLAG_LEN], id[UUID_LEN+1], *buf = NULL;
struct nlist *lclients = NULL;
/* header */
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
buf = (char *) malloc (data_len);
if (!buf)
goto fail;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
goto fail;
}
memset (id, 0, UUID_LEN + 1);
memcpy (id, buf, UUID_LEN);
lock (DB);
if (!database_master_close_storage (db, id))
{ /* XXX must change and retry to close storage... */
unlock (DB);
goto fail;
}
/* remove storage from index */
lock (STORAGES_IDX);
create_index ();
unlock (STORAGES_IDX);
/* send message of del storage to all clients */
if (database_master_get_all_clients_infos (db, &lclients) == 1)
for (i = 0; i < lclients->last; i++)
delStorage (lclients->objects[i].addr, lclients->objects[i].port,
DEL_SN, id);
unlock (DB);
if (lclients != NULL)
{
free_nlist (lclients);
free (lclients);
}
free (buf);
return 1;
fail:
if (lclients != NULL)
{
free_nlist (lclients);
free (lclients);
}
if (buf != NULL)
free (buf);
returnErrorMessage (conn, STORAGE_CLOSE, TMP_FAILURE,
"Error on master node");
return 1;
}
static int
h_storageStart (int conn, char *hbuf)
{
u_int16_t port, status = 0;
u_int32_t len = 0, data_len = 0;
char rflags[FLAG_LEN], id[UUID_LEN+1], ip[IP_LEN];
char *buf = NULL, *sock_ip = NULL;
/* header */
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
buf = (char *) malloc (data_len);
if (!buf)
goto fail;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
goto fail;
}
/* id */
memset (id, 0, UUID_LEN + 1);
memcpy (id, buf, UUID_LEN);
/* ip */
memset (ip, 0, IP_LEN + 1);
memcpy (ip, buf + UUID_LEN, IP_LEN);
/* port */
port = ntohs (*((u_int16_t *) (buf + UUID_LEN + IP_LEN)));
if (port == 0) /* trying to add strange storage */
return 1;
/* XXX make better test */
if (!getIp (conn, &sock_ip))
perror("storage starting");
/* update or store information about the storage node */
lock (DB);
if (!database_master_storage_starting (db, id, sock_ip, port, &status))
{
unlock (DB);
goto fail;
}
unlock (DB);
if (status == 2) /*storage unreliable */
{
if (!returnStorageStart (conn, STORAGE_START, ID, status))
goto fail;
/* then send data to storage in order to get back its sanity */
make_storage_clean (conn, id);
}
else if (status == 1)
{
if (!returnStorageStart (conn, STORAGE_START, ID, status))
goto fail;
/* send index to make the storage check */
send_storage_index (conn, id);
}
else if (!returnStorageStart (conn, STORAGE_START, ID, status))
goto fail;
free (buf);
return 1;
fail:
if (buf != NULL)
free (buf);
if (sock_ip != NULL)
free (sock_ip);
returnErrorMessage (conn, STORAGE_START, TMP_FAILURE,
"Error on master node");
return 1;
}
static int
h_storageReady (int conn, char *hbuf)
{
char rflags[FLAG_LEN];
u_int32_t len = 0, data_len = 0, j;
u_int16_t port;
char *ip = NULL, *buf = NULL, storage_id[UUID_LEN + 1];
struct nlist *lclients = NULL;
/* header */
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
buf = (char *) malloc (data_len);
if (!buf)
goto fail;
while (len < data_len)
if (!fill_buffer (conn, buf, &len, data_len - len))
goto fail;
/* storage id */
memset (storage_id, 0, UUID_LEN + 1);
memcpy (storage_id, buf, UUID_LEN);
/* change status to ok */
lock (DB);
if (!database_master_storage_ready (db, storage_id))
{
unlock (DB);
goto fail;
}
/* add storage into index */
lock (STORAGES_IDX);
create_index ();
unlock (STORAGES_IDX);
master_ready = 1;
/* check if master is ready */
/* if (!master_ready) */
/* { */
/* if (!database_master_all_objects_accessible(db)) */
/* /\* master not ready *\/ */
/* master_ready = 0; */
/* else */
/* master_ready = 1; */
/* } */
/* Get infos for the storage */
if (!database_master_get_storage_infos (db, storage_id, &ip, &port))
{
unlock (DB);
goto fail;
}
/* send message to all clients to add storage */
if (database_master_get_all_clients_infos (db, &lclients) == 1)
{
for (j = 0; j < lclients->last; j++)
addStorage (lclients->objects[j].addr, lclients->objects[j].port,
ADD_SN, storage_id, ip, port);
}
unlock (DB);
if (lclients != NULL)
{
free_nlist (lclients);
free (lclients);
}
free (buf);
if (ip != NULL)
free (ip);
return 1;
fail:
if (lclients != NULL)
{
free_nlist (lclients);
free (lclients);
}
if (buf != NULL)
free (buf);
if (ip != NULL)
free (ip);
returnErrorMessage (conn, STORAGE_READY, TMP_FAILURE,
"Error on master node");
return 1;
}
static int
h_clientStart (int conn, char *hbuf)
{
u_int16_t port;
u_int32_t len = 0, data_len = 0, i;
char rflags[FLAG_LEN];
char ip[IP_LEN + 1], id[UUID_LEN + 1], *buf = NULL;
struct nlist *lclients = NULL;
/* header */
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
buf = (char *) malloc (data_len);
if (!buf)
goto fail;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
goto fail;
}
/* must check if master is ready otherwise dont take message into account */
if (!master_ready)
{
returnErrorMessage (conn, CLIENT_START, NOT_READY,
"Not all objects accessible");
return 1;
}
/* id */
memset (id, 0, UUID_LEN + 1);
memcpy (id, buf, UUID_LEN);
/* ip */
memset (ip, 0, IP_LEN + 1);
memcpy (ip, buf + UUID_LEN, IP_LEN);
/* port */
port = ntohs (*((u_int16_t *) (buf + UUID_LEN + IP_LEN)));
if (port == 0)
return 1;
/* add client into database */
lock (DB);
if (!database_master_start_client (db, id, ip, port, conn))
{
unlock (DB);
goto fail;
}
/* send message to add client to all other clients */
if (!database_master_get_all_clients_infos (db, &lclients))
{
unlock (DB);
goto fail;
}
unlock (DB);
for (i = 0; i < lclients->last; i++)
if (strncmp (lclients->objects[i].id, id, ID_LEN) != 0)
addClient (lclients->objects[i].addr, lclients->objects[i].port, ADD_CN,
id, ip, port);
/* send database info to client */
if (!returnClientStart (conn, CLIENT_START, DBinfo))
goto fail;
if (lclients != NULL)
{
free_nlist (lclients);
free (lclients);
}
free (buf);
return 1;
fail:
if (lclients != NULL)
{
free_nlist (lclients);
free (lclients);
}
if (buf != NULL)
free (buf);
returnErrorMessage (conn, CLIENT_START, TMP_FAILURE,
"Error on master node");
return 1;
}
static int
h_getStorageForTrans (int conn, char *hbuf)
{
char rflags[FLAG_LEN];
u_int64_t tid;
u_int32_t len = 0, data_len = 0;
char *buf = NULL, storage_id[UUID_LEN + 1];
struct stringList *storages = NULL;
/* header */
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
buf = (char *) malloc (data_len);
if (!buf)
goto fail;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
goto fail;
}
memset (storage_id, 0, UUID_LEN + 1);
memcpy (storage_id, buf, UUID_LEN);
tid = ntohll (*((u_int64_t *) (buf + UUID_LEN)));
lock (DB);
if (!database_master_get_storages_for_trans
(db, tid, storage_id, &storages))
{
unlock (DB);
goto fail;
}
unlock (DB);
if (!returnGetStorageForTrans (conn, GET_STORAGE_FOR_TRANS, *storages))
goto fail;
free (buf);
return 1;
fail:
if (buf != NULL)
free (buf);
returnErrorMessage (conn, GET_STORAGE_FOR_TRANS, TMP_FAILURE,
"Error on master node");
return 1;
}
/* function that handle each new connection and call the appropriate function */
static void *
client_handler (void *data)
{
int conn;
char buf[HEADER_LEN];
u_int32_t buf_len = 0;
u_int16_t method;
database_thread_init ();
conn = *((int *) data);
while (1)
{
buf_len = 0;
if (!fill_buffer (conn, buf, &buf_len, 8))
goto fail;
method = ntohs (*((u_int16_t *) (buf)));
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "client %d call method %d",
conn, method);
switch (method)
{
case GET_OBJECT_BY_OID:
if (!h_getObjectByOid (conn, buf))
goto fail;
break;
case GET_OBJECT_BY_SERIAL:
if (!h_getObjectBySerial (conn, buf))
goto fail;
break;
case GET_SERIAL:
if (!h_getSerial (conn, buf))
goto fail;
break;
case GET_LAST_TRANS:
if (!h_getLastTransaction (conn, buf))
goto fail;
break;
case GET_OID:
if (!h_getOid (conn, buf))
goto fail;
break;
case GET_TRANS_SN:
if (!h_getTransSN (conn, buf))
goto fail;
break;
case GET_OBJECT_HIST:
if (!h_getObjectHist (conn, buf))
goto fail;
break;
case UNDO_TRANS:
if (!h_undoTrans (conn, buf))
goto fail;
break;
case BEGIN_TRANS:
if (!h_beginTrans (conn, buf))
goto fail;
break;
case END_TRANS:
if (!h_endTrans (conn, buf))
goto fail;
break;
case GET_ALL_SN:
if (!h_getAllSN (conn, buf))
goto fail;
break;
case GET_ALL_CN:
if (!h_getAllCN (conn, buf))
goto fail;
break;
case GET_SN_INFO:
if (!h_getSNInfo (conn, buf))
goto fail;
break;
case FAILURE:
if (!h_failure (conn, buf))
goto fail;
break;
case CLIENT_CLOSE:
h_clientClose (conn, buf);
goto end;
break;
case STORAGE_CLOSE:
h_storageClose (conn, buf);
goto end;
break;
case STORAGE_START:
if (!h_storageStart (conn, buf))
goto end;
break;
case STORAGE_READY:
h_storageReady (conn, buf);
goto end;
break;
case GET_STORAGE_FOR_TRANS:
if (!h_getStorageForTrans (conn, buf))
goto fail;
break;
case CLIENT_START:
if (!h_clientStart (conn, buf))
goto fail;
break;
}
}
fail:
lock(DB);
database_master_remove_client (db, conn);
unlock(DB);
end:
syslog (LOG_MAKEPRI (LOG_USER, LOG_INFO), "End of connection %d", conn);
database_thread_end ();
close (conn);
free (data);
return NULL;
}
/*
* thread which is a udp server, used for the automatic discovery
* of master node by storages and client
*/
static void *
udp_server(void *data)
{
int soc, rcode;
int bd = 1;
u_int16_t meth;
u_int32_t data_len;
ssize_t received, send;
struct sockaddr_in addr;
char rcv_buf[HEADER_LEN], send_buf[RHEADER_LEN];
/* create server */
soc = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);
setsockopt (soc, SOL_SOCKET, SO_BROADCAST, (int *) &bd, sizeof (bd));
addr.sin_family = AF_INET;
addr.sin_port = htons (10825);
addr.sin_addr.s_addr = htonl (INADDR_ANY);
bind(soc,(struct sockaddr *)&addr,sizeof addr);
/* prebuild a response packet */
meth = htons (SEARCH_MASTER);
data_len = htonl(0);
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
while (1)
{
struct sockaddr_in client_addr;
int size = sizeof (client_addr);
/* wait for a packet */
memset (rcv_buf, 0, HEADER_LEN);
received = recvfrom (soc, rcv_buf, HEADER_LEN, 0, (struct sockaddr *) &client_addr, &size);
/* check packet */
if ((ntohs (*((u_int16_t *) (rcv_buf)))) != SEARCH_MASTER)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_WARNING), "return method error");
rcode = htons (METHOD_ERROR);
memcpy (send_buf + INT16_LEN + FLAG_LEN + INT32_LEN, &rcode, INT16_LEN);
send = sendto (soc, (char *)send_buf, RHEADER_LEN, 0, (struct sockaddr *) &client_addr, size);
continue;
}
/* send response */
rcode = 0;
memcpy (send_buf + INT16_LEN + FLAG_LEN + INT32_LEN, &rcode, INT16_LEN);
send = sendto (soc, (char *)send_buf, RHEADER_LEN, 0, (struct sockaddr *) &client_addr, size);
}
close(soc);
}
/* function that generate a uuid and store it on disk */
static int
generate_id ()
{
FILE *fid;
memset (ID, 0, UUID_LEN + 1);
/* check if a uuid ever exists */
if ((fid = fopen (MASTER_ID_FILE, "r")) != NULL)
{
fread (ID, UUID_LEN, 1, fid);
uuid_parse (ID, master_id);
fclose (fid);
return 1;
}
/* otherwise generate uuid */
uuid_generate (master_id);
uuid_unparse (master_id, ID);
/* store it on disk */
fid = fopen (MASTER_ID_FILE, "w");
fwrite (ID, UUID_LEN, 1, fid);
fclose (fid);
return 1;
}
int
parse_arg (int argc, char **argv)
{
int c, option_index = 0;
while (1)
{
static struct option long_options[] = {
{"log-level", required_argument, 0, 'l'},
{"create-database", no_argument, 0, 'c'},
{"replications", required_argument, 0, 'r'},
{"database", required_argument, 0, 'd'},
{0, 0, 0, 0}
};
option_index = 0;
c = getopt_long (argc, argv, "cl:d:r:", long_options, &option_index);
/* Detect the end of the options. */
if (c == -1)
break;
switch (c)
{
case 'c':
create_db = 1;
break;
case 'l':
switch (atoi (optarg))
{
case 3:
setlogmask (LOG_UPTO (LOG_DEBUG));
break;
case 2:
setlogmask (LOG_UPTO (LOG_INFO));
break;
case 1:
setlogmask (LOG_UPTO (LOG_NOTICE));
break;
}
break;
case 'r':
replication_nb = atoi (optarg);
break;
case 'd':
strncpy (database_dir, optarg, BUF_SIZE-1);
break;
case '?':
/* getopt_long already printed an error message. */
break;
default:
abort ();
}
}
/* Print any remaining command line arguments (not options). */
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
putchar ('\n');
return 0;
}
return 1;
}
int
main (int argc, char **argv)
{
struct sockaddr_in addr;
pthread_attr_t attr;
pthread_t udp_th;
int r, reuse = 1, i;
FILE *fd;
signal (SIGINT, cleanup_handler);
signal (SIGTERM, cleanup_handler);
signal (SIGSEGV, cleanup_handler);
/* default init */
setlogmask (LOG_UPTO (LOG_ERR));
strncpy (database_dir, "./db", BUF_SIZE-1);
if (!parse_arg (argc, argv))
return -1;
/* open syslog */
openlog ("neomaster", 0, 0);
if (!generate_id ())
goto fail;
syslog (LOG_MAKEPRI (LOG_USER, LOG_NOTICE), "id : %s", ID);
/* open database */
if ((db = database_master_open (create_db)) == 0)
goto fail;
syslog (LOG_MAKEPRI (LOG_USER, LOG_NOTICE),
"connection to database opened");
/* init info */
DBinfo.name = (char *) malloc (sizeof ("Neo") + 1);
memset (DBinfo.name, 0, sizeof ("Neo") + 1);
strcpy (DBinfo.name, "Neo");
DBinfo.supportVersion = 0;
DBinfo.supportUndo = 1;
DBinfo.supportTransUndo = 1;
DBinfo.readOnly = 0;
DBinfo.ext = (char *) malloc (sizeof (" ") + 1);
memset (DBinfo.ext, 0, sizeof (" ") + 1);
strcpy (DBinfo.ext, " ");
/* init for oid and tid generation */
if (!create_db)
{
fd = fopen (MASTER_DATA_FILE, "r");
fread (ascii, sizeof (int), 8, fd);
fread (last_generated_tid, sizeof (u_int16_t), 8, fd);
fclose (fd);
}
else
{
for (i = 0; i < ID_LEN; i++)
{
ascii[i] = 0;
last_generated_tid[i] = 0;
}
}
ltid = 0;
/* init storages index */
storage_index = NULL;
last_storage_replication = 0;
/* set thread */
init_mutex ();
if (pthread_attr_init (&attr) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "pthread_attr_init %s",
strerror (errno));
goto fail;
}
if (pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR),
"pthread_attr_setdetachedstate %s", strerror (errno));
goto fail;
}
/* create udp server */
if (pthread_create (&udp_th, &attr, udp_server, NULL) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "pthread_create forudp server %s",
strerror (errno));
goto fail;
}
/* create socket to listen */
soc = socket (PF_INET, SOCK_STREAM, 0);
if (soc < 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "socket %s", strerror (errno));
goto fail;
}
r =
setsockopt (soc, SOL_SOCKET, SO_REUSEADDR, (int *) &reuse,
sizeof (reuse));
if (r == -1)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "setsockopt %s",
strerror (errno));
}
addr.sin_family = AF_INET;
addr.sin_port = htons (MASTER_PORT);
addr.sin_addr.s_addr = htonl (INADDR_ANY);
if (bind (soc, (struct sockaddr *) &addr, sizeof (addr)) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "bind %s", strerror (errno));
goto fail;
}
if (listen (soc, 5) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "listen %s", strerror (errno));
goto fail;
}
syslog (LOG_MAKEPRI (LOG_USER, LOG_NOTICE), "listening on port %d",
MASTER_PORT);
while (1)
{
int *connp;
pthread_t th;
/* XXX not optimal */
connp = (int *) malloc (sizeof (int));
if (!connp)
{
perror ("malloc");
goto fail;
}
*connp = accept (soc, 0, 0);
if (*connp < 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "accept %s",
strerror (errno));
free (connp);
goto fail;
}
syslog (LOG_MAKEPRI (LOG_USER, LOG_INFO),
"New client connected with %d", *connp);
if (pthread_create (&th, &attr, client_handler, connp) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "pthread_create %s",
strerror (errno));
free (connp);
goto fail;
}
}
fail:
free (DBinfo.ext);
if (soc >= 0)
close (soc);
database_close (db);
syslog (LOG_MAKEPRI (LOG_USER, LOG_NOTICE), "Close master");
closelog ();
return 1;
}
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <stdio.h>
#include "neo_socket.h"
#include "neo_struct.h"
#include "master_request.h"
int
masterClose (char node_ip[IP_LEN], u_int16_t node_port, int method,
char master_id[UUID_LEN], char **node_id)
{
u_int32_t buf_len, data_len, meth;
u_int16_t conn;
char *send_buf;
u_int32_t len = 0;
char buf[BUF_SIZE];
u_int16_t return_code;
char rflags[2];
/* send request to nodes */
meth = htons (method);
data_len = htonl (UUID_LEN);
send_buf = (char *) malloc (HEADER_LEN + UUID_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
/* data */
memcpy (send_buf + HEADER_LEN, master_id, UUID_LEN);
if (!(conn = connectTo (node_ip, node_port)))
return 0;
if (!send_all (conn, send_buf, HEADER_LEN + UUID_LEN))
{
free (send_buf);
return 0;
}
free (send_buf);
/* wait response from nodes */
buf_len = 0, data_len = 0;
if (!wait_packet (conn, buf, &buf_len, RHEADER_LEN))
return 0;
if ((ntohs (*((u_int16_t *) (buf)))) != method)
{
perror ("receive");
return 0;
}
memcpy (rflags, buf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (buf + INT16_LEN + FLAG_LEN)));
return_code =
ntohs (*((u_int16_t *) (buf + INT16_LEN + FLAG_LEN + INT32_LEN)));
len = buf_len - RHEADER_LEN;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
return 0;
}
*node_id = (char *) malloc (UUID_LEN + 1);
memset (*node_id, 0, UUID_LEN + 1);
memcpy (*node_id, buf, UUID_LEN);
return 1;
}
char *
masterChange (char node_ip[IP_LEN], u_int16_t node_port, int method,
char id[UUID_LEN], char ip[IP_LEN], u_int16_t port)
{
u_int32_t buf_len, data_len, meth, rlen = 0;
u_int16_t len, conn, n_port;
char *send_buf;
char buf[BUF_SIZE];
u_int16_t return_code;
char *idr;
char rflags[2];
/* send request to client */
meth = htons (method);
data_len = htonl (UUID_LEN + IP_LEN + INT16_LEN);
send_buf = (char *) malloc (HEADER_LEN + UUID_LEN + IP_LEN + INT16_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
/* data */
memcpy (send_buf + HEADER_LEN, id, UUID_LEN);
len = HEADER_LEN + UUID_LEN;
memcpy (send_buf + HEADER_LEN, ip, IP_LEN);
len += IP_LEN;
n_port = htons (port);
memcpy (send_buf + len, &n_port, INT16_LEN);
if (!(conn = connectTo (node_ip, node_port)))
return 0;
if (!send_all (conn, send_buf, HEADER_LEN + UUID_LEN + IP_LEN + INT16_LEN))
{
free (send_buf);
return NULL;
}
free (send_buf);
/* wait response from nodes */
buf_len = 0, data_len = 0;
if (!wait_packet (conn, buf, &buf_len, RHEADER_LEN))
return 0;
if ((ntohs (*((u_int16_t *) (buf)))) != method)
{
perror ("receive");
return 0;
}
memcpy (rflags, buf + 2, 2);
data_len = ntohl (*((u_int32_t *) (buf + 4)));
return_code = ntohs (*((u_int16_t *) (buf + 8)));
rlen = buf_len - 10;
while (rlen < data_len)
{
if (!fill_buffer (conn, buf, &rlen, data_len - rlen))
return 0;
}
close (conn);
idr = (char *) malloc (UUID_LEN + 1);
memset (idr, 0, UUID_LEN + 1);
memcpy (idr, buf, UUID_LEN);
return idr;
}
int
addStorage (char node_ip[IP_LEN], u_int16_t node_port, int method,
char storage_id[UUID_LEN], char storage_ip[IP_LEN],
u_int16_t storage_port)
{
u_int32_t data_len, conn;
u_int16_t len, meth, n_storage_port;
char *send_buf;
if (!(conn = connectTo (node_ip, node_port)))
return 0;
/* send request to client */
meth = htons (method);
data_len = htonl (UUID_LEN + IP_LEN + INT16_LEN);
send_buf = (char *) malloc (HEADER_LEN + UUID_LEN + IP_LEN + INT16_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
/* data */
len = HEADER_LEN;
memcpy (send_buf + len, storage_id, UUID_LEN);
len += UUID_LEN;
strncpy (send_buf + len, storage_ip, IP_LEN);
len += IP_LEN;
n_storage_port = htons (storage_port);
memcpy (send_buf + len, &n_storage_port, INT16_LEN);
if (!send_all (conn, send_buf, HEADER_LEN + UUID_LEN + IP_LEN + INT16_LEN))
{
free (send_buf);
return 0;
}
free (send_buf);
close (conn);
return 1;
}
int
addClient (char node_ip[IP_LEN], u_int16_t node_port, int method,
char client_id[UUID_LEN], char client_ip[IP_LEN],
u_int16_t client_port)
{
u_int32_t data_len, conn;
u_int16_t len, meth, n_client_port;
char *send_buf;
if (!(conn = connectTo (node_ip, node_port)))
return 0;
/* send request to client */
meth = htons (method);
data_len = htonl (UUID_LEN + IP_LEN + INT16_LEN);
send_buf = (char *) malloc (HEADER_LEN + UUID_LEN + IP_LEN + INT16_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
/* data */
len = HEADER_LEN;
memcpy (send_buf + len, client_id, UUID_LEN);
len += UUID_LEN;
memcpy (send_buf + len, client_ip, IP_LEN);
len += IP_LEN;
n_client_port = htons (client_port);
memcpy (send_buf + len, &n_client_port, INT16_LEN);
if (!send_all (conn, send_buf, HEADER_LEN + UUID_LEN + IP_LEN + INT16_LEN))
{
free (send_buf);
return 0;
}
free (send_buf);
close (conn);
return 1;
}
int
delStorage (char node_ip[IP_LEN], u_int16_t node_port, int method,
char storage_id[UUID_LEN])
{
u_int32_t data_len, conn;
u_int16_t meth;
char *send_buf;
if (!(conn = connectTo (node_ip, node_port)))
return 0;
/* send request to client */
meth = htons (method);
data_len = htonl (UUID_LEN);
send_buf = (char *) malloc (HEADER_LEN + UUID_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
/* data */
memcpy (send_buf + HEADER_LEN, storage_id, UUID_LEN);
if (!send_all (conn, send_buf, HEADER_LEN + UUID_LEN))
{
free (send_buf);
return 0;
}
free (send_buf);
close (conn);
return 1;
}
int
delClient (char node_ip[IP_LEN], u_int16_t node_port, int method,
char client_id[UUID_LEN])
{
u_int32_t data_len, conn;
u_int16_t meth;
char *send_buf;
if (!(conn = connectTo (node_ip, node_port)))
return 0;
/* send request to client */
meth = htons (method);
data_len = htonl (UUID_LEN);
send_buf = (char *) malloc (HEADER_LEN + UUID_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
/* data */
memcpy (send_buf + HEADER_LEN, client_id, UUID_LEN);
if (!send_all (conn, send_buf, HEADER_LEN + UUID_LEN))
{
free (send_buf);
return 0;
}
free (send_buf);
close (conn);
return 1;
}
/* int */
/* unreliableStorage (char *ip, int port, int method, char *id) */
/* { */
/* u_int32_t buf_len, data_len, conn; */
/* u_int16_t id_len, meth; */
/* char *send_buf; */
/* conn = connectTo (ip, port); */
/* /\* send request to client *\/ */
/* meth = htons (method); */
/* data_len = htonl (2 + strlen (id)); */
/* id_len = htons (strlen (id)); */
/* buf_len = HEADER_LEN + ntohl (data_len); */
/* send_buf = (char *) malloc (buf_len); */
/* /\* header *\/ */
/* memcpy (send_buf, &meth, INT16_LEN); */
/* memcpy (send_buf + INT16_LEN, flags, FLAG_LEN); */
/* memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN); */
/* memcpy (send_buf, &meth, 2); */
/* memcpy (send_buf + 2, flags, 2); */
/* memcpy (send_buf + 4, &data_len, 4); */
/* /\* data *\/ */
/* memcpy (send_buf + 8, &id_len, 2); */
/* memcpy (send_buf + 10, id, strlen (id)); */
/* if (!send_all (conn, send_buf, buf_len)) */
/* { */
/* free (send_buf); */
/* return 0; */
/* } */
/* free (send_buf); */
/* close (conn); */
/* return 1; */
/* } */
#ifndef master_request_h
#define master_request_h
#include "neo_struct.h"
int masterClose (char node_ip[IP_LEN], u_int16_t node_port, int method,
char master_id[UUID_LEN], char **storage_id);
char *masterChange (char node_ip[IP_LEN], u_int16_t node_port, int method,
char master_ip[IP_LEN], char master_id[UUID_LEN],
u_int16_t master_port);
int addStorage (char node_ip[IP_LEN], u_int16_t node_port, int method,
char storage_id[UUID_LEN], char storage_ip[IP_LEN],
u_int16_t storage_port);
int addClient (char node_ip[IP_LEN], u_int16_t node_port, int method,
char client_id[UUID_LEN], char client_ip[IP_LEN],
u_int16_t client_port);
int delStorage (char node_ip[IP_LEN], u_int16_t node_port, int method,
char storage_id[UUID_LEN]);
int delClient (char node_ip[IP_LEN], u_int16_t node_port, int method,
char client_id[UUID_LEN]);
/* int unreliableStorage (char *ip, int port, int method, char *id); */
#endif
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/syslog.h>
#include "neo_socket.h"
#include "neo_struct.h"
#include "master_return.h"
static u_int16_t rcode = 0;
int
returnGetObjectByOid (int conn, int method, u_int64_t serial,
struct stringList storages)
{
u_int64_t n_serial;
u_int32_t data_len, n_nb_storage, i;
u_int16_t meth;
char *send_buf, *id;
int len = 0;
meth = htons (method);
/* compute len */
n_nb_storage = htonl (storages.last);
data_len = htonl (storages.last * UUID_LEN + INT64_LEN + INT32_LEN);
send_buf =
(char *) malloc (RHEADER_LEN + storages.last * UUID_LEN + INT64_LEN +
INT32_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN + INT32_LEN, &rcode, INT16_LEN);
/* data */
n_serial = htonll (serial);
memcpy (send_buf + RHEADER_LEN, &n_serial, INT64_LEN);
len += RHEADER_LEN + INT64_LEN;
memcpy (send_buf + len, &n_nb_storage, INT32_LEN);
len += INT32_LEN;
/* storage list */
for (i = 0; i < storages.last; i++)
{
stringList_GetItem (&storages, &id, i);
memcpy (send_buf + len, id, UUID_LEN);
free (id);
len += UUID_LEN;
}
if (!send_all
(conn, send_buf,
RHEADER_LEN + storages.last * UUID_LEN + INT64_LEN + INT32_LEN))
{
free (send_buf);
return 0;
}
free (send_buf);
return 1;
}
int
returnGetObjectBySerial (int conn, int method, struct stringList storages)
{
u_int32_t data_len, n_nb_storage, i;
u_int16_t meth;
char *send_buf, *id;
int len = 0;
meth = htons (method);
/* compute len */
data_len = htonl (storages.last * UUID_LEN + INT32_LEN);
send_buf =
(char *) malloc (RHEADER_LEN + storages.last * UUID_LEN + INT32_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN + INT32_LEN, &rcode, INT16_LEN);
/* data */
n_nb_storage = htonl (storages.last);
memcpy (send_buf + RHEADER_LEN, &n_nb_storage, INT32_LEN);
len = RHEADER_LEN + INT32_LEN;
/* list of storages */
for (i = 0; i < storages.last; i++)
{
stringList_GetItem (&storages, &id, i);
memcpy (send_buf + len, id, UUID_LEN);
free (id);
len += UUID_LEN;
}
if (!send_all
(conn, send_buf, RHEADER_LEN + storages.last * UUID_LEN + INT32_LEN))
{
free (send_buf);
return 0;
}
free (send_buf);
return 1;
}
int
returnGetSerial (int conn, int method, u_int64_t serial)
{
u_int64_t n_serial;
u_int32_t data_len;
u_int16_t meth;
char *send_buf;
meth = htons (method);
data_len = htonl (INT64_LEN);
send_buf = (char *) malloc (RHEADER_LEN + INT64_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN + INT32_LEN, &rcode, INT16_LEN);
/* serial */
n_serial = htonll (serial);
memcpy (send_buf + RHEADER_LEN, &n_serial, INT64_LEN);
if (!send_all (conn, send_buf, RHEADER_LEN + INT64_LEN))
{
free (send_buf);
return 0;
}
free (send_buf);
return 1;
}
int
returnGetLastTransaction (int conn, int method, u_int64_t tid)
{
u_int64_t n_tid;
u_int32_t buf_len, data_len;
u_int16_t meth;
char *send_buf;
meth = htons (method);
data_len = htonl (INT64_LEN);
buf_len = RHEADER_LEN + ntohl (data_len);
send_buf = (char *) malloc (buf_len);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN + INT32_LEN, &rcode, INT16_LEN);
/* data */
n_tid = htonll (tid);
memcpy (send_buf + RHEADER_LEN, &n_tid, INT64_LEN);
if (!send_all (conn, send_buf, RHEADER_LEN + INT64_LEN))
{
free (send_buf);
return 0;
}
free (send_buf);
return 1;
}
int
returnGetOidInt (int conn, int method, struct oidList list)
{
u_int32_t buf_len, data_len;
u_int16_t meth, net_int, n_nb_oid, i, j;
char *send_buf;
int tlen = 0, oid[8];
meth = htons (method);
data_len = htonl (list.last * ID_LEN * INT16_LEN + INT16_LEN);
buf_len = RHEADER_LEN + ntohl (data_len);
send_buf = (char *) malloc (buf_len);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN + INT32_LEN, &rcode, INT16_LEN);
/* data */
n_nb_oid = htons (list.last);
memcpy (send_buf + 10, &n_nb_oid, INT16_LEN);
/* list of oid */
tlen = RHEADER_LEN + INT16_LEN;
for (i = 0; i < list.last; i++)
{
oidList_GetItem (&list, oid, i);
for (j = 0; j < ID_LEN; j++)
{
net_int = htons (oid[j]);
memcpy (send_buf + tlen, &net_int, INT16_LEN);
tlen += INT16_LEN;
}
}
if (!send_all (conn, send_buf, buf_len))
{
free (send_buf);
return 0;
}
free (send_buf);
return 1;
}
int
returnClientStart (int conn, int method, struct storageInfo info)
{
u_int32_t buf_len, data_len, meth;
u_int16_t name_len, ext_len, len, sV, sU, sTU, rO;
char *send_buf;
/* send information back */
meth = htons (method);
/* compute len */
data_len = htonl (strlen (info.name) + strlen (info.ext) + 12);
name_len = htons (strlen (info.name));
ext_len = htons (strlen (info.ext));
sV = htons (info.supportVersion);
sU = htons (info.supportUndo);
sTU = htons (info.supportTransUndo);
rO = htons (info.readOnly);
buf_len = RHEADER_LEN + ntohl (data_len);
send_buf = (char *) malloc (buf_len);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN + INT32_LEN, &rcode, INT16_LEN);
/* information about storage */
len = RHEADER_LEN;
memcpy (send_buf + len, &name_len, INT16_LEN);
len += INT16_LEN;
memcpy (send_buf + len, info.name, strlen (info.name));
len += strlen (info.name);
memcpy (send_buf + len, &sV, INT16_LEN);
len += INT16_LEN;
memcpy (send_buf + len, &sU, INT16_LEN);
len += INT16_LEN;
memcpy (send_buf + len, &sTU, INT16_LEN);
len += INT16_LEN;
memcpy (send_buf + len, &rO, INT16_LEN);
len += INT16_LEN;
memcpy (send_buf + len, &ext_len, INT16_LEN);
len += INT16_LEN;
memcpy (send_buf + len, info.ext, strlen (info.ext));
if (!send_all (conn, send_buf, buf_len))
{
free (send_buf);
return 0;
}
free (send_buf);
return 1;
}
int
returnGetTransSN (int conn, int method, struct tlist tl)
{
u_int64_t n_tid;
u_int32_t buf_len, data_len, j, len = 0, size = 0, n_nb_storage;
u_int16_t meth, n_nb_trans, i;
char *send_buf;
meth = htons (method);
/* compute len for each transaction */
for (i = 0; i < tl.last; i++)
size += tl.objects[i].list.last * UUID_LEN;
data_len = htonl (size + INT16_LEN + tl.last * (INT64_LEN + INT32_LEN));
buf_len =
RHEADER_LEN + size + INT16_LEN + tl.last * (INT64_LEN + INT32_LEN);
send_buf = (char *) malloc (buf_len);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN + INT32_LEN, &rcode, INT16_LEN);
/* data */
n_nb_trans = htons (tl.last);
memcpy (send_buf + RHEADER_LEN, &n_nb_trans, INT16_LEN);
/* list of transaction */
len = RHEADER_LEN + INT16_LEN;
for (i = 0; i < tl.last; i++)
{
/* tid */
n_tid = htonll (tl.objects[i].tid);
memcpy (send_buf + len, &n_tid, INT64_LEN);
len += INT64_LEN;
/* storage nb */
n_nb_storage = htonl (tl.objects[i].list.last);
memcpy (send_buf + len, &n_nb_storage, INT32_LEN);
len += INT32_LEN;
for (j = 0; j < tl.objects[i].list.last; j++)
{ /* storage id */
memcpy (send_buf + len, tl.objects[i].list.objects[j].data,
UUID_LEN);
len += UUID_LEN;
}
}
if (!send_all (conn, send_buf, buf_len))
{
free (send_buf);
return 0;
}
free (send_buf);
return 1;
}
int
returnGetObjectHist (int conn, int method, struct tlist tl)
{
u_int64_t n_serial;
u_int32_t buf_len, data_len, j, len = 0, size = 0, n_nb_storage;
u_int16_t meth, i, n_nb_trans;
char *send_buf;
meth = htons (method);
/* compute len , same as returnGetTransSN */
size = 0;
for (i = 0; i < tl.last; i++)
size += tl.objects[i].list.last * UUID_LEN;
data_len = htonl (size + INT16_LEN + tl.last * (INT64_LEN + INT32_LEN));
buf_len =
RHEADER_LEN + size + INT16_LEN + tl.last * (INT64_LEN + INT32_LEN);
send_buf = (char *) malloc (buf_len);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN + INT32_LEN, &rcode, INT16_LEN);
/* list of storages for each object entry */
n_nb_trans = htons (tl.last);
memcpy (send_buf + RHEADER_LEN, &n_nb_trans, INT16_LEN);
len = RHEADER_LEN + INT16_LEN;
for (i = 0; i < tl.last; i++)
{
/* serial */
n_serial = htonll (tl.objects[i].tid);
memcpy (send_buf + len, &n_serial, INT64_LEN);
len += INT64_LEN;
/* storage nb */
n_nb_storage = htonl (tl.objects[i].list.last);
memcpy (send_buf + len, &n_nb_storage, INT32_LEN);
len += INT32_LEN;
for (j = 0; j < tl.objects[i].list.last; j++)
{ /* storage id */
memcpy (send_buf + len, tl.objects[i].list.objects[j].data,
UUID_LEN);
len += UUID_LEN;
}
}
if (!send_all (conn, send_buf, buf_len))
{
free (send_buf);
return 0;
}
free (send_buf);
return 1;
}
int
returnUndoTrans (int conn, int method, struct stringList storages)
{
u_int32_t data_len, n_nb_storage, i;
u_int16_t meth;
char *send_buf, *id;
int len = 0;
meth = htons (method);
data_len = htonl (storages.last * UUID_LEN + INT32_LEN);
send_buf =
(char *) malloc (RHEADER_LEN + storages.last * UUID_LEN + INT32_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN + INT32_LEN, &rcode, INT16_LEN);
/* list of storages */
n_nb_storage = htonl (storages.last);
memcpy (send_buf + RHEADER_LEN, &n_nb_storage, INT32_LEN);
len = RHEADER_LEN + INT32_LEN;
for (i = 0; i < storages.last; i++)
{
stringList_GetItem (&storages, &id, i);
memcpy (send_buf + len, id, UUID_LEN);
free (id);
len += UUID_LEN;
}
if (!send_all
(conn, send_buf, RHEADER_LEN + storages.last * UUID_LEN + INT32_LEN))
{
free (send_buf);
return 0;
}
free (send_buf);
return 1;
}
int
returnBeginTrans (int conn, int method, u_int16_t tid[ID_LEN],
struct stringList storages)
{
u_int32_t buf_len, data_len, i, n_nb_storage;
u_int16_t meth, n_tid;
int len = 0;
char *send_buf, *oid;
meth = htons (method);
data_len =
htonl (storages.last * UUID_LEN + INT16_LEN * ID_LEN + INT32_LEN);
buf_len =
RHEADER_LEN + storages.last * UUID_LEN + INT16_LEN * ID_LEN + INT32_LEN;
send_buf = (char *) malloc (buf_len);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN + INT32_LEN, &rcode, INT16_LEN);
/* transaction id */
len = RHEADER_LEN;
for (i = 0; i < ID_LEN; i++)
{
n_tid = htons (tid[i]);
memcpy (send_buf + len, &n_tid, INT16_LEN);
len += INT16_LEN;
}
/* list of storages */
n_nb_storage = htonl (storages.last);
memcpy (send_buf + len, &n_nb_storage, INT32_LEN);
len += INT32_LEN;
for (i = 0; i < storages.last; i++)
{ /* storage id */
stringList_GetItem (&storages, &oid, i);
memcpy (send_buf + len, oid, UUID_LEN);
free (oid);
len += UUID_LEN;
}
if (!send_all (conn, send_buf, buf_len))
{
free (send_buf);
return 0;
}
free (send_buf);
return 1;
}
int
returnEndTrans (int conn, int method)
{
u_int32_t data_len;
u_int16_t meth;
char *send_buf;
meth = htons (method);
data_len = htonl (0);
send_buf = (char *) malloc (RHEADER_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN + INT32_LEN, &rcode, INT16_LEN);
if (!send_all (conn, send_buf, RHEADER_LEN))
{
free (send_buf);
return 0;
}
free (send_buf);
return 1;
}
int
returnGetAllSN (int conn, int method, struct nlist storages)
{
u_int32_t buf_len, data_len, n_nb_storage, i;
u_int16_t meth, n_port;
char *send_buf;
int len = 0;
meth = htons (method);
data_len =
htonl (storages.last * (UUID_LEN + IP_LEN + INT16_LEN) + INT32_LEN);
buf_len =
RHEADER_LEN + storages.last * (UUID_LEN + IP_LEN + INT16_LEN) + INT32_LEN;
send_buf = (char *) malloc (buf_len);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN + INT32_LEN, &rcode, INT16_LEN);
/* list of all storage nodes */
len = RHEADER_LEN;
n_nb_storage = htonl (storages.last);
memcpy (send_buf + len, &n_nb_storage, INT32_LEN);
len += INT32_LEN;
for (i = 0; i < storages.last; i++)
{
memcpy (send_buf + len, storages.objects[i].id, UUID_LEN);
len += UUID_LEN;
strncpy (send_buf + len, storages.objects[i].addr, IP_LEN);
/* memcpy (send_buf + len, storages.objects[i].addr, IP_LEN); */
len += IP_LEN;
n_port = htons (storages.objects[i].port);
memcpy (send_buf + len, &n_port, INT16_LEN);
len += INT16_LEN;
}
if (!send_all (conn, send_buf, buf_len))
{
free (send_buf);
return 0;
}
free (send_buf);
return 1;
}
int
returnGetAllCN (int conn, int method, struct nlist storages)
{
u_int32_t buf_len, data_len, n_nb_storage, i;
u_int16_t meth, n_port;
char *send_buf;
int len = 0;
meth = htons (method);
data_len =
htonl (storages.last * (UUID_LEN + IP_LEN + INT16_LEN) + INT32_LEN);
buf_len =
RHEADER_LEN + storages.last * (UUID_LEN + IP_LEN + INT16_LEN) + INT32_LEN;
send_buf = (char *) malloc (buf_len);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN + INT32_LEN, &rcode, INT16_LEN);
/* list of all client nodes */
n_nb_storage = htonl (storages.last);
memcpy (send_buf + 10, &n_nb_storage, INT32_LEN);
len = RHEADER_LEN + INT32_LEN;
for (i = 0; i < storages.last; i++)
{
memcpy (send_buf + len, storages.objects[i].id, UUID_LEN);
len += UUID_LEN;
strncpy (send_buf + len, storages.objects[i].addr, IP_LEN);
/* memcpy (send_buf + len, storages.objects[i].addr, IP_LEN); */
len += IP_LEN;
n_port = htons (storages.objects[i].port);
memcpy (send_buf + len, &n_port, INT16_LEN);
len += INT16_LEN;
}
if (!send_all (conn, send_buf, buf_len))
{
free (send_buf);
return 0;
}
free (send_buf);
return 1;
}
int
returnGetSNInfo (int conn, int method, struct node info)
{
u_int32_t buf_len, data_len, meth;
u_int16_t id_len, addr_len, len;
char *send_buf;
meth = htons (method);
addr_len = htons (strlen (info.addr));
id_len = htons (strlen (info.id));
data_len = htonl (2 + strlen (info.addr) + 2 + 2 + strlen (info.id));
buf_len = RHEADER_LEN + ntohl (data_len);
send_buf = (char *) malloc (buf_len);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN + INT32_LEN, &rcode, INT16_LEN);
/* header */
memcpy (send_buf, &meth, 2);
memcpy (send_buf + 2, flags, 2);
memcpy (send_buf + 4, &data_len, 4);
memcpy (send_buf + 8, &rcode, 2);
/* id, ip and port for a given storage */
len = 10;
memcpy (send_buf + len, &id_len, 2);
len += 2;
memcpy (send_buf + len, info.id, strlen (info.id));
len += strlen (info.id);
memcpy (send_buf + len, &addr_len, 2);
len += 2;
memcpy (send_buf + len, info.addr, strlen (info.addr));
len += strlen (info.addr);
memcpy (send_buf + len, &(info.port), 2);
if (!send_all (conn, send_buf, buf_len))
{
free (send_buf);
return 0;
}
free (send_buf);
return 1;
}
int
returnStorageStart (int conn, int method, char id[UUID_LEN], u_int16_t status)
{
u_int32_t data_len, meth;
u_int16_t n_status;
char *send_buf;
meth = htons (method);
data_len = htonl (UUID_LEN + INT16_LEN);
send_buf = (char *) malloc (RHEADER_LEN + UUID_LEN + INT16_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN + INT32_LEN, &rcode, INT16_LEN);
/* return master id */
memcpy (send_buf + RHEADER_LEN, id, UUID_LEN);
n_status = htons (status);
memcpy (send_buf + RHEADER_LEN + UUID_LEN, &n_status, INT16_LEN);
if (!send_all (conn, send_buf, RHEADER_LEN + UUID_LEN + INT16_LEN))
{
free (send_buf);
return 0;
}
free (send_buf);
return 1;
}
int
returnErrorMessage (int conn, int method, int code, char *message)
{
u_int32_t data_len;
u_int16_t n_msg_len, n_error_code, meth;
char *send_buf;
syslog (LOG_MAKEPRI (LOG_USER, LOG_WARNING),
"return error message for conn %d : method %d and code %d", conn,
method, code);
meth = htons (method);
data_len = htonl (INT16_LEN + strlen (message));
send_buf = (char *) malloc (RHEADER_LEN + INT16_LEN + strlen (message));
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
n_error_code = htons (code);
memcpy (send_buf + INT16_LEN + FLAG_LEN + INT32_LEN, &n_error_code,
INT16_LEN);
/* error message */
n_msg_len = htons (strlen (message));
memcpy (send_buf + RHEADER_LEN, &n_msg_len, INT16_LEN);
memcpy (send_buf + RHEADER_LEN + INT16_LEN, message, strlen (message));
if (!send_all (conn, send_buf, RHEADER_LEN + INT16_LEN + strlen (message)))
{
free (send_buf);
return 0;
}
free (send_buf);
return 1;
}
int
returnStorageSanity (int conn, int method, struct tlist tl)
{
u_int64_t n_tid;
u_int32_t data_len, n_nb_trans, size = 0, len, n_nb_storage;
u_int16_t meth, i, j, n_port;
char *send_buf;
meth = htons (method);
/* compute len , same as returnGetTransSN */
for (i = 0; i < tl.last; i++)
size +=
tl.objects[i].list.last * (IP_LEN + INT16_LEN) + INT64_LEN + INT32_LEN;
data_len = htonl (INT32_LEN + size);
send_buf = (char *) malloc (RHEADER_LEN + INT32_LEN + size);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN + INT32_LEN, &rcode, INT16_LEN);
/* list of storages for each transaction */
n_nb_trans = htonl (tl.last);
memcpy (send_buf + RHEADER_LEN, &n_nb_trans, INT32_LEN);
len = RHEADER_LEN + INT32_LEN;
for (i = 0; i < tl.last; i++)
{
/* transaction id */
n_tid = htonll (tl.objects[i].tid);
memcpy (send_buf + len, &n_tid, INT64_LEN);
len += INT64_LEN;
/* storage nb */
n_nb_storage = htonl (tl.objects[i].list.last / 2);
memcpy (send_buf + len, &n_nb_storage, INT32_LEN);
len += INT32_LEN;
for (j = 0; j < tl.objects[i].list.last; j++)
{ /* storage ip */
memcpy (send_buf + len, tl.objects[i].list.objects[j].data, IP_LEN);
len += IP_LEN;
j++;
/* storage port */
n_port =
htons (strtol (tl.objects[i].list.objects[j].data, NULL, 10));
memcpy (send_buf + len, &n_port, INT16_LEN);
len += INT16_LEN;
}
}
if (!send_all (conn, send_buf, RHEADER_LEN + INT32_LEN + size))
{
free (send_buf);
return 0;
}
free (send_buf);
return 1;
}
int
returnStorageIndex (int conn, int method, struct transactionList *txn)
{
u_int64_t n_tid, n_oid;
u_int16_t meth;
u_int32_t data_len, size =
0, buf_len, len, n_nb_oid, obj_nb, n_txn_nb, txn_nb;
char *send_buf;
for (txn_nb = 0; txn_nb < txn->last; txn_nb++)
size += txn->txn[txn_nb].objects.last * INT64_LEN;
meth = htons (method);
data_len = htonl (INT32_LEN + txn->last * (INT64_LEN + INT32_LEN) + size);
buf_len =
RHEADER_LEN + INT32_LEN + txn->last * (INT64_LEN + INT32_LEN) + size;
send_buf = (char *) malloc (buf_len);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN + INT32_LEN, &rcode, INT16_LEN);
/* data */
len = RHEADER_LEN;
n_txn_nb = htonl (txn->last);
memcpy (send_buf + len, &n_txn_nb, INT32_LEN);
len += INT32_LEN;
for (txn_nb = 0; txn_nb < txn->last; txn_nb++)
{
n_tid = htonll (txn->txn[txn_nb].tid);
memcpy (send_buf + len, &n_tid, INT64_LEN);
len += INT64_LEN;
n_nb_oid = htonl (txn->txn[txn_nb].objects.last);
memcpy (send_buf + len, &n_nb_oid, INT32_LEN);
len += INT32_LEN;
for (obj_nb = 0; obj_nb < txn->txn[txn_nb].objects.last; obj_nb++)
{
n_oid = htonll (txn->txn[txn_nb].objects.list[obj_nb].oid);
memcpy (send_buf + len, &n_oid, INT64_LEN);
len += INT64_LEN;
}
}
if (!send_all (conn, send_buf, buf_len))
{
free (send_buf);
return 0;
}
free (send_buf);
return 1;
}
int
returnGetStorageForTrans (int conn, int method, struct stringList storages)
{
u_int32_t data_len, n_nb_storage, i;
u_int16_t meth, port, n_port;
char *send_buf, *ip, *s_port;
int len = 0;
meth = htons (method);
/* compute len */
n_nb_storage = htonl (storages.last / 2);
data_len = htonl (storages.last / 2 * (IP_LEN + INT16_LEN) + INT32_LEN);
send_buf =
(char *) malloc (RHEADER_LEN + storages.last / 2 * (IP_LEN + INT16_LEN) +
INT32_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN + INT32_LEN, &rcode, INT16_LEN);
/* data */
len = RHEADER_LEN;
memcpy (send_buf + len, &n_nb_storage, INT32_LEN);
len += INT32_LEN;
/* storage list */
for (i = 0; i < storages.last; i++)
{
stringList_GetItem (&storages, &ip, i);
memcpy (send_buf + len, ip, IP_LEN);
len += IP_LEN;
i++;
stringList_GetItem (&storages, &s_port, i);
sscanf (s_port, "%hu", &port);
n_port = htons (port);
memcpy (send_buf + len, &n_port, INT16_LEN);
len += INT16_LEN;
free (ip);
free (s_port);
}
if (!send_all
(conn, send_buf,
RHEADER_LEN + storages.last / 2 * (IP_LEN + INT16_LEN) + INT32_LEN))
{
free (send_buf);
return 0;
}
free (send_buf);
return 1;
}
#ifndef mater_return_h
#define mater_return_h
#include "neo_struct.h"
int returnGetObjectByOid (int conn, int method, u_int64_t serial,
struct stringList storages);
int returnGetObjectBySerial (int conn, int method,
struct stringList storages);
int returnGetSerial (int conn, int method, u_int64_t serial);
int returnGetLastTransaction (int conn, int method, u_int64_t tid);
int returnGetOid (int conn, int method, struct list list);
int returnGetOidInt (int conn, int method, struct oidList list);
int returnClientStart (int conn, int method, struct storageInfo info);
int returnGetTransSN (int conn, int method, struct tlist tl);
int returnGetObjectHist (int conn, int method, struct tlist tl);
int returnUndoTrans (int conn, int method, struct stringList storages);
int returnBeginTrans (int conn, int method, u_int16_t tid[ID_LEN],
struct stringList storages);
int returnEndTrans (int conn, int method);
int returnGetAllSN (int conn, int method, struct nlist storages);
int returnGetAllCN (int conn, int method, struct nlist storages);
int returnGetSNInfo (int conn, int method, struct node info);
int returnStorageStart (int conn, int method, char id[UUID_LEN],
u_int16_t status);
int returnErrorMessage (int conn, int method, int code, char *message);
int returnStorageSanity (int conn, int method, struct tlist tl);
int returnStorageIndex (int conn, int method, struct transactionList *txn);
int returnGetStorageForTrans (int conn, int method,
struct stringList storages);
#endif
#! /bin/sh
# Common stub for a few missing GNU programs while installing.
# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
# 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, 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.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
if test $# -eq 0; then
echo 1>&2 "Try \`$0 --help' for more information"
exit 1
fi
run=:
# In the cases where this matters, `missing' is being run in the
# srcdir already.
if test -f configure.ac; then
configure_ac=configure.ac
else
configure_ac=configure.in
fi
case "$1" in
--run)
# Try to run requested program, and just exit if it succeeds.
run=
shift
"$@" && exit 0
;;
esac
# If it does not exist, or fails to run (possibly an outdated version),
# try to emulate it.
case "$1" in
-h|--h|--he|--hel|--help)
echo "\
$0 [OPTION]... PROGRAM [ARGUMENT]...
Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
error status if there is no known handling for PROGRAM.
Options:
-h, --help display this help and exit
-v, --version output version information and exit
--run try to run the given command, and emulate it if it fails
Supported PROGRAM values:
aclocal touch file \`aclocal.m4'
autoconf touch file \`configure'
autoheader touch file \`config.h.in'
automake touch all \`Makefile.in' files
bison create \`y.tab.[ch]', if possible, from existing .[ch]
flex create \`lex.yy.c', if possible, from existing .c
help2man touch the output file
lex create \`lex.yy.c', if possible, from existing .c
makeinfo touch the output file
tar try tar, gnutar, gtar, then tar without non-portable flags
yacc create \`y.tab.[ch]', if possible, from existing .[ch]"
;;
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "missing 0.4 - GNU automake"
;;
-*)
echo 1>&2 "$0: Unknown \`$1' option"
echo 1>&2 "Try \`$0 --help' for more information"
exit 1
;;
aclocal*)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`acinclude.m4' or \`${configure_ac}'. You might want
to install the \`Automake' and \`Perl' packages. Grab them from
any GNU archive site."
touch aclocal.m4
;;
autoconf)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`${configure_ac}'. You might want to install the
\`Autoconf' and \`GNU m4' packages. Grab them from any GNU
archive site."
touch configure
;;
autoheader)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`acconfig.h' or \`${configure_ac}'. You might want
to install the \`Autoconf' and \`GNU m4' packages. Grab them
from any GNU archive site."
files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
test -z "$files" && files="config.h"
touch_files=
for f in $files; do
case "$f" in
*:*) touch_files="$touch_files "`echo "$f" |
sed -e 's/^[^:]*://' -e 's/:.*//'`;;
*) touch_files="$touch_files $f.in";;
esac
done
touch $touch_files
;;
automake*)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
You might want to install the \`Automake' and \`Perl' packages.
Grab them from any GNU archive site."
find . -type f -name Makefile.am -print |
sed 's/\.am$/.in/' |
while read f; do touch "$f"; done
;;
autom4te)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
echo 1>&2 "\
WARNING: \`$1' is needed, and you do not seem to have it handy on your
system. You might have modified some files without having the
proper tools for further handling them.
You can get \`$1' as part of \`Autoconf' from any GNU
archive site."
file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'`
test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'`
if test -f "$file"; then
touch $file
else
test -z "$file" || exec >$file
echo "#! /bin/sh"
echo "# Created by GNU Automake missing as a replacement of"
echo "# $ $@"
echo "exit 0"
chmod +x $file
exit 1
fi
;;
bison|yacc)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified a \`.y' file. You may need the \`Bison' package
in order for those modifications to take effect. You can get
\`Bison' from any GNU archive site."
rm -f y.tab.c y.tab.h
if [ $# -ne 1 ]; then
eval LASTARG="\${$#}"
case "$LASTARG" in
*.y)
SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
if [ -f "$SRCFILE" ]; then
cp "$SRCFILE" y.tab.c
fi
SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
if [ -f "$SRCFILE" ]; then
cp "$SRCFILE" y.tab.h
fi
;;
esac
fi
if [ ! -f y.tab.h ]; then
echo >y.tab.h
fi
if [ ! -f y.tab.c ]; then
echo 'main() { return 0; }' >y.tab.c
fi
;;
lex|flex)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified a \`.l' file. You may need the \`Flex' package
in order for those modifications to take effect. You can get
\`Flex' from any GNU archive site."
rm -f lex.yy.c
if [ $# -ne 1 ]; then
eval LASTARG="\${$#}"
case "$LASTARG" in
*.l)
SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
if [ -f "$SRCFILE" ]; then
cp "$SRCFILE" lex.yy.c
fi
;;
esac
fi
if [ ! -f lex.yy.c ]; then
echo 'main() { return 0; }' >lex.yy.c
fi
;;
help2man)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified a dependency of a manual page. You may need the
\`Help2man' package in order for those modifications to take
effect. You can get \`Help2man' from any GNU archive site."
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
if test -z "$file"; then
file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'`
fi
if [ -f "$file" ]; then
touch $file
else
test -z "$file" || exec >$file
echo ".ab help2man is required to generate this page"
exit 1
fi
;;
makeinfo)
if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then
# We have makeinfo, but it failed.
exit 1
fi
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified a \`.texi' or \`.texinfo' file, or any other file
indirectly affecting the aspect of the manual. The spurious
call might also be the consequence of using a buggy \`make' (AIX,
DU, IRIX). You might want to install the \`Texinfo' package or
the \`GNU make' package. Grab either from any GNU archive site."
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
if test -z "$file"; then
file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
fi
touch $file
;;
tar)
shift
if test -n "$run"; then
echo 1>&2 "ERROR: \`tar' requires --run"
exit 1
fi
# We have already tried tar in the generic part.
# Look for gnutar/gtar before invocation to avoid ugly error
# messages.
if (gnutar --version > /dev/null 2>&1); then
gnutar "$@" && exit 0
fi
if (gtar --version > /dev/null 2>&1); then
gtar "$@" && exit 0
fi
firstarg="$1"
if shift; then
case "$firstarg" in
*o*)
firstarg=`echo "$firstarg" | sed s/o//`
tar "$firstarg" "$@" && exit 0
;;
esac
case "$firstarg" in
*h*)
firstarg=`echo "$firstarg" | sed s/h//`
tar "$firstarg" "$@" && exit 0
;;
esac
fi
echo 1>&2 "\
WARNING: I can't seem to be able to run \`tar' with the given arguments.
You may want to install GNU tar or Free paxutils, or check the
command line arguments."
exit 1
;;
*)
echo 1>&2 "\
WARNING: \`$1' is needed, and you do not seem to have it handy on your
system. You might have modified some files without having the
proper tools for further handling them. Check the \`README' file,
it often tells you about the needed prerequisites for installing
this package. You may also peek at any GNU archive site, in case
some other package would contain this missing \`$1' program."
exit 1
;;
esac
exit 0
#! /bin/sh
# mkinstalldirs --- make directory hierarchy
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
# Created: 1993-05-16
# Public domain
errstatus=0
dirmode=""
usage="\
Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..."
# process command line arguments
while test $# -gt 0 ; do
case $1 in
-h | --help | --h*) # -h for help
echo "$usage" 1>&2
exit 0
;;
-m) # -m PERM arg
shift
test $# -eq 0 && { echo "$usage" 1>&2; exit 1; }
dirmode=$1
shift
;;
--) # stop option processing
shift
break
;;
-*) # unknown option
echo "$usage" 1>&2
exit 1
;;
*) # first non-opt arg
break
;;
esac
done
for file
do
if test -d "$file"; then
shift
else
break
fi
done
case $# in
0) exit 0 ;;
esac
case $dirmode in
'')
if mkdir -p -- . 2>/dev/null; then
echo "mkdir -p -- $*"
exec mkdir -p -- "$@"
fi
;;
*)
if mkdir -m "$dirmode" -p -- . 2>/dev/null; then
echo "mkdir -m $dirmode -p -- $*"
exec mkdir -m "$dirmode" -p -- "$@"
fi
;;
esac
for file
do
set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
shift
pathcomp=
for d
do
pathcomp="$pathcomp$d"
case $pathcomp in
-*) pathcomp=./$pathcomp ;;
esac
if test ! -d "$pathcomp"; then
echo "mkdir $pathcomp"
mkdir "$pathcomp" || lasterr=$?
if test ! -d "$pathcomp"; then
errstatus=$lasterr
else
if test ! -z "$dirmode"; then
echo "chmod $dirmode $pathcomp"
lasterr=""
chmod "$dirmode" "$pathcomp" || lasterr=$?
if test ! -z "$lasterr"; then
errstatus=$lasterr
fi
fi
fi
fi
pathcomp="$pathcomp/"
done
done
exit $errstatus
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# End:
# mkinstalldirs ends here
MYSQL_LDFLAGS = @MYSQL_LDFLAGS@
MYSQL_INCLUDE = @MYSQL_INCLUDE@
MYSQL_LIBS = @MYSQL_LIBS@
AM_CFLAGS = -Wall -W
AM_CPPFLAGS = -I${top_srcdir}/include ${MYSQL_INCLUDE}
LDADD = -lneo -lstdc++ ${MYSQL_LIBS}
AM_LDFLAGS = ${MYSQL_LDFLAGS} -L../lib
bin_PROGRAMS = neostorage
neostorage_SOURCES = storage_return.c storage_request.c storage_node.c \
storage_return.h storage_request.h
# Makefile.in generated by automake 1.7.9 from Makefile.am.
# @configure_input@
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
# Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
ACLOCAL = @ACLOCAL@
AMDEP_FALSE = @AMDEP_FALSE@
AMDEP_TRUE = @AMDEP_TRUE@
AMTAR = @AMTAR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
MAKEINFO = @MAKEINFO@
MYSQL_CONFIG = @MYSQL_CONFIG@
MYSQL_INCLUDE = @MYSQL_INCLUDE@
MYSQL_LDFLAGS = @MYSQL_LDFLAGS@
MYSQL_LIBS = @MYSQL_LIBS@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PYTHON = @PYTHON@
PYTHON_BASECFLAGS = @PYTHON_BASECFLAGS@
PYTHON_CC = @PYTHON_CC@
PYTHON_CCSHARED = @PYTHON_CCSHARED@
PYTHON_INCLUDE = @PYTHON_INCLUDE@
PYTHON_LDSHARED = @PYTHON_LDSHARED@
PYTHON_OPT = @PYTHON_OPT@
PYTHON_SO = @PYTHON_SO@
RANLIB = @RANLIB@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
ac_ct_CC = @ac_ct_CC@
ac_ct_RANLIB = @ac_ct_RANLIB@
ac_ct_STRIP = @ac_ct_STRIP@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
bindir = @bindir@
build_alias = @build_alias@
datadir = @datadir@
exec_prefix = @exec_prefix@
host_alias = @host_alias@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localstatedir = @localstatedir@
mandir = @mandir@
oldincludedir = @oldincludedir@
prefix = @prefix@
program_transform_name = @program_transform_name@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
AM_CFLAGS = -Wall -W
AM_CPPFLAGS = -I${top_srcdir}/include ${MYSQL_INCLUDE}
LDADD = -lneo -lstdc++ ${MYSQL_LIBS}
AM_LDFLAGS = ${MYSQL_LDFLAGS} -L../lib
bin_PROGRAMS = neostorage
neostorage_SOURCES = storage_return.c storage_request.c storage_node.c \
storage_return.h storage_request.h
subdir = storage
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
bin_PROGRAMS = neostorage$(EXEEXT)
PROGRAMS = $(bin_PROGRAMS)
am_neostorage_OBJECTS = storage_return.$(OBJEXT) \
storage_request.$(OBJEXT) storage_node.$(OBJEXT)
neostorage_OBJECTS = $(am_neostorage_OBJECTS)
neostorage_LDADD = $(LDADD)
neostorage_DEPENDENCIES =
neostorage_LDFLAGS =
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/storage_node.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/storage_request.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/storage_return.Po
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
DIST_SOURCES = $(neostorage_SOURCES)
DIST_COMMON = $(srcdir)/Makefile.in Makefile.am
SOURCES = $(neostorage_SOURCES)
all: all-am
.SUFFIXES:
.SUFFIXES: .c .o .obj
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4)
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu storage/Makefile
Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
install-binPROGRAMS: $(bin_PROGRAMS)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(bindir)
@list='$(bin_PROGRAMS)'; for p in $$list; do \
p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
if test -f $$p \
; then \
f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) $$p $(DESTDIR)$(bindir)/$$f"; \
$(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) $$p $(DESTDIR)$(bindir)/$$f || exit 1; \
else :; fi; \
done
uninstall-binPROGRAMS:
@$(NORMAL_UNINSTALL)
@list='$(bin_PROGRAMS)'; for p in $$list; do \
f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
echo " rm -f $(DESTDIR)$(bindir)/$$f"; \
rm -f $(DESTDIR)$(bindir)/$$f; \
done
clean-binPROGRAMS:
-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
neostorage$(EXEEXT): $(neostorage_OBJECTS) $(neostorage_DEPENDENCIES)
@rm -f neostorage$(EXEEXT)
$(LINK) $(neostorage_LDFLAGS) $(neostorage_OBJECTS) $(neostorage_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT) core *.core
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/storage_node.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/storage_request.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/storage_return.Po@am__quote@
.c.o:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
@am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \
@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
@am__fastdepCC_TRUE@ fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$<
.c.obj:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
@am__fastdepCC_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \
@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
@am__fastdepCC_TRUE@ fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`
uninstall-info-am:
ETAGS = etags
ETAGSFLAGS =
CTAGS = ctags
CTAGSFLAGS =
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
mkid -fID $$unique
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)$$tags$$unique" \
|| $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$tags $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& cd $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) $$here
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
top_distdir = ..
distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
list='$(DISTFILES)'; for file in $$list; do \
case $$file in \
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
esac; \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkinstalldirs) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(PROGRAMS)
installdirs:
$(mkinstalldirs) $(DESTDIR)$(bindir)
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-am
dvi-am:
info: info-am
info-am:
install-data-am:
install-exec-am: install-binPROGRAMS
install-info: install-info-am
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-binPROGRAMS uninstall-info-am
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
clean-generic ctags distclean distclean-compile \
distclean-generic distclean-tags distdir dvi dvi-am info \
info-am install install-am install-binPROGRAMS install-data \
install-data-am install-exec install-exec-am install-info \
install-info-am install-man install-strip installcheck \
installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
uninstall-am uninstall-binPROGRAMS uninstall-info-am
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
#include <pthread.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <signal.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <uuid/uuid.h>
#include <getopt.h>
#include <syslog.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "neo_mysql.h"
#include "storage_request.h"
#include "storage_return.h"
#include "neo_socket.h"
#include "neo_struct.h"
#define DB 0
#define STORAGE_DATA_FILE "storage_data.txt"
#define STORAGE_ID_FILE "storage_id.txt"
struct master_node
{
char id[UUID_LEN + 1];
char ip[IP_LEN + 1];
u_int16_t port;
};
static struct master_node *master;
static int soc = -1;
static int create_db = 0;
static uuid_t storage_id;
static char ID[UUID_LEN+1]; /* uuid is unparse into a 36 byte string */
static struct database *db;
char database_dir[BUF_SIZE]; /* path to the mysql db dir */
static pthread_mutex_t mutex_db = PTHREAD_MUTEX_INITIALIZER;
int
init_mutex ()
{
pthread_mutex_init (&mutex_db, NULL);
return 1;
}
int
lock (int mutex)
{
if (mutex == DB)
pthread_mutex_lock (&mutex_db);
else
{
perror ("lock mutex");
return 0;
}
return 1;
}
int
unlock (int mutex)
{
if (mutex == DB)
pthread_mutex_unlock (&mutex_db);
else
{
perror ("unlock mutex");
return 0;
}
return 1;
}
/* handler called when master close */
static void
cleanup_handler (int sig)
{
database_close (db);
storageClose (master->ip, master->port, ID);
free (master);
if (soc >= 0)
close (soc);
syslog (LOG_MAKEPRI (LOG_USER, LOG_NOTICE), "storage close");
closelog ();
exit (0);
}
/* function that generate a uuid and store it on disk */
int
generate_id ()
{
memset (ID, 0, UUID_LEN + 1);
FILE *fid;
/* check if a uuid ever exists */
if ((fid = fopen (STORAGE_ID_FILE, "r")) != NULL)
{
fread (ID, UUID_LEN, 1, fid);
uuid_parse (ID, storage_id);
fclose (fid);
return 1;
}
/* generate uuid */
uuid_generate (storage_id);
uuid_unparse (storage_id, ID);
/* store it on disk */
fid = fopen (STORAGE_ID_FILE, "w");
fwrite (ID, UUID_LEN, 1, fid);
fclose (fid);
return 1;
}
static int
h_transaction (int conn, char *hbuf, u_int32_t * buf_len) /* done */
{
u_int64_t tid, oid, serial, object_len;
char rflags[FLAG_LEN];
u_int16_t ulen, dlen, elen;
u_int32_t len = 0, nb_objects, data_len = 0, i;
int32_t crc;
char *user = NULL, *desc = NULL, *ext = NULL, *data = NULL, *buf = NULL;
/* header */
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
buf = (char *) malloc (data_len);
len = *buf_len - 8;
while (len < data_len)
if (!fill_buffer (conn, buf, &len, data_len - len))
goto fail;
len = 0;
/* get transaction info */
tid = ntohll (*((u_int64_t *) (buf + len)));
len += INT64_LEN;
ulen = ntohs (*((u_int16_t *) (buf + len)));
len += INT16_LEN;
dlen = ntohs (*((u_int16_t *) (buf + len)));
len += INT16_LEN;
elen = ntohs (*((u_int16_t *) (buf + len)));
len += INT16_LEN;
/* XXX use just one malloc for all */
user = (char *) malloc (ulen + 1);
desc = (char *) malloc (dlen + 1);
ext = (char *) malloc (elen + 1);
memset (user, 0, ulen + 1);
memset (desc, 0, dlen + 1);
memset (ext, 0, elen + 1);
memcpy (user, buf + len, ulen);
len += ulen;
memcpy (desc, buf + len, dlen);
len += dlen;
memcpy (ext, buf + len, elen);
len += elen;
/* get object list */
nb_objects = ntohl (*((u_int32_t *) (buf + len)));
len += INT32_LEN;
/* store transaction into db */
lock (DB);
if (!database_storage_put_trans (db, tid, user, desc, ext))
{ /* must abort trans */
unlock (DB);
returnErrorMessage (conn, TRANSACTION, TRANS_NOT_FOUND,
"transaction not found");
return 1;
}
unlock (DB);
for (i = 0; i < nb_objects; i++)
{
oid = ntohll (*((u_int64_t *) (buf + len))); /* oid */
len += INT64_LEN;
serial = ntohll (*((u_int64_t *) (buf + len))); /* oid */
len += INT64_LEN;
object_len = ntohll (*((u_int64_t *) (buf + len))); /* data length */
len += INT64_LEN;
data = (char *) malloc (object_len + 1);
memset (data, 0, object_len + 1);
memcpy (data, buf + len, object_len); /* data */
len += object_len;
crc = ntohl (*((u_int32_t *) (buf + len))); /* crc */
len += INT32_LEN;
/* store object in db */
lock (DB);
if (!database_storage_put_object (db, oid, serial, tid, (void *) data,
strlen (data), crc))
{ /* must abort trans , del object and transaction into db */
unlock (DB);
if (data != NULL)
free (data);
goto fail;
}
if (data != NULL)
free (data);
unlock (DB);
}
if (!returnTransaction (conn, TRANSACTION))
goto fail;
free (user);
free (desc);
free (ext);
free (buf);
return 1;
fail:
if (user != NULL)
free (user);
if (desc != NULL)
free (desc);
if (ext != NULL)
free (ext);
if (buf != NULL)
free (buf);
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "return method failed");
returnErrorMessage (conn, TRANSACTION, TMP_FAILURE, "Error storage node");
return 0;
}
static int
h_undo (int conn, char *hbuf, u_int32_t * buf_len)
{
u_int64_t tid;
char rflags[FLAG_LEN], *buf;
u_int32_t len = 0, data_len = 0, nb_oid;
u_int64_t *oid_list;
/* struct stringList *loid; */
/* header */
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
buf = (char *) malloc (data_len);
len = *buf_len - 8;
while (len < data_len)
if (!fill_buffer (conn, buf, &len, data_len - len))
goto fail;
tid = ntohll (*((u_int64_t *) (buf)));
/* get object list to return to client to invalidate cache */
lock (DB);
if (!database_storage_get_object_list (db, tid, &oid_list, &nb_oid))
{ /* error in db */
unlock (DB);
goto fail;
}
/* don't delete transaction because needed for next undo */
/* if (!database_storage_del_trans (db, tid)) */
/* { */
/* unlock (DB); */
/* goto fail; */
/* } */
unlock (DB);
if (!returnUndo (conn, UNDO, oid_list, nb_oid))
{
goto fail;
}
free (buf);
return 1;
fail:
free (buf);
returnErrorMessage (conn, UNDO, TMP_FAILURE, "Error storage node");
return 0;
}
static int
h_histInfo (int conn, char *hbuf, u_int32_t * buf_len)
{
struct hist hist;
u_int64_t oid, serial;
char *buf;
u_int32_t len = 0, data_len = 0;
char rflags[FLAG_LEN];
/* header */
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
buf = (char *) malloc (data_len);
len = *buf_len - 8;
while (len < data_len)
if (!fill_buffer (conn, buf, &len, data_len - len))
goto fail;
oid = ntohll (*((u_int64_t *) (buf)));
serial = ntohll (*((u_int64_t *) (buf + INT64_LEN)));
lock (DB);
if (!database_storage_get_object_info (db, oid, serial, &hist))
{
unlock (DB);
goto fail;
}
unlock (DB);
/* create history entry */
hist.time = 0;
hist.serial = serial;
if (!returnHistInfo (conn, HIST_INFO, hist))
goto fail;
free (hist.user);
free (hist.desc);
free (buf);
return 1;
fail:
if (hist.user != NULL)
free (hist.user);
if (hist.desc != NULL)
free (hist.desc);
if (buf != NULL)
free (buf);
returnErrorMessage (conn, HIST_INFO, TMP_FAILURE, "Error storage node");
return 0;
}
static int
h_load (int conn, char *hbuf, u_int32_t * buf_len)
{
u_int64_t oid, serial;
char rflags[FLAG_LEN], *buf;
u_int32_t len = 0, data_len = 0;
int32_t crc;
char *data;
/* header */
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
buf = (char *) malloc (data_len);
len = *buf_len - 8;
while (len < data_len)
if (!fill_buffer (conn, buf, &len, data_len - len))
goto fail;
oid = ntohll (*((u_int64_t *) (buf)));
serial = ntohll (*((u_int64_t *) (buf + INT64_LEN)));
lock (DB);
if (!database_storage_get_object (db, oid, serial, (void **) &data, &crc))
{
unlock (DB);
returnErrorMessage (conn, LOAD, OID_NOT_FOUND,
"object not found in storage");
return 0;
}
unlock (DB);
if (!returnLoad (conn, LOAD, data, crc))
{
free (data);
goto fail;
}
free (data);
free (buf);
return 1;
fail:
free (buf);
returnErrorMessage (conn, LOAD, TMP_FAILURE, "Error storage node");
return 0;
}
static int
h_getSize (int conn, char *hbuf, u_int32_t * buf_len)
{
u_int64_t size = 0;
u_int32_t len = 0, data_len = 0;
char rflags[FLAG_LEN], *buf;
/* header */
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
buf = (char *) malloc (data_len);
len = *buf_len - 8;
while (len < data_len)
if (!fill_buffer (conn, buf, &len, data_len - len))
goto fail;
printf ("in get size\n");
lock(DB);
if (!database_storage_get_db_size (db, &size))
{
unlock (DB);
printf ("get db failed\n");
returnErrorMessage (conn, GET_SIZE, METHOD_ERROR,
"can not get size for storage");
return 0;
}
unlock (DB);
printf ("return get size %llu\n", size);
if (!returnGetSize (conn, GET_SIZE, size))
goto fail;
free (buf);
return 1;
fail:
free (buf);
returnErrorMessage (conn, GET_SIZE, TMP_FAILURE, "Error storage node");
return 0;
}
static int
h_undoInfo (int conn, char *hbuf, u_int32_t * buf_len)
{
u_int64_t tid;
struct undoInfo info;
u_int32_t len = 0, data_len = 0;
char rflags[FLAG_LEN];
char *buf;
/* header */
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
buf = (char *) malloc (data_len);
len = *buf_len - 8;
while (len < data_len)
if (!fill_buffer (conn, buf, &len, data_len - len))
goto fail;
tid = ntohll (*((u_int64_t *) (buf)));
/* get info */
/* XXX use structure in database */
lock (DB);
if (!database_storage_get_trans_info (db, tid, &info))
{
unlock (DB);
returnErrorMessage (conn, UNDO_INFO, TRANS_NOT_FOUND, "");
return 1;
}
unlock (DB);
/* init structure */
info.time = 0;
/* copy data */
info.id = tid;
if (!returnUndoInfo (conn, UNDO_INFO, info))
goto fail;
free (buf);
free (info.desc);
free (info.user);
return 1;
fail:
free (info.desc);
free (info.user);
free (buf);
returnErrorMessage (conn, UNDO_INFO, TMP_FAILURE, "Error storage node");
return 0;
}
static int
h_masterClose (int conn, char *hbuf, u_int32_t * buf_len)
{
u_int32_t len = 0, data_len = 0;
char rflags[FLAG_LEN];
char *buf, master_id[UUID_LEN + 1];
/* header */
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
buf = (char *) malloc (data_len);
len = *buf_len - 8;
while (len < data_len)
if (!fill_buffer (conn, buf, &len, data_len - len))
goto fail;
memset (master_id, 0, UUID_LEN + 1);
memcpy (master_id, buf, UUID_LEN);
if (!returnMasterClose (conn, MASTER_CLOSE, ID))
goto fail;
free (buf);
return 1;
fail:
free (buf);
returnErrorMessage (conn, MASTER_CLOSE, TMP_FAILURE, "Error storage node");
return 0;
}
static int
h_masterChange (int conn, char *hbuf, u_int32_t * buf_len)
{
u_int32_t len = 0, data_len = 0;
char rflags[FLAG_LEN], master_id[UUID_LEN + 1], master_ip[IP_LEN + 1];
u_int16_t master_port;
char *buf;
/* header */
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
buf = (char *) malloc (data_len);
len = *buf_len - 8;
while (len < data_len)
if (!fill_buffer (conn, buf, &len, data_len - len))
goto fail;
memset (master_id, 0, UUID_LEN + 1);
memcpy (master_id, buf, UUID_LEN);
buf += UUID_LEN;
memset (master_ip, 0, IP_LEN + 1);
memcpy (master_ip, buf, IP_LEN);
buf += IP_LEN;
master_port = ntohs (*((u_int16_t *) (buf)));
if (!returnMasterChange (conn, MASTER_CHANGE, ID))
goto fail;
free (buf);
return 1;
/* XXX must close connection to master and connect to new master to check it ??? */
fail:
free (buf);
returnErrorMessage (conn, MASTER_CHANGE, TMP_FAILURE, "Error storage node");
return 0;
}
static int
h_getTransData (int conn, char *hbuf, u_int32_t * buf_len)
{
u_int64_t tid;
u_int32_t len = 0, data_len = 0;
char rflags[FLAG_LEN], *buf = NULL, *user = NULL, *desc = NULL, *ext = NULL;
struct objectList *objects = NULL;
/* method calleb by other storage to get all data from a transaction */
/* header */
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
buf = (char *) malloc (data_len);
while (len < data_len)
if (!fill_buffer (conn, buf, &len, data_len - len))
goto fail;
tid = ntohll (*((u_int64_t *) (buf)));
lock (DB);
if (!database_storage_get_trans_data
(db, tid, &user, &desc, &ext, &objects))
{
unlock (DB);
goto fail;
}
unlock (DB);
if (!returnGetTransData
(conn, GET_TRANS_DATA, tid, user, desc, ext, *objects))
goto fail;
free (desc);
free (user);
free (ext);
free (buf);
objectList_Free (objects);
free (objects);
return 1;
fail:
if (buf != NULL)
free (buf);
if (desc != NULL)
free (desc);
if (ext != NULL)
free (ext);
if (user != NULL)
free (user);
if (objects != NULL)
{
objectList_Free (objects);
free (objects);
}
returnErrorMessage (conn, GET_TRANS_DATA, TMP_FAILURE,
"Error storage node");
return 0;
}
/* function that handle each new connection and call the appropriate function */
static void *
client_handler (void *data)
{
int conn;
char buf[HEADER_LEN];
u_int32_t buf_len = 0;
u_int16_t method;
database_thread_init ();
conn = *((int *) data);
while (1)
{
buf_len = 0;
if (!fill_buffer (conn, buf, &buf_len, HEADER_LEN))
goto fail;
method = ntohs (*((u_int16_t *) (buf)));
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "client %d call method %d",
conn, method);
switch (method)
{
case TRANSACTION:
if (!h_transaction (conn, buf, &buf_len))
goto fail;
break;
case UNDO:
if (!h_undo (conn, buf, &buf_len))
goto fail;
break;
case HIST_INFO:
if (!h_histInfo (conn, buf, &buf_len))
goto fail;
break;
case UNDO_INFO:
if (!h_undoInfo (conn, buf, &buf_len))
goto fail;
break;
case LOAD:
if (!h_load (conn, buf, &buf_len))
goto fail;
break;
case GET_SIZE:
if (!h_getSize (conn, buf, &buf_len))
goto fail;
break;
case MASTER_CLOSE:
h_masterClose (conn, buf, &buf_len);
goto end;
break;
case MASTER_CHANGE:
if (!h_masterChange (conn, buf, &buf_len))
goto fail;
break;
case GET_TRANS_DATA:
if (!h_getTransData (conn, buf, &buf_len))
goto fail;
break;
}
}
fail:
syslog (LOG_MAKEPRI (LOG_USER, LOG_DEBUG), "return method failed");
syslog (LOG_MAKEPRI (LOG_USER, LOG_INFO), "End client connection %d", conn);
database_thread_end ();
close (conn);
free (data);
return NULL;
end: /* end storage node */
syslog (LOG_MAKEPRI (LOG_USER, LOG_NOTICE), "Close storage");
database_thread_end ();
close (conn);
free (data);
exit (1);
}
/**
* function that restore a transaction from data coming from
* another storage node
*/
int
restore_transaction (int conn)
{
u_int64_t tid, oid, serial, data_size;
char hbuf[RHEADER_LEN], rflags[FLAG_LEN], *buf = NULL, *data = NULL, *user =
NULL, *desc = NULL, *ext = NULL;
u_int32_t buf_len = 0, len = 0, data_len, nb_object, i;
u_int16_t return_code, tlen;
int32_t crc = 0;
if (!wait_packet (conn, hbuf, &buf_len, RHEADER_LEN))
return 0;
if ((ntohs (*((u_int16_t *) (hbuf)))) != GET_TRANS_DATA)
{
perror ("receive");
return 0;
}
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
return_code =
ntohs (*((u_int16_t *) (hbuf + INT16_LEN + FLAG_LEN + INT32_LEN)));
buf = (char *) malloc (data_len);
if (!buf)
return 0;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
{
free (buf);
return 0;
}
}
if (return_code != 0)
return return_code;
tid = ntohll (*((u_int64_t *) (buf)));
buf += INT64_LEN;
/* user */
tlen = ntohs (*((u_int16_t *) (buf)));
buf += INT16_LEN;
user = (char *) malloc (tlen + 1);
memset (user, 0, tlen + 1);
memcpy (user, buf, tlen);
buf += tlen;
/* desc */
tlen = ntohs (*((u_int16_t *) (buf)));
buf += INT16_LEN;
desc = (char *) malloc (tlen + 1);
memset (desc, 0, tlen + 1);
memcpy (desc, buf, tlen);
buf += tlen;
/* ext */
tlen = ntohs (*((u_int16_t *) (buf)));
buf += INT16_LEN;
ext = (char *) malloc (tlen + 1);
memset (ext, 0, tlen + 1);
memcpy (ext, buf, tlen);
buf += tlen;
/* store transaction in database */
database_storage_store_trans (db, tid, user, desc, ext);
/* object list */
nb_object = ntohl (*((u_int32_t *) (buf)));
buf += INT32_LEN;
for (i = 0; i < nb_object; i++)
{
/* oid */
oid = ntohll (*((u_int64_t *) (buf)));
buf += INT64_LEN;
/* serial */
serial = ntohll (*((u_int64_t *) (buf)));
buf += INT64_LEN;
/* data */
data_size = ntohll (*((u_int64_t *) (buf)));
buf += INT64_LEN;
data = (char *) malloc (data_size + 1);
memset (data, 0, data_size + 1);
memcpy (data, buf, data_size);
buf += data_size;
database_storage_put_object (db, oid, serial, tid, (void *) data,
strlen (data), crc);
free (data);
}
free (buf - data_len);
free (ext);
free (desc);
free (user);
return 1;
}
/**
* function that get list of storage node for each transaction
* known to be stored by the storage node
*/
static int
make_storage_sane (int conn)
{
u_int64_t tid;
char hbuf[RHEADER_LEN], rflags[FLAG_LEN], *buf;
u_int32_t buf_len = 0, len =
0, data_len, trans_nb, storage_nb, nb, i, storage_conn;
u_int16_t return_code, storage_port, exist = 0;
char storage_ip[IP_LEN + 1];
if (!wait_packet (conn, hbuf, &buf_len, RHEADER_LEN))
return 0;
if ((ntohs (*((u_int16_t *) (hbuf)))) != SANITY_CHECK)
{
perror ("receive");
return 0;
}
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
return_code =
ntohs (*((u_int16_t *) (hbuf + INT16_LEN + FLAG_LEN + INT32_LEN)));
if (return_code != 0)
return return_code;
buf = (char *) malloc (data_len);
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
return 0;
}
trans_nb = ntohl (*((u_int32_t *) (buf)));
len = INT32_LEN;
/**
* get all data from other storage and store them
*/
for (nb = 0; nb < trans_nb; nb++)
{
/* get transaction id */
tid = ntohll (*((u_int64_t *) (buf + len)));
len += INT64_LEN;
/* check if transaction exist */
/* database_storage_trans_exist (db, tid, &exist); */
if (!exist)
{
/* number of storage for the transaction */
storage_nb = ntohl (*((u_int32_t *) (buf + len)));
len += INT32_LEN;
/* get storages list */
for (i = 0; i < storage_nb; i++)
{
/* storage ip */
memset (storage_ip, 0, IP_LEN + 1);
memcpy (storage_ip, buf + len, IP_LEN);
len += IP_LEN;
/* storage port */
storage_port = ntohs (*((u_int16_t *) (buf + len)));
len += INT16_LEN;
/* get data from another storage */
storage_conn = connectTo(storage_ip, storage_port);
if (getTransData (storage_conn, GET_TRANS_DATA, tid))
/* restore data */
if (restore_transaction (storage_conn))
{
/* it's ok, go to next transaction */
len += (INT16_LEN + IP_LEN) * (storage_nb - i - 1);
close (storage_conn);
break;
}
close (storage_conn);
}
}
else
len += (INT16_LEN + IP_LEN) * (storage_nb);
}
free (buf);
return 1;
}
/**
* send request to master to get storage node list
* for the given transaction
*/
static int
restore_data (int conn, u_int64_t tid)
{
u_int64_t n_tid;
u_int32_t data_len, meth;
char *send_buf;
char hbuf[RHEADER_LEN], rflags[FLAG_LEN], *buf;
u_int32_t buf_len = 0, len = 0, storage_nb, i, storage_conn;
u_int16_t return_code, storage_port;
char storage_ip[IP_LEN + 1];
/* send request to master */
meth = htons (GET_STORAGE_FOR_TRANS);
data_len = htonl (INT64_LEN + UUID_LEN);
send_buf = (char *) malloc (HEADER_LEN + INT64_LEN + UUID_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
/* data */
memcpy (send_buf + HEADER_LEN, ID, UUID_LEN);
n_tid = htonll (tid);
memcpy (send_buf + HEADER_LEN + UUID_LEN, &n_tid, INT64_LEN);
if (!send_all (conn, send_buf, HEADER_LEN + INT64_LEN + UUID_LEN))
{
free (send_buf);
return 0;
}
free (send_buf);
/* get answer from master node */
if (!wait_packet (conn, hbuf, &buf_len, RHEADER_LEN))
return 0;
/* header */
if ((ntohs (*((u_int16_t *) (hbuf)))) != GET_STORAGE_FOR_TRANS)
{
perror ("receive");
return 0;
}
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
return_code =
ntohs (*((u_int16_t *) (hbuf + INT16_LEN + FLAG_LEN + INT32_LEN)));
buf = (char *) malloc (data_len);
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
return 0;
}
if (return_code != 0)
return return_code;
/* data */
len = 0;
storage_nb = ntohl (*((u_int32_t *) (buf + len)));
len = INT32_LEN;
/* get storages list */
for (i = 0; i < storage_nb; i++)
{
/* storage ip */
memset (storage_ip, 0, IP_LEN + 1);
memcpy (storage_ip, buf + len, IP_LEN);
len += IP_LEN;
/* storage port */
storage_port = ntohs (*((u_int16_t *) (buf + len)));
len += INT16_LEN;
/* get data from another storage */
storage_conn = connectTo(storage_ip, storage_port);
if (getTransData
(storage_conn, GET_TRANS_DATA, tid))
/* restore data */
if (restore_transaction (storage_conn))
{
close (storage_conn);
free (buf);
return 1;
}
close (storage_conn);
}
/* never get here otherwise transaction isn't restored */
free (buf);
return 0;
}
/**
* check if data stored by storage and master node index match
*/
static int
check_storage_sanity (int conn)
{
/* get index of transaction with oid from master and check if all is ok */
char hbuf[RHEADER_LEN], *buf, rflags[FLAG_LEN];
u_int32_t data_len, len = 0, buf_len = 0, nb_oid, oid_nb, nb_txn, txn_nb;
u_int64_t tid, oid;
u_int16_t return_code;
if (!wait_packet (conn, hbuf, &buf_len, RHEADER_LEN))
return 0;
/* get header */
if ((ntohs (*((u_int16_t *) (hbuf)))) != STORAGE_INDEX)
{
perror ("receive");
return 0;
}
memcpy (rflags, hbuf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (hbuf + INT16_LEN + FLAG_LEN)));
return_code =
ntohs (*((u_int16_t *) (hbuf + INT16_LEN + FLAG_LEN + INT32_LEN)));
buf = (char *) malloc (data_len);
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
return 0;
}
if (return_code != 0)
return return_code;
/* get data */
len = 0;
nb_txn = ntohl (*((u_int64_t *) (buf + len)));
len += INT32_LEN;
for (txn_nb = 0; txn_nb < nb_txn; txn_nb++)
{
tid = ntohll (*((u_int64_t *) (buf + len)));
len += INT64_LEN;
nb_oid = ntohl (*((u_int32_t *) (buf + len)));
len += INT32_LEN;
/* XXX must construct list of oid before checking with DB */
for (oid_nb = 0; oid_nb < nb_oid; oid_nb++)
{
oid = ntohll (*((u_int64_t *) (buf + len)));
len += INT64_LEN;
/* now check with database if allright */
if (!database_storage_check_sanity (db, tid, oid))
{
/* must get data from another storage */
restore_data (conn, tid);
}
}
}
free (buf);
return 1;
}
/* send broadcast message to find where is the master */
static int
search_master ()
{
int soc, bd = 1, size;
char send_buf[HEADER_LEN], rcv_buf[RHEADER_LEN + 1], rflags[FLAG_LEN];
struct sockaddr_in addr;
u_int16_t meth, return_code;
u_int32_t data_len;
size_t send, received;
soc = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);
setsockopt (soc, SOL_SOCKET, SO_BROADCAST, (int *) &bd, sizeof (bd));
addr.sin_family = AF_INET;
addr.sin_port = htons (10825);
addr.sin_addr.s_addr = htonl (INADDR_BROADCAST);
/* create packet */
meth = htons (SEARCH_MASTER);
data_len = htonl (0);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
send = sendto (soc, (char *)send_buf, HEADER_LEN, 0, (struct sockaddr *)&addr, sizeof(addr));
/* wait for a response */
size = sizeof (addr);
memset (rcv_buf, 0, RHEADER_LEN);
received = recvfrom (soc, (char *)rcv_buf, RHEADER_LEN, 0, (struct sockaddr *)&addr, &size);
/* check response */
if ((ntohs (*((u_int16_t *) (rcv_buf)))) != SEARCH_MASTER)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_WARNING), "return method error from master in udp broadcast");
return METHOD_ERROR;
}
memcpy (rflags, rcv_buf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (rcv_buf + INT16_LEN + FLAG_LEN)));
return_code =
ntohs (*((u_int16_t *) (rcv_buf + INT16_LEN + FLAG_LEN + INT32_LEN)));
if (return_code != 0)
return return_code;
/* get master ip */
memset (master->ip, 0, IP_LEN + 1);
strncpy (master->ip, inet_ntoa(addr.sin_addr), IP_LEN);
printf ("master found on %s\n", master->ip);
syslog (LOG_MAKEPRI (LOG_USER, LOG_NOTICE), "master found on %s", master->ip);
close(soc);
return 0;
}
static int
parse_arg (int argc, char **argv)
{
int c, option_index = 0;
while (1)
{
static struct option long_options[] = {
{"create-database", no_argument, 0, 'c'},
{"log-level", required_argument, 0, 'l'},
{"database", required_argument, 0, 'd'},
{0, 0, 0, 0}
};
option_index = 0;
c = getopt_long (argc, argv, "cl:d:", long_options, &option_index);
/* Detect the end of the options. */
if (c == -1)
break;
switch (c)
{
case 'c':
create_db = 1;
break;
case 'l':
switch (atoi (optarg))
{
case 3:
setlogmask (LOG_UPTO (LOG_DEBUG));
break;
case 2:
setlogmask (LOG_UPTO (LOG_INFO));
break;
case 1:
setlogmask (LOG_UPTO (LOG_NOTICE));
break;
}
break;
case 'd': /* XXX must test len of dir! */
strncpy (database_dir, optarg, BUF_SIZE-1);
break;
case '?':
/* getopt_long already printed an error message. */
break;
default:
abort ();
}
}
/* Print any remaining command line arguments (not options). */
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
putchar ('\n');
return 0;
}
return 1;
}
int
main (int argc, char **argv)
{
struct sockaddr_in addr;
pthread_attr_t attr;
char old_MasterID[UUID_LEN+1];
u_int16_t port = 10000; /* default port */
int *connp, status, master_conn;
pthread_t th;
FILE *fid;
/* init default before geting args */
setlogmask (LOG_UPTO (LOG_ERR));
strncpy (database_dir, "./db", BUF_SIZE-1);
master = (struct master_node *) malloc (sizeof (struct master_node));
if (!parse_arg (argc, argv))
return -1;
/* open syslog */
openlog ("neostorage", 0, 0);
signal (SIGINT, cleanup_handler);
signal (SIGTERM, cleanup_handler);
if (!generate_id ())
goto fail;
syslog (LOG_MAKEPRI (LOG_USER, LOG_NOTICE), "id : %s", ID);
/* open database */
if ((db = database_storage_open (create_db)) == 0)
return -1;
syslog (LOG_MAKEPRI (LOG_USER, LOG_NOTICE),
"connection to database opened");
/* search for master */
if (search_master() != 0)
{
printf ("master not found\n");
return -1;
}
init_mutex ();
/* set attributes to thread */
if (pthread_attr_init (&attr) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "pthread_attr_init %s",
strerror (errno));
goto fail;
}
if (pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR),
"pthread_attr_setdetachstate %s", strerror (errno));
goto fail;
}
/* create socket */
soc = socket (PF_INET, SOCK_STREAM, 0);
if (soc < 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "socket %s", strerror (errno));
goto fail;
}
addr.sin_family = AF_INET;
addr.sin_port = htons (port);
addr.sin_addr.s_addr = htonl (INADDR_ANY);
/* try to open a port for storage server */
bind:
if (bind (soc, (struct sockaddr *) &addr, sizeof (addr)) != 0)
{
port++;
addr.sin_port = htons (port);
goto bind;
}
if (listen (soc, 5) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "listen %s", strerror (errno));
goto fail;
}
syslog (LOG_MAKEPRI (LOG_USER, LOG_NOTICE), "listening on port %d", port);
/* connect to master */
master->port = MASTER_PORT;
master_conn = connectTo(master->ip, master->port);
storageStart (master_conn, ID, "127.0.0.1", port, master->id, &status);
memset(old_MasterID, 0, UUID_LEN+1);
/* Check if a master id already exists */
if ((fid = fopen (STORAGE_DATA_FILE, "r")) != NULL)
{
fread (old_MasterID, UUID_LEN, 1, fid);
fclose (fid);
if (strncmp (old_MasterID, master->id, UUID_LEN) != 0)
{
/* master change anyway the storage is make sane just after */
/* just store the new master id */
fid = fopen (STORAGE_DATA_FILE, "w");
fwrite (master->id, UUID_LEN, 1, fid);
fclose (fid);
}
}
/* check the status of the storage */
printf ("status %d\n", status);
if (status == 2) /* storage marked as unsane */
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_NOTICE), "storage unreliable");
if (!make_storage_sane (master_conn))
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "impossible to make the storage reliable");
goto fail;
}
}
else if (status == 1)
/* must check index with master */
if (!check_storage_sanity (master_conn))
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "storage index check failed");
goto fail;
}
/* storage is ready to handle request */
if (!storageReady (master_conn, ID))
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "impossible to start storage");
goto fail;
}
close (master_conn);
printf ("storage ready\n");
/* now wait for connection */
while (1)
{
connp = (int *) malloc (sizeof (int));
if (!connp)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "malloc %s",
strerror (errno));
goto fail;
}
*connp = accept (soc, 0, 0);
if (*connp < 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "accept %s",
strerror (errno));
free (connp);
goto fail;
}
syslog (LOG_MAKEPRI (LOG_USER, LOG_INFO),
"New client connected with %d", *connp);
if (pthread_create (&th, &attr, client_handler, connp) != 0)
{
syslog (LOG_MAKEPRI (LOG_USER, LOG_ERR), "pthread_create %s",
strerror (errno));
perror ("pthread_create");
free (connp);
goto fail;
}
}
close (soc);
return 0;
fail:
free (master);
if (soc >= 0)
close (soc);
database_close (db);
syslog (LOG_MAKEPRI (LOG_USER, LOG_NOTICE), "Close storage");
closelog ();
return 1;
}
#include <netinet/in.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include "neo_socket.h"
#include "neo_struct.h"
#define STORAGE_START 29
int
storageClose (char master_ip[IP_LEN], u_int16_t master_port,
char storage_id[UUID_LEN])
{
int conn;
u_int32_t data_len, meth;
char *send_buf;
/* send request to master */
meth = htons (STORAGE_CLOSE);
data_len = htonl (UUID_LEN);
send_buf = (char *) malloc (HEADER_LEN + UUID_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
/* data */
memcpy (send_buf + HEADER_LEN, storage_id, UUID_LEN);
if (!(conn = connectTo (master_ip, master_port)))
return 0;
if (!send_all (conn, send_buf, HEADER_LEN + UUID_LEN))
{
free (send_buf);
return 0;
}
free (send_buf);
close (conn);
return 1;
}
int
storageStart (int conn, char storage_id[UUID_LEN], char storage_ip[IP_LEN],
u_int16_t storage_port, char master_id[UUID_LEN], int *status)
{
u_int32_t buf_len, data_len, meth, len = 0;
u_int16_t n_storage_port;
char buf[BUF_SIZE];
u_int16_t return_code;
char rflags[FLAG_LEN];
char *send_buf;
/* send request to master */
meth = htons (STORAGE_START);
data_len = htonl (UUID_LEN + IP_LEN + INT16_LEN);
send_buf = (char *) malloc (HEADER_LEN + UUID_LEN + IP_LEN + INT16_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
/* data */
len = HEADER_LEN;
memcpy (send_buf + len, storage_id, UUID_LEN);
len += UUID_LEN;
memcpy (send_buf + len, storage_ip, IP_LEN);
len += IP_LEN;
n_storage_port = htons (storage_port);
memcpy (send_buf + len, &n_storage_port, INT16_LEN);
if (!send_all (conn, send_buf, HEADER_LEN + UUID_LEN + IP_LEN + INT16_LEN))
{
free (send_buf);
return 0;
}
free (send_buf);
/* Wait for response */
data_len = 0;
buf_len = 0;
if (!wait_packet (conn, buf, &buf_len, RHEADER_LEN))
return 0;
if ((ntohs (*((u_int16_t *) (buf)))) != STORAGE_START)
{
perror ("receive");
return 0;
}
memcpy (rflags, buf + INT16_LEN, FLAG_LEN);
data_len = ntohl (*((u_int32_t *) (buf + INT16_LEN + FLAG_LEN)));
return_code =
ntohs (*((u_int16_t *) (buf + INT16_LEN + FLAG_LEN + INT32_LEN)));
if (return_code != 0)
return return_code;
len = buf_len - 10;
while (len < data_len)
{
if (!fill_buffer (conn, buf, &len, data_len - len))
return 0;
}
memset (master_id, 0, UUID_LEN + 1);
memcpy (master_id, buf, UUID_LEN);
*status = ntohs (*((u_int16_t *) (buf + UUID_LEN)));
return 1;
}
int
storageReady (int conn, char storage_id[UUID_LEN])
{
u_int32_t data_len, meth;
char *send_buf;
/* send request to master */
meth = htons (STORAGE_READY);
data_len = htonl (UUID_LEN);
send_buf = (char *) malloc (HEADER_LEN + UUID_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
/* data */
memcpy (send_buf + HEADER_LEN, storage_id, UUID_LEN);
if (!send_all (conn, send_buf, HEADER_LEN + UUID_LEN))
{
free (send_buf);
return 0;
}
free (send_buf);
return 1;
}
int
getTransData (int conn, int method, u_int64_t tid)
{
u_int64_t n_tid;
u_int32_t buf_len, data_len, meth, len = 0;
char *send_buf;
/* send request to master */
meth = htons (GET_TRANS_DATA);
data_len = htonl (ID_LEN);
buf_len = HEADER_LEN + ntohl (data_len);
send_buf = (char *) malloc (buf_len);
/* header */
memcpy (send_buf, &meth, 2);
memcpy (send_buf + 2, flags, 2);
memcpy (send_buf + 4, &data_len, 4);
/* data */
len = 8;
n_tid = htonll (tid);
memcpy (send_buf + len, &n_tid, INT64_LEN);
if (!send_all (conn, send_buf, buf_len))
{
free (send_buf);
return 0;
}
free (send_buf);
return 1;
}
#ifndef storage_request_h
#define storage_request_h
int storageClose (char master_ip[IP_LEN], u_int16_t port,
char storage_id[UUID_LEN]);
int storageStart (int conn,
char storage_id[UUID_LEN], char storage_ip[IP_LEN],
u_int16_t storage_port, char master_id[UUID_LEN],
int *status);
int storageReady (int conn,
char storage_id[UUID_LEN]);
int getTransData (int conn, int method,
u_int64_t tid);
#endif
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <stdio.h>
#include "neo_socket.h"
#include "neo_struct.h"
static u_int16_t rcode = 0;
int
returnTransaction (int conn, int method)
{
u_int32_t data_len;
u_int16_t meth;
char *send_buf;
/* send request to master */
meth = htons (method);
data_len = htonl (0);
send_buf = (char *) malloc (RHEADER_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN + INT32_LEN, &rcode, INT16_LEN);
if (!send_all (conn, send_buf, RHEADER_LEN))
{
free (send_buf);
return 0;
}
free (send_buf);
return 1;
}
int
returnUndo (int conn, int method, u_int64_t * oid_list, u_int32_t nb_oid)
{
u_int64_t n_oid;
u_int32_t buf_len, data_len, n_nb_oid, i;
u_int16_t meth;
char *send_buf;
int len = 0;
/* send request to master */
meth = htons (method);
data_len = htonl (nb_oid * INT64_LEN + INT32_LEN);
buf_len = RHEADER_LEN + ntohl (data_len);
send_buf = (char *) malloc (buf_len);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN + INT32_LEN, &rcode, INT16_LEN);
/* data */
n_nb_oid = htonl (nb_oid);
memcpy (send_buf + RHEADER_LEN, &n_nb_oid, INT32_LEN);
len = RHEADER_LEN + INT32_LEN;
for (i = 0; i < nb_oid; i++)
{
n_oid = htonll (oid_list[i]);
memcpy (send_buf + len, &n_oid, INT64_LEN);
len += INT64_LEN;
}
if (!send_all (conn, send_buf, buf_len))
{
free (send_buf);
return 0;
}
free (send_buf);
return 1;
}
int
returnHistInfo (int conn, int method, struct hist hist) // done
{
u_int64_t n_serial, n_size;
u_int32_t buf_len, data_len, meth;
u_int16_t time_len, user_len, desc_len, len;
char *send_buf, time[10];
snprintf (time, 10, "%10f", hist.time);
/* send request to master */
meth = htons (method);
data_len =
htonl (3 * INT16_LEN + 2 * INT64_LEN + strlen (time) +
strlen (hist.user) + strlen (hist.desc));
buf_len = RHEADER_LEN + ntohl (data_len);
send_buf = (char *) malloc (buf_len);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN + INT32_LEN, &rcode, INT16_LEN);
/* data */
len = RHEADER_LEN;
/* time */
time_len = htons (strlen (time));
memcpy (send_buf + len, &time_len, INT16_LEN);
len += INT16_LEN;
memcpy (send_buf + len, time, strlen (time));
len += strlen (time);
/* user */
user_len = htons (strlen (hist.user));
memcpy (send_buf + len, &user_len, INT16_LEN);
len += INT16_LEN;
memcpy (send_buf + len, hist.user, strlen (hist.user));
len += strlen (hist.user);
/* desc */
desc_len = htons (strlen (hist.desc));
memcpy (send_buf + len, &desc_len, INT16_LEN);
len += INT16_LEN;
memcpy (send_buf + len, hist.desc, strlen (hist.desc));
len += strlen (hist.desc);
/* serial */
n_serial = htonll (hist.serial);
memcpy (send_buf + len, &n_serial, INT64_LEN);
len += INT64_LEN;
/* size */
n_size = htonll (hist.size);
memcpy (send_buf + len, &n_size, INT64_LEN);
if (!send_all (conn, send_buf, buf_len))
{
free (send_buf);
return 0;
}
free (send_buf);
return 1;
}
int
returnUndoInfo (int conn, int method, struct undoInfo hist) // done
{
u_int64_t n_id;
u_int32_t buf_len, data_len, meth;
u_int16_t time_len, user_len, desc_len, len;
char *send_buf, time[10];
sprintf (time, "%10f", hist.time);
/* send request to master */
meth = htons (method);
data_len =
htonl (strlen (time) + strlen (hist.user) + strlen (hist.desc) +
INT64_LEN + 3 * INT16_LEN);
buf_len = RHEADER_LEN + ntohl (data_len);
send_buf = (char *) malloc (buf_len);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN + INT32_LEN, &rcode, INT16_LEN);
/* data */
len = RHEADER_LEN;
/* time */
time_len = htons (strlen (time));
memcpy (send_buf + len, &time_len, INT16_LEN);
len += INT16_LEN;
memcpy (send_buf + len, time, strlen (time));
len += strlen (time);
/* user */
user_len = htons (strlen (hist.user));
memcpy (send_buf + len, &user_len, INT16_LEN);
len += INT16_LEN;
memcpy (send_buf + len, hist.user, strlen (hist.user));
len += strlen (hist.user);
/* desc */
desc_len = htons (strlen (hist.desc));
memcpy (send_buf + len, &desc_len, INT16_LEN);
len += INT16_LEN;
memcpy (send_buf + len, hist.desc, strlen (hist.desc));
len += strlen (hist.desc);
/* id */
n_id = htonll (hist.id);
memcpy (send_buf + len, &n_id, INT64_LEN);;
if (!send_all (conn, send_buf, buf_len))
{
free (send_buf);
return 0;
}
free (send_buf);
return 1;
}
int
returnLoad (int conn, int method, char *object, int32_t crc)
{
u_int64_t object_len;
u_int32_t buf_len, data_len, meth;
int32_t n_crc;
char *send_buf;
/* send request to master */
meth = htons (method);
data_len = htonl (INT64_LEN + strlen (object) + INT32_LEN);
object_len = htonll (strlen (object));
buf_len = RHEADER_LEN + ntohl (data_len);
send_buf = (char *) malloc (buf_len);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN + INT32_LEN, &rcode, INT16_LEN);
/* data */
memcpy (send_buf + RHEADER_LEN, &object_len, INT64_LEN);
memcpy (send_buf + RHEADER_LEN + INT64_LEN, object, strlen (object));
/* crc */
n_crc = htonl (crc);
memcpy (send_buf + RHEADER_LEN + INT64_LEN + strlen (object), &n_crc,
INT32_LEN);
if (!send_all (conn, send_buf, buf_len))
{
free (send_buf);
return 0;
}
free (send_buf);
return 1;
}
int
returnGetSize (int conn, int method, u_int64_t size)
{
u_int32_t buf_len, data_len, meth;
u_int64_t ssize;
char *send_buf;
/* send request to master */
meth = htons (method);
data_len = htonl(INT64_LEN);
ssize = htonll (size);
send_buf = (char *) malloc (RHEADER_LEN + INT64_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN + INT32_LEN, &rcode, INT16_LEN);
/* data */
memcpy (send_buf + RHEADER_LEN, &ssize, INT64_LEN);
if (!send_all (conn, send_buf, RHEADER_LEN + INT64_LEN))
{
free (send_buf);
return 0;
}
free (send_buf);
return 1;
}
int
returnMasterClose (int conn, int method, char *id) // done
{
u_int32_t data_len, meth;
char *send_buf;
/* send request to master */
meth = htons (method);
data_len = htonl (UUID_LEN);
send_buf = (char *) malloc (RHEADER_LEN + UUID_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN + INT32_LEN, &rcode, INT16_LEN);
/* data */
memcpy (send_buf + RHEADER_LEN, id, UUID_LEN);
if (!send_all (conn, send_buf, RHEADER_LEN + UUID_LEN))
{
free (send_buf);
return 0;
}
free (send_buf);
return 1;
}
int
returnMasterChange (int conn, int method, char *id) // done
{
u_int32_t data_len, meth;
char *send_buf;
/* send request to master */
meth = htons (method);
data_len = htonl (UUID_LEN);
send_buf = (char *) malloc (RHEADER_LEN + UUID_LEN);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN + INT32_LEN, &rcode, INT16_LEN);
/* data */
memcpy (send_buf + RHEADER_LEN, id, UUID_LEN);
if (!send_all (conn, send_buf, RHEADER_LEN + UUID_LEN))
{
free (send_buf);
return 0;
}
free (send_buf);
return 1;
}
int
returnErrorMessage (int conn, int method, int code, char *message)
{
u_int32_t buf_len, data_len, meth;
u_int16_t msg_len, err_code;
char *send_buf;
/* send request to nodes */
meth = htons (method);
data_len = htonl (INT16_LEN + strlen (message));
err_code = htons (code);
msg_len = htons (strlen (message));
buf_len = RHEADER_LEN + ntohl (data_len);
send_buf = (char *) malloc (buf_len);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN + INT32_LEN, &err_code, INT16_LEN);
/* data */
memcpy (send_buf + RHEADER_LEN, &msg_len, INT16_LEN);
memcpy (send_buf + RHEADER_LEN + INT16_LEN, message, strlen (message));
if (!send_all (conn, send_buf, buf_len))
{
free (send_buf);
return 0;
}
free (send_buf);
return 1;
}
int
returnGetTransData (int conn, int method, u_int64_t tid, char *user,
char *desc, char *ext, struct objectList list)
{
u_int64_t n_oid, n_serial, n_tid, n_data_size;
u_int32_t buf_len, data_len, nb_object, i, size = 0;
u_int16_t meth, user_len, desc_len, ext_len;
char *send_buf;
int tlen = 0;
/* send request to master */
meth = htons (method);
user_len = htons (strlen (user));
desc_len = htons (strlen (desc));
ext_len = htons (strlen (ext));
// get data from struct
nb_object = htonl (list.last);
/* must get data size for packet */
for (i = 0; i < list.last; i++)
size += strlen (list.list[i].data);
data_len =
htonl (list.last * (2 * INT64_LEN + INT64_LEN) + size + INT32_LEN +
INT64_LEN + 3 * INT16_LEN + strlen (user) + strlen (desc) +
strlen (ext));
buf_len = RHEADER_LEN + ntohl (data_len);
send_buf = (char *) malloc (buf_len);
/* header */
memcpy (send_buf, &meth, INT16_LEN);
memcpy (send_buf + INT16_LEN, flags, FLAG_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN, &data_len, INT32_LEN);
memcpy (send_buf + INT16_LEN + FLAG_LEN + INT32_LEN, &rcode, INT16_LEN);
/* data */
tlen = RHEADER_LEN;
n_tid = htonll (tid);
memcpy (send_buf + tlen, &n_tid, ID_LEN);
tlen += INT64_LEN;
/* transaction info */
memcpy (send_buf + tlen, &user_len, INT16_LEN);
tlen += INT16_LEN;
memcpy (send_buf + tlen, user, strlen (user));
tlen += strlen (user);
memcpy (send_buf + tlen, &desc_len, INT16_LEN);
tlen += INT16_LEN;
memcpy (send_buf + tlen, desc, strlen (desc));
tlen += strlen (desc);
memcpy (send_buf + tlen, &ext_len, INT16_LEN);
tlen += INT16_LEN;
memcpy (send_buf + tlen, ext, strlen (ext));
tlen += strlen (ext);
/* object list */
memcpy (send_buf + tlen, &nb_object, INT32_LEN);
tlen += INT32_LEN;
for (i = 0; i < list.last; i++)
{
n_oid = htonll (list.list[i].oid);
memcpy (send_buf + tlen, &n_oid, INT64_LEN);
tlen += INT64_LEN;
n_serial = htonll (list.list[i].serial);
memcpy (send_buf + tlen, &n_serial, INT64_LEN);
tlen += INT64_LEN;
n_data_size = htonll (strlen (list.list[i].data));
memcpy (send_buf + tlen, &n_data_size, INT64_LEN);
tlen += INT64_LEN;
memcpy (send_buf + tlen, list.list[i].data, strlen (list.list[i].data));
tlen += strlen (list.list[i].data);
}
if (!send_all (conn, send_buf, buf_len))
{
free (send_buf);
return 0;
}
free (send_buf);
return 1;
}
#ifndef storage_return_h
#define storage_return_h
int returnTransaction (int conn, int method);
int returnUndo (int conn, int method, u_int64_t * oid, u_int32_t nb_oid);
int returnHistInfo (int conn, int method, struct hist hist);
int returnUndoInfo (int conn, int method, struct undoInfo hist);
int returnLoad (int conn, int method, char *object, int32_t crc);
int returnGetSize (int conn, int method, u_int64_t size);
int returnMasterClose (int conn, int method, char *id);
int returnMasterChange (int conn, int method, char *id);
int returnErrorMessage (int conn, int method, int code, char *message);
int returnGetTransData (int conn, int method, u_int64_t tid, char *user,
char *desc, char *ext, struct objectList objects);
#endif
EXTRA_DIST = functional_test.py performances_test.py unit_test.py neo.conf \
profile_test.py perf_result.txt trivial_client_test.py
# Makefile.in generated by automake 1.7.9 from Makefile.am.
# @configure_input@
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
# Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
ACLOCAL = @ACLOCAL@
AMDEP_FALSE = @AMDEP_FALSE@
AMDEP_TRUE = @AMDEP_TRUE@
AMTAR = @AMTAR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
MAKEINFO = @MAKEINFO@
MYSQL_CONFIG = @MYSQL_CONFIG@
MYSQL_INCLUDE = @MYSQL_INCLUDE@
MYSQL_LDFLAGS = @MYSQL_LDFLAGS@
MYSQL_LIBS = @MYSQL_LIBS@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PYTHON = @PYTHON@
PYTHON_BASECFLAGS = @PYTHON_BASECFLAGS@
PYTHON_CC = @PYTHON_CC@
PYTHON_CCSHARED = @PYTHON_CCSHARED@
PYTHON_INCLUDE = @PYTHON_INCLUDE@
PYTHON_LDSHARED = @PYTHON_LDSHARED@
PYTHON_OPT = @PYTHON_OPT@
PYTHON_SO = @PYTHON_SO@
RANLIB = @RANLIB@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
ac_ct_CC = @ac_ct_CC@
ac_ct_RANLIB = @ac_ct_RANLIB@
ac_ct_STRIP = @ac_ct_STRIP@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
bindir = @bindir@
build_alias = @build_alias@
datadir = @datadir@
exec_prefix = @exec_prefix@
host_alias = @host_alias@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localstatedir = @localstatedir@
mandir = @mandir@
oldincludedir = @oldincludedir@
prefix = @prefix@
program_transform_name = @program_transform_name@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
EXTRA_DIST = functional_test.py performances_test.py unit_test.py neo.conf \
profile_test.py perf_result.txt trivial_client_test.py
subdir = test
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
DIST_SOURCES =
DIST_COMMON = $(srcdir)/Makefile.in Makefile.am
all: all-am
.SUFFIXES:
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4)
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu test/Makefile
Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
uninstall-info-am:
tags: TAGS
TAGS:
ctags: CTAGS
CTAGS:
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
top_distdir = ..
distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
list='$(DISTFILES)'; for file in $$list; do \
case $$file in \
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
esac; \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkinstalldirs) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic mostlyclean-am
distclean: distclean-am
-rm -f Makefile
distclean-am: clean-am distclean-generic
dvi: dvi-am
dvi-am:
info: info-am
info-am:
install-data-am:
install-exec-am:
install-info: install-info-am
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-generic
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-info-am
.PHONY: all all-am check check-am clean clean-generic distclean \
distclean-generic distdir dvi dvi-am info info-am install \
install-am install-data install-data-am install-exec \
install-exec-am install-info install-info-am install-man \
install-strip installcheck installcheck-am installdirs \
maintainer-clean maintainer-clean-generic mostlyclean \
mostlyclean-generic pdf pdf-am ps ps-am uninstall uninstall-am \
uninstall-info-am
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
#! /usr/bin/env python
#
# Functional test script for the neo system
# See how it works if we get storage failure and recovery
#
import os, time, sys, signal, random
from ZODB import Transaction
from NEO import neostorage
from threading import Thread, Lock
login = 'aurelien'
config_file = "neo.conf"
class foo:
""" class for testing object """
pass
NUM_CLIENTS = 20
NUM_THREADS_PER_CLIENT = 5
NUM_REQUESTS = 20
NUM_OBJECTS_PER_TRANS = 1
OBJECT_DATA = "data for objects..."
NO_VERSION = 0
CRASH_FREQUENCY =400 # frequency of crash relative to the number of requests
storages_list = {}
objects_list = []
user_thread_list = []
client_thread_list = []
request_cpt = 0
neomaster_ip = None
cpt_lock = Lock()
# functions for managing nodes
def setup_nodes():
""" setup master and storage nodes from the config file """
global neomaster_ip
f = open(config_file, "r")
line = f.readline()
while line != '':
# comment line
if line[0] == '#':
line = f.readline()
continue
# read config line
line = line.split(' ', 4)
type = line[0]
ip = line[1]
exec_path = line[2]
path_to_bin = line[3]
options = line[4]
if options[-1] == '\n':
options = options[:-1]
# setup the node
if type == 'master':
neomaster_ip = ip
os.system('ssh '+login+'@'+ip+' "cd '+exec_path+'; '+path_to_bin+'neomaster '+options+'" &')
if type == 'storage':
storages_list[len(storages_list)] = (ip, exec_path, path_to_bin, options)
os.system('ssh '+login+'@'+ip+' "cd '+exec_path+'; '+path_to_bin+'neostorage '+options+' -m'+neomaster_ip+'" &')
# wait for init
time.sleep (1)
line = f.readline()
def crash_node(node):
""" kill a node """
os.system('ssh '+login+'@'+str(node[0])+' killall '+str(node[2])+'neostorage -sSEGV &')
print 'functional test : on node %s, storage crashed' %(node[0])
def restart_node(node):
""" restart a node """
global neomaster_ip
os.system('ssh '+login+'@'+str(node[0])+' "cd '+str(node[1])+'; '+str(node[2])+'neostorage -l3 -m'+neomaster_ip+' &>/dev/null" &')
print 'functional test : storage on node %s restarted' %(node[0])
def close_master():
""" when master node close, all storages nodes are close automatically """
global neomaster_ip
os.system('ssh '+login+'@'+neomaster_ip+' killall neomaster')
# functions for managing ZODB behaviour
def createTransaction():
""" create a zodb transaction """
txn = Transaction.Transaction()
txn.user = "test user"
txn.description = "transaction for functional tests"
txn.extension = "None"
return txn
def storeObjects(db):
""" store objects into database """
t = createTransaction()
tid = db.tpc_begin(t)
for i in xrange(NUM_OBJECTS_PER_TRANS):
oid = db.new_oid()
objects_list.append(oid)
obj = foo()
obj.data = OBJECT_DATA
db.store(oid, None, obj, 0, t)
db.tpc_vote(t)
db.tpc_finish(t)
# functions for simulating users behaviour
def simulate_neo_user(db=None):
""" simulate a user storing some objects """
global request_cpt
for i in xrange(NUM_REQUESTS):
cpt_lock.acquire()
request_cpt+=1
print 'simulate_neo_user : i %r, db %r, request_cpt %r' %(i, db, request_cpt)
cpt_lock.release()
storeObjects(db)
# check if we have to crash a node
cpt_lock.acquire()
if (request_cpt % CRASH_FREQUENCY) == 0:
cpt_lock.release()
print 'crashing node...'
# XXX may find a better way to do this
s = random.choice (storages_list)
crash_node(s)
time.sleep(2)
restart_node(s)
else:
cpt_lock.release()
def simulate_neo_client():
""" simulate a neoclient wich handle many connection from users """
db = neostorage.neostorage(master = neomaster_ip)
# each client have some users
for i in xrange(NUM_THREADS_PER_CLIENT):
th = Thread(target=simulate_neo_user, args=(db,))
th.start()
user_thread_list.append(th)
for th in user_thread_list:
th.join()
# try to load all objects created by users
for oid in objects_list:
object, serial = db.load(oid, NO_VERSION)
assert object.data == OBJECT_DATA, 'different data for object'
if __name__ == '__main__':
setup_nodes()
for i in xrange(NUM_CLIENTS):
th = Thread(target=simulate_neo_client, args=())
th.start()
client_thread_list.append(th)
for th in client_thread_list:
th.join()
close_master()
# config file for the unit test
# first line must be the master node
# path must end with '/'
# don't put the -c option here, and make sure the database dir exist
# content of a line : name ip path options
# type where exec_path path_to_exec options
master aubox neo/src/master/ ./ -l3 -r1 -d ./db
storage aubox neo/src/storage/ ./ -l3 -d ./db
storage robox ./ ./ -l3 -d ./tmp/db1
storage robox ./tmp/ ../ -l3 -d ./db2
aurelien@tinyleon /home/aurelien/neo/test % ./testPerf.py fs
MakeTransaction test time : 1.18748 s
Store test time : 0.85873 s
Load test time : 0.18928 s
Load from serial test time : 0.23414 s
Get history test time : 0.44399 s
New oid test time : 0.90766 s
aurelien@tinyleon /home/aurelien/neo/test % ./testPerf.py neo (one replication)
MakeTransaction test time : 3.08242 s
Store test time : 3.71913 s
Load test time : 0.50854 s
Load from serial test time : 1.21174 s
Get history test time : 45.34129 s
New oid test time : 3.45416 s
aurelien@tinyleon /home/aurelien/neo/test % ./testPerf.py zeo
MakeTransaction test time : 52.15134 s
Store test time : 5.22532 s
Load test time : 0.21759 s
Load from serial test time : 19.80786 s
Get history test time : 12.50073 s
New oid test time : 4.39331 s
aurelien@tinyleon /home/aurelien/neo/test % ./testPerf.py neo (two replication)
MakeTransaction test time : 2.88133 s
Store test time : 3.79288 s
Load test time : 0.43135 s
Load from serial test time : 1.30829 s
Get history test time : 19.67929 s
New oid test time : 3.51044 s
#!/usr/bin/python
#
# Script for testing neo, zeo and file storage perfomances
#
from NEO import neostorage
import ZODB
from Persistence import Persistent
from ZODB.FileStorage import FileStorage
from ZODB.tests.StorageTestBase import removefs
from ZODB.utils import oid_repr, p64, u64, U64
from ZEO.ClientStorage import ClientStorage
from ZEO.tests import forker
from timeit import Timer
from random import choice, randrange
import sys, os, signal
class foo(Persistent):
""" Object use in transaction, must implement
some variable and funtion to work correctly """
def __init__(self, jar = None, oid = None):
self._p_jar = jar
self._p_oid = oid
self._p_changed = 1
def __getstate__(self):
pass
listOid = []
listTrans = []
def StoreTest(c):
""" Store many objects in one transaction """
try:
# init
t = ZODB.Transaction.Transaction()
c.tpc_begin(t)
# create objects
for i in xrange(100000):
oid = c.new_oid()
listOid.append(oid)
obj = foo(c, oid)
obj.test = U64(oid)
# store it
c.commit(obj, t)
# finish transaction
c.tpc_vote(t)
c.tpc_finish(t)
except:
raise
def LoadTest(c):
""" Load many objects """
try:
for oid in listOid:
# c[oid]
c._storage.load (oid, None)
except:
raise
def GetHistoryTest(db):
""" Get history foe each object """
for oid in listOid:
db.history(oid,None)
def LoadFromSerialTest(c):
""" Load serial version of object """
for oid in listOid:
s = c._storage.getSerial(oid)
c._storage.loadSerial(oid, s)
def MakeTransactionTest(c):
""" Make many transactions """
try:
for i in xrange(5000):
t = ZODB.Transaction.Transaction()
# listTrans.append(t)
c.tpc_begin(t)
# create one object per transaction
oid = c.new_oid()
obj = foo(c, oid)
obj.test = '25'
c.commit(obj, t)
# finish transaction
c.tpc_vote(t)
c.tpc_finish(t)
except:
raise
def UndoTransactionTest(c, db):
""" Undo some transactions """
for i in xrange(10):
log = db.undoLog(0,-50)
tid = choice(log)['id']
db.undo(tid)
def getSizeTest(db):
""" Get size of storage """
db.getSize()
def new_oidTest(c):
""" Get many new oid """
for i in range(100000):
oid = c.new_oid()
# print len(oid)
# class to test performances
class perf:
""" super class for performances test
a subclass might override """
def __init__(self):
self.storage = None
def run(self):
self.db = ZODB.DB(self.storage)
self.c = self.db.open()
# tests
t = Timer("MakeTransactionTest(perf.c)", "from __main__ import MakeTransactionTest, perf")
print 'MakeTransaction test time : %.5f s' % t.timeit(number=1)
t = Timer("StoreTest(perf.c)", "from __main__ import StoreTest, perf")
print 'Store test time : %.5f s' % t.timeit(number=1)
t = Timer("LoadTest(perf.c)", "from __main__ import LoadTest, perf")
print 'Load test time : %.5f s' % t.timeit(number=1)
# t = Timer("LoadFromSerialTest(perf.c)", "from __main__ import LoadFromSerialTest, perf")
# print 'Load from serial test time : %.5f s' % t.timeit(number=1)
# t = Timer("GetHistoryTest(perf.db)", "from __main__ import GetHistoryTest, perf")
# print 'Get history test time : %.5f s' % t.timeit(number=1)
# t = Timer("new_oidTest(perf.c)", "from __main__ import new_oidTest, perf")
# print 'New oid test time : %.5f s' % t.timeit(number=1)
# XXX not use for test yet
# t = Timer("UndoTransactionTest(c, db)", "from __main__ import UndoTransactionTest, c, db")
# print 'UndoTransaction test time : %.5f s' % t.timeit(number=1)
# t = Timer("getSizeTest(db)", "from __main__ import getSizeTest, db")
# print 'getSize test time : %.5f s' % t.timeit(number=1)
class neo_perf(perf):
""" class to mesure neo performances """
def __init__(self):
self.storage = neostorage.neostorage(master = '127.0.0.1')
def __del__(self):
self.db.close()
self.c._storage.closeStorageConnection()
pid = os.getpid()
os.kill(pid, signal.SIGTERM)
class zeo_perf(perf):
""" class to mesure zeo performances """
def __init__(self):
# create zeo config
storage_conf = """<filestorage 1>
path /home/aurelien/zeo_instance/var/Data.fs
</filestorage>
<eventlog>
level error
<logfile>
path /home/aurelien/zeo.log
</logfile>
</eventlog>
"""
zaddr = '', randrange(20000, 30000)
zeo_conf = forker.ZEOConfig(zaddr)
# create zeo server
t, addr, pid, exitobj = forker.start_zeo_server(storage_conf, zeo_conf, zaddr[1])
# create db and connection to storage
self.storage = ClientStorage(zaddr, debug=0, min_disconnect_poll=0.5, wait=1)
def __del__(self):
self.db.close()
class fs_perf(perf):
""" class to mesure file storage performances """
def __init__(self):
self.storage = FileStorage("cluster.fs")
def __del__(self):
self.db.close()
removefs("cluster.fs")
if __name__ == "__main__":
if len(sys.argv) !=2:
sys.exit('argument missing')
if sys.argv[1] == 'neo':
perf = neo_perf()
elif sys.argv[1] == 'fs':
perf = fs_perf()
elif sys.argv[1] == 'zeo':
perf = zeo_perf()
else:
sys.exit('wrong argument')
perf.run()
#!/usr/bin/python
#
# Script to profile neo and zeo storage system
#
from NEO import neostorage
from Persistence import Persistent
import ZODB, profile, pstats, sys
from random import randrange
from ZEO.ClientStorage import ClientStorage
from ZEO.tests import forker
listOid = []
class foo(Persistent):
""" Test object """
def __init__(self, jar = None, oid = None):
self._p_jar = jar
self._p_oid = oid
self._p_changed = 1
def __getstate__(self):
pass
def MakeTransactionTest(c):
""" Make many transaction """
try:
for i in xrange(1000):
t = ZODB.Transaction.Transaction()
c.tpc_begin(t)
# create one object
oid = c.new_oid()
obj = foo(c, oid)
obj.test = '25'
c.commit(obj, t)
# finish transaction
c.tpc_vote(t)
c.tpc_finish(t)
except:
raise
def StoreTest(c):
""" Store many object in one transaction """
try:
# init
t = ZODB.Transaction.Transaction()
c.tpc_begin(t)
# create objects
for i in xrange(5000):
oid = c.new_oid()
listOid.append(oid)
obj = foo(c, oid)
obj.test = oid
# store it
c.commit(obj, t)
# finish transaction
c.tpc_vote(t)
c.tpc_finish(t)
except:
raise
def LoadTest(c):
""" Load many object from the storage """
for oid in listOid:
c._storage.load (oid, None)
def GetHistoryTest(c, db):
""" Get history from object """
for oid in listOid:
db.history(oid,None)
def LoadFromSerialTest(c):
""" Load some Serial """
for oid in listOid:
s = c._storage.getSerial(oid)
c._storage.loadSerial(oid, s)
class profiler:
""" super class for profiling storage system
a dubclass might override """
def __init__(self):
self.storage = None
def run(self):
db = ZODB.DB(self.storage)
c = db.open()
# make test
MakeTransactionTest(c)
StoreTest(c)
LoadTest(c)
LoadFromSerialTest(c)
GetHistoryTest(c, db)
class neo_profiler(profiler):
""" class to profile neo application execution """
def __init__(self):
self.storage = neostorage.neostorage(master = '127.0.0.1')
self.run()
class zeo_profiler(profiler):
""" class to profile zeo application execution """
def __init__(self):
storage_conf = """<filestorage 1>path /home/aurelien/zeo_instance/var/Data.fs</filestorage> """
zaddr = '', randrange(20000, 30000)
zeo_conf = forker.ZEOConfig(zaddr)
# create zeo server
t, addr, pid, exitobj = forker.start_zeo_server(storage_conf, zeo_conf, zaddr[1])
# create db and connection to storage
self.storage = ClientStorage(zaddr, debug=0, min_disconnect_poll=0.5, wait=1)
self.run()
if __name__ == "__main__":
if len(sys.argv) !=2:
sys.exit('argument missing')
if sys.argv[1] == 'neo':
profile.run ('neo_profiler()', 'result')
elif sys.argv[1] == 'zeo':
profile.run ('zeo_profiler()', 'result')
else:
sys.exit ('wrong argument')
# display result
p = pstats.Stats('result')
p.strip_dirs().sort_stats('cumulative').print_stats(30)
p.print_callees()
#! /usr/bin/env python
#
# Some functions to test quickly basics functions of neo
#
from NEO import neostorage
from ZODB import POSException, Transaction
from ZODB.utils import oid_repr, p64, U64
oid1 = ''
serial1 = ''
class foo:
""" class representing an object """
pass
def store_objects(c):
""" store some objects in one transaction """
global oid1, serial1
oid1 = c.new_oid()
oid2 = c.new_oid()
oid3 = c.new_oid()
print "apply store_object : new oid %s %s" %(U64(oid1), oid_repr(oid1))
# try to load an object
try:
ob = c.load(oid1, 0)
except POSException.POSKeyError:
print 'apply store_object : object not found'
# store an object using transaction
txn = Transaction.Transaction()
txn.user = "moi"
txn.description = "transaction test"
txn.extension = "no extension"
serial = c.tpc_begin(txn)
serial1 = serial
print "apply store_object : serial %s" %oid_repr(serial)
# first object
ob1 = foo()
ob1.txt = "object data for testing"
c.store(oid1, None, ob1, 0, txn)
# try with second object
ob2 = foo()
ob2.txt = "second object data for testing"
c.store(oid2, None, ob2, 0, txn)
# try with third object
ob3 = foo()
ob3.txt = "third object data for testing"
c.store(oid3, None, ob3, 0, txn)
# make transaction
c.tpc_vote(txn)
c.tpc_finish(txn)
# now undo trans
# c.transactionalUndo (serial)
txn = None
print "apply store_object : transaction finished"
c.load(oid1, 0)
def update_object(c):
""" update one object already stored """
# load object
ob = c.load(oid1, 0)
print 'apply update_object : object load with data : %s' %ob.txt
# create transaction
txn = Transaction.Transaction()
txn.user = "moi"
txn.description = "transaction test for update"
txn.extension = "no extension"
serial = c.tpc_begin(txn)
# modify it
print 'apply update_object : transaction serial %s' %U64(serial)
ob.txt = "data updated for object"
# store transaction
oldserial = c.getSerial(oid1)
print oid_repr(oldserial), oid_repr(oldserial)
c.store(oid1, oldserial, ob, 0, txn)
c.tpc_vote(txn)
c.tpc_finish(txn)
print 'apply update_object : update transaction ended'
def load_last(c):
""" load last version of object """
ob = c.load(oid1, 0)
print 'apply load_last : last object load with data : %s' %ob.txt
def load_old(c):
""" load an old version of object """
ob = c.loadSerial(oid1,serial1)
print 'apply load_old : old object load with data : %s' %ob.txt
def get_serial(c):
""" get serial of an objet and load it """
serial = c.getSerial(oid1)
print 'apply get_serial : serial get %s' %U64(serial)
ob = c.loadSerial (oid1, serial)
print 'apply get_serial : load serial, data : %s' %ob.txt
def lastTrans(c):
""" get last transaction id """
ltid = c.lastTransaction()
print 'apply lastTrans : last transaction id : %s' %U64(ltid)
def transInfo(c):
""" get info about the two last transaction """
infos = c.undoInfo(last=-2)
print "apply transInfos : "
print infos
def objectHistory(c):
""" get history for one object """
hist = c.history(oid1, length = 2)
print "apply objectHistory : "
print hist
def abortInTrans(c):
""" abort transaction before finished, called after vote """
oid1 = c.new_oid()
oid2 = c.new_oid()
print "apply : new oid %s %s" %(oid_repr(oid1), oid_repr(oid2))
# store an object using transaction
txn = Transaction.Transaction()
txn.user = "moi"
txn.description = "transaction test"
txn.extension = "no extension"
serial = c.tpc_begin(txn)
print "apply : serial %s" %oid_repr(serial)
# first object
ob1 = foo()
ob1.txt = "object data for testing"
c.store(oid1, serial, ob1, 0, txn)
# try with second object
ob2 = foo()
ob2.txt = "second object data for testing"
c.store(oid2, serial, ob2, 0, txn)
# make transaction
c.tpc_vote(txn)
c.tpc_abort(txn)
txn = None
print "apply : transaction aborted"
def transUndo(c):
""" Test the transactional undo method """
oid1 = c.new_oid()
oid2 = c.new_oid()
print "undo : apply : new oid %s %s" %(oid_repr(oid1), oid_repr(oid2))
# store an object using transaction
txn = Transaction.Transaction()
txn.user = "moi"
txn.description = "undo transaction test"
txn.extension = "no extension"
serial = c.tpc_begin(txn)
print "apply : serial %s" %oid_repr(serial)
# first object
ob1 = foo()
ob1.txt = "object data for testing"
c.store(oid1, serial, ob1, 0, txn)
# try with second object
ob2 = foo()
ob2.txt = "second object data for testing"
c.store(oid2, serial, ob2, 0, txn)
# make transaction
c.tpc_vote(txn)
c.transactionalUndo(serial, txn)
print 'apply : trans undo done'
if __name__ == '__main__':
# instantiate storage and run some test
c = neostorage.neostorage (master = '127.0.0.1')
store_objects(c)
update_object(c)
load_last(c)
load_old(c)
get_serial(c)
lastTrans(c)
transInfo(c)
# transUndo(c)
# abortInTrans(c)
# objectHistory(c)
# c.close()
#! /usr/bin/env python
import unittest, os, signal, struct, socket, time
from ZODB import Transaction
from ZODB.POSException import UndoError, POSKeyError, MultipleUndoErrors, StorageTransactionError
from ZODB.utils import oid_repr, p64, u64, U64
from NEO import neostorage
login = "aurelien"
config_file = "neo.conf"
storages = {}
master_ip = None
def createTransaction():
txn = Transaction.Transaction()
txn.user = "unit tester"
txn.description = "transaction for unit tests"
txn.extension = "None"
return txn
def setupNodes():
""" instore the storage and master node from the neo.conf file """
f = open (config_file, "r")
line = f.readline()
while line != '':
if line[0] == '#': # comment line
line = f.readline()
continue
line = line.split(' ', 3)
type = line[0]
ip = line[1]
path = line[2]
options = line[3][:-1]
if type == 'master':
global master_ip
master_ip = ip
os.system('ssh '+login+'@'+ip+' '+path+'neomaster '+options+' &>/dev/null &') # &>/dev/null
elif type == 'storage':
global storages
storages[len(storages)] = (ip, path)
os.system('ssh '+login+'@'+ip+' '+path+'neostorage '+options+' -m'+master_ip+' &')
time.sleep (2)
line = f.readline()
class foo:
pass
class NeoTests (unittest.TestCase):
""" Unit test class """
def setUp (self):
global master_ip
time.sleep (2)
self.storage = neostorage.neostorage(master = master_ip)
def tearDown (self):
self.storage.close()
def testLoadGetObject (self):
""" store and load the same object, then compare data """
t = createTransaction()
tid = self.storage.tpc_begin(t)
oid = self.storage.new_oid()
obj1 = foo()
obj1.data = 'data for unit test'
self.storage.store(oid, tid, obj1, 0, t)
self.storage.tpc_vote(t)
self.storage.tpc_finish(t)
obj2, s2 = self.storage.load(oid, 0)
self.assertEqual (obj1.data, obj2.data)
def testLoadUnknownObject (self):
""" try to load an unknown object """
oid = self.storage.new_oid()
self.assertRaises(POSKeyError, self.storage.load, oid, 0)
def testGetHistory (self):
""" check if history for an object stord is not None """
t = createTransaction()
tid = self.storage.tpc_begin(t)
oid = self.storage.new_oid()
obj1 = foo()
obj1.data = 'data testing'
self.storage.store(oid, tid, obj1, 0, t)
self.storage.tpc_vote(t)
self.storage.tpc_finish(t)
hist = self.storage.history(oid, 1)
self.assertEqual (hist[0]['user_name'], 'unit tester')
self.assertEqual (U64(hist[0]['serial']), U64(tid))
def testIncreasingOid (self):
oid_list = []
for i in xrange (20):
oid_list.append(self.storage.new_oid())
for i in xrange (19):
self.failIf (oid_list[i] > oid_list[i+1])
def testTwoTransactions (self):
""" Transaction can be done just one at a time """
t1 = createTransaction()
t2 = createTransaction()
self.storage.tpc_begin(t1)
self.assertRaises (StorageTransactionError, self.storage.tpc_vote, t2)
def testUndoTransaction (self):
""" check if object from undone transaction doesn't exist """
t = createTransaction()
tid = self.storage.tpc_begin(t)
oid = self.storage.new_oid()
obj1 = foo()
obj1.data = 'data testing'
self.storage.store(oid, tid, obj1, 0, t)
self.storage.tpc_vote(t)
self.storage.transactionalUndo(tid, t)
self.assertRaises (POSKeyError, self.storage.loadSerial, oid, tid)
def testUndoUnknownTransaction(self):
t = createTransaction
self.storage.tpc_begin(t)
tid = self.storage.new_oid()
self.assertRaises (UndoError , self.storage.transactionalUndo, tid, t)
def testUndoInfo (self):
t = createTransaction()
tid = self.storage.tpc_begin(t)
oid = self.storage.new_oid()
obj1 = foo()
obj1.data = 'data testing'
NO_VERSION = 0
self.storage.store(oid, tid, obj1, 0, t)
self.storage.tpc_vote(t)
self.storage.tpc_finish(t)
undo = self.storage.undoInfo()
self.assertEqual(undo[0]['username'], 'unit tester')
self.assertEqual(U64(undo[0]['id']), U64(tid))
def testSupportVersion (self):
self.assertEqual(0, self.storage.supportsVersions())
def testSupportUndo (self):
self.assertEqual(1, self.storage.supportsUndo())
def testStorageName (self):
self.assertEqual('Cluster Storage system', self.storage.getName())
def testStorageName (self):
self.failIf(self.storage.getSize() < 0)
def testLoadSerial (self):
# make a first transaction
t = createTransaction()
tid1 = self.storage.tpc_begin(t)
oid = self.storage.new_oid()
obj1 = foo()
obj1.data = 'data testing'
self.storage.store(oid, None, obj1, 0, t)
self.storage.tpc_vote(t)
self.storage.tpc_finish(t)
# make a second one with the same object
t = createTransaction()
tid2 = self.storage.tpc_begin(t)
obj2 = foo()
obj2.data = 'updated data testing'
self.storage.store(oid, tid1, obj2, 0, t)
self.storage.tpc_vote(t)
self.storage.tpc_finish(t)
# load old one
obj3 = self.storage.loadSerial(oid, tid1)
self.assertEqual(obj1.data, obj3.data)
# get serial
self.assertEqual(tid2, self.storage.getSerial(oid))
# load last one
obj4, s4 = self.storage.load(oid, 0)
self.assertEqual(obj2.data, obj4.data)
# def testMasterBadMessages (self):
# """ test if master node doesn't crash with bad format message """
# for i in xrange (26):
# buf = struct.pack('!HccI 40s', i, ' ', ' ', 40000, 'p'*40000 )
# self.storage.MasterSock.sendall(buf)
# # dont call method 26 otherwise it close connection
# for i in xrange (27, 50):
# buf = struct.pack('!HccI 40s', i, ' ', ' ', 40000, 'p'*40000 )
# self.storage.MasterSock.sendall(buf)
# def testStorageBadMessages (self):
# """ test if storage node doesn't crash with bad format message """
# sock = None
# # get one storage
# s = neostorage.storages.popitem()
# for i in xrange(28):
# buf = struct.pack('!HccI 40s', i, ' ', ' ', 40000, 'p'*40000 )
# sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# sock.connect((s[1][0], s[1][1]))
# sock.sendall(buf)
# sock.close()
# # don't call method 28 otherwise storage close
# for i in xrange(29,50):
# buf = struct.pack('!HccI 40s', i, ' ', ' ', 40000, 'p'*40000 )
# sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# sock.connect((s[1][0], s[1][1]))
# sock.sendall(buf)
# sock.close()
# def testBigSizeMessage (self):
# """ test a big message """
# buf = struct.pack('!HccLs', 10, ' ', ' ', 929496729, 'p'*929496729 )
# self.storage.MasterSock.sendall(buf)
def test_suite():
s = unittest.makeSuite(NeoTests, 'test')
return s
def kill_neo():
os.system('ssh '+login+'@'+master_ip+' killall neomaster')
for storage in storages.values():
os.system('ssh '+login+'@'+str(storage[0])+' killall neostorage')
if __name__=='__main__':
setupNodes()
unittest.TextTestRunner().run(test_suite())
# kill unit test program
kill_neo()
pid = os.getpid()
os.kill(pid, signal.SIGTERM)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment