зеркало из https://github.com/microsoft/AMBROSIA.git
Merge branch 'master' of https://github.com/Microsoft/AMBROSIA
This commit is contained in:
Коммит
65e782c29e
30
.travis.yml
30
.travis.yml
|
@ -1,25 +1,37 @@
|
|||
|
||||
language: minimal
|
||||
language: csharp
|
||||
mono: none
|
||||
dotnet: 2.1
|
||||
dist: xenial
|
||||
|
||||
services:
|
||||
- docker
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libunwind-dev
|
||||
- make
|
||||
- gcc
|
||||
|
||||
env:
|
||||
global:
|
||||
# Mount the logs from outside the container:
|
||||
# Mount the logs from outside the container when/if running PerformanceTestInterruptible:
|
||||
- PTI_MOUNT_LOGS=ExternalLogs
|
||||
|
||||
matrix:
|
||||
matrix:
|
||||
# Bring up a basic test within or between containers:
|
||||
- PTI_MODE=OneContainer
|
||||
- PTI_MODE=TwoContainers
|
||||
- DOCK=nodocker
|
||||
- DOCK=docker PTI_MODE=OneContainer
|
||||
# - DOCK=docker PTI_MODE=TwoContainers
|
||||
|
||||
before_install:
|
||||
- sudo apt-get install -y libunwind-dev make gcc
|
||||
|
||||
script:
|
||||
# Need to remove the dependence on Azure Tables /
|
||||
# AZURE_STORAGE_CONN_STRING if we want to do full CI in a public
|
||||
# context (or find some way to use an account without leaking its auth
|
||||
# info).
|
||||
# - ./._run_ci.sh
|
||||
|
||||
# In the meantime, we can just make sure the images build:
|
||||
- ./build_docker_images.sh
|
||||
# In the meantime, this will just make sure that everything builds.
|
||||
- ./Scripts/run_linux_ci.sh $DOCK
|
||||
|
|
|
@ -0,0 +1,284 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by Microsoft Visio, SVG Export Architecture.svg Page-1 -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events"
|
||||
xmlns:v="http://schemas.microsoft.com/visio/2003/SVGExtensions/" width="8.3941in" height="5.44479in"
|
||||
viewBox="0 0 604.375 392.025" xml:space="preserve" color-interpolation-filters="sRGB" class="st13">
|
||||
<v:documentProperties v:langID="1033" v:viewMarkup="false">
|
||||
<v:userDefs>
|
||||
<v:ud v:nameU="msvNoAutoConnect" v:val="VT0(1):26"/>
|
||||
</v:userDefs>
|
||||
</v:documentProperties>
|
||||
|
||||
<style type="text/css">
|
||||
<![CDATA[
|
||||
.st1 {fill:#ffffff}
|
||||
.st2 {stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5}
|
||||
.st3 {fill:#ffffff;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:2}
|
||||
.st4 {fill:#000000;font-family:Calibri;font-size:1.99999em}
|
||||
.st5 {font-size:1em}
|
||||
.st6 {fill:#ffffff;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
|
||||
.st7 {fill:none;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:2}
|
||||
.st8 {marker-end:url(#mrkr5-73);marker-start:url(#mrkr5-70);stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:2}
|
||||
.st9 {fill:#000000;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:0.44247787610619}
|
||||
.st10 {fill:none;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.25}
|
||||
.st11 {fill:none;stroke:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.75}
|
||||
.st12 {fill:#000000;font-family:Calibri;font-size:1.99999em;font-weight:bold}
|
||||
.st13 {fill:none;fill-rule:evenodd;font-size:12px;overflow:visible;stroke-linecap:square;stroke-miterlimit:3}
|
||||
]]>
|
||||
</style>
|
||||
|
||||
<defs id="Markers">
|
||||
<g id="lend5">
|
||||
<path d="M 2 1 L 0 0 L 1.98117 -0.993387 C 1.67173 -0.364515 1.67301 0.372641 1.98465 1.00043 " style="stroke:none"/>
|
||||
</g>
|
||||
<marker id="mrkr5-70" class="st9" v:arrowType="5" v:arrowSize="2" v:setback="3.775" refX="3.775" orient="auto"
|
||||
markerUnits="strokeWidth" overflow="visible">
|
||||
<use xlink:href="#lend5" transform="scale(2.26) "/>
|
||||
</marker>
|
||||
<marker id="mrkr5-73" class="st9" v:arrowType="5" v:arrowSize="2" v:setback="3.955" refX="-3.955" orient="auto"
|
||||
markerUnits="strokeWidth" overflow="visible">
|
||||
<use xlink:href="#lend5" transform="scale(-2.26,-2.26) "/>
|
||||
</marker>
|
||||
</defs>
|
||||
<g v:mID="0" v:index="1" v:groupContext="foregroundPage">
|
||||
<title>Page-1</title>
|
||||
<v:pageProperties v:drawingScale="1" v:pageScale="1" v:drawingUnits="19" v:shadowOffsetX="9" v:shadowOffsetY="-9"/>
|
||||
<v:layer v:name="Flowchart" v:index="0"/>
|
||||
<v:layer v:name="Connector" v:index="1"/>
|
||||
<g id="group1-1" transform="translate(18.75,-144.625)" v:mID="1" v:groupContext="group">
|
||||
<title>Sheet.1</title>
|
||||
<g id="shape2-2" v:mID="2" v:groupContext="shape" v:layerMember="0">
|
||||
<title>Disk storage</title>
|
||||
<v:custProps>
|
||||
<v:cp v:nameU="Cost" v:lbl="Cost" v:type="7" v:format="@" v:langID="1033"/>
|
||||
<v:cp v:nameU="Duration" v:lbl="Duration" v:type="2" v:langID="1033"/>
|
||||
<v:cp v:nameU="Resources" v:lbl="Resources" v:langID="1033"/>
|
||||
</v:custProps>
|
||||
<v:userDefs>
|
||||
<v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
|
||||
</v:userDefs>
|
||||
<path d="M0 345.22 L0 384.82 A36 7.2 -180 1 0 72 384.82 L72 345.22 A36 7.2 -180 0 0 0 345.22 Z" class="st1"/>
|
||||
<path d="M0 345.22 L0 384.82 A36 7.2 -180 1 0 72 384.82 L72 345.22 A36 7.2 -180 0 0 0 345.22" class="st2"/>
|
||||
<path d="M0 345.22 A36 7.2 -180 1 0 72 345.22" class="st2"/>
|
||||
<path d="M0 348.82 A36 7.2 -180 1 0 72 348.82" class="st2"/>
|
||||
</g>
|
||||
<g id="shape3-7" v:mID="3" v:groupContext="shape" v:layerMember="0" transform="translate(18,0)">
|
||||
<title>Disk storage.6</title>
|
||||
<v:custProps>
|
||||
<v:cp v:nameU="Cost" v:lbl="Cost" v:type="7" v:format="@" v:langID="1033"/>
|
||||
<v:cp v:nameU="Duration" v:lbl="Duration" v:type="2" v:langID="1033"/>
|
||||
<v:cp v:nameU="Resources" v:lbl="Resources" v:langID="1033"/>
|
||||
</v:custProps>
|
||||
<v:userDefs>
|
||||
<v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
|
||||
</v:userDefs>
|
||||
<path d="M0 345.22 L0 384.82 A36 7.2 -180 1 0 72 384.82 L72 345.22 A36 7.2 -180 0 0 0 345.22 Z" class="st1"/>
|
||||
<path d="M0 345.22 L0 384.82 A36 7.2 -180 1 0 72 384.82 L72 345.22 A36 7.2 -180 0 0 0 345.22" class="st2"/>
|
||||
<path d="M0 345.22 A36 7.2 -180 1 0 72 345.22" class="st2"/>
|
||||
<path d="M0 348.82 A36 7.2 -180 1 0 72 348.82" class="st2"/>
|
||||
</g>
|
||||
<g id="shape4-12" v:mID="4" v:groupContext="shape" v:layerMember="0" transform="translate(36,0)">
|
||||
<title>Disk storage.7</title>
|
||||
<v:custProps>
|
||||
<v:cp v:nameU="Cost" v:lbl="Cost" v:type="7" v:format="@" v:langID="1033"/>
|
||||
<v:cp v:nameU="Duration" v:lbl="Duration" v:type="2" v:langID="1033"/>
|
||||
<v:cp v:nameU="Resources" v:lbl="Resources" v:langID="1033"/>
|
||||
</v:custProps>
|
||||
<v:userDefs>
|
||||
<v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
|
||||
</v:userDefs>
|
||||
<path d="M0 345.22 L0 384.82 A36 7.2 -180 1 0 72 384.82 L72 345.22 A36 7.2 -180 0 0 0 345.22 Z" class="st1"/>
|
||||
<path d="M0 345.22 L0 384.82 A36 7.2 -180 1 0 72 384.82 L72 345.22 A36 7.2 -180 0 0 0 345.22" class="st2"/>
|
||||
<path d="M0 345.22 A36 7.2 -180 1 0 72 345.22" class="st2"/>
|
||||
<path d="M0 348.82 A36 7.2 -180 1 0 72 348.82" class="st2"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="shape5-17" v:mID="5" v:groupContext="shape" transform="translate(144.75,-252.625)">
|
||||
<title>Rectangle.42</title>
|
||||
<desc>Immortal Coordinator</desc>
|
||||
<v:userDefs>
|
||||
<v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
|
||||
</v:userDefs>
|
||||
<v:textBlock v:margins="rect(4,4,4,4)"/>
|
||||
<v:textRect cx="67.5" cy="356.025" width="135" height="72"/>
|
||||
<rect x="0" y="320.025" width="135" height="72" class="st3"/>
|
||||
<text x="22.27" y="348.82" class="st4" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Immortal <tspan
|
||||
x="8.62" dy="1.2em" class="st5">Coordinator</tspan></text> </g>
|
||||
<g id="group6-21" transform="translate(315.75,-144.625)" v:mID="6" v:groupContext="group">
|
||||
<title>Sheet.6</title>
|
||||
<g id="shape7-22" v:mID="7" v:groupContext="shape" v:layerMember="0">
|
||||
<title>Disk storage</title>
|
||||
<v:custProps>
|
||||
<v:cp v:nameU="Cost" v:lbl="Cost" v:type="7" v:format="@" v:langID="1033"/>
|
||||
<v:cp v:nameU="Duration" v:lbl="Duration" v:type="2" v:langID="1033"/>
|
||||
<v:cp v:nameU="Resources" v:lbl="Resources" v:langID="1033"/>
|
||||
</v:custProps>
|
||||
<v:userDefs>
|
||||
<v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
|
||||
</v:userDefs>
|
||||
<path d="M0 345.22 L0 384.82 A36 7.2 -180 1 0 72 384.82 L72 345.22 A36 7.2 -180 0 0 0 345.22 Z" class="st1"/>
|
||||
<path d="M0 345.22 L0 384.82 A36 7.2 -180 1 0 72 384.82 L72 345.22 A36 7.2 -180 0 0 0 345.22" class="st2"/>
|
||||
<path d="M0 345.22 A36 7.2 -180 1 0 72 345.22" class="st2"/>
|
||||
<path d="M0 348.82 A36 7.2 -180 1 0 72 348.82" class="st2"/>
|
||||
</g>
|
||||
<g id="shape8-27" v:mID="8" v:groupContext="shape" v:layerMember="0" transform="translate(18,0)">
|
||||
<title>Disk storage.6</title>
|
||||
<v:custProps>
|
||||
<v:cp v:nameU="Cost" v:lbl="Cost" v:type="7" v:format="@" v:langID="1033"/>
|
||||
<v:cp v:nameU="Duration" v:lbl="Duration" v:type="2" v:langID="1033"/>
|
||||
<v:cp v:nameU="Resources" v:lbl="Resources" v:langID="1033"/>
|
||||
</v:custProps>
|
||||
<v:userDefs>
|
||||
<v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
|
||||
</v:userDefs>
|
||||
<path d="M0 345.22 L0 384.82 A36 7.2 -180 1 0 72 384.82 L72 345.22 A36 7.2 -180 0 0 0 345.22 Z" class="st1"/>
|
||||
<path d="M0 345.22 L0 384.82 A36 7.2 -180 1 0 72 384.82 L72 345.22 A36 7.2 -180 0 0 0 345.22" class="st2"/>
|
||||
<path d="M0 345.22 A36 7.2 -180 1 0 72 345.22" class="st2"/>
|
||||
<path d="M0 348.82 A36 7.2 -180 1 0 72 348.82" class="st2"/>
|
||||
</g>
|
||||
<g id="shape9-32" v:mID="9" v:groupContext="shape" v:layerMember="0" transform="translate(36,0)">
|
||||
<title>Disk storage.7</title>
|
||||
<v:custProps>
|
||||
<v:cp v:nameU="Cost" v:lbl="Cost" v:type="7" v:format="@" v:langID="1033"/>
|
||||
<v:cp v:nameU="Duration" v:lbl="Duration" v:type="2" v:langID="1033"/>
|
||||
<v:cp v:nameU="Resources" v:lbl="Resources" v:langID="1033"/>
|
||||
</v:custProps>
|
||||
<v:userDefs>
|
||||
<v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
|
||||
</v:userDefs>
|
||||
<path d="M0 345.22 L0 384.82 A36 7.2 -180 1 0 72 384.82 L72 345.22 A36 7.2 -180 0 0 0 345.22 Z" class="st1"/>
|
||||
<path d="M0 345.22 L0 384.82 A36 7.2 -180 1 0 72 384.82 L72 345.22 A36 7.2 -180 0 0 0 345.22" class="st2"/>
|
||||
<path d="M0 345.22 A36 7.2 -180 1 0 72 345.22" class="st2"/>
|
||||
<path d="M0 348.82 A36 7.2 -180 1 0 72 348.82" class="st2"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="shape10-37" v:mID="10" v:groupContext="shape" transform="translate(441.75,-252.625)">
|
||||
<title>Rectangle.50</title>
|
||||
<desc>Immortal Coordinator</desc>
|
||||
<v:userDefs>
|
||||
<v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
|
||||
</v:userDefs>
|
||||
<v:textBlock v:margins="rect(4,4,4,4)"/>
|
||||
<v:textRect cx="67.5" cy="356.025" width="135" height="72"/>
|
||||
<rect x="0" y="320.025" width="135" height="72" class="st3"/>
|
||||
<text x="22.27" y="348.82" class="st4" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Immortal <tspan
|
||||
x="8.62" dy="1.2em" class="st5">Coordinator</tspan></text> </g>
|
||||
<g id="group11-41" transform="translate(151.5,-30.625)" v:mID="11" v:groupContext="group">
|
||||
<title>Sheet.11</title>
|
||||
<g id="group12-42" transform="translate(0,-1.5)" v:mID="12" v:groupContext="group">
|
||||
<title>Sheet.12</title>
|
||||
<g id="shape13-43" v:mID="13" v:groupContext="shape">
|
||||
<title>Rectangle.48</title>
|
||||
<desc>Application</desc>
|
||||
<v:userDefs>
|
||||
<v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
|
||||
</v:userDefs>
|
||||
<v:textBlock v:margins="rect(4,4,4,4)"/>
|
||||
<v:textRect cx="60.75" cy="371.775" width="121.5" height="40.5"/>
|
||||
<rect x="0" y="351.525" width="121.5" height="40.5" class="st6"/>
|
||||
<text x="5.46" y="378.97" class="st4" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Application</text> </g>
|
||||
<g id="shape14-46" v:mID="14" v:groupContext="shape" transform="translate(0,-40.5)">
|
||||
<title>Rectangle.51</title>
|
||||
<desc>AMBROSIA Binding</desc>
|
||||
<v:userDefs>
|
||||
<v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
|
||||
</v:userDefs>
|
||||
<v:textBlock v:margins="rect(4,4,4,4)"/>
|
||||
<v:textRect cx="60.75" cy="365.025" width="121.5" height="54"/>
|
||||
<rect x="0" y="338.025" width="121.5" height="54" class="st6"/>
|
||||
<text x="7.08" y="357.82" class="st4" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>AMBROSIA <tspan
|
||||
x="24.15" dy="1.2em" class="st5">Binding</tspan></text> </g>
|
||||
</g>
|
||||
<g id="shape15-50" v:mID="15" v:groupContext="shape">
|
||||
<title>Rectangle.54</title>
|
||||
<v:userDefs>
|
||||
<v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
|
||||
</v:userDefs>
|
||||
<rect x="0" y="296.025" width="121.5" height="96" class="st7"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="group16-52" transform="translate(448.5,-30.625)" v:mID="16" v:groupContext="group">
|
||||
<title>Sheet.16</title>
|
||||
<g id="group17-53" transform="translate(0,-1.5)" v:mID="17" v:groupContext="group">
|
||||
<title>Sheet.17</title>
|
||||
<g id="shape18-54" v:mID="18" v:groupContext="shape">
|
||||
<title>Rectangle.48</title>
|
||||
<desc>Application</desc>
|
||||
<v:userDefs>
|
||||
<v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
|
||||
</v:userDefs>
|
||||
<v:textBlock v:margins="rect(4,4,4,4)"/>
|
||||
<v:textRect cx="60.75" cy="371.775" width="121.5" height="40.5"/>
|
||||
<rect x="0" y="351.525" width="121.5" height="40.5" class="st6"/>
|
||||
<text x="5.46" y="378.97" class="st4" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Application</text> </g>
|
||||
<g id="shape19-57" v:mID="19" v:groupContext="shape" transform="translate(0,-40.5)">
|
||||
<title>Rectangle.51</title>
|
||||
<desc>AMBROSIA Binding</desc>
|
||||
<v:userDefs>
|
||||
<v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
|
||||
</v:userDefs>
|
||||
<v:textBlock v:margins="rect(4,4,4,4)"/>
|
||||
<v:textRect cx="60.75" cy="365.025" width="121.5" height="54"/>
|
||||
<rect x="0" y="338.025" width="121.5" height="54" class="st6"/>
|
||||
<text x="7.08" y="357.82" class="st4" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>AMBROSIA <tspan
|
||||
x="24.15" dy="1.2em" class="st5">Binding</tspan></text> </g>
|
||||
</g>
|
||||
<g id="shape20-61" v:mID="20" v:groupContext="shape">
|
||||
<title>Rectangle.54</title>
|
||||
<v:userDefs>
|
||||
<v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
|
||||
</v:userDefs>
|
||||
<rect x="0" y="296.025" width="121.5" height="96" class="st7"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="shape21-63" v:mID="21" v:groupContext="shape" v:layerMember="1" transform="translate(203.25,-252.625)">
|
||||
<title>Dynamic connector.61</title>
|
||||
<path d="M9 399.57 L9 399.93 L9 510.11" class="st8"/>
|
||||
</g>
|
||||
<g id="shape22-74" v:mID="22" v:groupContext="shape" v:layerMember="1" transform="translate(279.75,-279.625)">
|
||||
<title>Dynamic connector.63</title>
|
||||
<path d="M7.55 383.02 L7.91 383.02 L154.09 383.02" class="st8"/>
|
||||
</g>
|
||||
<g id="shape23-81" v:mID="23" v:groupContext="shape" v:layerMember="1" transform="translate(500.25,-252.625)">
|
||||
<title>Dynamic connector.64</title>
|
||||
<path d="M9 399.57 L9 399.93 L9 510.11" class="st8"/>
|
||||
</g>
|
||||
<g id="shape24-88" v:mID="24" v:groupContext="shape" v:layerMember="1" transform="translate(144.75,-252.625)">
|
||||
<title>Dynamic connector.66</title>
|
||||
<path d="M-7.55 392.02 L-7.91 392.02 L-72 392.02 L-72 438.11" class="st8"/>
|
||||
</g>
|
||||
<g id="shape25-95" v:mID="25" v:groupContext="shape" v:layerMember="1" transform="translate(441.75,-252.625)">
|
||||
<title>Dynamic connector.68</title>
|
||||
<path d="M-7.55 392.02 L-7.91 392.02 L-54 392.02 L-54 438.11" class="st8"/>
|
||||
</g>
|
||||
<g id="shape26-102" v:mID="26" v:groupContext="shape" transform="translate(135.75,-18.625)">
|
||||
<title>Rectangle.71</title>
|
||||
<v:userDefs>
|
||||
<v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
|
||||
</v:userDefs>
|
||||
<rect x="0" y="68.0247" width="153" height="324" class="st10"/>
|
||||
</g>
|
||||
<g id="shape27-104" v:mID="27" v:groupContext="shape" transform="translate(432.75,-18.625)">
|
||||
<title>Rectangle.72</title>
|
||||
<v:userDefs>
|
||||
<v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
|
||||
</v:userDefs>
|
||||
<rect x="0" y="68.0247" width="153" height="324" class="st10"/>
|
||||
</g>
|
||||
<g id="shape28-106" v:mID="28" v:groupContext="shape" transform="translate(136.75,-349.625)">
|
||||
<title>Sheet.28</title>
|
||||
<desc>Immortal 1</desc>
|
||||
<v:textBlock v:margins="rect(4,4,4,4)"/>
|
||||
<v:textRect cx="76" cy="382.025" width="152" height="20"/>
|
||||
<rect x="0" y="372.025" width="152" height="20" class="st11"/>
|
||||
<text x="20.73" y="389.22" class="st12" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Immortal 1</text> </g>
|
||||
<g id="shape29-109" v:mID="29" v:groupContext="shape" transform="translate(432.75,-349.625)">
|
||||
<title>Sheet.29</title>
|
||||
<desc>Immortal 2</desc>
|
||||
<v:textBlock v:margins="rect(4,4,4,4)"/>
|
||||
<v:textRect cx="76" cy="382.025" width="152" height="20"/>
|
||||
<rect x="0" y="372.025" width="152" height="20" class="st11"/>
|
||||
<text x="20.73" y="389.22" class="st12" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Immortal 2</text> </g>
|
||||
</g>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 15 KiB |
|
@ -0,0 +1,3 @@
|
|||
# Contributing
|
||||
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
|
@ -2,37 +2,62 @@
|
|||
Client Protocol for AMBROSIA network participants
|
||||
=================================================
|
||||
|
||||
This document covers how a network endpoint should communicate with
|
||||
the AMBROSIA reliability coordinator assigned to it (typically located
|
||||
within the same physical machine).
|
||||
This document covers how an application should communicate with the AMBROSIA
|
||||
reliability coordinator assigned to it. The coordinator is located within the
|
||||
same physical machine/container and assumed to survive or fail with the
|
||||
application process. The coordinator communicates via TCP/IP over a local
|
||||
socket with the application. This process separation is designed to minimize
|
||||
assumptions about the application and maximize language-agnosticity.
|
||||
|
||||
Overview and Terminology
|
||||
------------------------
|
||||
|
||||
FINISHME
|
||||
In AMBROSIA a set of application processes (services) serve as communication
|
||||
endpoints, communicating *exclusively* through the network of Immortal
|
||||
Coordinators, which collectively serve as the message bus. The individual
|
||||
processes (or objects contained therein) are the *Immortals* which survive the
|
||||
failure of individual machines.
|
||||
|
||||
* Commit ID
|
||||
* Sequence ID
|
||||
Below we use the following terminology:
|
||||
|
||||
* "Async/await" RPC - a classic notion of a *future*. These RPCs return a value back to the caller. Because AMBROSIA ensures reliability, they are semantically identical to function calls, without introducing new failure modes such as timeouts or disconnections.
|
||||
* Committer ID - an arbitrary (32 bit) identifier for a communication endpoint
|
||||
(a service) in the network of running "immortals". This is typically
|
||||
generated automatically the first time each application process starts.
|
||||
It is distinct from the destination *name*.
|
||||
|
||||
* "Fire and Forget" RPC - launch a remote computation, but provide no information back to the caller. Note that even an async/await
|
||||
RPC with "void" return value exposes more than this, because the caller can ascertain when the remote RPC has been completely processed.
|
||||
* Destination name - the string identifying a communication endpoint, often
|
||||
human readable.
|
||||
|
||||
* Sequence ID - the (monotonically increasing) number of a log entry. Note that
|
||||
each logical immortal has its own log.
|
||||
|
||||
* "Async/await" RPCs - are *futures*; they return a value back to the
|
||||
caller. Because AMBROSIA ensures reliability, they are semantically
|
||||
identical to function calls, without introducing new failure modes such as
|
||||
timeouts or disconnections.
|
||||
|
||||
* "Fire and Forget" RPCs - launch a remote computation, but provide no
|
||||
information back to the caller. Note that even an async/await RPC with
|
||||
"void" return value indicates more to the caller (namely, that the remote
|
||||
computation has completed).
|
||||
|
||||
Required Helper Functions
|
||||
-------------------------
|
||||
|
||||
FINISHME:
|
||||
In order to build the binary message formats described below, we assume that the
|
||||
new client software can access TCP sockets and additionally implements the
|
||||
following serialized datatypes.
|
||||
|
||||
Assumes TCP +
|
||||
* ZigZagInt - a zig-zag encoded 32-bit signed integer
|
||||
* ZigZagLong - a zig-zag encoded 64-bit signed integer
|
||||
* IntFixed - a 32-bit little endian number
|
||||
* LongFixed - a 64-bit little endian number
|
||||
|
||||
* WriteZigZagInt
|
||||
* WriteFixedInt
|
||||
* WriteZigZagLong
|
||||
* WriteFixedLong
|
||||
* CheckSum - FINISHME
|
||||
|
||||
The variable-length integers are in the same format used by, e.g.,
|
||||
[Protobufs](https://developers.google.com/protocol-buffers/docs/encoding).
|
||||
|
||||
* CheckSum
|
||||
|
||||
Message Formats
|
||||
---------------
|
||||
|
@ -43,7 +68,7 @@ Message Formats
|
|||
All information received from the reliability coordinator is in the form of a sequence of log records.
|
||||
Each log record has a 24 byte header, followed by the actual record contents. The header is as follows:
|
||||
|
||||
* Bytes [0-3]: The commit ID for the service, this should be constant for all records for the lifetime of the service, format IntFixed.
|
||||
* Bytes [0-3]: The committer ID for the service, this should be constant for all records for the lifetime of the service, format IntFixed.
|
||||
* Bytes [4-7]: The size of the whole log record, in bytes, including the header. The format is IntFixed
|
||||
* Bytes [8-15]: The check bytes to check the integrity of the log record. The format is LongFixed.
|
||||
* Bytes [16-23]: The log record sequence ID. Excluding records labeled with sequence ID “-1”, these should be in order. The format is LongFixed
|
||||
|
@ -58,8 +83,8 @@ The rest of the record is a sequence of messages, packed tightly, each with the
|
|||
All information sent to the reliability coordinator is in the form of a sequence of messages with the format specified above.
|
||||
Message types and associated data which may be sent to or received by services:
|
||||
|
||||
* 14 - TrimTo (RRN: INTERNAL!??!)
|
||||
* 13 - CountReplayableRPCBatchByte (RRN: INTERNAL!??!)
|
||||
* 14 - TrimTo (FINISHME - INTERNAL!??!)
|
||||
* 13 - CountReplayableRPCBatchByte (FINISHME - INTERNAL!??!)
|
||||
|
||||
* 12 – `UpgradeService` (Received): No data
|
||||
|
||||
|
@ -69,7 +94,12 @@ Message types and associated data which may be sent to or received by services:
|
|||
|
||||
* 9 – `InitialMessage` (Sent/Received): Data is a complete (incoming rpc) message which is given back to the service as the very first RPC message it ever receives. Used to bootstrap service start behavior.
|
||||
|
||||
* 8 – `Checkpoint` (Sent/Received): Data are the bytes corresponding to the serialized state of the service.
|
||||
* 8 – `Checkpoint` (Sent/Received): The payload is a single 64 bit number.
|
||||
That payload in turn is the size in bytes of a checkpoint itself, which is a
|
||||
binary blob that follows this message immediately (no additional header).
|
||||
The reason that checkpoints are not sent in the message payload directly is
|
||||
so that they can have a 64-bit instead of 32-bit length, in order to support
|
||||
large checkpoints.
|
||||
|
||||
* 5 – `RPCBatch` (Sent/Received): Data are a count of the number of RPC messages in the batch, followed by the corresponding number of RPC messages. Note that the count is in variable sized WriteInt format
|
||||
|
||||
|
@ -135,6 +165,7 @@ If performing an upgrade what-if test:
|
|||
|
||||
When a TakeCheckpoint message is received, no further messages may be processed until the state is serialized and sent in a checkpoint message. Note that the serialized state must include any unsent output messages which resulted from previous incoming calls. Those serialized unsent messages must follow the checkpoint message.
|
||||
|
||||
(RRN: What are the rules for SENDING!!)
|
||||
### Attach-before-send protocol
|
||||
|
||||
FINISHME...
|
||||
|
||||
(RRN: What is the ATTACH protocol??)
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
|
||||
# Put your -D variables here, e.g. -DDEBUG
|
||||
DEFINES= -DIPV4
|
||||
# Put your -D variables here:
|
||||
DEFINES ?=
|
||||
|
||||
EXTRA_DEFINES = -DIPV4
|
||||
# ^ TODO build everything twice for IPV6 vs IPV4.
|
||||
# TODOTODO fix it so that one compile can work for both.
|
||||
|
||||
ALL_DEFINES = $(DEFINES) $(EXTRA_DEFINES)
|
||||
|
||||
GNULIBS= -lpthread
|
||||
GNUOPTS= -pthread -O3
|
||||
|
@ -16,13 +19,16 @@ OBJS1= $(patsubst src/%.c,bin/static/%.o, $(SRCS) )
|
|||
|
||||
OBJS2= $(patsubst src/%.c,bin/shared/%.o, $(SRCS) )
|
||||
|
||||
COMP= gcc $(DEFINES) -I include/ $(GNUOPTS)
|
||||
COMP= gcc $(ALL_DEFINES) -I include/ $(GNUOPTS)
|
||||
LINK= gcc
|
||||
|
||||
LIBNAME=libambrosia
|
||||
|
||||
all: bin/$(LIBNAME).a bin/$(LIBNAME).so
|
||||
|
||||
debug:
|
||||
$(MAKE) DEFINES="-DAMBCLIENT_DEBUG" clean publish
|
||||
|
||||
bin/$(LIBNAME).a: $(OBJS1)
|
||||
ar rcs $@ $(OBJS1)
|
||||
|
||||
|
|
|
@ -53,8 +53,6 @@ enum MsgType { RPC=0, //
|
|||
// FIXME: these should become PRIVATE to the library:
|
||||
extern int g_to_immortal_coord, g_from_immortal_coord;
|
||||
|
||||
extern int upport, downport;
|
||||
|
||||
|
||||
// Communicates with the server to establish normal operation.
|
||||
//
|
||||
|
@ -62,9 +60,14 @@ extern int upport, downport;
|
|||
// received from a call to connect_sockets.
|
||||
void startup_protocol(int upfd, int downfd);
|
||||
|
||||
// Connect the
|
||||
void connect_sockets(int* upptr, int* downptr);
|
||||
// Connect to the ImmortalCoordinator. Use the provided ports.
|
||||
//
|
||||
// On the "up" port we connect, and on "down" the coordinator connects
|
||||
// to us. This function writes the file descriptors for the opened
|
||||
// connections into the pointers provided as the last two arguments.
|
||||
void connect_sockets(int upport, int downport, int* up_fd_ptr, int* down_fd_ptr);
|
||||
|
||||
// Encoding and Decoding message types
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// PRECONDITION: sufficient space free at output pointer.
|
||||
|
@ -94,6 +97,8 @@ void amb_send_outgoing_rpc(void* tempbuf, char* dest, int32_t destLen, char RPC_
|
|||
void amb_recv_log_hdr(int sockfd, struct log_hdr* hdr);
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// TEMP - audit me
|
||||
void attach_if_needed(char* dest, int destLen);
|
||||
|
||||
|
@ -125,8 +130,18 @@ int zigzag_int_size(int32_t value);
|
|||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifdef AMBCLIENT_DEBUG
|
||||
extern volatile int64_t amb_debug_lock;
|
||||
|
||||
extern volatile int64_t debug_lock;
|
||||
// Helper used only below
|
||||
static inline void amb_sleep_seconds(double n) {
|
||||
#ifdef _WIN32
|
||||
Sleep((int)(n * 1000));
|
||||
#else
|
||||
int64_t nanos = (int64_t)(10e9 * n);
|
||||
const struct timespec ts = {0, nanos};
|
||||
nanosleep(&ts, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void amb_debug_log(const char *format, ...)
|
||||
{
|
||||
|
@ -134,14 +149,14 @@ static inline void amb_debug_log(const char *format, ...)
|
|||
va_start(args, format);
|
||||
amb_sleep_seconds((double)(rand()%1000) * 0.00001); // .01 - 10 ms
|
||||
#ifdef _WIN32
|
||||
while ( 1 == InterlockedCompareExchange64(&debug_lock, 1, 0) ) { }
|
||||
while ( 1 == InterlockedCompareExchange64(&amb_debug_lock, 1, 0) ) { }
|
||||
#else
|
||||
while ( 1 == __sync_val_compare_and_swap(&debug_lock, 1, 0) ) { }
|
||||
while ( 1 == __sync_val_compare_and_swap(&amb_debug_lock, 1, 0) ) { }
|
||||
#endif
|
||||
fprintf(amb_dbg_fd," [AMBCLIENT] ");
|
||||
vfprintf(amb_dbg_fd,format, args);
|
||||
fflush(amb_dbg_fd);
|
||||
debug_lock = 0;
|
||||
amb_debug_lock = 0;
|
||||
va_end(args);
|
||||
}
|
||||
#else
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
|
||||
// Internal helper: try repeatedly on a socket until all bytes are sent.
|
||||
static inline void socket_send_all(int sock, const void* buf, size_t len, int flags) {
|
||||
static inline
|
||||
void socket_send_all(int sock, const void* buf, size_t len, int flags) {
|
||||
char* cur = (char*)buf;
|
||||
int remaining = len;
|
||||
while (remaining > 0) {
|
||||
|
@ -21,3 +22,18 @@ static inline void socket_send_all(int sock, const void* buf, size_t len, int fl
|
|||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline
|
||||
void print_hex_bytes(FILE* fd, char* ptr, int len) {
|
||||
const int limit = 100; // Only print this many:
|
||||
fprintf(fd,"0x");
|
||||
int j;
|
||||
for (j=0; j < len && j < limit; j++) {
|
||||
fprintf(fd,"%02hhx", (unsigned char)ptr[j]);
|
||||
if (j % 2 == 1)
|
||||
fprintf(fd," ");
|
||||
}
|
||||
if (j<len) fprintf(fd,"...");
|
||||
}
|
||||
|
||||
|
|
|
@ -25,18 +25,12 @@
|
|||
#include "ambrosia/client.h"
|
||||
#include "ambrosia/internal/bits.h"
|
||||
|
||||
// Library-level global variables:
|
||||
// Library-level (private) global variables:
|
||||
// --------------------------------------------------
|
||||
|
||||
// FIXME: looks like we need a hashtable after all...
|
||||
int g_attached = 0; // For now, ONE destination.
|
||||
|
||||
|
||||
// This follows the rule that the RECV side acts as the server:
|
||||
int upport = 1000; // Send. Up to the reliability-coordinator-as-server
|
||||
int downport = 1001; // Recv. Down from the coordinator (we're server)
|
||||
|
||||
|
||||
// Global variables that should be initialized once for the library.
|
||||
// We can ONLY ever have ONE reliability coordinator.
|
||||
int g_to_immortal_coord, g_from_immortal_coord;
|
||||
|
@ -50,7 +44,7 @@ const char* coordinator_host = "::1";
|
|||
#endif
|
||||
|
||||
#ifdef AMBCLIENT_DEBUG
|
||||
// volatile int64_t debug_lock = 0;
|
||||
volatile int64_t amb_debug_lock = 0;
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -71,18 +65,6 @@ char* amb_get_error_string() {
|
|||
return strerror(errno);
|
||||
#endif
|
||||
}
|
||||
|
||||
void print_hex_bytes(FILE* fd, char* ptr, int len) {
|
||||
const int limit = 100; // Only print this many:
|
||||
fprintf(fd,"0x");
|
||||
int j;
|
||||
for (j=0; j < len && j < limit; j++) {
|
||||
fprintf(fd,"%02hhx", (unsigned char)ptr[j]);
|
||||
if (j % 2 == 1)
|
||||
fprintf(fd," ");
|
||||
}
|
||||
if (j<len) fprintf(fd,"...");
|
||||
}
|
||||
|
||||
void print_decimal_bytes(char* ptr, int len) {
|
||||
const int limit = 100; // Only print this many:
|
||||
|
@ -201,27 +183,6 @@ void* amb_write_outgoing_rpc(void* buf, char* dest, int32_t destLen, char RPC_or
|
|||
return (void*)cursor;
|
||||
}
|
||||
|
||||
|
||||
// This is a convenience method that sits above the buffer API:
|
||||
// ------------------------------------------------------------
|
||||
|
||||
/*
|
||||
// Logically the same as send_outgoing_*, except uses the global buffer.
|
||||
// PRECONDITION: buffer is free / no outstanding "reserve" that needs to be released.
|
||||
void buffer_outgoing_rpc_hdr(char* dest, int32_t destLen, char RPC_or_RetVal,
|
||||
int32_t methodID, char fireForget, int argsLen) {
|
||||
// Overestimate the space needed:
|
||||
int sizeBound = (1 // type tag
|
||||
+ 5 + destLen + 1 // RPC_or_RetVal
|
||||
+ 5 + 1 // fireForget
|
||||
+ 5);
|
||||
char* start = reserve_buffer(sizeBound);
|
||||
char* end = amb_write_outgoing_rpc_hdr(start, dest,destLen,RPC_or_RetVal,methodID,fireForget,argsLen);
|
||||
// If we want to create RPCBatch messages we need to only send complete messages, not just headers:
|
||||
finished_reserve_buffer(end-start);
|
||||
}
|
||||
*/
|
||||
|
||||
// Direct socket sends/recvs
|
||||
// ------------------------------
|
||||
|
||||
|
@ -291,29 +252,6 @@ void attach_if_needed(char* dest, int destLen) {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// INEFFICIENT version that makes an extra copy:
|
||||
void send_message(char* buf, int len) {
|
||||
attach_if_needed(destName, ??); // Hard-coded global dest name.
|
||||
|
||||
// FIXME - LAME COPY to PREPEND header bytes!
|
||||
char* sendbuf = (char*)malloc(1 + 5 + destLen + 1 + 5 + 1 + len);
|
||||
char* newpos = amb_write_outgoing_rpc(sendbuf, destName, destLen, 0, TPUT_MSG_ID, 1, buf, len);
|
||||
|
||||
// FIXME: one system call per message!
|
||||
socket_send_all(g_to_immortal_coord, sendbuf, newpos-sendbuf, 0);
|
||||
#ifdef AMBCLIENT_DEBUG
|
||||
amb_debug_log("Sent %d byte message up to coordinator, argsLen %d...\n Hex: ", newpos-sendbuf, len);
|
||||
print_hex_bytes(amb_dbg_fd, sendbuf, newpos-sendbuf);
|
||||
fprintf(amb_dbg_fd,"\n Decimal: ");
|
||||
print_decimal_bytes(sendbuf, newpos-sendbuf); printf("\n");
|
||||
#endif
|
||||
free(sendbuf);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
// Begin connect_sockets:
|
||||
// --------------------------------------------------
|
||||
|
@ -343,7 +281,7 @@ void enable_fast_loopback(SOCKET sock) {
|
|||
}
|
||||
}
|
||||
|
||||
void connect_sockets(int* upptr, int* downptr) {
|
||||
void connect_sockets(int upport, int downport, int* upptr, int* downptr) {
|
||||
WSADATA wsa;
|
||||
SOCKET sock;
|
||||
|
||||
|
@ -502,7 +440,7 @@ void connect_sockets(int* upptr, int* downptr) {
|
|||
|
||||
// Establish both connections with the reliability coordinator.
|
||||
// Takes two output parameters where it will write the resulting sockets.
|
||||
void connect_sockets(int* upptr, int* downptr) {
|
||||
void connect_sockets(int upport, int downport, int* upptr, int* downptr) {
|
||||
#ifdef IPV4
|
||||
struct hostent* immortalCoord;
|
||||
struct sockaddr_in addr;
|
||||
|
@ -632,6 +570,7 @@ void startup_protocol(int upfd, int downfd) {
|
|||
case TakeBecomingPrimaryCheckpoint:
|
||||
amb_debug_log("Starting up for the first time (TakeBecomingPrimaryCheckpoint)\n");
|
||||
break;
|
||||
|
||||
case Checkpoint:
|
||||
fprintf(stderr, "RECOVER mode ... not implemented yet.\n");
|
||||
|
||||
|
|
|
@ -230,10 +230,6 @@ char* reserve_buffer(int len)
|
|||
|
||||
void release_buffer(int len)
|
||||
{
|
||||
// finished_reserve_buffer(len);
|
||||
// g_buffer_tail += g_buffer_total_reserved; // Publish it!
|
||||
// g_buffer_total_reserved = 0;
|
||||
|
||||
spsc_rring_debug_log(" => release_buffer of %d bytes, new tail %d\n", len, g_buffer_tail + len);
|
||||
|
||||
if (len > g_buffer_last_reserved) {
|
||||
|
|
|
@ -23,11 +23,12 @@
|
|||
|
||||
# Oh, that's happening even on ambrosia-dev:
|
||||
FROM ambrosia-dev
|
||||
# We get build dependencies from ambrosia-dev, since it built the native library.
|
||||
# RUN apt-get update && \
|
||||
# apt-get install -y make gcc
|
||||
# nmap
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y make gcc nmap
|
||||
|
||||
ADD . /ambrosia/NativeService
|
||||
ADD . /ambrosia/NativeService
|
||||
WORKDIR /ambrosia/NativeService
|
||||
|
||||
ENV AMBROSIA_BINDIR=/ambrosia/bin
|
||||
|
|
|
@ -20,7 +20,7 @@ LIBS= -L $(AMBROSIA_BINDIR) -l:libambrosia.a -lpthread
|
|||
LINK= gcc
|
||||
|
||||
all: service_v4.exe service_v6.exe
|
||||
dbg: service_dbg_v4.exe
|
||||
debug: service_dbg_v4.exe
|
||||
|
||||
service_temp.exe: service.c
|
||||
$(COMP) service.c -o service.o
|
||||
|
@ -29,10 +29,12 @@ service_temp.exe: service.c
|
|||
service_v4.exe: $(HEADERS) $(SRCS) service.c
|
||||
$(MAKE) DEFINES="-DIPV4" partclean service_temp.exe
|
||||
mv service_temp.exe $@
|
||||
ln -sf $@ service.exe
|
||||
|
||||
service_dbg_v4.exe: $(HEADERS) $(SRCS) service.c
|
||||
$(MAKE) DEFINES="-DAMBCLIENT_DEBUG -DIPV4" partclean service_temp.exe
|
||||
mv service_temp.exe $@
|
||||
ln -sf $@ service.exe
|
||||
|
||||
service_v6.exe: $(HEADERS) $(SRCS) service.c
|
||||
$(MAKE) DEFINES="-DIPV6" partclean service_temp.exe
|
||||
|
@ -42,7 +44,7 @@ partclean:
|
|||
rm -f service_temp.exe
|
||||
|
||||
clean:
|
||||
rm -f service_winsockv4.exe service_winsockv6.exe service_v4.exe service_v6.exe
|
||||
rm -f service_winsockv4.exe service_winsockv6.exe service_v4.exe service_v6.exe service_dbg_v4.exe serice_temp.exe
|
||||
rm -f \#* .\#* *~
|
||||
|
||||
.PHONY: lin clean partclean
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -xeuo pipefail
|
||||
|
||||
# Run both processes together in one script. This is intended to be
|
||||
# used within the Docker container built by Dockerfile.
|
||||
|
||||
# TODO: set up your credentials before calling this script:
|
||||
# export AZURE_STORAGE_CONN_STRING="..."
|
||||
|
||||
echo "Launching CRA worker"
|
||||
# strace dotnet "/ambrosia/ImmortalCoordinator/bin/Release/netcoreapp2.0/linux-x64/ImmortalCoordinator.dll" rrnjob 1500 2> /tmp/coord.log &
|
||||
dotnet "/ambrosia/ImmortalCoordinator/bin/Release/netcoreapp2.0/linux-x64/ImmortalCoordinator.dll" rrnjob 1500 &
|
||||
PID1=$!
|
||||
sleep 1
|
||||
# dotnet "/ambrosia/ImmortalCoordinator/bin/Release/netcoreapp2.0/linux-x64/ImmortalCoordinator.dll" rrnserver 2500 &
|
||||
# PID2=$!
|
||||
|
||||
# Lame, racy:
|
||||
sleep 7
|
||||
|
||||
echo "Proceeding on the assumption you saw \"Ready...\" above this line..."
|
||||
./service_v4.exe
|
||||
|
||||
wait $PID1
|
||||
# wait $PID2
|
|
@ -11,10 +11,17 @@ set -euo pipefail
|
|||
|
||||
# source `dirname $0`/default_var_settings.sh
|
||||
|
||||
PORT1=49001
|
||||
PORT2=49002
|
||||
PORT3=49003
|
||||
PORT4=49004
|
||||
|
||||
# A number to add to all ports to avoid colliding or reusing recently
|
||||
# used ports.
|
||||
if ! [ ${PORTOFFSET:+defined} ]; then
|
||||
PORTOFFSET=0
|
||||
fi
|
||||
|
||||
PORT1=$((49001 + PORTOFFSET))
|
||||
PORT2=$((49002 + PORTOFFSET))
|
||||
PORT3=$((49003 + PORTOFFSET))
|
||||
PORT4=$((49004 + PORTOFFSET))
|
||||
|
||||
INSTANCE_PREFIX=""
|
||||
if [ $# -ne 0 ];
|
||||
|
@ -23,26 +30,32 @@ fi
|
|||
CLIENTNAME=${INSTANCE_PREFIX}nativeSend
|
||||
SERVERNAME=${INSTANCE_PREFIX}nativeRecv
|
||||
|
||||
_cleanup() {
|
||||
kill -TERM "$pid_server" 2>/dev/null || true
|
||||
}
|
||||
trap _cleanup TERM INT QUIT HUP
|
||||
|
||||
echo
|
||||
echo "--------------------------------------------------------------------------------"
|
||||
echo "Running NativeService with 4 processes all in this machine/container"
|
||||
echo " Instance: names $CLIENTNAME, $SERVERNAME"
|
||||
|
||||
echo "--------------------------------------------------------------------------------"
|
||||
echo
|
||||
|
||||
set -x
|
||||
time Ambrosia RegisterInstance -i $CLIENTNAME --rp $PORT1 --sp $PORT2 -l "./ambrosia_logs/"
|
||||
time Ambrosia RegisterInstance -i $SERVERNAME --rp $PORT3 --sp $PORT4 -l "./ambrosia_logs/"
|
||||
set +x
|
||||
|
||||
# AMBROSIA_IMMORTALCOORDINATOR_PORT=2500 runAmbrosiaService.sh ./service_v4.exe 0 $SERVERNAME $PORT1 $PORT2 24 1 20
|
||||
if ! [ ${SKIP_REGISTER:+defined} ]; then
|
||||
set -x
|
||||
time Ambrosia RegisterInstance -i $CLIENTNAME --rp $PORT1 --sp $PORT2 -l "./ambrosia_logs/"
|
||||
time Ambrosia RegisterInstance -i $SERVERNAME --rp $PORT3 --sp $PORT4 -l "./ambrosia_logs/"
|
||||
set +x
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "NativeService: Launching Receiver"
|
||||
set -x
|
||||
AMBROSIA_INSTANCE_NAME=$SERVERNAME AMBROSIA_IMMORTALCOORDINATOR_PORT=1500 \
|
||||
AMBROSIA_INSTANCE_NAME=$SERVERNAME AMBROSIA_IMMORTALCOORDINATOR_PORT=$((1600 + PORTOFFSET)) \
|
||||
COORDTAG=CoordRecv AMBROSIA_IMMORTALCOORDINATOR_LOG=./recvr.log \
|
||||
runAmbrosiaService.sh ./service_v4.exe 1 $CLIENTNAME $PORT3 $PORT4 24 1 20 &
|
||||
runAmbrosiaService.sh ./service.exe 1 $CLIENTNAME $PORT3 $PORT4 24 1 20 &
|
||||
pid_server=$!
|
||||
set +x
|
||||
|
||||
|
@ -56,9 +69,9 @@ fi
|
|||
echo
|
||||
echo "NativeService: Launching Sender now:"
|
||||
set -x
|
||||
AMBROSIA_INSTANCE_NAME=$CLIENTNAME AMBROSIA_IMMORTALCOORDINATOR_PORT=2500 \
|
||||
AMBROSIA_INSTANCE_NAME=$CLIENTNAME AMBROSIA_IMMORTALCOORDINATOR_PORT=$((1601 + PORTOFFSET)) \
|
||||
COORDTAG=CoordSend AMBROSIA_IMMORTALCOORDINATOR_LOG=./sender.log \
|
||||
runAmbrosiaService.sh ./service_v4.exe 0 $SERVERNAME $PORT1 $PORT2 24 1 20
|
||||
runAmbrosiaService.sh ./service.exe 0 $SERVERNAME $PORT1 $PORT2 24 1 20
|
||||
set +x
|
||||
|
||||
echo
|
||||
|
|
|
@ -37,8 +37,9 @@
|
|||
// TODO: remove internal dependency:
|
||||
#include "ambrosia/internal/spsc_rring.h"
|
||||
#include "ambrosia/client.h"
|
||||
#include "ambrosia/internal/bits.h"
|
||||
|
||||
// Extra utilities (print_hex_bytes, socket_send_all):
|
||||
#include "ambrosia/internal/bits.h"
|
||||
|
||||
// Library-level global variables:
|
||||
// --------------------------------------------------
|
||||
|
@ -100,21 +101,6 @@ int destLen; // Initialized below..
|
|||
// General helper functions
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
#ifdef AMBCLIENT_DEBUG
|
||||
// DUPLICATED with ambrosia_client.
|
||||
void print_hex_bytes(FILE* fd, char* ptr, int len) {
|
||||
const int limit = 100; // Only print this many:
|
||||
fprintf(fd,"0x");
|
||||
int j;
|
||||
for (j=0; j < len && j < limit; j++) {
|
||||
fprintf(fd,"%02hhx", (unsigned char)ptr[j]);
|
||||
if (j % 2 == 1)
|
||||
fprintf(fd," ");
|
||||
}
|
||||
if (j<len) fprintf(fd,"...");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Hacky busy-wait by thread-yielding for now:
|
||||
static inline void yield_thread() {
|
||||
#ifdef _WIN32
|
||||
|
@ -587,7 +573,7 @@ void* network_progress_thread( void* lpParam )
|
|||
} else if ( spin_tries == 0) {
|
||||
spin_tries = hot_spin_amount;
|
||||
// amb_debug_log(" network thread: yielding to wait...\n");
|
||||
#ifdef AMBCLIENT_DEBUG
|
||||
#ifdef AMBCLIENT_DEBUG
|
||||
sleep_seconds(0.5);
|
||||
sleep_seconds(0.05);
|
||||
#endif
|
||||
|
@ -625,10 +611,12 @@ void reset_trial_state() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// How big to allocate the buffer:
|
||||
int buffer_bytes_allocated = -1; // Ivar semantics - write once.
|
||||
int upport, downport;
|
||||
|
||||
srand(time(0));
|
||||
|
||||
|
@ -664,6 +652,7 @@ int main(int argc, char** argv)
|
|||
destLen = strlen(destName);
|
||||
upport = atoi(argv[3]);
|
||||
downport = atoi(argv[4]);
|
||||
|
||||
} else {
|
||||
fprintf(stderr, "Usage: this executable expects args: <role=0/1/2/3> <destination> <port> <port> [roundsz] [trials] [bufsz]\n");
|
||||
fprintf(stderr, " where <role> is 0/1 for sender/receiver throughput mode\n");
|
||||
|
@ -681,6 +670,11 @@ int main(int argc, char** argv)
|
|||
fprintf(stderr, "\nERROR: Bytes-per-round should be bigger than max message size.\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
if ( g_is_sender || destLen == 0)
|
||||
printf("We are running the SENDER\n");
|
||||
else
|
||||
printf("We are running the RECEIVER\n");
|
||||
|
||||
printf("Connecting to my coordinator on ports: %d (up), %d (down)\n", upport, downport);
|
||||
printf("The 'up' port we connect, and the 'down' one the coordinator connects to us.\n");
|
||||
|
@ -690,7 +684,7 @@ int main(int argc, char** argv)
|
|||
/* printf("(You need four ports, in the above example: 50000-50003 .)\n"); */
|
||||
|
||||
int upfd, downfd;
|
||||
connect_sockets(&upfd, &downfd);
|
||||
connect_sockets(upport, downport, &upfd, &downfd);
|
||||
amb_debug_log("Connections established (%d,%d), beginning protocol.\n", upfd, downfd);
|
||||
startup_protocol(upfd, downfd);
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Perform the code-generation step for this example application.
|
||||
|
||||
if (-not ( $env:AMBVARIANT )) {
|
||||
$env:AMBVARIANT="x64\Debug\netcoreapp2.0"
|
||||
if (-not ( $env:AMBVARIANTCORE )) {
|
||||
$env:AMBVARIANTCORE="x64\Debug\netcoreapp2.0"
|
||||
}
|
||||
|
||||
# Build the API projects
|
||||
|
@ -17,9 +17,9 @@ Copy-Item "IJob\bin\Debug\netcoreapp2.0\publish\*" -Force -Destination "CodeGenD
|
|||
|
||||
Copy-Item "..\..\Clients\CSharp\AmbrosiaCS\AmbrosiaCS.csproj" -Force -Destination "CodeGenDependencies\netcoreapp2.0\"
|
||||
|
||||
Write-Host "Using variant of AmbrosiaCS.exe: $env:AMBVARIANT"
|
||||
Write-Host "Using variant of AmbrosiaCS.exe: $env:AMBVARIANTCORE"
|
||||
|
||||
Write-Host "Executing codegen command: dotnet ..\..\Clients\CSharp\AmbrosiaCS\bin\$env:AMBVARIANT\AmbrosiaCS.dll CodeGen -a=API\bin\$env:AMBVARIANT\ServerAPI.dll -a=IJob\bin\$env:AMBVARIANT\IJob.dll -o=PTIAmbrosiaGeneratedAPINetCore -f=netcoreapp2.0 -b=CodeGenDependencies\netcoreapp2.0"
|
||||
Write-Host "Executing codegen command: dotnet ..\..\Clients\CSharp\AmbrosiaCS\bin\$env:AMBVARIANTCORE\AmbrosiaCS.dll CodeGen -a=API\bin\$env:AMBVARIANTCORE\ServerAPI.dll -a=IJob\bin\$env:AMBVARIANTCORE\IJob.dll -o=PTIAmbrosiaGeneratedAPINetCore -f=netcoreapp2.0 -b=CodeGenDependencies\netcoreapp2.0"
|
||||
|
||||
# Generate the assemblies, assumes an .exe which is created by a .Net Framework build:
|
||||
& dotnet "..\..\Clients\CSharp\AmbrosiaCS\bin\$env:AMBVARIANT\AmbrosiaCS.dll" CodeGen -a="API\bin\$env:AMBVARIANT\ServerAPI.dll" -a="IJob\bin\$env:AMBVARIANT\IJob.dll" -o="PTIAmbrosiaGeneratedAPINetCore" -f="netcoreapp2.0" -b="CodeGenDependencies\netcoreapp2.0"
|
||||
& dotnet "..\..\Clients\CSharp\AmbrosiaCS\bin\$env:AMBVARIANTCORE\AmbrosiaCS.dll" CodeGen -a="API\bin\$env:AMBVARIANTCORE\ServerAPI.dll" -a="IJob\bin\$env:AMBVARIANTCORE\IJob.dll" -o="PTIAmbrosiaGeneratedAPINetCore" -f="netcoreapp2.0" -b="CodeGenDependencies\netcoreapp2.0"
|
||||
|
|
|
@ -4,8 +4,6 @@ PORT2=50002
|
|||
PORT3=50003
|
||||
PORT4=50004
|
||||
|
||||
CLIENTNAME=dockertest1
|
||||
SERVERNAME=dockertest2
|
||||
|
||||
CRAPORT1=1500
|
||||
CRAPORT2=50500
|
||||
|
||||
|
|
|
@ -18,6 +18,19 @@ set -euo pipefail
|
|||
cd `dirname $0`
|
||||
source ./default_var_settings.sh
|
||||
|
||||
# PORTOFFSET: A number to add to all ports to avoid colliding or
|
||||
# reusing recently used ports.
|
||||
if ! [ ${PORTOFFSET:+defined} ]; then
|
||||
PORTOFFSET=0
|
||||
else
|
||||
PORT1=$((PORT1 + PORTOFFSET))
|
||||
PORT2=$((PORT2 + PORTOFFSET))
|
||||
PORT3=$((PORT3 + PORTOFFSET))
|
||||
PORT4=$((PORT4 + PORTOFFSET))
|
||||
CRAPORT1=$((CRAPORT1 + PORTOFFSET))
|
||||
CRAPORT2=$((CRAPORT2 + PORTOFFSET))
|
||||
fi
|
||||
|
||||
INSTANCE_PREFIX=""
|
||||
if [ $# -ne 0 ];
|
||||
then INSTANCE_PREFIX="$1"
|
||||
|
@ -38,16 +51,22 @@ echo " Instance: names $CLIENTNAME, $SERVERNAME"
|
|||
echo "--------------------------------------------------------------------------------"
|
||||
echo
|
||||
|
||||
set -x
|
||||
time Ambrosia RegisterInstance -i $CLIENTNAME --rp $PORT1 --sp $PORT2 -l "./ambrosia_logs/"
|
||||
time Ambrosia RegisterInstance -i $SERVERNAME --rp $PORT3 --sp $PORT4 -l "./ambrosia_logs/"
|
||||
set +x
|
||||
if ! [ ${SKIP_REGISTER:+defined} ]; then
|
||||
set -x
|
||||
time Ambrosia RegisterInstance -i $CLIENTNAME --rp $PORT1 --sp $PORT2 -l "./ambrosia_logs/"
|
||||
time Ambrosia RegisterInstance -i $SERVERNAME --rp $PORT3 --sp $PORT4 -l "./ambrosia_logs/"
|
||||
set +x
|
||||
fi
|
||||
|
||||
which runAmbrosiaService.sh
|
||||
slog=`mktemp server.XXXX.log`
|
||||
jlog=`mktemp job.XXXX.log`
|
||||
|
||||
echo
|
||||
echo "PTI: Launching Server:"
|
||||
set -x
|
||||
AMBROSIA_INSTANCE_NAME=$SERVERNAME AMBROSIA_IMMORTALCOORDINATOR_PORT=$CRAPORT1 \
|
||||
COORDTAG=CoordServ AMBROSIA_IMMORTALCOORDINATOR_LOG=./server.log \
|
||||
COORDTAG=CoordServ AMBROSIA_IMMORTALCOORDINATOR_LOG=$slog \
|
||||
runAmbrosiaService.sh ./Server/publish/Server --rp $PORT4 --sp $PORT3 -j $CLIENTNAME -s $SERVERNAME -n 1 -c &
|
||||
set +x
|
||||
pid_server=$!
|
||||
|
@ -64,7 +83,7 @@ echo
|
|||
echo "PTI: Launching Job now:"
|
||||
set -x
|
||||
AMBROSIA_INSTANCE_NAME=$CLIENTNAME AMBROSIA_IMMORTALCOORDINATOR_PORT=$CRAPORT2 \
|
||||
COORDTAG=CoordCli AMBROSIA_IMMORTALCOORDINATOR_LOG=./job.log \
|
||||
COORDTAG=CoordCli AMBROSIA_IMMORTALCOORDINATOR_LOG=$jlog \
|
||||
runAmbrosiaService.sh ./Client/publish/Job --rp $PORT2 --sp $PORT1 -j $CLIENTNAME -s $SERVERNAME --mms 65536 -n 2 -c
|
||||
set +x
|
||||
|
||||
|
@ -78,5 +97,6 @@ echo "Attempt a cleanup of our table metadata:"
|
|||
set -x
|
||||
UnsafeDeregisterInstance $CLIENTNAME || true
|
||||
UnsafeDeregisterInstance $SERVERNAME || true
|
||||
rm $slog $jlog
|
||||
set +x
|
||||
echo "All done."
|
||||
|
|
111
README.md
111
README.md
|
@ -14,7 +14,7 @@ dramatically lowers development and deployment costs and time to
|
|||
market by automatically providing recovery and high availability.
|
||||
|
||||
Today's datacenter oriented applications, which include most popular
|
||||
services running in Azure today, are composed of highly complex,
|
||||
services running in the cloud today, are composed of highly complex,
|
||||
distributed software stacks. For instance, they typically incorporate
|
||||
Event Hub or Kafka to robustly journal input and interactions for
|
||||
recoverability, log important information to stores like Azure blobs
|
||||
|
@ -26,8 +26,51 @@ service code.
|
|||
In contrast, Ambrosia automatically gives programmers recoverability,
|
||||
high availability, debuggability, upgradability, and exactly once
|
||||
execution, without requiring developers to weave together such complex
|
||||
systems, or use overly expensive mechanisms. Check out the overview
|
||||
deck linked to the left to learn more or email us.
|
||||
systems, or use overly expensive mechanisms.
|
||||
|
||||
To learn more about Ambrosia's implementation and performance you can read our [whitepaper](https://www.microsoft.com/en-us/research/publication/a-m-b-r-o-s-i-a-providing-performant-virtual-resiliency-for-distributed-applications/).
|
||||
|
||||
Table of Contents
|
||||
-----------
|
||||
* [AMBROSIA Concepts](#ambrosia-concepts)
|
||||
* [How it works](#how-it-works)
|
||||
* [Features](#features)
|
||||
* [Getting started]()
|
||||
* [Windows]()
|
||||
* [Kubernetes]()
|
||||
* [Reference](#reference)
|
||||
* [Language Support](#language-support)
|
||||
* [Usage](#usage)
|
||||
|
||||
## AMBROSIA Concepts
|
||||
|
||||
### Virtual Resiliency
|
||||
> *Virtual Resiliency* is a mechanism in a (possibly distributed) programming and execution environment, typically employing a log, which exploits the replayably deterministic nature and serializability of an application to automatically mask failure.
|
||||
|
||||
We use the term virtual resiliency to describe the mechanism in AMBROSIA that allows programmers to write their applications in a failure oblivious way, removing the need for application writers to write logic for recovery or state protection. Data processing systems, which typically express their queries in SQL variants, have provided their query writers virtual resiliency for decades. Map-reduce systems, which don’t necessarily use SQL, also provide this capability. Note that in all these cases, this feature leverages the ability to deterministically replay, like AMBROSIA.
|
||||
|
||||
### Deterministic Replayability
|
||||
In order to achieve virtual resiliency through AMBROSIA, applications but uphold the following contract: from some initial state, any execution of the same requests in the same order results in both the *same final state*, as well as the *same outgoing requests in the same order*.
|
||||
|
||||
### Immortals
|
||||
The basic building blocks of AMBROSIA are *Immortals*, reliable distributed objects that communicate through RPCs. An Immortal defines a set of persistent state and a set of RPC handlers that operate on that state. An *instance* of an Immortal is a named entity that maintains state and executes RPC handlers according to the Immortal's definition. An AMBROSIA application often has multiple instances of the same Immortal; for example, an application may define a single "job" Immortal for running a data-processing job and run multiple instances of that job operating on different data sets.
|
||||
|
||||
## How it works
|
||||
The figure below outlines the basic architecture of an AMBROSIA application, showing two communicating AMBROSIA services, called Immortals. Each inner box in the figure represents a separate process running as part of the Immortal. Each instance of an Immortal exists as a software object and thread of control running inside of an application process. An Immortal instance communicates with other Immortal instances through an *Immortal Coordinator* process, which durably logs the instance's RPCs and encapsulates the low-level networking required to send RPCs. The position of requests in the log determines the order in which they are submitted to the application process for execution and then re-execution upon recovery.
|
||||
|
||||
![Ambrosia Architecture](Architecture.svg)
|
||||
|
||||
In addition, the language specific AMBROSIA binding provides a state serializer. To avoid replaying from the start of the service during recovery, the Immortal Coordinator occasionally checkpoints the state of the Immortal, which includes the application state. The way this serialization is provided can vary from language to language, or even amongst bindings for the same language.
|
||||
|
||||
## Features
|
||||
Here is a list of features that AMBROSIA provides to application developers and deployers:
|
||||
|
||||
* Register Instance, Add Replica
|
||||
* Debug Instance
|
||||
* Active Active
|
||||
* Live Upgrades, Test Upgrades
|
||||
* RPC
|
||||
* Asynchronous RPC (beta)
|
||||
|
||||
Quick Start: Fetch a binary distribution
|
||||
----------------------------------------
|
||||
|
@ -51,3 +94,65 @@ Running a Sample
|
|||
----------------
|
||||
|
||||
FINISHME - AmbrosiaDocs.md content will move here!!
|
||||
|
||||
## Reference
|
||||
|
||||
### Language Support
|
||||
AMBROSIA currently supports C# on both .NET Core and .NET Framework. We plan to exand this support with AMBROSIA bindings for other languages in the future.
|
||||
|
||||
### Usage
|
||||
```
|
||||
Usage: Ambrosia.exe RegisterInstance [OPTIONS]
|
||||
Options:
|
||||
-i, --instanceName=VALUE The instance name [REQUIRED].
|
||||
--rp, --receivePort=VALUE
|
||||
The service receive from port [REQUIRED].
|
||||
--sp, --sendPort=VALUE The service send to port. [REQUIRED]
|
||||
-l, --log=VALUE The service log path.
|
||||
--cs, --createService=VALUE
|
||||
[A - AutoRecovery | N - NoRecovery | Y -
|
||||
AlwaysRecover].
|
||||
--ps, --pauseAtStart Is pause at start enabled.
|
||||
--npl, --noPersistLogs Is persistent logging disabled.
|
||||
--lts, --logTriggerSize=VALUE
|
||||
Log trigger size (in MBs).
|
||||
--aa, --activeActive Is active-active enabled.
|
||||
--cv, --currentVersion=VALUE
|
||||
The current version #.
|
||||
--uv, --upgradeVersion=VALUE
|
||||
The upgrade version #.
|
||||
-h, --help show this message and exit
|
||||
Usage: Ambrosia.exe AddReplica [OPTIONS]
|
||||
Options:
|
||||
-r, --replicaNum=VALUE The replica # [REQUIRED].
|
||||
-i, --instanceName=VALUE The instance name [REQUIRED].
|
||||
--rp, --receivePort=VALUE
|
||||
The service receive from port [REQUIRED].
|
||||
--sp, --sendPort=VALUE The service send to port. [REQUIRED]
|
||||
-l, --log=VALUE The service log path.
|
||||
--cs, --createService=VALUE
|
||||
[A - AutoRecovery | N - NoRecovery | Y -
|
||||
AlwaysRecover].
|
||||
--ps, --pauseAtStart Is pause at start enabled.
|
||||
--npl, --noPersistLogs Is persistent logging disabled.
|
||||
--lts, --logTriggerSize=VALUE
|
||||
Log trigger size (in MBs).
|
||||
--aa, --activeActive Is active-active enabled.
|
||||
--cv, --currentVersion=VALUE
|
||||
The current version #.
|
||||
--uv, --upgradeVersion=VALUE
|
||||
The upgrade version #.
|
||||
-h, --help show this message and exit
|
||||
Usage: Ambrosia.exe DebugInstance [OPTIONS]
|
||||
Options:
|
||||
-i, --instanceName=VALUE The instance name [REQUIRED].
|
||||
--rp, --receivePort=VALUE
|
||||
The service receive from port [REQUIRED].
|
||||
--sp, --sendPort=VALUE The service send to port. [REQUIRED]
|
||||
-l, --log=VALUE The service log path.
|
||||
-c, --checkpoint=VALUE The checkpoint # to load.
|
||||
--cv, --currentVersion=VALUE
|
||||
The version # to debug.
|
||||
--tu, --testingUpgrade Is testing upgrade.
|
||||
-h, --help show this message and exit
|
||||
```
|
|
@ -18,6 +18,33 @@ else
|
|||
exit 1
|
||||
fi
|
||||
|
||||
# Helpers
|
||||
# ------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
# Compute the relative path to A starting from directory B
|
||||
# Output the resulting relative path to stdout.
|
||||
if which realpath 2>&1 >/dev/null ; then
|
||||
|
||||
function getrelative() {
|
||||
realpath "$1" --relative-to="$2"
|
||||
}
|
||||
|
||||
elif which python 2>&1 >/dev/null ; then
|
||||
|
||||
function getrelative() {
|
||||
python -c "import os,sys;print(os.path.relpath(*(sys.argv[1:])))" "$1" "$2"
|
||||
}
|
||||
|
||||
# elif which perl; then
|
||||
else
|
||||
echo "ERROR $0: can't find an easy way to compute relative paths on this system."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ------------------------------------------------------------
|
||||
|
||||
echo "Begin script in mode = $mode"
|
||||
|
||||
cd `dirname $0`/../bin
|
||||
|
@ -57,11 +84,9 @@ for dir in $secondary; do
|
|||
symlink)
|
||||
while read f; do
|
||||
echo -ne "."
|
||||
# echo "ln -sf $relative $f"
|
||||
# Requires realpath from GNU coreutils:
|
||||
dirof=`dirname $f`
|
||||
relative=`realpath ../runtime/$f --relative-to=$dirof`
|
||||
ln -sf $relative $f
|
||||
relativepath=$(getrelative "../runtime/$f" "$dirof")
|
||||
ln -sf $relativepath $f
|
||||
done < $dups
|
||||
echo
|
||||
;;
|
||||
|
@ -109,11 +134,12 @@ else
|
|||
cd "$bindir/$dir"
|
||||
mv -n * ..
|
||||
done
|
||||
|
||||
echo
|
||||
echo "After squishing, these files left behind / conflicting:"
|
||||
echo "-------------------------------------------------------"
|
||||
cd "$bindir"
|
||||
find $secondary
|
||||
echo "-------------------------------------------------------"
|
||||
echo "Every one of these represents a risk of undefined behavior!"
|
||||
echo
|
||||
fi
|
||||
|
|
|
@ -79,6 +79,33 @@ fi
|
|||
# Helper functions
|
||||
# --------------------------------------------------
|
||||
|
||||
# Global variable set below:
|
||||
tail_pid=""
|
||||
coord_pid=""
|
||||
app_pid=""
|
||||
keep_monitoring=""
|
||||
|
||||
_normal_cleanup() {
|
||||
kill -TERM "$coord_pid" 2>/dev/null || true
|
||||
kill -TERM "$tail_pid" 2>/dev/null || true
|
||||
kill -TERM "$app_pid" 2>/dev/null || true
|
||||
rm -f "$keep_monitoring" 2>/dev/null || true
|
||||
}
|
||||
|
||||
_unexpected_cleanup() {
|
||||
trap '' EXIT # some shells will call EXIT after the INT handler
|
||||
if [ ${$1:+defined} ];
|
||||
then local WHCH="($1)"
|
||||
else local WHCH=""
|
||||
fi
|
||||
echo "$0: Exiting script abnormally! Cleaning up. $WHCH"
|
||||
_normal_cleanup
|
||||
echo "$0: Done with cleanup."
|
||||
}
|
||||
|
||||
trap _normal_cleanup EXIT
|
||||
trap _unexpected_cleanup TERM INT QUIT
|
||||
|
||||
function tag_stdin() {
|
||||
local MSG=$1
|
||||
# A complicated but full-proof bash method of line-by-line reading:
|
||||
|
@ -87,13 +114,10 @@ function tag_stdin() {
|
|||
done
|
||||
}
|
||||
|
||||
# Global variable set below:
|
||||
tail_pid=""
|
||||
|
||||
function tail_tagged() {
|
||||
local MSG=$1
|
||||
local FILE=$2
|
||||
(tail -F "$FILE" | tag_stdin $MSG) &
|
||||
tail -F "$FILE" | tag_stdin $MSG &
|
||||
tail_pid=$!
|
||||
}
|
||||
|
||||
|
@ -125,8 +149,10 @@ function start_immortal_coordinator() {
|
|||
touch "$COORDLOG"
|
||||
fi
|
||||
echo " $TAG Redirecting output to: $COORDLOG"
|
||||
|
||||
if which rotatelogs; then
|
||||
|
||||
# OPTION (1): Bound logs, but complicated.
|
||||
# ----------------------------------------
|
||||
if which rotatelogs >/dev/null ; then
|
||||
# Bound the total amount of output used by the ImmortalCoordinator log:
|
||||
ImmortalCoordinator $* 2>&1 | rotatelogs -f -t "$COORDLOG" 10M &
|
||||
coord_pid=$!
|
||||
|
@ -135,10 +161,14 @@ function start_immortal_coordinator() {
|
|||
ImmortalCoordinator $* >>"$COORDLOG" 2>&1 &
|
||||
coord_pid=$!
|
||||
fi
|
||||
|
||||
if ! [[ ${AMBROSIA_SILENT_COORDINATOR:+defined} ]]; then
|
||||
tail_tagged "$COORDTAG" "$COORDLOG"
|
||||
fi
|
||||
# ----------------------------------------
|
||||
# OPTION (2) Don't bound coordinator log on disk. Keep it simple:
|
||||
# ImmortalCoordinator $* 2>&1 | tee "$COORDLOG" &
|
||||
# coord_pid=$!
|
||||
|
||||
while ! grep -q "Ready" "$COORDLOG" && kill -0 $coord_pid 2>/dev/null ;
|
||||
do sleep 2; done
|
||||
|
||||
|
@ -154,6 +184,9 @@ function start_immortal_coordinator() {
|
|||
echo " $TAG Coordinator looks ready."
|
||||
}
|
||||
|
||||
# Script main body:
|
||||
# --------------------------------------------------------------------------------
|
||||
|
||||
# Health monitoring. This is an example of AMBROSIA required practice:
|
||||
# the coordinator and application are bound together, if one dies the
|
||||
# other must (as though they were one process.)
|
||||
|
|
|
@ -17,6 +17,14 @@ fi
|
|||
# Set up common definitions.
|
||||
source Scripts/ci_common_defs.sh
|
||||
|
||||
function check_az_storage_and_bail() {
|
||||
echo
|
||||
echo "All builds completed. Proceeding to running system tests."
|
||||
if ! [[ ${AZURE_STORAGE_CONN_STRING:+defined} ]]; then
|
||||
echo "AZURE_STORAGE_CONN_STRING not defined, so not attempting runnning system tests."
|
||||
exit 0
|
||||
fi
|
||||
}
|
||||
|
||||
case $mode in
|
||||
docker)
|
||||
|
@ -25,10 +33,19 @@ case $mode in
|
|||
# When we are trying to run tests we don't really want the tarball:
|
||||
DONT_BUILD_TARBALL=1 ./build_docker_images.sh
|
||||
|
||||
check_az_storage_and_bail
|
||||
|
||||
# APPLICATION 1: PTI
|
||||
./Scripts/internal/run_linux_PTI_docker.sh
|
||||
# ----------------------------------------
|
||||
./Scripts/internal/run_linux_PTI_docker.sh
|
||||
|
||||
# Application 2: NativeService
|
||||
# ----------------------------------------
|
||||
# docker --env AZURE_STORAGE_CONN_STRING="${AZURE_STORAGE_CONN_STRING}" --rm \
|
||||
# ambrosia-nativeapp ./run_test_in_one_machine.sh
|
||||
|
||||
;;
|
||||
|
||||
|
||||
nodocker)
|
||||
|
||||
echo "Executing raw-Linux, non-Docker build."
|
||||
|
@ -39,19 +56,13 @@ case $mode in
|
|||
# ----------------------------------------
|
||||
cd "$AMBROSIA_ROOT"/InternalImmortals/PerformanceTestInterruptible
|
||||
./build_dotnetcore.sh
|
||||
|
||||
if [[ ${AZURE_STORAGE_CONN_STRING:+defined} ]]; then
|
||||
echo
|
||||
echo "All builds completed. Attempt to run a test."
|
||||
./run_small_PTI_and_shutdown.sh $INSTPREF
|
||||
else
|
||||
echo "AZURE_STORAGE_CONN_STRING not defined, so not attempting PTI test."
|
||||
fi
|
||||
|
||||
check_az_storage_and_bail
|
||||
./run_small_PTI_and_shutdown.sh $INSTPREF
|
||||
|
||||
# Application 2: ...
|
||||
# ----------------------------------------
|
||||
|
||||
cd "$AMBROSIA_ROOT"
|
||||
|
||||
|
||||
;;
|
||||
|
||||
*)
|
||||
|
|
|
@ -40,17 +40,20 @@ echo
|
|||
$DOCKER build -t ${TAG1A} .
|
||||
|
||||
if ! [[ ${DONT_BUILD_RELEASE_IMAGE:+defined} ]]; then
|
||||
echo;echo "Building Release Image: $TAG1B"; echo
|
||||
$DOCKER build -f Dockerfile.release -t ${TAG1B} .
|
||||
fi
|
||||
|
||||
if ! [[ ${DONT_BUILD_APP_IMAGES:+defined} ]]; then
|
||||
|
||||
if ! [[ ${DONT_BUILD_PTI_IMAGE:+defined} ]]; then
|
||||
if ! [[ ${DONT_BUILD_PTI_IMAGE:+defined} ]]; then
|
||||
echo;echo "Building App Image: $TAG2"; echo
|
||||
cd "$AMBROSIA_ROOT"/InternalImmortals/PerformanceTestInterruptible
|
||||
$DOCKER build -t ${TAG2} .
|
||||
cd "$AMBROSIA_ROOT"
|
||||
fi
|
||||
if ! [[ ${DONT_BUILD_NATIVE_IMAGE:+defined} ]]; then
|
||||
if ! [[ ${DONT_BUILD_NATIVE_IMAGE:+defined} ]]; then
|
||||
echo;echo "Building App Image: $TAG3"; echo
|
||||
cd "$AMBROSIA_ROOT"/InternalImmortals/NativeService
|
||||
docker build -t ${TAG3} .
|
||||
cd "$AMBROSIA_ROOT"
|
||||
|
|
|
@ -126,8 +126,7 @@ echo "--------------------------------------------------------------"
|
|||
if [ ${OS:+defined} ] && [ "$OS" == "Windows_NT" ];
|
||||
then ./Scripts/dedup_bindist.sh squish
|
||||
elif [ "$UNAME" == Darwin ];
|
||||
then ./Scripts/dedup_bindist.sh squish
|
||||
# FIXME ^ should symlink, but "realpath" is needed.
|
||||
then ./Scripts/dedup_bindist.sh symlink
|
||||
else ./Scripts/dedup_bindist.sh symlink
|
||||
fi
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
# Securing Ambrosia Communications
|
||||
|
||||
This document describes how deployers of the Immortal Coordinator may secure all communications between coordinators. Immortal
|
||||
Coordinators communicate with each using a reliable network connection library called [CRA](https://github.com/Microsoft/CRA).
|
||||
CRA uses standard unsecured TCP connections by default. If the deployer wants to secure all communications between Immortal
|
||||
Coordinators, they can do so by writing a _communication wrapper_ and providing this information to the coordinator. The deployer
|
||||
need to provide two pieces of information related to securing connections: an assemby name and an assembly class name. Together,
|
||||
this information points to an assembly that implements an interface that is called whenever a TCP connection is created between two
|
||||
Immortal Coordinators. The interface is called `ISecureStreamConnectionDescriptor`, and is shown [here](https://github.com/Microsoft/CRA/blob/master/src/CRA.ClientLibrary/Security/ISecureStreamConnectionDescriptor.cs).
|
||||
|
||||
For example, suppose we wish to use a dummy security wrapper that simply passes the stream without securing it. See
|
||||
[here](https://github.com/Microsoft/CRA/blob/master/src/CRA.ClientLibrary/Security/DummySecureStreamConnectionDescriptor.cs)
|
||||
for such an example. We would provide the information to Amborosia when invoking the Immortal Coordinator, as follows.
|
||||
|
||||
dotnet ImmortalCoordinator.dll --instanceName=client1 --port=1500 -an=CRA.ClientLibrary -ac=CRA.ClientLibrary.DummySecureStreamConnectionDescriptor
|
||||
dotnet ImmortalCoordinator.dll --instanceName=server1 --port=2500 -an=CRA.ClientLibrary -ac=CRA.ClientLibrary.DummySecureStreamConnectionDescriptor
|
||||
|
||||
Another example of a security wrapper is provided [here](https://github.com/Microsoft/CRA/blob/master/src/CRA.ClientLibrary/Security/SampleSecureStreamConnectionDescriptor.cs).
|
||||
This example uses an X509 Certificate to create SslStream wrappers around the TCP connections.
|
Загрузка…
Ссылка в новой задаче