v1.3b6
parent
de8a3c799b
commit
602326e415
|
|
@ -6,7 +6,7 @@
|
|||
<META NAME="GENERATOR" CONTENT="NeoOffice/J 1.1 (Unix)">
|
||||
<META NAME="AUTHOR" CONTENT="Robert Adamson">
|
||||
<META NAME="CREATED" CONTENT="20040824;14180000">
|
||||
<META NAME="CHANGED" CONTENT="20050907;17092400">
|
||||
<META NAME="CHANGED" CONTENT="20050919;14362900">
|
||||
<META NAME="DESCRIPTION" CONTENT="NORM Object Functions 42
NORM Object Functions
NORM_OBJECT_STREAM
NORM Sender Functions 19
NORM Sender Functions
">
|
||||
<META NAME="KEYWORDS" CONTENT="norm object value application function ">
|
||||
<STYLE>
|
||||
|
|
@ -51,22 +51,24 @@
|
|||
</TD>
|
||||
<TD WIDTH=371>
|
||||
<P ALIGN=LEFT STYLE="margin-left: 0.86in; margin-top: 0.17in; font-style: normal">
|
||||
<FONT FACE="Helvetica, sans-serif"><FONT SIZE=6 STYLE="font-size: 28pt"><B>NORM<BR>Developer’s
|
||||
<BR>Guide</B></FONT></FONT></P>
|
||||
<FONT FACE="Helvetica, sans-serif"><FONT SIZE=4 STYLE="font-size: 16pt"><B><FONT SIZE=6 STYLE="font-size: 28pt">NORM<BR>Developer’s
|
||||
<BR>Guide<BR></FONT><FONT SIZE=4>(version 1.3b6)</FONT></B></FONT></FONT></P>
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
<H1 CLASS="western">Background</H1>
|
||||
<H1 CLASS="western"><A NAME="Background">Background</A></H1>
|
||||
<P CLASS="western" STYLE="font-style: normal">This document describes
|
||||
an application programming interface (API) for the Nack-Oriented
|
||||
Reliable Multicast (NORM) protocol implementation developed by the
|
||||
United States Naval Research Laboratory (NRL). The NORM protocol
|
||||
provides general purpose reliable data transport for applications
|
||||
wishing to use Internet Protocol (IP) Multicast services for group
|
||||
data delivery. NORM can also support unicast (point-to-point) data
|
||||
an application programming interface (API) for the <FONT COLOR="#0000ff"><U><A HREF="http://norm.pf.itd.nrl.navy.mil/">Nack-Oriented
|
||||
Reliable Multicast (NORM)</A></U></FONT> protocol implementation
|
||||
developed by the United States <FONT COLOR="#0000ff"><U><A HREF="http://www.nrl.navy.mil/">Naval
|
||||
Research Laboratory</A></U></FONT> (NRL). The NORM protocol provides
|
||||
general purpose reliable data transport for applications wishing to
|
||||
use Internet Protocol (IP) Multicast services for group data
|
||||
delivery. NORM can also support unicast (point-to-point) data
|
||||
communication and may be used for such when deemed appropriate. The
|
||||
current NORM protocol specification is given in the Internet
|
||||
Engineering Task Force RFC 3940.</P>
|
||||
current NORM protocol specification is given in the <FONT COLOR="#0000ff"><U><A HREF="http://www.ietf.org/">Internet
|
||||
Engineering Task Force</A></U></FONT> (IETF) <FONT COLOR="#0000ff"><U><A HREF="http://norm.pf.itd.nrl.navy.mil/rfc3940.pdf">RFC
|
||||
3940</A></U></FONT>.</P>
|
||||
<P CLASS="western" STYLE="font-style: normal">The NORM protocol is
|
||||
designed to provide end-to-end reliable transport of bulk data
|
||||
objects or streams over generic IP multicast routing and forwarding
|
||||
|
|
@ -96,32 +98,24 @@ possible group communication paradigms dictate different needs for
|
|||
different applications. Even with NORM, the developer should have a
|
||||
thorough understanding of the specific application's group
|
||||
communication needs.</P>
|
||||
<H1 CLASS="western" ALIGN=CENTER STYLE="page-break-before: always">Table
|
||||
of Contents</H1>
|
||||
<H1 CLASS="western" ALIGN=CENTER STYLE="page-break-before: always"><A NAME="Table
|
||||
of Contents">Table
|
||||
of Contents</A></H1>
|
||||
<DIV ID="Table of Contents1" DIR="LTR">
|
||||
<P STYLE="margin-top: 0.25in; font-style: normal"><FONT FACE="Helvetica, sans-serif"><B>Overview</B></FONT></P>
|
||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>API
|
||||
Initialization</B></FONT></P>
|
||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>Session
|
||||
Creation and Control</B></FONT></P>
|
||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>NORM
|
||||
Data Transport</B></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2>NORM
|
||||
Data Transmission</FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2>NORM
|
||||
Data Reception</FONT></P>
|
||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>API
|
||||
Event Notification</B></FONT></P>
|
||||
<P STYLE="margin-top: 0.25in; font-style: normal"><FONT FACE="Helvetica, sans-serif"><B>Build
|
||||
Notes</B></FONT></P>
|
||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>Unix
|
||||
Platforms</B></FONT></P>
|
||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>Win32/WiNCE
|
||||
Platforms</B></FONT></P>
|
||||
<P STYLE="margin-top: 0.25in; font-style: normal"><FONT FACE="Helvetica, sans-serif"><B>API
|
||||
Reference</B></FONT></P>
|
||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>API
|
||||
Variable Types and Constants</B></FONT></P>
|
||||
<P STYLE="margin-top: 0.25in; font-style: normal"><BR>
|
||||
</P>
|
||||
<P STYLE="margin-top: 0.25in; font-style: normal"><FONT FACE="Helvetica, sans-serif"><B><A HREF="#Overview">Overview</A></B></FONT></P>
|
||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B><A HREF="#API Initialization">API Initialization</A></B></FONT></P>
|
||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B><A HREF="#Session Creation and Control">Session Creation and Control</A></B></FONT></P>
|
||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B><A HREF="#Data Transport">Data Transport</A></B></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#Data Transmission">Data Transmission</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#Data Reception">Data Reception</A></FONT></P>
|
||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B><A HREF="#API Event Notification">API Event Notification</A></B></FONT></P>
|
||||
<P STYLE="margin-top: 0.25in; font-style: normal"><FONT FACE="Helvetica, sans-serif"><B><A HREF="#Build Notes">Build Notes</A></B></FONT></P>
|
||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B><A HREF="#Unix Platforms">Unix Platforms</A></B></FONT></P>
|
||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B><A HREF="#Win32/WiNCE Platforms">Win32/WiNCE Platforms</A></B></FONT></P>
|
||||
<P STYLE="margin-top: 0.25in; font-style: normal"><FONT FACE="Helvetica, sans-serif"><B><A HREF="#API Reference">API Reference</A></B></FONT></P>
|
||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B><A HREF="#API Variable Types and Constants">API Variable Types and Constants</A></B></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormInstanceHandle">NormInstanceHandle</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSessionHandle">NormSessionHandle</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSessionId">NormSessionId</A></FONT></P>
|
||||
|
|
@ -138,15 +132,14 @@ of Contents</H1>
|
|||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormProbingMode">NormProbingMode</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormNackingMode">NormNackingMode</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormRepairBoundary">NormRepairBoundary</A></FONT></P>
|
||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>API
|
||||
Initialization and Operation</B></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormAckingStatus">NormAckingStatus</A></FONT></P>
|
||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B><A HREF="#API Initialization and Operation">API Initialization and Operation</A></B></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormCreateInstance()">NormCreateInstance()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormDestroyInstance()">NormDestroyInstance()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetCacheDirectory()">NormSetCacheDirectory()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormGetNextEvent()">NormGetNextEvent()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormGetDescriptor()">NormGetDescriptor()</A></FONT></P>
|
||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>Session
|
||||
Creation and Control</B></FONT></P>
|
||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B><A HREF="#Session Creation and Control Functions">Session Creation and Control Functions</A></B></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormCreateSession()">NormCreateSession()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormDestroySession()">NormDestroySession()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetUserData()">NormSetUserData()</A></FONT></P>
|
||||
|
|
@ -158,8 +151,7 @@ of Contents</H1>
|
|||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetTTL()">NormSetTTL()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetTOS()">NormSetTOS()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetLoopback()">NormSetLoopback()</A></FONT></P>
|
||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>NORM
|
||||
Sender Functions</B></FONT></P>
|
||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B><A HREF="#NORM Sender Functions">NORM Sender Functions</A></B></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStartSender()">NormStartSender()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStopSender()">NormStopSender()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetTransmitRate()">NormSetTransmitRate()</A></FONT></P>
|
||||
|
|
@ -172,8 +164,6 @@ of Contents</H1>
|
|||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetGrttMax()">NormSetGrttMax()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetGrttProbingMode()">NormSetGrttProbingMode()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetGrttProbingInterval()">NormSetGrttProbingInterval()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormAddAckingNode()">NormAddAckingNode()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormRemoveAckingNode()">NormRemoveAckingNode()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormFileEnqueue()">NormFileEnqueue()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormDataEnqueue()">NormDataEnqueue()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamOpen()">NormStreamOpen()</A></FONT></P>
|
||||
|
|
@ -185,8 +175,10 @@ of Contents</H1>
|
|||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamHasVacancy()">NormStreamHasVacancy()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamMarkEom()">NormStreamMarkEom()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetWatermark()">NormSetWatermark()</A></FONT></P>
|
||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>NORM
|
||||
Receiver Functions</B></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormAddAckingNode()">NormAddAckingNode()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormRemoveAckingNode()">NormRemoveAckingNode()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormGetAckingStatus()">NormGetAckingStatus()</A></FONT></P>
|
||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B><A HREF="#NORM Receiver Functions">NORM Receiver Functions</A></B></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStartReceiver()">NormStartReceiver()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStopReceiver()">NormStopReceiver()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormSetRxSocketBuffer()">NormSetRxSocketBuffer()</A></FONT></P>
|
||||
|
|
@ -201,8 +193,7 @@ of Contents</H1>
|
|||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamRead()">NormStreamRead()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamSeekMsgStart()">NormStreamSeekMsgStart()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormStreamGetReadOffset()">NormStreamGetReadOffset()</A></FONT></P>
|
||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>NORM
|
||||
Object Functions</B></FONT></P>
|
||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B><A HREF="#NORM Object Functions">NORM Object Functions</A></B></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectGetType()">NormObjectGetType()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectHasInfo()">NormObjectHasInfo()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectGetInfoLength()">NormObjectGetInfoLength()</A></FONT></P>
|
||||
|
|
@ -217,14 +208,13 @@ of Contents</H1>
|
|||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormDataAccessData()">NormDataAccessData()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormDataDetachData()">NormDataDetachData()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormObjectGetSender()">NormObjectGetSender()</A></FONT></P>
|
||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B>NORM
|
||||
Node Functions</B></FONT></P>
|
||||
<P STYLE="margin-top: 0.17in; font-style: normal"><FONT SIZE=2><B><A HREF="#NORM Node Functions">NORM Node Functions</A></B></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormNodeGetId()">NormNodeGetId()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormNodeGetAddress()">NormNodeGetAddress()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormNodeRetain()">NormNodeRetain()</A></FONT></P>
|
||||
<P STYLE="margin-left: 0.17in; margin-top: 0in; font-style: normal"><FONT SIZE=2><A HREF="#NormNodeRelease()">NormNodeRelease()</A></FONT></P>
|
||||
</DIV>
|
||||
<H1 CLASS="western" STYLE="page-break-before: always">Overview</H1>
|
||||
<H1 CLASS="western" STYLE="page-break-before: always"><A NAME="Overview">Overview</A></H1>
|
||||
<P CLASS="western" STYLE="font-style: normal">The NORM API has been
|
||||
designed to provide simple, straightforward access to and control of
|
||||
NORM protocol state and functions. Functions are provided to create
|
||||
|
|
@ -244,15 +234,14 @@ protocol thread notifies the application of various protocol events
|
|||
through a thread-safe event dispatching mechanism and API calls are
|
||||
provided to allow the application to control NORM operation. (<I>Note:
|
||||
API mechanisms for lower-level, non-threaded control and execution
|
||||
of the NORM protocol engine will also be provided in the future</I>.)</P>
|
||||
of the NORM protocol engine may also be provided in the future</I>.)</P>
|
||||
<P CLASS="western" STYLE="font-style: normal">The NORM API operation
|
||||
can be roughly summarized with the following categories of functions:</P>
|
||||
<OL>
|
||||
<LI><P CLASS="western" STYLE="font-style: normal">API Initialization</P>
|
||||
<LI><P CLASS="western" STYLE="font-style: normal">Session Creation
|
||||
and Control</P>
|
||||
<LI><P CLASS="western" STYLE="font-style: normal">Data Transport</P>
|
||||
<LI><P CLASS="western" STYLE="font-style: normal">Event Notification</P>
|
||||
<LI><P CLASS="western" STYLE="font-style: normal"><A HREF="#API Initialization">API Initialization</A></P>
|
||||
<LI><P CLASS="western" STYLE="font-style: normal"><A HREF="#Session Creation and Control">Session Creation and Control</A></P>
|
||||
<LI><P CLASS="western" STYLE="font-style: normal"><A HREF="#Data Transport">Data Transport</A></P>
|
||||
<LI><P CLASS="western" STYLE="font-style: normal"><A HREF="#API Event Notification">API Event Notification</A></P>
|
||||
</OL>
|
||||
<P CLASS="western" STYLE="font-style: normal">Note the order of these
|
||||
categories roughly reflects the order of function calls required to
|
||||
|
|
@ -269,23 +258,37 @@ application of significant sender and receiver events. There are
|
|||
also a number support functions provided for the application to
|
||||
control and monitor its participation within a NORM transport
|
||||
session.</P>
|
||||
<H2 CLASS="western">API Initialization</H2>
|
||||
<H2 CLASS="western"><A NAME="API Initialization">API Initialization</A></H2>
|
||||
<P CLASS="western" STYLE="font-style: normal">The NORM API requires
|
||||
that an application explicitly create at least one instance of the
|
||||
NORM protocol engine which is subsequently used as a conduit for
|
||||
further NORM API calls. By default, the NORM protocol engine runs in
|
||||
its own operating system thread and interacts with the application in
|
||||
a thread-safe manner through the API calls and event dispatching
|
||||
mechanism. In general, only the thread creating the NORM API
|
||||
instance should invoke API calls referencing that instance or any
|
||||
sessions or state created within that instance (<I>NOTE: This
|
||||
limitation may change in the future. The current implementation is
|
||||
theoretically safe for concurrent access, but this has not been fully
|
||||
tested</I>). Multiple API instances may be created as needed for
|
||||
applications with specific requirements for accessing and controlling
|
||||
participation in multiple NORM sessions from operating system
|
||||
multiple threads.</P>
|
||||
<H2 CLASS="western">Session Creation and Control</H2>
|
||||
mechanism.
|
||||
</P>
|
||||
<P CLASS="western" STYLE="font-style: normal">In general, only a
|
||||
single thread should access the <FONT FACE="Courier"><A HREF="#NormGetNextEvent()">NormGetNextEvent()</A></FONT>
|
||||
API call for a given <FONT FACE="Courier">NormInstance</FONT>. This
|
||||
function serves as the conduit for delivering NORM protocol engine
|
||||
events to the application. While a NORM application can be designed
|
||||
to be single-threaded, even with multiple active <I>NormSessions</I>,
|
||||
multiple API instances can be created (see <FONT FACE="Courier"><A HREF="#NormCreateInstance()">NormCreateInstance()</A></FONT>)
|
||||
as needed for applications with specific requirements for accessing
|
||||
and controlling participation in multiple <I>NormSessions</I> from
|
||||
separate operating system multiple threads. Or, alternatively, a
|
||||
single <FONT FACE="Courier">NormInstance</FONT> could be used, with a
|
||||
"master thread" serving as an intermediary between the
|
||||
<FONT FACE="Courier"><A HREF="#NormGetNextEvent()">NormGetNextEvent()</A></FONT> function,
|
||||
demultiiplexing and dispatching events as appropriate to other "child
|
||||
threads" that are created to handle "per-<I>NormSession</I>"
|
||||
input/output. The advantage of this alternative approach is that the
|
||||
end result would be one NORM protocol engine thread plus one "master
|
||||
thread" plus one "child thread" per <I>NormSession</I>
|
||||
instead of two threads (protocol engine plus application thread) per
|
||||
<I>NormSession</I> if such multi-threaded operation is needed by the
|
||||
application.</P>
|
||||
<H2 CLASS="western"><A NAME="Session Creation and Control">Session Creation and Control</A></H2>
|
||||
<P CLASS="western" STYLE="font-style: normal">Once an API instance
|
||||
has been successfully created, the application may then create NORM
|
||||
transport session instances as needed. The application can
|
||||
|
|
@ -310,7 +313,7 @@ limit the number of active senders monitored and/or provide the
|
|||
application with finer control over receive buffer allocation,
|
||||
perhaps on a per sender basis</I>).
|
||||
</P>
|
||||
<H2 CLASS="western">NORM Data Transport</H2>
|
||||
<H2 CLASS="western"><A NAME="Data Transport">Data Transport</A></H2>
|
||||
<P CLASS="western" STYLE="font-style: normal">The NORM protocol
|
||||
supports transport of three basic types of data content. These
|
||||
include the types <FONT FACE="Courier"><I>NORM_OBJECT_FILE</I></FONT>
|
||||
|
|
@ -333,7 +336,7 @@ application-defined message-oriented transport where receivers can
|
|||
recover message boundaries without any “handshake” with the
|
||||
sender. Stream content is buffered by the NORM implementation for
|
||||
transmission/retransmission and as it is received.</P>
|
||||
<H3 CLASS="western">NORM Data Transmission</H3>
|
||||
<H3 CLASS="western"><A NAME="Data Transmission">Data Transmission</A></H3>
|
||||
<P CLASS="western" STYLE="font-style: normal">The behavior of data
|
||||
transport operation is largely placed in the control of the NORM
|
||||
sender(s). NORM senders controls their data transmission rate,
|
||||
|
|
@ -375,7 +378,59 @@ node list") and set "watermark" points for which
|
|||
positive acknowledgement is collected. This process can provide the
|
||||
application with explicit flow control for an application-determined
|
||||
critical set of receivers in the group.</P>
|
||||
<H3 CLASS="western">NORM Data Reception</H3>
|
||||
<P CLASS="western" STYLE="font-style: normal">For a NORM application
|
||||
to perform data transmission, it must first create a session using
|
||||
<FONT FACE="Courier"><A HREF="#NormCreateSession()">NormCreateSession()</A></FONT> and make a call to
|
||||
<FONT FACE="Courier"><A HREF="#NormStartSender()">NormStartSender()</A></FONT> before sending actual
|
||||
user data. The functions <FONT FACE="Courier">NormEnqueueFile()</FONT>,
|
||||
<FONT FACE="Courier">NormEnqueueData()</FONT>, and <FONT FACE="Courier"><A HREF="#NormStreamWrite()">NormStreamWrite()</A></FONT>
|
||||
are available for the application to pass data to the NORM protocol
|
||||
engine for transmission. Note that to use <FONT FACE="Courier"><A HREF="#NormStreamWrite()">NormStreamWrite()</A></FONT>,
|
||||
a "sender stream" must first be created using
|
||||
<FONT FACE="Courier"><A HREF="#NormStreamOpen()">NormStreamOpen()</A></FONT>.
|
||||
</P>
|
||||
<P CLASS="western" STYLE="font-style: normal">The calls to enqueue
|
||||
transport objects or write to a stream may be called at any time, but
|
||||
the <FONT FACE="Courier"><I>NORM_TX_QUEUE_EMPTY</I></FONT> and
|
||||
<FONT FACE="Courier"><I>NORM_TX_QUEUE_VACANCY</I></FONT> notification
|
||||
events (see <FONT FACE="Courier"><A HREF="#NormGetNextEvent()">NormGetNextEvent()</A></FONT>) provide
|
||||
useful cues for when these functions may be successfully called.
|
||||
Typically, an application might catch both <FONT FACE="Courier"><I>NORM_TX_QUEUE_EMPTY</I></FONT>
|
||||
and <FONT FACE="Courier"><I>NORM_TX_QUEUE_VACANCY</I></FONT> event
|
||||
types as cues for enqueuing additional transport objects or writing
|
||||
to a stream. However, an application may choose to cue off of
|
||||
<FONT FACE="Courier"><I>NORM_TX_QUEUE_EMPTY</I></FONT> only if it
|
||||
wishes to provide the "freshest" data to NORM for
|
||||
transmission. The advantage of additionally using
|
||||
<FONT FACE="Courier"><I>NORM_TX_QUEUE_VACANCY</I></FONT> is that if
|
||||
the application uses this cue to fill up NORM transport object or
|
||||
stream buffers, it can keep the NORM stream busy sending data and
|
||||
realize the highest possible transmission rate when attempting very
|
||||
high speed communication (Otherwise, the NORM protocol engine may
|
||||
experience some "dead air time" waiting for the application
|
||||
thread to respond to a <FONT FACE="Courier"><I>NORM_TX_QUEUE_EMPTY</I></FONT>
|
||||
event). Note the sender application can control buffer depths as
|
||||
needed with the <A HREF="#NormSetTransmitCacheBounds()">NormSetTransmitCacheBounds()</A> and <A HREF="#NormStreamOpen()">NormStreamOpen()</A>
|
||||
calls.</P>
|
||||
<P CLASS="western" STYLE="font-style: normal">Another cue that can be
|
||||
leveraged by the sender application to determine when it is
|
||||
appropriate to enqueue (or write) additional data for transmission is
|
||||
the <FONT FACE="Courier"><I>NORM_TX_WATERMARK_COMPLETED</I></FONT>
|
||||
event. This event is posted when the flushing or explicit positive
|
||||
acknowledgment collection process has completed for a "watermark"
|
||||
point in transmission that was set by the sender (see
|
||||
<FONT FACE="Courier"><A HREF="#NormSetWatermark()">NormSetWatermark()</A></FONT> and
|
||||
<FONT FACE="Courier"><A HREF="#NormAddAckingNode()">NormAddAckingNode()</A></FONT>). A list of
|
||||
<FONT FACE="Courier">NormNodeIds</FONT> can be supplied from which
|
||||
explicit acknowledgement is expected and/or the <FONT FACE="Courier"><A HREF="#NormNodeId">NormNodeId</A></FONT>
|
||||
NORM_NODE_NONE can be set (using <FONT FACE="Courier"><A HREF="#NormAddAckingNode()">NormAddAckingNode()</A></FONT>)
|
||||
for completion of a NACK-based version of the watermark flushing
|
||||
procedure. This flushing process can be used as a flow control
|
||||
mechanism for NORM applications. Note this is distinct from NORM's
|
||||
congestion control mechanism that, while it provides network-friendly
|
||||
transmission rate control, does guarantee flow control to receiving
|
||||
nodes.</P>
|
||||
<H3 CLASS="western"><A NAME="Data Reception">Data Reception</A></H3>
|
||||
<P CLASS="western" STYLE="font-style: normal">NORM receiver
|
||||
applications learn of active senders and their corresponding pending
|
||||
and completed data transfers, etc via the API event dispatching
|
||||
|
|
@ -384,8 +439,12 @@ repair of transmitted content from the originating sender as needed
|
|||
to achieve reliable transfer. Some API functions are available to
|
||||
provide some additional control over the NACKing behavior, such as
|
||||
initially NACKing for NORM_INFO content only or even to the extent of
|
||||
disabling receiver feedback (silent receiver operation) entirely.</P>
|
||||
<H2 CLASS="western">API Event Notification</H2>
|
||||
disabling receiver feedback (silent receiver or emission-controlled
|
||||
(EMCON) operation) entirely. Otherwise, the parameters and operation
|
||||
of reliable data transmission are left to sender applications and
|
||||
receivers learn of sender parameters in NORM protocol message headers
|
||||
and are instructed by NORM_CMD messages from the sender(s).</P>
|
||||
<H2 CLASS="western"><A NAME="API Event Notification">API Event Notification</A></H2>
|
||||
<P CLASS="western" STYLE="font-style: normal">An asynchronous event
|
||||
dispatching mechanism is provided to notify the application of
|
||||
significant NORM protocol events. The centerpiece of this is the
|
||||
|
|
@ -402,7 +461,7 @@ be signaled when a <FONT FACE="Courier"><A HREF="#NormEvent">NormEvent</A></FON
|
|||
available. For Win32 platforms, dispatching of a user-defined
|
||||
Windows message for NORM event notification is also planned for a
|
||||
future update to the API.</P>
|
||||
<H1 CLASS="western">Build Notes</H1>
|
||||
<H1 CLASS="western"><A NAME="Build Notes">Build Notes</A></H1>
|
||||
<P CLASS="western" STYLE="font-style: normal">To build applications
|
||||
that use the NORM library, a path to the "normApi.h" header
|
||||
file must be provided and the linker step needs to reference the NORM
|
||||
|
|
@ -410,22 +469,23 @@ library file ("libnorm.a" for Unix platforms and "Norm.lib"
|
|||
for Win32 platforms). NORM also depends upon the NRL Protean
|
||||
Protocol Prototyping toolkit "Protokit" library (a.k.a
|
||||
"Protolib") (static library files "libProtokit.a"
|
||||
for Unix and "Protokit.lib" for Win32). Depending upon the
|
||||
platform, some additional library dependencies may be required to
|
||||
support the needs of NORM and/or Protokit. These are described
|
||||
below.</P>
|
||||
<H2 CLASS="western">Unix Platforms</H2>
|
||||
for Unix and "Protokit.lib" for Win32). Shared or
|
||||
dynamically-linked versions of these libraries may also be built from
|
||||
the NORM source code or provided. Depending upon the platform, some
|
||||
additional library dependencies may be required to support the needs
|
||||
of NORM and/or Protokit. These are described below.</P>
|
||||
<H2 CLASS="western"><A NAME="Unix Platforms">Unix Platforms</A></H2>
|
||||
<P CLASS="western" STYLE="font-style: normal">NORM has been built and
|
||||
tested on Linux (various architectures), MacOS (BSD), Solaris, and
|
||||
IRIX (SGI) platforms. The code should be readily portable to other
|
||||
Unix platforms.</P>
|
||||
<P CLASS="western" STYLE="font-style: normal">To support IPv6
|
||||
operation, the NORM and the Protokit library must be compiled with
|
||||
the "HAVE_IPV6" macro defined. This is default in the NORM
|
||||
and Protokit Makefiles for platforms that support IPv6. It is
|
||||
important that NORM and Protokit be built with this macro defined the
|
||||
same. With NORM, it is recommended that "large file support"
|
||||
options be enabled when possible.</P>
|
||||
operation, the NORM and the <I>Protokit</I> library must be compiled
|
||||
with the "HAVE_IPV6" macro defined. This is default in the
|
||||
NORM and <I>Protokit</I> Makefiles for platforms that support IPv6.
|
||||
It is important that NORM and <I>Protokit</I> be built with this
|
||||
macro defined the same. With NORM, it is recommended that "large
|
||||
file support" options be enabled when possible.</P>
|
||||
<P CLASS="western" STYLE="font-style: normal">The NORM API uses
|
||||
threading so that the NORM protocol engine may run independent of the
|
||||
application. Thus the "POSIX Threads" library must be
|
||||
|
|
@ -444,7 +504,7 @@ the compilation to enable "large file support".
|
|||
Applications built using NORM should have the same compilation option
|
||||
set to operate correctly (The definition of the <FONT FACE="Courier"><A HREF="#NormSize">NormSize</A></FONT>
|
||||
type in "normApi.h" depends upon this compilation flag).</P>
|
||||
<H2 CLASS="western">Win32/WiNCE Platforms</H2>
|
||||
<H2 CLASS="western"><A NAME="Win32/WiNCE Platforms">Win32/WiNCE Platforms</A></H2>
|
||||
<P CLASS="western" STYLE="font-style: normal">NORM has been built
|
||||
using Microsoft's Visual C++ (6.0 and .NET) and Embedded VC++ 4.2
|
||||
environments. In addition to proper macro definitions (e.g.,
|
||||
|
|
@ -463,14 +523,24 @@ and these must be included in the project "Link"
|
|||
attributes.</P>
|
||||
<P CLASS="western" STYLE="font-style: normal">An additional note is
|
||||
that a bug in VC++ 6.0 and earlier compilers (includes embedded VC++
|
||||
4.x compilers) prevent compilation of Protokit-based code with
|
||||
4.x compilers) prevent compilation of <I>Protokit</I>-based code with
|
||||
debugging capabilities enabled. However, this has been resolved in
|
||||
VC++ .NET and is hoped to be resolved in the future for the WinCE
|
||||
build tools.</P>
|
||||
<H1 CLASS="western">API Reference</H1>
|
||||
<P CLASS="western" STYLE="font-style: normal">Operation on Windows
|
||||
NT4 (and perhaps other older Windows operating systems) requires that
|
||||
the compile time macro <FONT FACE="Courier"><I>WINVER=0x0400</I></FONT>
|
||||
defined. This is because the version of the IP Helper API library
|
||||
(<I>iphlpapi.lib</I>) used y Protolib (and hence NORM) for this
|
||||
system doesn't support some of the functions defined for this
|
||||
library. This may be related to IPv6 support issues so it may be
|
||||
possible that the Protolib build could be tweaked to provide a single
|
||||
binary executable suitable for IPv4 operation only across a large
|
||||
range of Windows platforms.</P>
|
||||
<H1 CLASS="western"><A NAME="API Reference">API Reference</A></H1>
|
||||
<P CLASS="western" STYLE="font-style: normal">This section provides a
|
||||
reference to the NORM API variable types, constants and functions.</P>
|
||||
<H2 CLASS="western">API Variable Types and Constants</H2>
|
||||
<H2 CLASS="western"><A NAME="API Variable Types and Constants">API Variable Types and Constants</A></H2>
|
||||
<P CLASS="western" STYLE="font-style: normal">The NORM API defines
|
||||
and enumerates a number of supporting variable types and values which
|
||||
are used in different function calls. The variable types are
|
||||
|
|
@ -648,7 +718,7 @@ these values is given in the description of <FONT FACE="Courier"><A HREF="#Norm
|
|||
function.</P>
|
||||
<H3 CLASS="functionheading-western"><A NAME="NormNackingMode">NormNackingMode</A></H3>
|
||||
<P CLASS="western" STYLE="font-style: normal">The <FONT FACE="Courier"><A HREF="#NormNackingMode">NormNackingMode</A></FONT>
|
||||
consist of the following enumeration:</P>
|
||||
type consists of the following enumeration:</P>
|
||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>enum
|
||||
<A HREF="#NormNackingMode">NormNackingMode</A><BR>{<BR> NORM_NACK_NONE,<BR> NORM_NACK_INFO_ONLY,<BR> NORM_NACK_NORMAL<BR>};</FONT></FONT></P>
|
||||
<P CLASS="western" STYLE="font-style: normal">The interpretation of
|
||||
|
|
@ -658,14 +728,22 @@ these values is given in the descriptions of the
|
|||
<FONT FACE="Courier"><A HREF="#NormObjectSetNackingMode()">NormObjectSetNackingMode()</A></FONT> functions.</P>
|
||||
<H3 CLASS="functionheading-western"><A NAME="NormRepairBoundary">NormRepairBoundary</A></H3>
|
||||
<P CLASS="western" STYLE="font-style: normal">The <FONT FACE="Courier"><A HREF="#NormRepairBoundary">NormRepairBoundary</A></FONT>
|
||||
consist of the following enumeration:</P>
|
||||
types consists of the following enumeration:</P>
|
||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>enum
|
||||
<A HREF="#NormRepairBoundary">NormRepairBoundary</A><BR>{<BR> NORM_BOUNDARY_BLOCK,<BR> NORM_BOUNDARY_OBJECT<BR>};</FONT></FONT></P>
|
||||
<P CLASS="western" STYLE="font-style: normal">The interpretation of
|
||||
these values is given in the descriptions of the
|
||||
<FONT FACE="Courier"><A HREF="#NormSetDefaultRepairBoundary()">NormSetDefaultRepairBoundary()</A> </FONT>and
|
||||
<FONT FACE="Courier"><A HREF="#NormNodeSetRepairBoundary()">NormNodeSetRepairBoundary()</A></FONT> functions.</P>
|
||||
<H2 CLASS="western">API Initialization and Operation</H2>
|
||||
<H3 CLASS="functionheading-western"><A NAME="NormAckingStatus">NormAckingStatus</A></H3>
|
||||
<P CLASS="western" STYLE="font-style: normal">The <FONT FACE="Courier"><A HREF="#NormAckingStatus">NormAckingStatus</A></FONT>
|
||||
consist of the following enumeration:</P>
|
||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>enum
|
||||
<A HREF="#NormAckingStatus">NormAckingStatus</A><BR>{<BR> NORM_ACK_INVALID,<BR> NORM_ACK_FAILURE,<BR> NORM_ACK_PENDING,<BR> NORM_ACK_SUCCESS<BR>};</FONT></FONT></P>
|
||||
<P CLASS="western" STYLE="font-style: normal">The interpretation of
|
||||
these values is given in the descriptions of the
|
||||
<FONT FACE="Courier"><A HREF="#NormGetAckingStatus()">NormGetAckingStatus()</A></FONT> function.</P>
|
||||
<H2 CLASS="western"><A NAME="API Initialization and Operation">API Initialization and Operation</A></H2>
|
||||
<P CLASS="western" STYLE="font-style: normal">The first step in using
|
||||
the NORM API is to create an "instance" of the NORM
|
||||
protocol engine. Note that multiple instances may be created by the
|
||||
|
|
@ -804,8 +882,12 @@ function call.</P>
|
|||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||
This event indicates that there is room for additional transmit
|
||||
objects to be enqueued, or, if the handle of <FONT FACE="Courier"><I>NORM_OBJECT_STREAM</I></FONT>
|
||||
is given in the event "object" field, the application
|
||||
may successfully write to the indicated stream object.</P>
|
||||
is given in the corresponding event "object" field, the
|
||||
application may successfully write to the indicated stream object.
|
||||
Note this event is not dispatched until a call to
|
||||
<FONT FACE="Courier">NormEnqueueFile()</FONT>, <FONT FACE="Courier">NormEnqueueData()</FONT>,
|
||||
or <FONT FACE="Courier"><A HREF="#NormStreamWrite()">NormStreamWrite()</A></FONT> fails because of
|
||||
a filled transmit cache or stream buffer.</P>
|
||||
</TD>
|
||||
</TR>
|
||||
<TR VALIGN=TOP>
|
||||
|
|
@ -817,7 +899,14 @@ function call.</P>
|
|||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||
This event indicates the NORM protocol engine has no new data
|
||||
pending transmission and the application may enqueue additional
|
||||
objects for transmission.</P>
|
||||
objects for transmission. If the handle of a sender
|
||||
<FONT FACE="Courier"><I>NORM_OBJECT_STREAM</I></FONT> is given in
|
||||
the corresponding event "object" field, this indicates
|
||||
the stream transmit buffer has been emptied and the sender
|
||||
application may write to the stream (Use of <FONT FACE="Courier"><I>NORM_TX_QUEUE_VACANCY</I></FONT>
|
||||
may be preferred for this purpose since it allows the application
|
||||
to keep the NORM protocol engine busier sending data, resulting in
|
||||
higher throughput when attempting very high transfer rates).</P>
|
||||
</TD>
|
||||
</TR>
|
||||
<TR VALIGN=TOP>
|
||||
|
|
@ -840,6 +929,20 @@ function call.</P>
|
|||
transmission, even with packet loss rates of 50%.</P>
|
||||
</TD>
|
||||
</TR>
|
||||
<TR VALIGN=TOP>
|
||||
<TD WIDTH=269>
|
||||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||
<FONT FACE="Courier"><I>NORM_TX_WATERMARK_COMPLETED</I></FONT></P>
|
||||
</TD>
|
||||
<TD WIDTH=293>
|
||||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||
This event indicates that the flushing process initiated by a
|
||||
prior application call to <FONT FACE="Courier"><A HREF="#NormSetWatermark()">NormSetWatermark()</A></FONT>
|
||||
has completed The posting of this event indicates the appropriate
|
||||
time for the application to make a call <FONT FACE="Courier"><A HREF="#NormGetAckingStatus()">NormGetAckingStatus()</A></FONT>
|
||||
to determine the results of the watermark flushing process.</P>
|
||||
</TD>
|
||||
</TR>
|
||||
<TR VALIGN=TOP>
|
||||
<TD WIDTH=269>
|
||||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||
|
|
@ -1068,7 +1171,7 @@ descriptor.</P>
|
|||
returned which is valid until a call to <FONT FACE="Courier"><A HREF="#NormDestroyInstance()">NormDestroyInstance()</A></FONT>
|
||||
is made. Upon error, a value of <I><FONT FACE="Courier">NORM_DESCRIPTOR_INVALID</FONT></I>
|
||||
is returned.</P>
|
||||
<H2 CLASS="western">Session Creation and Control</H2>
|
||||
<H2 CLASS="western"><A NAME="Session Creation and Control Functions">Session Creation and Control Functions</A></H2>
|
||||
<H3 CLASS="functionheading-western"><A NAME="NormCreateSession()">NormCreateSession()</A></H3>
|
||||
<H4 CLASS="western">Synopsis</H4>
|
||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
||||
|
|
@ -1428,8 +1531,7 @@ created.</P>
|
|||
<H4 CLASS="western">Return Values</H4>
|
||||
<P CLASS="western" STYLE="font-style: normal">This function has no
|
||||
return values.</P>
|
||||
<H2 CLASS="western">NORM<SPAN STYLE="font-style: normal"> </SPAN>Sender
|
||||
Functions</H2>
|
||||
<H2 CLASS="western"><A NAME="NORM Sender Functions">NORM Sender Functions</A></H2>
|
||||
<H3 CLASS="functionheading-western"><A NAME="NormStartSender()">NormStartSender()</A></H3>
|
||||
<H4 CLASS="western">Synopsis</H4>
|
||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
||||
|
|
@ -1925,7 +2027,7 @@ return values.</P>
|
|||
<normApi.h></FONT></FONT></P>
|
||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>void
|
||||
NormSetGrttProbingMode(<A HREF="#NormSessionHandle">NormSessionHandle</A> session,
|
||||
<BR> NormProbingMode probingMode);</FONT></FONT></P>
|
||||
<BR> <A HREF="#NormProbingMode">NormProbingMode</A> probingMode);</FONT></FONT></P>
|
||||
<H4 CLASS="western">Description</H4>
|
||||
<P CLASS="western" STYLE="font-style: normal">This function sets the
|
||||
sender's mode of probing for round trip timing measurement responses
|
||||
|
|
@ -2010,44 +2112,6 @@ values are 1.0 second and 30.0 seconds, respectively.</P>
|
|||
<H4 CLASS="western">Return Values</H4>
|
||||
<P CLASS="western" STYLE="font-style: normal">This function has no
|
||||
return values.</P>
|
||||
<H3 CLASS="functionheading-western"><A NAME="NormAddAckingNode()">NormAddAckingNode()</A></H3>
|
||||
<H4 CLASS="western">Synopsis</H4>
|
||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
||||
<normApi.h></FONT></FONT></P>
|
||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>bool
|
||||
NormAddAckingNode(<A HREF="#NormSessionHandle">NormSessionHandle</A> session,<BR> <A HREF="#NormNodeId">NormNodeId</A> nodeId);</FONT></FONT></P>
|
||||
<H4 CLASS="western">Description</H4>
|
||||
<P CLASS="western" STYLE="font-style: normal">When this function is
|
||||
called, the specified <FONT FACE="Courier"><U>nodeId</U></FONT> is
|
||||
added to the list of <I>NormNodes</I> used when NORM sender operation
|
||||
performs positive acknowledgement (ACK) collection for the specified
|
||||
<FONT FACE="Courier"><U>session</U></FONT>. The optional NORM
|
||||
positive acknowledgement collection occurs when a specified
|
||||
transmission point (see <FONT FACE="Courier"><A HREF="#NormSetWatermark()">NormSetWatermark()</A>)</FONT>
|
||||
is reached or for specialized protocol actions such as
|
||||
positively-acknowledged application-defined commands (<I>TBD</I>).</P>
|
||||
<H4 CLASS="western">Return Values</H4>
|
||||
<P CLASS="western" STYLE="font-style: normal">The function returns
|
||||
<FONT FACE="Courier"><I>true</I></FONT> upon success and <FONT FACE="Courier"><I>false</I></FONT>
|
||||
upon failure. The only failure condition is that insufficient memory
|
||||
resources were available. If a specific <FONT FACE="Courier"><U>nodeId</U></FONT>
|
||||
is added more than once, this has no effect.</P>
|
||||
<H3 CLASS="functionheading-western"><A NAME="NormRemoveAckingNode()">NormRemoveAckingNode()</A></H3>
|
||||
<H4 CLASS="western">Synopsis</H4>
|
||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
||||
<normApi.h></FONT></FONT></P>
|
||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>void
|
||||
NormRemoveAckingNode(<A HREF="#NormSessionHandle">NormSessionHandle</A> session,<BR> <A HREF="#NormNodeId">NormNodeId</A> nodeId);</FONT></FONT></P>
|
||||
<H4 CLASS="western">Description</H4>
|
||||
<P CLASS="western" STYLE="font-style: normal">This function deletes
|
||||
the specified <FONT FACE="Courier"><U>nodeId</U></FONT> from the list
|
||||
of <I>NormNodes</I> used when NORM sender operation performs positive
|
||||
acknowledgement (ACK) collection for the specified <FONT FACE="Courier"><U>session</U></FONT>.
|
||||
|
||||
</P>
|
||||
<H4 CLASS="western">Return Values</H4>
|
||||
<P CLASS="western" STYLE="font-style: normal">The function has no
|
||||
return values.</P>
|
||||
<H3 CLASS="functionheading-western"><A NAME="NormFileEnqueue()">NormFileEnqueue()</A></H3>
|
||||
<H4 CLASS="western">Synopsis</H4>
|
||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
||||
|
|
@ -2330,10 +2394,21 @@ reliability does not provide explicit flow control, there is some
|
|||
degree of implicit flow control in limiting writing new data to the
|
||||
stream against pending repairs.
|
||||
</P>
|
||||
<P CLASS="western" STYLE="font-style: normal">The <FONT FACE="Courier"><A HREF="#NormEvent">NormEvent</A></FONT>
|
||||
NORM_TX_QUEUE_VACANCY is posted with its <I><A HREF="#NormEvent">NormEvent</A>::object</I>
|
||||
field set to a valid sender stream <FONT FACE="Courier"><A HREF="#NormObjectHandle">NormObjectHandle</A></FONT>
|
||||
to indicate when the stream is ready for writing via this function.
|
||||
Note that, after this event type is posted, the application <I>must</I>
|
||||
make a call to <FONT FACE="Courier"><A HREF="#NormStreamWrite()">NormStreamWrite()</A></FONT> with a
|
||||
non-zero <FONT FACE="Courier"><U>numBytes</U></FONT> value before
|
||||
addition NORM_TX_QUEUE_VACANCY events are posted for the given
|
||||
<FONT FACE="Courier"><U>streamHandle</U></FONT>.</P>
|
||||
<H4 CLASS="western">Return Values</H4>
|
||||
<P CLASS="western" STYLE="font-style: normal">This function returns
|
||||
the number of bytes of data successfully enqueued for NORM stream
|
||||
transmission.</P>
|
||||
transmission. If the underlying send stream buffer is full, this
|
||||
function may return zero.
|
||||
</P>
|
||||
<H3 CLASS="functionheading-western"><A NAME="NormStreamFlush()">NormStreamFlush()</A></H3>
|
||||
<H4 CLASS="western">Synopsis</H4>
|
||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
||||
|
|
@ -2548,53 +2623,218 @@ NormSetWatermark(<A HREF="#NormSessionHandle">NormSessionHandle</A> session
|
|||
<H4 CLASS="western">Description</H4>
|
||||
<P CLASS="western" STYLE="font-style: normal">This function specifies
|
||||
a "watermark" transmission point at which NORM sender
|
||||
protocol operation should perform positive acknowledgment collection
|
||||
for a given <FONT FACE="Courier"><U>session</U></FONT>. For
|
||||
<FONT FACE="Courier"><I>NORM_OBJECT_FILE</I></FONT> and
|
||||
protocol operation should perform a flushing process and/or positive
|
||||
acknowledgment collection for a given <FONT FACE="Courier"><U>session</U></FONT>.
|
||||
For <FONT FACE="Courier"><I>NORM_OBJECT_FILE</I></FONT> and
|
||||
<FONT FACE="Courier"><I>NORM_OBJECT_DATA</I></FONT> transmissions,
|
||||
the positive acknowledgement collection will begin when the specified
|
||||
<FONT FACE="Courier"><U>object</U></FONT> has been completely
|
||||
transmitted. The object parameter must be a valid handle to a
|
||||
previously-created sender object (see <FONT SIZE=2><FONT FACE="Courier">NormEnqueueFile(),</FONT></FONT>
|
||||
<FONT SIZE=2><FONT FACE="Courier">NormEnqueueData()</FONT></FONT>, or
|
||||
<FONT SIZE=2><FONT FACE="Courier"><A HREF="#NormStreamOpen()">NormStreamOpen()</A></FONT></FONT>).
|
||||
For <FONT FACE="Courier"><I>NORM_OBJECT_STREAM</I></FONT>
|
||||
previously-created sender object (see <FONT FACE="Courier">NormEnqueueFile()</FONT><FONT SIZE=2><FONT FACE="Courier">,</FONT></FONT>
|
||||
<FONT FACE="Courier">NormEnqueueData()</FONT>, or <FONT FACE="Courier"><A HREF="#NormStreamOpen()">NormStreamOpen()</A></FONT>).
|
||||
For <FONT FACE="Courier"><I>NORM_OBJECT_STREAM</I></FONT>
|
||||
transmission, the positive acknowledgment collection begins
|
||||
immediately, using the current position (last data written) of the
|
||||
sender stream as a reference.
|
||||
immediately, using the current position (offset of most recent data
|
||||
written) of the sender stream as a reference.
|
||||
</P>
|
||||
<P CLASS="western" STYLE="font-style: normal">As the acknowledgment
|
||||
collection proceeds, <FONT FACE="Courier"><I>NORM_ACK_FAILED</I></FONT>
|
||||
events will be posted for individual receiver <I>NormNodes</I> which
|
||||
fail to acknowledge the request. The <FONT FACE="Courier"><A HREF="#NormEvent">NormEvent</A>::node</FONT>
|
||||
field contains a <FONT FACE="Courier"><A HREF="#NormNodeHandle">NormNodeHandle</A></FONT> for the
|
||||
failed node and <FONT FACE="Courier"><A HREF="#NormNodeGetId()">NormNodeGetId()</A></FONT> can be
|
||||
used to retrieve the failing node's <FONT FACE="Courier"><A HREF="#NormNodeId">NormNodeId</A></FONT>.
|
||||
When the sender acknowledgment collection process has completed, the
|
||||
<FONT FACE="Courier"><I>NORM_ACK_COMPLETE</I></FONT> event is posted
|
||||
and the application may assume that the remaining nodes (those for
|
||||
which there was no <FONT FACE="Courier"><I>NORM_ACK_FAILED</I></FONT>
|
||||
event) successfully acknowledged the request.</P>
|
||||
<P CLASS="western" STYLE="font-style: normal">If a subsequent call is
|
||||
made to <FONT FACE="Courier"><A HREF="#NormSetWatermark()">NormSetWatermark()</A></FONT> before the
|
||||
prior acknowledgement request has completed, the pending
|
||||
acknowledgment request is canceled and new one may begin.</P>
|
||||
<P CLASS="western" STYLE="font-style: normal">Note that the sender
|
||||
may still enqueue <I>NormObjects</I> for transmission (or write to
|
||||
the existing stream) and the positive acknowledgement collection will
|
||||
be multiplexed with the ongoing data transmission. However, the
|
||||
sender application may wish to defer sending more data until a
|
||||
<FONT FACE="Courier"><I>NORM_ACK_COMPLETE</I></FONT> event is
|
||||
received for the <FONT FACE="Courier"><U>session</U></FONT>. This
|
||||
provides a form of explicit sender->receiver(s) flow control (with
|
||||
respect to the current list of "acking" receivers) which
|
||||
does not exist in NORM's default NACK-only operation.</P>
|
||||
<P CLASS="western" STYLE="font-style: normal">The functions
|
||||
<FONT FACE="Courier"><A HREF="#NormAddAckingNode()">NormAddAckingNode()</A></FONT> and
|
||||
<FONT FACE="Courier"><A HREF="#NormRemoveAckingNode()">NormRemoveAckingNode()</A></FONT> are used to manage
|
||||
the list of <FONT FACE="Courier"><A HREF="#NormNodeId">NormNodeId</A></FONT> values
|
||||
corresponding to NORM receivers that are expected to explicitly
|
||||
acknowledge the watermark flushing messages transmitted by the
|
||||
sender. Note that the <FONT FACE="Courier"><A HREF="#NormNodeId">NormNodeId</A></FONT>
|
||||
<FONT FACE="Courier"><I>NORM_NODE_NONE</I></FONT> may be included in
|
||||
the list. Inclusion of <FONT FACE="Courier"><I>NORM_NODE_NONE</I></FONT>
|
||||
forces the watermark flushing process to proceed through a full
|
||||
<FONT FACE="Courier"><I>NORM_ROBUST_FACTOR</I></FONT> number of
|
||||
rounds before completing, prompting any receivers that have not
|
||||
completed reliable reception to the given watermark point to NACK for
|
||||
any repair needs. If NACKs occur, the flushing process is reset and
|
||||
repeated until completing with no NACKs for data through the given
|
||||
watermark transmission point are received. Thus, even without
|
||||
explicit positive acknowledgment, the sender can use this process (by
|
||||
adding <FONT FACE="Courier"><I>NORM_NODE_NONE</I></FONT> to the
|
||||
<FONT FACE="Courier"><U>session</U></FONT>'s list of acking nodes)
|
||||
for a high level of assurance that the receiver set is "happy"
|
||||
(completed reliable data reception) through the given <FONT FACE="Courier"><U>object</U></FONT>
|
||||
(or stream transmission point).
|
||||
</P>
|
||||
<P CLASS="western" STYLE="font-style: normal">The event
|
||||
<FONT FACE="Courier"><I>NORM_TX_WATERMARK_COMPLETED</I></FONT> is
|
||||
posted for the given <FONT FACE="Courier"><U>session</U></FONT> when
|
||||
the flushing process or positive acknowledgment collection has
|
||||
completed. The process completes as soon as all listed receivers
|
||||
have responded unless <FONT FACE="Courier"><I>NORM_NODE_NONE</I></FONT>
|
||||
is included in the acking list. The sender application may use the
|
||||
function <FONT FACE="Courier"><A HREF="#NormGetAckingStatus()">NormGetAckingStatus()</A></FONT> to
|
||||
determine the degree of success of the flushing process in general or
|
||||
for individual <FONT FACE="Courier"><A HREF="#NormNodeId">NormNodeId</A></FONT> values.
|
||||
</P>
|
||||
<P CLASS="western" STYLE="font-style: normal">The flushing is
|
||||
conducted concurrently with ongoing data transmission and does not
|
||||
impede the progress of reliable data transfer. Thus the sender may
|
||||
still enqueue <I>NormObjects</I> for transmission (or write to the
|
||||
existing stream) and the positive acknowledgement collection and
|
||||
flushing procedure will be multiplexed with the ongoing data
|
||||
transmission. However, the sender application may wish to defer from
|
||||
or limit itself in sending more data until a
|
||||
<FONT FACE="Courier"><I>NORM_TX_WATERMARK_COMPLETED</I></FONT> event
|
||||
is received for the given <FONT FACE="Courier"><U>session</U></FONT>.
|
||||
This provides a form of sender->receiver(s) flow control which
|
||||
does not exist in NORM's default protocol operation. If a subsequent
|
||||
call is made to <FONT FACE="Courier"><A HREF="#NormSetWatermark()">NormSetWatermark()</A></FONT> before
|
||||
the current acknowledgement request has completed, the pending
|
||||
acknowledgment request is canceled and the new one begins.</P>
|
||||
<H4 CLASS="western">Return Values</H4>
|
||||
<P CLASS="western" STYLE="font-style: normal">The function returns
|
||||
<FONT FACE="Courier"><I>true</I></FONT> upon successful establishment
|
||||
of the watermark point. The function may return <FONT FACE="Courier"><I>false</I></FONT>
|
||||
upon failure (<I>why would it fail? – TBD</I>).</P>
|
||||
<H2 CLASS="western">NORM Receiver Functions</H2>
|
||||
<H3 CLASS="functionheading-western"><A NAME="NormAddAckingNode()">NormAddAckingNode()</A></H3>
|
||||
<H4 CLASS="western">Synopsis</H4>
|
||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
||||
<normApi.h></FONT></FONT></P>
|
||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>bool
|
||||
NormAddAckingNode(<A HREF="#NormSessionHandle">NormSessionHandle</A> session,<BR> <A HREF="#NormNodeId">NormNodeId</A> nodeId);</FONT></FONT></P>
|
||||
<H4 CLASS="western">Description</H4>
|
||||
<P CLASS="western" STYLE="font-style: normal">When this function is
|
||||
called, the specified <FONT FACE="Courier"><U>nodeId</U></FONT> is
|
||||
added to the list of <I>NormNodes</I> used when NORM sender operation
|
||||
performs positive acknowledgement (ACK) collection for the specified
|
||||
<FONT FACE="Courier"><U>session</U></FONT>. The optional NORM
|
||||
positive acknowledgement collection occurs when a specified
|
||||
transmission point (see <FONT FACE="Courier"><A HREF="#NormSetWatermark()">NormSetWatermark()</A>)</FONT>
|
||||
is reached or for specialized protocol actions such as
|
||||
positively-acknowledged application-defined commands. Additionally a
|
||||
value of <FONT FACE="Courier"><U>nodeId</U></FONT> equal to
|
||||
<FONT FACE="Courier"><I>NORM_NODE_NONE</I></FONT> may be set to force
|
||||
the watermark flushing process through a full <FONT FACE="Courier"><I>NORM_ROBUST_FACTOR</I></FONT>
|
||||
number of rounds regardless of actual acking nodes. Otherwise the
|
||||
flushing process is terminated when all of the nodes in the acking
|
||||
node list have responded.</P>
|
||||
<H4 CLASS="western">Return Values</H4>
|
||||
<P CLASS="western" STYLE="font-style: normal">The function returns
|
||||
<FONT FACE="Courier"><I>true</I></FONT> upon success and <FONT FACE="Courier"><I>false</I></FONT>
|
||||
upon failure. The only failure condition is that insufficient memory
|
||||
resources were available. If a specific <FONT FACE="Courier"><U>nodeId</U></FONT>
|
||||
is added more than once, this has no effect.</P>
|
||||
<H3 CLASS="functionheading-western"><A NAME="NormRemoveAckingNode()">NormRemoveAckingNode()</A></H3>
|
||||
<H4 CLASS="western">Synopsis</H4>
|
||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
||||
<normApi.h></FONT></FONT></P>
|
||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>void
|
||||
NormRemoveAckingNode(<A HREF="#NormSessionHandle">NormSessionHandle</A> session,<BR> <A HREF="#NormNodeId">NormNodeId</A> nodeId);</FONT></FONT></P>
|
||||
<H4 CLASS="western">Description</H4>
|
||||
<P CLASS="western" STYLE="font-style: normal">This function deletes
|
||||
the specified <FONT FACE="Courier"><U>nodeId</U></FONT> from the list
|
||||
of <I>NormNodes</I> used when NORM sender operation performs positive
|
||||
acknowledgement (ACK) collection for the specified <FONT FACE="Courier"><U>session</U></FONT>.
|
||||
Note that if the <FONT FACE="Courier"><U>nodeId</U></FONT>
|
||||
<FONT FACE="Courier"><I>NORM_NODE_NONE</I></FONT> has been added to
|
||||
the list, it too must be removed to change the watermark flushing
|
||||
behavior if desired.</P>
|
||||
<H4 CLASS="western">Return Values</H4>
|
||||
<P CLASS="western" STYLE="font-style: normal">The function has no
|
||||
return values.</P>
|
||||
<H3 CLASS="functionheading-western"><A NAME="NormGetAckingStatus()">NormGetAckingStatus()</A></H3>
|
||||
<H4 CLASS="western">Synopsis</H4>
|
||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
||||
<normApi.h></FONT></FONT></P>
|
||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2><A HREF="#NormAckingStatus">NormAckingStatus</A>
|
||||
NormGetAckingStatus(<A HREF="#NormSessionHandle">NormSessionHandle</A> session,<BR> <A HREF="#NormNodeId">NormNodeId</A> nodeId
|
||||
=
|
||||
NORM_NODE_ANY);</FONT></FONT></P>
|
||||
<H4 CLASS="western">Description</H4>
|
||||
<P CLASS="western" STYLE="font-style: normal">This function queries
|
||||
the status of the watermark flushing process and/or positive
|
||||
acknowledgment collection initiated by a prior call to
|
||||
<FONT FACE="Courier"><A HREF="#NormSetWatermark()">NormSetWatermark()</A></FONT> for the given <FONT FACE="Courier"><U>session</U></FONT>.
|
||||
In general, it is expected that applications will invoke this
|
||||
function <I>after</I> the corresponding <FONT FACE="Courier"><I>NORM_TX_WATERMARK_COMPLETED</I></FONT>
|
||||
event has been posted. Setting the default parameter value <FONT FACE="Courier"><U>nodeId</U></FONT>
|
||||
= <FONT FACE="Courier"><I>NORM_NODE_ANY</I></FONT> returns a "status"
|
||||
indication for the overall process. Also, individual <FONT FACE="Courier"><U>nodeId</U></FONT>
|
||||
values may be queried using the <FONT FACE="Courier"><A HREF="#NormNodeId">NormNodeId</A></FONT>
|
||||
values of receivers that were included in previous calls to
|
||||
<FONT FACE="Courier"><A HREF="#NormAddAckingNode()">NormAddAckingNode()</A></FONT> to populate the
|
||||
sender <FONT FACE="Courier"><U>session</U></FONT>'s acking node list.
|
||||
|
||||
</P>
|
||||
<P CLASS="western" STYLE="font-style: normal">If the
|
||||
flushing/acknowledgment process is being used for application flow
|
||||
control, the sender application may wish to reset the watermark and
|
||||
flushing process (using <FONT FACE="Courier"><A HREF="#NormSetWatermark()">NormSetWatermark()</A></FONT>)
|
||||
if the response indicates that some nodes have failed to respond.
|
||||
However, note that the flushing/acknowledgment process itself does
|
||||
elicit NACKs from receivers as needed and is interrupted and reset by
|
||||
any repair response that occurs. Thus, even by the time the flushing
|
||||
process has completed (and <FONT FACE="Courier"><I>NORM_TX_WATERMARK_COMPLETED</I></FONT>
|
||||
is posted) once, this is an indication that the NORM protocol has
|
||||
made a valiant attempt to deliver the content. Resetting the
|
||||
watermark process <I>can</I> increase robustness, but it may be in
|
||||
vain to repeat this process multiple times when likely network
|
||||
connectivity has been lost or expected receivers have failed (dropped
|
||||
out, shut down, etc).</P>
|
||||
<H4 CLASS="western">Return Values</H4>
|
||||
<P CLASS="western" STYLE="font-style: normal; page-break-after: avoid">
|
||||
Possible return values include:</P>
|
||||
<TABLE WIDTH=592 BORDER=1 BORDERCOLOR="#000000" CELLPADDING=8 CELLSPACING=0>
|
||||
<COL WIDTH=200>
|
||||
<COL WIDTH=358>
|
||||
<TR VALIGN=TOP>
|
||||
<TD WIDTH=200>
|
||||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid; page-break-after: avoid">
|
||||
NORM_ACK_INVALID</P>
|
||||
</TD>
|
||||
<TD WIDTH=358>
|
||||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid; page-break-after: avoid">
|
||||
The given session is invalid or the given <FONT FACE="Courier"><U>nodeId</U></FONT>
|
||||
is not in the session's acking list.</P>
|
||||
</TD>
|
||||
</TR>
|
||||
<TR VALIGN=TOP>
|
||||
<TD WIDTH=200>
|
||||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid; page-break-after: avoid">
|
||||
NORM_ACK_FAILURE</P>
|
||||
</TD>
|
||||
<TD WIDTH=358>
|
||||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid; page-break-after: avoid">
|
||||
The positive acknowledgement collection process did not receive
|
||||
acknowledgment from every listed receiver (<FONT FACE="Courier"><U>nodeId</U></FONT>
|
||||
= <FONT FACE="Courier"><I>NORM_NODE_ANY</I></FONT>) or the
|
||||
identified <FONT FACE="Courier"><U>nodeId</U></FONT> did not
|
||||
respond.</P>
|
||||
</TD>
|
||||
</TR>
|
||||
<TR VALIGN=TOP>
|
||||
<TD WIDTH=200>
|
||||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid; page-break-after: avoid">
|
||||
NORM_ACK_PENDING</P>
|
||||
</TD>
|
||||
<TD WIDTH=358>
|
||||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid; page-break-after: avoid">
|
||||
The flushing process at large has not yet completed (<FONT FACE="Courier"><U>nodeId</U></FONT>
|
||||
= <FONT FACE="Courier"><I>NORM_NODE_ANY</I></FONT>) or the given
|
||||
individual <FONT FACE="Courier"><U>nodeId</U></FONT> is still
|
||||
being queried for response.</P>
|
||||
</TD>
|
||||
</TR>
|
||||
<TR VALIGN=TOP>
|
||||
<TD WIDTH=200>
|
||||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||
NORM_ACK_SUCCESS</P>
|
||||
</TD>
|
||||
<TD WIDTH=358>
|
||||
<P CLASS="western" STYLE="font-style: normal; page-break-inside: avoid">
|
||||
All receivers (<FONT FACE="Courier"><U>nodeId</U></FONT> =
|
||||
<FONT FACE="Courier"><I>NORM_NODE_ANY</I></FONT>) responded with
|
||||
positive acknowledgement or the given specific <FONT FACE="Courier"><U>nodeId</U></FONT>
|
||||
did acknowledge.</P>
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
<H2 CLASS="western"><A NAME="NORM Receiver Functions">NORM Receiver Functions</A></H2>
|
||||
<H3 CLASS="functionheading-western"><A NAME="NormStartReceiver()">NormStartReceiver()</A></H3>
|
||||
<H4 CLASS="western">Synopsis</H4>
|
||||
<P STYLE="font-style: normal; page-break-after: avoid"><FONT FACE="Courier"><FONT SIZE=2>#include
|
||||
|
|
@ -3047,7 +3287,7 @@ associate some application context with stream position.</P>
|
|||
the current read offset in bytes. The return value is undefined for
|
||||
sender streams. There is no error result.
|
||||
</P>
|
||||
<H2 CLASS="western">NORM Object Functions</H2>
|
||||
<H2 CLASS="western"><A NAME="NORM Object Functions">NORM Object Functions</A></H2>
|
||||
<P CLASS="western" STYLE="font-style: normal">The functions described
|
||||
in this section may be used for sender or receiver purposes to manage
|
||||
transmission and reception of NORM transport objects. In most cases,
|
||||
|
|
@ -3442,7 +3682,7 @@ valid for the same period that the <FONT FACE="Courier"><U>objectHandle</U></FON
|
|||
is valid. The returned <FONT FACE="Courier"><A HREF="#NormNodeHandle">NormNodeHandle</A></FONT>
|
||||
may optionally be retained for further use by the application using
|
||||
the <FONT FACE="Courier"><A HREF="#NormNodeRetain()">NormNodeRetain()</A></FONT> function call. The
|
||||
returned value can be used in the NORM Node Functions described later
|
||||
returned value can be used in the <A HREF="#NORM Node Functions">NORM Node Functions</A> described later
|
||||
in this document.</P>
|
||||
<H4 CLASS="western">Return Values</H4>
|
||||
<P CLASS="western" STYLE="font-style: normal">This function returns
|
||||
|
|
@ -3451,7 +3691,7 @@ remote sender of the transport object associated with the given
|
|||
<FONT FACE="Courier"><U>objectHandle</U></FONT> parameter. A value
|
||||
of NORM_NODE_INVALID is returned if the specified <FONT FACE="Courier"><U>objectHandle</U></FONT>
|
||||
references a locally originated, sender object.</P>
|
||||
<H2 CLASS="western">NORM Node Functions</H2>
|
||||
<H2 CLASS="western"><A NAME="NORM Node Functions">NORM Node Functions</A></H2>
|
||||
<P CLASS="western" STYLE="font-style: normal">The functions described
|
||||
in this section may be used for NORM sender or receiver (most
|
||||
typically receiver) purposes to retrieve additional information about
|
||||
|
|
|
|||
Binary file not shown.
18
VERSION.TXT
18
VERSION.TXT
|
|
@ -1,5 +1,23 @@
|
|||
NORM Version History
|
||||
|
||||
Version 1.3b6
|
||||
=============
|
||||
- Fixed some oversite bugs that crept in with changes in 1.3b5
|
||||
(Fixed code related to NormNode/NormObject retain and release)
|
||||
- Changed NORM_TX_QUEUE_VACANCY posting behavior to be less chatty.
|
||||
NORM_TX_QUEUE_VACANCY now posted _only_ after a call to
|
||||
NormStreamWrite() fails to fulfill a full write request
|
||||
(i.e. returns less than the "numBytes" requested to be written)
|
||||
This helps prevent build up of these notifications in multi-
|
||||
threaded applications that write to a stream in a different
|
||||
thread than is fetching events via NormGetNextEvent().
|
||||
- Added NORM_TX_WATERMARK_COMPLETED notification and NormGetAckingStatus()
|
||||
function to provide API support for optional positive acknowledgment
|
||||
(ACK) collection in NORM implementation. Note that use of
|
||||
NormAddAckingNode(session, NORM_NODE_NONE) enables a NACK-based
|
||||
watermark flushing concurrent with ongoing data transmission that
|
||||
can be used as a scalable application-level flow control mechanism.
|
||||
|
||||
Version 1.3b5
|
||||
=============
|
||||
- Changed ProtoSocket::GetInterfaceAddress() and related methods on Win32
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ class NormInstance : public NormController
|
|||
|
||||
void PurgeObjectNotifications(NormObjectHandle objectHandle);
|
||||
|
||||
unsigned long CountCompletedObjects(NormSession* theSession);
|
||||
|
||||
ProtoDispatcher::Descriptor GetDescriptor() const
|
||||
{
|
||||
#ifdef WIN32
|
||||
|
|
@ -57,6 +59,7 @@ class NormInstance : public NormController
|
|||
|
||||
static NormInstance* GetInstanceFromSession(NormSessionHandle sessionHandle)
|
||||
{
|
||||
if (NORM_SESSION_INVALID == sessionHandle) return ((NormInstance*)NULL);
|
||||
NormSession* session = (NormSession*)sessionHandle;
|
||||
NormInstance* theInstance = static_cast<NormInstance*>(session->GetSessionMgr().GetController());
|
||||
return theInstance;
|
||||
|
|
@ -64,11 +67,13 @@ class NormInstance : public NormController
|
|||
}
|
||||
static NormInstance* GetInstanceFromNode(NormNodeHandle nodeHandle)
|
||||
{
|
||||
if (NORM_NODE_INVALID == nodeHandle) return ((NormInstance*)NULL);
|
||||
NormSession& session = ((NormNode*)nodeHandle)->GetSession();
|
||||
return static_cast<NormInstance*>(session.GetSessionMgr().GetController());
|
||||
}
|
||||
static NormInstance* GetInstanceFromObject(NormObjectHandle objectHandle)
|
||||
{
|
||||
if (NORM_OBJECT_INVALID == objectHandle) return ((NormInstance*)NULL);
|
||||
NormSession& session = ((NormObject*)objectHandle)->GetSession();;
|
||||
return static_cast<NormInstance*>(session.GetSessionMgr().GetController());
|
||||
}
|
||||
|
|
@ -610,6 +615,21 @@ void NormInstance::Shutdown()
|
|||
notify_pool.Destroy();
|
||||
} // end NormInstance::Shutdown()
|
||||
|
||||
unsigned long NormInstance::CountCompletedObjects(NormSession* session)
|
||||
{
|
||||
unsigned long result = 0UL;
|
||||
Notification* n = notify_queue.GetHead();
|
||||
while (NULL != n)
|
||||
{
|
||||
if ((session == n->event.session) &&
|
||||
(NORM_RX_OBJECT_COMPLETED == n->event.type))
|
||||
{
|
||||
result ++;
|
||||
}
|
||||
n = n->GetNext();
|
||||
}
|
||||
return result;
|
||||
} // end NormInstance::CountCompletedObjects()
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// NORM API FUNCTION IMPLEMENTATIONS
|
||||
|
|
@ -1024,35 +1044,6 @@ void NormSetGrttProbingInterval(NormSessionHandle sessionHandle,
|
|||
}
|
||||
} // end NormSetGrttProbingInterval()
|
||||
|
||||
|
||||
|
||||
bool NormAddAckingNode(NormSessionHandle sessionHandle,
|
||||
NormNodeId nodeId)
|
||||
{
|
||||
bool result = false;
|
||||
NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle);
|
||||
if (instance && instance->dispatcher.SuspendThread())
|
||||
{
|
||||
NormSession* session = (NormSession*)sessionHandle;
|
||||
if (session)
|
||||
result = session->ServerAddAckingNode(nodeId);
|
||||
instance->dispatcher.ResumeThread();
|
||||
}
|
||||
return result;
|
||||
} // end NormAddAckingNode()
|
||||
|
||||
void NormRemoveAckingNode(NormSessionHandle sessionHandle,
|
||||
NormNodeId nodeId)
|
||||
{
|
||||
NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle);
|
||||
if (instance && instance->dispatcher.SuspendThread())
|
||||
{
|
||||
NormSession* session = (NormSession*)sessionHandle;
|
||||
if (session) session->ServerRemoveAckingNode(nodeId);
|
||||
instance->dispatcher.ResumeThread();
|
||||
}
|
||||
} // end NormRemoveAckingNode()
|
||||
|
||||
NormObjectHandle NormFileEnqueue(NormSessionHandle sessionHandle,
|
||||
const char* fileName,
|
||||
const char* infoPtr,
|
||||
|
|
@ -1249,6 +1240,50 @@ bool NormSetWatermark(NormSessionHandle sessionHandle,
|
|||
return result;
|
||||
} // end NormSetWatermark()
|
||||
|
||||
bool NormAddAckingNode(NormSessionHandle sessionHandle,
|
||||
NormNodeId nodeId)
|
||||
{
|
||||
bool result = false;
|
||||
NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle);
|
||||
if (instance && instance->dispatcher.SuspendThread())
|
||||
{
|
||||
NormSession* session = (NormSession*)sessionHandle;
|
||||
if (session)
|
||||
result = session->ServerAddAckingNode(nodeId);
|
||||
instance->dispatcher.ResumeThread();
|
||||
}
|
||||
return result;
|
||||
} // end NormAddAckingNode()
|
||||
|
||||
void NormRemoveAckingNode(NormSessionHandle sessionHandle,
|
||||
NormNodeId nodeId)
|
||||
{
|
||||
NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle);
|
||||
if (instance && instance->dispatcher.SuspendThread())
|
||||
{
|
||||
NormSession* session = (NormSession*)sessionHandle;
|
||||
if (session) session->ServerRemoveAckingNode(nodeId);
|
||||
instance->dispatcher.ResumeThread();
|
||||
}
|
||||
} // end NormRemoveAckingNode()
|
||||
|
||||
NormAckingStatus NormGetAckingStatus(NormSessionHandle sessionHandle,
|
||||
NormNodeId nodeId)
|
||||
{
|
||||
NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle);
|
||||
if (instance && instance->dispatcher.SuspendThread())
|
||||
{
|
||||
NormSession* session = (NormSession*)sessionHandle;
|
||||
NormAckingStatus status =
|
||||
(NormAckingStatus)session->ServerGetAckingStatus(nodeId);
|
||||
instance->dispatcher.ResumeThread();
|
||||
return status;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NORM_ACK_INVALID;
|
||||
}
|
||||
} // end NormGetAckingNodeStatus()
|
||||
|
||||
/** NORM Receiver Functions */
|
||||
|
||||
|
|
@ -1260,10 +1295,7 @@ bool NormStartReceiver(NormSessionHandle sessionHandle,
|
|||
if (instance && instance->dispatcher.SuspendThread())
|
||||
{
|
||||
NormSession* session = (NormSession*)sessionHandle;
|
||||
if (session)
|
||||
result = session->StartClient(bufferSpace);
|
||||
else
|
||||
result = false;
|
||||
result = session->StartClient(bufferSpace);
|
||||
instance->dispatcher.ResumeThread();
|
||||
}
|
||||
return result;
|
||||
|
|
@ -1276,7 +1308,7 @@ void NormStopReceiver(NormSessionHandle sessionHandle)
|
|||
if (instance && instance->dispatcher.SuspendThread())
|
||||
{
|
||||
NormSession* session = (NormSession*)sessionHandle;
|
||||
if (session) session->StopClient();
|
||||
session->StopClient();
|
||||
instance->dispatcher.ResumeThread();
|
||||
}
|
||||
} // end NormStopReceiver()
|
||||
|
|
@ -1364,8 +1396,7 @@ bool NormStreamRead(NormObjectHandle streamHandle,
|
|||
{
|
||||
NormStreamObject* stream =
|
||||
static_cast<NormStreamObject*>((NormObject*)streamHandle);
|
||||
if (stream)
|
||||
result = stream->Read(buffer, numBytes);
|
||||
result = stream->Read(buffer, numBytes);
|
||||
instance->dispatcher.ResumeThread();
|
||||
}
|
||||
return result;
|
||||
|
|
@ -1380,8 +1411,7 @@ bool NormStreamSeekMsgStart(NormObjectHandle streamHandle)
|
|||
NormStreamObject* stream =
|
||||
static_cast<NormStreamObject*>((NormObject*)streamHandle);
|
||||
unsigned int numBytes = 0;
|
||||
if (stream)
|
||||
result = stream->Read(NULL, &numBytes, true);
|
||||
result = stream->Read(NULL, &numBytes, true);
|
||||
instance->dispatcher.ResumeThread();
|
||||
}
|
||||
return result;
|
||||
|
|
@ -1391,7 +1421,10 @@ bool NormStreamSeekMsgStart(NormObjectHandle streamHandle)
|
|||
unsigned long NormStreamGetReadOffset(NormObjectHandle streamHandle)
|
||||
{
|
||||
NormStreamObject* stream = static_cast<NormStreamObject*>((NormObject*)streamHandle);
|
||||
return stream->GetCurrentReadOffset();
|
||||
if (stream)
|
||||
return stream->GetCurrentReadOffset();
|
||||
else
|
||||
return 0;
|
||||
} // end NormStreamGetReadOffset()
|
||||
|
||||
|
||||
|
|
@ -1641,3 +1674,16 @@ void NormNodeRelease(NormNodeHandle nodeHandle)
|
|||
// the app to install an event handler callback and dispatch
|
||||
// events with a "NormDispatchEvents()" call ...
|
||||
//
|
||||
|
||||
unsigned long NormCountCompletedObjects(NormSessionHandle sessionHandle)
|
||||
{
|
||||
unsigned long result = 0;
|
||||
NormSession* session = (NormSession*)sessionHandle;
|
||||
NormInstance* instance = NormInstance::GetInstanceFromSession(sessionHandle);
|
||||
if (instance && instance->dispatcher.SuspendThread())
|
||||
{
|
||||
result = instance->CountCompletedObjects(session);
|
||||
instance->dispatcher.ResumeThread();
|
||||
}
|
||||
return result;
|
||||
} // end long NormCountCompletedObjects()
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
// C++ code continues to evolve. But, until this notice
|
||||
// is removed, the API shouldn't be considered final.
|
||||
|
||||
// NORM API control
|
||||
/** NORM API Types */
|
||||
typedef const void* NormInstanceHandle;
|
||||
extern const NormInstanceHandle NORM_INSTANCE_INVALID;
|
||||
|
||||
|
|
@ -66,6 +66,14 @@ enum NormNackingMode
|
|||
NORM_NACK_NORMAL
|
||||
};
|
||||
|
||||
enum NormAckingStatus
|
||||
{
|
||||
NORM_ACK_INVALID,
|
||||
NORM_ACK_FAILURE,
|
||||
NORM_ACK_PENDING,
|
||||
NORM_ACK_SUCCESS
|
||||
};
|
||||
|
||||
enum NormProbingMode
|
||||
{
|
||||
NORM_PROBE_NONE,
|
||||
|
|
@ -85,6 +93,7 @@ enum NormEventType
|
|||
NORM_TX_QUEUE_VACANCY,
|
||||
NORM_TX_QUEUE_EMPTY,
|
||||
NORM_TX_FLUSH_COMPLETED,
|
||||
NORM_TX_WATERMARK_COMPLETED,
|
||||
NORM_TX_OBJECT_SENT,
|
||||
NORM_TX_OBJECT_PURGED,
|
||||
NORM_LOCAL_SERVER_CLOSED,
|
||||
|
|
@ -221,12 +230,6 @@ void NormSetGrttProbingInterval(NormSessionHandle sessionHandle,
|
|||
double intervalMin,
|
||||
double intervalMax);
|
||||
|
||||
bool NormAddAckingNode(NormSessionHandle sessionHandle,
|
||||
NormNodeId nodeId);
|
||||
|
||||
void NormRemoveAckingNode(NormSessionHandle sessionHandle,
|
||||
NormNodeId nodeId);
|
||||
|
||||
NormObjectHandle NormFileEnqueue(NormSessionHandle sessionHandle,
|
||||
const char* fileName,
|
||||
const char* infoPtr = (const char*)0,
|
||||
|
|
@ -261,13 +264,22 @@ void NormStreamSetPushEnable(NormObjectHandle streamHandle,
|
|||
|
||||
bool NormStreamHasVacancy(NormObjectHandle streamHandle);
|
||||
|
||||
NormSize NormGetObjectSize(NormObjectHandle objectHandle);
|
||||
|
||||
void NormStreamMarkEom(NormObjectHandle streamHandle);
|
||||
|
||||
bool NormSetWatermark(NormSessionHandle sessionHandle,
|
||||
NormObjectHandle objectHandle);
|
||||
|
||||
bool NormAddAckingNode(NormSessionHandle sessionHandle,
|
||||
NormNodeId nodeId);
|
||||
|
||||
void NormRemoveAckingNode(NormSessionHandle sessionHandle,
|
||||
NormNodeId nodeId);
|
||||
|
||||
NormAckingStatus NormGetAckingStatus(NormSessionHandle sessionHandle,
|
||||
NormNodeId nodeId = NORM_NODE_ANY);
|
||||
|
||||
/* NORM Receiver Functions */
|
||||
|
||||
bool NormStartReceiver(NormSessionHandle sessionHandle,
|
||||
unsigned long bufferSpace);
|
||||
|
||||
|
|
@ -359,5 +371,9 @@ void NormNodeRetain(NormNodeHandle nodeHandle);
|
|||
|
||||
void NormNodeRelease(NormNodeHandle nodeHandle);
|
||||
|
||||
/** Some experimental functions */
|
||||
|
||||
unsigned long NormCountCompletedObjects(NormSessionHandle sessionHandle);
|
||||
|
||||
|
||||
#endif // _NORM_API
|
||||
|
|
|
|||
|
|
@ -437,6 +437,7 @@ void NormServerNode::HandleCommand(const struct timeval& currentTime,
|
|||
NormNodeId localId = LocalNodeId();
|
||||
for (UINT16 i = 0; i < nodeCount; i++)
|
||||
{
|
||||
// (TBD) also ACK if NORM_NODE_ANY is listed???
|
||||
if (flush.GetAckingNodeId(i) == localId)
|
||||
{
|
||||
doAck = true;
|
||||
|
|
@ -1084,7 +1085,6 @@ void NormServerNode::HandleObjectMessage(const NormObjectMsg& msg)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (repair_boundary)
|
||||
{
|
||||
case BLOCK_BOUNDARY:
|
||||
|
|
@ -1296,6 +1296,7 @@ bool NormServerNode::PassiveRepairCheck(NormObjectId objectId,
|
|||
NormBlockId blockId,
|
||||
NormSegmentId segmentId)
|
||||
{
|
||||
if (!synchronized) return true;
|
||||
NormObjectId nextId;
|
||||
if (GetFirstPending(nextId))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -148,13 +148,14 @@ class NormAckingNode : public NormNode
|
|||
NormAckingNode(class NormSession& theSession, NormNodeId nodeId);
|
||||
~NormAckingNode();
|
||||
bool IsPending() const
|
||||
{return (!ack_received &&( req_count > 0));}
|
||||
{return (!ack_received && ( req_count > 0));}
|
||||
void Reset(unsigned int maxAttempts = NORM_ROBUST_FACTOR)
|
||||
{
|
||||
ack_received = false;
|
||||
req_count = maxAttempts;
|
||||
}
|
||||
void DecrementReqCount() {if (req_count > 0) req_count--;}
|
||||
void ResetReqCount() {req_count = NORM_ROBUST_FACTOR;}
|
||||
unsigned int GetReqCount() const {return req_count;}
|
||||
bool AckReceived() const {return ack_received;}
|
||||
void MarkAckReceived() {ack_received = true;}
|
||||
|
|
|
|||
|
|
@ -18,9 +18,14 @@ NormObject::NormObject(NormObject::Type theType,
|
|||
info_ptr(NULL), info_len(0), accepted(false), notify_on_update(true)
|
||||
{
|
||||
if (theServer)
|
||||
{
|
||||
nacking_mode = theServer->GetDefaultNackingMode();
|
||||
theServer->Retain();
|
||||
}
|
||||
else
|
||||
{
|
||||
nacking_mode = NACK_NORMAL; // it doesn't really matter if !theServer
|
||||
}
|
||||
}
|
||||
|
||||
NormObject::~NormObject()
|
||||
|
|
@ -47,7 +52,6 @@ void NormObject::Release()
|
|||
else
|
||||
{
|
||||
DMSG(0, "NormObject::Release() releasing non-retained object?!\n");
|
||||
ASSERT(0);
|
||||
}
|
||||
if (0 == reference_count) delete this;
|
||||
} // end NormObject::Release()
|
||||
|
|
@ -1677,6 +1681,7 @@ void NormStreamObject::StreamAdvance()
|
|||
|
||||
bool NormObject::CalculateBlockParity(NormBlock* block)
|
||||
{
|
||||
if (0 == nparity) return true;
|
||||
char buffer[NormMsg::MAX_SIZE];
|
||||
UINT16 numData = GetBlockSize(block->GetId());
|
||||
for (UINT16 i = 0; i < numData; i++)
|
||||
|
|
@ -2548,14 +2553,18 @@ UINT16 NormStreamObject::ReadSegment(NormBlockId blockId,
|
|||
if ((UINT32)offsetDelta < object_size.LSB())
|
||||
{
|
||||
NormBlock* b = stream_buffer.Find(stream_buffer.RangeLo());
|
||||
if (b && !b->IsPending()) write_vacancy = true;
|
||||
if (b && !b->IsPending())
|
||||
{
|
||||
write_vacancy = true;
|
||||
session.Notify(NormController::TX_QUEUE_VACANCY, NULL, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (write_vacancy && !posted_tx_queue_vacancy)
|
||||
/*if (HasVacancy() && !posted_tx_queue_vacancy)
|
||||
{
|
||||
posted_tx_queue_vacancy = true;
|
||||
session.Notify(NormController::TX_QUEUE_VACANCY, NULL, this);
|
||||
}
|
||||
} */
|
||||
|
||||
UINT16 segmentLength = NormDataMsg::ReadStreamPayloadLength(segment);
|
||||
ASSERT(segmentLength <= segment_size);
|
||||
|
|
@ -3103,7 +3112,7 @@ UINT32 NormStreamObject::Write(const char* buffer, UINT32 len, bool eom)
|
|||
{
|
||||
if (0 != len)
|
||||
{
|
||||
DMSG(0, "NormStreamObject::Write() error: stream is closing\n");
|
||||
DMSG(0, "NormStreamObject::Write() error: stream is closing (len:%lu eom:%d)\n", len, eom);
|
||||
len = 0;
|
||||
}
|
||||
break;
|
||||
|
|
@ -3254,7 +3263,7 @@ UINT32 NormStreamObject::Write(const char* buffer, UINT32 len, bool eom)
|
|||
msg_start = true;
|
||||
if (FLUSH_ACTIVE == flush_mode)
|
||||
flush_pending = true;
|
||||
else
|
||||
else if (!stream_closing)
|
||||
flush_pending = false;
|
||||
if ((0 != nBytes) || (FLUSH_NONE != flush_mode))
|
||||
session.TouchServer();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#include "normSegment.h"
|
||||
|
||||
NormSegmentPool::NormSegmentPool()
|
||||
: seg_size(0), seg_count(0), seg_total(0), seg_list(NULL),
|
||||
: seg_size(0), seg_count(0), seg_total(0), seg_list(NULL), seg_pool(NULL),
|
||||
peak_usage(0), overruns(0), overrun_flag(false)
|
||||
{
|
||||
}
|
||||
|
|
@ -14,7 +14,7 @@ NormSegmentPool::~NormSegmentPool()
|
|||
|
||||
bool NormSegmentPool::Init(unsigned int count, unsigned int size)
|
||||
{
|
||||
if (seg_list) Destroy();
|
||||
if (seg_pool) Destroy();
|
||||
peak_usage = 0;
|
||||
overruns = 0;
|
||||
#ifdef SIMULATE
|
||||
|
|
@ -23,46 +23,41 @@ bool NormSegmentPool::Init(unsigned int count, unsigned int size)
|
|||
size = MIN(size, (SIM_PAYLOAD_MAX+1));
|
||||
#endif // SIMULATE
|
||||
// This makes sure we get appropriate alignment
|
||||
unsigned int alloc_size = size / sizeof(char*);
|
||||
if ((alloc_size*sizeof(char*)) < size) alloc_size++;
|
||||
seg_size = alloc_size * sizeof(char*);
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
char** ptr = new char*[alloc_size];
|
||||
if (ptr)
|
||||
{
|
||||
*ptr = seg_list;
|
||||
seg_list = (char*)ptr;
|
||||
seg_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
DMSG(0, "NormSegmentPool::Init() memory allocation error: %s\n",
|
||||
GetErrorString());
|
||||
seg_total = seg_count;
|
||||
Destroy();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
seg_total = seg_count;
|
||||
return true;
|
||||
unsigned int allocSize = size / sizeof(char*);
|
||||
if ((allocSize*sizeof(char*)) < size) allocSize++;
|
||||
seg_size = allocSize * sizeof(char*);
|
||||
seg_pool = new char*[allocSize * count];
|
||||
if (seg_pool)
|
||||
{
|
||||
char **ptr = seg_pool;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
*ptr = seg_list;
|
||||
seg_list = (char*)ptr;
|
||||
ptr += allocSize;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DMSG(0, "NormSegmentPool::Init() memory allocation error: %s\n",
|
||||
GetErrorString());
|
||||
Destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
seg_total = seg_count = count;
|
||||
return true;
|
||||
} // end NormSegmentPool::Init()
|
||||
|
||||
void NormSegmentPool::Destroy()
|
||||
{
|
||||
ASSERT(seg_count == seg_total);
|
||||
char* ptr = seg_list;
|
||||
while (ptr)
|
||||
{
|
||||
char* next;
|
||||
memcpy(&next, ptr, sizeof(char*));
|
||||
delete[] ptr;
|
||||
ptr = next;
|
||||
}
|
||||
seg_list = NULL;
|
||||
seg_count = 0;
|
||||
seg_total = 0;
|
||||
seg_size = 0;
|
||||
delete [] seg_pool;
|
||||
seg_pool = NULL;
|
||||
seg_list = NULL;
|
||||
seg_count = 0;
|
||||
seg_total = 0;
|
||||
seg_size = 0;
|
||||
} // end NormSegmentPool::Destroy()
|
||||
|
||||
char* NormSegmentPool::Get()
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ class NormSegmentPool
|
|||
//char** ptr = (char**)segment;
|
||||
//ptr = seg_list;
|
||||
// (TBD) avoid this system call
|
||||
memcpy(segment, &seg_list, sizeof(char*));
|
||||
//memcpy(segment, &seg_list, sizeof(char*));
|
||||
*((char**)segment) = seg_list; // this might make a warning on Solaris
|
||||
seg_list = segment;
|
||||
seg_count++;
|
||||
}
|
||||
|
|
@ -39,6 +40,7 @@ class NormSegmentPool
|
|||
unsigned int seg_count;
|
||||
unsigned int seg_total;
|
||||
char* seg_list;
|
||||
char** seg_pool;
|
||||
|
||||
unsigned long peak_usage;
|
||||
unsigned long overruns;
|
||||
|
|
|
|||
|
|
@ -240,12 +240,19 @@ void NormSession::SetTxRateInternal(double txRate)
|
|||
{
|
||||
if (tx_timer.IsActive())
|
||||
{
|
||||
tx_timer.Deactivate();
|
||||
if (txRate > 0.0)
|
||||
{
|
||||
double adjustInterval = (tx_rate/txRate) * tx_timer.GetTimeRemaining();
|
||||
tx_timer.SetInterval(adjustInterval);
|
||||
ActivateTimer(tx_timer);
|
||||
if (adjustInterval > 0.100)
|
||||
{
|
||||
tx_timer.SetInterval(adjustInterval);
|
||||
tx_timer.Reschedule();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tx_timer.Deactivate();
|
||||
|
||||
}
|
||||
tx_rate = txRate;
|
||||
}
|
||||
|
|
@ -379,6 +386,7 @@ bool NormSession::StartServer(UINT16 instanceId,
|
|||
prev_update_time.tv_sec = prev_update_time.tv_usec = 0;
|
||||
sent_accumulator = 0;
|
||||
nominal_packet_size = (double)segmentSize;
|
||||
data_active = false;
|
||||
ndata = numData;
|
||||
nparity = numParity;
|
||||
is_server = true;
|
||||
|
|
@ -478,7 +486,7 @@ void NormSession::Serve()
|
|||
{
|
||||
// Determine next message (objectId::blockId::segmentId) to be sent
|
||||
NormObject* nextObj;
|
||||
NormObjectId nextObjectId;
|
||||
NormObjectId nextObjectId = next_tx_object_id;
|
||||
NormBlockId nextBlockId = 0;
|
||||
NormSegmentId nextSegmentId = 0;
|
||||
if (obj)
|
||||
|
|
@ -520,18 +528,32 @@ void NormSession::Serve()
|
|||
{
|
||||
// Nothing transmit pending, check for repair pending object
|
||||
NormObjectTable::Iterator iterator(tx_table);
|
||||
while ((nextObj = iterator.GetNextObject()))
|
||||
if (nextObj->IsRepairPending()) break;
|
||||
if (ServerGetFirstRepairPending(nextObjectId))
|
||||
{
|
||||
if (nextObj && (nextObj->GetId() < nextObjectId))
|
||||
while ((nextObj = iterator.GetNextObject()))
|
||||
{
|
||||
nextObjectId = nextObj->GetId();
|
||||
if (nextObjectId < nextObj->GetId())
|
||||
{
|
||||
nextObj = tx_table.Find(nextObjectId);
|
||||
break;
|
||||
}
|
||||
else if (nextObj->IsRepairPending())
|
||||
{
|
||||
nextObjectId = nextObj->GetId();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
nextObjectId = next_tx_object_id;
|
||||
while ((nextObj = iterator.GetNextObject()))
|
||||
{
|
||||
nextObj = tx_table.Find(nextObjectId);
|
||||
ASSERT(nextObj);
|
||||
if (nextObj->IsRepairPending())
|
||||
{
|
||||
nextObjectId = nextObj->GetId();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nextObj)
|
||||
|
|
@ -542,10 +564,6 @@ void NormSession::Serve()
|
|||
nextObj->FindRepairIndex(nextBlockId, nextSegmentId);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
nextObjectId = next_tx_object_id;
|
||||
}
|
||||
}
|
||||
if ((nextObjectId > watermark_object_id) ||
|
||||
((nextObjectId == watermark_object_id) &&
|
||||
|
|
@ -555,12 +573,29 @@ void NormSession::Serve()
|
|||
{
|
||||
if (ServerQueueWatermarkFlush())
|
||||
{
|
||||
watermark_active = true;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// (TBD) optionally return here to have ack collection temporarily suspend data transmission
|
||||
return;
|
||||
// (TBD) optionally return here to have ack collection temporarily
|
||||
// suspend forward progress of data transmission
|
||||
//return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reset non-acked acking nodes since server has rewound
|
||||
if (watermark_active)
|
||||
{
|
||||
watermark_active = false;
|
||||
NormNodeTreeIterator iterator(acking_node_tree);
|
||||
NormAckingNode* next;
|
||||
while ((next = static_cast<NormAckingNode*>(iterator.GetNextNode())))
|
||||
{
|
||||
//if (next->IsPending())
|
||||
next->ResetReqCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end if (watermark_pending)
|
||||
|
|
@ -572,6 +607,23 @@ void NormSession::Serve()
|
|||
{
|
||||
if (obj->NextServerMsg(msg))
|
||||
{
|
||||
if (cc_enable && !data_active)
|
||||
{
|
||||
data_active = true;
|
||||
if (probe_timer.IsActive())
|
||||
{
|
||||
double elapsed = probe_timer.GetInterval() - probe_timer.GetTimeRemaining();
|
||||
const NormCCNode* clr = static_cast<const NormCCNode*>(cc_node_list.Head());
|
||||
double probeInterval = (clr && clr->IsActive()) ?
|
||||
MIN(grtt_advertised, clr->GetRtt()) :
|
||||
grtt_advertised;
|
||||
if (elapsed > probeInterval)
|
||||
probe_timer.SetInterval(0.0);
|
||||
else
|
||||
probe_timer.SetInterval(probeInterval - elapsed);
|
||||
probe_timer.Reschedule();
|
||||
}
|
||||
}
|
||||
msg->SetDestination(address);
|
||||
msg->SetGrtt(grtt_quantized);
|
||||
msg->SetBackoffFactor((unsigned char)backoff_factor);
|
||||
|
|
@ -602,28 +654,29 @@ void NormSession::Serve()
|
|||
{
|
||||
// Queue flush message
|
||||
if (!flush_timer.IsActive())
|
||||
{
|
||||
if (flush_count < NORM_ROBUST_FACTOR)
|
||||
{
|
||||
ServerQueueFlush();
|
||||
}
|
||||
else if (NORM_ROBUST_FACTOR == flush_count)
|
||||
{
|
||||
DMSG(6, "NormSession::Serve() node>%lu server flush complete ...\n",
|
||||
LocalNodeId());
|
||||
flush_count++;
|
||||
if (stream->IsClosing())
|
||||
{
|
||||
stream->Close();
|
||||
stream->Retain();
|
||||
Notify(NormController::TX_OBJECT_PURGED, (NormServerNode*)NULL, stream);
|
||||
stream->Release();
|
||||
DeleteTxObject(stream);
|
||||
obj = NULL;
|
||||
ServerQueueFlush();
|
||||
}
|
||||
else if (NORM_ROBUST_FACTOR == flush_count)
|
||||
{
|
||||
DMSG(6, "NormSession::Serve() node>%lu server flush complete ...\n",
|
||||
LocalNodeId());
|
||||
flush_count++;
|
||||
if (stream->IsClosing())
|
||||
{
|
||||
stream->Close();
|
||||
Notify(NormController::TX_OBJECT_PURGED, (NormServerNode*)NULL, stream);
|
||||
DeleteTxObject(stream);
|
||||
obj = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!posted_tx_queue_empty)
|
||||
if (!posted_tx_queue_empty && !stream->IsClosing())
|
||||
{
|
||||
//data_active = false;
|
||||
posted_tx_queue_empty = true;
|
||||
Notify(NormController::TX_QUEUE_EMPTY, (NormServerNode*)NULL, obj);
|
||||
// (TBD) Was session deleted?
|
||||
|
|
@ -649,6 +702,7 @@ void NormSession::Serve()
|
|||
// No pending objects or positive acknowledgement request
|
||||
if (!posted_tx_queue_empty)
|
||||
{
|
||||
data_active = false;
|
||||
posted_tx_queue_empty = true;
|
||||
Notify(NormController::TX_QUEUE_EMPTY,
|
||||
(NormServerNode*)NULL,
|
||||
|
|
@ -666,7 +720,6 @@ void NormSession::Serve()
|
|||
{
|
||||
DMSG(6, "NormSession::Serve() node>%lu server flush complete ...\n",
|
||||
LocalNodeId());
|
||||
|
||||
Notify(NormController::TX_FLUSH_COMPLETED,
|
||||
(NormServerNode*)NULL,
|
||||
(NormObject*)NULL);
|
||||
|
|
@ -682,10 +735,11 @@ void NormSession::ServerSetWatermark(NormObjectId objectId,
|
|||
TRACE("NormSession::ServerSetWatermark(%hu:%lu:%hu) ...\n",
|
||||
(UINT16)objectId, (UINT32)blockId, (UINT16)segmentId);
|
||||
watermark_pending = true;
|
||||
watermark_active = false;
|
||||
watermark_object_id = objectId;
|
||||
watermark_block_id = blockId;
|
||||
watermark_segment_id = segmentId;
|
||||
acks_collected = 0;
|
||||
acking_success_count = 0;
|
||||
// Reset acking_node_list
|
||||
NormNodeTreeIterator iterator(acking_node_tree);
|
||||
NormNode* next;
|
||||
|
|
@ -721,16 +775,54 @@ bool NormSession::ServerAddAckingNode(NormNodeId nodeId)
|
|||
|
||||
void NormSession::ServerRemoveAckingNode(NormNodeId nodeId)
|
||||
{
|
||||
NormAckingNode* theNode = static_cast<NormAckingNode*>(acking_node_tree.FindNodeById(nodeId));
|
||||
NormAckingNode* theNode =
|
||||
static_cast<NormAckingNode*>(acking_node_tree.FindNodeById(nodeId));
|
||||
if (theNode)
|
||||
{
|
||||
if (watermark_pending && theNode->AckReceived())
|
||||
acks_collected--;
|
||||
acking_node_tree.DetachNode(theNode);
|
||||
acking_node_count--;
|
||||
}
|
||||
} // end NormSession::RemoveAckingNode()
|
||||
|
||||
NormSession::AckingStatus NormSession::ServerGetAckingStatus(NormNodeId nodeId)
|
||||
{
|
||||
if (NORM_NODE_ANY == nodeId)
|
||||
{
|
||||
// Return result based on overall success of acking process
|
||||
if (watermark_pending)
|
||||
{
|
||||
return ACK_PENDING;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (acking_success_count < acking_node_count)
|
||||
return ACK_FAILURE;
|
||||
else
|
||||
return ACK_SUCCESS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NormAckingNode* theNode =
|
||||
static_cast<NormAckingNode*>(acking_node_tree.FindNodeById(nodeId));
|
||||
if (theNode)
|
||||
{
|
||||
if (theNode->IsPending())
|
||||
return ACK_PENDING;
|
||||
else if (NORM_NODE_NONE == theNode->GetId())
|
||||
return ACK_SUCCESS;
|
||||
else if (theNode->AckReceived())
|
||||
return ACK_SUCCESS;
|
||||
else
|
||||
return ACK_FAILURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ACK_INVALID;
|
||||
}
|
||||
}
|
||||
} // end NormSession::ServerGetAckingStatus()
|
||||
|
||||
bool NormSession::ServerQueueWatermarkFlush()
|
||||
{
|
||||
if (flush_timer.IsActive()) return false;
|
||||
|
|
@ -748,9 +840,24 @@ bool NormSession::ServerQueueWatermarkFlush()
|
|||
NormNodeTreeIterator iterator(acking_node_tree);
|
||||
NormAckingNode* next;
|
||||
watermark_pending = false;
|
||||
NormAckingNode* nodeNone = NULL;
|
||||
acking_success_count = 0;
|
||||
while ((next = static_cast<NormAckingNode*>(iterator.GetNextNode())))
|
||||
{
|
||||
if (next->IsPending())
|
||||
// Save NORM_NODE_NONE for last
|
||||
if (NORM_NODE_NONE == next->GetId())
|
||||
{
|
||||
if (next->IsPending())
|
||||
nodeNone = next;
|
||||
else
|
||||
acking_success_count++; // implicit success for NORM_NODE_NONE
|
||||
continue;
|
||||
}
|
||||
if (next->AckReceived())
|
||||
{
|
||||
acking_success_count++; // ACK was received for this node
|
||||
}
|
||||
else if (next->IsPending())
|
||||
{
|
||||
// Add node to list
|
||||
if (flush->AppendAckingNode(next->GetId(), segment_size))
|
||||
|
|
@ -761,21 +868,39 @@ bool NormSession::ServerQueueWatermarkFlush()
|
|||
else
|
||||
{
|
||||
DMSG(8, "NormSession::ServeQueueWatermarkFlush() full cmd ...\n");
|
||||
nodeNone = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (NULL != nodeNone)
|
||||
{
|
||||
if (flush->AppendAckingNode(NORM_NODE_NONE, segment_size))
|
||||
{
|
||||
nodeNone->DecrementReqCount();
|
||||
watermark_pending = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
DMSG(8, "NormSession::ServeQueueWatermarkFlush() full cmd ...\n");
|
||||
}
|
||||
}
|
||||
if (watermark_pending)
|
||||
{
|
||||
flush_count++;
|
||||
if (flush_count < NORM_ROBUST_FACTOR) flush_count++;
|
||||
QueueMessage(flush);
|
||||
DMSG(8, "NormSession::ServeQueueWatermarkFlush() node>%lu cmd queued ...\n",
|
||||
LocalNodeId());
|
||||
}
|
||||
else if (NULL != acking_node_tree.GetRoot())
|
||||
{
|
||||
DMSG(4, "NormSession::ServeQueueWatermarkFlush() node>%lu watermark ack finished.\n");
|
||||
Notify(NormController::TX_WATERMARK_COMPLETED, (NormServerNode*)NULL, (NormObject*)NULL);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
DMSG(4, "NormSession::ServeQueueWatermarkFlush() node>%lu watermark ack finished incomplete\n");
|
||||
// (TBD) notify app
|
||||
DMSG(2, "NormSession::ServeQueueWatermarkFlush() node>%lu no acking nodes specified?!\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -819,7 +944,7 @@ void NormSession::ServerQueueFlush()
|
|||
// (TBD) send NORM_CMD(EOT) instead? - no
|
||||
if (ServerQueueSquelch(next_tx_object_id))
|
||||
{
|
||||
flush_count++;
|
||||
if (flush_count < NORM_ROBUST_FACTOR) flush_count++;
|
||||
flush_timer.SetInterval(2*grtt_advertised);
|
||||
ActivateTimer(flush_timer);
|
||||
}
|
||||
|
|
@ -839,7 +964,7 @@ void NormSession::ServerQueueFlush()
|
|||
flush->SetFecBlockId(blockId);
|
||||
flush->SetFecSymbolId(segmentId);
|
||||
QueueMessage(flush);
|
||||
flush_count++;
|
||||
if (flush_count < NORM_ROBUST_FACTOR) flush_count++;
|
||||
DMSG(4, "NormSession::ServerQueueFlush() node>%lu, flush queued (flush_count:%u)...\n",
|
||||
LocalNodeId(), flush_count);
|
||||
}
|
||||
|
|
@ -1058,7 +1183,7 @@ bool NormSession::QueueTxObject(NormObject* obj)
|
|||
count = tx_table.Count();
|
||||
}
|
||||
}
|
||||
// Attempt to queue the object
|
||||
// Attempt to queue the object (note it gets "retained" by the tx_table)
|
||||
if (!tx_table.Insert(obj))
|
||||
{
|
||||
DMSG(0, "NormSession::QueueTxObject() tx_table insert error\n");
|
||||
|
|
@ -1074,6 +1199,7 @@ bool NormSession::QueueTxObject(NormObject* obj)
|
|||
|
||||
void NormSession::DeleteTxObject(NormObject* obj)
|
||||
{
|
||||
ASSERT(obj);
|
||||
if (tx_table.Remove(obj))
|
||||
{
|
||||
NormObjectId objectId = obj->GetId();
|
||||
|
|
@ -1101,6 +1227,7 @@ void NormSession::SetTxCacheBounds(NormObjectSize sizeMax,
|
|||
{
|
||||
// Remove oldest non-pending
|
||||
NormObject* oldest = tx_table.Find(tx_table.RangeLo());
|
||||
ASSERT(oldest);
|
||||
Notify(NormController::TX_OBJECT_PURGED, (NormServerNode*)NULL, oldest);
|
||||
DeleteTxObject(oldest);
|
||||
count = tx_table.Count();
|
||||
|
|
@ -1878,13 +2005,6 @@ void NormSession::ServerHandleAckMessage(const struct timeval& currentTime, cons
|
|||
(watermark_segment_id == flushAck.GetFecSymbolId()))
|
||||
{
|
||||
acker->MarkAckReceived();
|
||||
acks_collected++;
|
||||
if (acks_collected >= acking_node_count)
|
||||
{
|
||||
watermark_pending = false;
|
||||
DMSG(4, "NormSession::ServerHandleAckMessage() watermark acknowledgement complete\n");
|
||||
// (TBD) notify app
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -2840,7 +2960,8 @@ bool NormSession::SendMessage(NormMsg& msg)
|
|||
if (probe_reset)
|
||||
{
|
||||
probe_reset = false;
|
||||
OnProbeTimeout(probe_timer);
|
||||
OnProbeTimeout(probe_timer); //we commented this out to give data a chance at low rates
|
||||
// we may want to re-visit this, it might compromis high rate performance a little
|
||||
ActivateTimer(probe_timer);
|
||||
}
|
||||
}
|
||||
|
|
@ -2870,12 +2991,11 @@ void NormSession::SetGrttProbingInterval(double intervalMin, double intervalMax)
|
|||
{
|
||||
double elapsed = probe_timer.GetInterval() - probe_timer.GetTimeRemaining();
|
||||
if (elapsed < 0.0) elapsed = 0.0;
|
||||
probe_timer.Deactivate();
|
||||
if (elapsed > grtt_interval)
|
||||
probe_timer.SetInterval(0.0);
|
||||
else
|
||||
probe_timer.SetInterval(grtt_interval - elapsed);
|
||||
ActivateTimer(probe_timer);
|
||||
probe_timer.Reschedule();
|
||||
}
|
||||
}
|
||||
} // end NormSession::SetGrttProbingInterval()
|
||||
|
|
@ -3088,23 +3208,31 @@ bool NormSession::OnProbeTimeout(ProtoTimer& /*theTimer*/)
|
|||
AdjustRate(false);
|
||||
|
||||
// Determine next probe_interval
|
||||
const NormCCNode* clr = static_cast<const NormCCNode*>(cc_node_list.Head());
|
||||
probeInterval = clr ? MIN(grtt_advertised, clr->GetRtt()) : grtt_advertised;
|
||||
//double nominalRate = ((double)segment_size)/((double)tx_rate);
|
||||
//probeInterval = MAX(probeInterval, nominalRate);
|
||||
if (data_active)
|
||||
{
|
||||
const NormCCNode* clr = static_cast<const NormCCNode*>(cc_node_list.Head());
|
||||
probeInterval = (clr && clr->IsActive()) ? MIN(grtt_advertised, clr->GetRtt()) : grtt_advertised;
|
||||
}
|
||||
else
|
||||
{
|
||||
probeInterval = grtt_interval;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Determine next probe_interval
|
||||
probeInterval = grtt_interval;
|
||||
}
|
||||
// perhaps this instead of the commented out probe_reset case???
|
||||
double nominalInterval = ((double)segment_size)/((double)tx_rate);
|
||||
if (nominalInterval > probeInterval) probeInterval = nominalInterval;
|
||||
|
||||
// Set probe_timer interval for next probe
|
||||
probe_timer.SetInterval(probeInterval);
|
||||
|
||||
QueueMessage(cmd);
|
||||
probe_pending = true;
|
||||
|
||||
// 3) Set probe_timer interval
|
||||
probe_timer.SetInterval(probeInterval);
|
||||
|
||||
return true;
|
||||
} // end NormSession::OnProbeTimeout()
|
||||
|
||||
|
|
@ -3117,33 +3245,42 @@ void NormSession::AdjustRate(bool onResponse)
|
|||
double txRate = tx_rate;
|
||||
if (onResponse)
|
||||
{
|
||||
// Adjust rate based on CLR feedback and
|
||||
// adjust probe schedule
|
||||
ASSERT(clr);
|
||||
// (TBD) check feedback age
|
||||
if (cc_slow_start)
|
||||
if (data_active) // adjust only if actively transmitting
|
||||
{
|
||||
txRate = clr->GetRate();
|
||||
DMSG(6, "NormSession::AdjustRate(slow start) clr>%lu newRate>%lf (oldRate>%lf sentRate>%lf clrRate>%lf\n",
|
||||
clr->GetId(), txRate*8.0/1000.0, tx_rate*8.0/1000.0, sent_rate*8.0/1000.0,
|
||||
clr->GetRate()*8.0/1000.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
double clrRate = clr->GetRate();
|
||||
if (clrRate > txRate)
|
||||
// Adjust rate based on CLR feedback and
|
||||
// adjust probe schedule
|
||||
ASSERT(clr);
|
||||
// (TBD) check feedback age
|
||||
if (cc_slow_start)
|
||||
{
|
||||
double linRate = txRate + segment_size;
|
||||
txRate = MIN(clrRate, linRate);
|
||||
txRate = clr->GetRate();
|
||||
DMSG(6, "NormSession::AdjustRate(slow start) clr>%lu newRate>%lf (oldRate>%lf sentRate>%lf clrRate>%lf\n",
|
||||
clr->GetId(), txRate*8.0/1000.0, tx_rate*8.0/1000.0, sent_rate*8.0/1000.0,
|
||||
clr->GetRate()*8.0/1000.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
txRate = clrRate;
|
||||
double clrRate = clr->GetRate();
|
||||
if (clrRate > txRate)
|
||||
{
|
||||
double linRate = txRate + segment_size;
|
||||
txRate = MIN(clrRate, linRate);
|
||||
}
|
||||
else
|
||||
{
|
||||
txRate = clrRate;
|
||||
}
|
||||
DMSG(6, "NormSession::AdjustRate(stdy state) clr>%lu newRate>%lf (rtt>%lf loss>%lf)\n",
|
||||
clr->GetId(), txRate*8.0/1000.0, clr->GetRtt(), clr->GetLoss());
|
||||
}
|
||||
DMSG(6, "NormSession::AdjustRate(stdy state) clr>%lu newRate>%lf (rtt>%lf loss>%lf)\n",
|
||||
clr->GetId(), txRate*8.0/1000.0, clr->GetRtt(), clr->GetLoss());
|
||||
}
|
||||
}
|
||||
else if (!data_active)
|
||||
{
|
||||
// reduce rate if no active data transmission
|
||||
// (TBD) Perhaps we want to be less aggressive here someday
|
||||
txRate *= 0.5;
|
||||
}
|
||||
else if (clr && clr->IsActive())
|
||||
{
|
||||
// (TBD) fix CC feedback aging ...
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ class NormController
|
|||
TX_QUEUE_VACANCY,
|
||||
TX_QUEUE_EMPTY,
|
||||
TX_FLUSH_COMPLETED,
|
||||
TX_WATERMARK_COMPLETED,
|
||||
TX_OBJECT_SENT,
|
||||
TX_OBJECT_PURGED,
|
||||
LOCAL_SERVER_CLOSED,
|
||||
|
|
@ -98,6 +99,13 @@ class NormSession
|
|||
static const UINT16 DEFAULT_NDATA;
|
||||
static const UINT16 DEFAULT_NPARITY;
|
||||
enum ProbingMode {PROBE_NONE, PROBE_PASSIVE, PROBE_ACTIVE};
|
||||
enum AckingStatus
|
||||
{
|
||||
ACK_INVALID,
|
||||
ACK_FAILURE,
|
||||
ACK_PENDING,
|
||||
ACK_SUCCESS
|
||||
};
|
||||
|
||||
// General methods
|
||||
const NormNodeId& LocalNodeId() const {return local_node_id;}
|
||||
|
|
@ -205,6 +213,7 @@ class NormSession
|
|||
NormSegmentId segmentId);
|
||||
bool ServerAddAckingNode(NormNodeId nodeId);
|
||||
void ServerRemoveAckingNode(NormNodeId nodeId);
|
||||
AckingStatus ServerGetAckingStatus(NormNodeId nodeId);
|
||||
|
||||
|
||||
UINT16 ServerSegmentSize() const {return segment_size;}
|
||||
|
|
@ -411,11 +420,12 @@ class NormSession
|
|||
// For postive acknowledgement collection
|
||||
NormNodeTree acking_node_tree;
|
||||
unsigned int acking_node_count;
|
||||
unsigned int acking_success_count;
|
||||
bool watermark_pending;
|
||||
bool watermark_active;
|
||||
NormObjectId watermark_object_id;
|
||||
NormBlockId watermark_block_id;
|
||||
NormSegmentId watermark_segment_id;
|
||||
unsigned int acks_collected;
|
||||
|
||||
// for unicast nack/cc feedback suppression
|
||||
bool advertise_repairs;
|
||||
|
|
@ -454,6 +464,7 @@ class NormSession
|
|||
struct timeval prev_update_time; // for sent_rate measurement
|
||||
unsigned long sent_accumulator; // for sent_rate measurement
|
||||
double nominal_packet_size;
|
||||
bool data_active; // true when actively sending data
|
||||
|
||||
// Client parameters
|
||||
bool is_client;
|
||||
|
|
|
|||
|
|
@ -28,16 +28,14 @@ int main(int argc, char* argv[])
|
|||
|
||||
NormSetCacheDirectory(instance, cachePath);
|
||||
|
||||
|
||||
|
||||
// Here's a trick to generate a _hopefully_ unique NormNodeId
|
||||
// based on an XOR of the system's IP address and the process id.
|
||||
// (We use ProtoAddress::GetEndIdentifier() to get the local
|
||||
// "default" IP address for the system)
|
||||
// (Note that passing "NORM_NODE_ANY" to the last arg of
|
||||
// NormCreateSession() does a similar thing but without
|
||||
// the process id ... perhaps we should add the process id
|
||||
// hack to that default NormNodeId picker?
|
||||
// the processId XOR ... perhaps we should add the processId
|
||||
// hack to that default "NORM_NODE_ANY" local NormNodeId picker???
|
||||
ProtoAddress localAddr;
|
||||
if (!localAddr.ResolveLocalAddress())
|
||||
{
|
||||
|
|
@ -59,10 +57,9 @@ int main(int argc, char* argv[])
|
|||
{
|
||||
localId ^= (NormNodeId)rand();
|
||||
}
|
||||
//localId = 15; // for testing purposes
|
||||
|
||||
|
||||
|
||||
|
||||
// Create a NORM session instance
|
||||
NormSessionHandle session = NormCreateSession(instance,
|
||||
"224.1.2.3",
|
||||
6003,
|
||||
|
|
@ -74,6 +71,7 @@ int main(int argc, char* argv[])
|
|||
//NormSetMessageTrace(session, true);
|
||||
// Uncomment to turn on some random packet loss
|
||||
//NormSetTxLoss(session, 10.0); // 10% packet loss
|
||||
//NormSetRxLoss(session, 20.0);
|
||||
struct timeval currentTime;
|
||||
ProtoSystemTime(currentTime);
|
||||
// Uncomment to get different packet loss patterns from run to run
|
||||
|
|
@ -82,7 +80,10 @@ int main(int argc, char* argv[])
|
|||
|
||||
//NormSetGrttEstimate(session, 0.001); // 1 msec initial grtt
|
||||
|
||||
NormSetTransmitRate(session, 6000.0e+03); // in bits/second
|
||||
NormSetTransmitRate(session, 256.0e+03); // in bits/second
|
||||
|
||||
// Uncomment to enable TCP-friendly congestion control (overrides NormSetTransmitRate())
|
||||
NormSetCongestionControl(session, true);
|
||||
|
||||
NormSetDefaultRepairBoundary(session, NORM_BOUNDARY_BLOCK);
|
||||
|
||||
|
|
@ -100,7 +101,7 @@ int main(int argc, char* argv[])
|
|||
NormSetRxPortReuse(session, true);
|
||||
|
||||
// Uncomment to receive your own traffic
|
||||
NormSetLoopback(session, true);
|
||||
//NormSetLoopback(session, true);
|
||||
|
||||
// Uncomment this line to participate as a receiver
|
||||
//NormStartReceiver(session, 1024*1024);
|
||||
|
|
@ -109,13 +110,9 @@ int main(int argc, char* argv[])
|
|||
// (might be needed for high rate sessions)
|
||||
NormSetRxSocketBuffer(session, 512000);
|
||||
|
||||
// Uncomment to enable TCP-friendly congestion control
|
||||
NormSetCongestionControl(session, true);
|
||||
|
||||
// We use a random "sessionId"
|
||||
NormSessionId sessionId = (NormSessionId)rand();
|
||||
|
||||
|
||||
// Uncomment the following line to start sender
|
||||
NormStartSender(session, sessionId, 1024*1024, 1420, 64, 0);
|
||||
|
||||
|
|
@ -123,12 +120,13 @@ int main(int argc, char* argv[])
|
|||
// (might be needed for high rate sessions)
|
||||
NormSetTxSocketBuffer(session, 512000);
|
||||
|
||||
NormAddAckingNode(session, NormGetLocalNodeId(session));
|
||||
NormAddAckingNode(session, NORM_NODE_NONE); //15); //NormGetLocalNodeId(session));
|
||||
|
||||
NormObjectHandle stream = NORM_OBJECT_INVALID;
|
||||
const char* filePath = "/home/adamson/images/art/giger/giger205.jpg";
|
||||
const char* fileName = "ferrari.jpg";
|
||||
|
||||
//const char* filePath = "/home/adamson/pkgs/rh73.tgz";
|
||||
const char* fileName = "file1.jpg";
|
||||
const char* fileName2 = "file2.jpg";
|
||||
// Uncomment this line to send a stream instead of the file
|
||||
stream = NormStreamOpen(session, 10*1024*1024);
|
||||
|
||||
|
|
@ -148,18 +146,20 @@ int main(int argc, char* argv[])
|
|||
int msgCount = 0;
|
||||
int recvCount = -1; // used to monitor reliable stream reception
|
||||
int sendCount = 0;
|
||||
int sendMax = 20;
|
||||
int sendMax = -1; // -1 means unlimited
|
||||
NormEvent theEvent;
|
||||
while (NormGetNextEvent(instance, &theEvent))
|
||||
{
|
||||
switch (theEvent.type)
|
||||
{
|
||||
case NORM_TX_QUEUE_VACANCY:
|
||||
// TRACE("NORM_TX_QUEUE_VACANCY ...\n");
|
||||
case NORM_TX_QUEUE_EMPTY:
|
||||
//TRACE("NORM_TX_QUEUE_EMPTY ...\n");
|
||||
//if (sendCount >= sendMax) break;
|
||||
if (NORM_OBJECT_INVALID != stream)
|
||||
/*if (NORM_TX_QUEUE_VACANCY == theEvent.type)
|
||||
TRACE("NORM_TX_QUEUE_VACANCY ...\n");
|
||||
else
|
||||
TRACE("NORM_TX_QUEUE_EMPTY ...\n");*/
|
||||
if ((sendMax > 0) && (sendCount >= sendMax)) break;
|
||||
if (NORM_OBJECT_INVALID != theEvent.object)
|
||||
{
|
||||
// We loop here to keep stream buffer full ....
|
||||
bool keepWriting = true;
|
||||
|
|
@ -187,22 +187,27 @@ int main(int argc, char* argv[])
|
|||
NormStreamMarkEom(stream);
|
||||
txLen = txIndex = 0;
|
||||
sendCount++;
|
||||
if (sendCount >= sendMax)
|
||||
if (sendCount == 15)
|
||||
{
|
||||
NormSetWatermark(session, stream);
|
||||
}
|
||||
if ((sendMax > 0) && (sendCount >= sendMax))
|
||||
{
|
||||
// Uncomment to gracefully shut down the stream
|
||||
// after "sendMax" messages
|
||||
//NormStreamClose(stream, true);
|
||||
//keepWriting = false;
|
||||
NormStreamClose(stream, true);
|
||||
keepWriting = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end while(keepWriting)
|
||||
}
|
||||
else
|
||||
else if (NORM_OBJECT_INVALID == stream) // we weren't sending a stream that finished
|
||||
{
|
||||
const char* namePtr = (0 == (sendCount & 0x01)) ? fileName : fileName2;
|
||||
NormObjectHandle txFile =
|
||||
NormFileEnqueue(session,
|
||||
filePath,
|
||||
fileName,
|
||||
namePtr,
|
||||
strlen(fileName));
|
||||
// Repeatedly queue our file for sending
|
||||
if (NORM_OBJECT_INVALID == txFile)
|
||||
|
|
@ -214,7 +219,7 @@ int main(int argc, char* argv[])
|
|||
{
|
||||
TRACE("QUEUED FILE ...\n");
|
||||
sendCount++;
|
||||
NormSetWatermark(session, txFile);
|
||||
if (sendCount < 2) NormSetWatermark(session, txFile);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -223,6 +228,14 @@ int main(int argc, char* argv[])
|
|||
DMSG(2, "normTest: NORM_TX_OBJECT_PURGED event ...\n");
|
||||
break;
|
||||
|
||||
case NORM_TX_FLUSH_COMPLETED:
|
||||
DMSG(2, "normTest: NORM_TX_FLUSH_COMPLETED event ...\n");
|
||||
break;
|
||||
|
||||
case NORM_TX_WATERMARK_COMPLETED:
|
||||
DMSG(2, "normTest: NORM_TX_WATERMARK_COMPLETED event ...\n");
|
||||
break;
|
||||
|
||||
case NORM_RX_OBJECT_NEW:
|
||||
DMSG(3, "normTest: NORM_RX_OBJECT_NEW event ...\n");
|
||||
break;
|
||||
|
|
@ -335,6 +348,7 @@ int main(int argc, char* argv[])
|
|||
|
||||
case NORM_RX_OBJECT_COMPLETED:
|
||||
TRACE("normTest: NORM_RX_OBJECT_COMPLETED event ...\n");
|
||||
//NormStopReceiver(session);
|
||||
break;
|
||||
|
||||
case NORM_RX_OBJECT_ABORTED:
|
||||
|
|
@ -345,8 +359,8 @@ int main(int argc, char* argv[])
|
|||
TRACE("Got event type: %d\n", theEvent.type);
|
||||
} // end switch(theEvent.type)
|
||||
|
||||
// Break after sending "sendMax" messages or files
|
||||
//if (sendCount >= sendMax) break;
|
||||
// Uncomment to exit program after sending "sendMax" messages or files
|
||||
//if ((sendMax > 0) && (sendCount >= sendMax)) break;
|
||||
|
||||
} // end while (NormGetNextEvent())
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,6 @@
|
|||
|
||||
#ifndef _NORM_VERSION
|
||||
#define _NORM_VERSION
|
||||
#define VERSION "1.3b5"
|
||||
#define VERSION "1.3b6"
|
||||
#endif // _NORM_VERSION
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
BUILD (Unix):
|
||||
|
||||
g++ -o normFileSend normFileSend.cpp -D_FILE_OFFSET_BITS=64 -DPROTO_DEBUG \
|
||||
g++ -o normFileRecv normFileRecv.cpp -D_FILE_OFFSET_BITS=64 -DPROTO_DEBUG \
|
||||
-I../common/ -I../protolib/common ../unix/libnorm.a \
|
||||
../protolib/unix/libProtokit.a -lpthread
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
This directory contains files for incorporating the NORM protocol
|
||||
into the ns-2 network simulation tool.
|
||||
|
||||
(The NORM ns-2 support may need a little tweaking to work)
|
||||
|
||||
FILES:
|
||||
|
||||
nsNormAgent.h
|
||||
|
|
|
|||
Loading…
Reference in New Issue