Create a sandbox branch to experiment with latest APR.

git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1052740 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
jsdelfino 2010-12-25 01:49:19 +00:00
commit dc15dc32bb
590 changed files with 55306 additions and 0 deletions

View file

@ -0,0 +1,5 @@
Apache Tuscany SCA Runtime
==========================
The Apache Software Foundation (http://www.apache.org/)

View file

@ -0,0 +1,203 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View file

@ -0,0 +1,12 @@
Apache Tuscany SCA Runtime
==========================
For a log of all changes see the Tuscany commits mailing list:
commits@tuscany.apache.org
Archives:
http://www.mail-archive.com/commits@tuscany.apache.org
To subscribe send an email to:
commits-subscribe@tuscany.apache.org

View file

@ -0,0 +1,216 @@
Apache Tuscany SCA Runtime
==========================
Automated installation on Ubuntu 10.10 64-bit
=============================================
Tuscany provides two automated install scripts for Ubuntu. You can start with
a fresh Ubuntu Server 10.10 64-bit system and these scripts will take care of
all the download, build and installation steps for you.
ubuntu/ubuntu-install-all:
Complete build and installation with most dependencies built from source.
System dependencies are downloaded and installed using sudo apt-get. Source
dependencies are downloaded and built in the current directory.
To run the automated installation:
mkdir tuscany
cd tuscany
wget http://svn.apache.org/repos/asf/tuscany/sca-cpp/trunk/ubuntu/ubuntu-install-all
chmod +x ./ubuntu-install-all
./ubuntu-install-all
The installation script will display each command as it's executed.
That's all you need to do to build and install the Tuscany SCA runtime on
Ubuntu 10.10 64-bit.
For manual build and install steps on other systems or if you need to customize
your installation, read on...
Building
========
The Tuscany SCA Linux build uses the GNU Autotools tool chain.
First install the following development tools:
autoconf-2.67
automake-1.11
libtool-2.2.6
doxygen-1.7.1
gcc-g++-4.4.5
Then install the following development dependencies:
Apache HTTP server and APR:
httpd-2.3.8 (http://httpd.apache.org/)
with included libapr and libaprutil
built with OpenSSL libssl-0.9.8, libpcre3-8.02,
and expat 2.0.1
Memcached:
memcached-1.4.5 (http://memcached.org/)
built with libevent-1.4.13
XML:
libxml2-2.7.7 (http://xmlsoft.org/)
CURL:
curl-7-19-5
libcurl4-openssl-7.19.5
JSON:
Mozilla TraceMonkey libmozjs (https://wiki.mozilla.org/JavaScript:TraceMonkey)
also included in xulrunner-1.9.2
Key/value store:
tinycdb-0.77 (http://www.corpit.ru/mjt/tinycdb.html)
Optional dependencies:
Web Services:
Apache Axis2/C 1.6.0 (http://ws.apache.org/axis2/c/)
Queueing:
Apache Qpid/C++ 0.6 (http://qpid.apache.org/)
built with libuuid-2.17.2, libboost-1.42.0, libboost-program-options-1.42.0 and
libboost-filesystem-1.42.0
Python:
Python 2.6.6 (http://www.python.org/)
Google AppEngine 1.4.0 (http://code.google.com/appengine/)
Java:
a Java 5+ JDK (http://openjdk.java.net/, http://harmony.apache.org/)
OpenID authentication:
Mod_auth_openid (http://trac.butterfat.net/public/mod_auth_openid)
build it from source at http://github.com/jsdelfino/mod_auth_openid
requires Libopkele (http://kin.klever.net/libopkele/ or
http://github.com/jsdelfino/libopkele)
and HTML Tidy (http://tidy.sourceforge.net/)
OAuth authorization:
Liboauth 0.9.1 (http://liboauth.sourceforge.net/)
XMPP Chat:
Apache Vysper 0.5 (http://mina.apache.org/)
Libstrophe (http://code.stanziq.com/strophe/)
build it from source at git://github.com/jsdelfino/libstrophe.git
SQL Database:
postgresql-9.0.1 (http://www.postgresql.org/)
Logging:
Facebook Scribe 2.2 (http://github.com/facebook/scribe/downloads)
requires Apache Thrift 0.2.0 (http://incubator.apache.org/thrift/)
Cloud deployment:
Apache Libcloud 0.3.1 (http://incubator.apache.org/libcloud/)
To configure the Tuscany SCA build do this:
./bootstrap
./configure --prefix=<install dir>
To enable debugging and strict warning compile options, add:
--enable-maintainer-mode
To enable gprof profiling, add:
--enable-profiling
To enable multi-threading (required by the Queue and Chat components and
for running with the HTTPD worker or event multi-threaded MPMs):
--enable-threads
To enable support for Python component implementations:
--enable-python
To enable support for Java component implementations:
--enable-java
To build the Queue utility component (requires Apache Qpid/C++):
--enable-queue
To build the Chat utility component (requires Libstrophe and optionally Apache
Vysper if you want to run the tests with a local Vysper XMPP server):
--enable-chat
To build the Log utility component (requires Facebook Scribe and Apache Thrift):
--enable-log
To build the SQL Database utility component (requires PostgreSQL):
--enable-sqldb
To build the Web service utility component (requires Apache Axis2/C):
--enable-webservice
To build the support for OAuth authorization:
--enable-oauth
To build the support for OpenID authentication:
--enable-openid
To generate doxygen documentation, add:
--enable-doxygen
To configure where to find dependencies, see the --with-* options described
in the configure help:
./configure --help
Here's an example configuration tested on Ubuntu 10.10 64-bit, with the system
dependencies installed in the standard system directories and some of the
dependencies installed under $HOME:
./configure --prefix=$HOME/tuscany-sca-cpp-bin \
--with-apr=$HOME/httpd-2.3.8-bin --with-httpd=$HOME/httpd-2.3.8-bin \
--with-memcached=$HOME/memcached-1.4.5-bin \
--with-tinycdb=$HOME/tinycdb-0.77-bin \
--with-curl=$HOME/curl-7.19.5-bin --with-libxml2=/usr \
--with-js-include=/usr/include/xulrunner-1.9.2 \
--with-js-lib=/usr/lib/xulrunner-1.9.2 \
--enable-libcloud \
--with-libcloud=$HOME/libcloud-0.3.1-bin \
--enable-threads \
--enable-python --with-python=/usr \
--enable-gae --with-gae=$HOME/google_appengine \
--enable-java --with-java=/usr/lib/jvm/default-java \
--enable-webservice --with-axis2c=$HOME/axis2c-1.6.0-bin \
--with-libxml2=$HOME/libxml2-2.7.7-bin \
--enable-queue --with-qpidc=$HOME/qpidc-0.6-bin \
--enable-chat --with-libstrophe=$HOME/libstrophe-bin \
--with-vysper=$HOME/vysper-0.5 \
--enable-sqldb --with-pgsql=$HOME/postgresql-9.0.1-bin \
--enable-log --with-thrift=$HOME/thrift-0.2.0-bin \
--with-scribe=$HOME/scribe-2.2-bin \
--enable-openid --with-mod-auth-openid=$HOME/mod-auth-openid-bin \
--enable-oauth --with-liboauth=$HOME/liboauth-0.9.1-bin \
--enable-maintainer-mode
To build the Tuscany SCA runtime, do this:
make
To run the tests, do this:
make check
To build ctags for the source, do this:
make ctags
To build a source distribution, do this:
make dist
To build a binary distribution, do this:
make bindist
Installing
==========
To install the Tuscany SCA binaries, do this:
make install

View file

@ -0,0 +1,342 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================================================
Apache Tuscany SCA C++ Subcomponents:
The Tuscany SCA C++ release includes a number of subcomponents with separate
copyright notices and license terms. Your use of the source code for these
subcomponents is subject to the terms and conditions of the following licenses.
================================================================================
The xsd component includes XML files under the following license:
Copyright OASIS 2005, 2009. All Rights Reserved.
All capitalized terms in the following text have the meanings assigned to them in the OASIS Intellectual
Property Rights Policy (the "OASIS IPR Policy"). The full Policy may be found at the OASIS website.
This document and translations of it may be copied and furnished to others, and derivative works that
comment on or otherwise explain it or assist in its implementation may be prepared, copied, published,
and distributed, in whole or in part, without restriction of any kind, provided that the above copyright
notice and this section are included on all such copies and derivative works. However, this document
itself may not be modified in any way, including by removing the copyright notice or references to OASIS,
except as needed for the purpose of developing any document or deliverable produced by an OASIS
Technical Committee (in which case the rules applicable to copyrights, as set forth in the OASIS IPR
Policy, must be followed) or as required to translate it into languages other than English.
The limited permissions granted above are perpetual and will not be revoked by OASIS or its successors
or assigns.
This document and the information contained herein is provided on an "AS IS" basis and OASIS
DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY
WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY OWNERSHIP
RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR
PURPOSE.
OASIS requests that any OASIS Party or any other party that believes it has patent claims that would
necessarily be infringed by implementations of this OASIS Committee Specification or OASIS Standard,
to notify OASIS TC Administrator and provide an indication of its willingness to grant patent licenses to
such patent claims in a manner consistent with the IPR Mode of the OASIS Technical Committee that
produced this specification.
OASIS invites any party to contact the OASIS TC Administrator if it is aware of a claim of ownership of
any patent claims that would necessarily be infringed by implementations of this specification by a patent
holder that is not willing to provide a license to such patent claims in a manner consistent with the IPR
Mode of the OASIS Technical Committee that produced this specification. OASIS may include such
claims on its website, but disclaims any obligation to do so.
OASIS takes no position regarding the validity or scope of any intellectual property or other rights that
might be claimed to pertain to the implementation or use of the technology described in this document or
the extent to which any license under such rights might or might not be available; neither does it represent
that it has made any effort to identify any such rights. Information on OASIS' procedures with respect to
rights in any document or deliverable produced by an OASIS Technical Committee can be found on the
OASIS website. Copies of claims of rights made available for publication and any assurances of licenses
to be made available, or the result of an attempt made to obtain a general license or permission for the use
of such proprietary rights by implementers or users of this OASIS Committee Specification or OASIS
Standard, can be obtained from the OASIS TC Administrator. OASIS makes no representation that any
information or list of intellectual property rights will at any time be complete, or that any claims in such list
are, in fact, Essential Claims.
The names "OASIS", are trademarks of OASIS, the owner and developer of this specification, and should
be used only to refer to the organization and its official outputs. OASIS welcomes reference to, and
implementation and use of, specifications, while reserving the right to enforce its marks against misleading
uses. Please see http://www.oasis-open.org/who/trademark.php for above guidance.
================================================================================
The xsd component includes XML files under the following license:
http://www.w3.org/Consortium/Legal/copyright-software-19980720
W3C® SOFTWARE NOTICE AND LICENSE
Copyright (c) 1994-2002 World Wide Web Consortium, (Massachusetts Institute of Technology, Institut National de Recherche
en Informatique et en Automatique, Keio University). All Rights Reserved. http://www.w3.org/Consortium/Legal/
This W3C work (including software, documents, or other related items) is being provided by the copyright holders under
the following license. By obtaining, using and/or copying this work, you (the licensee) agree that you have read, understood,
and will comply with the following terms and conditions:
Permission to use, copy, modify, and distribute this software and its documentation, with or without modification,
for any purpose and without fee or royalty is hereby granted, provided that you include the following on ALL copies
of the software and documentation or portions thereof, including modifications, that you make:
1. The full text of this NOTICE in a location viewable to users of the redistributed or derivative work.
2. Any pre-existing intellectual property disclaimers, notices, or terms and conditions. If none exist, a short
notice of the following form (hypertext is preferred, text is permitted) should be used within the body of any redistributed
or derivative code: "Copyright (c) [$date-of-software] World Wide Web Consortium, (Massachusetts Institute of Technology,
Institut National de Recherche en Informatique et en Automatique, Keio University). All Rights Reserved. http://www.w3.org/Consortium/Legal/"
3. Notice of any changes or modifications to the W3C files, including the date changes were made. (We recommend you provide URIs
to the location from which the code is derived.)
THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE
OR THAT THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE
OF THE SOFTWARE OR DOCUMENTATION.
The name and trademarks of copyright holders may NOT be used in advertising or publicity pertaining to the software
without specific, written prior permission. Title to copyright in this software and any associated documentation will
at all times remain with copyright holders.
================================================================================
The components/chat component includes the Libstrophe library under the
following MIT license:
Copyright (c) 2005-2009 Collecta, Inc.
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
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
================================================================================
The components/log component includes the Scribe library under the following
Apache license:
Copyright (c) 2007-2008 Facebook
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================================================

View file

@ -0,0 +1,38 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = etc kernel modules components samples doc ubuntu
datadir=$(prefix)
dist_data_DATA = AUTHORS README LICENSE COPYING NOTICE NEWS
nobase_dist_data_DATA = xsd/*.xsd xsd/external/*.xsd xsd/external/*.dtd
EXTRA_DIST = INSTALL bootstrap
dist-hook:
rm -rf `find $(distdir)/ -type d -name .svn`
rm -rf `find $(distdir)/ -type d -name .deps`
rm -rf $(distdir)/.git
bindist: install
rm -rf ${PACKAGE}-${PACKAGE_VERSION}-bin
mkdir ${PACKAGE}-${PACKAGE_VERSION}-bin
cp -r $(prefix)/* ${PACKAGE}-${PACKAGE_VERSION}-bin
tar -cf - ${PACKAGE}-${PACKAGE_VERSION}-bin | gzip -c > ${PACKAGE}-${PACKAGE_VERSION}-bin.tar.gz
rm -rf ${PACKAGE}-${PACKAGE_VERSION}-bin

View file

@ -0,0 +1,13 @@
Apache Tuscany SCA Runtime
==========================
For any news see the Tuscany development mailing list:
dev@tuscany.apache.org
Archives:
http://www.mail-archive.com/dev@tuscany.apache.org
http://marc.info/?l=tuscany-dev
To subscribe send an email to:
dev-subscribe@tuscany.apache.org

View file

@ -0,0 +1,48 @@
Apache Tuscany
Copyright (c) 2005-2010 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/)
This product includes software under the OASIS Specification License
with the following copyright:
Copyright(C) OASIS(R) 2005,2009. All Rights Reserved.
OASIS trademark, IPR and other policies apply.
This product includes software under the W3C(c) Software License
with the following copyright:
Copyright (c) 2008 World Wide Web Consortium, (Massachusetts Institute of Technology,
European Research Consortium for Informatics and Mathematics, Keio University).
All Rights Reserved. This work is distributed under the W3C(c) Software License [1] 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.
[1] http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
This product includes software under the W3C(c) Software License
with the following copyright:
Copyright 2001 The Internet Society and W3C (Massachusetts Institute
of Technology, Institut National de Recherche en Informatique et en
Automatique, Keio University). All Rights Reserved.
http://www.w3.org/Consortium/Legal/
This document is governed by the W3C Software License [1] as described
in the FAQ [2].
[1] http://www.w3.org/Consortium/Legal/copyright-software-19980720
[2] http://www.w3.org/Consortium/Legal/IPR-FAQ-20000620.html#DTD
This product includes software under the MIT license
with the following copyright:
Copyright (c) 2005-2009 Collecta, Inc.
This product includes software under the Apache 2.0 license
with the following copyright:
Copyright (c) 2007-2008 Facebook

View file

@ -0,0 +1,115 @@
Apache Tuscany SCA Runtime
==========================
Tuscany SCA Native is an SCA (Service Component Architecture) runtime written
in C++ and integrated with the Apache HTTPD server.
It supports SCA components written in C++ and Python. Experimental support
for other programming languages is under construction. SCA bindings are
available for the JSON-RPC, ATOMPub and RSS protocols. User signin is
implemented using OpenID and OAuth.
Several useful SCA components are provided on top of the SCA runtime, which
can be used to help assemble distributed SCA composite applications:
Cache: Key/value memory cache, using Memcached;
Chat: XMPP chat, using Apache Vysper and Libstrophe;
Log: distributed logger, using Facebook Scribe.
Nosqldb: Key/value 'NoSQL' persistent store, using TinyCDB;
Queue: AMQP queuing, using Apache Qpid/C;
Sqldb: SQL database, using PostgreSQL;
Webservice: Web service gateway, using Apache Axis2/C;
These components present a simple ATOMPub REST interface, allowing you to send
a message to a queue, a chat connection, or add an entry to a cache or a
database for example, using a simple HTTP POST.
Getting the source code
=======================
To checkout the source code, do this:
git clone git://git.apache.org/tuscany-sca-cpp
or
svn checkout http://svn.apache.org/repos/asf/tuscany/sca-cpp tuscany-sca-cpp
To checkout the source code with commit access, do this:
git clone git://git.apache.org/tuscany-sca-cpp
cd tuscany-sca-cpp
wget -P .git http://git.apache.org/authors.txt
git config svn.authorsfile .git/authors.txt
git config user.email <you>@apache.org
git config svn.rmdir true
git svn init --prefix=origin/ -s https://svn.apache.org/repos/asf/tuscany/sca-cpp
git svn rebase
Layout
======
Here's a rough guide to the Tuscany SCA source tree:
/
|-- trunk Master development branch
| |
| |-- kernel SCA runtime kernel
| |
| |-- modules Modules that plug into the runtime
| | |-- atom AtomPub encoding
| | |-- http HTTP protocol
| | |-- java Support for Java components
| | |-- json JSON-RPC encoding
| | |-- oauth User signin using OAuth
| | |-- openid User signin using OpenID
| | |-- python Support for Python components
| | |-- scheme Support for Scheme components
| | |-- server Apache HTTPD server integration
| | |-- wsgi Python WSGI server integration
| |
| |-- components Useful SCA components
| | |-- cache Memcached key/value cache
| | |-- chat XMPP chat
| | |-- log Scribe logger
| | |-- nosqldb TinyCDB NoSQL database
| | |-- queue AMQP message queue
| | |-- sqldb PostgreSQL database
| | |-- webservice Axis2 Web service gateway
| |
| |-- samples Sample Applications
| | |-- store-cluster Online store on a proxy + server + db cluster
| | |-- store-cpp Online store written in C++
| | |-- store-gae Online store written in Python, working on GAE
| | |-- store-java Online store written in Java
| | |-- store-nosql Online store using a NoSQL database
| | |-- store-python Online store written in Python
| | |-- store-scheme Online store written in Scheme
| | |-- store-sql Online store using an SQL database
| | |-- store-vhost Online store on virtual hosts
| |
| |-- ubuntu Automated install on Ubuntu 10.10 64-bit
|
|-- branches Topic and release branches
|
|-- tags Release tags
Building
========
See the INSTALL file at the root of the source tree.
Contributing to the project
===========================
To contribute to the project or report issues see the Tuscany development
mailing list:
dev@tuscany.apache.org
Archives:
http://www.mail-archive.com/dev@tuscany.apache.org
http://marc.info/?l=tuscany-dev
To subscribe send an email to:
dev-subscribe@tuscany.apache.org

View file

@ -0,0 +1,31 @@
#!/bin/bash
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
for i in "libtoolize --force" aclocal autoconf autoheader
do
echo -n "Running $i..."
$i || exit 1
echo 'done.'
done
echo -n 'Running automake...'
automake --add-missing
echo 'done.'
exit 0

View file

@ -0,0 +1,19 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
SUBDIRS = cache chat log nosqldb filedb queue sqldb webservice

View file

@ -0,0 +1,53 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
incl_HEADERS = *.hpp
incldir = $(prefix)/include/components/cache
dist_comp_SCRIPTS = memcached-start memcached-stop
compdir=$(prefix)/components/cache
comp_DATA = memcached.prefix
memcached.prefix: $(top_builddir)/config.status
echo ${MEMCACHED_PREFIX} >memcached.prefix
EXTRA_DIST = cache.composite memcache.componentType datacache.componentType memocache.componentType *.scm
comp_LTLIBRARIES = libmemcache.la libdatacache.la libmemocache.la
noinst_DATA = libmemcache.so libdatacache.so libmemocache.so
libmemcache_la_SOURCES = memcache.cpp
libmemcache.so:
ln -s .libs/libmemcache.so
libdatacache_la_SOURCES = datacache.cpp
libdatacache.so:
ln -s .libs/libdatacache.so
libmemocache_la_SOURCES = memocache.cpp
libmemocache.so:
ln -s .libs/libmemocache.so
memcache_test_SOURCES = memcache-test.cpp
memcache_test_LDFLAGS = -lxml2
client_test_SOURCES = client-test.cpp
client_test_LDFLAGS = -lxml2 -lcurl -lmozjs
dist_noinst_SCRIPTS = memcached-test memcached-ssl-test server-test
noinst_PROGRAMS = memcache-test client-test
TESTS = memcached-test memcached-ssl-test server-test

View file

@ -0,0 +1,20 @@
; Licensed to the Apache Software Foundation (ASF) under one
; or more contributor license agreements. See the NOTICE file
; distributed with this work for additional information
; regarding copyright ownership. The ASF licenses this file
; to you under the Apache License, Version 2.0 (the
; "License"); you may not use this file except in compliance
; with the License. You may obtain a copy of the License at
;
; http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing,
; software distributed under the License is distributed on an
; "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
; KIND, either express or implied. See the License for the
; specific language governing permissions and limitations
; under the License.
; Logger test case
(define (add a b) (+ a b))

View file

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
-->
<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
targetNamespace="http://tuscany.apache.org/xmlns/sca/components"
name="memcache">
<component name="memcache">
<implementation.cpp path="." library="libmemcache"/>
<service name="memcache">
<t:binding.http uri="memcache"/>
</service>
<property name="servers">localhost,localhost:11212,localhost:11213</property>
</component>
<component name="l2cache">
<implementation.cpp path="." library="libmemcache"/>
<service name="l2cache">
<t:binding.http uri="l2cache"/>
</service>
<property name="servers">localhost:11411,localhost:11412,localhost:11413</property>
</component>
<component name="datacache">
<implementation.cpp path="." library="libdatacache"/>
<service name="datacache">
<t:binding.http uri="datacache"/>
</service>
<reference name="l1reader" target="memcache"/>
<reference name="l1writer" target="memcache"/>
<reference name="l2reader" target="l2cache"/>
<reference name="l2writer" target="l2cache"/>
</component>
<component name="memocache">
<implementation.cpp path="." library="libmemocache"/>
<service name="memocache">
<t:binding.http uri="memocache"/>
</service>
<reference name="relay" target="adder"/>
<reference name="cache" target="memcache"/>
</component>
<component name="adder">
<implementation.scheme script="adder-test.scm"/>
<service name="adder">
<t:binding.http uri="adder"/>
</service>
</component>
</composite>

View file

@ -0,0 +1,156 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
/**
* Test cache component.
*/
#include <assert.h>
#include "stream.hpp"
#include "string.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "perf.hpp"
#include "../../modules/http/http.hpp"
namespace tuscany {
namespace cache {
const string memcacheuri("http://localhost:8090/memcache");
const string datacacheuri("http://localhost:8090/datacache");
const string memocacheuri("http://localhost:8090/memocache");
bool testCache(const string& uri) {
http::CURLSession cs("", "", "");
const list<value> i = list<value>()
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$2.99"));
const list<value> a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
const failable<value> id = http::post(a, uri, cs);
assert(hasContent(id));
const string p = path(content(id));
{
const failable<value> val = http::get(uri + p, cs);
assert(hasContent(val));
assert(content(val) == a);
}
const list<value> j = list<value>()
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$3.55"));
const list<value> b = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), j);
{
const failable<value> r = http::put(b, uri + p, cs);
assert(hasContent(r));
assert(content(r) == value(true));
}
{
const failable<value> val = http::get(uri + p, cs);
assert(hasContent(val));
assert(content(val) == b);
}
{
const failable<value> r = http::del(uri + p, cs);
assert(hasContent(r));
assert(content(r) == value(true));
}
{
const failable<value> val = http::get(uri + p, cs);
assert(!hasContent(val));
}
return true;
}
bool testMemcache() {
return testCache(memcacheuri);
}
bool testDatacache() {
return testCache(datacacheuri);
}
bool testMemocache() {
http::CURLSession cs("", "", "");
const failable<value> res = http::evalExpr(mklist<value>(string("add"), 33, 22), memocacheuri, cs);
assert(hasContent(res));
assert((int)content(res) == 55);
const failable<value> res2 = http::evalExpr(mklist<value>(string("add"), 33, 22), memocacheuri, cs);
assert(hasContent(res2));
assert((int)content(res2) == 55);
return true;
}
struct getLoop {
const string path;
const value entry;
http::CURLSession cs;
getLoop(const string& path, const value& entry, http::CURLSession cs) : path(path), entry(entry), cs(cs) {
}
const bool operator()() const {
const failable<value> val = http::get(memcacheuri + path, cs);
assert(hasContent(val));
assert(content(val) == entry);
return true;
}
};
bool testGetPerf() {
const list<value> i = list<value>()
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$4.55"));
const value a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
http::CURLSession cs("", "", "");
const failable<value> id = http::post(a, memcacheuri, cs);
assert(hasContent(id));
const string p = path(content(id));
const lambda<bool()> gl = getLoop(p, a, cs);
cout << "Cache get test " << time(gl, 5, 200) << " ms" << endl;
return true;
}
}
}
int main() {
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::cache::testMemcache();
tuscany::cache::testDatacache();
tuscany::cache::testMemocache();
tuscany::cache::testGetPerf();
tuscany::cout << "OK" << tuscany::endl;
return 0;
}

View file

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
-->
<componentType xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
targetNamespace="http://tuscany.apache.org/xmlns/sca/components">
<service name="datacache"/>
<reference name="l1reader"/>
<reference name="l1writer"/>
<reference name="l2reader"/>
<reference name="l2writer"/>
</composite>

View file

@ -0,0 +1,125 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
/**
* A data cache component implementation which coordinates access to two
* levels of backend read/write caches or stores. Each cache or store is
* accessed through two references: a writer reference and a reader reference.
*
* This is useful if your level2 store is made of a master and slave
* replicated databases, you can then wire the writer reference to the master
* database and the reader reference to one your slave databases (assuming
* that the updates eventually get replicated to the slave database, in the
* meantime the updates will be retrieved from the level1 cache).
*/
#include "string.hpp"
#include "function.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
namespace tuscany {
namespace datacache {
/**
* Get an item from the cache.
*/
const failable<value> get(const value& key, const lambda<value(const list<value>&)> rcache1, const lambda<value(const list<value>&)> wcache1, const lambda<value(const list<value>&)> rcache2, unused const lambda<value(const list<value>&)> wcache2) {
// Lookup level1 cache
const value val1 = rcache1(mklist<value>("get", key));
if (!isNil(val1))
return val1;
// Lookup level2 cache
const value val2 = rcache2(mklist<value>("get", key));
if (isNil(val2))
return mkfailure<value>("Couldn't get cache entry");
// Update level1 cache
wcache1(mklist<value>("put", key, val2));
return val2;
}
/**
* Post an item to the cache.
*/
const failable<value> post(const value& key, const value& val, unused const lambda<value(const list<value>&)> rcache1, const lambda<value(const list<value>&)> wcache1, unused const lambda<value(const list<value>&)> rcache2, const lambda<value(const list<value>&)> wcache2) {
const value id = append<value>(key, mklist(mkuuid()));
// Update level1 cache
wcache1(mklist<value>("put", id, val));
// Update level2 cache
wcache2(mklist<value>("put", id, val));
return id;
}
/**
* Put an item into the cache.
*/
const failable<value> put(const value& key, const value& val, unused const lambda<value(const list<value>&)> rcache1, const lambda<value(const list<value>&)> wcache1, unused const lambda<value(const list<value>&)> rcache2, const lambda<value(const list<value>&)> wcache2) {
// Update level1 cache
wcache1(mklist<value>("put", key, val));
// Update level2 cache
wcache2(mklist<value>("put", key, val));
return value(true);
}
/**
* Delete an item from the cache.
*/
const failable<value> del(const value& key, unused const lambda<value(const list<value>&)> rcache1, const lambda<value(const list<value>&)> wcache1, unused const lambda<value(const list<value>&)> rcache2, const lambda<value(const list<value>&)> wcache2) {
// Delete from level1 cache
wcache1(mklist<value>("delete", key));
// Delete from level2 cache
wcache2(mklist<value>("delete", key));
return value(true);
}
}
}
extern "C" {
const tuscany::value apply(const tuscany::list<tuscany::value>& params) {
const tuscany::value func(car(params));
if (func == "get")
return tuscany::datacache::get(cadr(params), caddr(params), cadddr(params), caddddr(params), cadddddr(params));
if (func == "post")
return tuscany::datacache::post(cadr(params), caddr(params), cadddr(params), caddddr(params), cadddddr(params), caddddddr(params));
if (func == "put")
return tuscany::datacache::put(cadr(params), caddr(params), cadddr(params), caddddr(params), cadddddr(params), caddddddr(params));
if (func == "delete")
return tuscany::datacache::del(cadr(params), caddr(params), cadddr(params), caddddr(params), cadddddr(params));
return tuscany::mkfailure<tuscany::value>();
}
}

View file

@ -0,0 +1,82 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
/**
* Test Memcached access functions.
*/
#include <assert.h>
#include "stream.hpp"
#include "string.hpp"
#include "perf.hpp"
#include "memcache.hpp"
namespace tuscany {
namespace memcache {
bool testMemCached() {
MemCached ch(mklist<string>("localhost:11211", "localhost:11212", "localhost:11213"));
const value k = mklist<value>("a");
assert(hasContent(post(k, string("AAA"), ch)));
assert(get(k, ch) == value(string("AAA")));
assert(hasContent(put(k, string("aaa"), ch)));
assert(get(k, ch) == value(string("aaa")));
assert(hasContent(del(k, ch)));
assert(!hasContent(get(k, ch)));
return true;
}
struct getLoop {
const value k;
MemCached& ch;
getLoop(const value& k, MemCached& ch) : k(k), ch(ch) {
}
const bool operator()() const {
assert(get(k, ch) == value(string("CCC")));
return true;
}
};
bool testGetPerf() {
const value k = mklist<value>("c");
MemCached ch(mklist<string>("localhost:11211", "localhost:11212", "localhost:11213"));
assert(hasContent(post(k, string("CCC"), ch)));
const lambda<bool()> gl = getLoop(k, ch);
cout << "Memcached get test " << time(gl, 5, 200) << " ms" << endl;
return true;
}
}
}
int main() {
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::memcache::testMemCached();
tuscany::memcache::testGetPerf();
tuscany::cout << "OK" << tuscany::endl;
return 0;
}

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
-->
<componentType xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
targetNamespace="http://tuscany.apache.org/xmlns/sca/components">
<service name="memcache"/>
<property name="servers" type="xsd:string">localhost</property>
</composite>

View file

@ -0,0 +1,123 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
/**
* Memcached-based cache component implementation.
*/
#include "string.hpp"
#include "function.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "memcache.hpp"
namespace tuscany {
namespace cache {
/**
* Get an item from the cache.
*/
const failable<value> get(const list<value>& params, memcache::MemCached& ch) {
return memcache::get(car(params), ch);
}
/**
* Post an item to the cache.
*/
const failable<value> post(const list<value>& params, memcache::MemCached& ch) {
const value id = append<value>(car(params), mklist(mkuuid()));
const failable<bool> val = memcache::post(id, cadr(params), ch);
if (!hasContent(val))
return mkfailure<value>(reason(val));
return id;
}
/**
* Put an item into the cache.
*/
const failable<value> put(const list<value>& params, memcache::MemCached& ch) {
const failable<bool> val = memcache::put(car(params), cadr(params), ch);
if (!hasContent(val))
return mkfailure<value>(reason(val));
return value(content(val));
}
/**
* Delete an item from the cache.
*/
const failable<value> del(const list<value>& params, memcache::MemCached& ch) {
const failable<bool> val = memcache::del(car(params), ch);
if (!hasContent(val))
return mkfailure<value>(reason(val));
return value(content(val));
}
/**
* Component implementation lambda function.
*/
class applyCache {
public:
applyCache(memcache::MemCached& ch) : ch(ch) {
}
const value operator()(const list<value>& params) const {
const value func(car(params));
if (func == "get")
return get(cdr(params), ch);
if (func == "post")
return post(cdr(params), ch);
if (func == "put")
return put(cdr(params), ch);
if (func == "delete")
return del(cdr(params), ch);
return tuscany::mkfailure<tuscany::value>();
}
private:
memcache::MemCached& ch;
};
/**
* Start the component.
*/
const failable<value> start(unused const list<value>& params) {
// Connect to memcached
const value servers = ((lambda<value(list<value>)>)car(params))(list<value>());
memcache::MemCached& ch = *(new (gc_new<memcache::MemCached>()) memcache::MemCached(tokenize(",", servers)));
// Return the component implementation lambda function
return value(lambda<value(const list<value>&)>(applyCache(ch)));
}
}
}
extern "C" {
const tuscany::value apply(const tuscany::list<tuscany::value>& params) {
const tuscany::value func(car(params));
if (func == "start")
return tuscany::cache::start(cdr(params));
return tuscany::mkfailure<tuscany::value>();
}
}

View file

@ -0,0 +1,191 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
#ifndef tuscany_memcache_hpp
#define tuscany_memcache_hpp
/**
* Memcached access functions.
*/
#include "apr.h"
#include "apu.h"
#include "apr_general.h"
#include "apr_strings.h"
#include "apr_hash.h"
#include "apr_memcache.h"
#include "apr_network_io.h"
#include "string.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "../../modules/scheme/eval.hpp"
namespace tuscany {
namespace memcache {
/**
* Represents a memcached context.
*/
class MemCached {
public:
MemCached() : owner(false) {
}
MemCached(const string host, const int port) : owner(true) {
apr_pool_create(&pool, NULL);
apr_memcache_create(pool, 1, 0, &mc);
addServer(host, port);
}
MemCached(const list<string>& servers) : owner(true) {
apr_pool_create(&pool, NULL);
apr_memcache_create(pool, 1, 0, &mc);
addServers(servers);
}
MemCached(const MemCached& c) : owner(false), pool(c.pool), mc(c.mc) {
}
~MemCached() {
if (!owner)
return;
apr_pool_destroy(pool);
}
private:
bool owner;
apr_pool_t* pool;
apr_memcache_t* mc;
friend const failable<bool> post(const value& key, const value& val, const MemCached& cache);
friend const failable<bool> put(const value& key, const value& val, const MemCached& cache);
friend const failable<value> get(const value& key, const MemCached& cache);
friend const failable<bool> del(const value& key, const MemCached& cache);
/**
* Add servers to the memcached context.
*/
const failable<bool> addServer(const string& host, const int port) {
apr_memcache_server_t *server;
const apr_status_t sc = apr_memcache_server_create(pool, c_str(host), (apr_port_t)port, 1, 1, 1, 600, &server);
if (sc != APR_SUCCESS)
return mkfailure<bool>("Could not create memcached server");
const apr_status_t as = apr_memcache_add_server(mc, server);
if (as != APR_SUCCESS)
return mkfailure<bool>("Could not add memcached server");
return true;
}
const failable<bool> addServers(const list<string>& servers) {
if (isNil(servers))
return true;
const list<string> toks = tokenize(":", car(servers));
const failable<bool> r = addServer(car(toks), isNil(cdr(toks))? 11211 : atoi(c_str(cadr(toks))));
if (!hasContent(r))
return r;
return addServers(cdr(servers));
}
};
/**
* Replace spaces by tabs (as spaces are not allowed in memcached keys).
*/
const char* nospaces(const char* s) {
char* c = const_cast<char*>(s);
for (; *c; c++)
if (*c == ' ')
*c = '\t';
return s;
}
/**
* Post a new item to the cache.
*/
const failable<bool> post(const value& key, const value& val, const MemCached& cache) {
debug(key, "memcache::post::key");
debug(val, "memcache::post::value");
const string ks(scheme::writeValue(key));
const string vs(scheme::writeValue(val));
const apr_status_t rc = apr_memcache_add(cache.mc, nospaces(c_str(ks)), const_cast<char*>(c_str(vs)), length(vs), 0, 27);
if (rc != APR_SUCCESS)
return mkfailure<bool>("Could not add memcached entry");
debug(true, "memcache::post::result");
return true;
}
/**
* Update an item in the cache. If the item doesn't exist it is added.
*/
const failable<bool> put(const value& key, const value& val, const MemCached& cache) {
debug(key, "memcache::put::key");
debug(val, "memcache::put::value");
const string ks(scheme::writeValue(key));
const string vs(scheme::writeValue(val));
const apr_status_t rc = apr_memcache_set(cache.mc, nospaces(c_str(ks)), const_cast<char*>(c_str(vs)), length(vs), 0, 27);
if (rc != APR_SUCCESS)
return mkfailure<bool>("Could not set memcached entry");
debug(true, "memcache::put::result");
return true;
}
/**
* Get an item from the cache.
*/
const failable<value> get(const value& key, const MemCached& cache) {
debug(key, "memcache::get::key");
const string ks(scheme::writeValue(key));
char *data;
apr_size_t size;
const apr_status_t rc = apr_memcache_getp(cache.mc, cache.pool, nospaces(c_str(ks)), &data, &size, NULL);
if (rc != APR_SUCCESS)
return mkfailure<value>("Could not get memcached entry");
const value val(scheme::readValue(string(data, size)));
debug(val, "memcache::get::result");
return val;
}
/**
* Delete an item from the cache
*/
const failable<bool> del(const value& key, const MemCached& cache) {
debug(key, "memcache::delete::key");
const string ks(scheme::writeValue(key));
const apr_status_t rc = apr_memcache_delete(cache.mc, nospaces(c_str(ks)), 0);
if (rc != APR_SUCCESS)
return mkfailure<bool>("Could not delete memcached entry");
debug(true, "memcache::delete::result");
return true;
}
}
}
#endif /* tuscany_memcache_hpp */

View file

@ -0,0 +1,54 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Setup
../../modules/http/ssl-ca-conf tmp/ssl localhost
../../modules/http/ssl-cert-conf tmp/ssl localhost server
../../modules/http/ssl-cert-conf tmp/ssl localhost tunnel
./memcached-start 11411
./memcached-start 11412
./memcached-start 11413
../../modules/http/httpd-conf tmp/tunnel localhost 8089 htdocs
../../modules/http/httpd-event-conf tmp/tunnel
tar -C tmp/ssl -c `../../modules/http/ssl-cert-find tmp/ssl` | tar -C tmp/tunnel -x
../../modules/http/tunnel-ssl-conf tmp/tunnel 11211 localhost 8453 11411
../../modules/http/tunnel-ssl-conf tmp/tunnel 11212 localhost 8453 11412
../../modules/http/tunnel-ssl-conf tmp/tunnel 11213 localhost 8453 11413
../../modules/http/httpd-start tmp/tunnel
../../modules/http/httpd-conf tmp/server localhost 8090 htdocs
tar -C tmp/ssl -c `../../modules/http/ssl-cert-find tmp/ssl` | tar -C tmp/server -x
../../modules/http/httpd-ssl-conf tmp/server 8453
../../modules/http/cert-auth-conf tmp/server
../../modules/http/httpd-start tmp/server
sleep 1
# Test
./memcache-test 2>/dev/null
rc=$?
# Cleanup
../../modules/http/httpd-stop tmp/tunnel
../../modules/http/httpd-stop tmp/server
./memcached-stop 11411
./memcached-stop 11412
./memcached-stop 11413
return $rc

View file

@ -0,0 +1,38 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Start memcached
here=`readlink -f $0`; here=`dirname $here`
addr=$1
if [ "$addr" = "" ]; then
ip=""
port="11211"
else
ip=`$here/../../modules/http/httpd-addr ip $addr`
port=`$here/../../modules/http/httpd-addr port $addr`
fi
memcached_prefix=`cat $here/memcached.prefix`
if [ "$ip" = "" ]; then
$memcached_prefix/bin/memcached -d -m 4 -p $port
else
$memcached_prefix/bin/memcached -d -l $ip -m 4 -p $port
fi

View file

@ -0,0 +1,39 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Stop memcached
here=`readlink -f $0`; here=`dirname $here`
addr=$1
if [ "$addr" = "" ]; then
ip=""
port="11211"
else
ip=`$here/../../modules/http/httpd-addr ip $addr`
port=`$here/../../modules/http/httpd-addr port $addr`
fi
memcached_prefix=`cat $here/memcached.prefix`
if [ "$ip" = "" ]; then
mc="$memcached_prefix/bin/memcached -d -m 4 -p $port"
else
mc="$memcached_prefix/bin/memcached -d -l $ip -m 4 -p $port"
fi
kill `ps -ef | grep -v grep | grep "${mc}" | awk '{ print $2 }'`

View file

@ -0,0 +1,34 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Setup
./memcached-start 11211
./memcached-start 11212
./memcached-start 11213
sleep 1
# Test
./memcache-test 2>/dev/null
rc=$?
# Cleanup
./memcached-stop 11211
./memcached-stop 11212
./memcached-stop 11213
return $rc

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
-->
<componentType xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
targetNamespace="http://tuscany.apache.org/xmlns/sca/components">
<service name="memocache"/>
<reference name="relay"/>
<reference name="cache"/>
</composite>

View file

@ -0,0 +1,77 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
/**
* A cache component implementation which memoizes the value of function
* applications, keyed by the function arguments, in a key/value cache passed
* as a reference.
*
* This is useful if your functions are idempotent and applied many times to
* the same arguments. The results can then be retrieved quickly from the
* cache without actually applying the function.
*/
#include "string.hpp"
#include "function.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
namespace tuscany {
namespace memocache {
/**
* Memoize the value of a function application in a cache.
*/
const failable<value> memoize(const list<value>& params, const lambda<value(const list<value>&)> relay, const lambda<value(const list<value>&)> cache) {
debug(params, "memocache::memoize::params");
// Lookup memoized value from cache
const value val = cache(mklist<value>("get", params));
if (!isNil(val)) {
debug(val, "memocache::memoize::cached");
return val;
}
// Apply the given function
const value res = relay(params);
debug(res, "memocache::memoize::res");
// Store the result value in the cache
cache(mklist<value>("put", params, res));
return res;
}
}
}
extern "C" {
const tuscany::value apply(const tuscany::list<tuscany::value>& params) {
const tuscany::value func(car(params));
if (func == "start" || func == "stop")
return tuscany::mkfailure<tuscany::value>();
const tuscany::list<tuscany::value> rev = tuscany::reverse(params);
return tuscany::memocache::memoize(tuscany::reverse(tuscany::cddr(rev)), tuscany::cadr(rev), tuscany::car(rev));
}
}

View file

@ -0,0 +1,51 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Setup
../../modules/http/httpd-conf tmp localhost 8090 ../../modules/http/htdocs
../../modules/server/server-conf tmp
../../modules/server/scheme-conf tmp
cat >>tmp/conf/httpd.conf <<EOF
SCAContribution `pwd`/
SCAComposite cache.composite
EOF
./memcached-start 11211
./memcached-start 11212
./memcached-start 11213
./memcached-start 11411
./memcached-start 11412
./memcached-start 11413
../../modules/http/httpd-start tmp
sleep 2
# Test
./client-test 2>/dev/null
rc=$?
# Cleanup
../../modules/http/httpd-stop tmp
./memcached-stop 11211
./memcached-stop 11212
./memcached-stop 11213
./memcached-stop 11411
./memcached-stop 11412
./memcached-stop 11413
sleep 2
return $rc

View file

@ -0,0 +1,68 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
JAVAROOT = $(top_builddir)/components/chat
if WANT_CHAT
INCLUDES = -I${LIBSTROPHE_INCLUDE}
incl_HEADERS = *.hpp
incldir = $(prefix)/include/components/chat
dist_comp_SCRIPTS = vysper-start vysper-stop vysper-classpath
compdir=$(prefix)/components/chat
comp_DATA = vysper.prefix
vysper.prefix: $(top_builddir)/config.status
echo ${VYSPER_PREFIX} >vysper.prefix
EXTRA_DIST = chat.composite chat-sendreceiver.componentType chat-sender.componentType *.scm
comp_LTLIBRARIES = libchat-sendreceiver.la libchat-sender.la
noinst_DATA = libchat-sendreceiver.so libchat-sender.so
libchat_sendreceiver_la_SOURCES = chat-sendreceiver.cpp
libchat_sendreceiver_la_LDFLAGS = -L${LIBSTROPHE_LIB} -R${LIBSTROPHE_LIB} -lstrophe -lssl -lresolv
libchat-sendreceiver.so:
ln -s .libs/libchat-sendreceiver.so
libchat_sender_la_SOURCES = chat-sender.cpp
libchat_sender_la_LDFLAGS = -L${LIBSTROPHE_LIB} -R${LIBSTROPHE_LIB} -lstrophe -lssl -lresolv
libchat-sender.so:
ln -s .libs/libchat-sender.so
xmpp_test_SOURCES = xmpp-test.cpp
xmpp_test_LDFLAGS = -L${LIBSTROPHE_LIB} -R${LIBSTROPHE_LIB} -lstrophe -lssl -lresolv
client_test_SOURCES = client-test.cpp
client_test_LDFLAGS = -lxml2 -lcurl -lmozjs -L${LIBSTROPHE_LIB} -R${LIBSTROPHE_LIB} -lstrophe -lssl -lresolv
noinst_PROGRAMS = xmpp-test client-test
dist_noinst_SCRIPTS = server-test
if WANT_VYSPER
AM_JAVACFLAGS = -cp `${top_builddir}/components/chat/vysper-classpath ${VYSPER_PREFIX}`${JAVAROOT}
dist_noinst_JAVA = test/*.java
CLEANFILES = test/*.class
dist_noinst_SCRIPTS += echo-test
TESTS = echo-test
endif
endif

View file

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
-->
<componentType xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
targetNamespace="http://tuscany.apache.org/xmlns/sca/components">
<service name="send"/>
<property name="jid" type="xsd:string"/>
<property name="password" type="xsd:string"/>
</composite>

View file

@ -0,0 +1,150 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
/**
* XMPP chat sender component implementation.
*/
#include "string.hpp"
#include "function.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "parallel.hpp"
#include "xmpp.hpp"
namespace tuscany {
namespace chat {
namespace sender {
/**
* Post an item to an XMPP JID.
*/
const failable<value> post(const list<value>& params, XMPPClient& xc) {
const value to = car<value>(car(params));
const value val = cadr(params);
debug(to, "chat::post::jid");
debug(val, "chat::post::value");
const failable<bool> r = post(to, val, xc);
if (!hasContent(r))
return mkfailure<value>(reason(r));
return value(mklist<value>(to));
}
/**
* Subscribe and listen to an XMPP session.
*/
class noop {
public:
noop() {
}
const failable<bool> operator()(unused const value& jid, unused const value& val, unused XMPPClient& xc) const {
return true;
}
};
class subscribe {
public:
subscribe(XMPPClient& xc) : xc(xc) {
}
const failable<bool> operator()() const {
gc_pool pool;
debug("chat::subscribe::listen");
const failable<bool> r = listen(noop(), const_cast<XMPPClient&>(xc));
debug("chat::subscribe::stopped");
return r;
}
private:
const lambda<failable<bool>(const value&, const value&, XMPPClient&)> l;
XMPPClient xc;
};
/**
* Chatter component lambda function
*/
class chatSender {
public:
chatSender(XMPPClient& xc, worker& w) : xc(xc), w(w) {
}
const value operator()(const list<value>& params) const {
const tuscany::value func(car(params));
if (func == "post")
return post(cdr(params), const_cast<XMPPClient&>(xc));
// Stop the chat sender component
if (func != "stop")
return tuscany::mkfailure<tuscany::value>();
debug("chat::sender::stop");
// Disconnect and shutdown the worker thread
disconnect(const_cast<XMPPClient&>(xc));
cancel(const_cast<worker&>(w));
debug("chat::sender::stopped");
return failable<value>(value(lambda<value(const list<value>&)>()));
}
private:
const XMPPClient xc;
worker w;
};
/**
* Start the component.
*/
const failable<value> start(const list<value>& params) {
// Extract the the XMPP JID and password
const list<value> props = params;
const value jid = ((lambda<value(list<value>)>)car(props))(list<value>());
const value pass = ((lambda<value(list<value>)>)cadr(props))(list<value>());
// Create an XMPP client session
XMPPClient xc(jid, pass, false);
const failable<bool> r = connect(xc);
if (!hasContent(r))
return mkfailure<value>(reason(r));
// Listen and relay messages in a worker thread
worker w(3);
submit<failable<bool> >(w, lambda<failable<bool>()>(subscribe(xc)));
// Return the chat sender component lambda function
return value(lambda<value(const list<value>&)>(chatSender(xc, w)));
}
}
}
}
extern "C" {
const tuscany::value apply(const tuscany::list<tuscany::value>& params) {
const tuscany::value func(car(params));
if (func == "start")
return tuscany::chat::sender::start(cdr(params));
return tuscany::mkfailure<tuscany::value>();
}
}

View file

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
-->
<componentType xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
targetNamespace="http://tuscany.apache.org/xmlns/sca/components">
<service name="send"/>
<reference name="relay"/>
<property name="jid" type="xsd:string"/>
<property name="password" type="xsd:string"/>
</composite>

View file

@ -0,0 +1,164 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
/**
* XMPP chat sender/receiver component implementation.
*/
#include "string.hpp"
#include "function.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "parallel.hpp"
#include "xmpp.hpp"
namespace tuscany {
namespace chat {
namespace sendreceiver {
/**
* Post an item to an XMPP JID.
*/
const failable<value> post(const list<value>& params, XMPPClient& xc) {
const value to = car<value>(car(params));
const value val = cadr(params);
debug(to, "chat::post::jid");
debug(val, "chat::post::value");
const failable<bool> r = post(to, val, xc);
if (!hasContent(r))
return mkfailure<value>(reason(r));
return value(mklist<value>(to));
}
/**
* A relay function that posts the XMPP messages it receives to a relay component reference.
*/
class relay {
public:
relay(const lambda<value(const list<value>&)>& rel) : rel(rel) {
}
const failable<bool> operator()(const value& jid, const value& val, unused XMPPClient& xc) const {
if (isNil(rel))
return true;
debug(jid, "chat::relay::jid");
debug(val, "chat::relay::value");
const value res = rel(mklist<value>("post", mklist<value>(jid), val));
return true;
}
private:
const lambda<value(const list<value>&)> rel;
};
/**
* Subscribe and listen to an XMPP session.
*/
class subscribe {
public:
subscribe(const lambda<failable<bool>(const value&, const value&, XMPPClient&)>& l, XMPPClient& xc) : l(l), xc(xc) {
}
const failable<bool> operator()() const {
gc_pool pool;
debug("chat::subscribe::listen");
const failable<bool> r = listen(l, const_cast<XMPPClient&>(xc));
debug("chat::subscribe::stopped");
return r;
}
private:
const lambda<failable<bool>(const value&, const value&, XMPPClient&)> l;
XMPPClient xc;
};
/**
* Chat sender/receiver component lambda function
*/
class chatSenderReceiver {
public:
chatSenderReceiver(XMPPClient& xc, worker& w) : xc(xc), w(w) {
}
const value operator()(const list<value>& params) const {
const tuscany::value func(car(params));
if (func == "post")
return post(cdr(params), const_cast<XMPPClient&>(xc));
// Stop the chat sender/receiver component
if (func != "stop")
return tuscany::mkfailure<tuscany::value>();
debug("chat::sendreceiver::stop");
// Disconnect and shutdown the worker thread
disconnect(const_cast<XMPPClient&>(xc));
cancel(const_cast<worker&>(w));
debug("chat::sendreceiver::stopped");
return failable<value>(value(lambda<value(const list<value>&)>()));
}
private:
const XMPPClient xc;
worker w;
};
/**
* Start the component.
*/
const failable<value> start(const list<value>& params) {
// Extract the relay reference and the XMPP JID and password
const bool hasRelay = !isNil(cddr(params));
const value rel = hasRelay? car(params) : value(lambda<value(const list<value>&)>());
const list<value> props = hasRelay? cdr(params) : params;
const value jid = ((lambda<value(list<value>)>)car(props))(list<value>());
const value pass = ((lambda<value(list<value>)>)cadr(props))(list<value>());
// Create an XMPP client session
XMPPClient xc(jid, pass, false);
const failable<bool> r = connect(xc);
if (!hasContent(r))
return mkfailure<value>(reason(r));
// Listen and relay messages in a worker thread
worker w(3);
const lambda<failable<bool>(const value&, const value&, XMPPClient&)> rl = relay(rel);
submit<failable<bool> >(w, lambda<failable<bool>()>(subscribe(rl, xc)));
// Return the chat sender/receiver component lambda function
return value(lambda<value(const list<value>&)>(chatSenderReceiver(xc, w)));
}
}
}
}
extern "C" {
const tuscany::value apply(const tuscany::list<tuscany::value>& params) {
const tuscany::value func(car(params));
if (func == "start")
return tuscany::chat::sendreceiver::start(cdr(params));
return tuscany::mkfailure<tuscany::value>();
}
}

View file

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
-->
<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
targetNamespace="http://tuscany.apache.org/xmlns/sca/components"
name="chat">
<component name="print-sender">
<implementation.cpp path="." library="libchat-sender"/>
<property name="jid">sca1@localhost</property>
<property name="password">sca1</property>
<service name="print-sender">
<t:binding.http uri="print-sender"/>
</service>
</component>
<component name="print-chatter">
<implementation.cpp path="." library="libchat-sendreceiver"/>
<property name="jid">sca2@localhost</property>
<property name="password">sca2</property>
<service name="print-chatter">
<t:binding.http uri="print-chatter"/>
</service>
<reference name="relay" target="print"/>
</component>
<component name="print">
<t:implementation.scheme script="server-test.scm"/>
<service name="print">
<t:binding.http uri="print"/>
</service>
<reference name="report" target="print-chatter"/>
</component>
</composite>

View file

@ -0,0 +1,111 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
/**
* Test chat component.
*/
#include <assert.h>
#include "stream.hpp"
#include "string.hpp"
#include "list.hpp"
#include "element.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "perf.hpp"
#include "parallel.hpp"
#include "../../modules/http/http.hpp"
#include "xmpp.hpp"
namespace tuscany {
namespace chat {
const value jid1("sca1@localhost");
const value pass1("sca1");
const value jid2("sca2@localhost");
const value pass2("sca2");
const value jid3("sca3@localhost");
const value pass3("sca3");
const list<value> item = list<value>()
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$2.99"));
const list<value> entry = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), item);
worker w(2);
bool received;
const failable<bool> listener(const value& from, const value& val, unused XMPPClient& xc) {
assert(contains(from, "sca2@localhost"));
assert(val == entry);
received = true;
return false;
}
struct subscribe {
XMPPClient& xc;
subscribe(XMPPClient& xc) : xc(xc) {
}
const failable<bool> operator()() const {
const lambda<failable<bool>(const value&, const value&, XMPPClient&)> l(listener);
listen(l, xc);
return true;
}
};
bool testListen() {
received = false;
XMPPClient& xc = *(new (gc_new<XMPPClient>()) XMPPClient(jid3, pass3));
const failable<bool> c = connect(xc);
assert(hasContent(c));
const lambda<failable<bool>()> subs = subscribe(xc);
submit(w, subs);
return true;
}
bool testPost() {
gc_scoped_pool pool;
http::CURLSession ch("", "", "");
const failable<value> id = http::post(entry, "http://localhost:8090/print-sender/sca2@localhost", ch);
assert(hasContent(id));
return true;
}
bool testReceived() {
shutdown(w);
assert(received == true);
return true;
}
}
}
int main() {
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::chat::testListen();
tuscany::chat::testPost();
tuscany::chat::testReceived();
tuscany::cout << "OK" << tuscany::endl;
return 0;
}

View file

@ -0,0 +1,31 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Setup
./vysper-start
sleep 3
# Test
./xmpp-test 2>/dev/null
rc=$?
# Cleanup
./vysper-stop
sleep 1
return $rc

View file

@ -0,0 +1,39 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Setup
../../modules/http/httpd-conf tmp localhost 8090 ../../modules/http/htdocs
../../modules/server/server-conf tmp
../../modules/server/scheme-conf tmp
cat >>tmp/conf/httpd.conf <<EOF
SCAContribution `pwd`/
SCAComposite chat.composite
EOF
../../modules/http/httpd-start tmp
sleep 2
# Test
./client-test 2>/dev/null
rc=$?
# Cleanup
../../modules/http/httpd-stop tmp
sleep 1
return $rc

View file

@ -0,0 +1,20 @@
; Licensed to the Apache Software Foundation (ASF) under one
; or more contributor license agreements. See the NOTICE file
; distributed with this work for additional information
; regarding copyright ownership. The ASF licenses this file
; to you under the Apache License, Version 2.0 (the
; "License"); you may not use this file except in compliance
; with the License. You may obtain a copy of the License at
;
; http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing,
; software distributed under the License is distributed on an
; "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
; KIND, either express or implied. See the License for the
; specific language governing permissions and limitations
; under the License.
; Chat test case
(define (post key val report) (report "post" '("sca3@localhost") val))

View file

@ -0,0 +1,79 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package test;
/**
* A test XMPP server, using Apache Vysper.
*/
import static java.lang.System.*;
import java.io.File;
import org.apache.vysper.mina.TCPEndpoint;
import org.apache.vysper.stanzasession.StanzaSessionFactory;
import org.apache.vysper.storage.StorageProviderRegistry;
import org.apache.vysper.storage.inmemory.MemoryStorageProviderRegistry;
import org.apache.vysper.xmpp.authorization.AccountManagement;
import org.apache.vysper.xmpp.modules.extension.xep0049_privatedata.PrivateDataModule;
import org.apache.vysper.xmpp.modules.extension.xep0054_vcardtemp.VcardTempModule;
import org.apache.vysper.xmpp.modules.extension.xep0092_software_version.SoftwareVersionModule;
import org.apache.vysper.xmpp.modules.extension.xep0119_xmppping.XmppPingModule;
import org.apache.vysper.xmpp.modules.extension.xep0202_entity_time.EntityTimeModule;
import org.apache.vysper.xmpp.server.XMPPServer;
class TestVysperServer {
public static void main(final String args[]) throws Exception {
out.println("Starting test Vysper server...");
// Add the XMPP users used by the xmpp-test and server-test test cases
// If you're using your own XMPP server you need to add these users manually
final StorageProviderRegistry providerRegistry = new MemoryStorageProviderRegistry();
final AccountManagement accountManagement = (AccountManagement)providerRegistry.retrieve(AccountManagement.class);
accountManagement.addUser("sca1@localhost", "sca1");
accountManagement.addUser("sca2@localhost", "sca2");
accountManagement.addUser("sca3@localhost", "sca3");
// Create and start XMPP server for domain: localhost
final XMPPServer server = new org.apache.vysper.xmpp.server.XMPPServer("localhost");
server.addEndpoint(new TCPEndpoint());
server.addEndpoint(new StanzaSessionFactory());
server.setStorageProviderRegistry(providerRegistry);
final File cert = new File(TestVysperServer.class.getClassLoader().getResource("bogus_mina_tls.cert").getPath());
server.setTLSCertificateInfo(cert, "boguspw");
server.start();
server.addModule(new SoftwareVersionModule());
server.addModule(new EntityTimeModule());
server.addModule(new VcardTempModule());
server.addModule(new XmppPingModule());
server.addModule(new PrivateDataModule());
out.println("Test Vysper server started...");
// Wait forever
final Object lock = new Object();
synchronized(lock) {
lock.wait();
}
System.out.println("Stopping test Vysper server...");
server.stop();
out.println("Test Vysper server stopped.");
System.exit(0);
}
}

View file

@ -0,0 +1,29 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Compute a classpath for running a Vysper server
here=`readlink -f $0`; here=`dirname $here`
if [ "$1" = "" ]; then
vysper_prefix=`cat $here/vysper.prefix`
else
vysper_prefix=$1
fi
jars=`find $vysper_prefix/lib -name "*.jar" | awk '{ printf "%s:", $1 }'`
echo "$vysper_prefix/config:$jars"

View file

@ -0,0 +1,25 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Start Vysper test XMPP server
here=`readlink -f $0`; here=`dirname $here`
java_prefix=`cat $here/../../modules/java/java.prefix`
mkdir -p $here/tmp/logs
${java_prefix}/jre/bin/java -cp `$here/vysper-classpath`$here test.TestVysperServer 2>&1 1>>$here/tmp/logs/vysper.log &

View file

@ -0,0 +1,25 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Stop Vysper test XMPP server
here=`readlink -f $0`; here=`dirname $here`
java_prefix=`cat $here/../../modules/java/java.prefix`
kill `ps -ef | grep -v grep | grep "${java_prefix}/jre/bin/java" | grep "vysper" | awk '{ print $2 }'`

View file

@ -0,0 +1,103 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
/**
* Test XMPP support functions.
*/
#include <assert.h>
#include "stream.hpp"
#include "string.hpp"
#include "list.hpp"
#include "element.hpp"
#include "monad.hpp"
#include "value.hpp"
#include "perf.hpp"
#include "parallel.hpp"
#include "xmpp.hpp"
namespace tuscany {
namespace chat {
const value jid1("sca1@localhost");
const value pass1("sca1");
const value jid2("sca2@localhost");
const value pass2("sca2");
worker w(2);
bool received;
const failable<bool> listener(const value& from, const value& val, unused XMPPClient& xc) {
assert(contains(from, "sca1@localhost"));
assert(val == "hey");
received = true;
return false;
}
struct subscribe {
XMPPClient& xc;
subscribe(XMPPClient& xc) : xc(xc) {
}
const failable<bool> operator()() const {
const lambda<failable<bool>(const value&, const value&, XMPPClient&)> l(listener);
listen(l, xc);
return true;
}
};
bool testListen() {
received = false;
XMPPClient& xc = *(new (gc_new<XMPPClient>()) XMPPClient(jid2, pass2));
const failable<bool> c = connect(xc);
assert(hasContent(c));
const lambda<failable<bool>()> subs = subscribe(xc);
submit(w, subs);
return true;
}
bool testPost() {
XMPPClient xc(jid1, pass1);
const failable<bool> c = connect(xc);
assert(hasContent(c));
const failable<bool> p = post(jid2, "hey", xc);
assert(hasContent(p));
return true;
}
bool testReceived() {
shutdown(w);
assert(received == true);
return true;
}
}
}
int main() {
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::chat::testListen();
tuscany::chat::testPost();
tuscany::chat::testReceived();
tuscany::cout << "OK" << tuscany::endl;
return 0;
}

View file

@ -0,0 +1,320 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
#ifndef tuscany_queue_hpp
#define tuscany_queue_hpp
/**
* XMPP support functions.
*/
#include "strophe.h"
extern "C" {
#include "common.h"
}
#include "string.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "../../modules/scheme/eval.hpp"
namespace tuscany {
namespace chat {
/**
* XMPP runtime, one per process.
*/
class XMPPRuntime {
public:
XMPPRuntime() {
xmpp_initialize();
log = xmpp_get_default_logger(XMPP_LEVEL_DEBUG);
}
~XMPPRuntime() {
xmpp_shutdown();
}
private:
friend class XMPPClient;
xmpp_log_t* log;
} xmppRuntime;
/**
* Represents an XMPP client.
*/
class XMPPClient {
public:
XMPPClient(const string& jid, const string& pass, bool owner = true) : owner(owner), ctx(xmpp_ctx_new(NULL, xmppRuntime.log)), conn(xmpp_conn_new(ctx)), connecting(false), connected(false), disconnecting(false) {
xmpp_conn_set_jid(conn, c_str(jid + "/" + mkuuid()));
xmpp_conn_set_pass(conn, c_str(pass));
}
XMPPClient(const XMPPClient& xc) : owner(false), ctx(xc.ctx), conn(xc.conn), listener(xc.listener), connecting(xc.connecting), connected(xc.connected), disconnecting(xc.disconnecting) {
}
~XMPPClient() {
extern const failable<bool> disconnect(XMPPClient& xc);
if (!owner)
return;
if (!disconnecting)
disconnect(*this);
xmpp_conn_release(conn);
xmpp_ctx_free(ctx);
}
private:
friend int versionHandler(xmpp_conn_t* const conn, xmpp_stanza_t* const stanza, void* const udata);
friend void connHandler(xmpp_conn_t * const conn, const xmpp_conn_event_t status, const int err, xmpp_stream_error_t* const errstream, void *const udata);
friend int messageHandler(xmpp_conn_t* const conn, xmpp_stanza_t* const stanza, void* const udata);
friend const failable<bool> connect(XMPPClient& xc);
friend const failable<size_t> send(const char* data, const size_t len, XMPPClient& xc);
friend const failable<size_t> send(xmpp_stanza_t* const stanza, XMPPClient& xc);
friend const failable<bool> post(const value& to, const value& val, XMPPClient& xc);
friend const failable<bool> disconnect(XMPPClient& xc);
friend const failable<bool> listen(const lambda<failable<bool>(const value&, const value&, XMPPClient&)>& listener, XMPPClient& xc);
const bool owner;
xmpp_ctx_t* ctx;
xmpp_conn_t* conn;
lambda<failable<bool>(const value&, const value&, XMPPClient&)> listener;
bool connecting;
bool connected;
bool disconnecting;
};
/**
* Make a text stanza.
*/
xmpp_stanza_t* textStanza(const char* text, xmpp_ctx_t* ctx) {
xmpp_stanza_t* stanza = xmpp_stanza_new(ctx);
xmpp_stanza_set_text(stanza, text);
return stanza;
}
/**
* Make a named stanza.
*/
xmpp_stanza_t* namedStanza(const char* ns, const char* name, xmpp_ctx_t* ctx) {
xmpp_stanza_t* stanza = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(stanza, name);
if (ns != NULL)
xmpp_stanza_set_ns(stanza, ns);
return stanza;
}
/**
* Make a named stanza using a qualified name.
*/
xmpp_stanza_t* namedStanza(const char* name, xmpp_ctx_t* ctx) {
xmpp_stanza_t* stanza = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(stanza, name);
return stanza;
}
/**
* XMPP version handler.
*/
int versionHandler(xmpp_conn_t* const conn, xmpp_stanza_t* const stanza, void* const udata) {
XMPPClient& xc = *(XMPPClient*)udata;
// Build version reply stanza
xmpp_stanza_t* reply = namedStanza("iq", xc.ctx);
xmpp_stanza_set_type(reply, "result");
xmpp_stanza_set_id(reply, xmpp_stanza_get_id(stanza));
xmpp_stanza_set_attribute(reply, "to", xmpp_stanza_get_attribute(stanza, "from"));
xmpp_stanza_t* query = namedStanza(xmpp_stanza_get_ns(xmpp_stanza_get_children(stanza)), "query", xc.ctx);
xmpp_stanza_add_child(reply, query);
xmpp_stanza_t* name = namedStanza("name", xc.ctx);
xmpp_stanza_add_child(query, name);
xmpp_stanza_add_child(name, textStanza("Apache Tuscany", xc.ctx));
xmpp_stanza_t* version = namedStanza("version", xc.ctx);
xmpp_stanza_add_child(query, version);
xmpp_stanza_add_child(version, textStanza("1.0", xc.ctx));
// Send it
xmpp_send(conn, reply);
xmpp_stanza_release(reply);
return 1;
}
/**
* XMPP message handler
*/
int messageHandler(unused xmpp_conn_t* const conn, xmpp_stanza_t* const stanza, void* const udata) {
// Ignore noise
if(xmpp_stanza_get_child_by_name(stanza, "body") == NULL)
return 1;
if(!strcmp(xmpp_stanza_get_attribute(stanza, "type"), "error"))
return 1;
// Call the client listener function
XMPPClient& xc = *(XMPPClient*)udata;
const char* from = xmpp_stanza_get_attribute(stanza, "from");
const char* text = xmpp_stanza_get_text(xmpp_stanza_get_child_by_name(stanza, "body"));
if (isNil(xc.listener))
return 1;
const value val(scheme::readValue(text));
debug(from, "chat::messageHandler::from");
debug(val, "chat::messageHandler::body");
const failable<bool> r = xc.listener(value(string(from)), val, xc);
if (!hasContent(r) || !content(r)) {
// Stop listening
xc.listener = lambda<failable<bool>(const value&, const value&, XMPPClient&)>();
return 0;
}
return 1;
}
/**
* XMPP connection handler.
*/
void connHandler(xmpp_conn_t * const conn, const xmpp_conn_event_t status, unused const int err, unused xmpp_stream_error_t* const errstream, void *const udata) {
XMPPClient& xc = *(XMPPClient*)udata;
xc.connecting = false;
if (status == XMPP_CONN_CONNECT) {
debug("chat::connHandler::connected");
xmpp_handler_add(conn, versionHandler, "jabber:iq:version", "iq", NULL, &xc);
// Send a <presence/> stanza so that we appear online to contacts
xmpp_stanza_t* pres = xmpp_stanza_new(xc.ctx);
xmpp_stanza_set_name(pres, "presence");
xmpp_send(conn, pres);
xmpp_stanza_release(pres);
xc.connected = true;
return;
}
debug("chat::connHandler::disconnected");
xc.connected = false;
if (xc.ctx->loop_status == XMPP_LOOP_RUNNING)
xc.ctx->loop_status = XMPP_LOOP_QUIT;
}
/**
* Connect to an XMPP server.
*/
const failable<bool> connect(XMPPClient& xc) {
xc.connecting = true;
xmpp_connect_client(xc.conn, NULL, 0, connHandler, &xc);
while(xc.connecting)
xmpp_run_once(xc.ctx, 20L);
if (!xc.connected)
return mkfailure<bool>("Couldn't connect to XMPP server");
return true;
}
/**
* Send a buffer on an XMPP session.
*/
const failable<size_t> send(const char* data, const size_t len, XMPPClient& xc) {
if (len == 0)
return 0;
const size_t written = xc.conn->tls? tls_write(xc.conn->tls, data, len) : sock_write(xc.conn->sock, data, len);
if (written == (size_t)-1) {
xc.conn->error = xc.conn->tls? tls_error(xc.conn->tls) : sock_error();
return mkfailure<size_t>("Couldn't send stanza to XMPP server");
}
return send(data + written, len - written, xc);
}
/**
* Send a string on an XMPP session.
*/
const failable<size_t> send(const string& data, XMPPClient& xc) {
return send(c_str(data), length(data), xc);
}
/**
* Send a stanza on an XMPP session.
*/
const failable<size_t> send(xmpp_stanza_t* const stanza, XMPPClient& xc) {
char *buf;
size_t len;
const int rc = xmpp_stanza_to_text(stanza, &buf, &len);
if (rc != 0)
return mkfailure<size_t>("Couldn't convert stanza to text");
const failable<size_t> r = send(buf, len, xc);
if (!hasContent(r)) {
xmpp_free(xc.conn->ctx, buf);
return r;
}
xmpp_debug(xc.conn->ctx, "conn", "SENT: %s", buf);
xmpp_free(xc.conn->ctx, buf);
return content(r);
}
/**
* Post a message to an XMPP jid.
*/
const failable<bool> post(const value& to, const value& val, XMPPClient& xc) {
debug(to, "chat::post::to");
debug(val, "chat::post::body");
// Convert the value to a string
const string vs(scheme::writeValue(val));
// Build message stanza
xmpp_stanza_t* stanza = namedStanza("message", xc.ctx);
xmpp_stanza_set_type(stanza, "chat");
xmpp_stanza_set_attribute(stanza, "to", c_str(string(to)));
xmpp_stanza_t* body = namedStanza("body", xc.ctx);
xmpp_stanza_add_child(stanza, body);
xmpp_stanza_add_child(body, textStanza(c_str(vs), xc.ctx));
// Send it
const failable<size_t> r = send(stanza, xc);
xmpp_stanza_release(stanza);
if (!hasContent(r))
return mkfailure<bool>(reason(r));
return true;
}
/**
* Disconnect an XMPP session.
*/
const failable<bool> disconnect(XMPPClient& xc) {
xc.disconnecting = true;
const failable<size_t> r = send("</stream:stream>", xc);
if (!hasContent(r))
return mkfailure<bool>(reason(r));
return true;
}
/**
* Listen to messages received by an XMPP client.
*/
const failable<bool> listen(const lambda<failable<bool>(const value&, const value&, XMPPClient&)>& listener, XMPPClient& xc) {
debug("chat::listen");
xc.listener = listener;
xmpp_handler_add(xc.conn, messageHandler, NULL, "message", NULL, &xc);
xc.ctx->loop_status = XMPP_LOOP_RUNNING;
while(xc.connected && !isNil(xc.listener) && xc.ctx->loop_status == XMPP_LOOP_RUNNING)
xmpp_run_once(xc.ctx, 1000L);
return true;
}
}
}
#endif /* tuscany_xmpp_hpp */

View file

@ -0,0 +1,44 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
INCLUDES = -I${TINYCDB_INCLUDE}
incl_HEADERS = *.hpp
incldir = $(prefix)/include/components/filedb
compdir=$(prefix)/components/filedb
EXTRA_DIST = filedb.composite filedb.componentType
comp_LTLIBRARIES = libfiledb.la
noinst_DATA = libfiledb.so
libfiledb_la_SOURCES = filedb.cpp
libfiledb_la_LDFLAGS = -lxml2 -lmozjs
libfiledb.so:
ln -s .libs/libfiledb.so
file_test_SOURCES = file-test.cpp
file_test_LDFLAGS = -lxml2 -lmozjs
client_test_SOURCES = client-test.cpp
client_test_LDFLAGS = -lxml2 -lcurl -lmozjs
dist_noinst_SCRIPTS = filedb-test server-test
noinst_PROGRAMS = file-test client-test
TESTS = filedb-test server-test

View file

@ -0,0 +1,130 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
/**
* Test file database component.
*/
#include <assert.h>
#include "stream.hpp"
#include "string.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "perf.hpp"
#include "../../modules/http/http.hpp"
namespace tuscany {
namespace filedb {
const string uri("http://localhost:8090/filedb");
bool testFileDB() {
http::CURLSession cs("", "", "");
const list<value> i = list<value>()
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$2.99"));
const list<value> a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
const failable<value> id = http::post(a, uri, cs);
assert(hasContent(id));
const string p = path(content(id));
{
const failable<value> val = http::get(uri + p, cs);
assert(hasContent(val));
assert(content(val) == a);
}
const list<value> j = list<value>()
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$3.55"));
const list<value> b = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), j);
{
const failable<value> r = http::put(b, uri + p, cs);
assert(hasContent(r));
assert(content(r) == value(true));
}
{
const failable<value> val = http::get(uri + p, cs);
assert(hasContent(val));
assert(content(val) == b);
}
{
const failable<value> r = http::del(uri + p, cs);
assert(hasContent(r));
assert(content(r) == value(true));
}
{
const failable<value> val = http::get(uri + p, cs);
assert(!hasContent(val));
}
return true;
}
struct getLoop {
const string path;
const value entry;
http::CURLSession cs;
getLoop(const string& path, const value& entry, http::CURLSession cs) : path(path), entry(entry), cs(cs) {
}
const bool operator()() const {
const failable<value> val = http::get(uri + path, cs);
assert(hasContent(val));
assert(content(val) == entry);
return true;
}
};
bool testGetPerf() {
const list<value> i = list<value>()
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$4.55"));
const value a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
http::CURLSession cs("", "", "");
const failable<value> id = http::post(a, uri, cs);
assert(hasContent(id));
const string p = path(content(id));
const lambda<bool()> gl = getLoop(p, a, cs);
cout << "FileDB get test " << time(gl, 5, 200) << " ms" << endl;
return true;
}
}
}
int main() {
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::filedb::testFileDB();
tuscany::filedb::testGetPerf();
tuscany::cout << "OK" << tuscany::endl;
return 0;
}

View file

@ -0,0 +1,94 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
/**
* Test FileDB access functions.
*/
#include <assert.h>
#include "stream.hpp"
#include "string.hpp"
#include "perf.hpp"
#include "filedb.hpp"
namespace tuscany {
namespace filedb {
bool testFileDB(const string& dbname, const string& format) {
FileDB db(dbname, format);
const value k = mklist<value>("a", "b");
const list<value> a = mklist<value>(list<value>() + "ns1:a" + (list<value>() + "@xmlns:ns1" + string("http://aaa")) + (list<value>() + "text" + string("Hey!")));
const list<value> b = mklist<value>(list<value>() + "ns1:b" + (list<value>() + "@xmlns:ns1" + string("http://bbb")) + (list<value>() + "text" + string("Hey!")));
assert(hasContent(post(k, a, db)));
assert((get(k, db)) == value(a));
assert(hasContent(put(k, b, db)));
assert((get(k, db)) == value(b));
assert(hasContent(del(k, db)));
assert(!hasContent(get(k, db)));
assert(hasContent(post(k, a, db)));
return true;
}
struct getLoop {
const value k;
FileDB& db;
const list<value> c;
getLoop(const value& k, FileDB& db) : k(k), db(db),
c(mklist<value>(list<value>() + "ns1:c" + (list<value>() + "@xmlns:ns1" + string("http://ccc")) + (list<value>() + "text" + string("Hey!")))) {
}
const bool operator()() const {
assert((get(k, db)) == value(c));
return true;
}
};
bool testGetPerf(const string& dbname, const string& format) {
FileDB db(dbname, format);
const value k = mklist<value>("c");
const list<value> c = mklist<value>(list<value>() + "ns1:c" + (list<value>() + "@xmlns:ns1" + string("http://ccc")) + (list<value>() + "text" + string("Hey!")));
assert(hasContent(post(k, c, db)));
const lambda<bool()> gl = getLoop(k, db);
cout << "FileDB get test " << time(gl, 5, 5000) << " ms" << endl;
return true;
}
}
}
int main() {
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::filedb::testFileDB("tmp/schemedb", "scheme");
tuscany::filedb::testGetPerf("tmp/schemedb", "scheme");
tuscany::filedb::testFileDB("tmp/xmldb", "xml");
tuscany::filedb::testGetPerf("tmp/xmldb", "xml");
tuscany::filedb::testFileDB("tmp/jsondb", "json");
tuscany::filedb::testGetPerf("tmp/jsondb", "json");
tuscany::cout << "OK" << tuscany::endl;
return 0;
}

View file

@ -0,0 +1,31 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Setup
mkdir -p tmp
mkdir -p tmp/schemedb
mkdir -p tmp/xmldb
mkdir -p tmp/jsondb
# Test
./file-test 2>/dev/null
rc=$?
# Cleanup
return $rc

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
-->
<componentType xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
targetNamespace="http://tuscany.apache.org/xmlns/sca/components">
<service name="filedb"/>
<property name="dbname" type="xsd:string"/>
</composite>

View file

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
-->
<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
targetNamespace="http://tuscany.apache.org/xmlns/sca/components"
name="filedb">
<component name="filedb">
<implementation.cpp path="." library="libfiledb"/>
<property name="dbname">tmp/testdb</property>
<property name="format">scheme</property>
<service name="filedb">
<t:binding.http uri="filedb"/>
</service>
</component>
</composite>

View file

@ -0,0 +1,124 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
/**
* File based database component implementation.
*/
#include "string.hpp"
#include "function.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "filedb.hpp"
namespace tuscany {
namespace filedb {
/**
* Get an item from the database.
*/
const failable<value> get(const list<value>& params, filedb::FileDB& db) {
return filedb::get(car(params), db);
}
/**
* Post an item to the database.
*/
const failable<value> post(const list<value>& params, filedb::FileDB& db) {
const value id = append<value>(car(params), mklist(mkuuid()));
const failable<bool> val = filedb::post(id, cadr(params), db);
if (!hasContent(val))
return mkfailure<value>(reason(val));
return id;
}
/**
* Put an item into the database.
*/
const failable<value> put(const list<value>& params, filedb::FileDB& db) {
const failable<bool> val = filedb::put(car(params), cadr(params), db);
if (!hasContent(val))
return mkfailure<value>(reason(val));
return value(content(val));
}
/**
* Delete an item from the database.
*/
const failable<value> del(const list<value>& params, filedb::FileDB& db) {
const failable<bool> val = filedb::del(car(params), db);
if (!hasContent(val))
return mkfailure<value>(reason(val));
return value(content(val));
}
/**
* Component implementation lambda function.
*/
class applyfiledb {
public:
applyfiledb(filedb::FileDB& db) : db(db) {
}
const value operator()(const list<value>& params) const {
const value func(car(params));
if (func == "get")
return get(cdr(params), db);
if (func == "post")
return post(cdr(params), db);
if (func == "put")
return put(cdr(params), db);
if (func == "delete")
return del(cdr(params), db);
return tuscany::mkfailure<tuscany::value>();
}
private:
filedb::FileDB& db;
};
/**
* Start the component.
*/
const failable<value> start(const list<value>& params) {
// Connect to the configured database and table
const value dbname = ((lambda<value(list<value>)>)car(params))(list<value>());
const value format = ((lambda<value(list<value>)>)cadr(params))(list<value>());
filedb::FileDB& db = *(new (gc_new<filedb::FileDB>()) filedb::FileDB(dbname, format));
// Return the component implementation lambda function
return value(lambda<value(const list<value>&)>(applyfiledb(db)));
}
}
}
extern "C" {
const tuscany::value apply(const tuscany::list<tuscany::value>& params) {
const tuscany::value func(car(params));
if (func == "start")
return tuscany::filedb::start(cdr(params));
return tuscany::mkfailure<tuscany::value>();
}
}

View file

@ -0,0 +1,225 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
#ifndef tuscany_filedb_hpp
#define tuscany_filedb_hpp
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include "string.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "fstream.hpp"
#include "element.hpp"
#include "xml.hpp"
#include "../../modules/scheme/eval.hpp"
#include "../../modules/json/json.hpp"
namespace tuscany {
namespace filedb {
/**
* Represents a FileDB connection.
*/
class FileDB {
public:
FileDB() : owner(false), jscx(*jscontext("")) {
}
FileDB(const string& name, const string& format) : owner(true), name(name), format(format), jscx(*jscontext(format)) {
}
FileDB(const FileDB& c) : owner(false), name(c.name), format(c.format), jscx(c.jscx) {
}
~FileDB() {
}
private:
bool owner;
string name;
string format;
js::JSContext& jscx;
js::JSContext* jscontext(const string& format) {
if (format != "json")
return NULL;
return new (gc_new<js::JSContext>()) js::JSContext();
}
friend const failable<bool> write(const value& v, ostream& os, const string& format, FileDB& db);
friend const failable<value> read(istream& is, const string& format, FileDB& db);
friend const failable<bool> post(const value& key, const value& val, FileDB& db);
friend const failable<bool> put(const value& key, const value& val, FileDB& db);
friend const failable<value> get(const value& key, FileDB& db);
friend const failable<bool> del(const value& key, FileDB& db);
};
/**
* Convert a key to a file name.
*/
const string filename(const list<value>& path, const string& root) {
if (isNil(path))
return root;
string name = root + "/" + scheme::writeValue(car(path));
return filename(cdr(path), name);
}
const string filename(const value& key, const string& root) {
if (!isList(key))
return filename(mklist(key), root);
return filename((list<value>)key, root);
}
/**
* Make the parent directories of a keyed file.
*/
const failable<bool> mkdirs(const list<value>& path, const string& root) {
if (isNil(cdr(path)))
return true;
string dir = root + "/" + scheme::writeValue(car(path));
mkdir(c_str(dir), S_IRWXU);
return mkdirs(cdr(path), dir);
}
/**
* Write a value to a database file.
*/
const failable<bool> write(const value& v, ostream& os, const string& format, FileDB& db) {
if (format == "scheme") {
const string vs(scheme::writeValue(v));
os << vs;
return true;
}
if (format == "xml") {
failable<list<string> > s = writeXML(valuesToElements(v));
if (!hasContent(s))
return mkfailure<bool>(reason(s));
write(content(s), os);
return true;
}
if (format == "json") {
failable<list<string> > s = json::writeJSON(valuesToElements(v), db.jscx);
if (!hasContent(s))
return mkfailure<bool>(reason(s));
write(content(s), os);
return true;
}
return mkfailure<bool>(string("Unsupported database format: ") + format);
}
/**
* Read a value from a database file.
*/
const failable<value> read(istream& is, const string& format, FileDB& db) {
if (format == "scheme") {
return scheme::readValue(is);
}
if (format == "xml") {
const value v = elementsToValues(readXML(streamList(is)));
return v;
}
if (format == "json") {
const failable<list<value> > fv = json::readJSON(streamList(is), db.jscx);
if (!hasContent(fv))
return mkfailure<value>(reason(fv));
const value v = elementsToValues(content(fv));
return v;
}
return mkfailure<value>(string("Unsupported database format: ") + format);
}
/**
* Post a new item to the database.
*/
const failable<bool> post(const value& key, const value& val, FileDB& db) {
debug(key, "filedb::post::key");
debug(val, "filedb::post::value");
debug(db.name, "filedb::post::dbname");
if (isList(key))
mkdirs(key, db.name);
ofstream os(filename(key, db.name));
if (os.fail())
return mkfailure<bool>("Couldn't post file database entry.");
const failable<bool> r = write(val, os, db.format, db);
debug(r, "filedb::post::result");
return r;
}
/**
* Update an item in the database. If the item doesn't exist it is added.
*/
const failable<bool> put(const value& key, const value& val, FileDB& db) {
debug(key, "filedb::put::key");
debug(val, "filedb::put::value");
debug(db.name, "filedb::put::dbname");
if (isList(key))
mkdirs(key, db.name);
ofstream os(filename(key, db.name));
if (os.fail())
return mkfailure<bool>("Couldn't put file database entry.");
const failable<bool> r = write(val, os, db.format, db);
debug(r, "filedb::put::result");
return r;
}
/**
* Get an item from the database.
*/
const failable<value> get(const value& key, FileDB& db) {
debug(key, "filedb::get::key");
debug(db.name, "filedb::get::dbname");
ifstream is(filename(key, db.name));
if (is.fail())
return mkfailure<value>("Couldn't get file database entry.");
const failable<value> val = read(is, db.format, db);
debug(val, "filedb::get::result");
return val;
}
/**
* Delete an item from the database
*/
const failable<bool> del(const value& key, FileDB& db) {
debug(key, "filedb::delete::key");
debug(db.name, "filedb::delete::dbname");
const int rc = unlink(c_str(filename(key, db.name)));
if (rc == -1)
return mkfailure<bool>("Couldn't delete file database entry.");
debug(true, "filedb::delete::result");
return true;
}
}
}
#endif /* tuscany_filedb_hpp */

View file

@ -0,0 +1,40 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Setup
../../modules/http/httpd-conf tmp localhost 8090 ../../modules/http/htdocs
../../modules/server/server-conf tmp
../../modules/server/scheme-conf tmp
cat >>tmp/conf/httpd.conf <<EOF
SCAContribution `pwd`/
SCAComposite filedb.composite
EOF
mkdir -p tmp/testdb
../../modules/http/httpd-start tmp
sleep 2
# Test
./client-test 2>/dev/null
rc=$?
# Cleanup
../../modules/http/httpd-stop tmp
sleep 2
return $rc

View file

@ -0,0 +1,76 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
if WANT_LOG
INCLUDES = -I${THRIFT_INCLUDE} -I${FB303_INCLUDE}
incl_HEADERS = *.hpp
incldir = $(prefix)/include/components/log
dist_comp_SCRIPTS = scribed-central-conf scribed-client-conf scribed-central-start scribed-central-stop scribed-client-start scribed-client-stop scribe-tail-start scribe-tail-stop
compdir=$(prefix)/components/log
comp_DATA = scribe.prefix thrift.prefix
scribe.prefix: $(top_builddir)/config.status
echo ${SCRIBE_PREFIX} >scribe.prefix
thrift.prefix: $(top_builddir)/config.status
echo ${THRIFT_PREFIX} >thrift.prefix
EXTRA_DIST = log.composite log.componentType logger.componentType *.scm *.thrift
BUILT_SOURCES=gen-cpp/fb303_constants.cpp gen-cpp/fb303_types.cpp gen-cpp/scribe_constants.cpp gen-cpp/scribe.cpp gen-cpp/scribe_types.cpp gen-cpp/FacebookService.cpp gen-cpp/scribe.h
gen-cpp/fb303_constants.cpp gen-cpp/fb303_types.cpp gen-cpp/scribe_constants.cpp gen-cpp/scribe.cpp gen-cpp/scribe_types.cpp gen-cpp/FacebookService.cpp gen-cpp/scribe.h: scribe.thrift
${THRIFT_PREFIX}/bin/thrift -r --gen cpp scribe.thrift
CLEANFILES = gen-cpp/*
comp_LTLIBRARIES = liblog.la liblogger.la
noinst_DATA = liblog.so liblogger.so
CXXFLAGS = ${DEFAULT_CXXFLAGS} -Wno-unused-parameter -Wno-conversion
nodist_liblog_la_SOURCES = gen-cpp/fb303_constants.cpp gen-cpp/fb303_types.cpp gen-cpp/scribe_constants.cpp gen-cpp/scribe.cpp gen-cpp/scribe_types.cpp gen-cpp/FacebookService.cpp gen-cpp/scribe.h
liblog_la_CXXFLAGS = -Wno-unused-parameter -Wno-conversion
liblog_la_SOURCES = log.cpp
liblog_la_LDFLAGS = -L${THRIFT_LIB} -R${THRIFT_LIB} -lthrift -L${FB303_LIB} -R${FB303_LIB} -lfb303 -L${SCRIBE_LIB} -R${SCRIBE_LIB} -lscribe
liblog.so:
ln -s .libs/liblog.so
nodist_liblogger_la_SOURCES = gen-cpp/fb303_constants.cpp gen-cpp/fb303_types.cpp gen-cpp/scribe_constants.cpp gen-cpp/scribe.cpp gen-cpp/scribe_types.cpp gen-cpp/FacebookService.cpp gen-cpp/scribe.h
liblogger_la_CXXFLAGS = -Wno-unused-parameter -Wno-conversion
liblogger_la_SOURCES = logger.cpp
liblogger_la_LDFLAGS = -L${THRIFT_LIB} -R${THRIFT_LIB} -lthrift -L${FB303_LIB} -R${FB303_LIB} -lfb303 -L${SCRIBE_LIB} -R${SCRIBE_LIB} -lscribe
liblogger.so:
ln -s .libs/liblogger.so
comp_PROGRAMS = scribe-cat
nodist_scribe_cat_SOURCES = gen-cpp/fb303_constants.cpp gen-cpp/fb303_types.cpp gen-cpp/scribe_constants.cpp gen-cpp/scribe.cpp gen-cpp/scribe_types.cpp gen-cpp/FacebookService.cpp gen-cpp/scribe.h
scribe_cat_CXXFLAGS = -Wno-unused-parameter -Wno-conversion
scribe_cat_SOURCES = scribe-cat.cpp
scribe_cat_LDFLAGS = -L${THRIFT_LIB} -R${THRIFT_LIB} -lthrift -L${FB303_LIB} -R${FB303_LIB} -lfb303 -L${SCRIBE_LIB} -R${SCRIBE_LIB} -lscribe
client_test_SOURCES = client-test.cpp
client_test_LDFLAGS = -lxml2 -lcurl -lmozjs
dist_noinst_SCRIPTS = scribe-test server-test
noinst_PROGRAMS = client-test
TESTS = scribe-test server-test
endif

View file

@ -0,0 +1,20 @@
; Licensed to the Apache Software Foundation (ASF) under one
; or more contributor license agreements. See the NOTICE file
; distributed with this work for additional information
; regarding copyright ownership. The ASF licenses this file
; to you under the Apache License, Version 2.0 (the
; "License"); you may not use this file except in compliance
; with the License. You may obtain a copy of the License at
;
; http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing,
; software distributed under the License is distributed on an
; "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
; KIND, either express or implied. See the License for the
; specific language governing permissions and limitations
; under the License.
; Logger test case
(define (add a b) (+ a b))

View file

@ -0,0 +1,107 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
/**
* Test log component.
*/
#include <assert.h>
#include "stream.hpp"
#include "string.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "perf.hpp"
#include "../../modules/http/http.hpp"
namespace tuscany {
namespace log {
const string uri("http://localhost:8090/log");
bool testLog() {
http::CURLSession cs("", "", "");
const list<value> i = list<value>()
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$2.99"));
const list<value> a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
const failable<value> id = http::post(a, uri, cs);
assert(hasContent(id));
return true;
}
struct logLoop {
const value a;
const string uri;
http::CURLSession cs;
logLoop(const value& a, const string& uri, http::CURLSession cs) : a(a), uri(uri), cs(cs) {
}
const bool operator()() const {
const failable<value> id = http::post(a, uri, cs);
assert(hasContent(id));
return true;
}
};
bool testLogPerf() {
const list<value> i = list<value>()
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$2.99"));
const value a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
http::CURLSession cs("", "", "");
const failable<value> id = http::post(a, uri, cs);
assert(hasContent(id));
const lambda<bool()> ll = logLoop(a, uri, cs);
cout << "Log test " << time(ll, 5, 200) << " ms" << endl;
return true;
}
bool testLogger() {
http::CURLSession cs("", "", "");
const failable<value> res = http::evalExpr(mklist<value>(string("sum"), 33, 22), string("http://localhost:8090/client"), cs);
assert(hasContent(res));
assert((int)content(res) == 55);
return true;
}
}
}
int main() {
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::log::testLog();
tuscany::log::testLogPerf();
tuscany::log::testLogger();
tuscany::cout << "OK" << tuscany::endl;
return 0;
}

View file

@ -0,0 +1,20 @@
; Licensed to the Apache Software Foundation (ASF) under one
; or more contributor license agreements. See the NOTICE file
; distributed with this work for additional information
; regarding copyright ownership. The ASF licenses this file
; to you under the Apache License, Version 2.0 (the
; "License"); you may not use this file except in compliance
; with the License. You may obtain a copy of the License at
;
; http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing,
; software distributed under the License is distributed on an
; "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
; KIND, either express or implied. See the License for the
; specific language governing permissions and limitations
; under the License.
; Logger test case
(define (sum a b adder) (adder "add" a b))

View file

@ -0,0 +1,112 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/**
* fb303.thrift
*/
namespace java com.facebook.fb303
namespace cpp facebook.fb303
namespace perl Facebook.FB303
/**
* Common status reporting mechanism across all services
*/
enum fb_status {
DEAD = 0,
STARTING = 1,
ALIVE = 2,
STOPPING = 3,
STOPPED = 4,
WARNING = 5,
}
/**
* Standard base service
*/
service FacebookService {
/**
* Returns a descriptive name of the service
*/
string getName(),
/**
* Returns the version of the service
*/
string getVersion(),
/**
* Gets the status of this service
*/
fb_status getStatus(),
/**
* User friendly description of status, such as why the service is in
* the dead or warning state, or what is being started or stopped.
*/
string getStatusDetails(),
/**
* Gets the counters for this service
*/
map<string, i64> getCounters(),
/**
* Gets the value of a single counter
*/
i64 getCounter(1: string key),
/**
* Sets an option
*/
void setOption(1: string key, 2: string value),
/**
* Gets an option
*/
string getOption(1: string key),
/**
* Gets all options
*/
map<string, string> getOptions(),
/**
* Returns a CPU profile over the given time interval (client and server
* must agree on the profile format).
*/
string getCpuProfile(1: i32 profileDurationInSec),
/**
* Returns the unix time that the server has been running since
*/
i64 aliveSince(),
/**
* Tell the server to reload its configuration, reopen log files, etc
*/
oneway void reinitialize(),
/**
* Suggest a shutdown to the server
*/
oneway void shutdown(),
}

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
-->
<componentType xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
targetNamespace="http://tuscany.apache.org/xmlns/sca/components">
<service name="log"/>
<property name="category" type="xsd:string">default</property>
</composite>

View file

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
-->
<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
targetNamespace="http://tuscany.apache.org/xmlns/sca/components"
name="log">
<component name="log">
<implementation.cpp path="." library="liblog"/>
<property name="category">default</property>
<service name="log">
<t:binding.http uri="log"/>
</service>
</component>
<component name="client">
<implementation.scheme script="client-test.scm"/>
<service name="client">
<t:binding.http uri="client"/>
</service>
<reference name="adder" target="logger"/>
</component>
<component name="logger">
<implementation.cpp path="." library="liblogger"/>
<property name="category">default</property>
<service name="logger">
<t:binding.http uri="logger"/>
</service>
<reference name="relay" target="adder"/>
</component>
<component name="adder">
<implementation.scheme script="adder-test.scm"/>
<service name="adder">
<t:binding.http uri="adder"/>
</service>
</component>
</composite>

View file

@ -0,0 +1,94 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
/**
* Scribe-based log component implementation.
*/
#include "string.hpp"
#include "function.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "scribe.hpp"
namespace tuscany {
namespace log {
/**
* Post an item to the Scribe log.
*/
const failable<value> post(const list<value>& params, const value& category, scribe::Scribe& sc) {
debug(cadr(params), "log::post::value");
const failable<bool> val = scribe::log(cadr(params), category, sc);
if (!hasContent(val))
return mkfailure<value>(reason(val));
return value(mklist<value>(true));
}
/**
* Component implementation lambda function.
*/
class applyLog {
public:
applyLog(const value& category, scribe::Scribe& sc) : category(category), sc(sc) {
}
const value operator()(const list<value>& params) const {
const value func(car(params));
if (func == "post")
return post(cdr(params), category, sc);
return tuscany::mkfailure<tuscany::value>();
}
private:
const value category;
scribe::Scribe& sc;
};
/**
* Start the component.
*/
const failable<value> start(unused const list<value>& params) {
// Connect to Scribe
scribe::Scribe& sc = *(new (gc_new<scribe::Scribe>()) scribe::Scribe("localhost", 1464));
// Extract the configured category
const value category = ((lambda<value(list<value>)>)car(params))(list<value>());
debug(category, "log::start::category");
// Return the component implementation lambda function
return value(lambda<value(const list<value>&)>(applyLog(category, sc)));
}
}
}
extern "C" {
const tuscany::value apply(const tuscany::list<tuscany::value>& params) {
const tuscany::value func(car(params));
if (func == "start")
return tuscany::log::start(cdr(params));
return tuscany::mkfailure<tuscany::value>();
}
}

View file

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
-->
<componentType xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
targetNamespace="http://tuscany.apache.org/xmlns/sca/components">
<service name="logger"/>
<reference name="relay"/>
<property name="category" type="xsd:string">default</property>
</composite>

View file

@ -0,0 +1,92 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
/**
* Scribe-based logger component implementation, used to intercept
* and log service invocations.
*/
#include "string.hpp"
#include "function.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "scribe.hpp"
namespace tuscany {
namespace logger {
/**
* Component implementation lambda function.
*/
class applyLog {
public:
applyLog(const lambda<value(const list<value>&)>& relay, const value& category, scribe::Scribe& sc) : relay(relay), category(category), sc(sc) {
}
const value operator()(const list<value>& params) const {
// Log the function params
debug(params, "logger::apply::params");
scribe::log(params, category, sc);
// Relay the function
const failable<value> res = relay(params);
// Log the result
scribe::log(res, category, sc);
return res;
}
private:
const lambda<value(const list<value>&)> relay;
const value category;
scribe::Scribe& sc;
};
/**
* Start the component.
*/
const failable<value> start(unused const list<value>& params) {
// Connect to Scribe
scribe::Scribe& sc = *(new (gc_new<scribe::Scribe>()) scribe::Scribe("localhost", 1464));
// Extract the configured relay service and category
const value rel = car(params);
const value category = ((lambda<value(list<value>)>)cadr(params))(list<value>());
debug(category, "logger::start::category");
// Return the component implementation lambda function
return value(lambda<value(const list<value>&)>(applyLog(rel, category, sc)));
}
}
}
extern "C" {
const tuscany::value apply(const tuscany::list<tuscany::value>& params) {
const tuscany::value func(car(params));
if (func == "start")
return tuscany::logger::start(cdr(params));
return tuscany::mkfailure<tuscany::value>();
}
}

View file

@ -0,0 +1,77 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
/**
* A utility that logs stdin into a scribe log.
*/
#include "string.hpp"
#include "function.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#undef debug
#define debug(...)
#include "scribe.hpp"
namespace tuscany {
namespace scribecat {
int cat(const string& category, const string& type) {
// Connect to Scribe
scribe::Scribe& sc = *(new (gc_new<scribe::Scribe>()) scribe::Scribe("localhost", 1464));
// Read lines from stdin and log them
char buf[8192];
for (;;) {
const char* s = fgets(buf, 8192, stdin);
if (s == NULL)
return 0;
const int l = strlen(s);
if (l < 2)
return 0;
buf[l - 1] = '\0';
// Log each line as is
if (length(type) == 0) {
const failable<bool> val = scribe::log(buf, category, sc);
if (!hasContent(val))
return 1;
continue;
}
// Log each line prefixed with time and a type tag
ostringstream os;
os << "[" << logTime() << "] [" << type << "] " << buf;
const failable<bool> val = scribe::log(c_str(str(os)), category, sc);
if (!hasContent(val))
return 1;
}
}
}
}
int main(const int argc, const char** argv) {
return tuscany::scribecat::cat(argc < 2? "default" : argv[1], argc < 3? "" : argv[2]);
}

View file

@ -0,0 +1,44 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Tail a file and pipe into scribe-cat
here=`readlink -f $0`; here=`dirname $here`
category=""
type=""
file=""
if [ "$3" != "" ]; then
category=$1
type=$2
file=$3
else
if [ "$2" != "" ]; then
category=$1
file=$2
else
file=$1
fi
fi
mkdir -p `dirname $file`
touch $file
file=`readlink -f $file`
tail -f -n 0 $file | $here/scribe-cat $category $type &

View file

@ -0,0 +1,42 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Stop tailing a file
here=`readlink -f $0`; here=`dirname $here`
category=""
type=""
file=""
if [ "$3" != "" ]; then
category=$1
type=$2
file=$3
else
if [ "$2" != "" ]; then
category=$1
file=$2
else
file=$1
fi
fi
file=`readlink -f $file`
cmd="tail -f -n 0 $file"
kill `ps -ef | grep -v grep | grep "${cmd}" | awk '{ print $2 }'`

View file

@ -0,0 +1,43 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
echo "Testing..."
# Setup
rm -rf tmp
./scribed-central-conf tmp
./scribed-client-conf tmp localhost
./scribed-central-start tmp
./scribed-client-start tmp
sleep 1
# Test logging a message
echo test | ./scribe-cat >/dev/null
sleep 4
grep test tmp/scribe/logs/central/default/default_current >/dev/null
rc=$?
# Cleanup
./scribed-client-stop tmp
./scribed-central-stop tmp
sleep 1
if [ "$rc" = "0" ]; then
echo "OK"
fi
return $rc

View file

@ -0,0 +1,147 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
#ifndef tuscany_scribe_hpp
#define tuscany_scribe_hpp
/**
* Scribe logging functions.
*/
// Work around redundant defines in Scribe headers
#undef PACKAGE
#undef PACKAGE_BUGREPORT
#undef PACKAGE_NAME
#undef PACKAGE_STRING
#undef PACKAGE_TARNAME
#undef PACKAGE_VERSION
#undef VERSION
// Ignore integer conversion issues in Thrift and Scribe headers
#ifdef WANT_MAINTAINER_MODE
#pragma GCC diagnostic ignored "-Wconversion"
#endif
#include <protocol/TBinaryProtocol.h>
#include <transport/TSocket.h>
#include <transport/TTransportUtils.h>
#include "gen-cpp/scribe.h"
#ifdef WANT_MAINTAINER_MODE
#pragma GCC diagnostic warning "-Wconversion"
#endif
#include "string.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "../../modules/scheme/eval.hpp"
namespace tuscany {
namespace scribe {
/**
* Represents a Scribe connection.
*/
class Scribe {
public:
Scribe() : owner(false) {
}
Scribe(const string host, const int port) : owner(true) {
init(host, port);
}
Scribe(const Scribe& c) : owner(false) {
client = c.client;
transport = c.transport;
}
~Scribe() {
if (!owner)
return;
try {
transport->close();
delete client;
} catch (const std::exception& e) {
mkfailure<bool>(e.what());
}
}
private:
bool owner;
::scribe::thrift::scribeClient* client;
boost::shared_ptr<apache::thrift::transport::TTransport> transport;
friend const failable<bool> log(const value& val, const value& category, const Scribe& sc);
/**
* Initialize the Scribe connection.
*/
const failable<bool> init(const string& host, const int port) {
try {
boost::shared_ptr<apache::thrift::transport::TTransport> sock(new apache::thrift::transport::TSocket(c_str(host), port));
boost::shared_ptr<apache::thrift::transport::TFramedTransport> framedSock(new apache::thrift::transport::TFramedTransport(sock));
transport = framedSock;
boost::shared_ptr<apache::thrift::protocol::TProtocol> proto(new apache::thrift::protocol::TBinaryProtocol(transport));
client = new ::scribe::thrift::scribeClient(proto);
transport->open();
return true;
} catch (const std::exception& e) {
return mkfailure<bool>(e.what());
}
}
};
/**
* Log an item.
*/
const failable<bool> log(const value& val, const value& category, const Scribe& sc) {
debug(val, "scribe::log::value");
debug(category, "scribe::log::category");
const value cat = isString(category)? value(c_str(category)):category;
const string cs(scheme::writeValue(cat));
const string vs(scheme::writeValue(val));
try {
::scribe::thrift::LogEntry entry;
entry.category = c_str(cs);
entry.message = c_str(vs);
std::vector< ::scribe::thrift::LogEntry> msgs;
msgs.push_back(entry);
int result = sc.client->Log(msgs);
if (result != ::scribe::thrift::OK)
return mkfailure<bool>("Could not log value, retry later");
} catch (const std::exception& e) {
return mkfailure<bool>(e.what());
}
debug(true, "scribe::log::result");
return true;
}
}
}
#endif /* tuscany_scribe_hpp */

View file

@ -0,0 +1,39 @@
#!/usr/local/bin/thrift --cpp --php
## Copyright (c) 2007-2008 Facebook
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
## See accompanying file LICENSE or visit the Scribe site at:
## http://developers.facebook.com/scribe/
include "fb303.thrift"
namespace cpp scribe.thrift
enum ResultCode
{
OK,
TRY_LATER
}
struct LogEntry
{
1: string category,
2: string message
}
service scribe extends fb303.FacebookService
{
ResultCode Log(1: list<LogEntry> messages);
}

View file

@ -0,0 +1,73 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Generate a Scribe central conf
here=`readlink -f $0`; here=`dirname $here`
mkdir -p $1
root=`readlink -f $1`
port=$2
if [ "$port" = "" ]; then
port="1463"
fi
mkdir -p $root/scribe/conf
mkdir -p $root/scribe/logs/central
mkdir -p $root/scribe/logs/central-secondary
cat >$root/scribe/conf/scribe-central.conf <<EOF
# Generated by: scribed-central-conf $*
# Scribe central configuration
port=$port
max_msg_per_second=2000000
check_interval=3
# Log store configuration
<store>
category=default
type=buffer
target_write_size=20480
max_write_interval=1
buffer_send_rate=2
retry_interval=30
retry_interval_range=10
<primary>
type=file
fs_type=std
file_path=$root/scribe/logs/central
base_filename=central
max_size=1000000
add_newlines=1
rotate_period=daily
rotate_hour=0
rotate_minute=10
</primary>
<secondary>
type=file
fs_type=std
file_path=$root/scribe/logs/central-secondary
base_filename=central
max_size=3000000
</secondary>
</store>
EOF

View file

@ -0,0 +1,27 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Start central scribed
here=`readlink -f $0`; here=`dirname $here`
root=`readlink -f $1`
scribe_prefix=`cat $here/scribe.prefix`
thrift_prefix=`cat $here/thrift.prefix`
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${thrift_prefix}/lib:${thrift_prefix}/contrib/fb303/lib:${scribe_prefix}/lib
$scribe_prefix/bin/scribed -c $root/scribe/conf/scribe-central.conf 1>$root/scribe/logs/central.log 2>&1 &

View file

@ -0,0 +1,28 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Stop central scribed
here=`readlink -f $0`; here=`dirname $here`
root=`readlink -f $1`
scribe_prefix=`cat $here/scribe.prefix`
thrift_prefix=`cat $here/thrift.prefix`
scribed="$scribe_prefix/bin/scribed -c $root/scribe/conf/scribe-central.conf"
kill `ps -ef | grep -v grep | grep "${scribed}" | awk '{ print $2 }'`

View file

@ -0,0 +1,67 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Generate a Scribe client conf
here=`readlink -f $0`; here=`dirname $here`
mkdir -p $1
root=`readlink -f $1`
central=$2
cport=$3
if [ "$cport" = "" ]; then
cport="1463"
fi
mkdir -p $root/scribe/conf
mkdir -p $root/scribe/logs/client-secondary
cat >$root/scribe/conf/scribe-client.conf <<EOF
# Generated by: scribed-client-conf $*
# Scribe client configuration
port=1464
max_msg_per_second=2000000
check_interval=3
# Forward all messages to central Scribe on port 1463
# Save them locally as well
<store>
category=default
type=buffer
target_write_size=20480
max_write_interval=1
buffer_send_rate=1
retry_interval=30
retry_interval_range=10
<primary>
type=network
remote_host=$central
remote_port=$cport
</primary>
<secondary>
type=file
fs_type=std
file_path=$root/scribe/logs/client-secondary
base_filename=client
max_size=3000000
</secondary>
</store>
EOF

View file

@ -0,0 +1,27 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Start client scribed
here=`readlink -f $0`; here=`dirname $here`
root=`readlink -f $1`
scribe_prefix=`cat $here/scribe.prefix`
thrift_prefix=`cat $here/thrift.prefix`
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${thrift_prefix}/lib:${thrift_prefix}/contrib/fb303/lib:${scribe_prefix}/lib
$scribe_prefix/bin/scribed -c $root/scribe/conf/scribe-client.conf 1>$root/scribe/logs/client.log 2>&1 &

View file

@ -0,0 +1,28 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Stop client scribed
here=`readlink -f $0`; here=`dirname $here`
root=`readlink -f $1`
scribe_prefix=`cat $here/scribe.prefix`
thrift_prefix=`cat $here/thrift.prefix`
scribed="$scribe_prefix/bin/scribed -c $root/scribe/conf/scribe-client.conf"
kill `ps -ef | grep -v grep | grep "${scribed}" | awk '{ print $2 }'`

View file

@ -0,0 +1,65 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Setup
../../modules/http/httpd-conf tmp localhost 8090 ../../modules/http/htdocs
../../modules/server/server-conf tmp
../../modules/server/scheme-conf tmp
cat >>tmp/conf/httpd.conf <<EOF
SCAContribution `pwd`/
SCAComposite log.composite
EOF
rm -rf tmp/scribe
./scribed-central-conf tmp
./scribed-client-conf tmp localhost
./scribed-central-start tmp
./scribed-client-start tmp
sleep 1
../../modules/http/httpd-start tmp
sleep 2
# Test
./client-test 2>/dev/null
rc=$?
if [ "$rc" = "0" ]; then
echo "Testing..."
sleep 4
grep "Apple" tmp/scribe/logs/central/default/default_current >/dev/null
rc=$?
fi
if [ "$rc" = "0" ]; then
grep "(add 33 22)" tmp/scribe/logs/central/default/default_current >/dev/null
rc=$?
fi
if [ "$rc" = "0" ]; then
grep "55" tmp/scribe/logs/central/default/default_current >/dev/null
rc=$?
fi
# Cleanup
../../modules/http/httpd-stop tmp
sleep 1
./scribed-client-stop tmp
./scribed-central-stop tmp
sleep 1
if [ "$rc" = "0" ]; then
echo "OK"
fi
return $rc

View file

@ -0,0 +1,49 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
INCLUDES = -I${TINYCDB_INCLUDE}
incl_HEADERS = *.hpp
incldir = $(prefix)/include/components/nosqldb
dist_comp_SCRIPTS = tinycdb
compdir=$(prefix)/components/nosqldb
comp_DATA = tinycdb.prefix
tinycdb.prefix: $(top_builddir)/config.status
echo ${TINYCDB_PREFIX} >tinycdb.prefix
EXTRA_DIST = nosqldb.composite nosqldb.componentType
comp_LTLIBRARIES = libnosqldb.la
noinst_DATA = libnosqldb.so
libnosqldb_la_SOURCES = nosqldb.cpp
libnosqldb_la_LDFLAGS = -L${TINYCDB_LIB} -R${TINYCDB_LIB} -lcdb
libnosqldb.so:
ln -s .libs/libnosqldb.so
tinycdb_test_SOURCES = tinycdb-test.cpp
tinycdb_test_LDFLAGS = -L${TINYCDB_LIB} -R${TINYCDB_LIB} -lcdb
client_test_SOURCES = client-test.cpp
client_test_LDFLAGS = -lxml2 -lcurl -lmozjs
dist_noinst_SCRIPTS = nosqldb-test server-test
noinst_PROGRAMS = tinycdb-test client-test
TESTS = nosqldb-test server-test

View file

@ -0,0 +1,130 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
/**
* Test NoSQL database component.
*/
#include <assert.h>
#include "stream.hpp"
#include "string.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "perf.hpp"
#include "../../modules/http/http.hpp"
namespace tuscany {
namespace nosqldb {
const string uri("http://localhost:8090/nosqldb");
bool testNoSqlDb() {
http::CURLSession cs("", "", "");
const list<value> i = list<value>()
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$2.99"));
const list<value> a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
const failable<value> id = http::post(a, uri, cs);
assert(hasContent(id));
const string p = path(content(id));
{
const failable<value> val = http::get(uri + p, cs);
assert(hasContent(val));
assert(content(val) == a);
}
const list<value> j = list<value>()
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$3.55"));
const list<value> b = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), j);
{
const failable<value> r = http::put(b, uri + p, cs);
assert(hasContent(r));
assert(content(r) == value(true));
}
{
const failable<value> val = http::get(uri + p, cs);
assert(hasContent(val));
assert(content(val) == b);
}
{
const failable<value> r = http::del(uri + p, cs);
assert(hasContent(r));
assert(content(r) == value(true));
}
{
const failable<value> val = http::get(uri + p, cs);
assert(!hasContent(val));
}
return true;
}
struct getLoop {
const string path;
const value entry;
http::CURLSession cs;
getLoop(const string& path, const value& entry, http::CURLSession cs) : path(path), entry(entry), cs(cs) {
}
const bool operator()() const {
const failable<value> val = http::get(uri + path, cs);
assert(hasContent(val));
assert(content(val) == entry);
return true;
}
};
bool testGetPerf() {
const list<value> i = list<value>()
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$4.55"));
const value a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
http::CURLSession cs("", "", "");
const failable<value> id = http::post(a, uri, cs);
assert(hasContent(id));
const string p = path(content(id));
const lambda<bool()> gl = getLoop(p, a, cs);
cout << "NoSqldb get test " << time(gl, 5, 200) << " ms" << endl;
return true;
}
}
}
int main() {
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::nosqldb::testNoSqlDb();
tuscany::nosqldb::testGetPerf();
tuscany::cout << "OK" << tuscany::endl;
return 0;
}

View file

@ -0,0 +1,29 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Setup
mkdir -p tmp
./tinycdb -c -m tmp/test.cdb </dev/null
# Test
./tinycdb-test 2>/dev/null
rc=$?
# Cleanup
return $rc

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
-->
<componentType xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
targetNamespace="http://tuscany.apache.org/xmlns/sca/components">
<service name="nosqldb"/>
<property name="dbname" type="xsd:string"/>
</composite>

View file

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
-->
<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
targetNamespace="http://tuscany.apache.org/xmlns/sca/components"
name="nosqldb">
<component name="nosqldb">
<implementation.cpp path="." library="libnosqldb"/>
<property name="dbname">tmp/test.cdb</property>
<service name="nosqldb">
<t:binding.http uri="nosqldb"/>
</service>
</component>
</composite>

View file

@ -0,0 +1,123 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
/**
* TinyCDB-based database component implementation.
*/
#include "string.hpp"
#include "function.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "tinycdb.hpp"
namespace tuscany {
namespace nosqldb {
/**
* Get an item from the database.
*/
const failable<value> get(const list<value>& params, tinycdb::TinyCDB& cdb) {
return tinycdb::get(car(params), cdb);
}
/**
* Post an item to the database.
*/
const failable<value> post(const list<value>& params, tinycdb::TinyCDB& cdb) {
const value id = append<value>(car(params), mklist(mkuuid()));
const failable<bool> val = tinycdb::post(id, cadr(params), cdb);
if (!hasContent(val))
return mkfailure<value>(reason(val));
return id;
}
/**
* Put an item into the database.
*/
const failable<value> put(const list<value>& params, tinycdb::TinyCDB& cdb) {
const failable<bool> val = tinycdb::put(car(params), cadr(params), cdb);
if (!hasContent(val))
return mkfailure<value>(reason(val));
return value(content(val));
}
/**
* Delete an item from the database.
*/
const failable<value> del(const list<value>& params, tinycdb::TinyCDB& cdb) {
const failable<bool> val = tinycdb::del(car(params), cdb);
if (!hasContent(val))
return mkfailure<value>(reason(val));
return value(content(val));
}
/**
* Component implementation lambda function.
*/
class applyNoSqldb {
public:
applyNoSqldb(tinycdb::TinyCDB& cdb) : cdb(cdb) {
}
const value operator()(const list<value>& params) const {
const value func(car(params));
if (func == "get")
return get(cdr(params), cdb);
if (func == "post")
return post(cdr(params), cdb);
if (func == "put")
return put(cdr(params), cdb);
if (func == "delete")
return del(cdr(params), cdb);
return tuscany::mkfailure<tuscany::value>();
}
private:
tinycdb::TinyCDB& cdb;
};
/**
* Start the component.
*/
const failable<value> start(unused const list<value>& params) {
// Connect to the configured database and table
const value dbname = ((lambda<value(list<value>)>)car(params))(list<value>());
tinycdb::TinyCDB& cdb = *(new (gc_new<tinycdb::TinyCDB>()) tinycdb::TinyCDB(dbname));
// Return the component implementation lambda function
return value(lambda<value(const list<value>&)>(applyNoSqldb(cdb)));
}
}
}
extern "C" {
const tuscany::value apply(const tuscany::list<tuscany::value>& params) {
const tuscany::value func(car(params));
if (func == "start")
return tuscany::nosqldb::start(cdr(params));
return tuscany::mkfailure<tuscany::value>();
}
}

View file

@ -0,0 +1,40 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Setup
../../modules/http/httpd-conf tmp localhost 8090 ../../modules/http/htdocs
../../modules/server/server-conf tmp
../../modules/server/scheme-conf tmp
cat >>tmp/conf/httpd.conf <<EOF
SCAContribution `pwd`/
SCAComposite nosqldb.composite
EOF
./tinycdb -c -m tmp/test.cdb </dev/null
../../modules/http/httpd-start tmp
sleep 2
# Test
./client-test 2>/dev/null
rc=$?
# Cleanup
../../modules/http/httpd-stop tmp
sleep 2
return $rc

View file

@ -0,0 +1,24 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
here=`readlink -f $0`; here=`dirname $here`
tinycdb_prefix=`cat $here/tinycdb.prefix`
$tinycdb_prefix/bin/cdb $*

View file

@ -0,0 +1,82 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
/**
* Test TinyCDB access functions.
*/
#include <assert.h>
#include "stream.hpp"
#include "string.hpp"
#include "perf.hpp"
#include "tinycdb.hpp"
namespace tuscany {
namespace tinycdb {
bool testTinyCDB() {
TinyCDB cdb("tmp/test.cdb");
const value k = mklist<value>("a");
assert(hasContent(post(k, string("AAA"), cdb)));
assert((get(k, cdb)) == value(string("AAA")));
assert(hasContent(put(k, string("aaa"), cdb)));
assert((get(k, cdb)) == value(string("aaa")));
assert(hasContent(del(k, cdb)));
assert(!hasContent(get(k, cdb)));
return true;
}
struct getLoop {
const value k;
TinyCDB& cdb;
getLoop(const value& k, TinyCDB& cdb) : k(k), cdb(cdb) {
}
const bool operator()() const {
assert((get(k, cdb)) == value(string("CCC")));
return true;
}
};
bool testGetPerf() {
const value k = mklist<value>("c");
TinyCDB cdb("tmp/test.cdb");
assert(hasContent(post(k, string("CCC"), cdb)));
const lambda<bool()> gl = getLoop(k, cdb);
cout << "TinyCDB get test " << time(gl, 5, 100000) << " ms" << endl;
return true;
}
}
}
int main() {
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::tinycdb::testTinyCDB();
tuscany::tinycdb::testGetPerf();
tuscany::cout << "OK" << tuscany::endl;
return 0;
}

View file

@ -0,0 +1,460 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
#ifndef tuscany_tinycdb_hpp
#define tuscany_tinycdb_hpp
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <cdb.h>
#include "string.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "../../modules/scheme/eval.hpp"
namespace tuscany {
namespace tinycdb {
/**
* A reallocatable buffer.
*/
class buffer {
public:
operator void*() const throw() {
return buf;
}
operator unsigned char*() const throw() {
return (unsigned char*)buf;
}
operator char*() const throw() {
return (char*)buf;
}
private:
buffer(const unsigned int size, void* buf) : size(size), buf(buf) {
}
unsigned int size;
void* buf;
friend const buffer mkbuffer(const unsigned int sz);
friend const buffer mkbuffer(const buffer& b, const unsigned int newsz);
friend const bool free(const buffer& b);
};
/**
* Make a new buffer.
*/
const buffer mkbuffer(const unsigned int sz) {
return buffer(sz, malloc(sz));
}
/**
* Make a new buffer by reallocating an existing one.
*/
const buffer mkbuffer(const buffer& b, const unsigned int sz) {
if (sz <= b.size)
return b;
return buffer(sz, realloc(b.buf, sz));
}
/**
* Free a buffer.
*/
const bool free(const buffer&b) {
::free(b.buf);
return true;
}
/**
* Represents a TinyCDB connection.
*/
class TinyCDB {
public:
TinyCDB() : owner(false), fd(-1) {
st.st_ino = 0;
}
TinyCDB(const string& name) : owner(true), name(name), fd(-1) {
st.st_ino = 0;
}
TinyCDB(const TinyCDB& c) : owner(false), name(c.name), fd(c.fd) {
st.st_ino = c.st.st_ino;
}
~TinyCDB() {
if (!owner)
return;
if (fd == -1)
return;
close(fd);
}
private:
bool owner;
string name;
int fd;
struct stat st;
friend const string dbname(const TinyCDB& cdb);
friend const failable<int> cdbopen(TinyCDB& cdb);
friend const failable<bool> cdbclose(TinyCDB& cdb);
};
/**
* Return the name of the database.
*/
const string dbname(const TinyCDB& cdb) {
return cdb.name;
}
/**
* Open a database.
*/
const failable<int> cdbopen(TinyCDB& cdb) {
// Get database file serial number
struct stat st;
const int s = stat(c_str(cdb.name), &st);
if (s == -1)
return mkfailure<int>(string("Couldn't tinycdb read database stat ") + cdb.name);
// Open database for the first time
if (cdb.fd == -1) {
cdb.fd = open(c_str(cdb.name), O_RDONLY);
if (cdb.fd == -1)
return mkfailure<int>(string("Couldn't open tinycdb database file ") + cdb.name);
debug(cdb.fd, "tinycdb::open::fd");
cdb.st = st;
return cdb.fd;
}
// Close and reopen database after a change
if (st.st_ino != cdb.st.st_ino) {
// Close current fd
close(cdb.fd);
// Reopen database
const int newfd = open(c_str(cdb.name), O_RDONLY);
if (newfd == -1)
return mkfailure<int>(string("Couldn't open tinycdb database file ") + cdb.name);
if (newfd == cdb.fd) {
debug(cdb.fd, "tinycdb::open::fd");
cdb.st = st;
return cdb.fd;
}
// We got a different fd, dup it to the current fd then close it
if (fcntl(newfd, F_DUPFD, cdb.fd) == -1)
return mkfailure<int>(string("Couldn't dup tinycdb database file handle ") + cdb.name);
close(newfd);
debug(cdb.fd, "tinycdb::open::fd");
cdb.st = st;
return cdb.fd;
}
// No change, just return the current fd
return cdb.fd;
}
/**
* Close a database.
*/
const failable<bool> cdbclose(TinyCDB& cdb) {
close(cdb.fd);
cdb.fd = -1;
return true;
}
/**
* Rewrite a database. The given update function is passed each entry, and
* can return true to let the entry added to the new db, false to skip the
* entry, or a failure.
*/
const failable<bool> rewrite(const lambda<failable<bool>(buffer& buf, const unsigned int klen, const unsigned int vlen)>& update, const lambda<failable<bool>(struct cdb_make&)>& finish, buffer& buf, const int tmpfd, TinyCDB& cdb) {
// Initialize new db structure
struct cdb_make cdbm;
cdb_make_start(&cdbm, tmpfd);
// Open existing db
failable<int> ffd = cdbopen(cdb);
if (!hasContent(ffd))
return mkfailure<bool>(reason(ffd));
const int fd = content(ffd);
// Read the db header
unsigned int pos = 0;
if (lseek(fd, 0, SEEK_SET) != 0)
return mkfailure<bool>("Could not seek to tinycdb database start");
if (::read(fd, buf, 2048) != 2048)
return mkfailure<bool>("Could not read tinycdb database header");
pos += 2048;
unsigned int eod = cdb_unpack(buf);
debug(pos, "tinycdb::rewrite::eod");
// Read and add the existing entries
while(pos < eod) {
if (eod - pos < 8)
return mkfailure<bool>("Invalid tinycdb database format, couldn't read entry header");
if (::read(fd, buf, 8) != 8)
return mkfailure<bool>("Couldn't read tinycdb entry header");
pos += 8;
unsigned int klen = cdb_unpack(buf);
unsigned int vlen = cdb_unpack(((unsigned char*)buf) + 4);
unsigned int elen = klen + vlen;
// Read existing entry
buf = mkbuffer(buf, elen);
if (eod - pos < elen)
return mkfailure<bool>("Invalid tinycdb database format, couldn't read entry");
if ((unsigned int)::read(fd, buf, elen) != elen)
return mkfailure<bool>("Couldn't read tinycdb entry");
pos += elen;
// Apply the update function to the entry
debug(string((char*)buf, klen), "tinycdb::rewrite::existing key");
debug(string(((char*)buf) + klen, vlen), "tinycdb::rewrite::existing value");
const failable<bool> u = update(buf, klen, vlen);
if (!hasContent(u))
return u;
// Skip the entry if the update function returned false
if (u == false)
continue;
// Add the entry to the new db
if (cdb_make_add(&cdbm, buf, klen, ((unsigned char*)buf)+klen, vlen) == -1)
return mkfailure<bool>("Could not add tinycdb entry");
}
if (pos != eod)
return mkfailure<bool>("Invalid tinycdb database format");
// Call the finish function
const failable<bool> f = finish(cdbm);
if (!hasContent(f))
return f;
// Save the new db
if (cdb_make_finish(&cdbm) == -1)
return mkfailure<bool>("Could not save tinycdb database");
return true;
}
const failable<bool> rewrite(const lambda<failable<bool>(buffer& buf, const unsigned int klen, const unsigned int vlen)>& update, const lambda<failable<bool>(struct cdb_make&)>& finish, TinyCDB& cdb) {
// Create a new temporary db file
string tmpname = dbname(cdb) + ".XXXXXX";
int tmpfd = mkstemp(const_cast<char*>(c_str(tmpname)));
if (tmpfd == -1)
return mkfailure<bool>("Could not create temporary tinycdb database");
// Rewrite the db, apply the update function to each entry
buffer buf = mkbuffer(2048);
const failable<bool> r = rewrite(update, finish, buf, tmpfd, cdb);
if (!hasContent(r)) {
close(tmpfd);
free(buf);
return r;
}
// Atomically replace the db and reopen it in read mode
if (rename(c_str(tmpname), c_str(dbname(cdb))) == -1)
return mkfailure<bool>("Could not rename temporary tinycdb database");
cdbclose(cdb);
failable<int> ffd = cdbopen(cdb);
if (!hasContent(ffd))
return mkfailure<bool>(reason(ffd));
return true;
}
/**
* Post a new item to the database.
*/
struct postUpdate {
const string ks;
postUpdate(const string& ks) : ks(ks) {
}
const failable<bool> operator()(buffer& buf, const unsigned int klen, unused const unsigned int vlen) const {
if (ks == string((char*)buf, klen))
return mkfailure<bool>("Key already exists in tinycdb database");
return true;
}
};
struct postFinish {
const string ks;
const string vs;
postFinish(const string& ks, const string& vs) : ks(ks), vs(vs) {
}
const failable<bool> operator()(struct cdb_make& cdbm) const {
if (cdb_make_add(&cdbm, c_str(ks), (unsigned int)length(ks), c_str(vs), (unsigned int)length(vs)) == -1)
return mkfailure<bool>("Could not add tinycdb entry");
return true;
}
};
const failable<bool> post(const value& key, const value& val, TinyCDB& cdb) {
debug(key, "tinycdb::post::key");
debug(val, "tinycdb::post::value");
debug(dbname(cdb), "tinycdb::post::dbname");
const string ks(scheme::writeValue(key));
const string vs(scheme::writeValue(val));
// Process each entry and detect existing key
const lambda<failable<bool>(buffer& buf, const unsigned int klen, const unsigned int vlen)> update = postUpdate(ks);
// Add the new entry to the db
const lambda<failable<bool>(struct cdb_make& cdbm)> finish = postFinish(ks, vs);
// Rewrite the db
const failable<bool> r = rewrite(update, finish, cdb);
debug(r, "tinycdb::post::result");
return r;
}
/**
* Update an item in the database. If the item doesn't exist it is added.
*/
struct putUpdate {
const string ks;
putUpdate(const string& ks) : ks(ks) {
}
const failable<bool> operator()(buffer& buf, const unsigned int klen, unused const unsigned int vlen) const {
if (ks == string((char*)buf, klen))
return false;
return true;
}
};
struct putFinish {
const string ks;
const string vs;
putFinish(const string& ks, const string& vs) : ks(ks), vs(vs) {
}
const failable<bool> operator()(struct cdb_make& cdbm) const {
if (cdb_make_add(&cdbm, c_str(ks), (unsigned int)length(ks), c_str(vs), (unsigned int)length(vs)) == -1)
return mkfailure<bool>("Could not add tinycdb entry");
return true;
}
};
const failable<bool> put(const value& key, const value& val, TinyCDB& cdb) {
debug(key, "tinycdb::put::key");
debug(val, "tinycdb::put::value");
debug(dbname(cdb), "tinycdb::put::dbname");
const string ks(scheme::writeValue(key));
const string vs(scheme::writeValue(val));
// Process each entry and skip existing key
const lambda<failable<bool>(buffer& buf, const unsigned int klen, const unsigned int vlen)> update = putUpdate(ks);
// Add the new entry to the db
const lambda<failable<bool>(struct cdb_make& cdbm)> finish = putFinish(ks, vs);
// Rewrite the db
const failable<bool> r = rewrite(update, finish, cdb);
debug(r, "tinycdb::put::result");
return r;
}
/**
* Get an item from the database.
*/
const failable<value> get(const value& key, TinyCDB& cdb) {
debug(key, "tinycdb::get::key");
debug(dbname(cdb), "tinycdb::get::dbname");
const failable<int> ffd = cdbopen(cdb);
if (!hasContent(ffd))
return mkfailure<value>(reason(ffd));
const int fd = content(ffd);
const string ks(scheme::writeValue(key));
cdbi_t vlen;
if (cdb_seek(fd, c_str(ks), (unsigned int)length(ks), &vlen) <= 0)
return mkfailure<value>("Could not get tinycdb entry");
char* data = gc_cnew(vlen + 1);
cdb_bread(fd, data, vlen);
data[vlen] = '\0';
const value val(scheme::readValue(string(data)));
debug(val, "tinycdb::get::result");
return val;
}
/**
* Delete an item from the database
*/
struct delUpdate {
const string ks;
delUpdate(const string& ks) : ks(ks) {
}
const failable<bool> operator()(buffer& buf, const unsigned int klen, unused const unsigned int vlen) const {
if (ks == string((char*)buf, klen))
return false;
return true;
}
};
struct delFinish {
delFinish() {
}
const failable<bool> operator()(unused struct cdb_make& cdbm) const {
return true;
}
};
const failable<bool> del(const value& key, TinyCDB& cdb) {
debug(key, "tinycdb::delete::key");
debug(dbname(cdb), "tinycdb::delete::dbname");
const string ks(scheme::writeValue(key));
// Process each entry and skip existing key
const lambda<failable<bool>(buffer& buf, const unsigned int klen, const unsigned int vlen)> update = delUpdate(ks);
// Nothing to do to finish
const lambda<failable<bool>(struct cdb_make& cdbm)> finish = delFinish();
// Rewrite the db
const failable<bool> r = rewrite(update, finish, cdb);
debug(r, "tinycdb::delete::result");
return r;
}
}
}
#endif /* tuscany_tinycdb_hpp */

View file

@ -0,0 +1,57 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
if WANT_QUEUE
INCLUDES = -I${QPIDC_INCLUDE}
incl_HEADERS = *.hpp
incldir = $(prefix)/include/components/queue
dist_comp_SCRIPTS = qpidd-start qpidd-stop
compdir=$(prefix)/components/queue
comp_DATA = qpidc.prefix
qpidc.prefix: $(top_builddir)/config.status
echo ${QPIDC_PREFIX} >qpidc.prefix
EXTRA_DIST = queue.composite queue-sender.componentType queue-listener.componentType *.scm
comp_LTLIBRARIES = libqueue-sender.la libqueue-listener.la
noinst_DATA = libqueue-sender.so libqueue-listener.so
libqueue_sender_la_SOURCES = queue-sender.cpp
libqueue_sender_la_LDFLAGS = -L${QPIDC_LIB} -R${QPIDC_LIB} -lqpidclient -lqpidcommon
libqueue-sender.so:
ln -s .libs/libqueue-sender.so
libqueue_listener_la_SOURCES = queue-listener.cpp
libqueue_listener_la_LDFLAGS = -L${QPIDC_LIB} -R${QPIDC_LIB} -lqpidclient -lqpidcommon
libqueue-listener.so:
ln -s .libs/libqueue-listener.so
qpid_test_SOURCES = qpid-test.cpp
qpid_test_LDFLAGS = -L${QPIDC_LIB} -R${QPIDC_LIB} -lqpidclient -lqpidcommon
client_test_SOURCES = client-test.cpp
client_test_LDFLAGS = -lxml2 -lcurl -lmozjs -L${QPIDC_LIB} -R${QPIDC_LIB} -lqpidclient -lqpidcommon
dist_noinst_SCRIPTS = send-test server-test
noinst_PROGRAMS = qpid-test client-test
TESTS = send-test server-test
endif

View file

@ -0,0 +1,99 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
/**
* Test queue component.
*/
#include <assert.h>
#include "stream.hpp"
#include "string.hpp"
#include "list.hpp"
#include "element.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "perf.hpp"
#include "../../modules/http/http.hpp"
#include "qpid.hpp"
// Ignore conversion issues and redundant declarations in Qpid headers
#ifdef WANT_MAINTAINER_MODE
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wredundant-decls"
#endif
namespace tuscany {
namespace queue {
const value key(mklist<value>(string("report")));
const string qname("reportq");
const list<value> item = list<value>()
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$2.99"));
const list<value> entry = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), item);
bool testDeclareQueue() {
QpidConnection qc;
QpidSession qs(qc);
const failable<bool> r = declareQueue(key, qname, qs);
assert(hasContent(r));
return true;
}
const bool listener(const value& k, const value& v) {
cerr << "k " << k << " v " << v << endl;
assert(k == key);
assert(v == entry);
return false;
}
bool testListen() {
QpidConnection qc;
QpidSession qs(qc);
QpidSubscription qsub(qs);
const lambda<bool(const value&, const value&)> l(listener);
listen(qname, l, qsub);
return true;
}
bool testPost() {
gc_scoped_pool pool;
http::CURLSession ch("", "", "");
const failable<value> id = http::post(entry, "http://localhost:8090/print-sender", ch);
assert(hasContent(id));
return true;
}
}
}
int main() {
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::queue::testDeclareQueue();
tuscany::queue::testPost();
tuscany::queue::testListen();
tuscany::cout << "OK" << tuscany::endl;
return 0;
}

View file

@ -0,0 +1,97 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
/**
* Test Qpid support functions.
*/
#include <assert.h>
#include "stream.hpp"
#include "string.hpp"
#include "list.hpp"
#include "element.hpp"
#include "monad.hpp"
#include "value.hpp"
#include "perf.hpp"
#include "qpid.hpp"
// Ignore conversion issues and redundant declarations in Qpid headers
#ifdef WANT_MAINTAINER_MODE
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wredundant-decls"
#endif
namespace tuscany {
namespace queue {
const value key(mklist<value>("test"));
const string qname("testq");
bool testDeclareQueue() {
QpidConnection qc;
QpidSession qs(qc);
const failable<bool> r = declareQueue(key, qname, qs);
assert(hasContent(r));
return true;
}
const list<value> item = list<value>()
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$2.99"));
const list<value> entry = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), item);
bool testPost() {
QpidConnection qc;
QpidSession qs(qc);
const failable<bool> r = post(key, entry, qs);
assert(hasContent(r));
return true;
}
const bool listener(const value& k, const value& v) {
assert(k == key);
assert(v == entry);
return false;
}
bool testListen() {
QpidConnection qc;
QpidSession qs(qc);
QpidSubscription qsub(qs);
const lambda<bool(const value&, const value&)> l(listener);
listen(qname, l, qsub);
return true;
}
}
}
int main() {
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::queue::testDeclareQueue();
tuscany::queue::testPost();
tuscany::queue::testListen();
tuscany::cout << "OK" << tuscany::endl;
return 0;
}

View file

@ -0,0 +1,260 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
#ifndef tuscany_qpid_hpp
#define tuscany_qpid_hpp
/**
* AMQP queue access functions.
*/
// Ignore conversion issues and redundant declarations in Qpid headers
#ifdef WANT_MAINTAINER_MODE
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wredundant-decls"
#endif
#include <qpid/client/Connection.h>
#include <qpid/client/Session.h>
#include <qpid/client/MessageListener.h>
#include <qpid/client/SubscriptionManager.h>
#include "string.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "../../modules/scheme/eval.hpp"
namespace tuscany {
namespace queue {
/**
* Represents a Qpid connection.
*/
class QpidConnection {
public:
QpidConnection() : owner(true) {
c.open("localhost", 5672);
}
QpidConnection(const bool owner) : owner(owner) {
c.open("localhost", 5672);
}
QpidConnection(const QpidConnection& qc) : owner(false), c(qc.c) {
}
~QpidConnection() {
if (!owner)
return;
c.close();
}
private:
friend const failable<bool> close(QpidConnection& qc);
friend class QpidSession;
const bool owner;
qpid::client::Connection c;
};
/**
* Close a Qpid connection.
*/
const failable<bool> close(QpidConnection& qc) {
qc.c.close();
return true;
}
/**
* Represents a Qpid session.
*/
class QpidSession {
public:
QpidSession(QpidConnection& qc) : owner(true), s(qc.c.newSession()) {
}
QpidSession(QpidConnection& qc, const bool owner) : owner(owner), s(qc.c.newSession()) {
}
QpidSession(const QpidSession& qs) : owner(false), s(qs.s) {
}
~QpidSession() {
if (!owner)
return;
s.close();
}
private:
friend const failable<bool> close(QpidSession& qs);
friend const failable<bool> declareQueue(const value& key, const string& name, QpidSession& qs);
friend const failable<bool> post(const value& key, const value& val, QpidSession& qs);
friend class QpidSubscription;
const bool owner;
qpid::client::Session s;
};
/**
* Close a Qpid session.
*/
const failable<bool> close(QpidSession& qs) {
try {
qs.s.close();
} catch (const qpid::Exception& e) {
return mkfailure<bool>(string("Qpid failure: ") + e.what());
}
return true;
}
/**
* Declare a key / AMQP queue pair.
*/
const failable<bool> declareQueue(const value& key, const string& name, QpidSession& qs) {
const string ks(scheme::writeValue(key));
try {
qs.s.queueDeclare(qpid::client::arg::queue=c_str(name));
qs.s.exchangeBind(qpid::client::arg::exchange="amq.direct", qpid::client::arg::queue=c_str(name), qpid::client::arg::bindingKey=c_str(ks));
} catch (const qpid::Exception& e) {
return mkfailure<bool>(string("Qpid failure: ") + e.what());
}
return true;
}
/**
* Post a key / value pair message to an AMQP broker.
*/
const failable<bool> post(const value& key, const value& val, QpidSession& qs) {
// Send in a message with the given key.
const string ks(scheme::writeValue(key));
const string vs(scheme::writeValue(val));
try {
qpid::client::Message message;
message.getDeliveryProperties().setRoutingKey(c_str(ks));
message.setData(c_str(vs));
qs.s.messageTransfer(qpid::client::arg::content=message, qpid::client::arg::destination="amq.direct");
} catch (const qpid::Exception& e) {
return mkfailure<bool>(string("Qpid failure: ") + e.what());
}
return true;
}
/**
* Represents a Qpid subscription.
*/
class QpidSubscription {
public:
QpidSubscription(QpidSession& qs) : owner(true), subs(qs.s) {
}
QpidSubscription(QpidSession& qs, const bool owner) : owner(owner), subs(qs.s) {
}
QpidSubscription(const QpidSubscription& qsub) : owner(false), subs(qsub.subs) {
}
~QpidSubscription() {
if (!owner)
return;
try {
subs.stop();
} catch (const qpid::Exception& e) {
mkfailure<bool>(string("Qpid failure: ") + e.what());
}
}
private:
friend const failable<bool> listen(const string& name, const lambda<bool(const value&, const value&)>& l, QpidSubscription& qsub);
friend const failable<bool> stop(QpidSubscription& qsub);
const bool owner;
qpid::client::SubscriptionManager subs;
};
/**
* Register a listener function with an AMQP queue.
*/
class Listener : public qpid::client::MessageListener {
public:
Listener(const lambda<bool(const value&, const value&)> l, qpid::client::SubscriptionManager& subs) : l(l), subs(subs) {
}
virtual void received(qpid::client::Message& msg) {
// Call the listener function
const value k(scheme::readValue(msg.getDeliveryProperties().getRoutingKey().c_str()));
const value v(scheme::readValue(msg.getData().c_str()));
const bool r = l(k, v);
if (!r) {
try {
subs.cancel(msg.getDestination());
} catch (const qpid::Exception& e) {
mkfailure<bool>(string("Qpid failure: ") + e.what());
}
}
}
private:
const lambda<bool(const value&, const value&)> l;
qpid::client::SubscriptionManager& subs;
};
const failable<bool> listen(const string& name, const lambda<bool(const value&, const value&)>& l, QpidSubscription& qsub) {
debug("queue::listen");
Listener listener(l, qsub.subs);
try {
qsub.subs.subscribe(listener, c_str(name));
qsub.subs.run();
} catch (const qpid::Exception& e) {
return mkfailure<bool>(string("Qpid failure: ") + e.what());
}
debug("queue::listen::stopped");
return true;
}
/**
* Stop an AMQP subscription.
*/
const failable<bool> stop(QpidSubscription& qsub) {
debug("queue::stop");
try {
qsub.subs.stop();
} catch (const qpid::Exception& e) {
return mkfailure<bool>(string("Qpid failure: ") + e.what());
}
debug("queue::stopped");
return true;
}
}
}
// Re-enable conversion and redundant declarations warnings
#ifdef WANT_MAINTAINER_MODE
#pragma GCC diagnostic warning "-Wconversion"
#pragma GCC diagnostic warning "-Wredundant-decls"
#endif
#endif /* tuscany_qpid_hpp */

View file

@ -0,0 +1,24 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Start qpidd
here=`readlink -f $0`; here=`dirname $here`
qpid_prefix=`cat $here/qpidc.prefix`
$qpid_prefix/sbin/qpidd &

View file

@ -0,0 +1,26 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Stop qpidd
here=`readlink -f $0`; here=`dirname $here`
qpid_prefix=`cat $here/qpidc.prefix`
qpidd="$qpid_prefix/sbin/qpidd"
kill `ps -ef | grep -v grep | grep "${qpidd}" | awk '{ print $2 }'`

View file

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
-->
<componentType xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
targetNamespace="http://tuscany.apache.org/xmlns/sca/components">
<reference name="relay"/>
<property name="key" type="xsd:string"/>
<property name="queue" type="xsd:string"/>
</composite>

View file

@ -0,0 +1,158 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
/**
* AMQP queue listener component implementation.
*/
#include "string.hpp"
#include "function.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "parallel.hpp"
#include "qpid.hpp"
// Ignore conversion issues and redundant declarations in Qpid headers
#ifdef WANT_MAINTAINER_MODE
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wredundant-decls"
#endif
namespace tuscany {
namespace queue {
/**
* A relay function that posts the AMQP messages it receives to a relay component reference.
*/
class relay {
public:
relay(const lambda<value(const list<value>&)>& rel) : rel(rel) {
}
const bool operator()(const value& k, const value& v) const {
debug(k, "queue::relay::key");
debug(v, "queue::relay::value");
const value res = rel(mklist<value>("post", isList(k)? (list<value>)k : mklist<value>(k), v));
return true;
}
private:
const lambda<value(const list<value>&)> rel;
};
/**
* Subscribe and listen to an AMQP queue.
*/
class subscribe {
public:
subscribe(const string& qname, const lambda<bool(const value&, const value&)>& l, const QpidSubscription& qsub) : qname(qname), l(l), qsub(qsub) {
}
const failable<bool> operator()() const {
gc_pool pool;
debug(qname, "queue::subscribe::listen");
const failable<bool> r = listen(qname, l, const_cast<QpidSubscription&>(qsub));
debug(qname, "queue::subscribe::stopped");
return r;
}
private:
const string qname;
const lambda<bool(const value&, const value&)> l;
const QpidSubscription qsub;
};
/**
* Listener lambda function, responsible for starting an AMQP subscription in a worker thread, and
* apply any function calls to the listener component. The only supported function is stop(),
* called to stop the listener component and shutdown the worker thread.
*/
class listener {
public:
listener(QpidConnection& qc, QpidSession& qs, QpidSubscription& qsub, worker& w) : qc(qc), qs(qs), qsub(qsub), w(w) {
}
const value operator()(const list<value>& params) const {
const tuscany::value func(car(params));
// Stop the component
if (func != "stop")
return tuscany::mkfailure<tuscany::value>();
debug("queue::listener::stop");
// TODO check why stop() and close() hang in child processes
stop(const_cast<QpidSubscription&>(qsub));
close(const_cast<QpidSession&>(qs));
close(const_cast<QpidConnection&>(qc));
cancel(const_cast<worker&>(w));
debug("queue::listener::stopped");
return failable<value>(value(lambda<value(const list<value>&)>()));
}
private:
QpidConnection qc;
QpidSession qs;
QpidSubscription qsub;
worker w;
};
/**
* Start the component.
*/
const failable<value> start(const list<value>& params) {
// Extract the relay reference and the AMQP key and queue name
const value rel = car(params);
const value pk = ((lambda<value(list<value>)>)cadr(params))(list<value>());
const value key = isList(pk)? (list<value>)pk : mklist<value>(pk);
const value qname = ((lambda<value(list<value>)>)caddr(params))(list<value>());
// Create an AMQP session
QpidConnection qc(false);
QpidSession qs(qc, false);
// Declare the configured AMQP key / queue pair
declareQueue(key, qname, qs);
// Listen and relay messages in a worker thread
QpidSubscription qsub(qs, false);
worker w(3);
const lambda<bool(const value&, const value&)> rl = relay(rel);
submit<failable<bool> >(w, lambda<failable<bool>()>(subscribe(qname, rl, qsub)));
// Return the listener component lambda function
return value(lambda<value(const list<value>&)>(listener(qc, qs, qsub, w)));
}
}
}
extern "C" {
const tuscany::value apply(const tuscany::list<tuscany::value>& params) {
const tuscany::value func(car(params));
if (func == "start")
return tuscany::queue::start(cdr(params));
return tuscany::mkfailure<tuscany::value>();
}
}

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
-->
<componentType xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
targetNamespace="http://tuscany.apache.org/xmlns/sca/components">
<service name="sender"/>
<property name="key" type="xsd:string"/>
</composite>

View file

@ -0,0 +1,72 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
/**
* AMQP queue sender component implementation.
*/
#include "string.hpp"
#include "function.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "qpid.hpp"
// Ignore conversion issues and redundant declarations in Qpid headers
#ifdef WANT_MAINTAINER_MODE
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wredundant-decls"
#endif
namespace tuscany {
namespace queue {
/**
* Post an item to a queue.
*/
const failable<value> post(const list<value>& params) {
QpidConnection qc;
QpidSession qs(qc);
// Post the item
const value pk = ((lambda<value(list<value>)>)caddr(params))(list<value>());
const value key = isList(pk)? append<value>(pk, (list<value>)car(params)) : cons<value>(pk, (list<value>)car(params));
debug(key, "queue::post::key");
debug(cadr(params), "queue::post::value");
const failable<bool> r = post(key, cadr(params), qs);
if (!hasContent(r))
return mkfailure<value>(reason(r));
return key;
}
}
}
extern "C" {
const tuscany::value apply(const tuscany::list<tuscany::value>& params) {
const tuscany::value func(car(params));
if (func == "post")
return tuscany::queue::post(cdr(params));
return tuscany::mkfailure<tuscany::value>();
}
}

View file

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
-->
<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
targetNamespace="http://tuscany.apache.org/xmlns/sca/components"
name="queue">
<component name="print-sender">
<implementation.cpp path="." library="libqueue-sender"/>
<property name="key">print</property>
<service name="print-sender">
<t:binding.http uri="print-sender"/>
</service>
</component>
<component name="print-listener">
<implementation.cpp path="." library="libqueue-listener"/>
<property name="key">print</property>
<property name="queue">printq</property>
<reference name="relay" target="print"/>
</component>
<component name="print">
<t:implementation.scheme script="server-test.scm"/>
<service name="print">
<t:binding.http uri="print"/>
</service>
<reference name="report" target="report-sender"/>
</component>
<component name="report-sender">
<implementation.cpp path="." library="libqueue-sender"/>
<property name="key">report</property>
<service name="report-sender">
<t:binding.http uri="report-sender"/>
</service>
</component>
</composite>

View file

@ -0,0 +1,31 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Setup
./qpidd-start
sleep 1
# Test
./qpid-test 2>/dev/null
rc=$?
# Cleanup
./qpidd-stop
sleep 1
return $rc

View file

@ -0,0 +1,43 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Setup
../../modules/http/httpd-conf tmp localhost 8090 ../../modules/http/htdocs
../../modules/server/server-conf tmp
../../modules/server/scheme-conf tmp
cat >>tmp/conf/httpd.conf <<EOF
SCAContribution `pwd`/
SCAComposite queue.composite
EOF
./qpidd-start
sleep 1
../../modules/http/httpd-start tmp
sleep 2
# Test
./client-test 2>/dev/null
rc=$?
# Cleanup
../../modules/http/httpd-stop tmp
sleep 1
./qpidd-stop
sleep 1
return $rc

View file

@ -0,0 +1,20 @@
; Licensed to the Apache Software Foundation (ASF) under one
; or more contributor license agreements. See the NOTICE file
; distributed with this work for additional information
; regarding copyright ownership. The ASF licenses this file
; to you under the Apache License, Version 2.0 (the
; "License"); you may not use this file except in compliance
; with the License. You may obtain a copy of the License at
;
; http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing,
; software distributed under the License is distributed on an
; "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
; KIND, either express or implied. See the License for the
; specific language governing permissions and limitations
; under the License.
; Queue test case
(define (post key val report) (report "post" '() val))

Some files were not shown because too many files have changed in this diff Show more