]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
zone2lmdb and lmdb-backend regression tests
authorKees Monshouwer <mind04@monshouwer.org>
Wed, 28 May 2014 22:02:18 +0000 (00:02 +0200)
committermind04 <mind04@monshouwer.org>
Tue, 24 Jun 2014 16:23:25 +0000 (18:23 +0200)
.travis.yml
configure.ac
pdns/.gitignore
pdns/Makefile.am
pdns/zone2lmdb.cc [new file with mode: 0644]
regression-tests/.gitignore
regression-tests/backends/common
regression-tests/backends/lmdb-master [new file with mode: 0644]

index eee49816eefa5482670cd47bcd545334bce60c70..2f338e8fbe6668231f0f8fb7ed03aaaf75f65324 100644 (file)
@@ -79,6 +79,7 @@ script:
  - ./timestamp ./start-test-stop 5300 gsqlite3-nsec3-both
  - ./timestamp ./start-test-stop 5300 gsqlite3-nsec3-optout-both
  - ./timestamp ./start-test-stop 5300 gsqlite3-nsec3-narrow
+ - ./timestamp ./start-test-stop 5300 lmdb-nodnssec
  - ./timestamp ./start-test-stop 5300 mydns
  - ./timestamp ./start-test-stop 5300 opendbx-sqlite3
  - travis_retry ./timestamp timeout 120s ./start-test-stop 5300 remotebackend-pipe # Workaround for remotebackend failures on travis-ci
index 84dec815232ee90363c96cba4bd383c051749f60..ad7f7ee44765a84138092cef8f9847e16d182cea 100644 (file)
@@ -247,6 +247,7 @@ for a in $modules $dynmodules; do
       ;;
     lmdb)
       PDNS_WITH_LMDB
+      needlmdb=yes
       ;;
     mydns|gmysql|pdns)
       PDNS_WITH_MYSQL
@@ -271,6 +272,8 @@ done
 
 AM_CONDITIONAL([ORACLE],[test "x$needoracle" = "xyes"])
 
+AM_CONDITIONAL([LMDB],[test "x$needlmdb" = "xyes"])
+
 AM_CONDITIONAL([SQLITE3], [test "x$needsqlite3" = "xyes"])
 if test "$needsqlite3"; then
   PKG_CHECK_MODULES([SQLITE3], $SQLITE3PC,
index 2c4f7809298b064a003ef4b20c3940e3807fd033..96f8b4054ab4bf36cca9ccde4d057daf08484a3b 100644 (file)
@@ -37,6 +37,7 @@ version_generated.h
 /zone2ldap
 /zone2sql
 /zone2json
+/zone2lmdb
 /bindlexer.c
 /bindparser.cc
 /bindparser.h
index 177ccb8b6f499b8b024770aa219434b517b0a9c9..17b3f53f295849a7695d0e3b352e371065dd076a 100644 (file)
@@ -145,6 +145,20 @@ zone2ldap_SOURCES=bindparser.yy bindlexer.l bind-dnssec.schema.sqlite3.sql.h \
 zone2ldap_LDFLAGS=@THREADFLAGS@
 zone2ldap_LDADD= $(POLARSSL_LIBS)
 
+if LMDB
+bin_PROGRAMS += zone2lmdb
+
+zone2lmdb_SOURCES=bindparser.yy bindlexer.l bind-dnssec.schema.sqlite3.sql.h \
+       arguments.cc logger.cc zone2lmdb.cc statbag.cc misc.cc \
+       unix_utility.cc qtype.cc zoneparser-tng.cc dnsrecords.cc \
+       dnswriter.cc dnslabeltext.cc rcpgenerator.cc dnsparser.cc base64.cc sillyrecords.cc \
+       nsecrecords.cc base32.cc bindparserclasses.hh \
+       dns_random.cc dns.cc
+
+zone2lmdb_LDFLAGS=@THREADFLAGS@
+zone2lmdb_LDADD= $(POLARSSL_LIBS) -llmdb
+endif
+
 if BOTAN110
 pdnssec_SOURCES += botan110signers.cc botansigners.cc
 pdnssec_LDADD += $(BOTAN110_LIBS) -lgmp -lrt
diff --git a/pdns/zone2lmdb.cc b/pdns/zone2lmdb.cc
new file mode 100644 (file)
index 0000000..e7d7b64
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2002 - 2014  PowerDNS.COM BV
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License version 2
+    as published by the Free Software Foundation
+
+    Additionally, the license of this program contains a special
+    exception which allows to distribute the program in binary form when
+    it is linked against OpenSSL.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <unistd.h>
+#include <string>
+#include <map>
+
+#include <iostream>
+#include <stdio.h>
+#include "namespaces.hh"
+
+#include "dns.hh"
+#include "arguments.hh"
+#include "bindparserclasses.hh"
+#include "statbag.hh"
+#include "misc.hh"
+#include "dnspacket.hh"
+#include "zoneparser-tng.hh"
+#include "dnsrecords.hh"
+#include <boost/algorithm/string.hpp>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <boost/foreach.hpp>
+#include <lmdb.h>
+
+StatBag S;
+int g_numZones=0;
+int g_numRecords=0;
+int g_numRefs=0;
+
+MDB_env *env;
+MDB_dbi data_db, zone_db, data_extended_db;
+MDB_txn *txn, *txn_zone;
+
+void openDB(){
+  mdb_env_create(&env);
+  mdb_env_set_mapsize(env, 1*1024*1024*1024);
+  mdb_env_set_maxdbs(env, 3);
+  mdb_env_open(env, "./", 0, 0644);
+
+  mdb_txn_begin(env, NULL, 0, &txn);
+
+  mdb_dbi_open(txn, "zone", MDB_CREATE, &zone_db);
+  mdb_dbi_open(txn, "data", MDB_CREATE | MDB_DUPSORT, &data_db);
+  mdb_dbi_open(txn, "extended_data", MDB_CREATE, &data_extended_db);
+}
+
+void closeDB(){
+  mdb_txn_commit(txn);
+  mdb_dbi_close(env, data_db);
+  mdb_dbi_close(env, zone_db);
+  mdb_dbi_close(env, data_extended_db);
+  mdb_env_close(env);
+}
+
+string reverse(const string &name) {
+  return toLower(string(name.rbegin(), name.rend()));
+}
+
+void emitData(string zone, ZoneParserTNG &zpt){
+
+  bool hasSOA = false;
+  int numRefs=g_numRefs;
+  int numRecords=g_numRecords;
+  SOAData sd;
+  DNSResourceRecord rr;
+  MDB_val key, data, keyExt, dataExt;
+
+  mdb_txn_begin(env, txn, 0, &txn_zone);
+  while(zpt.get(rr)) {
+    numRecords++;
+    if (rr.qtype == QType::SOA) {
+      hasSOA = true;
+      fillSOAData(rr.content, sd);
+      sd.ttl=rr.ttl;
+      continue;
+    }
+    string keyStr=reverse(stripDot(rr.qname))+"\t"+rr.qtype.getName();
+    string dataStr=itoa(g_numZones+1)+"\t"+itoa(rr.ttl)+"\t"+rr.content;
+
+    key.mv_data = (char*)keyStr.c_str();
+    key.mv_size = keyStr.length();
+    data.mv_data = (char*)dataStr.c_str();
+    data.mv_size = dataStr.length();
+
+    if (dataStr.length() > 500) {
+      string keyStrExt=itoa(++numRefs);
+      string dataStrExt="REF\t"+itoa(numRefs);
+
+      keyExt.mv_data = (char*)keyStrExt.c_str();
+      keyExt.mv_size = keyStrExt.length();
+      dataExt.mv_data = (char*)dataStrExt.c_str();
+      dataExt.mv_size = dataStrExt.length();
+
+      mdb_put(txn_zone, data_extended_db, &keyExt, &data, 0);
+      mdb_put(txn_zone, data_db, &key, &dataExt, 0);
+    } else
+      mdb_put(txn_zone, data_db, &key, &data, 0);
+  }
+  if (hasSOA) {
+    string keyStr=(reverse(stripDot(zone)));
+    string dataStr=itoa(g_numZones+1)+"\t"+itoa(sd.ttl)+"\t"+serializeSOAData(sd);
+
+    key.mv_data = (char*)keyStr.c_str();
+    key.mv_size = keyStr.length();
+    data.mv_data = (char*)dataStr.c_str();
+    data.mv_size = dataStr.length();
+
+    mdb_put(txn_zone, zone_db, &key, &data, 0);
+  } else {
+    mdb_txn_abort(txn_zone);
+    throw PDNSException("Zone'"+zone+"' has no SOA record");
+  }
+  mdb_txn_commit(txn_zone);
+  g_numZones++;
+  g_numRecords=numRecords;
+  g_numRefs=numRefs;
+}
+
+ArgvMap &arg()
+{
+  static ArgvMap theArg;
+  return theArg;
+}
+
+
+int main(int argc, char **argv)
+try
+{
+  reportAllTypes();
+  reportFancyTypes();
+#if __GNUC__ >= 3
+  std::ios_base::sync_with_stdio(false);
+#endif
+
+  ::arg().setSwitch("verbose","Verbose comments on operation")="no";
+  ::arg().setSwitch("on-error-resume-next","Continue after errors")="no";
+  ::arg().set("zone","Zonefile to parse")="";
+  ::arg().set("zone-name","Specify an $ORIGIN in case it is not present")="";
+  ::arg().set("named-conf","Bind 8/9 named.conf to parse")="";
+  
+  ::arg().set("soa-minimum-ttl","Do not change")="0";
+  ::arg().set("soa-refresh-default","Do not change")="0";
+  ::arg().set("soa-retry-default","Do not change")="0";
+  ::arg().set("soa-expire-default","Do not change")="0";
+
+  ::arg().setCmd("help","Provide a helpful message");
+
+  S.declare("logmessages");
+
+  string namedfile="";
+  string zonefile="";
+
+  ::arg().parse(argc, argv);
+
+  if(::arg().mustDo("help")) {
+    cout<<"syntax:"<<endl<<endl;
+    cout<<::arg().helpstring()<<endl;
+    exit(0);
+  }
+
+  if(argc<2) {
+    cerr<<"syntax:"<<endl<<endl;
+    cerr<<::arg().helpstring()<<endl;
+    exit(1);
+  }
+
+  namedfile=::arg()["named-conf"];
+  zonefile=::arg()["zone"];
+
+  int count=0;
+
+  if(zonefile.empty()) {
+    BindParser BP;
+    BP.setVerbose(::arg().mustDo("verbose"));
+    BP.parse(namedfile.empty() ? "./named.conf" : namedfile);
+
+    vector<BindDomainInfo> domains=BP.getDomains();
+    struct stat st;
+    for(vector<BindDomainInfo>::iterator i=domains.begin(); i!=domains.end(); ++i) {
+      if(stat(i->filename.c_str(), &st) == 0) {
+        i->d_dev = st.st_dev;
+        i->d_ino = st.st_ino;
+      }
+    }
+
+    sort(domains.begin(), domains.end()); // put stuff in inode order
+
+    int numdomains=domains.size();
+    int tick=numdomains/100;
+
+    cout <<"[";
+    openDB();
+    for(vector<BindDomainInfo>::const_iterator i=domains.begin(); i!=domains.end(); ++i) {
+      if(i->type!="master" && i->type!="slave") {
+        cerr<<" Warning! Skipping '"<<i->type<<"' zone '"<<i->name<<"'"<<endl;
+        continue;
+      }
+      try {
+        ZoneParserTNG zpt(i->filename, i->name, BP.getDirectory());
+        emitData(i->name, zpt);
+      }
+      catch(std::exception &ae) {
+        if(!::arg().mustDo("on-error-resume-next"))
+          throw;
+        else
+          cerr<<endl<<ae.what()<<endl;
+      }
+      catch(PDNSException &ae) {
+        if(!::arg().mustDo("on-error-resume-next"))
+          throw;
+        else
+          cerr<<ae.reason<<endl;
+      }
+      if(!tick || !((count++)%tick))
+        cerr<<"\r"<<count*100/numdomains<<"% done ("<<i->filename<<")\033\133\113";
+    }
+    cout << "]\n";
+    cerr<<"\r100% done\033\133\113"<<endl;
+  }
+  else {
+    ZoneParserTNG zpt(zonefile, ::arg()["zone-name"]);
+    cout << "{\"name\":\"" << ::arg()["zone-name"] << "\",\"records\":";
+    emitData(::arg()["zone-name"], zpt);
+    cout << "}\n";
+  }
+  cerr<<g_numZones<<" domains were fully parsed, containing "<<g_numRecords<<" records\n";
+  closeDB();
+  return 0;
+
+}
+catch(PDNSException &ae) {
+  cerr<<endl<<"Fatal error: "<<ae.reason<<endl;
+  return 1;
+}
+catch(std::exception &e) {
+  cerr<<endl<<"Died because of STL error: "<<e.what()<<endl;
+  return 1;
+}
+catch(...) {
+  cerr<<endl<<"Died because of unknown exception"<<endl;
+  return 1;
+}
index b354825e92823b2f6fd53ce5801db59b831e3998..5e3f3e6470959cd29b1ab75ffb0b620bd453d171 100644 (file)
@@ -29,3 +29,5 @@
 /goracle2.log
 /oracle.log
 /oracle2.log
+/data.mdb
+/lock.mdb
index e420b87bbc590ac8c812998b89218bbfddee373a..d5d8bf930b678fec28b3cc0c604f6d54bf7ccceb 100644 (file)
@@ -21,6 +21,10 @@ start_master ()
                                source ./backends/gsqlite3-master
                                ;;
 
+                       lmdb*)
+                               source ./backends/lmdb-master
+                               ;;
+
                        mydns*)
                                source ./backends/mydns-master
                                ;;
diff --git a/regression-tests/backends/lmdb-master b/regression-tests/backends/lmdb-master
new file mode 100644 (file)
index 0000000..fd15924
--- /dev/null
@@ -0,0 +1,69 @@
+case $context in
+       lmdb-nodnssec | lmdb | lmdb-nsec3 | lmdb-nsec3-optout | lmdb-nodnssec-zone | lmdb-zone | lmdb-nsec3-zone | lmdb-nsec3-optout-zone)
+
+               if [ "${context: -5}" = "-zone" ]
+               then
+                       orgcontext=$context
+
+                       case $context in
+                               lmdb-nodnssec-zone)
+                                       context=bind
+                                       ;;
+                               lmdb-zone)
+                                       context=bind-dnssec
+                                       ;;
+                               lmdb-nsec3-zone)
+                                       context=bind-dnssec-nsec3
+                                       ;;
+                               lmdb-nsec3-optout-zone)
+                                       context=bind-dnssec-nsec3-optout
+                                       ;;
+                       esac
+
+                       source ./backends/bind-master
+
+                       for zone in $(grep 'zone ' named.conf  | cut -f2 -d\")
+                       do
+                               ../pdns/saxfr 127.0.0.1 $port $zone showdetails showflags > zones/$zone.signed
+                       done
+                       kill $(cat pdns*.pid)
+                       sleep 2
+                       context=${orgcontext%-zone}
+               fi
+
+               ${MAKE} -C ../pdns zone2sql > /dev/null
+               rm -f data.mdb lock.mdb
+               ../pdns/zone2lmdb --named-conf=./named.conf
+
+               $RUNWRAPPER $PDNS --daemon=no --local-port=$port --socket-dir=./  \
+                       --no-shuffle --launch=lmdb \
+                       --send-root-referral \
+                       --cache-ttl=$cachettl --experimental-dname-processing --no-config \
+                       --lmdb-datapath=./ &
+               
+               skipreasons="noent nodyndns nometa lmdb"
+
+               if [ $context = lmdb-nsec3 ]
+               then
+                       extracontexts="dnssec nsec3"
+                       skipreasons="$skipreasons nsec3"
+               elif [ $context = lmdb-nsec3-optout ]
+               then
+                       extracontexts="dnssec nsec3 nsec3-optout"
+                       skipreasons="$skipreasons optout"
+               elif [ $context = lmdb-nsec3-narrow ]
+               then
+                       extracontexts="dnssec narrow"
+                       skipreasons="$skipreasons narrow"
+               elif [ $context = lmdb-nodnssec ]
+               then
+                       skipreasons="$skipreasons nodnssec"
+               else
+                       extracontexts="dnssec"
+                       skipreasons="$skipreasons"
+               fi
+               ;;
+
+       *)
+               nocontext=yes
+esac