<y:ColumnNodeLabelModelParameter id="column_1" inside="true" verticalPosition="0.0"/>
</y:ModelParameter>
</y:NodeLabel>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" textColor="#000000" visible="true" width="69.619140625" x="720.516845703125" y="33.0">PingRotate<y:LabelModel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" textColor="#000000" visible="true" width="233.27734375" x="638.687744140625" y="33.0">PingRotate --> merged into Scheduler<y:LabelModel>
<y:ColumnNodeLabelModel offset="3.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:Geometry height="30.0" width="40.173828125" x="-1230.8963594079278" y="1262.5323388756406"/>
<y:Fill color="#FFFF00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" textColor="#000000" visible="true" width="30.173828125" x="5.0" y="6.015624999999886">ping<y:LabelModel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" textColor="#000000" visible="true" width="30.173828125" x="5.0" y="6.015625">ping<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:Geometry height="30.0" width="60.904296875" x="-146.1677184824265" y="2030.9866653484803"/>
<y:Fill color="#CCFFCC" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" textColor="#000000" visible="true" width="50.904296875" x="5.0" y="6.015625">send_to<y:LabelModel>
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" textColor="#000000" visible="true" width="50.904296875" x="5.0" y="6.015625000000227">send_to<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
</data>
</node>
<node id="n0::n75">
- <data key="d5"/>
<data key="d6">
<y:ShapeNode>
<y:Geometry height="30.0" width="114.681640625" x="26.82837526757328" y="1124.0724963223506"/>
</data>
</node>
<node id="n0::n76">
- <data key="d5"/>
<data key="d6">
<y:ShapeNode>
<y:Geometry height="30.0" width="140.33984375" x="-1116.6863984704278" y="1133.9604050609246"/>
</data>
</node>
<node id="n0::n77">
- <data key="d5"/>
<data key="d6">
<y:ShapeNode>
<y:Geometry height="30.0" width="80.9609375" x="-1086.9969453454278" y="1358.3890702216547"/>
</data>
</node>
<node id="n0::n78">
- <data key="d5"/>
<data key="d6">
<y:ShapeNode>
<y:Geometry height="30.0" width="80.9609375" x="-1230.8963594079278" y="1358.3890702216547"/>
</data>
</node>
<node id="n0::n79">
- <data key="d5"/>
<data key="d6">
<y:ShapeNode>
<y:Geometry height="71.46774098582364" width="93.50116782449732" x="-1165.2167675389264" y="1418.3890702216547"/>
</data>
</node>
<node id="n0::n80">
- <data key="d5"/>
<data key="d6">
<y:ShapeNode>
<y:Geometry height="30.0" width="147.060546875" x="21.77759401757328" y="997.2892395532036"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="31.9375" modelName="custom" textColor="#000000" visible="true" width="137.060546875" x="5.0" y="-0.96875">DnsResolver
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="31.9375" modelName="custom" textColor="#000000" visible="true" width="137.060546875" x="5.0" y="-0.9687500000001137">DnsResolver
::have_up_to_date_ips<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
</data>
</node>
<node id="n0::n81">
- <data key="d5"/>
<data key="d6">
<y:ShapeNode>
<y:Geometry height="30.0" width="43.443359375" x="-1207.9129609704278" y="956.1902905952509"/>
<y:Geometry height="72.48975640804383" width="143.66796875" x="125.82837526757328" y="2229.39993270065"/>
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="45.90625" modelName="custom" textColor="#000000" visible="true" width="115.041015625" x="14.3134765625" y="13.291753204022143">send request
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="45.90625" modelName="custom" textColor="#000000" visible="true" width="115.041015625" x="14.3134765625" y="13.291753204021916">send request
receive echo reply
or destin. unreach<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</data>
</node>
<node id="n0::n85">
- <data key="d5"/>
<data key="d6">
<y:ShapeNode>
<y:Geometry height="30.0" width="31.783203125" x="288.4344433984078" y="2436.146238846486"/>
</data>
</node>
<node id="n0::n86">
- <data key="d5"/>
<data key="d6">
<y:ShapeNode>
<y:Geometry height="30.0" width="67.30859375" x="-1080.1707734704278" y="1193.9604050609244"/>
</data>
</node>
<node id="n0::n87">
- <data key="d5"/>
<data key="d6">
<y:ShapeNode>
<y:Geometry height="30.0" width="25.443359375" x="-1059.2381562829278" y="1271.3044684845509"/>
</data>
</node>
<node id="n0::n88">
- <data key="d5"/>
<data key="d6">
<y:ShapeNode>
<y:Geometry height="30.0" width="91.537109375" x="43.99352118234219" y="1660.1875174077268"/>
</data>
</node>
<node id="n0::n89">
- <data key="d5"/>
<data key="d6">
<y:ShapeNode>
<y:Geometry height="30.0" width="25.443359375" x="-1001.5164765954278" y="1241.3044684845509"/>
</data>
</node>
<node id="n0::n90">
- <data key="d5"/>
<data key="d6">
<y:ShapeNode>
<y:Geometry height="30.0" width="91.876953125" x="24.765096638232762" y="1193.9604050609244"/>
</data>
</node>
<node id="n0::n91">
- <data key="d5"/>
<data key="d6">
<y:ShapeNode>
<y:Geometry height="30.0" width="80.9609375" x="-1089.6868501305844" y="3176.729663059174"/>
</data>
</node>
<node id="n0::n92">
- <data key="d5"/>
<data key="d6">
<y:ShapeNode>
<y:Geometry height="30.0" width="102.599609375" x="30.724859642573392" y="3483.326382452209"/>
</data>
</node>
<node id="n0::n93">
- <data key="d5"/>
<data key="d6">
<y:ShapeNode>
<y:Geometry height="58.92919585228492" width="68.05859375" x="180.25942878040712" y="3356.576129494021"/>
<node id="n1">
<data key="d6">
<y:ShapeNode>
- <y:Geometry height="30.0" width="81.552734375" x="396.8046875" y="-528.4126953124982"/>
+ <y:Geometry height="30.0" width="81.552734375" x="-735.6935273766776" y="-314.4263864547577"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" textColor="#000000" visible="true" width="71.552734375" x="5.0" y="6.015625">IcmpPinger<y:LabelModel>
<node id="n2">
<data key="d6">
<y:ShapeNode>
- <y:Geometry height="30.0" width="81.552734375" x="396.8046875" y="-450.41269531249816"/>
+ <y:Geometry height="30.0" width="81.552734375" x="-735.6935273766776" y="-236.42638645475768"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" textColor="#000000" visible="true" width="71.552734375" x="5.0" y="6.015625">IcmpPinger<y:LabelModel>
<node id="n3">
<data key="d6">
<y:ShapeNode>
- <y:Geometry height="38.0" width="147.669921875" x="63.41796875" y="-544.4126953124982"/>
+ <y:Geometry height="38.0" width="147.669921875" x="-1069.0802461266776" y="-330.4263864547577"/>
<y:Fill color="#00FF00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="31.9375" modelName="custom" textColor="#000000" visible="true" width="137.669921875" x="5.0" y="3.03125">IcmpPacketDistributor
<node id="n4">
<data key="d6">
<y:ShapeNode>
- <y:Geometry height="30.0" width="97.044921875" x="651.5" y="-614.4126953124982"/>
+ <y:Geometry height="30.0" width="97.044921875" x="-480.9982148766776" y="-400.4263864547577"/>
<y:Fill color="#FF99CC" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" textColor="#000000" visible="true" width="87.044921875" x="5.0" y="6.015625">PingerFactory<y:LabelModel>
<node id="n5">
<data key="d6">
<y:ShapeNode>
- <y:Geometry height="30.0" width="128.603515625" x="635.720703125" y="-371.41269531249816"/>
+ <y:Geometry height="30.0" width="128.603515625" x="-496.7775117516776" y="-157.42638645475768"/>
<y:Fill color="#00FFFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" textColor="#000000" visible="true" width="118.603515625" x="5.0" y="6.015625">IcmpPacketFactory<y:LabelModel>
<node id="n6">
<data key="d6">
<y:ShapeNode>
- <y:Geometry height="46.0" width="54.59375" x="148.494140625" y="-427.41269531249816"/>
+ <y:Geometry height="46.0" width="54.59375" x="-984.0040742516776" y="-213.42638645475768"/>
<y:Fill color="#CCFFFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="31.9375" modelName="custom" textColor="#000000" visible="true" width="44.59375" x="5.0" y="7.03125">ICMP
<node id="n7">
<data key="d6">
<y:GenericNode configuration="com.yworks.flowchart.cloud">
- <y:Geometry height="82.0" width="128.603515625" x="141.2099609375" y="-314.41269531249816"/>
+ <y:Geometry height="82.0" width="128.603515625" x="-991.2882539391776" y="-100.42638645475768"/>
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" textColor="#000000" visible="true" width="60.548828125" x="34.02734375" y="32.015625">the world<y:LabelModel>
<node id="n8">
<data key="d6">
<y:ShapeNode>
- <y:Geometry height="30.0" width="117.828125" x="-4.8720703125" y="-419.41269531249816"/>
+ <y:Geometry height="30.0" width="117.828125" x="-1137.3702851891776" y="-205.42638645475768"/>
<y:Fill color="#CCFFFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" textColor="#000000" visible="true" width="107.828125" x="5.0" y="6.015625">NetworkInterface<y:LabelModel>
<node id="n9">
<data key="d6">
<y:ShapeNode>
- <y:Geometry height="30.0" width="103.671875" x="343.2451171875" y="-598.1626953124982"/>
+ <y:Geometry height="30.0" width="103.671875" x="-789.2530976891776" y="-384.1763864547577"/>
<y:Fill color="#FF9900" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" textColor="#000000" visible="true" width="93.671875" x="5.0" y="6.015625">deadline_timer<y:LabelModel>
<node id="n10">
<data key="d6">
<y:ShapeNode>
- <y:Geometry height="30.0" width="103.671875" x="343.2451171875" y="-382.91269531249816"/>
+ <y:Geometry height="30.0" width="103.671875" x="-789.2530976891776" y="-168.92638645475768"/>
<y:Fill color="#FF9900" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" textColor="#000000" visible="true" width="93.671875" x="5.0" y="6.015625">deadline_timer<y:LabelModel>
<node id="n11">
<data key="d6">
<y:ShapeNode>
- <y:Geometry height="30.0" width="99.869140625" x="602.4694010416667" y="-741.612695312498"/>
+ <y:Geometry height="30.0" width="99.869140625" x="-632.7618867516776" y="-435.1263864547575"/>
<y:Fill color="#FFFF00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" textColor="#000000" visible="true" width="89.869140625" x="5.0" y="6.015625">PingScheduler<y:LabelModel>
<node id="n12">
<data key="d6">
<y:ShapeNode>
- <y:Geometry height="30.0" width="99.869140625" x="604.9694010416667" y="-231.0955078124981"/>
+ <y:Geometry height="30.0" width="99.869140625" x="-632.7618867516776" y="-92.87410084385726"/>
<y:Fill color="#FFFF00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" textColor="#000000" visible="true" width="89.869140625" x="5.0" y="6.015625">PingScheduler<y:LabelModel>
<node id="n13">
<data key="d6">
<y:ShapeNode>
- <y:Geometry height="30.0" width="103.671875" x="427.525390625" y="-709.112695312498"/>
+ <y:Geometry height="30.0" width="103.671875" x="-766.4337617516776" y="-478.17185184415416"/>
<y:Fill color="#FF9900" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" textColor="#000000" visible="true" width="93.671875" x="5.0" y="6.015625">deadline_timer<y:LabelModel>
<node id="n14">
<data key="d6">
<y:ShapeNode>
- <y:Geometry height="30.0" width="103.671875" x="436.42252604166674" y="-264.62392578124906"/>
+ <y:Geometry height="30.0" width="103.671875" x="-779.5100743951876" y="-66.67183725793416"/>
<y:Fill color="#FF9900" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" textColor="#000000" visible="true" width="93.671875" x="5.0" y="6.015625">deadline_timer<y:LabelModel>
<node id="n15">
<data key="d6">
<y:ShapeNode>
- <y:Geometry height="30.0" width="79.619140625" x="540.0944010416667" y="-331.91269531249816"/>
- <y:Fill color="#339966" transparent="false"/>
- <y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" textColor="#000000" visible="true" width="69.619140625" x="5.0" y="6.015625">PingRotate<y:LabelModel>
- <y:SmartNodeLabelModel distance="4.0"/>
- </y:LabelModel>
- <y:ModelParameter>
- <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
- </y:ModelParameter>
- </y:NodeLabel>
- <y:Shape type="rectangle"/>
- </y:ShapeNode>
- </data>
- </node>
- <node id="n16">
- <data key="d6">
- <y:ShapeNode>
- <y:Geometry height="30.0" width="79.619140625" x="519.4169921875" y="-659.112695312498"/>
- <y:Fill color="#339966" transparent="false"/>
- <y:BorderStyle color="#000000" type="line" width="1.0"/>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" textColor="#000000" visible="true" width="69.619140625" x="5.0" y="6.015625">PingRotate<y:LabelModel>
- <y:SmartNodeLabelModel distance="4.0"/>
- </y:LabelModel>
- <y:ModelParameter>
- <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
- </y:ModelParameter>
- </y:NodeLabel>
- <y:Shape type="rectangle"/>
- </y:ShapeNode>
- </data>
- </node>
- <node id="n17">
- <data key="d6">
- <y:ShapeNode>
- <y:Geometry height="22.5" width="37.28125" x="426.4404296875" y="-485.66269531249816"/>
+ <y:Geometry height="22.5" width="37.28125" x="-706.0577851891776" y="-271.6763864547577"/>
<y:Fill hasColor="false" transparent="false"/>
<y:BorderStyle hasColor="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="20" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="27.28125" modelName="custom" rotationAngle="90.0" textColor="#000000" visible="true" width="26.79296875" x="5.0" y="-2.146484375">...<y:LabelModel>
</y:ShapeNode>
</data>
</node>
- <node id="n18">
+ <node id="n16">
<data key="d6">
<y:ShapeNode>
- <y:Geometry height="30.0" width="79.560546875" x="451.63671875000006" y="-780.3626953124979"/>
+ <y:Geometry height="30.0" width="79.560546875" x="-725.6699090261293" y="-531.256279047079"/>
<y:Fill color="#666699" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" textColor="#000000" visible="true" width="69.560546875" x="5.0" y="6.015625">HostStatus<y:LabelModel>
</y:ShapeNode>
</data>
</node>
- <node id="n19">
+ <node id="n17">
<data key="d6">
<y:ShapeNode>
- <y:Geometry height="30.0" width="79.560546875" x="460.5338541666668" y="-190.91269531249816"/>
+ <y:Geometry height="30.0" width="79.560546875" x="-733.7013398766776" y="-6.671837257934158"/>
<y:Fill color="#666699" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" textColor="#000000" visible="true" width="69.560546875" x="5.0" y="6.015625">HostStatus<y:LabelModel>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="2.0"/>
<y:Arrows source="standard" target="standard"/>
- <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="31.9375" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="74.65234375" x="55.5322265625" y="-12.258471390085447">hold
+ <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="31.9375" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="74.65234375" x="55.532241666291156" y="-12.25846013976684">hold
shared_ptrs<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="standard"/>
- <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="48.607421875" x="-113.622802734375" y="20.284816638891243">creates<y:LabelModel>
+ <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="48.607421875" x="-113.62278763058384" y="20.284797371631782">creates<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
- <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="35.013671875" x="-4.926223502671434" y="30.515618896486217">owns<y:LabelModel>
+ <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="35.013671875" x="-4.926223657669425" y="30.515630146804824">owns<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dotted" width="2.0"/>
<y:Arrows source="none" target="standard"/>
- <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="32.857421875" x="-113.287109375" y="2.485157095905379">send<y:LabelModel>
+ <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="32.857421875" x="-113.28709427120884" y="2.485168346224043">send<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
- <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="35.013671875" x="-47.421514716030146" y="34.51561889648622">owns<y:LabelModel>
+ <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="35.013671875" x="-47.421514871027966" y="34.515630146804824">owns<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
- <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="30.87109375" x="63.24609375" y="14.70034228063389">calls<y:LabelModel>
+ <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="30.87109375" x="63.246108853791156" y="14.700338272163492">calls<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
- <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="35.013671875" x="-29.6170654296875" y="-28.85935058593566">owns<y:LabelModel>
+ <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="35.013671875" x="-29.617050325896344" y="-28.859369853195176">owns<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
- <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="35.013671875" x="-29.3123779296875" y="9.765618896486217">owns<y:LabelModel>
+ <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="35.013671875" x="-29.312362825896344" y="9.765630146804824">owns<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
</y:QuadCurveEdge>
</data>
</edge>
- <edge id="e13" source="n16" target="n1">
+ <edge id="e13" source="n12" target="n2">
<data key="d10">
<y:QuadCurveEdge straightness="0.1">
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
- <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="35.013671875" x="-64.36871337890625" y="41.36560058593943">owns<y:LabelModel>
+ <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="35.013671875" x="-61.83934036495873" y="-65.76051891786216">owns<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
</y:QuadCurveEdge>
</data>
</edge>
- <edge id="e14" source="n12" target="n15">
+ <edge id="e14" source="n11" target="n13">
<data key="d10">
<y:QuadCurveEdge straightness="0.1">
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
- <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="35.013671875" x="-43.848042805989394" y="-44.39297180175595">owns<y:LabelModel>
+ <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="35.013671875" x="-37.94945020843579" y="-15.662381592859674">owns<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
</y:QuadCurveEdge>
</data>
</edge>
- <edge id="e15" source="n11" target="n13">
+ <edge id="e15" source="n12" target="n14">
<data key="d10">
<y:QuadCurveEdge straightness="0.1">
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
- <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="35.013671875" x="-53.14292399088538" y="-2.2913699997856156">owns<y:LabelModel>
- <y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
- </y:LabelModel>
- <y:ModelParameter>
- <y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="center" ratio="0.5" segment="0"/>
- </y:ModelParameter>
- <y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
- </y:EdgeLabel>
- </y:QuadCurveEdge>
- </data>
- </edge>
- <edge id="e16" source="n12" target="n14">
- <data key="d10">
- <y:QuadCurveEdge straightness="0.1">
- <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
- <y:LineStyle color="#000000" type="line" width="1.0"/>
- <y:Arrows source="none" target="standard"/>
- <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="35.013671875" x="-49.94435628255201" y="-15.510667133839007">owns<y:LabelModel>
+ <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="35.013671875" x="-39.536991738762254" y="-4.999197749635961">owns<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
</y:QuadCurveEdge>
</data>
</edge>
- <edge id="e17" source="n15" target="n2">
- <data key="d10">
- <y:QuadCurveEdge straightness="0.1">
- <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
- <y:LineStyle color="#000000" type="line" width="1.0"/>
- <y:Arrows source="none" target="standard"/>
- <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="35.013671875" x="-70.65275065104163" y="-53.23438110351378">owns<y:LabelModel>
- <y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
- </y:LabelModel>
- <y:ModelParameter>
- <y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="center" ratio="0.5" segment="0"/>
- </y:ModelParameter>
- <y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
- </y:EdgeLabel>
- </y:QuadCurveEdge>
- </data>
- </edge>
- <edge id="e18" source="n11" target="n16">
+ <edge id="e16" source="n11" target="n1">
<data key="d10">
<y:QuadCurveEdge straightness="0.1">
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
- <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="35.013671875" x="-47.15421549479174" y="17.265600585939524">owns<y:LabelModel>
+ <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="35.013671875" x="-59.621811068083844" y="36.36561183625804">owns<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
</y:QuadCurveEdge>
</data>
</edge>
- <edge id="e19" source="n11" target="n18">
+ <edge id="e17" source="n11" target="n16">
<data key="d10">
<y:QuadCurveEdge straightness="0.1">
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
- <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="35.013671875" x="-53.14292399088538" y="-17.562073554226117">owns<y:LabelModel>
+ <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="35.013671875" x="-52.956254334216055" y="-42.04933445990264">owns<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
</y:QuadCurveEdge>
</data>
</edge>
- <edge id="e20" source="n12" target="n19">
+ <edge id="e18" source="n12" target="n17">
<data key="d10">
<y:QuadCurveEdge straightness="0.1">
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
- <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="35.013671875" x="-49.94435628255201" y="-0.5528433361312182">owns<y:LabelModel>
+ <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="35.013671875" x="-53.722335970427594" y="19.116755680549595">owns<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
</data>
</edge>
<edge id="n0::e72" source="n0::n67" target="n0::n82">
- <data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
</data>
</edge>
<edge id="n0::e73" source="n0::n82" target="n0::n75">
- <data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
</data>
</edge>
<edge id="n0::e74" source="n0::n75" target="n0::n76">
- <data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
</data>
</edge>
<edge id="n0::e75" source="n0::n87" target="n0::n77">
- <data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="14.990234375" tx="0.0" ty="0.0"/>
</data>
</edge>
<edge id="n0::e76" source="n0::n5" target="n0::n1">
- <data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
</data>
</edge>
<edge id="n0::e77" source="n0::n78" target="n0::n79">
- <data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
</data>
</edge>
<edge id="n0::e78" source="n0::n77" target="n0::n79">
- <data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
</data>
</edge>
<edge id="n0::e79" source="n0::n79" target="n0::n31">
- <data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
</data>
</edge>
<edge id="n0::e80" source="n0::n64" target="n0::n80">
- <data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
</data>
</edge>
<edge id="n0::e81" source="n0::n81" target="n0::n66">
- <data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
</data>
</edge>
<edge id="n0::e82" source="n0::n81" target="n0::n77">
- <data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
</data>
</edge>
<edge id="n0::e83" source="n0::n85" target="n0::n83">
- <data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
</data>
</edge>
<edge id="n0::e84" source="n0::n85" target="n0::n84">
- <data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
</data>
</edge>
<edge id="n0::e85" source="n0::n4" target="n0::n11">
- <data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
</data>
</edge>
<edge id="n0::e86" source="n0::n87" target="n0::n60">
- <data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="12.736566543579102" sy="0.0" tx="0.0" ty="0.0"/>
</data>
</edge>
<edge id="n0::e87" source="n0::n87" target="n0::n68">
- <data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
</data>
</edge>
<edge id="n0::e88" source="n0::n76" target="n0::n86">
- <data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
</data>
</edge>
<edge id="n0::e89" source="n0::n86" target="n0::n87">
- <data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
</data>
</edge>
<edge id="n0::e90" source="n0::n79" target="n0::n88">
- <data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
</data>
</edge>
<edge id="n0::e91" source="n0::n86" target="n0::n89">
- <data key="d9"/>
<data key="d10">
<y:SplineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
</data>
</edge>
<edge id="n0::e92" source="n0::n89" target="n0::n66">
- <data key="d9"/>
<data key="d10">
<y:SplineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
</data>
</edge>
<edge id="n0::e93" source="n0::n89" target="n0::n90">
- <data key="d9"/>
<data key="d10">
<y:SplineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
</data>
</edge>
<edge id="n0::e94" source="n0::n74" target="n0::n91">
- <data key="d9"/>
<data key="d10">
<y:SplineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
</data>
</edge>
<edge id="n0::e95" source="n0::n15" target="n0::n92">
- <data key="d9"/>
<data key="d10">
<y:SplineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
, Ttl( ttl )
{}
+Cname::Cname(const std::string &host, const TimeToLive &ttl)
+ : Host( host )
+ , Ttl( ttl )
+{}
+
DnsCache::DnsCache(const IoServiceItem &io_serv,
const std::string &cache_file)
: IpCache()
DnsCache::~DnsCache()
{
- GlobalLogger.info() << "Dns Cache is being destructed";
+ GlobalLogger.info() << "DnsCache: being destructed";
// save one last time without re-scheduling the next save
save_to_cachefile();
void DnsCache::save_to_cachefile()
{
if (!HasChanged)
- {
GlobalLogger.info() << "DnsCache: skip saving because has not changed";
- return;
- }
else if (CacheFile.empty())
- {
GlobalLogger.warning()
<< "DnsCache: skip saving because file name empty!";
- return;
- }
-
- try
- {
- std::ofstream ofs( CacheFile.c_str() );
- boost::archive::xml_oarchive oa(ofs);
- oa << boost::serialization::make_nvp("IpCache", IpCache);
- oa << boost::serialization::make_nvp("CnameCache", CnameCache);
- GlobalLogger.info() << "DnsCache: saved to cache file " << CacheFile;
-
- HasChanged = false;
- }
- catch (std::exception &exc)
+ else if (CacheFile == DO_NOT_USE_CACHE_FILE)
+ GlobalLogger.info() << "DnsCache: configured not to use cache file";
+ else
{
- GlobalLogger.warning() << "Saving failed: " << exc.what();
+ try
+ {
+ std::ofstream ofs( CacheFile.c_str() );
+ boost::archive::xml_oarchive oa(ofs);
+ //oa << boost::serialization::make_nvp("IpCache", IpCache);
+ //oa << boost::serialization::make_nvp("CnameCache", CnameCache);
+ oa & BOOST_SERIALIZATION_NVP(IpCache);
+ oa & BOOST_SERIALIZATION_NVP(CnameCache);
+ GlobalLogger.info() << "DnsCache: saved to cache file " << CacheFile;
+
+ HasChanged = false;
+ }
+ catch (std::exception &exc)
+ {
+ GlobalLogger.warning() << "Saving failed: " << exc.what();
+ }
}
}
-
void DnsCache::load_from_cachefile()
{
if (CacheFile.empty())
- {
GlobalLogger.warning()
<< "DnsCache: cannot load because cache file name is empty!";
- return;
- }
+ else if (CacheFile == DO_NOT_USE_CACHE_FILE)
+ GlobalLogger.info() << "DnsCache: configured not to use cache file";
else if ( !I2n::file_exists(CacheFile) )
- {
GlobalLogger.warning() << "DnsCache: cannot load because cache file "
<< CacheFile << " does not exist!";
- return;
- }
- try
+ else
{
- HostAddressVec cache;
-
- std::ifstream ifs( CacheFile.c_str() );
- boost::archive::xml_iarchive ia(ifs);
+ try
+ {
+ std::ifstream ifs( CacheFile.c_str() );
+ boost::archive::xml_iarchive ia(ifs);
- ia >> boost::serialization::make_nvp("IpCache", cache);
- ia >> boost::serialization::make_nvp("CnameCache", cache);
- GlobalLogger.info() << "DnsCache: loaded from file " << CacheFile;
- }
- catch (boost::archive::archive_exception &exc)
- {
- GlobalLogger.warning() << "DnsCache: archive exception loading from "
- << CacheFile << ": " << exc.what();
- }
- catch (std::exception &exc)
- {
- GlobalLogger.warning() << "DnsCache: exception while loading from "
- << CacheFile << ": " << exc.what();
+ ia & BOOST_SERIALIZATION_NVP(IpCache);
+ ia & BOOST_SERIALIZATION_NVP(CnameCache);
+ GlobalLogger.info() << "DnsCache: loaded from file " << CacheFile;
+ }
+ catch (boost::archive::archive_exception &exc)
+ {
+ GlobalLogger.warning() << "DnsCache: archive exception loading from "
+ << CacheFile << ": " << exc.what();
+ }
+ catch (std::exception &exc)
+ {
+ GlobalLogger.warning() << "DnsCache: exception while loading from "
+ << CacheFile << ": " << exc.what();
+ }
}
}
-void DnsCache::update(const std::string &hostname,
- const HostAddressVec &new_data)
+
+// warn if hostname is empty and remove trailing dot
+std::string DnsCache::key_for_hostname(const std::string &hostname) const
{
- GlobalLogger.info() << "DnsCache: update IPs for " << hostname
- << " to " << new_data.size() << "-list";
- IpCache[hostname] = new_data;
- HasChanged = true;
+ if (hostname.empty())
+ {
+ GlobalLogger.warning() << "DnsCache: empty host!";
+ return "";
+ }
+
+ // check whether last character is a dot
+ if (hostname.rfind('.') == hostname.length()-1)
+ return hostname.substr(0, hostname.length()-1);
+ else
+ return hostname;
}
void DnsCache::update(const std::string &hostname,
- const Cname &cname)
+ const HostAddressVec &new_ips)
{
- GlobalLogger.info() << "DnsCache: update CNAME for " << hostname
- << " to " << cname.Host;
- CnameCache[hostname] = cname;
+ std::string key = key_for_hostname(hostname);
+ if ( !get_cname(hostname).Host.empty() )
+ { // ensure that there is never IP and CNAME for the same host
+ GlobalLogger.warning() << "DnsCache: Saving IPs for " << key
+ << " removes CNAME to " << get_cname(hostname).Host << "!";
+ update(hostname, Cname()); // overwrite with "empty" cname
+ }
+ GlobalLogger.debug() << "DnsCache: update IPs for " << key
+ << " to " << new_ips.size() << "-list";
+ IpCache[key] = new_ips;
HasChanged = true;
}
void DnsCache::update(const std::string &hostname,
- const uint32_t new_ttl)
+ const Cname &cname)
{
- GlobalLogger.info() << "DnsCache: ensure TTL for IPs for " << hostname
- << " is below " << new_ttl << "s";
- HostAddressVec ips = IpCache[hostname];
- TimeToLive current_ttl;
- BOOST_FOREACH( HostAddress &addr, ips )
- {
- current_ttl = addr.get_ttl();
- if (current_ttl.get_value() > new_ttl)
- {
- current_ttl.set_value(new_ttl);
- addr.set_ttl(current_ttl);
- HasChanged = true;
- }
+ std::string key = key_for_hostname(hostname);
+ if ( !get_ips(hostname).empty() )
+ { // ensure that there is never IP and CNAME for the same host
+ GlobalLogger.warning() << "DnsCache: Saving CNAME for " << key
+ << " removes " << get_ips(hostname).size() << " IPs for same host!";
+ update(hostname, HostAddressVec()); // overwrite with empty IP list
}
- IpCache[hostname] = ips;
+
+ // remove possible trailing dot from cname
+ Cname to_save = Cname(key_for_hostname(cname.Host),
+ cname.Ttl);
+
+ GlobalLogger.info() << "DnsCache: update CNAME for " << key
+ << " to " << to_save.Host;
+ CnameCache[key] = to_save;
+ HasChanged = true;
}
HostAddressVec DnsCache::get_ips(const std::string &hostname,
const bool check_up_to_date)
{
- HostAddressVec result = IpCache[hostname];
+ std::string key = key_for_hostname(hostname);
+ HostAddressVec result = IpCache[key];
if (check_up_to_date)
{
HostAddressVec result_up_to_date;
uint32_t threshold = static_cast<uint32_t>(
DnsMaster::get_instance()->get_resolved_ip_ttl_threshold() );
+ uint32_t updated_ttl;
BOOST_FOREACH( const HostAddress &addr, result )
{
- if (addr.get_ttl().get_updated_value() > threshold)
+ updated_ttl = addr.get_ttl().get_updated_value();
+ if (updated_ttl > threshold)
result_up_to_date.push_back(addr);
+ else
+ GlobalLogger.debug() << "DnsCache: do not return "
+ << addr.get_ip().to_string() << " since TTL "
+ << updated_ttl << "s is out of date (thresh="
+ << threshold << "s)";
}
- GlobalLogger.debug() << "DnsCache: From cached list of size "
- << result.size() << " return " << result_up_to_date.size()
- << " since rest out of date";
result = result_up_to_date;
}
- GlobalLogger.info() << "DnsCache: request IPs for " << hostname
- << " --> " << result.size() << "-list";
+ GlobalLogger.debug() << "DnsCache: request IPs for " << key
+ << " --> " << result.size() << "-list";
+ BOOST_FOREACH( const HostAddress &addr, result )
+ GlobalLogger.debug() << "DnsCache: " << addr.get_ip().to_string()
+ << " (TTL " << addr.get_ttl().get_value() << "s)";
return result;
}
Cname DnsCache::get_cname(const std::string &hostname,
const bool check_up_to_date)
{
- Cname result_obj = CnameCache[hostname];
- GlobalLogger.info() << "DnsCache: request CNAME for " << hostname
- << " --> \"" << result_obj.Host << "\"";
+ std::string key = key_for_hostname(hostname);
+ Cname result_obj = CnameCache[key];
+ GlobalLogger.debug() << "DnsCache: request CNAME for " << key
+ << " --> \"" << result_obj.Host << "\"";
if (result_obj.Host.empty())
return result_obj;
else if (check_up_to_date)
{
- if (result_obj.Ttl.get_updated_value() > DnsMaster::get_instance()
- ->get_resolved_ip_ttl_threshold())
+ if ( result_obj.Ttl.get_updated_value() > static_cast<uint32_t>(
+ DnsMaster::get_instance()->get_resolved_ip_ttl_threshold()) )
return result_obj;
else
{
while ( result.empty() )
{
current_cname = get_cname(current_host, check_up_to_date);
- current_host = current_cname.Host;
+ current_host = key_for_hostname(current_cname.Host);
if (current_host.empty())
break;
else if (++n_recursions >= Config::MaxRetrievalRecursions)
}
cname = get_cname(up_to_date_host);
- if (cname.Host.empty())
+ if (key_for_hostname(cname.Host).empty())
// reached end of cname list
break;
else if (cname.Ttl.get_updated_value() > ttl_thresh)
Cname();
Cname(const std::string &host, const uint32_t ttl);
+ Cname(const std::string &host, const TimeToLive &ttl);
// serialization
friend class boost::serialization::access;
};
typedef std::map<std::string, Cname> cname_map_type;
+/// constant to give as cache_file arg to DnsCache constructor
+/// indicating that no cache file should be used
+const std::string DO_NOT_USE_CACHE_FILE = "do not use cache file!";
+
// -----------------------------------------------------------------------------
// DnsCache
~DnsCache();
// accessed from ResolverBase subclasses
- void update(const std::string &hostname, const HostAddressVec &new_data);
+ void update(const std::string &hostname, const HostAddressVec &new_ips);
void update(const std::string &hostname, const Cname &cname);
- void update(const std::string &hostname, const uint32_t ttl);
// retrieval
HostAddressVec get_ips(const std::string &hostname,
void schedule_save(const boost::system::error_code &error);
void save_to_cachefile();
void load_from_cachefile();
+ std::string key_for_hostname(const std::string &hostname) const;
};
GlobalLogger.info() << "DnsMaster is being destructed";
if (DnsMaster::TheOnlyInstance)
- { // just to be sure ...
- GlobalLogger.warning() << "DnsMaster is being destructed that is not "
- << "singleton instance TheOnlyInstance!";
+ { // apparently, this static variable still exists while itself is
+ // destructed...
+ //GlobalLogger.warning() << "DnsMaster is being destructed that is not "
+ // << "singleton instance TheOnlyInstance!";
DnsMaster::TheOnlyInstance.reset();
}
return ResolverMap[key];
}
-// create resolver but do not remember it in ResolverMap
-ResolverItem DnsMaster::get_recursor_for(const std::string &hostname,
- const DnsIpProtocol &protocol,
- const boost::asio::ip::address &name_server)
-{
- resolver_key_type key(hostname, protocol);
- if ( !ResolverMap[key] )
- GlobalLogger.warning() << "DnsMaster: requesting recursor for host "
- << hostname << " and protocol " << to_string(protocol)
- << " but have no regular resolver for this combination!";
- else
- GlobalLogger.warning() << "DnsMaster: requesting recursor for host "
- << hostname << " and protocol " << to_string(protocol);
-
- ResolverItem new_resolver( new DnsResolver(IoService,
- hostname,
- protocol,
- Cache,
- name_server) );
- return new_resolver;
-}
-
/**
* return true if given hostname string actually is an IP
*
const PingProtocol &ping_protocol);
ResolverItem& get_resolver_for(const std::string &hostname,
const DnsIpProtocol &protocol);
- ResolverItem get_recursor_for(const std::string &hostname,
- const DnsIpProtocol &protocol,
- const boost::asio::ip::address &name_server);
// implementation of singleton
private:
// remember cname list (if there were any)
BOOST_FOREACH( const src_cname_pair &host_and_cname, result_cnames )
- {
- GlobalLogger.info() << LogPrefix << "Remember CNAME "
- << host_and_cname.first << " --> " << host_and_cname.second.Host;
ResolverBase::update_cache(host_and_cname.first, host_and_cname.second);
- }
if ( !result_ips.empty() )
handle_ips( result_ips );
// RETRIEVAL
//==============================================================================
-HostAddress DnsResolver::get_next_ip()
+HostAddress DnsResolver::get_next_ip(bool check_up_to_date)
{
// get cached data
+ // (do not use arg check_up_to_date here in order to give NextIpIndex
+ // a chance to stay above number of outdate IPs)
HostAddressVec cached_data = ResolverBase::get_cached_ips_recursively();
// if no results cached, return default-constructed HostAddress (0.0.0.0)
+ HostAddress return_candidate;
if ( cached_data.empty() )
{
- HostAddress return_value;
- return return_value;
+ GlobalLogger.debug() << LogPrefix << "Get next IP: nothing cached";
+ return return_candidate;
}
- // check validity of index (cache may have changed since last call)
- if (NextIpIndex >= cached_data.size())
- NextIpIndex = 0;
+ int n_iter = 0;
+ std::size_t n_ips = cached_data.size();
+ uint32_t ttl_thresh = static_cast<uint32_t>( DnsMaster::get_instance()
+ ->get_resolved_ip_ttl_threshold() );
- // return next IP
- return cached_data[NextIpIndex++];
+ GlobalLogger.info() << LogPrefix << "Get next IP from cached result of "
+ << n_ips << " IPs; first index to consider is " << NextIpIndex
+ << "; TTL thresh = " << ttl_thresh << " is used: " << check_up_to_date;
+
+ // loop until we have found a cached result (that is up to date)
+ // or until we have tried all cached IPs
+ while (true)
+ {
+ // check index since cache size may have changed since last call
+ if (NextIpIndex >= n_ips)
+ NextIpIndex = 0;
+ else if ( n_iter >= n_ips)
+ return HostAddress(); // have checked all candidates
+ else
+ { // there are candidates left to consider
+ return_candidate = cached_data[NextIpIndex++];
+ if (!check_up_to_date)
+ return return_candidate;
+ else if (cached_data[NextIpIndex].get_ttl().get_updated_value()
+ > ttl_thresh)
+ return cached_data[++NextIpIndex];
+ else
+ ++n_iter;
+ }
+ }
}
bool DnsResolver::have_up_to_date_ip()
{
- return ! ResolverBase::get_cached_ips_recursively("", true).empty();
+ return get_resolved_ip_count() > 0;
}
int DnsResolver::get_resolved_ip_count()
{
- return ResolverBase::get_cached_ips_recursively().size();
+ return ResolverBase::get_cached_ips_recursively("", true).size();
}
// (created using vim -- the world's best text editor)
friend ResolverItem& DnsMaster::get_resolver_for(
const std::string &hostname,
const DnsIpProtocol &protocol);
- friend ResolverItem DnsMaster::get_recursor_for(
- const std::string &hostname,
- const DnsIpProtocol &protocol,
- const boost::asio::ip::address &name_server);
private:
DnsResolver(IoServiceItem &io_serv,
const std::string &hostname,
// only real public function (called from pingers)
public:
- HostAddress get_next_ip();
+ HostAddress get_next_ip(const bool check_up_to_date=true);
bool have_up_to_date_ip();
int get_resolved_ip_count();
void cancel_resolve();
{
Ttl = ttl;
}
+
+bool HostAddress::is_valid() const
+{
+ return Ip == address() || Ip == boost::asio::ip::address_v4()
+ || Ip == boost::asio::ip::address_v6();
+}
TimeToLive get_ttl() const;
void set_ttl( const TimeToLive &ttl );
+ // return false if this HostAddress was default-constructed, so does not
+ // actually point to an ip (ip is probably 0.0.0.0)
+ bool is_valid() const;
+
private:
/// IP address of the host
boost::asio::ip::address Ip;
template<class Archive>
void save(Archive & ar, const unsigned int version) const
{
- std::string ip = Ip.to_string();
- ar & BOOST_SERIALIZATION_NVP(ip);
+ std::string ip_str = Ip.to_string();
+ ar & BOOST_SERIALIZATION_NVP(ip_str);
ar & BOOST_SERIALIZATION_NVP(Ttl);
}
template<class Archive>
void load(Archive & ar, const unsigned int version)
{
- std::string ip;
- ar & BOOST_SERIALIZATION_NVP(ip);
+ std::string ip_str;
+ ar & BOOST_SERIALIZATION_NVP(ip_str);
ar & BOOST_SERIALIZATION_NVP(Ttl);
- Ip = boost::asio::ip::address::from_string(ip);
+ Ip = boost::asio::ip::address::from_string(ip_str);
}
// only real public function
public:
- HostAddress get_next_ip() { return IpAddress; }
+ HostAddress get_next_ip(const bool check_up_to_date=true)
+ { return IpAddress; }
bool have_up_to_date_ip() { return true; }
int get_resolved_ip_count(){ return 1; }
bool is_resolving() { return false; }
std::string ResolverBase::get_hostname() const
{ return Hostname; }
-std::string ResolverBase::get_skipper() const
+std::string ResolverBase::get_skip_cname() const
{
DnsMasterItem master = DnsMaster::get_instance();
std::string first_out_of_date = Cache->get_first_outdated_cname(
}
void ResolverBase::update_cache( const std::string &hostname,
- const HostAddressVec &new_results ) const
-{ Cache->update( hostname, new_results ); }
+ const HostAddressVec &new_ips ) const
+{ Cache->update( hostname, new_ips ); }
void ResolverBase::update_cache( const std::string &hostname,
const Cname &cname ) const
{ Cache->update( hostname, cname ); }
-void ResolverBase::update_cache( const HostAddressVec &new_results ) const
-{ Cache->update( Hostname, new_results ); }
+void ResolverBase::update_cache( const HostAddressVec &new_ips ) const
+{ Cache->update( Hostname, new_ips ); }
void ResolverBase::update_cache( const Cname &cname ) const
{ Cache->update( Hostname, cname ); }
-void ResolverBase::update_cache( const uint32_t ttl ) const
-{ Cache->update( Hostname, ttl ); }
HostAddressVec ResolverBase::get_cached_ips_recursively(const std::string host,
bool check_up_to_date) const
virtual void cancel_resolve() = 0;
virtual bool is_resolving() = 0;
- virtual HostAddress get_next_ip() = 0;
+ virtual HostAddress get_next_ip(const bool check_up_to_date=true) = 0;
virtual bool have_up_to_date_ip() = 0;
virtual int get_resolved_ip_count() = 0;
std::string get_hostname() const;
- std::string get_skipper() const;
+ std::string get_skip_cname() const;
protected:
ResolverBase(const IoServiceItem &io_serv,
virtual void do_resolve() = 0;
// convenient forwards to DnsCache that just insert Hostname
- void update_cache( const HostAddressVec &new_results ) const;
+ void update_cache( const HostAddressVec &new_ips ) const;
void update_cache( const Cname &cname ) const;
void update_cache( const std::string &hostname,
- const HostAddressVec &new_results ) const;
+ const HostAddressVec &new_ips ) const;
void update_cache( const std::string &hostname,
const Cname &cname ) const;
- void update_cache( const uint32_t ttl ) const;
HostAddressVec get_cached_ips_recursively(const std::string host="",
const bool check_up_to_date=false) const;
template<class Archive>
void load(Archive & ar, const unsigned int version)
{
- uint32_t ttl_seconds;
std::string ttl_creation_time;
- ar & BOOST_SERIALIZATION_NVP(ttl_seconds);
+ ar & BOOST_SERIALIZATION_NVP(Ttl);
ar & BOOST_SERIALIZATION_NVP(ttl_creation_time);
// now convert to Ip and Ttl
- Ttl = ttl_seconds;
TtlSetTime = boost::posix_time::from_iso_string(ttl_creation_time);
}
#include <limits>
#include <boost/bind.hpp>
+#include <boost/foreach.hpp>
#include <logfunc.hpp>
#include "boost_assert_handler.h"
#include "host/pingerfactory.h"
+#include "dns/dnsmaster.h"
#include "icmp/icmppinger.h"
#include "link/linkstatus.h"
const long ping_interval_in_sec,
const int ping_fail_percentage_limit,
const int ping_reply_timeout,
- const int resolved_ip_ttl_threshold,
LinkStatusItem link_analyzer,
const int first_delay
) :
IoService( io_serv ),
NetworkInterfaceName( network_interface ),
- Resolver(),
DestinationAddress( destination_address ),
DestinationPort( destination_port ),
+ Protocols( ping_protocol_list ),
+ ProtocolIter(),
+ PingIntervalInSec( ping_interval_in_sec ),
+ FirstDelay( first_delay ),
NextPingTimer( *io_serv ),
TimeSentLastPing( microsec_clock::universal_time() ),
- PingIntervalInSec( ping_interval_in_sec ),
+ PingReplyTimeout( ping_reply_timeout ),
HostAnalyzer( destination_address, ping_fail_percentage_limit, link_analyzer ),
- FirstDelay( first_delay ),
- Ping()
+ Resolver(),
+ Ping(),
+ WantToPing( false ),
+ LogPrefix(),
+ ContinueOnOutdatedIps( false );
{
BOOST_ASSERT( !network_interface.empty() );
BOOST_ASSERT( !destination_address.empty() );
BOOST_ASSERT( (0 <= ping_fail_percentage_limit) &&
( ping_fail_percentage_limit <= 100) );
- std::stringstream temp;
- temp << "PS(" << DestinationAddress << "): ";
- LogPrefix = temp.str();
-
- // fill circular buffer with protocols
- BOOST_FOREACH( const PingProtocol &prot, protocol_list )
- ProtocolRotate.push_back(prot);
+ update_log_prefix();
init_ping_protocol();
}
}
-void PingRotate::try_to_ping()
+void PingScheduler::try_to_ping()
{
if ( !WantToPing )
{
- GlobalLogger.info() << "PingRotate: not pinging yet (not requested to)";
+ GlobalLogger.info() << "PingScheduler: not pinging (not requested to)";
return;
}
else if ( Resolver && Resolver->is_resolving() )
{
- GlobalLogger.info() << "PingRotate: not pinging yet (DNS not finished)";
+ GlobalLogger.info() << "PingScheduler: not pinging (DNS not finished)";
return;
}
else if ( !Resolver )
// should not happen, but check anyway
GlobalLogger.warning() << LogPrefix << "Have no resolver!";
- GlobalLogger.info() << "PingRotate: start ping";
+ GlobalLogger.info() << "PingScheduler: start ping";
WantToPing = false;
- Ping->ping(
- Resolver->get_next_ip().get_ip(),
- DestinationPort,
- boost::bind(&PingScheduler::ping_done_handler, this, _1)
- );
+ HostAddress ip = Resolver->get_next_ip();
+ if ( !ip.is_valid() && ContinueOnOutdatedIps)
+ {
+ GlobalLogger.info() << LogPrefix << "Checking for outdated IPs";
+ bool check_up_to_date = false;
+ ip = Resolver->get_next_ip(check_up_to_date);
+ }
+ if ( ip.is_valid() )
+ Ping->ping(
+ Resolver->get_next_ip().get_ip(),
+ DestinationPort,
+ boost::bind(&PingScheduler::ping_done_handler, this, _1)
+ );
+ else
+ { // should not happen
+ GlobalLogger.error() << LogPrefix << "No IP to ping "
+ << "-- this should not have happened!!";
+ WantToPing = true;
+ if ( !Resolver.is_resolving() )
+ start_resolving_ping_address();
+ }
}
// Ping Protocol Rotation
//------------------------------------------------------------------------------
-void PingRotate::init_ping_protocol()
+void PingScheduler::init_ping_protocol()
{
+ ProtocolIter = Protocols.end();
get_next_ping_protocol();
}
-void PingRotate::update_ping_protocol()
+void PingScheduler::update_ping_protocol()
{
if ( can_change_ping_protocol() )
{
}
}
-void PingRotate::get_next_ping_protocol()
+void PingScheduler::get_next_ping_protocol()
{
- PingProtocol ping_protocol = ProtocolRotate.front();
- ProtocolRotate.pop_front();
- ProtocolRotate.push_back(ping_protocol);
+ ++ProtocolIter;
+ if (ProtocolIter == Protocols.end())
+ ProtocolIter = Protocols.begin();
+ PingProtocol ping_protocol = *ProtocolIter;
+ // --> ProtocolIter still points to currently used protocol which is
+ // required in dns_resolve_callback
if (Ping)
Ping->stop_pinging();
update_dns_resolver( ping_protocol );
}
-bool PingRotate::can_change_ping_protocol() const
+bool PingScheduler::can_change_ping_protocol() const
{
// TODO can_change_ping_protocol() and get_next_ping_protocol() may be implemented in a Algorithm
// class that can be exchanged in this class to provide an algorithm neutral class
//------------------------------------------------------------------------------
// DNS host name resolution
//------------------------------------------------------------------------------
-//
-void PingRotate::update_dns_resolver( PingProtocol current_protocol )
+
+// show "!" after host name if running on outdated IPs
+void update_log_prefix()
+{
+ std::stringstream temp;
+ temp << "PS(" << DestinationAddress;
+ if (ContinueOnOutdatedIps)
+ temp << "!";
+ temp << "): ";
+ LogPrefix = temp.str();
+}
+
+void PingScheduler::update_dns_resolver( PingProtocol current_protocol )
{
if (Resolver && Resolver->is_resolving())
{
if ( Resolver->have_up_to_date_ip() )
{
if (!Resolver->is_resolving())
- GlobalLogger.warning() << "PingRotate: have up to date IPs but "
+ GlobalLogger.warning() << "PingScheduler: have up to date IPs but "
<< "resolver seems to be resolving all the same... "
<< "Start pinging anyway!";
try_to_ping();
start_resolving_ping_address();
}
-void PingRotate::start_resolving_ping_address() //lint !e1762
+void PingScheduler::start_resolving_ping_address()
{
- Resolver->async_resolve( boost::bind(&PingRotate::dns_resolve_callback,
+ Resolver->async_resolve( boost::bind(&PingScheduler::dns_resolve_callback,
this, _1, _2) );
}
-void PingRotate::dns_resolve_callback(const bool was_success,
- const int cname_count)
+void PingScheduler::dns_resolve_callback(const bool was_success,
+ const int cname_count)
{
- GlobalLogger.info() << "PingRotate: dns resolution finished "
+ GlobalLogger.info() << "PingScheduler: dns resolution finished "
<< "with success = " << was_success << " "
<< "and cname_count = " << cname_count;
- if ( !was_success )
- { // host name resolution failed; try again bypassing first CNAME(s)
- std::string skip_host = Resolver->get_skipper();
+ // TODO this is too simple, but need to think more about how to update here!
+ // (may have to switch back some time to resolver for original host or so
+ ContinueOnOutdatedIps = true;
+ update_log_prefix();
+
+ if ( was_success )
+ {
+ HostAnalyzer.set_resolved_ip_count( Resolver->get_resolved_ip_count());
+ try_to_ping();
+ }
+ else
+ { // host name resolution failed; try again bypassing first outdated CNAME
+
+ std::string skip_host = Resolver->get_skip_cname();
if (skip_host.empty())
{
GlobalLogger.notice() << LogPrefix << "DNS failed, "
<< "try anyway with cached data";
- HostAnalyzer->set_resolved_ip_count(0);
+ HostAnalyzer.set_resolved_ip_count(0);
try_to_ping();
}
else
<< "try again skipping a CNAME and resolving "
<< skip_host << " directly";
Resolver = DnsMaster::get_instance()
- ->get_resolver_for(skip_host, PingRotate.back());
+ ->get_resolver_for(skip_host, *ProtocolIter);
+ // the original resolver is still alive and cached by DnsMaster
+ // and counting down the time to re-try on its own
start_resolving_ping_address();
}
}
- else
- {
- HostAnalyzer->set_resolved_ip_count( Resolver->get_resolved_ip_count());
- try_to_ping();
- }
}
#include "host/pinger.h"
#include "host/pinginterval.h"
#include "host/pingprotocol.h"
-#include "host/pingrotate.h"
+#include "dns/resolverbase.h"
//-----------------------------------------------------------------------------
// PingScheduler
const long ping_interval_in_sec,
const int ping_fail_percentage_limit,
const int ping_reply_timeout,
- const int resolved_ip_ttl_threshold,
LinkStatusItem link_analyzer,
const int first_delay
);
// Methods
//
- void resolve_and_ping(const boost::system::error_code &error);
-
- void ping();
+ void ping(const boost::system::error_code &error);
void ping_done_handler(const bool ping_success);
void update_ping_interval();
void update_ping_elapsed_time();
void try_to_ping();
void dns_resolve_callback(const bool was_success, const int cname_count);
+ void start_resolving_ping_address();
+
+ void update_log_prefix();
//
// Attributes
//
- /// Timer to trigger the next ping
- boost::asio::deadline_timer NextPingTimer;
- /// Timer to trigger the next attempt to resolve addresses
- boost::asio::deadline_timer NextAddressTimer;
- /// Keeps track of the time when the last ping was send
- boost::posix_time::ptime TimeSentLastPing;
- /// Interval between each ping to the same host
- PingInterval PingIntervalInSec;
- /// Interval between attempts to resolve host address
- PingInterval AddressResolveIntervalInSec;
- /// Object responsible to evaluate the status of the host
- HostStatus HostAnalyzer;
- /// delay for very first ping to avoid lots of simultaneous pings
- int FirstDelay;
/// The IO service object, which has the loop event
IoServiceItem IoService;
/// The network interface name
std::string NetworkInterfaceName;
- /// The Dns resolver
- ResolverItem Resolver;
/// The address to ping
std::string DestinationAddress;
- /// The port to ping at destination host (same port to all protocols in the list)
+ /// The port to ping at destination host (same for all protocols)
uint16_t DestinationPort;
- /// time threshold for address resolution
- int ResolvedIpTtlThreshold;
- /// timeout for ping reply
+ /// The list of protocols to ping and iterator over them
+ PingProtocolList Protocols;
+ PingProtocolList::const_iterator ProtocolIter;
+ /// Interval between each ping to the same host
+ PingInterval PingIntervalInSec;
+ /// delay for very first ping to avoid lots of simultaneous pings at startup
+ int FirstDelay;
+ /// Timer to trigger the next ping
+ boost::asio::deadline_timer NextPingTimer;
+ /// Keeps track of the time when the last ping was send
+ boost::posix_time::ptime TimeSentLastPing;
+ /// time threshold for ping
const int PingReplyTimeout;
- /// The list of protocols to ping
- CircularProtocolList ProtocolRotate;
- /// Internal boost pinger object
+ /// Object responsible to evaluate the status of the host
+ HostStatus HostAnalyzer;
+ /// The Dns resolver
+ ResolverItem Resolver;
+ /// The actual pinger
PingerItem Ping;
/// a flag whether we should ping as soon as dns is ready
bool WantToPing;
+ /// Prefix to log messages for quicker analysis/debugging
+ std::string LogPrefix;
+ /// Flag whether DNS resolution has failed so we have to run on outdated IPs
+ bool ContinueOnOutdatedIps;
};
//-----------------------------------------------------------------------------
function<void(bool)> ping_done_callback
)
{
- BOOST_ASSERT( !destination_ip.empty() );
-
PingDoneCallback = ping_done_callback;
// Prepare ping
string default_network_interface = configuration->get_source_network_interface();
int ping_fail_limit = configuration->get_ping_fail_limit();
int ping_reply_timeout = configuration->get_ping_reply_timeout();
- int resolved_ip_ttl_threshold = configuration->get_resolved_ip_ttl_threshold();
// remove some hosts at random
configuration->randomize_hosts();
ping_interval_in_sec,
ping_fail_limit,
ping_reply_timeout,
- resolved_ip_ttl_threshold,
status_notifier,
current_delay
)
--- /dev/null
+# compiler: creates the binaries
+add_executable(test_dns
+ ${CMAKE_SOURCE_DIR}/src/boost_assert_handler.cpp
+ ${CMAKE_SOURCE_DIR}/src/host/pinger.cpp
+ ${CMAKE_SOURCE_DIR}/src/dns/hostaddress.cpp
+ ${CMAKE_SOURCE_DIR}/src/dns/timetolive.cpp
+ ${CMAKE_SOURCE_DIR}/src/dns/dnsmaster.cpp
+ ${CMAKE_SOURCE_DIR}/src/dns/dnscache.cpp
+ ${CMAKE_SOURCE_DIR}/src/dns/resolverbase.cpp
+ ${CMAKE_SOURCE_DIR}/src/dns/dnsresolver.cpp
+ test_dns.cpp
+)
+
+set(Boost_USE_STATIC_LIBS OFF)
+set(Boost_USE_MULTITHREADED OFF)
+set(Boost_USE_STATIC_RUNTIME OFF)
+find_package(Boost 1.44 COMPONENTS serialization date_time REQUIRED)
+include_directories(${Boost_INCLUDE_DIRS})
+link_directories(${Boost_LIBRARY_DIRS})
+
+# package: boost-net-dns
+include_directories(${CMAKE_SOURCE_DIR}/lib/boost-net-dns)
+
+# linker: link the program against the libraries
+target_link_libraries(
+ test_dns
+ ${I2NCOMMON_LIBRARIES}
+ ${Boost_LIBRARIES}
+)
+
+# cmake: invocation via "make test"
+add_test(test_dns test_dns)
include(CMakeLists.test_icmpv6header.txt)
include(CMakeLists.test_icmppacket.txt)
include(CMakeLists.test_tcpheader.txt)
+include(CMakeLists.test_dns.txt)
# cmake: add a custom "make check" target which automatically builds the binary
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} DEPENDS
test_icmpv6header
test_icmppacket
test_tcpheader
+ test_dns
)
--- /dev/null
+/*
+The software in this package is distributed under the GNU General
+Public License version 2 (with a special exception described below).
+
+A copy of GNU General Public License (GPL) is included in this distribution,
+in the file COPYING.GPL.
+
+As a special exception, if other files instantiate templates or use macros
+or inline functions from this file, or you compile this file and link it
+with other works to produce a work based on this file, this file
+does not by itself cause the resulting work to be covered
+by the GNU General Public License.
+
+However the source code for this file must still be made available
+in accordance with section (3) of the GNU General Public License.
+
+This exception does not invalidate any other reasons why a work based
+on this file might be covered by the GNU General Public License.
+*/
+
+#define BOOST_TEST_MAIN
+#define BOOST_TEST_DYN_LINK
+
+#include <algorithm>
+
+#include <boost/test/unit_test.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/ip/address.hpp>
+
+#include "host/pingprotocol.h"
+#include "dns/hostaddress.h"
+#include "dns/dnsmaster.h"
+#include "dns/dnscache.h"
+#include "dns/resolverbase.h"
+
+//------------------------------------------------------------------------------
+// helper functions
+//------------------------------------------------------------------------------
+
+void create_master();
+
+// TODO: try to run this only once for test suite
+void create_master()
+{
+ // only create if it does not exist yet
+ DnsMasterItem master = DnsMaster::get_instance();
+ if ( !master )
+ {
+ boost::asio::ip::address name_server =
+ boost::asio::ip::address::from_string("127.0.0.1");
+ int resolved_ip_ttl_threshold = 3;
+ int max_address_resolution_attempts = 2;
+ std::string cache_file = DO_NOT_USE_CACHE_FILE;
+ IoServiceItem io_serv;
+
+ // create it
+ DnsMaster::create_master(io_serv,
+ name_server,
+ resolved_ip_ttl_threshold,
+ max_address_resolution_attempts,
+ cache_file);
+ master = DnsMaster::get_instance();
+
+ // simple checks
+ BOOST_CHECK_EQUAL( master->get_resolved_ip_ttl_threshold(),
+ resolved_ip_ttl_threshold );
+ BOOST_CHECK_EQUAL( master->get_max_address_resolution_attempts(),
+ max_address_resolution_attempts );
+ }
+}
+
+//------------------------------------------------------------------------------
+// test suite
+//------------------------------------------------------------------------------
+
+BOOST_AUTO_TEST_SUITE( TestDns )
+
+BOOST_AUTO_TEST_CASE( create_master )
+{
+ create_master();
+}
+
+BOOST_AUTO_TEST_CASE( create_v4 )
+{
+ create_master();
+
+ // create resolver
+ std::string hostname = "www.intra2net.com";
+ ResolverItem resolver = DnsMaster::get_instance()
+ ->get_resolver_for(hostname, PingProtocol_ICMP);
+ BOOST_CHECK_EQUAL( resolver->get_hostname(), hostname );
+ BOOST_CHECK( !resolver->is_resolving() );
+
+ // cancel should have no effect
+ resolver->cancel_resolve();
+ BOOST_CHECK( !resolver->is_resolving() );
+
+ // should not have any ips since cache did not load anything
+ BOOST_CHECK_EQUAL( resolver->get_resolved_ip_count(), 0 );
+ BOOST_CHECK( !resolver->have_up_to_date_ip() );
+ std::string no_ip = "0.0.0.0";
+ BOOST_CHECK_EQUAL( resolver->get_next_ip().get_ip().to_string(), no_ip );
+}
+
+BOOST_AUTO_TEST_SUITE_END()