diff options
-rw-r--r-- | sca-cpp/trunk/INSTALL | 12 | ||||
-rw-r--r-- | sca-cpp/trunk/README | 2 | ||||
-rw-r--r-- | sca-cpp/trunk/samples/loan-python/Makefile.am | 28 | ||||
-rw-r--r-- | sca-cpp/trunk/samples/loan-python/htdocs/index.html | 160 | ||||
-rw-r--r-- | sca-cpp/trunk/samples/loan-python/loan-approval.py | 77 | ||||
-rw-r--r-- | sca-cpp/trunk/samples/loan-python/loan.composite | 45 | ||||
-rw-r--r-- | sca-cpp/trunk/samples/loan-python/loan.py | 45 | ||||
-rwxr-xr-x | sca-cpp/trunk/samples/loan-python/server-test | 58 | ||||
-rwxr-xr-x | sca-cpp/trunk/samples/loan-python/start | 32 | ||||
-rwxr-xr-x | sca-cpp/trunk/samples/loan-python/stop | 21 | ||||
-rw-r--r-- | sca-cpp/trunk/samples/loan-python/util.py | 145 |
11 files changed, 11 insertions, 614 deletions
diff --git a/sca-cpp/trunk/INSTALL b/sca-cpp/trunk/INSTALL index 93f2b47c79..97cc13e156 100644 --- a/sca-cpp/trunk/INSTALL +++ b/sca-cpp/trunk/INSTALL @@ -89,8 +89,8 @@ XML: libxml2-2.7.7 (http://xmlsoft.org/) CURL: -curl-7-19-5 -libcurl4-openssl-7.19.5 +curl-7-24.0 +libcurl4-openssl-7.24.0 JSON: Mozilla SpiderMonkey libmozjs 1.8.5 and @@ -168,6 +168,12 @@ To enable debugging and strict warning compile options, add: To enable gprof profiling, add: --enable-profiling +To enable memory usage debugging using Electric Fence add: +--enable-efence + +To enable memory usage debugging using mmap add: +--enable-malloc-mmap + 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 @@ -225,7 +231,7 @@ dependencies installed under $build: --with-apr=$build/apr-1.4.x-bin --with-httpd=$build/httpd-2.3.15-bin \ --with-memcached=$build/memcached-1.4.7-bin \ --with-tinycdb=$build/tinycdb-0.77-bin \ ---with-curl=$build/curl-7.19.5-bin --with-libxml2=/usr \ +--with-curl=$build/curl-7.24.0-bin --with-libxml2=/usr \ --with-js-include=$build/js-1.8.5-bin/include \ --with-js-lib=$build/js-1.8.5-bin/lib \ --enable-libcloud \ diff --git a/sca-cpp/trunk/README b/sca-cpp/trunk/README index 92dfde8154..ce13557a1e 100644 --- a/sca-cpp/trunk/README +++ b/sca-cpp/trunk/README @@ -17,6 +17,7 @@ Chat: XMPP chat, using Apache Vysper and Libstrophe; Constdb: fast persistent store for mostly constant data, using TinyCDB; Filedb: key/value persistent store, using plain files; Http: HTTP client, using Libcurl; +Smtp: SMTP client, using Libcurl; Kvdb: fast key/value persistent store, using LevelDB; Log: distributed logger, using Facebook Scribe; Queue: AMQP queuing, using Apache Qpid/C; @@ -82,6 +83,7 @@ Here's a rough guide to the Tuscany SCA source tree: | | |-- kvdb LevelDB key/value persistent store | | |-- log Scribe logger | | |-- queue AMQP message queue + | | |-- smtp SMTP client | | |-- sqldb PostgreSQL database | | |-- webservice Axis2 Web service gateway | | diff --git a/sca-cpp/trunk/samples/loan-python/Makefile.am b/sca-cpp/trunk/samples/loan-python/Makefile.am deleted file mode 100644 index 0d0027ce6b..0000000000 --- a/sca-cpp/trunk/samples/loan-python/Makefile.am +++ /dev/null @@ -1,28 +0,0 @@ -# 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_PYTHON - -dist_sample_SCRIPTS = start stop -sampledir = $(prefix)/samples/loan-python - -nobase_dist_sample_DATA = loan.py loan-approval.py util.py loan.composite htdocs/*.html - -dist_noinst_SCRIPTS = server-test -TESTS = server-test - -endif diff --git a/sca-cpp/trunk/samples/loan-python/htdocs/index.html b/sca-cpp/trunk/samples/loan-python/htdocs/index.html deleted file mode 100644 index 3f607f78f4..0000000000 --- a/sca-cpp/trunk/samples/loan-python/htdocs/index.html +++ /dev/null @@ -1,160 +0,0 @@ -<!--
- * 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.
--->
-<html>
-<head>
-<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/>
-<meta name="apple-mobile-web-app-capable" content="yes"/>
-<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
-<title>Store</title>
-
-<script type="text/javascript" src="/component.js"></script>
-
-<script type="text/javascript">
-var component = new tuscany.sca.Component("Store");
-
-//@Reference
-var catalog = new tuscany.sca.Reference("catalog");
-
-//@Reference
-var shoppingCart = new tuscany.sca.Reference("shoppingCart");
-
-//@Reference
-var shoppingTotal = new tuscany.sca.Reference("shoppingTotal");
-
-var catalogItems;
-
-function catalog_itemsResponse(items, exception) {
- if (exception){
- alert(exception.message);
- return;
- }
- var catalog = "";
- for (var i=0; i<items.length; i++) {
- var item = items[i].name + ' - ' + items[i].price;
- catalog += '<input name="items" type="checkbox" value="' +
- item + '">' + item + ' <br>';
- }
- document.getElementById('catalog').innerHTML=catalog;
- catalogItems = items;
-
-}
-
-function shoppingCart_getResponse(feed) {
- if (feed != null) {
- var entries = feed.getElementsByTagName("entry");
- var list = "";
- for (var i=0; i<entries.length; i++) {
- var content = entries[i].getElementsByTagName("content")[0];
- var name = content.getElementsByTagName("name")[0].firstChild.nodeValue;
- var price = content.getElementsByTagName("price")[0].firstChild.nodeValue;
- list += name + ' - ' + price + ' <br>';
- }
- document.getElementById("shoppingCart").innerHTML = list;
-
- shoppingTotal.apply("total", shoppingTotal_totalResponse);
- }
-}
-
-function shoppingTotal_totalResponse(total, exception) {
- if (exception) {
- alert(exception.message);
- return;
- }
- document.getElementById('total').innerHTML = total;
-}
-
-function shoppingCart_postResponse(entry) {
- shoppingCart.get("", shoppingCart_getResponse);
-}
-
-function addToCart() {
- var items = document.catalogForm.items;
- var j = 0;
- for (var i=0; i<items.length; i++)
- if (items[i].checked) {
- var entry = '<entry xmlns="http://www.w3.org/2005/Atom"><title type="text">Item</title><content type="application/xml">' +
- '<item>' +
- '<name>' + catalogItems[i].name + '</name>' +
- '<currencyCode>' + catalogItems[i].currencyCode + '</currencyCode>' +
- '<currencySymbol>' + catalogItems[i].currencySymbol + '</currencySymbol>' +
- '<price>' + catalogItems[i].price + '</price>' +
- '</item>' +
- '</content></entry>';
- shoppingCart.post(entry, shoppingCart_postResponse);
- items[i].checked = false;
- }
-}
-function checkoutCart() {
- document.getElementById('store').innerHTML='<h2>' +
- 'Thanks for Shopping With Us!</h2>'+
- '<h2>Your Order</h2>'+
- '<form name="orderForm">'+
- document.getElementById('shoppingCart').innerHTML+
- '<br>'+
- document.getElementById('total').innerHTML+
- '<br>'+
- '<br>'+
- '<input type="submit" value="Continue Shopping">'+
- '</form>';
- shoppingCart.del("", null);
-}
-function deleteCart() {
- shoppingCart.del("", null);
- document.getElementById('shoppingCart').innerHTML = "";
- document.getElementById('total').innerHTML = "";
-}
-
-function init() {
- try {
- catalog.apply("items", catalog_itemsResponse);
- shoppingCart.get("", shoppingCart_getResponse);
- } catch(e){
- alert(e);
- }
-}
-</script>
-</head>
-
-<body onload="init()">
-<h1>Store</h1>
-<br/>
-<div id="store">
-<h2>Catalog</h2>
-<form name="catalogForm">
-<div id="catalog" ></div>
-<br>
-<input type="button" onClick="addToCart()" value="Add to Cart">
-</form>
-<br>
-
-<h2>Your Shopping Cart</h2>
-<form name="shoppingCartForm">
-<div id="shoppingCart"></div>
-<br>
-<div id="total"></div>
-<br>
-<input type="button" onClick="checkoutCart()" value="Checkout">
-<input type="button" onClick="deleteCart()" value="Empty">
-<a href="shoppingCart/">(feed)</a>
-</form>
-</div>
-
-</body>
-</html>
diff --git a/sca-cpp/trunk/samples/loan-python/loan-approval.py b/sca-cpp/trunk/samples/loan-python/loan-approval.py deleted file mode 100644 index 3951f16eeb..0000000000 --- a/sca-cpp/trunk/samples/loan-python/loan-approval.py +++ /dev/null @@ -1,77 +0,0 @@ -# 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. - -# Loan approval service implementation -import uuid -import sys -from util import * -from loan import * - -loansId = ("loans", "1234") - -# Return the list of loans -def loans(cache): - l = cache("get", loansId) - if l is None: - return () - return l - -# Post a new loan request -def post(collection, item, cache): - id = str(uuid.uuid1()) - loans = cons(cons(id, cdr(item)), loans(cache)) - cache("put", loansId, loans) - return (id,) - -# Return the person currently processing a loan request -def processor(l): - if approver(l) is not None: - return approver(l) - return assessor(l) - -# Return a list of loans that match a given criteria -def get(r, cache): - # All the loans - if r == (): - return loans(cache) - # Loans that need approval - if car(r) == "needApproval": - return filter(lambda l: (amount(l) >= 10000 or risk(l) == "high") and approval(l) is None, loans(cache)) - # Loans that need a risk assessment - if car(r) == "needAssessment": - return filter(lambda : amount(l) < 10000 and risk(l) is None, loans(cache)) - # Loans currently under approval - if car(r) == "underApproval": - return filter(lambda l: approver(l) is not None, loans(cache)) - # Loans currently under assessment - if car(r) == "underAssessment": - return filter(lambda l: assessor(l) is not None, loans(cache)) - # Loan requests that are unassigned - if car(r) == "unassigned": - return filter(lambda l: processor(l) is None, loans(cache)) - # Loan requests that are assigned and getting processed - if car(r) == "assigned": - return filter(lambda l: processor(l) == cadr(r), loans(cache)) - # Approved loans - if car(r) == "approved": - return filter(lambda l: approval(l) == true, loans(cache)) - # Denied loans - if car(r) == "denied": - return filter(lambda l: approval(l) == false, loans(cache)) - # A particular loan - return filter(lambda l: id(l) == r, loans(cache)) - diff --git a/sca-cpp/trunk/samples/loan-python/loan.composite b/sca-cpp/trunk/samples/loan-python/loan.composite deleted file mode 100644 index 9052737cf0..0000000000 --- a/sca-cpp/trunk/samples/loan-python/loan.composite +++ /dev/null @@ -1,45 +0,0 @@ -<?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" - targetNamespace="http://store" - name="store"> - - <component name="LoanApprovalUI"> - <implementation.widget/> - <reference name="loanApproval" target="LoanApproval"/> - </component> - - <component name="LoanApproval"> - <implementation.python script="loan-approval.py"/> - <service name="LoanApproval"> - <binding.atom uri="loan-approval"/> - </service> - <reference name="cache" target="Cache"/> - </component> - - <component name="Cache"> - <implementation.cpp path="../../components/cache" library="libmemcache"/> - <service name="Cache"> - <binding.atom uri="cache"/> - </service> - <property name="servers">localhost:11211</property> - </component> - -</composite> diff --git a/sca-cpp/trunk/samples/loan-python/loan.py b/sca-cpp/trunk/samples/loan-python/loan.py deleted file mode 100644 index 9e345cd1f6..0000000000 --- a/sca-cpp/trunk/samples/loan-python/loan.py +++ /dev/null @@ -1,45 +0,0 @@ -# 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. - -from util import * - -# Loan data type - -def firstName(loan): - return assoc("'firstName", loan) - -def lastName(loan): - return assoc("'lastName", loan) - -def ssn(loan): - return assoc("'ssn", loan) - -def amount(loan): - return assoc("'amount", loan) - -def approver(loan): - return assoc("'approver", loan) - -def approval(loan): - return assoc("'approval", loan) - -def assessor(loan): - return assoc("'assessor", loan) - -def risk(loan): - return assoc("'risk", loan) - diff --git a/sca-cpp/trunk/samples/loan-python/server-test b/sca-cpp/trunk/samples/loan-python/server-test deleted file mode 100755 index fb629a6814..0000000000 --- a/sca-cpp/trunk/samples/loan-python/server-test +++ /dev/null @@ -1,58 +0,0 @@ -#!/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..." -here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $here` -curl_prefix=`cat $here/../../modules/http/curl.prefix` - -# Setup -./start -sleep 2 - -# Test HTTP GET -$curl_prefix/bin/curl http://localhost:8090/ 2>/dev/null >tmp/index.html -diff tmp/index.html htdocs/index.html -rc=$? - -# Test Catalog -if [ "$rc" = "0" ]; then - $curl_prefix/bin/curl http://localhost:8090/references/Store/catalog -X POST -H "Content-type: application/json-rpc" --data @../store-cpp/htdocs/test/items-request.txt >tmp/items-result.txt 2>/dev/null - diff tmp/items-result.txt ../store-cpp/htdocs/test/items-result.txt - rc=$? -fi - -# Test Shopping Cart -if [ "$rc" = "0" ]; then - $curl_prefix/bin/curl http://localhost:8090/references/Store/shoppingCart -X POST -H "Content-type: application/atom+xml" --data @../store-cpp/htdocs/test/shopping-cart-entry.xml 2>/dev/null - rc=$? -fi -if [ "$rc" = "0" ]; then - $curl_prefix/bin/curl http://localhost:8090/references/Store/shoppingCart >tmp/shopping-cart-feed.xml 2>/dev/null - grep "3.55" tmp/shopping-cart-feed.xml >/dev/null - rc=$? -fi - -# Cleanup -./stop -sleep 2 - -if [ "$rc" = "0" ]; then - echo "OK" -fi -exit $rc diff --git a/sca-cpp/trunk/samples/loan-python/start b/sca-cpp/trunk/samples/loan-python/start deleted file mode 100755 index d334ebc58f..0000000000 --- a/sca-cpp/trunk/samples/loan-python/start +++ /dev/null @@ -1,32 +0,0 @@ -#!/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. - -../../modules/http/httpd-conf tmp localhost 8090 htdocs -../../modules/http/httpd-event-conf tmp -../../modules/server/server-conf tmp -../../modules/python/python-conf tmp -cat >>tmp/conf/httpd.conf <<EOF -# Configure SCA Composite -SCAContribution `pwd`/ -SCAComposite loan.composite - -EOF - -../../components/cache/memcached-start tmp -../../modules/http/httpd-start tmp diff --git a/sca-cpp/trunk/samples/loan-python/stop b/sca-cpp/trunk/samples/loan-python/stop deleted file mode 100755 index 3b4c74a587..0000000000 --- a/sca-cpp/trunk/samples/loan-python/stop +++ /dev/null @@ -1,21 +0,0 @@ -#!/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. - -../../modules/http/httpd-stop tmp -../../components/cache/memcached-stop tmp diff --git a/sca-cpp/trunk/samples/loan-python/util.py b/sca-cpp/trunk/samples/loan-python/util.py deleted file mode 100644 index 560101e32d..0000000000 --- a/sca-cpp/trunk/samples/loan-python/util.py +++ /dev/null @@ -1,145 +0,0 @@ -# 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. - -# Simple utility functions -from sys import maxint - -# Scheme-like lists -def cons(a, b): - return (a,) + b - -def car(l): - return l[0] - -def first(l): - return car(l) - -def cdr(l): - return l[1:] - -def rest(l): - return cdr(l) - -def cadr(l): - return car(cdr(l)) - -def cddr(l): - return cdr(cdr(l)) - -def caddr(l): - return car(cddr(l)) - -def append(a, b): - return a + b - -def reverse(l): - r = list(l) - r.reverse() - return tuple(r) - -def isNil(l): - if isinstance(l, streampair): - return l.isNil() - return l == () - -def isSymbol(v): - return isinstance(v, basestring) and v[0:1] == "'" - -def isList(v): - if getattr(v, '__iter__', False) == False: - return False - if isinstance(v, basestring) or isinstance(v, dict): - return False - return True - -def isTaggedList(v, t): - return isList(v) and not isNil(v) and car(v) == t - - -# Scheme-like streams -class streampair(object): - def __init__(self, car, cdr): - self.car = car - self.cdr = cdr - - def __repr__(self): - return repr(self[0:len(self)]) - - def isNil(self): - return self.cdr == () - - def __len__(self): - if self.cdr == (): - return 0 - return 1 + len(self.cdr()) - - def __getitem__(self, i): - if i == 0: - return self.car - return self.cdr()[i - 1] - - def __getslice__(self, i, j): - if isNil(self): - return () - if i > 0: - if j == maxint: - return self.cdr()[i - 1: j] - return self.cdr()[i - 1: j - 1] - if j == maxint: - return self - if j == 0: - return (self.car,) - return (self.car,) + self.cdr()[: j - 1] - - def __eq__(self, other): - sl = len(self) - ol = len(other) - if sl != ol: - return False - return self[0: sl] == other[0: ol] - - def __ne__(self, other): - return not self.__eq__(other) - -def cons_stream(car, cdr): - return streampair(car, cdr) - - -# Scheme-like associations -def assoc(k, l): - if l == (): - return None - - if k == car(car(l)): - return car(l) - return assoc(k, cdr(l)) - -# Currying / partial function application -def curry(f, *args): - return lambda *a: f(*(args + a)) - -# Split a path into a list of segments -def tokens(path): - return tuple(filter(lambda s: len(s) != 0, path.split("/"))) - -# Write a list of strings to a stream -def writeStrings(l, os): - if l == (): - return os - os.write(car(l)) - return writeStrings(cdr(l), os) - |