merged PingRotate into PingScheduler; fixed save/load of cache to/from file; started...
authorChristian Herdtweck <christian.herdtweck@intra2net.com>
Fri, 24 Apr 2015 16:41:29 +0000 (18:41 +0200)
committerChristian Herdtweck <christian.herdtweck@intra2net.com>
Mon, 4 May 2015 14:57:58 +0000 (16:57 +0200)
code now compiles and links and pings again!

merged because through Asynchronicity it is more difficult to give feedback from Rotate to Scheduler
further changes
* in cache ensure that there is not cname and ip for same hostname
* in cache remove trailing dots from hostnames
* by default ask only for [number of] updatd IPs in retrieval from resolver
* remove some left-overs from recursive resolving (e.g. Recursor creation in master)

20 files changed:
doc/pingcheck_icmp_distributor.graphml
src/dns/dnscache.cpp
src/dns/dnscache.h
src/dns/dnsmaster.cpp
src/dns/dnsmaster.h
src/dns/dnsresolver.cpp
src/dns/dnsresolver.h
src/dns/hostaddress.cpp
src/dns/hostaddress.h
src/dns/ippseudoresolver.h
src/dns/resolverbase.cpp
src/dns/resolverbase.h
src/dns/timetolive.h
src/host/pingscheduler.cpp
src/host/pingscheduler.h
src/icmp/icmppinger.cpp
src/main.cpp
test/CMakeLists.test_dns.txt [new file with mode: 0644]
test/CMakeLists.txt
test/test_dns.cpp [new file with mode: 0644]

index bca452a..7e532fa 100644 (file)
@@ -35,7 +35,7 @@
               <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 --&gt; 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>
@@ -516,7 +516,7 @@ PingIntervalInSec<y:LabelModel>
               <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>
@@ -1407,7 +1407,6 @@ _ping_address<y:LabelModel>
           </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"/>
@@ -1426,7 +1425,6 @@ _ping_address<y:LabelModel>
           </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"/>
@@ -1444,7 +1442,6 @@ _ping_address<y:LabelModel>
           </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"/>
@@ -1462,7 +1459,6 @@ _ping_address<y:LabelModel>
           </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"/>
@@ -1480,7 +1476,6 @@ _ping_address<y:LabelModel>
           </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"/>
@@ -1500,13 +1495,12 @@ finished<y:LabelModel>
           </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>
@@ -1519,7 +1513,6 @@ finished<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"/>
@@ -1559,7 +1552,7 @@ IPs?<y:LabelModel>
               <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"/>
@@ -1588,7 +1581,6 @@ or destin. unreach<y:LabelModel>
           </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"/>
@@ -1606,7 +1598,6 @@ or destin. unreach<y:LabelModel>
           </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"/>
@@ -1624,7 +1615,6 @@ or destin. unreach<y:LabelModel>
           </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"/>
@@ -1642,7 +1632,6 @@ or destin. unreach<y:LabelModel>
           </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"/>
@@ -1661,7 +1650,6 @@ or destin. unreach<y:LabelModel>
           </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"/>
@@ -1679,7 +1667,6 @@ or destin. unreach<y:LabelModel>
           </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"/>
@@ -1698,7 +1685,6 @@ or destin. unreach<y:LabelModel>
           </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"/>
@@ -1716,7 +1702,6 @@ or destin. unreach<y:LabelModel>
           </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"/>
@@ -1735,7 +1720,6 @@ cancel_resolve<y:LabelModel>
           </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"/>
@@ -1758,7 +1742,7 @@ SIGKILL<y:LabelModel>
     <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>
@@ -1775,7 +1759,7 @@ SIGKILL<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>
@@ -1792,7 +1776,7 @@ SIGKILL<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
@@ -1810,7 +1794,7 @@ SIGKILL<y:LabelModel>
     <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>
@@ -1827,7 +1811,7 @@ SIGKILL<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>
@@ -1844,7 +1828,7 @@ SIGKILL<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
@@ -1862,7 +1846,7 @@ Socket<y:LabelModel>
     <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>
@@ -1878,7 +1862,7 @@ Socket<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>
@@ -1895,7 +1879,7 @@ Socket<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>
@@ -1912,7 +1896,7 @@ Socket<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>
@@ -1929,7 +1913,7 @@ Socket<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>
@@ -1946,7 +1930,7 @@ Socket<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>
@@ -1963,7 +1947,7 @@ Socket<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>
@@ -1980,7 +1964,7 @@ Socket<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>
@@ -1997,41 +1981,7 @@ Socket<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>
@@ -2045,10 +1995,10 @@ Socket<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>
@@ -2062,10 +2012,10 @@ Socket<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>
@@ -2085,7 +2035,7 @@ Socket<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>
@@ -2112,7 +2062,7 @@ shared_ptrs<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>
@@ -2138,7 +2088,7 @@ shared_ptrs<y:LabelModel>
           <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>
@@ -2173,7 +2123,7 @@ shared_ptrs<y:LabelModel>
           <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>
@@ -2199,7 +2149,7 @@ shared_ptrs<y:LabelModel>
           <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>
@@ -2216,7 +2166,7 @@ shared_ptrs<y:LabelModel>
           <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>
@@ -2233,7 +2183,7 @@ shared_ptrs<y:LabelModel>
           <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>
@@ -2250,7 +2200,7 @@ shared_ptrs<y:LabelModel>
           <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>
@@ -2288,13 +2238,13 @@ shared_ptrs<y:LabelModel>
         </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>
@@ -2305,13 +2255,13 @@ shared_ptrs<y:LabelModel>
         </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>
@@ -2322,30 +2272,13 @@ shared_ptrs<y:LabelModel>
         </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>
@@ -2385,30 +2318,13 @@ shared_ptrs<y:LabelModel>
         </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>
@@ -2923,13 +2839,13 @@ shared_ptrs<y:LabelModel>
         </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>
@@ -2940,13 +2856,13 @@ shared_ptrs<y:LabelModel>
         </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>
@@ -3073,7 +2989,6 @@ shared_ptrs<y:LabelModel>
       </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"/>
@@ -3084,7 +2999,6 @@ shared_ptrs<y:LabelModel>
       </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"/>
@@ -3095,7 +3009,6 @@ shared_ptrs<y:LabelModel>
       </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"/>
@@ -3106,7 +3019,6 @@ shared_ptrs<y:LabelModel>
       </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"/>
@@ -3117,7 +3029,6 @@ shared_ptrs<y:LabelModel>
       </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"/>
@@ -3128,7 +3039,6 @@ shared_ptrs<y:LabelModel>
       </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"/>
@@ -3139,7 +3049,6 @@ shared_ptrs<y:LabelModel>
       </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"/>
@@ -3150,7 +3059,6 @@ shared_ptrs<y:LabelModel>
       </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"/>
@@ -3161,7 +3069,6 @@ shared_ptrs<y:LabelModel>
       </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"/>
@@ -3172,7 +3079,6 @@ shared_ptrs<y:LabelModel>
       </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"/>
@@ -3191,7 +3097,6 @@ shared_ptrs<y:LabelModel>
       </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"/>
@@ -3210,7 +3115,6 @@ shared_ptrs<y:LabelModel>
       </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"/>
@@ -3221,7 +3125,6 @@ shared_ptrs<y:LabelModel>
       </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"/>
@@ -3232,7 +3135,6 @@ shared_ptrs<y:LabelModel>
       </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">
@@ -3245,7 +3147,6 @@ shared_ptrs<y:LabelModel>
       </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"/>
@@ -3256,7 +3157,6 @@ shared_ptrs<y:LabelModel>
       </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"/>
@@ -3267,7 +3167,6 @@ shared_ptrs<y:LabelModel>
       </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"/>
@@ -3278,7 +3177,6 @@ shared_ptrs<y:LabelModel>
       </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"/>
@@ -3297,7 +3195,6 @@ shared_ptrs<y:LabelModel>
       </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"/>
@@ -3308,7 +3205,6 @@ shared_ptrs<y:LabelModel>
       </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"/>
@@ -3326,7 +3222,6 @@ shared_ptrs<y:LabelModel>
       </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">
@@ -3338,7 +3233,6 @@ shared_ptrs<y:LabelModel>
       </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"/>
@@ -3348,7 +3242,6 @@ shared_ptrs<y:LabelModel>
       </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"/>
@@ -3358,7 +3251,6 @@ shared_ptrs<y:LabelModel>
       </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"/>
index d516ae2..d306fd1 100644 (file)
@@ -58,6 +58,11 @@ Cname::Cname(const std::string &host, const uint32_t ttl)
     , 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()
@@ -78,7 +83,7 @@ DnsCache::DnsCache(const IoServiceItem &io_serv,
 
 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();
@@ -117,109 +122,121 @@ void DnsCache::schedule_save(const boost::system::error_code &error)
 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;
 }
 
 
@@ -229,24 +246,32 @@ void DnsCache::update(const std::string &hostname,
 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;
 }
 
@@ -256,16 +281,17 @@ HostAddressVec DnsCache::get_ips(const std::string &hostname,
 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
         {
@@ -290,7 +316,7 @@ HostAddressVec DnsCache::get_ips_recursive(const std::string &hostname,
     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)
@@ -353,7 +379,7 @@ std::string DnsCache::get_first_outdated_cname(const std::string &hostname,
         }
 
         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)
index 7a0fbe8..eaca600 100644 (file)
@@ -53,6 +53,7 @@ struct Cname
 
     Cname();
     Cname(const std::string &host, const uint32_t ttl);
+    Cname(const std::string &host, const TimeToLive &ttl);
 
     // serialization
     friend class boost::serialization::access;
@@ -72,6 +73,10 @@ struct Cname
 };
 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
@@ -85,9 +90,8 @@ public:
     ~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,
@@ -112,6 +116,7 @@ private:
     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;
 
 };
 
index 5b0a1ce..609924d 100644 (file)
@@ -87,9 +87,10 @@ DnsMaster::~DnsMaster()
     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();
     }
 
@@ -147,28 +148,6 @@ ResolverItem& DnsMaster::get_resolver_for(const std::string &hostname,
     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
  *
index 63e5be9..27470a9 100644 (file)
@@ -86,9 +86,6 @@ public:
                                    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:
index 1e236d3..3240e31 100644 (file)
@@ -234,11 +234,7 @@ void DnsResolver::handle_dns_result(const boost::system::error_code &error,
 
     // 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 );
@@ -674,34 +670,61 @@ void DnsResolver::wait_timer_timeout_handler(
 // 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)
index 1e8ce1a..895f6b4 100644 (file)
@@ -52,10 +52,6 @@ public:
     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,
@@ -65,7 +61,7 @@ private:
 
 // 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();
index ebc01ad..2879090 100644 (file)
@@ -72,3 +72,9 @@ void HostAddress::set_ttl( const TimeToLive &ttl )
 {
     Ttl = ttl;
 }
+
+bool HostAddress::is_valid() const
+{
+    return Ip == address() || Ip == boost::asio::ip::address_v4()
+                           || Ip == boost::asio::ip::address_v6();
+}
index d5fdf18..4fdc82f 100644 (file)
@@ -51,6 +51,10 @@ public:
     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;
@@ -64,18 +68,18 @@ private:
     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);
 
     }
 
index f508749..a3edee7 100644 (file)
@@ -63,7 +63,8 @@ private:
 
 // 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;      }
index 1ca1375..82b6c29 100644 (file)
@@ -55,7 +55,7 @@ ResolverBase::ResolverBase(const IoServiceItem &io_serv,
 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(
@@ -71,21 +71,19 @@ std::string ResolverBase::get_skipper() const
 }
 
 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
index 3b0fa09..7ceea42 100644 (file)
@@ -55,13 +55,13 @@ public:
     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,
@@ -80,13 +80,12 @@ protected:
     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;
index 70d9433..e3cd579 100644 (file)
@@ -68,13 +68,11 @@ private:
     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);
     }
 
index 2b476f4..694f6a7 100644 (file)
@@ -23,11 +23,13 @@ on this file might be covered by the GNU General Public License.
 #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"
 
@@ -67,22 +69,27 @@ PingScheduler::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
 
 ) :
     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() );
@@ -92,13 +99,7 @@ PingScheduler::PingScheduler(
     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();
 }
@@ -164,30 +165,46 @@ void PingScheduler::ping(const boost::system::error_code &error)
 }
 
 
-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();
+    }
 }
 
 
@@ -254,12 +271,13 @@ void PingScheduler::update_ping_elapsed_time()
 // 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() )
     {
@@ -267,11 +285,14 @@ void PingRotate::update_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();
@@ -282,7 +303,7 @@ void PingRotate::get_next_ping_protocol()
     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
@@ -292,8 +313,19 @@ bool PingRotate::can_change_ping_protocol() const
 //------------------------------------------------------------------------------
 // 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())
     {
@@ -311,7 +343,7 @@ void PingRotate::update_dns_resolver( PingProtocol current_protocol )
     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();
@@ -320,28 +352,39 @@ void PingRotate::update_dns_resolver( PingProtocol current_protocol )
         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
@@ -350,13 +393,10 @@ void PingRotate::dns_resolve_callback(const bool was_success,
                 << "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();
-    }
 }
index 250bf85..e61b0b0 100644 (file)
@@ -33,7 +33,7 @@ on this file might be covered by the GNU General Public License.
 #include "host/pinger.h"
 #include "host/pinginterval.h"
 #include "host/pingprotocol.h"
-#include "host/pingrotate.h"
+#include "dns/resolverbase.h"
 
 //-----------------------------------------------------------------------------
 // PingScheduler
@@ -56,7 +56,6 @@ public:
             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
     );
@@ -70,9 +69,7 @@ private:
     // 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();
@@ -86,45 +83,47 @@ private:
 
     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;
 };
 
 //-----------------------------------------------------------------------------
index 501a8b7..e6d51b6 100644 (file)
@@ -127,8 +127,6 @@ void IcmpPinger::ping(
         function<void(bool)> ping_done_callback
 )
 {
-    BOOST_ASSERT( !destination_ip.empty() );
-
     PingDoneCallback = ping_done_callback;
 
     // Prepare ping
index 46d0f58..972c0f7 100644 (file)
@@ -235,7 +235,6 @@ void init_pingers(
     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();
@@ -274,7 +273,6 @@ void init_pingers(
                         ping_interval_in_sec,
                         ping_fail_limit,
                         ping_reply_timeout,
-                        resolved_ip_ttl_threshold,
                         status_notifier,
                         current_delay
                 )
diff --git a/test/CMakeLists.test_dns.txt b/test/CMakeLists.test_dns.txt
new file mode 100644 (file)
index 0000000..158e588
--- /dev/null
@@ -0,0 +1,32 @@
+# 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)
index 3351090..7404ed2 100644 (file)
@@ -39,6 +39,7 @@ include(CMakeLists.test_icmpv4header.txt)
 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
@@ -56,4 +57,5 @@ add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} DEPENDS
     test_icmpv6header
     test_icmppacket
     test_tcpheader
+    test_dns
 )
diff --git a/test/test_dns.cpp b/test/test_dns.cpp
new file mode 100644 (file)
index 0000000..8ce9793
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+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()