Browse Source

[2377] Handle expected errors

By catching all exceptions. It is questionable, if we want to do it that
way, but it seems to work at least for now.
Michal 'vorner' Vaner 12 years ago
parent
commit
11ed5b5ca1
2 changed files with 82 additions and 39 deletions
  1. 80 37
      src/lib/dns/master_loader.cc
  2. 2 2
      src/lib/dns/tests/master_loader_unittest.cc

+ 80 - 37
src/lib/dns/master_loader.cc

@@ -64,45 +64,88 @@ public:
         }
         size_t count = 0;
         while (ok_ && count < count_limit) {
-            // Skip all EOLNs (empty lines) and finish on EOF
-            bool empty = true;
-            do {
-                const MasterToken& empty_token(lexer_.getNextToken());
-                if (empty_token.getType() == MasterToken::END_OF_FILE) {
-                    // TODO: Check if this is the last source, possibly pop
+            try {
+                // Skip all EOLNs (empty lines) and finish on EOF
+                bool empty = true;
+                do {
+                    const MasterToken& empty_token(lexer_.getNextToken());
+                    if (empty_token.getType() == MasterToken::END_OF_FILE) {
+                        // TODO: Check if this is the last source, possibly pop
+                        return (true);
+                    }
+                    empty = empty_token.getType() == MasterToken::END_OF_LINE;
+                } while (empty);
+                // Return the last token, as it was not empty
+                lexer_.ungetToken();
+
+                const MasterToken::StringRegion
+                    name_string(lexer_.getNextToken(MasterToken::QSTRING).
+                                getStringRegion());
+                // TODO $ handling
+                const Name name(name_string.beg, name_string.len,
+                                &zone_origin_);
+                // TODO: Some more flexibility. We don't allow omitting
+                // anything yet
+
+                // The parameters
+                const RRTTL ttl(getString());
+                const RRClass rrclass(getString());
+                const RRType rrtype(getString());
+
+                // TODO: Some more validation?
+                if (rrclass != zone_class_) {
+                    // It doesn't really matter much what type of exception
+                    // we throw, we catch it just below.
+                    isc_throw(isc::BadValue, "Class mismatch: " << rrclass <<
+                              "vs. " << zone_class_);
+                }
+
+                const rdata::RdataPtr data(rdata::createRdata(rrtype, rrclass,
+                                                              lexer_,
+                                                              &zone_origin_,
+                                                              options_,
+                                                              callbacks_));
+                // In case we get NULL, it means there was error creating
+                // the Rdata. The errors should have been reported by
+                // callbacks_ already. We need to decide if we want to continue
+                // or not.
+                if (data != rdata::RdataPtr()) {
+                    add_callback_(name, rrclass, rrtype, ttl, data);
+
+                    // Good, we loaded another one
+                    ++count;
+                } else if (!(options_ & MANY_ERRORS)) {
+                    return (true);
+                }
+            } catch (const isc::Exception& e) {
+                // TODO: Do we want to list expected exceptions here instead?
+                callbacks_.error(lexer_.getSourceName(),
+                                 lexer_.getSourceLine(),
+                                 e.what());
+                if (options_ & MANY_ERRORS) {
+                    // We want to continue. Try to read until the end of line
+                    bool end = false;
+                    do {
+                        const MasterToken& token(lexer_.getNextToken());
+                        switch (token.getType()) {
+                            case MasterToken::END_OF_FILE:
+                                // TODO: Try pop in case this is not the only
+                                // source
+                                return (true);
+                            case MasterToken::END_OF_LINE:
+                                end = true;
+                                break;
+                            default:
+                                // Do nothing. This is just to make compiler
+                                // happy
+                                break;
+                        }
+                    } while (!end);
+                } else {
+                    // We abort on first error. We are therefore done.
                     return (true);
                 }
-                empty = empty_token.getType() == MasterToken::END_OF_LINE;
-            } while (empty);
-            // Return the last token, as it was not empty
-            lexer_.ungetToken();
-
-            const MasterToken::StringRegion
-                name_string(lexer_.getNextToken(MasterToken::QSTRING).
-                            getStringRegion());
-            // TODO $ handling
-            const Name name(name_string.beg, name_string.len, &zone_origin_);
-            // TODO: Some more flexibility. We don't allow omitting anything yet
-
-            // The parameters
-            const RRTTL ttl(getString());
-            const RRClass rrclass(getString());
-            const RRType rrtype(getString());
-
-            const rdata::RdataPtr data(rdata::createRdata(rrtype, rrclass,
-                                                          lexer_,
-                                                          &zone_origin_,
-                                                          options_,
-                                                          callbacks_));
-            // In case we get NULL, it means there was error creating
-            // the Rdata. The errors should have been reported by
-            // callbacks_ already, so we just need to not report the RR
-            if (data != rdata::RdataPtr()) {
-                add_callback_(name, rrclass, rrtype, ttl, data);
-
-                // Good, we loaded another one
-                ++count;
-            };
+            }
         }
         // When there was a fatal error and ok is false, we say we are done.
         return (!ok_);

+ 2 - 2
src/lib/dns/tests/master_loader_unittest.cc

@@ -79,8 +79,8 @@ public:
         ofstream out(filename.c_str(),
                      std::ios_base::out | std::ios_base::trunc);
         ASSERT_FALSE(out.fail());
-        out << "example.org. 3600 IN SOA ns1.example.org.filename "
-            "admin.example.org.filename 1234 3600 1800 2419200 7200" << endl;
+        out << "example.org. 3600 IN SOA ns1.example.org. "
+            "admin.example.org. 1234 3600 1800 2419200 7200" << endl;
         out << line << endl;
         out << "correct 3600    IN  A 192.0.2.2" << endl;
         out.close();