зеркало из https://github.com/microsoft/AMBROSIA.git
Merge branch 'master' into ryan/native
This commit is contained in:
Коммит
5d47f2b38c
|
@ -471,7 +471,7 @@ namespace Ambrosia
|
|||
else
|
||||
{
|
||||
// writing a mixed batch
|
||||
outputStream.WriteInt(bytesInBatchData + 1 + 2 * StreamCommunicator.IntSize(numRPCs));
|
||||
outputStream.WriteInt(bytesInBatchData + 1 + StreamCommunicator.IntSize(numRPCs) + StreamCommunicator.IntSize(numReplayableMessagesToSend));
|
||||
outputStream.WriteByte(AmbrosiaRuntime.CountReplayableRPCBatchByte);
|
||||
outputStream.WriteInt(numRPCs);
|
||||
outputStream.WriteInt(numReplayableMessagesToSend);
|
||||
|
@ -564,7 +564,8 @@ namespace Ambrosia
|
|||
for (int i = 0; i < skipEvents; i++)
|
||||
{
|
||||
int eventSize = curBuffer.PageBytes.ReadBufferedInt(bufferPos);
|
||||
if (curBuffer.PageBytes[bufferPos + StreamCommunicator.IntSize(eventSize) + 1] != (byte)RpcTypes.RpcType.Impulse)
|
||||
var methodID = curBuffer.PageBytes.ReadBufferedInt(bufferPos + StreamCommunicator.IntSize(eventSize) + 2);
|
||||
if (curBuffer.PageBytes[bufferPos + StreamCommunicator.IntSize(eventSize) + 2 + StreamCommunicator.IntSize(methodID)] != (byte)RpcTypes.RpcType.Impulse)
|
||||
{
|
||||
curBuffer.UnsentReplayableMessages--;
|
||||
}
|
||||
|
@ -778,7 +779,8 @@ namespace Ambrosia
|
|||
for (var i = currentHead.LowestSeqNo; i <= trimSeqNo; i++ )
|
||||
{
|
||||
int eventSize = currentHead.PageBytes.ReadBufferedInt(readBufferPos);
|
||||
if (currentHead.PageBytes[readBufferPos + StreamCommunicator.IntSize(eventSize) + 1] != (byte)RpcTypes.RpcType.Impulse)
|
||||
var methodID = currentHead.PageBytes.ReadBufferedInt(readBufferPos + StreamCommunicator.IntSize(eventSize) + 2);
|
||||
if (currentHead.PageBytes[readBufferPos + StreamCommunicator.IntSize(eventSize) + 2 + StreamCommunicator.IntSize(methodID)] != (byte)RpcTypes.RpcType.Impulse)
|
||||
{
|
||||
currentHead.TotalReplayableMessages--;
|
||||
}
|
||||
|
@ -806,7 +808,8 @@ namespace Ambrosia
|
|||
for (int i = 0; i < numMessagesOnPage; i++)
|
||||
{
|
||||
int eventSize = curBuffer.PageBytes.ReadBufferedInt(readBufferPos);
|
||||
if (curBuffer.PageBytes[readBufferPos + StreamCommunicator.IntSize(eventSize) + 1] != (byte)RpcTypes.RpcType.Impulse)
|
||||
var methodID = curBuffer.PageBytes.ReadBufferedInt(readBufferPos + StreamCommunicator.IntSize(eventSize) + 2);
|
||||
if (curBuffer.PageBytes[readBufferPos + StreamCommunicator.IntSize(eventSize) + 2 + StreamCommunicator.IntSize(methodID)] != (byte)RpcTypes.RpcType.Impulse)
|
||||
{
|
||||
// Copy event over to new page bytes
|
||||
pageWriteStream.Write(curBuffer.PageBytes, readBufferPos, eventSize + StreamCommunicator.IntSize(eventSize));
|
||||
|
@ -2744,13 +2747,15 @@ namespace Ambrosia
|
|||
// lock to avoid conflict and ensure maximum memory cleaning during replay. No possible conflict during primary operation
|
||||
lock (_shuffleOutputRecord)
|
||||
{
|
||||
// Buffer the output if it is at or beyond the replay or trim point (during recovery). If we are recovering, this may not be the case.
|
||||
// Buffer the output if it is at or beyond the replay or trim point (during recovery).
|
||||
if ((_shuffleOutputRecord.LastSeqNoFromLocalService + 1 >= _shuffleOutputRecord.ReplayFrom) &&
|
||||
(_shuffleOutputRecord.LastSeqNoFromLocalService + 1 >= _shuffleOutputRecord.TrimTo))
|
||||
(_shuffleOutputRecord.LastSeqNoFromLocalService + 1 >= _shuffleOutputRecord.ReplayableTrimTo))
|
||||
{
|
||||
var writablePage = _shuffleOutputRecord.BufferedOutput.GetWritablePage(totalSize, _shuffleOutputRecord.LastSeqNoFromLocalService + 1);
|
||||
writablePage.HighestSeqNo = _shuffleOutputRecord.LastSeqNoFromLocalService + 1;
|
||||
if (RpcBuffer.Buffer[restOfRPCOffset] != (byte) RpcTypes.RpcType.Impulse)
|
||||
|
||||
var methodID = RpcBuffer.Buffer.ReadBufferedInt(restOfRPCOffset + 1);
|
||||
if (RpcBuffer.Buffer[restOfRPCOffset + 1 + StreamCommunicator.IntSize(methodID)] != (byte) RpcTypes.RpcType.Impulse)
|
||||
{
|
||||
writablePage.UnsentReplayableMessages++;
|
||||
writablePage.TotalReplayableMessages++;
|
||||
|
@ -2818,7 +2823,7 @@ namespace Ambrosia
|
|||
var sizeBytes = inputFlexBuffer.LengthLength;
|
||||
// Get the seqNo of the replay/filter point
|
||||
var commitSeqNo = StreamCommunicator.ReadBufferedLong(inputFlexBuffer.Buffer, sizeBytes + 1);
|
||||
var commitSeqNoReplayable = StreamCommunicator.ReadBufferedLong(inputFlexBuffer.Buffer, sizeBytes + 1);
|
||||
var commitSeqNoReplayable = StreamCommunicator.ReadBufferedLong(inputFlexBuffer.Buffer, sizeBytes + 1 + StreamCommunicator.LongSize(commitSeqNo));
|
||||
inputFlexBuffer.ResetBuffer();
|
||||
if (outputConnectionRecord.ConnectingAfterRestart)
|
||||
{
|
||||
|
@ -2829,6 +2834,7 @@ namespace Ambrosia
|
|||
// Don't think I actually need this lock, but can't hurt and shouldn't affect perf.
|
||||
outputConnectionRecord.BufferedOutput.AcquireTrimLock(2);
|
||||
outputConnectionRecord.BufferedOutput.RebaseSeqNosInBuffer(commitSeqNo, commitSeqNoReplayable);
|
||||
outputConnectionRecord.LastSeqNoFromLocalService += commitSeqNo - commitSeqNoReplayable;
|
||||
outputConnectionRecord.ConnectingAfterRestart = false;
|
||||
outputConnectionRecord.BufferedOutput.ReleaseTrimLock();
|
||||
}
|
||||
|
@ -3126,7 +3132,7 @@ namespace Ambrosia
|
|||
if (commitSeqNo > outputConnectionRecord.TrimTo && !outputConnectionRecord.WillResetConnection && !outputConnectionRecord.ConnectingAfterRestart)
|
||||
{
|
||||
outputConnectionRecord.TrimTo = Math.Max(outputConnectionRecord.TrimTo, commitSeqNo);
|
||||
outputConnectionRecord.ReplayableTrimTo = Math.Max(outputConnectionRecord.TrimTo, replayableCommitSeqNo);
|
||||
outputConnectionRecord.ReplayableTrimTo = Math.Max(outputConnectionRecord.ReplayableTrimTo, replayableCommitSeqNo);
|
||||
if (outputConnectionRecord.ControlWorkQ.IsEmpty)
|
||||
{
|
||||
outputConnectionRecord.ControlWorkQ.Enqueue(-2);
|
||||
|
@ -3153,7 +3159,8 @@ namespace Ambrosia
|
|||
switch (inputFlexBuffer.Buffer[sizeBytes])
|
||||
{
|
||||
case RPCByte:
|
||||
if (inputFlexBuffer.Buffer[sizeBytes + 1] != (byte) RpcTypes.RpcType.Impulse)
|
||||
var methodID = inputFlexBuffer.Buffer.ReadBufferedInt(sizeBytes + 2);
|
||||
if (inputFlexBuffer.Buffer[sizeBytes + 2 + StreamCommunicator.IntSize(methodID)] != (byte) RpcTypes.RpcType.Impulse)
|
||||
{
|
||||
inputRecord.LastProcessedReplayableID++;
|
||||
}
|
||||
|
|
|
@ -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,8 @@
|
|||
# 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.
|
||||
|
||||
See the [CONTRIBUTING](./CONTRIBUTING) folder for information and
|
||||
documentation for new contributors to the project, or those adding
|
||||
AMBROSIA language bindings for additional languages.
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
# Perform the code-generation step for this example application.
|
||||
|
||||
if (-not ( $env:AMBVARIANT )) {
|
||||
$env:AMBVARIANT="x64\Debug\netcoreapp2.0"
|
||||
if ( $env:AMBVARIANTCORE ) {
|
||||
$AMBVARIANTCORE=$env:AMBVARIANTCORE
|
||||
} else {
|
||||
$AMBVARIANTCORE = "x64\Debug\netcoreapp2.0"
|
||||
}
|
||||
|
||||
# Build the API projects
|
||||
|
@ -17,9 +19,8 @@ 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: $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\$AMBVARIANTCORE\AmbrosiaCS.dll CodeGen -a=API\bin\$AMBVARIANTCORE\ServerAPI.dll -a=IJob\bin\$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\$AMBVARIANTCORE\AmbrosiaCS.dll" CodeGen -a="API\bin\$AMBVARIANTCORE\ServerAPI.dll" -a="IJob\bin\$AMBVARIANTCORE\IJob.dll" -o="PTIAmbrosiaGeneratedAPINetCore" -f="netcoreapp2.0" -b="CodeGenDependencies\netcoreapp2.0"
|
||||
|
|
|
@ -1,21 +1,23 @@
|
|||
# Perform the code-generation step for this example application.
|
||||
|
||||
if (-not ( $env:AMBVARIANT )) {
|
||||
$env:AMBVARIANT="x64\Debug\net46"
|
||||
if ( $env:AMBVARIANT ) {
|
||||
$AMBVARIANT = $env:AMBVARIANT
|
||||
} else {
|
||||
$AMBVARIANT="x64\Debug\net46"
|
||||
}
|
||||
|
||||
# Create the dependencies folder
|
||||
New-Item -ItemType Directory -Force -Path "CodeGenDependencies\net46\"
|
||||
Get-ChildItem "CodeGenDependencies\net46\" | Remove-Item
|
||||
Copy-Item "API\bin\$env:AMBVARIANT\*" -Force -Destination "CodeGenDependencies\net46\"
|
||||
Copy-Item "API\bin\$AMBVARIANT\*" -Force -Destination "CodeGenDependencies\net46\"
|
||||
# DANGER, WARNING, FIXME: it is UNSAFE to MERGE the outputs of two publish directories:
|
||||
Copy-Item "IJob\bin\$env:AMBVARIANT\*" -Force -Destination "CodeGenDependencies\net46\"
|
||||
Copy-Item "IJob\bin\$AMBVARIANT\*" -Force -Destination "CodeGenDependencies\net46\"
|
||||
|
||||
Copy-Item "..\..\Clients\CSharp\AmbrosiaCS\AmbrosiaCS.csproj" -Force -Destination "CodeGenDependencies\net46\"
|
||||
|
||||
Write-Host "Using variant of AmbrosiaCS.exe: $env:AMBVARIANT"
|
||||
Write-Host "Using variant of AmbrosiaCS.exe: $AMBVARIANT"
|
||||
|
||||
Write-Host "Executing codegen command: ..\..\Clients\CSharp\AmbrosiaCS\bin\$env:AMBVARIANT\AmbrosiaCS.exe CodeGen -a=API\bin\$env:AMBVARIANT\ServerAPI.dll -a=IJob\bin\$env:AMBVARIANT\IJob.dll -o=PTIAmbrosiaGeneratedAPINet46 -f=net46 -b=CodeGenDependencies\net46"
|
||||
Write-Host "Executing codegen command: ..\..\Clients\CSharp\AmbrosiaCS\bin\$AMBVARIANT\AmbrosiaCS.exe CodeGen -a=API\bin\$AMBVARIANT\ServerAPI.dll -a=IJob\bin\$AMBVARIANT\IJob.dll -o=PTIAmbrosiaGeneratedAPINet46 -f=net46 -b=CodeGenDependencies\net46"
|
||||
|
||||
# Generate the assemblies, assumes an .exe which is created by a .Net Framework build:
|
||||
& "..\..\Clients\CSharp\AmbrosiaCS\bin\$env:AMBVARIANT\AmbrosiaCS.exe" CodeGen -a="API\bin\$env:AMBVARIANT\ServerAPI.dll" -a="IJob\bin\$env:AMBVARIANT\IJob.dll" -o="PTIAmbrosiaGeneratedAPINet46" -f="net46" -b="CodeGenDependencies\net46"
|
||||
& "..\..\Clients\CSharp\AmbrosiaCS\bin\$AMBVARIANT\AmbrosiaCS.exe" CodeGen -a="API\bin\$AMBVARIANT\ServerAPI.dll" -a="IJob\bin\$AMBVARIANT\IJob.dll" -o="PTIAmbrosiaGeneratedAPINet46" -f="net46" -b="CodeGenDependencies\net46"
|
||||
|
|
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
|
||||
```
|
|
@ -7,12 +7,12 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AmbrosiaLibCS" Version="2018.12.06.3" />
|
||||
<PackageReference Include="AmbrosiaLibCS" Version="2018.12.10.1" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Threading" Version="15.8.192" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\GeneratedSourceFiles\Client1Interfaces\latest\Client1Interfaces.csproj" />
|
||||
<ProjectReference Include="..\GeneratedSourceFiles\ServerInterfaces\latest\ServerInterfaces.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
using Ambrosia;
|
||||
using IClient1;
|
||||
using IServer;
|
||||
using Client1;
|
||||
using Server;
|
||||
using Microsoft.VisualStudio.Threading;
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
@ -9,7 +9,7 @@ using System.Threading.Tasks;
|
|||
namespace Client1
|
||||
{
|
||||
[DataContract]
|
||||
class Client1 : Immortal<IClient1Proxy>, IClient1.IClient1
|
||||
class Client1 : Immortal<IClient1Proxy>, IClient1
|
||||
{
|
||||
[DataMember]
|
||||
private string _serverName;
|
||||
|
@ -22,17 +22,16 @@ namespace Client1
|
|||
_serverName = serverName;
|
||||
}
|
||||
|
||||
public async Task SendMessageAsync(string message)
|
||||
{
|
||||
Console.WriteLine("Sending message to server: " + message);
|
||||
int numMessages = await _server.ReceiveMessageAsync(message);
|
||||
Console.WriteLine("Sent message to server! Server has received " + numMessages + " messages.");
|
||||
}
|
||||
|
||||
protected override async Task<bool> OnFirstStart()
|
||||
{
|
||||
_server = GetProxy<IServerProxy>(_serverName);
|
||||
await thisProxy.SendMessageAsync("Hello world!");
|
||||
_server.ReceiveMessageFork("Hello World 1!");
|
||||
Console.WriteLine("Press any key to continue");
|
||||
Console.ReadKey();
|
||||
_server.ReceiveMessageFork("Hello World 2!");
|
||||
_server.ReceiveMessageFork("Hello World 3!");
|
||||
Console.WriteLine("Press any key to end");
|
||||
Console.ReadKey();
|
||||
Program.finishedTokenQ.Enqueue(0);
|
||||
return true;
|
||||
}
|
||||
|
@ -47,10 +46,10 @@ namespace Client1
|
|||
|
||||
int receivePort = 1001;
|
||||
int sendPort = 1000;
|
||||
string clientInstanceName = "client1";
|
||||
string serverInstanceName = "server1";
|
||||
string clientInstanceName = "jgclient1";
|
||||
string serverInstanceName = "jgserver1";
|
||||
|
||||
using (var c = AmbrosiaFactory.Deploy<IClient1.IClient1>(clientInstanceName, new Client1(serverInstanceName), receivePort, sendPort))
|
||||
using (var c = AmbrosiaFactory.Deploy<IClient1>(clientInstanceName, new Client1(serverInstanceName), receivePort, sendPort))
|
||||
{
|
||||
finishedTokenQ.DequeueAsync().Wait();
|
||||
}
|
||||
|
|
|
@ -7,12 +7,12 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AmbrosiaLibCS" Version="2018.12.6.1" />
|
||||
<PackageReference Include="AmbrosiaLibCS" Version="2018.12.10.1" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Threading" Version="15.8.192" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\GeneratedSourceFiles\Client2Interfaces\latest\Client2Interfaces.csproj" />
|
||||
<ProjectReference Include="..\GeneratedSourceFiles\ServerInterfaces\latest\ServerInterfaces.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -3,14 +3,14 @@ using System.Runtime.Serialization;
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Ambrosia;
|
||||
using IClient2;
|
||||
using IServer;
|
||||
using Client2;
|
||||
using Server;
|
||||
using Microsoft.VisualStudio.Threading;
|
||||
|
||||
namespace Client2
|
||||
{
|
||||
[DataContract]
|
||||
class Client2 : Immortal<IClient2Proxy>, IClient2.IClient2
|
||||
class Client2 : Immortal<IClient2Proxy>, IClient2
|
||||
{
|
||||
[DataMember]
|
||||
private string _serverName;
|
||||
|
@ -23,14 +23,28 @@ namespace Client2
|
|||
_serverName = serverName;
|
||||
}
|
||||
|
||||
public void IngressKeyboardInput(string input)
|
||||
void InputLoop()
|
||||
{
|
||||
thisProxy.ReceiveKeyboardInputFork(input);
|
||||
while (true)
|
||||
{
|
||||
Console.Write("Enter a message (hit ENTER to send): ");
|
||||
string input = Console.ReadLine();
|
||||
thisProxy.ReceiveKeyboardInputFork(input);
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void BecomingPrimary()
|
||||
{
|
||||
Console.WriteLine("Finished initializing state/recovering");
|
||||
Thread timerThread = new Thread(InputLoop);
|
||||
timerThread.Start();
|
||||
}
|
||||
|
||||
public async Task ReceiveKeyboardInputAsync(string input)
|
||||
{
|
||||
await thisProxy.SendMessageAsync(input);
|
||||
Console.WriteLine("Sending keyboard input {0}", input);
|
||||
_server.ReceiveMessageFork(input);
|
||||
}
|
||||
|
||||
public async Task SendMessageAsync(string message)
|
||||
|
@ -57,20 +71,16 @@ namespace Client2
|
|||
|
||||
int receivePort = 1001;
|
||||
int sendPort = 1000;
|
||||
string clientInstanceName = "client2";
|
||||
string serverInstanceName = "server1";
|
||||
string clientInstanceName = "jgclient1";
|
||||
string serverInstanceName = "jgserver1";
|
||||
|
||||
Client2 client = new Client2(serverInstanceName);
|
||||
using (var c = AmbrosiaFactory.Deploy<IClient2.IClient2>(clientInstanceName, client, receivePort, sendPort))
|
||||
using (var c = AmbrosiaFactory.Deploy<IClient2>(clientInstanceName, client, receivePort, sendPort))
|
||||
{
|
||||
while (finishedTokenQ.IsEmpty)
|
||||
{
|
||||
Console.Write("Enter a message (hit ENTER to send): ");
|
||||
string input = Console.ReadLine();
|
||||
client.IngressKeyboardInput(input);
|
||||
Thread.Sleep(1000);
|
||||
finishedTokenQ.DequeueAsync().Wait();
|
||||
}
|
||||
finishedTokenQ.DequeueAsync().Wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@ $ambrosiaPath="..\.."
|
|||
New-Item -ItemType Directory -Force -Path "CodeGenDependencies\netcoreapp2.0" | Out-Null
|
||||
Get-ChildItem "CodeGenDependencies\netcoreapp2.0\" | Remove-Item
|
||||
|
||||
Copy-Item "..\..\Clients\CSharp\AmbrosiaCS\AmbrosiaCS.csproj" -Force -Destination "CodeGenDependencies\netcoreapp2.0\"
|
||||
|
||||
Write-Host "Using variant of CodeGen.exe: $env:AMBVARIANT"
|
||||
|
||||
Write-Host "Executing codegen command: dotnet $ambrosiaPath\Clients\CSharp\AmbrosiaCS\bin\$env:AMBVARIANT\AmbrosiaCS.dll CodeGen -a=ServerAPI\bin\$env:AMBVARIANT\IServer.dll -o=ServerInterfaces -f=netcoreapp2.0 -b=CodeGenDependencies\netcoreapp2.0"
|
||||
|
@ -20,5 +22,5 @@ Write-Host "Executing codegen command: dotnet $ambrosiaPath\Clients\CSharp\Ambro
|
|||
|
||||
# Generate the assemblies, assumes an .exe which is created by a .Net Framework build:
|
||||
& dotnet $ambrosiaPath\Clients\CSharp\AmbrosiaCS\bin\$env:AMBVARIANT\AmbrosiaCS.dll CodeGen -a="ServerAPI\bin\$env:AMBVARIANT\IServer.dll" -o=ServerInterfaces -f="netcoreapp2.0" -b="CodeGenDependencies\netcoreapp2.0"
|
||||
& dotnet $ambrosiaPath\Clients\CSharp\AmbrosiaCS\bin\$env:AMBVARIANT\AmbrosiaCS.dll CodeGen -a="IClient1\bin\$env:AMBVARIANT\IClient1.dll" -o=Client1Interfaces -f="netcoreapp2.0" -b="CodeGenDependencies\netcoreapp2.0"
|
||||
& dotnet $ambrosiaPath\Clients\CSharp\AmbrosiaCS\bin\$env:AMBVARIANT\AmbrosiaCS.dll CodeGen -a="IClient2\bin\$env:AMBVARIANT\IClient2.dll" -o=Client2Interfaces -f="netcoreapp2.0" -b="CodeGenDependencies\netcoreapp2.0"
|
||||
& dotnet $ambrosiaPath\Clients\CSharp\AmbrosiaCS\bin\$env:AMBVARIANT\AmbrosiaCS.dll CodeGen -a="ServerAPI\bin\$env:AMBVARIANT\IServer.dll" -a="IClient1\bin\$env:AMBVARIANT\IClient1.dll" -o=Client1Interfaces -f="netcoreapp2.0" -b="CodeGenDependencies\netcoreapp2.0"
|
||||
& dotnet $ambrosiaPath\Clients\CSharp\AmbrosiaCS\bin\$env:AMBVARIANT\AmbrosiaCS.dll CodeGen -a="ServerAPI\bin\$env:AMBVARIANT\IServer.dll" -a="IClient2\bin\$env:AMBVARIANT\IClient2.dll" -o=Client2Interfaces -f="netcoreapp2.0" -b="CodeGenDependencies\netcoreapp2.0"
|
|
@ -10,14 +10,25 @@ EndProject
|
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client1", "Client1\Client1.csproj", "{318EC3BE-E578-4779-9800-DB3436F1706C}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ServerInterfaces", "GeneratedSourceFiles\ServerInterfaces\latest\ServerInterfaces.csproj", "{04F60232-F122-47BF-850E-0092742DB33E}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{9180745A-DE7F-40CB-BC48-595057C8D98F} = {9180745A-DE7F-40CB-BC48-595057C8D98F}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client1Interfaces", "GeneratedSourceFiles\Client1Interfaces\latest\Client1Interfaces.csproj", "{625A71B0-DA9E-467F-9744-A4344EA8B6E5}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{8EFAD205-E2BF-46C0-B310-7D023210797F} = {8EFAD205-E2BF-46C0-B310-7D023210797F}
|
||||
{9180745A-DE7F-40CB-BC48-595057C8D98F} = {9180745A-DE7F-40CB-BC48-595057C8D98F}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IClient2", "IClient2\IClient2.csproj", "{975C3389-6CE2-4905-BE58-57FCF29B5D31}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client2", "Client2\Client2.csproj", "{644D897D-1311-4073-9F0C-4197A9719E28}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client2Interfaces", "GeneratedSourceFiles\Client2Interfaces\latest\Client2Interfaces.csproj", "{6E5C78F0-B847-4C22-90B6-FAA96C013609}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{9180745A-DE7F-40CB-BC48-595057C8D98F} = {9180745A-DE7F-40CB-BC48-595057C8D98F}
|
||||
{975C3389-6CE2-4905-BE58-57FCF29B5D31} = {975C3389-6CE2-4905-BE58-57FCF29B5D31}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IClient1", "IClient1\IClient1.csproj", "{8EFAD205-E2BF-46C0-B310-7D023210797F}"
|
||||
EndProject
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
using System;
|
||||
using Ambrosia;
|
||||
|
||||
namespace IClient1
|
||||
namespace Client1
|
||||
{
|
||||
public interface IClient1
|
||||
{
|
||||
void SendMessage(string message);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,4 +7,8 @@
|
|||
<RootNamespace>IClient1</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AmbrosiaLibCS" Version="2018.12.10.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using Ambrosia;
|
||||
using System;
|
||||
|
||||
namespace IClient2
|
||||
namespace Client2
|
||||
{
|
||||
public interface IClient2
|
||||
{
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AmbrosiaLibCS" Version="2018.12.6.1" />
|
||||
<PackageReference Include="AmbrosiaLibCS" Version="2018.12.10.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using Ambrosia;
|
||||
using IServer;
|
||||
using Microsoft.VisualStudio.Threading;
|
||||
using Server;
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Threading;
|
||||
|
@ -11,7 +10,7 @@ namespace Server
|
|||
class Program
|
||||
{
|
||||
[DataContract]
|
||||
sealed class Server : Immortal<IServerProxy>, IServer.IServer
|
||||
sealed class Server : Immortal<IServerProxy>, IServer
|
||||
{
|
||||
[DataMember]
|
||||
int _messagesReceived = 0;
|
||||
|
@ -37,8 +36,8 @@ namespace Server
|
|||
{
|
||||
int receivePort = 2001;
|
||||
int sendPort = 2000;
|
||||
string serviceName = "server1";
|
||||
using (var c = AmbrosiaFactory.Deploy<IServer.IServer>(serviceName, new Server(), receivePort, sendPort))
|
||||
string serviceName = "jgserver1";
|
||||
using (var c = AmbrosiaFactory.Deploy<IServer>(serviceName, new Server(), receivePort, sendPort))
|
||||
{
|
||||
Thread.Sleep(14 * 24 * 3600 * 1000);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AmbrosiaLibCS" Version="2018.12.06.3" />
|
||||
<PackageReference Include="AmbrosiaLibCS" Version="2018.12.10.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using Ambrosia;
|
||||
using System;
|
||||
|
||||
namespace IServer
|
||||
namespace Server
|
||||
{
|
||||
public interface IServer
|
||||
{
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AmbrosiaLibCS" Version="2018.12.06.3" />
|
||||
<PackageReference Include="AmbrosiaLibCS" Version="2018.12.10.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
Загрузка…
Ссылка в новой задаче