BIND 10 trac1175_reapplied, updated. 054699635affd9c9ecbe7a108d880829f3ba229e [1175] remove the retrying part because there is no clear necessity

BIND 10 source code commits bind10-changes at lists.isc.org
Mon Oct 3 05:05:43 UTC 2011


The branch, trac1175_reapplied has been updated
  discards  1006a9620414db12103f799466dde10b86fcbee6 (commit)
  discards  b55e98a16cf7fd9db8af871b770b48f9c9146e05 (commit)
  discards  8fd664266678c3f10df02e229a55b428d7f0481a (commit)
  discards  5c334f5ca17c52d988db1e4d6f47d2b76a84be4a (commit)
  discards  010e6976f7961150586356ba9bb9e56b58ebf25f (commit)
  discards  86105ab0a1029a76ecf5a948d86efcfc87123cab (commit)
  discards  b9bb528ab2141a8325877a1489dbb5928d58d404 (commit)
  discards  30659570e5ccbc8b0ab29e5d2139f4b6c54e55fb (commit)
  discards  bc376ed5f17acd7b203ba36b2634363a3c9a12a1 (commit)
  discards  4c1c53b06a3b1d3b3b40698fd1cdc1aa3e356394 (commit)
  discards  0a0e98ffd310e33a1aa1bf353b09b2502f64d9be (commit)
  discards  a48b3723667b0b87dbc70d4c7ee0b148331fd325 (commit)
  discards  b2b0cc8260ae79e5406f0f206e805c85d88f0429 (commit)
  discards  7ebb37173dfec48ea13d513c6020a73183a6764d (commit)
  discards  885b69af7cabbfdff8e22255b9deb1705201da57 (commit)
  discards  d6202285d5481b424eae9169aae0fa39cc34b271 (commit)
  discards  5a90a358b959edabf0c471bd84bac3255ca13596 (commit)
  discards  8e38c3cabdfd0d154678aa71712a52e08c516a2a (commit)
  discards  b1168693dcdf910866fea348599d569b5ee33494 (commit)
  discards  56552bfe686c314a9a1a812e84b92aab6fdfb651 (commit)
  discards  2b78536997d1d17168d622f6a777cfdcd24882eb (commit)
  discards  c72634c3bc4502890a57b7babbf534e9fe01eeaa (commit)
  discards  c6370d65b8e2aad10be895cdba5677f6245f3144 (commit)
  discards  adcc32e8f559f7525d709d801695bec1845065e6 (commit)
  discards  925e80e912191ce4bccf52d90ccaf4e665eb57e8 (commit)
  discards  e6f9a14f57eb5f2dd1e2e622fa139ac7a6488d2d (commit)
  discards  0d943ba9d25211863c437ea1dd0d69d2bdde0067 (commit)
  discards  34af1d005f42009c31186c2dd6001a29c9773606 (commit)
  discards  47734cf9b10886fc8f49c3fe6e10ad3f24256d77 (commit)
  discards  093ef97943821e0423f060ae485b8bb798b351e6 (commit)
  discards  15623cb6fc32e4d303668c480c8eec5871dd2194 (commit)
  discards  45cab58eefc4c02a65803b08f1ded1e63f4b2c68 (commit)
  discards  f9866a02cc7e3659d1b370ea6c9f5adc90560ba4 (commit)
  discards  16563433095c036dba4e2814838083a7ef89f752 (commit)
  discards  3cb838d07ed1bc285eeb255c36b32c8a76e35ffd (commit)
  discards  09d2b481e400a0fe519bd1227b0d7d29458c378f (commit)
  discards  08a3aa577ce47de0594264c267a38bceaf302061 (commit)
  discards  f00403387266c310a2ea3618a1d4e336e75faae1 (commit)
  discards  546a7e4e387c85cfcf23dc476db3fb2244b84857 (commit)
  discards  b2bac38d34242c760b0d396f943ffeda985fb640 (commit)
  discards  7fbe2a7eadcae6a8c4fbdb54de0786568de69122 (commit)
  discards  5aa4e96ef4f1c0a1f927924ab8ec1e1ff77d1794 (commit)
  discards  85cb5c5974c80333dd5c380a218cccc99a9d1947 (commit)
  discards  b44392cdab8494212e2acdcf40de33e08e4b3698 (commit)
  discards  66d82fe96595d4331b4ec61c07f350ba0d0dd93b (commit)
  discards  fe88e2b2d304fdc831b11c19aa85889318f15900 (commit)
  discards  e8149ae19a25ec711945b7be484a154ebd5d592b (commit)
  discards  9d43ec08b73fddba0a020c177c6ddba710719bc3 (commit)
  discards  369761f549bbac00a287339e45f1e777841b940c (commit)
  discards  d4536cbb5a10bebf7310c5e1d06f7d6627311617 (commit)
  discards  35fc22c9f60021360335f52d412eed636df35657 (commit)
  discards  97ed7e897f72492b911a571728c751d741d8c32c (commit)
  discards  ca774237066b3ed998a5beb6d91d960758adf09a (commit)
  discards  b82b2af6cbf716aae330c2a376cf21dc7a1805f4 (commit)
  discards  bf4803b911a837b4bfd568aef94ffd17cdf5ca25 (commit)
  discards  06dbb588f199cad98d7feabfc63d14cffa58ebfc (commit)
  discards  6e3a3487b30699507e12554b15e9f052fe04c0c5 (commit)
  discards  4e9a7ed9bcb7b2ce8b6d2983e814f4b9d5fd87b2 (commit)
  discards  216d579298b7ac073c9cb9ed3757c602e3c251e8 (commit)
  discards  e444604425665d42676728303c6e78e872682253 (commit)
  discards  b7155e7e969e97806ea9416abb7fe20a54c16e6c (commit)
  discards  8ceafbdf99824fc917ecd573f7ba529c0a898c32 (commit)
  discards  3bddd9a844a7d89972b7f71b0015bda896633367 (commit)
  discards  d1bfd53b673217da422975b3dc14c38f89094765 (commit)
  discards  4f8206ab0d632e993add8f29b90a515e213eda24 (commit)
  discards  03b79269e8d7d578587446c202c387413c47ffc8 (commit)
  discards  11c3c832347d09cd943970a1ddb72e6c2ac17fd9 (commit)
  discards  2dd40646cbf85f43a30cab21fab21759093f3d12 (commit)
  discards  2c72dc23bf3265aaab349471781a384b24873024 (commit)
  discards  2b148e41bc504de9df06b9cde7777f7113ea5978 (commit)
       via  054699635affd9c9ecbe7a108d880829f3ba229e (commit)
       via  d04acfb82c3425a638f09d2f49208ef86bc7a6b3 (commit)
       via  434f4fd17dd3dee1d17e7b2e008f1ab1416d5799 (commit)
       via  ce8b5fe9567f06f7acba34b9e9b35ad471e2ab67 (commit)
       via  34ead9dfeff5f64af36a209cae28075fcbbb3330 (commit)
       via  fcfe5af9c22c5b666e5ecf646bbe0d9da7b655e9 (commit)
       via  1f967a8ffe37f6732dd628d28a13abc442541c38 (commit)
       via  3efca5f9b7b7bfeac53044fdd44e5add61397157 (commit)
       via  a35b62699480e149f22f4e039935bfcf41f97ac2 (commit)
       via  9dedc72e89b9ca8ba2c5f3bc562ad9ccd1aa05b0 (commit)
       via  7808524aa9bbb424327ac67d7408647cb18840f5 (commit)
       via  5b866ef26bd5ae980bb86c494a592ef232552b68 (commit)
       via  a5387c15e93c6d1925bf4ad0eacdcfd63790c32a (commit)
       via  d56c782197242e32ccdd23c9e3652ff520f3d58f (commit)
       via  bd8cb42b61666342ee8bc6c33aed2a168301ff67 (commit)
       via  9accf90bb081b057023479f0a86e54017b02cdd3 (commit)
       via  9eafb04ee8dbd47022dd9a5e5c1310f88f398d2c (commit)
       via  7af1aeddc36a1ac1343f1af12aa29164f1028f03 (commit)
       via  15f5d7895a2744376062229cf19593016a773cde (commit)
       via  ddec42c7a23cca11903ece8f7ab614dcc7e5edd3 (commit)
       via  d8cac904c7aea4a652a47afb35aceb6ca4808ce8 (commit)
       via  433381e5ca62418fc90377d16f1805260b27b619 (commit)
       via  c8bbdd1d74ac313d8b57d8debe4f7b75490e5df2 (commit)
       via  e57c5196d3e8dd56b0190799c98b56a5be55333a (commit)
       via  06f7bc4b3b69e8fda96f6e626a7dac5b1fbbb233 (commit)
       via  0aa4c14ebd1eb0a68c2bcf5c617325596657ea71 (commit)
       via  9daa2f686b3bdb03b13e9becf45a722344888cf3 (commit)
       via  f159ac66aa577889514dc170c87a92c49be5a6cc (commit)
       via  d6b86a88c7a486f2e5b742fc60d374e48382320e (commit)
       via  5ddc441f77a34158039f0328c3ab7c2106b7b3b8 (commit)
       via  290e89c515e051dad269f1acbce0b52a541d9c8c (commit)
       via  9b8925a4d0ecbd8a09d307dfd56fa15fb8eedcc6 (commit)
       via  53314ecb63f3f0f85629b66a228207658d8fd73f (commit)
       via  863509e2dc3bf96fd38476d787abb62e0da46624 (commit)
       via  fe1d6665faf06b3fcc0aaf8ec72905aa4b7ce1f7 (commit)
       via  7581a21a7dce1dc6b92ad24293b4269a3531e6d4 (commit)
       via  1fd37ae8a4bb25a6e85ffb2158b2ae95fe8cbd04 (commit)
       via  8ed3b760c179df435882f2ad96b6dcfad5b6e9fa (commit)
       via  3516ab551851273faeeb0b8696695e5f3ffc88f9 (commit)
       via  9f8ddd6ee1b73c9403f85b6ef5c85605ca393aa7 (commit)
       via  898485cd30084d478e8be688151cd11fb4d492a7 (commit)
       via  30f4856101bf23ce155ef0f2ebd1ca6f034d2420 (commit)
       via  eb4be17ddf3b26c379e3f100cf8e8b0fd4329537 (commit)
       via  ac06a06d1df9a1cc905b224b79921b0d0ade4c05 (commit)
       via  611d0300fb8bb2e87d787023cb5c6030ee07d8d2 (commit)
       via  fdf02d580f2bb1fbc6fa85ee0edd81a07404d1de (commit)
       via  a0bb482b46bd05f8c8774bacdd26dc891cb3bef7 (commit)
       via  cebd7e3562312ade50d972af49239cee7f10d057 (commit)
       via  8750dc3ab772e29d7374d779cefb3c8b8c61d2d1 (commit)
       via  b743e6ba98c8cbb53c45e1c0f59e5a78ba62f5d4 (commit)
       via  6556a2ffdd7bdb5370c2f1b3d8c9e8799ef82140 (commit)
       via  3e9189a483c0f53eba4f05092c90f7955123f52c (commit)
       via  7f5702a379516cee041129c03dd37d67f26d49c1 (commit)
       via  e60ecc91ad65087c3cff3af479cc455abccbe020 (commit)
       via  62bd7736311e166aea3604b8e486b58c1315f82f (commit)
       via  9687077033661cf07b6ea2e966299e837a501612 (commit)
       via  703d5f36d0102993f311d21e662a28492d8cf7b4 (commit)
       via  84d9095c66c765cf78814323597b2e3bbef293d5 (commit)
       via  e54bc83c4e8a66fd9ab1ae9f27899d70ef82a066 (commit)
       via  1a8c86ea2503bffe6dc1f2300dfc2b4efba108cc (commit)
       via  ed5311a26b7b1368f28191c405ec13da907213ae (commit)
       via  493a6449b37b34ac5fe36257b266c229e34d105c (commit)
       via  6f6a4cf9d98f2b4550e0949da1e20a7f38440610 (commit)
       via  36a53f41a7da580926111dca65652d6389fcd909 (commit)
       via  61681dac2023240a4a029072add3a39809ccb7f0 (commit)
       via  96dd4d2daf1fb91672a798fa478da0ec8a7ac737 (commit)
       via  9354737244e0bb7c22ec684ed652c89991eca913 (commit)
       via  9bbc77b6b8381c9a6d831e490a7715ba84b9356f (commit)
       via  8023760a5fc6f346cf82340aa50df755b0d0d00a (commit)
       via  cc0d6e4674fd2e6ebe3775a28ec87fc5c869f924 (commit)
       via  f9cb0d187f02078b27a0119ce42c83f62461a507 (commit)
       via  4cde36d2b97a24f03c192a61248545d0180fb856 (commit)
       via  c874cb056e2a5e656165f3c160e1b34ccfe8b302 (commit)
       via  12fd115d2e1ea8b55f43313ac665c32e07f9498e (commit)
       via  84ada921a2fe98489b578b6d780c1ad2e6c31482 (commit)
       via  bb7833f2054edca11a32d24d17486f153db00ec1 (commit)
       via  c430e464860b4460a0ab32454e53918a1cc7444b (commit)
       via  39e529c506a4350cd676bf5ddff6d61686e8814f (commit)
       via  aba10a01b765b472d57112fd4e09a6fb47b49fa7 (commit)
       via  9688dee697e9ad279c6542bf164b820e907e526f (commit)
       via  c1a72c46b572eee2d94ab53a5589c724fcb1fcf1 (commit)
       via  9016513b4d19d2781d0b6f2575b490431e04ec79 (commit)
       via  13e8bc43e4888fe9e6df7e536ea0b439c6351199 (commit)
       via  e89895b7e5f3b7074271c89de281e426c53be347 (commit)
       via  938f4e9ba14954551fbc390abb7d1e06d38189c2 (commit)
       via  b0b0da67c915f3c02020397b8dcf6a078a9b3a90 (commit)
       via  1ee8ad4a2b092a6edc35c111c5a3b5b761da0dae (commit)
       via  c943619d223be1158ae8db5223f655343d06785f (commit)
       via  0d874a95d3c782b9c663c64be619f449956df457 (commit)
       via  2d325650009f46a1f16ef2e7c1f4ed0827db236f (commit)

This update added new revisions after undoing existing revisions.  That is
to say, the old revision is not a strict subset of the new revision.  This
situation occurs when you --force push a change and generate a repository
containing something like this:

 * -- * -- B -- O -- O -- O (1006a9620414db12103f799466dde10b86fcbee6)
            \
             N -- N -- N (054699635affd9c9ecbe7a108d880829f3ba229e)

When this happens we assume that you've already had alert emails for all
of the O revisions, and so we here report only the revisions in the N
branch from the common base, B.

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 054699635affd9c9ecbe7a108d880829f3ba229e
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Wed Sep 28 13:53:21 2011 +0900

    [1175] remove the retrying part because there is no clear necessity

commit d04acfb82c3425a638f09d2f49208ef86bc7a6b3
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Wed Sep 28 13:45:49 2011 +0900

    [1175] comment the reason why socket.has_ipv6 is not used

commit 434f4fd17dd3dee1d17e7b2e008f1ab1416d5799
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Mon Sep 26 22:13:09 2011 +0900

    [1175] correct the comment according to the purpose of the retry

commit ce8b5fe9567f06f7acba34b9e9b35ad471e2ab67
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Mon Sep 26 22:12:48 2011 +0900

    [1175] correct the names and comments of the functions according to their
    purposes

commit 34ead9dfeff5f64af36a209cae28075fcbbb3330
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Mon Sep 26 18:35:22 2011 +0900

    [1175] remove the two conditions because they do the same tests for IPv4
    whether IPv6 is enabled or not

commit fcfe5af9c22c5b666e5ecf646bbe0d9da7b655e9
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Mon Sep 26 18:04:13 2011 +0900

    [1175] modify b10-stats_test.py, b10-stats-httpd_test.py and test_utils.py
    
     - exclude the setup of handler in SIGALRM and add it as an external
       function in the SignalHandler class in test_utils.py
    
     - define the function in that class to reset the handler in
       test_utils.py, and add it in tearDown() in each testcase

commit 1f967a8ffe37f6732dd628d28a13abc442541c38
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Mon Sep 26 15:46:30 2011 +0900

    [1175] fix double hash signs

commit 3efca5f9b7b7bfeac53044fdd44e5add61397157
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Mon Sep 26 22:24:35 2011 +0900

    [1175] correct the comment of the function according to its purpose

commit a35b62699480e149f22f4e039935bfcf41f97ac2
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Tue Sep 13 18:22:23 2011 +0900

    [1175] correct the logging id

commit 9dedc72e89b9ca8ba2c5f3bc562ad9ccd1aa05b0
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Tue Sep 13 18:21:55 2011 +0900

    [1175] add the package name for SessionError

commit 7808524aa9bbb424327ac67d7408647cb18840f5
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Tue Sep 13 17:53:22 2011 +0900

    [1175] modify test_utils.py
    
     - explicitly shut down the socket of the msgq before shutting down
       the msgq
    
     - do nothing in the shutdown method of MockMsgq for avoiding shutting
       down the msgq twice
    
     - replace the stop method in the shutdown method of the MyStatsHttpd
       with the shutdown command of stats_httpd

commit 5b866ef26bd5ae980bb86c494a592ef232552b68
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Thu Sep 8 10:52:19 2011 +0900

    [1175] modify test_utils.py
    
      - move up an assignment of the BIND10_MSGQ_SOCKET_FILE environment
        variable (BaseModules uses a constant file name during each
        testcase)
    
      - BaseModules checks whether msgq is ready after it started the msgq
        object. A SessionTimeout is raised here if not.

commit a5387c15e93c6d1925bf4ad0eacdcfd63790c32a
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Tue Sep 6 20:27:44 2011 +0900

    [1175] fix a typo

commit d56c782197242e32ccdd23c9e3652ff520f3d58f
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Tue Sep 6 20:17:57 2011 +0900

    [1175] modify b10-stats-httpd_test.py
    
     - The function get_availaddr uses socket.getaddrinfo for getting the
       address family.
    
     - The function is_ipv6_enabled uses 3 random ports for checking
       whether IPv6 is enabled.

commit bd8cb42b61666342ee8bc6c33aed2a168301ff67
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Tue Sep 6 11:42:42 2011 +0900

    [1175] send the command 'status' to the stats when it started, and
    then send the command 'shutdown', and also check each value returned
    by each invoked command

commit 9accf90bb081b057023479f0a86e54017b02cdd3
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Mon Sep 5 17:14:11 2011 +0900

    [1175] modify stats_httpd.py.in, b10-stats-httpd_test.py and
    b10-stats_test.py
    
     - The stats httpd doesn't need to return an argument when it's
       shutting down.
    
     - The testcase sends the 'status' command or the 'shutdown' command
       to the stats or the stats httpd when they started, and then their
       returned values are checked.

commit 9eafb04ee8dbd47022dd9a5e5c1310f88f398d2c
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Mon Sep 5 05:01:18 2011 +0000

    [1175] modify test_utils.py
    
     - add 3-time retry to creating the server object when it fails in the
       ThreadingServerManager class
    
     - suppress outputs by Msgq, and add dummy sys module and the output
       methods
    
     - pass Exceptions raised while it's running with a thread

commit 7af1aeddc36a1ac1343f1af12aa29164f1028f03
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Mon Sep 5 04:53:24 2011 +0000

    [1175] remove a logging name from unittest

commit 15f5d7895a2744376062229cf19593016a773cde
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Mon Sep 5 04:53:11 2011 +0000

    [1175] modify b10-stats-httpd_test.py
    
      - remove a logging name from unittest
    
      - do stats_httpd.stop() in teadDown() instead of each test case
    
      - send 'shutdown' command to kill stats_httpd when testing address
        already in use

commit ddec42c7a23cca11903ece8f7ab614dcc7e5edd3
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Mon Sep 5 04:46:08 2011 +0000

    [1175] remove -v option from pycoverage

commit d8cac904c7aea4a652a47afb35aceb6ca4808ce8
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Thu Sep 1 11:34:28 2011 +0000

    [1175] add -v option in pycoverage for debugging the failure in
    buildbot. (unittest.main() with verbosity option is not supported
    in Python3.1.)

commit 433381e5ca62418fc90377d16f1805260b27b619
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Thu Sep 1 04:19:53 2011 +0000

    [1175] modify b10-stats-httpd_test.py, b10-stats_test.py and
    test_utils.py
    
     - more strictly close the io object whether it's successfully opened
       or not
    
     - add verbosity=2 in unittest.main for debugging the failure in the
       buildbot
    
     - don't redict sys.stderr in MockMsgq
    
     - rename the function name to create_specfile
    
     - switch the verbose in Msgq into True

commit c8bbdd1d74ac313d8b57d8debe4f7b75490e5df2
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Aug 26 12:01:47 2011 +0900

    [1175] fix wrong list-type handling in the function
    get_spec_defaults and add more tests into test_get_spec_defaults

commit e57c5196d3e8dd56b0190799c98b56a5be55333a
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Wed Aug 24 17:28:29 2011 +0900

    [1175] fix typo and correct changes from trac519

commit 06f7bc4b3b69e8fda96f6e626a7dac5b1fbbb233
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Wed Aug 24 16:51:11 2011 +0900

    [1175] deadlock will be killed afer 20 secs

commit 0aa4c14ebd1eb0a68c2bcf5c617325596657ea71
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Wed Aug 24 15:55:21 2011 +0900

    [1175] fix conflicts with trac519

commit 9daa2f686b3bdb03b13e9becf45a722344888cf3
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Tue Aug 23 16:42:18 2011 +0900

    [1175] modify stats_httpd.py.in and b10-stats-httpd_test.py
    
     - A hostname (canonical name of host) is not acceptable in listen_on
       configuration.
    
     - A default port number(starting number for search) is added in args
       of the function get_availaddr.

commit f159ac66aa577889514dc170c87a92c49be5a6cc
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Tue Aug 23 11:22:03 2011 +0900

    [1175] set msgq verbose off

commit d6b86a88c7a486f2e5b742fc60d374e48382320e
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Mon Aug 22 18:20:39 2011 +0900

    [1175] add #1175

commit 5ddc441f77a34158039f0328c3ab7c2106b7b3b8
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Mon Aug 22 18:18:47 2011 +0900

    [1175] modify test_utils.py
    
     - don't use time.sleep for waiting threads are starting or finishing
    
     - correct shutting down of mock modules
    
     - use _started (threading.Event) where command_handler is invoked
    
     - add implementation to changing contents of specfile of MyStatsHttpd
    
     - set "BIND10_MSGQ_SOCKET_FILE" only when it's not set yet

commit 290e89c515e051dad269f1acbce0b52a541d9c8c
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Mon Aug 22 18:10:25 2011 +0900

    [1175] modify b10-stats-httpd_test.py and b10-stats_test.py
    
     - add function get_availaddr to get available address and port on the
       platform
    
     - add function is_ipv6enabled to check ipv6 enabled on the platform
    
     - add miscellaneous changes to refactor unittest

commit 9b8925a4d0ecbd8a09d307dfd56fa15fb8eedcc6
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Mon Aug 22 18:05:57 2011 +0900

    [1175] modify stats_httpd.py.in
    
     - don't use DEFAULT_CONFIG
    
     - move up mccs.start and open_httpd to __init__(). It takes time to
       do these functions, and an extra sleep is needed in unittests.
    
     - set running to False in http stopping
    
     - use validate_config in module_spec class
    
     - don't close/open http before it's opened

commit 53314ecb63f3f0f85629b66a228207658d8fd73f
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Aug 5 16:24:03 2011 +0900

    [trac930] modify b10-stats-httpd_test.py and b10-stats_test.py
    
     - revise header comments in each test script
    
     - replace some hard-coded time strings with the constants defined in
       the setUp function
    
     - merged several checks about B10_FROM_SOURCE into the TestOSEnv
       class

commit 863509e2dc3bf96fd38476d787abb62e0da46624
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Aug 5 14:48:27 2011 +0900

    [trac930] modify b10-stats-httpd_test.py, b10-stats_test.py and
    test_utils.py
    
     - change address for test to 127.0.0.1 due to platform 127.0.0.2
       can't be assigned
    
     - remove unnecessary thread.Event.wait()
    
     - add thread.Event.clear() after thread.Event.wait()

commit fe1d6665faf06b3fcc0aaf8ec72905aa4b7ce1f7
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Wed Aug 3 11:41:05 2011 +0900

    [trac930] refactor unittests
    
     - remove time.sleep from various unittests and add in the "run"
       method in ThreadingServerManager
    
     - adjust the sleep time (TIMEOUT_SEC)
    
     - join some small unittests
       (test_start_with_err, test_command_status, test_command_shutdown)

commit 7581a21a7dce1dc6b92ad24293b4269a3531e6d4
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Tue Aug 2 22:00:11 2011 +0900

    [trac930] add comments about abstracts of the test scripts in their
    headers

commit 1fd37ae8a4bb25a6e85ffb2158b2ae95fe8cbd04
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Tue Aug 2 21:44:07 2011 +0900

    [trac930] modify stats.py
    
     - add more documentations into update_modules, get_statistics_data
       and update_statistics_data methods
    
     - modify two methods: "update_modules" and "get_statistics_data"
       methods raise StatsError instead of just returning None, when
       communication between stats module and config manager is failed or
       when it can't find specified statistics data.
    
     - also modify the unittest depending on the changes of these
       behaviors.

commit 8ed3b760c179df435882f2ad96b6dcfad5b6e9fa
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Tue Aug 2 20:17:28 2011 +0900

    [trac930] modify b10-stats_test.py
    
     - set the constant variables in the setUp method in the TestUtilties
       class, and compare values returned from the functions with these
       constants in testing methods.
    
     - remove the tearDown method which has no test case in the
       TestCallback class

commit 3516ab551851273faeeb0b8696695e5f3ffc88f9
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Tue Aug 2 19:57:58 2011 +0900

    [trac930] remove tailing whitespaces.

commit 9f8ddd6ee1b73c9403f85b6ef5c85605ca393aa7
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Mon Aug 1 18:38:35 2011 +0900

    [trac930] raise StatsError including errors in the stats spec file

commit 898485cd30084d478e8be688151cd11fb4d492a7
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Mon Aug 1 18:21:23 2011 +0900

    [trac930] rename the function name
    
     - rename the name of 'parse_spec' to 'get_spec_defaults' in the
       result of consideration of what it is doing
    
     - modify the description of the function as docstring
    
     - fix unitttests for the stats module depending on the function name

commit 30f4856101bf23ce155ef0f2ebd1ca6f034d2420
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Jul 29 22:11:38 2011 +0900

    [trac930] remove a unnecessary x bit from stats_httpd.py.in

commit eb4be17ddf3b26c379e3f100cf8e8b0fd4329537
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Thu Jul 28 22:07:15 2011 +0900

    [trac930] modify logging add loggings and new messages for logging
    remove unused messages from the message file add test logging names
    into unittest scripts

commit ac06a06d1df9a1cc905b224b79921b0d0ade4c05
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Wed Jul 27 20:45:18 2011 +0900

    [trac930] modify the update_modues function There is no part of
    statistics category in the spec file of a module which has no
    statistics data.

commit 611d0300fb8bb2e87d787023cb5c6030ee07d8d2
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Wed Jul 27 16:49:21 2011 +0900

    [trac930] modify stats.py and b10-stats_test.py
    
     - correct error messages in bindctl it prints together with
       arguments.
    
     - modify the command_show function it reports statistics data of the
       module even if name is not specified.
    
     - add/modify unittests depending on the changes of error messages

commit fdf02d580f2bb1fbc6fa85ee0edd81a07404d1de
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Wed Jul 27 16:42:54 2011 +0900

    [trac930] remove unnecessary a white space

commit a0bb482b46bd05f8c8774bacdd26dc891cb3bef7
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Wed Jul 27 10:18:07 2011 +0900

    [trac930] add a test pattern which the set command with a
    non-existent item name is sent

commit cebd7e3562312ade50d972af49239cee7f10d057
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Wed Jul 27 10:14:57 2011 +0900

    [trac930] modify parse_spec function returns empty dict if list-type
    is not specified in the argument

commit 8750dc3ab772e29d7374d779cefb3c8b8c61d2d1
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Jul 22 21:40:07 2011 +0900

    [trac930] fix conflicts with trac1021

commit b743e6ba98c8cbb53c45e1c0f59e5a78ba62f5d4
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Jul 22 18:50:41 2011 +0900

    [trac930] add changes because query counter names described in the
    specfile are changed.

commit 6556a2ffdd7bdb5370c2f1b3d8c9e8799ef82140
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Jul 22 18:45:19 2011 +0900

    [trac930] add the logging when the validation of statistics data
    fails

commit 3e9189a483c0f53eba4f05092c90f7955123f52c
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Jul 22 18:43:26 2011 +0900

    [trac930] Add unittests to test sumitStatistics with the validation
    of statistics data and add mock ModuleSpec class

commit 7f5702a379516cee041129c03dd37d67f26d49c1
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Jul 22 18:41:34 2011 +0900

    [trac930] Add prototypes of validator_typea and
    registerStatisticsValidator
    
      - validator_type -- a type of statistics validation function
    
      - registerStatisticsValidator -- the function to register the
        validation function

commit e60ecc91ad65087c3cff3af479cc455abccbe020
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Jul 22 18:37:22 2011 +0900

    [trac930] modify statistics.cc
    
     - Add implementation to validate statistics data
       -- When validation is success, it sends data to statistics
       module. But when it fails, it doesn't send and logs the message.
    
     - Add the function to register the validation function into the class

commit 62bd7736311e166aea3604b8e486b58c1315f82f
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Jul 22 18:32:22 2011 +0900

    [trac930] add the helper functions which are used around the
    registration of the function to validate the statistics data.

commit 9687077033661cf07b6ea2e966299e837a501612
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Jul 22 18:28:40 2011 +0900

    [trac930] add new messages into the message file of Auth and Boss
    when validation of statistics data to send to statistics module is
    failed.

commit 703d5f36d0102993f311d21e662a28492d8cf7b4
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Wed Jul 20 10:00:29 2011 +0900

    [trac930] add statistics validation for bob

commit 84d9095c66c765cf78814323597b2e3bbef293d5
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Wed Jul 13 20:25:54 2011 +0900

    [trac930] modify b10-stats-httpd_test.py
    
     - increase seconds in sleep time which is before HTTP client connects
       to the server
    
     - delete 'test_log_message' because of the deletion of original
       function

commit e54bc83c4e8a66fd9ab1ae9f27899d70ef82a066
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Jul 8 21:22:34 2011 +0900

    [trac930] remove unneeded empty TODO comments

commit 1a8c86ea2503bffe6dc1f2300dfc2b4efba108cc
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Jul 8 20:08:22 2011 +0900

    [trac930] refurbish the unittests for new stats module, new stats
    httpd module and new mockups and utilities in test_utils.py

commit ed5311a26b7b1368f28191c405ec13da907213ae
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Jul 8 19:56:24 2011 +0900

    [trac930] modify Stats
    
     - remove unneeded subject and listener classes
    
     - add StatsError for handling errors in Stats
    
     - add some new methods (update_modules, update_statistics_data and
       get_statistics_data)
    
     - modify implementations of existent commands(show and set) according changes
       stats.spec
    
     - remove reset and remove command because stats module couldn't manage other
       modules' statistics data schema
    
     - add implementation of strict validation of each statistics data
       (If the validation is failed, it puts out the error.)
    
     - stats module shows its PID when status command invoked
    
     - add new command showschema invokable via bindctl
    
     - set command requires arguments of owner module name and statistics item name
    
     - show and showschema commands accepts arguments of owner module name and
       statistics item name
    
     - exits at exit code 1 if got runtime errors
    
     - has boot time in _BASETIME

commit 493a6449b37b34ac5fe36257b266c229e34d105c
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Jul 8 19:40:15 2011 +0900

    [trac930] modify stats_httpd.py.in
    
     - remove "stats-schema.spec" setting and getting statistics data
       schema via this spec file
    
     - add "version" item in DEFAULT_CONFIG
    
     - get the address family by socket.getaddrinfo function with specified
       server_address in advance, and create HttpServer object once, in stead of
       creating double HttpServer objects for IPv6 and IPv4 in the prior code
       (It is aimed for avoiding to fail to close the once opened sockets.)
    
     - open HTTP port in start method
    
     - avoid calling config_handler recursively in the except statement
    
     - create XML, XSD, XSL documents after getting statistics data and schema from
       remote stats module via CC session
    
     - definitely close once opened template file object

commit 6f6a4cf9d98f2b4550e0949da1e20a7f38440610
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Jul 8 16:33:59 2011 +0900

    [trac930] update spec file of stats module
    
     - update description of status command, shutdown command and show
       command
    
     - change argument of show command (Owner module name of statistics
       data can be specified)
    
     - change argument of set command (Owner module name of statistics
       data is always required)
    
     - add showschema command which shows statistics data schema of each
       module specified)
    
     - disabled reset command and remove command

commit 36a53f41a7da580926111dca65652d6389fcd909
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Jul 8 16:21:49 2011 +0900

    [trac930] update argument name and argument format of set command in
    auth module and boss module and also update related unittests of
    their modules

commit 61681dac2023240a4a029072add3a39809ccb7f0
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Jul 8 16:18:38 2011 +0900

    [trac930] remove description about removing statistics data by stats
    module update example format in bindctl when show command of stats
    module is invoked

commit 96dd4d2daf1fb91672a798fa478da0ec8a7ac737
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Jul 8 16:13:17 2011 +0900

    [trac930] add a column "Owner" in the table tag

commit 9354737244e0bb7c22ec684ed652c89991eca913
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Jul 8 16:12:09 2011 +0900

    [trac930] remove descriptions about "stats-schema.spec" and add
    description about new features because stats module can be
    requested to show statistics data schema.

commit 9bbc77b6b8381c9a6d831e490a7715ba84b9356f
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Jul 8 16:00:30 2011 +0900

    [trac930] add utilities and mock-up modules for unittests of
    statistics modules and change some environ variables (PYTHONPATH,
    CONFIG_TESTDATA_PATH) in Makefile
    
    test_utilies.py internally calls msgq, cfgmgr and some mock modules
    with threads for as real situation as possible.

commit 8023760a5fc6f346cf82340aa50df755b0d0d00a
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Jul 8 15:57:41 2011 +0900

    [trac930] remove unneeded mockups, fake modules and dummy data

commit cc0d6e4674fd2e6ebe3775a28ec87fc5c869f924
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Jul 8 15:55:55 2011 +0900

    [trac930] remove unneeded specfile "stats-schema.spec"

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog                                          |   10 ++-
 src/lib/dns/message.cc                             |   43 ++++---
 src/lib/dns/message.h                              |   55 +++++++-
 src/lib/dns/python/Makefile.am                     |    1 +
 src/lib/dns/python/message_python.cc               |   78 +++++++----
 src/lib/dns/python/message_python_inc.cc           |   41 ++++++
 src/lib/dns/python/pydnspp.cc                      |  139 ++++++++++++--------
 src/lib/dns/python/tests/message_python_test.py    |   52 +++++++-
 src/lib/dns/tests/message_unittest.cc              |  131 ++++++++++++++++++-
 src/lib/dns/tests/testdata/Makefile.am             |    6 +-
 src/lib/dns/tests/testdata/message_fromWire19.spec |   20 +++
 src/lib/dns/tests/testdata/message_fromWire20.spec |   20 +++
 src/lib/dns/tests/testdata/message_fromWire21.spec |   20 +++
 src/lib/dns/tests/testdata/message_fromWire22.spec |   14 ++
 src/lib/python/isc/datasrc/Makefile.am             |    5 +-
 src/lib/python/isc/datasrc/__init__.py             |   11 ++-
 src/lib/python/isc/log/log.cc                      |    2 +-
 17 files changed, 527 insertions(+), 121 deletions(-)
 create mode 100644 src/lib/dns/python/message_python_inc.cc
 create mode 100644 src/lib/dns/tests/testdata/message_fromWire19.spec
 create mode 100644 src/lib/dns/tests/testdata/message_fromWire20.spec
 create mode 100644 src/lib/dns/tests/testdata/message_fromWire21.spec
 create mode 100644 src/lib/dns/tests/testdata/message_fromWire22.spec

-----------------------------------------------------------------------
diff --git a/ChangeLog b/ChangeLog
index e629e3d..d99bcbe 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,10 +1,18 @@
-xxx.    [func]          naokikambe
+291.    [func]          naokikambe
 	Statistics items are specified by each module's spec file.
 	Stats module can read these through the config manager. Stats
 	module and stats httpd report statistics data and statistics
 	schema by each module via both bindctl and HTTP/XML.
 	(Trac #928,#929,#930,#1175, git TBD)
 
+290.	[func]		jinmei
+	libdns++/pydnspp: added an option parameter to the "from wire"
+	methods of the Message class.  One option is defined,
+	PRESERVE_ORDER, which specifies the parser to handle each RR
+	separately, preserving the order, and constructs RRsets in the
+	message sections so that each RRset contains only one RR.
+	(Trac #1258, git c874cb056e2a5e656165f3c160e1b34ccfe8b302)
+
 289.	[func]*		jinmei
 	b10-xfrout: ACLs for xfrout can now be configured per zone basis.
 	A per zone ACl is part of a more general zone configuration.  A
diff --git a/src/lib/dns/message.cc b/src/lib/dns/message.cc
index c5ba4e1..b3e9229 100644
--- a/src/lib/dns/message.cc
+++ b/src/lib/dns/message.cc
@@ -124,10 +124,12 @@ public:
     void setOpcode(const Opcode& opcode);
     void setRcode(const Rcode& rcode);
     int parseQuestion(InputBuffer& buffer);
-    int parseSection(const Message::Section section, InputBuffer& buffer);
+    int parseSection(const Message::Section section, InputBuffer& buffer,
+                     Message::ParseOptions options);
     void addRR(Message::Section section, const Name& name,
                const RRClass& rrclass, const RRType& rrtype,
-               const RRTTL& ttl, ConstRdataPtr rdata);
+               const RRTTL& ttl, ConstRdataPtr rdata,
+               Message::ParseOptions options);
     void addEDNS(Message::Section section, const Name& name,
                  const RRClass& rrclass, const RRType& rrtype,
                  const RRTTL& ttl, const Rdata& rdata);
@@ -614,7 +616,7 @@ Message::parseHeader(InputBuffer& buffer) {
 }
 
 void
-Message::fromWire(InputBuffer& buffer) {
+Message::fromWire(InputBuffer& buffer, ParseOptions options) {
     if (impl_->mode_ != Message::PARSE) {
         isc_throw(InvalidMessageOperation,
                   "Message parse attempted in non parse mode");
@@ -626,11 +628,11 @@ Message::fromWire(InputBuffer& buffer) {
 
     impl_->counts_[SECTION_QUESTION] = impl_->parseQuestion(buffer);
     impl_->counts_[SECTION_ANSWER] =
-        impl_->parseSection(SECTION_ANSWER, buffer);
+        impl_->parseSection(SECTION_ANSWER, buffer, options);
     impl_->counts_[SECTION_AUTHORITY] =
-        impl_->parseSection(SECTION_AUTHORITY, buffer);
+        impl_->parseSection(SECTION_AUTHORITY, buffer, options);
     impl_->counts_[SECTION_ADDITIONAL] =
-        impl_->parseSection(SECTION_ADDITIONAL, buffer);
+        impl_->parseSection(SECTION_ADDITIONAL, buffer, options);
 }
 
 int
@@ -706,7 +708,7 @@ struct MatchRR : public unary_function<RRsetPtr, bool> {
 // is hardcoded here.
 int
 MessageImpl::parseSection(const Message::Section section,
-                          InputBuffer& buffer)
+                          InputBuffer& buffer, Message::ParseOptions options)
 {
     assert(section < MessageImpl::NUM_SECTIONS);
 
@@ -738,7 +740,7 @@ MessageImpl::parseSection(const Message::Section section,
             addTSIG(section, count, buffer, start_position, name, rrclass, ttl,
                     *rdata);
         } else {
-            addRR(section, name, rrclass, rrtype, ttl, rdata);
+            addRR(section, name, rrclass, rrtype, ttl, rdata, options);
             ++added;
         }
     }
@@ -749,19 +751,22 @@ MessageImpl::parseSection(const Message::Section section,
 void
 MessageImpl::addRR(Message::Section section, const Name& name,
                    const RRClass& rrclass, const RRType& rrtype,
-                   const RRTTL& ttl, ConstRdataPtr rdata)
+                   const RRTTL& ttl, ConstRdataPtr rdata,
+                   Message::ParseOptions options)
 {
-    vector<RRsetPtr>::iterator it =
-        find_if(rrsets_[section].begin(), rrsets_[section].end(),
-                MatchRR(name, rrtype, rrclass));
-    if (it != rrsets_[section].end()) {
-        (*it)->setTTL(min((*it)->getTTL(), ttl));
-        (*it)->addRdata(rdata);
-    } else {
-        RRsetPtr rrset(new RRset(name, rrclass, rrtype, ttl));
-        rrset->addRdata(rdata);
-        rrsets_[section].push_back(rrset);
+    if ((options & Message::PRESERVE_ORDER) == 0) {
+        vector<RRsetPtr>::iterator it =
+            find_if(rrsets_[section].begin(), rrsets_[section].end(),
+                    MatchRR(name, rrtype, rrclass));
+        if (it != rrsets_[section].end()) {
+            (*it)->setTTL(min((*it)->getTTL(), ttl));
+            (*it)->addRdata(rdata);
+            return;
+        }
     }
+    RRsetPtr rrset(new RRset(name, rrclass, rrtype, ttl));
+    rrset->addRdata(rdata);
+    rrsets_[section].push_back(rrset);
 }
 
 void
diff --git a/src/lib/dns/message.h b/src/lib/dns/message.h
index 6a8bf9f..f286c67 100644
--- a/src/lib/dns/message.h
+++ b/src/lib/dns/message.h
@@ -581,11 +581,58 @@ public:
     /// message
     void toWire(AbstractMessageRenderer& renderer, TSIGContext& tsig_ctx);
 
+    /// Parse options.
+    ///
+    /// describe PRESERVE_ORDER: note doesn't affect EDNS or TSIG.
+    ///
+    /// The option values are used as a parameter for \c fromWire().
+    /// These are values of a bitmask type.  Bitwise operations can be
+    /// performed on these values to express compound options.
+    enum ParseOptions {
+        PARSE_DEFAULT = 0,       ///< The default options
+        PRESERVE_ORDER = 1       ///< Preserve RR order and don't combine them
+    };
+
     /// \brief Parse the header section of the \c Message.
     void parseHeader(isc::util::InputBuffer& buffer);
 
-    /// \brief Parse the \c Message.
-    void fromWire(isc::util::InputBuffer& buffer);
+    /// \brief (Re)build a \c Message object from wire-format data.
+    ///
+    /// This method parses the given wire format data to build a
+    /// complete Message object.  On success, the values of the header section
+    /// fields can be accessible via corresponding get methods, and the
+    /// question and following sections can be accessible via the
+    /// corresponding iterators.  If the message contains an EDNS or TSIG,
+    /// they can be accessible via \c getEDNS() and \c getTSIGRecord(),
+    /// respectively.
+    ///
+    /// This \c Message must be in the \c PARSE mode.
+    ///
+    /// This method performs strict validation on the given message based
+    /// on the DNS protocol specifications.  If the given message data is
+    /// invalid, this method throws an exception (see the exception list).
+    ///
+    /// By default, this method combines RRs of the same name, RR type and
+    /// RR class in a section into a single RRset, even if they are interleaved
+    /// with a different type of RR (though it would be a rare case in
+    /// practice).  If the \c PRESERVE_ORDER option is specified, it handles
+    /// each RR separately, in the appearing order, and converts it to a
+    /// separate RRset (so this RRset should contain exactly one Rdata).
+    /// This mode will be necessary when the higher level protocol is
+    /// ordering conscious.  For example, in AXFR and IXFR, the position of
+    /// the SOA RRs are crucial.
+    ///
+    /// \exception InvalidMessageOperation \c Message is in the RENDER mode
+    /// \exception DNSMessageFORMERR The given message data is syntactically
+    /// \exception MessageTooShort The given data is shorter than a valid
+    /// header section
+    /// \exception std::bad_alloc Memory allocation failure
+    /// \exception Others \c Name, \c Rdata, and \c EDNS classes can also throw
+    ///
+    /// \param buffer A input buffer object that stores the wire data
+    /// \param options Parse options
+    void fromWire(isc::util::InputBuffer& buffer, ParseOptions options
+        = PARSE_DEFAULT);
 
     ///
     /// \name Protocol constants
@@ -629,6 +676,6 @@ std::ostream& operator<<(std::ostream& os, const Message& message);
 }
 #endif  // __MESSAGE_H
 
-// Local Variables: 
+// Local Variables:
 // mode: c++
-// End: 
+// End:
diff --git a/src/lib/dns/python/Makefile.am b/src/lib/dns/python/Makefile.am
index 4452e40..3b89358 100644
--- a/src/lib/dns/python/Makefile.am
+++ b/src/lib/dns/python/Makefile.am
@@ -39,6 +39,7 @@ pydnspp_la_CXXFLAGS = $(AM_CXXFLAGS) $(PYTHON_CXXFLAGS)
 pydnspp_la_LDFLAGS = $(PYTHON_LDFLAGS)
 
 EXTRA_DIST = tsigerror_python_inc.cc
+EXTRA_DIST += message_python_inc.cc
 
 # Python prefers .so, while some OSes (specifically MacOS) use a different
 # suffix for dynamic objects.  -module is necessary to work this around.
diff --git a/src/lib/dns/python/message_python.cc b/src/lib/dns/python/message_python.cc
index b40ab45..6012153 100644
--- a/src/lib/dns/python/message_python.cc
+++ b/src/lib/dns/python/message_python.cc
@@ -39,6 +39,9 @@ using namespace isc::dns;
 using namespace isc::dns::python;
 using namespace isc::util;
 
+// Import pydoc text
+#include "message_python_inc.cc"
+
 namespace {
 class s_Message : public PyObject {
 public:
@@ -75,7 +78,7 @@ PyObject* Message_makeResponse(s_Message* self);
 PyObject* Message_toText(s_Message* self);
 PyObject* Message_str(PyObject* self);
 PyObject* Message_toWire(s_Message* self, PyObject* args);
-PyObject* Message_fromWire(s_Message* self, PyObject* args);
+PyObject* Message_fromWire(PyObject* const pyself, PyObject* args);
 
 // This list contains the actual set of functions we have in
 // python. Each entry has
@@ -157,14 +160,7 @@ PyMethodDef Message_methods[] = {
       "If the given message is not in RENDER mode, an "
       "InvalidMessageOperation is raised.\n"
        },
-    { "from_wire", reinterpret_cast<PyCFunction>(Message_fromWire), METH_VARARGS,
-      "Parses the given wire format to a Message object.\n"
-      "The first argument is a Message to parse the data into.\n"
-      "The second argument must implement the buffer interface.\n"
-      "If the given message is not in PARSE mode, an "
-      "InvalidMessageOperation is raised.\n"
-      "Raises MessageTooShort, DNSMessageFORMERR or DNSMessageBADVERS "
-      " if there is a problem parsing the message." },
+    { "from_wire", Message_fromWire, METH_VARARGS, Message_fromWire_doc },
     { NULL, NULL, 0, NULL }
 };
 
@@ -646,30 +642,54 @@ Message_toWire(s_Message* self, PyObject* args) {
 }
 
 PyObject*
-Message_fromWire(s_Message* self, PyObject* args) {
+Message_fromWire(PyObject* const pyself, PyObject* args) {
+    s_Message* self = static_cast<s_Message*>(pyself);
     const char* b;
     Py_ssize_t len;
-    if (!PyArg_ParseTuple(args, "y#", &b, &len)) {
-        return (NULL);
-    }
+    unsigned int options = Message::PARSE_DEFAULT;
+        
+    if (PyArg_ParseTuple(args, "y#", &b, &len) ||
+        PyArg_ParseTuple(args, "y#I", &b, &len, &options)) {
+        // We need to clear the error in case the first call to ParseTuple
+        // fails.
+        PyErr_Clear();
 
-    InputBuffer inbuf(b, len);
-    try {
-        self->cppobj->fromWire(inbuf);
-        Py_RETURN_NONE;
-    } catch (const InvalidMessageOperation& imo) {
-        PyErr_SetString(po_InvalidMessageOperation, imo.what());
-        return (NULL);
-    } catch (const DNSMessageFORMERR& dmfe) {
-        PyErr_SetString(po_DNSMessageFORMERR, dmfe.what());
-        return (NULL);
-    } catch (const DNSMessageBADVERS& dmfe) {
-        PyErr_SetString(po_DNSMessageBADVERS, dmfe.what());
-        return (NULL);
-    } catch (const MessageTooShort& mts) {
-        PyErr_SetString(po_MessageTooShort, mts.what());
-        return (NULL);
+        InputBuffer inbuf(b, len);
+        try {
+            self->cppobj->fromWire(
+                inbuf, static_cast<Message::ParseOptions>(options));
+            Py_RETURN_NONE;
+        } catch (const InvalidMessageOperation& imo) {
+            PyErr_SetString(po_InvalidMessageOperation, imo.what());
+            return (NULL);
+        } catch (const DNSMessageFORMERR& dmfe) {
+            PyErr_SetString(po_DNSMessageFORMERR, dmfe.what());
+            return (NULL);
+        } catch (const DNSMessageBADVERS& dmfe) {
+            PyErr_SetString(po_DNSMessageBADVERS, dmfe.what());
+            return (NULL);
+        } catch (const MessageTooShort& mts) {
+            PyErr_SetString(po_MessageTooShort, mts.what());
+            return (NULL);
+        } catch (const InvalidBufferPosition& ex) {
+            PyErr_SetString(po_DNSMessageFORMERR, ex.what());
+            return (NULL);
+        } catch (const exception& ex) {
+            const string ex_what =
+                "Error in Message.from_wire: " + string(ex.what());
+            PyErr_SetString(PyExc_RuntimeError, ex_what.c_str());
+            return (NULL);
+        } catch (...) {
+            PyErr_SetString(PyExc_RuntimeError,
+                            "Unexpected exception in Message.from_wire");
+            return (NULL);
+        }
     }
+
+    PyErr_SetString(PyExc_TypeError,
+                    "from_wire() arguments must be a byte object and "
+                    "(optional) parse options");
+    return (NULL);
 }
 
 } // end of unnamed namespace
diff --git a/src/lib/dns/python/message_python_inc.cc b/src/lib/dns/python/message_python_inc.cc
new file mode 100644
index 0000000..561c494
--- /dev/null
+++ b/src/lib/dns/python/message_python_inc.cc
@@ -0,0 +1,41 @@
+namespace {
+const char* const Message_fromWire_doc = "\
+from_wire(data, options=PARSE_DEFAULT)\n\
+\n\
+(Re)build a Message object from wire-format data.\n\
+\n\
+This method parses the given wire format data to build a complete\n\
+Message object. On success, the values of the header section fields\n\
+can be accessible via corresponding get methods, and the question and\n\
+following sections can be accessible via the corresponding iterators.\n\
+If the message contains an EDNS or TSIG, they can be accessible via\n\
+get_edns() and get_tsig_record(), respectively.\n\
+\n\
+This Message must be in the PARSE mode.\n\
+\n\
+This method performs strict validation on the given message based on\n\
+the DNS protocol specifications. If the given message data is invalid,\n\
+this method throws an exception (see the exception list).\n\
+\n\
+By default, this method combines RRs of the same name, RR type and RR\n\
+class in a section into a single RRset, even if they are interleaved\n\
+with a different type of RR (though it would be a rare case in\n\
+practice). If the PRESERVE_ORDER option is specified, it handles each\n\
+RR separately, in the appearing order, and converts it to a separate\n\
+RRset (so this RRset should contain exactly one Rdata). This mode will\n\
+be necessary when the higher level protocol is ordering conscious. For\n\
+example, in AXFR and IXFR, the position of the SOA RRs are crucial.\n\
+\n\
+Exceptions:\n\
+  InvalidMessageOperation Message is in the RENDER mode\n\
+  DNSMessageFORMERR The given message data is syntactically\n\
+  MessageTooShort The given data is shorter than a valid header\n\
+             section\n\
+  Others     Name, Rdata, and EDNS classes can also throw\n\
+\n\
+Parameters:\n\
+  data       A byte object of the wire data\n\
+  options    Parse options\n\
+\n\
+";
+} // unnamed namespace
diff --git a/src/lib/dns/python/pydnspp.cc b/src/lib/dns/python/pydnspp.cc
index 830876c..0a7d8e5 100644
--- a/src/lib/dns/python/pydnspp.cc
+++ b/src/lib/dns/python/pydnspp.cc
@@ -89,64 +89,91 @@ initModulePart_Message(PyObject* mod) {
     if (PyType_Ready(&message_type) < 0) {
         return (false);
     }
+    void* p = &message_type;
+    if (PyModule_AddObject(mod, "Message", static_cast<PyObject*>(p)) < 0) {
+        return (false);
+    }
     Py_INCREF(&message_type);
 
-    // Class variables
-    // These are added to the tp_dict of the type object
-    //
-    addClassVariable(message_type, "PARSE",
-                     Py_BuildValue("I", Message::PARSE));
-    addClassVariable(message_type, "RENDER",
-                     Py_BuildValue("I", Message::RENDER));
-
-    addClassVariable(message_type, "HEADERFLAG_QR",
-                     Py_BuildValue("I", Message::HEADERFLAG_QR));
-    addClassVariable(message_type, "HEADERFLAG_AA",
-                     Py_BuildValue("I", Message::HEADERFLAG_AA));
-    addClassVariable(message_type, "HEADERFLAG_TC",
-                     Py_BuildValue("I", Message::HEADERFLAG_TC));
-    addClassVariable(message_type, "HEADERFLAG_RD",
-                     Py_BuildValue("I", Message::HEADERFLAG_RD));
-    addClassVariable(message_type, "HEADERFLAG_RA",
-                     Py_BuildValue("I", Message::HEADERFLAG_RA));
-    addClassVariable(message_type, "HEADERFLAG_AD",
-                     Py_BuildValue("I", Message::HEADERFLAG_AD));
-    addClassVariable(message_type, "HEADERFLAG_CD",
-                     Py_BuildValue("I", Message::HEADERFLAG_CD));
-
-    addClassVariable(message_type, "SECTION_QUESTION",
-                     Py_BuildValue("I", Message::SECTION_QUESTION));
-    addClassVariable(message_type, "SECTION_ANSWER",
-                     Py_BuildValue("I", Message::SECTION_ANSWER));
-    addClassVariable(message_type, "SECTION_AUTHORITY",
-                     Py_BuildValue("I", Message::SECTION_AUTHORITY));
-    addClassVariable(message_type, "SECTION_ADDITIONAL",
-                     Py_BuildValue("I", Message::SECTION_ADDITIONAL));
-
-    addClassVariable(message_type, "DEFAULT_MAX_UDPSIZE",
-                     Py_BuildValue("I", Message::DEFAULT_MAX_UDPSIZE));
-
-    /* Class-specific exceptions */
-    po_MessageTooShort = PyErr_NewException("pydnspp.MessageTooShort", NULL,
-                                            NULL);
-    PyModule_AddObject(mod, "MessageTooShort", po_MessageTooShort);
-    po_InvalidMessageSection =
-        PyErr_NewException("pydnspp.InvalidMessageSection", NULL, NULL);
-    PyModule_AddObject(mod, "InvalidMessageSection", po_InvalidMessageSection);
-    po_InvalidMessageOperation =
-        PyErr_NewException("pydnspp.InvalidMessageOperation", NULL, NULL);
-    PyModule_AddObject(mod, "InvalidMessageOperation",
-                       po_InvalidMessageOperation);
-    po_InvalidMessageUDPSize =
-        PyErr_NewException("pydnspp.InvalidMessageUDPSize", NULL, NULL);
-    PyModule_AddObject(mod, "InvalidMessageUDPSize", po_InvalidMessageUDPSize);
-    po_DNSMessageBADVERS = PyErr_NewException("pydnspp.DNSMessageBADVERS",
-                                              NULL, NULL);
-    PyModule_AddObject(mod, "DNSMessageBADVERS", po_DNSMessageBADVERS);
-
-    PyModule_AddObject(mod, "Message",
-                       reinterpret_cast<PyObject*>(&message_type));
-
+    try {
+        //
+        // Constant class variables
+        //
+
+        // Parse mode
+        installClassVariable(message_type, "PARSE",
+                             Py_BuildValue("I", Message::PARSE));
+        installClassVariable(message_type, "RENDER",
+                             Py_BuildValue("I", Message::RENDER));
+
+        // Parse options
+        installClassVariable(message_type, "PARSE_DEFAULT",
+                             Py_BuildValue("I", Message::PARSE_DEFAULT));
+        installClassVariable(message_type, "PRESERVE_ORDER",
+                             Py_BuildValue("I", Message::PRESERVE_ORDER));
+
+        // Header flags
+        installClassVariable(message_type, "HEADERFLAG_QR",
+                             Py_BuildValue("I", Message::HEADERFLAG_QR));
+        installClassVariable(message_type, "HEADERFLAG_AA",
+                             Py_BuildValue("I", Message::HEADERFLAG_AA));
+        installClassVariable(message_type, "HEADERFLAG_TC",
+                             Py_BuildValue("I", Message::HEADERFLAG_TC));
+        installClassVariable(message_type, "HEADERFLAG_RD",
+                             Py_BuildValue("I", Message::HEADERFLAG_RD));
+        installClassVariable(message_type, "HEADERFLAG_RA",
+                             Py_BuildValue("I", Message::HEADERFLAG_RA));
+        installClassVariable(message_type, "HEADERFLAG_AD",
+                             Py_BuildValue("I", Message::HEADERFLAG_AD));
+        installClassVariable(message_type, "HEADERFLAG_CD",
+                             Py_BuildValue("I", Message::HEADERFLAG_CD));
+
+        // Sections
+        installClassVariable(message_type, "SECTION_QUESTION",
+                             Py_BuildValue("I", Message::SECTION_QUESTION));
+        installClassVariable(message_type, "SECTION_ANSWER",
+                             Py_BuildValue("I", Message::SECTION_ANSWER));
+        installClassVariable(message_type, "SECTION_AUTHORITY",
+                             Py_BuildValue("I", Message::SECTION_AUTHORITY));
+        installClassVariable(message_type, "SECTION_ADDITIONAL",
+                             Py_BuildValue("I", Message::SECTION_ADDITIONAL));
+
+        // Protocol constant
+        installClassVariable(message_type, "DEFAULT_MAX_UDPSIZE",
+                             Py_BuildValue("I", Message::DEFAULT_MAX_UDPSIZE));
+
+        /* Class-specific exceptions */
+        po_MessageTooShort =
+            PyErr_NewException("pydnspp.MessageTooShort", NULL, NULL);
+        PyObjectContainer(po_MessageTooShort).installToModule(
+            mod, "MessageTooShort");
+        po_InvalidMessageSection =
+            PyErr_NewException("pydnspp.InvalidMessageSection", NULL, NULL);
+        PyObjectContainer(po_InvalidMessageSection).installToModule(
+            mod, "InvalidMessageSection");
+        po_InvalidMessageOperation =
+            PyErr_NewException("pydnspp.InvalidMessageOperation", NULL, NULL);
+        PyObjectContainer(po_InvalidMessageOperation).installToModule(
+            mod, "InvalidMessageOperation");
+        po_InvalidMessageUDPSize =
+            PyErr_NewException("pydnspp.InvalidMessageUDPSize", NULL, NULL);
+        PyObjectContainer(po_InvalidMessageUDPSize).installToModule(
+            mod, "InvalidMessageUDPSize");
+        po_DNSMessageBADVERS =
+            PyErr_NewException("pydnspp.DNSMessageBADVERS", NULL, NULL);
+        PyObjectContainer(po_DNSMessageBADVERS).installToModule(
+            mod, "DNSMessageBADVERS");
+    } catch (const std::exception& ex) {
+        const std::string ex_what =
+            "Unexpected failure in Message initialization: " +
+            std::string(ex.what());
+        PyErr_SetString(po_IscException, ex_what.c_str());
+        return (false);
+    } catch (...) {
+        PyErr_SetString(PyExc_SystemError,
+                        "Unexpected failure in Message initialization");
+        return (false);
+    }
 
     return (true);
 }
diff --git a/src/lib/dns/python/tests/message_python_test.py b/src/lib/dns/python/tests/message_python_test.py
index c731253..8f2d732 100644
--- a/src/lib/dns/python/tests/message_python_test.py
+++ b/src/lib/dns/python/tests/message_python_test.py
@@ -29,9 +29,9 @@ if "TESTDATA_PATH" in os.environ:
 else:
     testdata_path = "../tests/testdata"
 
-def factoryFromFile(message, file):
+def factoryFromFile(message, file, parse_options=Message.PARSE_DEFAULT):
     data = read_wire_data(file)
-    message.from_wire(data)
+    message.from_wire(data, parse_options)
     return data
 
 # we don't have direct comparison for rrsets right now (should we?
@@ -466,6 +466,54 @@ test.example.com. 3600 IN A 192.0.2.2
         self.assertEqual("192.0.2.2", rdata[1].to_text())
         self.assertEqual(2, len(rdata))
 
+    def test_from_wire_short_buffer(self):
+        data = read_wire_data("message_fromWire22.wire")
+        self.assertRaises(DNSMessageFORMERR, self.p.from_wire, data[:-1])
+
+    def test_from_wire_combind_rrs(self):
+        factoryFromFile(self.p, "message_fromWire19.wire")
+        rrset = self.p.get_section(Message.SECTION_ANSWER)[0]
+        self.assertEqual(RRType("A"), rrset.get_type())
+        self.assertEqual(2, len(rrset.get_rdata()))
+
+        rrset = self.p.get_section(Message.SECTION_ANSWER)[1]
+        self.assertEqual(RRType("AAAA"), rrset.get_type())
+        self.assertEqual(1, len(rrset.get_rdata()))
+
+    def check_preserve_rrs(self, message, section):
+        rrset = message.get_section(section)[0]
+        self.assertEqual(RRType("A"), rrset.get_type())
+        rdata = rrset.get_rdata()
+        self.assertEqual(1, len(rdata))
+        self.assertEqual('192.0.2.1', rdata[0].to_text())
+
+        rrset = message.get_section(section)[1]
+        self.assertEqual(RRType("AAAA"), rrset.get_type())
+        rdata = rrset.get_rdata()
+        self.assertEqual(1, len(rdata))
+        self.assertEqual('2001:db8::1', rdata[0].to_text())
+
+        rrset = message.get_section(section)[2]
+        self.assertEqual(RRType("A"), rrset.get_type())
+        rdata = rrset.get_rdata()
+        self.assertEqual(1, len(rdata))
+        self.assertEqual('192.0.2.2', rdata[0].to_text())
+
+    def test_from_wire_preserve_answer(self):
+        factoryFromFile(self.p, "message_fromWire19.wire",
+                        Message.PRESERVE_ORDER)
+        self.check_preserve_rrs(self.p, Message.SECTION_ANSWER)
+
+    def test_from_wire_preserve_authority(self):
+        factoryFromFile(self.p, "message_fromWire20.wire",
+                        Message.PRESERVE_ORDER)
+        self.check_preserve_rrs(self.p, Message.SECTION_AUTHORITY)
+
+    def test_from_wire_preserve_additional(self):
+        factoryFromFile(self.p, "message_fromWire21.wire",
+                        Message.PRESERVE_ORDER)
+        self.check_preserve_rrs(self.p, Message.SECTION_ADDITIONAL)
+
     def test_EDNS0ExtCode(self):
         # Extended Rcode = BADVERS
         message_parse = Message(Message.PARSE)
diff --git a/src/lib/dns/tests/message_unittest.cc b/src/lib/dns/tests/message_unittest.cc
index 6430626..f068791 100644
--- a/src/lib/dns/tests/message_unittest.cc
+++ b/src/lib/dns/tests/message_unittest.cc
@@ -118,16 +118,20 @@ protected:
     vector<unsigned char> received_data;
     vector<unsigned char> expected_data;
 
-    void factoryFromFile(Message& message, const char* datafile);
+    void factoryFromFile(Message& message, const char* datafile,
+                         Message::ParseOptions options =
+                         Message::PARSE_DEFAULT);
 };
 
 void
-MessageTest::factoryFromFile(Message& message, const char* datafile) {
+MessageTest::factoryFromFile(Message& message, const char* datafile,
+                             Message::ParseOptions options)
+{
     received_data.clear();
     UnitTestUtil::readWireData(datafile, received_data);
 
     InputBuffer buffer(&received_data[0], received_data.size());
-    message.fromWire(buffer);
+    message.fromWire(buffer, options);
 }
 
 TEST_F(MessageTest, headerFlag) {
@@ -175,7 +179,6 @@ TEST_F(MessageTest, headerFlag) {
     EXPECT_THROW(message_parse.setHeaderFlag(Message::HEADERFLAG_QR),
                  InvalidMessageOperation);
 }
-
 TEST_F(MessageTest, getEDNS) {
     EXPECT_FALSE(message_parse.getEDNS()); // by default EDNS isn't set
 
@@ -532,7 +535,46 @@ TEST_F(MessageTest, appendSection) {
     
 }
 
+TEST_F(MessageTest, parseHeader) {
+    received_data.clear();
+    UnitTestUtil::readWireData("message_fromWire1", received_data);
+
+    // parseHeader() isn't allowed in the render mode.
+    InputBuffer buffer(&received_data[0], received_data.size());
+    EXPECT_THROW(message_render.parseHeader(buffer), InvalidMessageOperation);
+
+    message_parse.parseHeader(buffer);
+    EXPECT_EQ(0x1035, message_parse.getQid());
+    EXPECT_EQ(Opcode::QUERY(), message_parse.getOpcode());
+    EXPECT_EQ(Rcode::NOERROR(), message_parse.getRcode());
+    EXPECT_TRUE(message_parse.getHeaderFlag(Message::HEADERFLAG_QR));
+    EXPECT_TRUE(message_parse.getHeaderFlag(Message::HEADERFLAG_AA));
+    EXPECT_FALSE(message_parse.getHeaderFlag(Message::HEADERFLAG_TC));
+    EXPECT_TRUE(message_parse.getHeaderFlag(Message::HEADERFLAG_RD));
+    EXPECT_FALSE(message_parse.getHeaderFlag(Message::HEADERFLAG_RA));
+    EXPECT_FALSE(message_parse.getHeaderFlag(Message::HEADERFLAG_AD));
+    EXPECT_FALSE(message_parse.getHeaderFlag(Message::HEADERFLAG_CD));
+    EXPECT_EQ(1, message_parse.getRRCount(Message::SECTION_QUESTION));
+    EXPECT_EQ(2, message_parse.getRRCount(Message::SECTION_ANSWER));
+    EXPECT_EQ(0, message_parse.getRRCount(Message::SECTION_AUTHORITY));
+    EXPECT_EQ(0, message_parse.getRRCount(Message::SECTION_ADDITIONAL));
+
+    // Only the header part should have been examined.
+    EXPECT_EQ(12, buffer.getPosition()); // 12 = size of the header section
+    EXPECT_TRUE(message_parse.beginQuestion() == message_parse.endQuestion());
+    EXPECT_TRUE(message_parse.beginSection(Message::SECTION_ANSWER) ==
+                message_parse.endSection(Message::SECTION_ANSWER));
+    EXPECT_TRUE(message_parse.beginSection(Message::SECTION_AUTHORITY) ==
+                message_parse.endSection(Message::SECTION_AUTHORITY));
+    EXPECT_TRUE(message_parse.beginSection(Message::SECTION_ADDITIONAL) ==
+                message_parse.endSection(Message::SECTION_ADDITIONAL));
+}
+
 TEST_F(MessageTest, fromWire) {
+    // fromWire() isn't allowed in the render mode.
+    EXPECT_THROW(factoryFromFile(message_render, "message_fromWire1"),
+                 InvalidMessageOperation);
+
     factoryFromFile(message_parse, "message_fromWire1");
     EXPECT_EQ(0x1035, message_parse.getQid());
     EXPECT_EQ(Opcode::QUERY(), message_parse.getOpcode());
@@ -564,6 +606,87 @@ TEST_F(MessageTest, fromWire) {
     EXPECT_TRUE(it->isLast());
 }
 
+TEST_F(MessageTest, fromWireShortBuffer) {
+    // We trim a valid message (ending with an SOA RR) for one byte.
+    // fromWire() should throw an exception while parsing the trimmed RR.
+    UnitTestUtil::readWireData("message_fromWire22.wire", received_data);
+    InputBuffer buffer(&received_data[0], received_data.size() - 1);
+    EXPECT_THROW(message_parse.fromWire(buffer), InvalidBufferPosition);
+}
+
+TEST_F(MessageTest, fromWireCombineRRs) {
+    // This message contains 3 RRs in the answer section in the order of
+    // A, AAAA, A types.  fromWire() should combine the two A RRs into a
+    // single RRset by default.
+    factoryFromFile(message_parse, "message_fromWire19.wire");
+
+    RRsetIterator it = message_parse.beginSection(Message::SECTION_ANSWER);
+    RRsetIterator it_end = message_parse.endSection(Message::SECTION_ANSWER);
+    ASSERT_TRUE(it != it_end);
+    EXPECT_EQ(RRType::A(), (*it)->getType());
+    EXPECT_EQ(2, (*it)->getRdataCount());
+
+    ++it;
+    ASSERT_TRUE(it != it_end);
+    EXPECT_EQ(RRType::AAAA(), (*it)->getType());
+    EXPECT_EQ(1, (*it)->getRdataCount());
+}
+
+// A helper function for a test pattern commonly used in several tests below.
+void
+preserveRRCheck(const Message& message, Message::Section section) {
+    RRsetIterator it = message.beginSection(section);
+    RRsetIterator it_end = message.endSection(section);
+    ASSERT_TRUE(it != it_end);
+    EXPECT_EQ(RRType::A(), (*it)->getType());
+    EXPECT_EQ(1, (*it)->getRdataCount());
+    EXPECT_EQ("192.0.2.1", (*it)->getRdataIterator()->getCurrent().toText());
+
+    ++it;
+    ASSERT_TRUE(it != it_end);
+    EXPECT_EQ(RRType::AAAA(), (*it)->getType());
+    EXPECT_EQ(1, (*it)->getRdataCount());
+    EXPECT_EQ("2001:db8::1", (*it)->getRdataIterator()->getCurrent().toText());
+
+    ++it;
+    ASSERT_TRUE(it != it_end);
+    EXPECT_EQ(RRType::A(), (*it)->getType());
+    EXPECT_EQ(1, (*it)->getRdataCount());
+    EXPECT_EQ("192.0.2.2", (*it)->getRdataIterator()->getCurrent().toText());
+}
+
+TEST_F(MessageTest, fromWirePreserveAnswer) {
+    // Using the same data as the previous test, but specify the PRESERVE_ORDER
+    // option.  The received order of RRs should be preserved, and each RR
+    // should be stored in a single RRset.
+    factoryFromFile(message_parse, "message_fromWire19.wire",
+                    Message::PRESERVE_ORDER);
+    {
+        SCOPED_TRACE("preserve answer RRs");
+        preserveRRCheck(message_parse, Message::SECTION_ANSWER);
+    }
+}
+
+TEST_F(MessageTest, fromWirePreserveAuthority) {
+    // Same for the previous test, but for the authority section.
+    factoryFromFile(message_parse, "message_fromWire20.wire",
+                    Message::PRESERVE_ORDER);
+    {
+        SCOPED_TRACE("preserve authority RRs");
+        preserveRRCheck(message_parse, Message::SECTION_AUTHORITY);
+    }
+}
+
+TEST_F(MessageTest, fromWirePreserveAdditional) {
+    // Same for the previous test, but for the additional section.
+    factoryFromFile(message_parse, "message_fromWire21.wire",
+                    Message::PRESERVE_ORDER);
+    {
+        SCOPED_TRACE("preserve additional RRs");
+        preserveRRCheck(message_parse, Message::SECTION_ADDITIONAL);
+    }
+}
+
 TEST_F(MessageTest, EDNS0ExtRcode) {
     // Extended Rcode = BADVERS
     factoryFromFile(message_parse, "message_fromWire10.wire");
diff --git a/src/lib/dns/tests/testdata/Makefile.am b/src/lib/dns/tests/testdata/Makefile.am
index 3aa4937..d8f0d1c 100644
--- a/src/lib/dns/tests/testdata/Makefile.am
+++ b/src/lib/dns/tests/testdata/Makefile.am
@@ -6,7 +6,9 @@ BUILT_SOURCES += message_fromWire10.wire message_fromWire11.wire
 BUILT_SOURCES += message_fromWire12.wire message_fromWire13.wire
 BUILT_SOURCES += message_fromWire14.wire message_fromWire15.wire
 BUILT_SOURCES += message_fromWire16.wire message_fromWire17.wire
-BUILT_SOURCES += message_fromWire18.wire
+BUILT_SOURCES += message_fromWire18.wire message_fromWire19.wire
+BUILT_SOURCES += message_fromWire20.wire message_fromWire21.wire
+BUILT_SOURCES += message_fromWire22.wire
 BUILT_SOURCES += message_toWire2.wire message_toWire3.wire
 BUILT_SOURCES += message_toWire4.wire message_toWire5.wire
 BUILT_SOURCES += message_toText1.wire message_toText2.wire
@@ -71,6 +73,8 @@ EXTRA_DIST += message_fromWire11.spec message_fromWire12.spec
 EXTRA_DIST += message_fromWire13.spec message_fromWire14.spec
 EXTRA_DIST += message_fromWire15.spec message_fromWire16.spec
 EXTRA_DIST += message_fromWire17.spec message_fromWire18.spec
+EXTRA_DIST += message_fromWire19.spec message_fromWire20.spec
+EXTRA_DIST += message_fromWire21.spec message_fromWire22.spec
 EXTRA_DIST += message_toWire1 message_toWire2.spec message_toWire3.spec
 EXTRA_DIST += message_toWire4.spec message_toWire5.spec
 EXTRA_DIST += message_toText1.txt message_toText1.spec
diff --git a/src/lib/dns/tests/testdata/message_fromWire19.spec b/src/lib/dns/tests/testdata/message_fromWire19.spec
new file mode 100644
index 0000000..8212dbf
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire19.spec
@@ -0,0 +1,20 @@
+#
+# A non realistic DNS response message containing mixed types of RRs in the
+# answer section in a mixed order.
+#
+
+[custom]
+sections: header:question:a/1:aaaa:a/2
+[header]
+qr: 1
+ancount: 3
+[question]
+name: www.example.com
+rrtype: A
+[a/1]
+as_rr: True
+[aaaa]
+as_rr: True
+[a/2]
+as_rr: True
+address: 192.0.2.2
diff --git a/src/lib/dns/tests/testdata/message_fromWire20.spec b/src/lib/dns/tests/testdata/message_fromWire20.spec
new file mode 100644
index 0000000..91986e4
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire20.spec
@@ -0,0 +1,20 @@
+#
+# A non realistic DNS response message containing mixed types of RRs in the
+# authority section in a mixed order.
+#
+
+[custom]
+sections: header:question:a/1:aaaa:a/2
+[header]
+qr: 1
+nscount: 3
+[question]
+name: www.example.com
+rrtype: A
+[a/1]
+as_rr: True
+[aaaa]
+as_rr: True
+[a/2]
+as_rr: True
+address: 192.0.2.2
diff --git a/src/lib/dns/tests/testdata/message_fromWire21.spec b/src/lib/dns/tests/testdata/message_fromWire21.spec
new file mode 100644
index 0000000..cd6aac9
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire21.spec
@@ -0,0 +1,20 @@
+#
+# A non realistic DNS response message containing mixed types of RRs in the
+# additional section in a mixed order.
+#
+
+[custom]
+sections: header:question:a/1:aaaa:a/2
+[header]
+qr: 1
+arcount: 3
+[question]
+name: www.example.com
+rrtype: A
+[a/1]
+as_rr: True
+[aaaa]
+as_rr: True
+[a/2]
+as_rr: True
+address: 192.0.2.2
diff --git a/src/lib/dns/tests/testdata/message_fromWire22.spec b/src/lib/dns/tests/testdata/message_fromWire22.spec
new file mode 100644
index 0000000..a52523b
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire22.spec
@@ -0,0 +1,14 @@
+#
+# A simple DNS message containing one SOA RR in the answer section.  This is
+# intended to be trimmed to emulate a bogus message.
+#
+
+[custom]
+sections: header:question:soa
+[header]
+qr: 1
+ancount: 1
+[question]
+rrtype: SOA
+[soa]
+as_rr: True
diff --git a/src/lib/python/isc/datasrc/Makefile.am b/src/lib/python/isc/datasrc/Makefile.am
index d8f6b08..ca2d9b4 100644
--- a/src/lib/python/isc/datasrc/Makefile.am
+++ b/src/lib/python/isc/datasrc/Makefile.am
@@ -1,17 +1,16 @@
 SUBDIRS = . tests
 
 # old data, should be removed in the near future once conversion is done
+pythondir = $(pyexecdir)/isc/datasrc
 python_PYTHON = __init__.py master.py sqlite3_ds.py
 
-#pythondir = $(pyexecdir)/isc/pydatasrc
 
 # new data
 
 AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
 AM_CPPFLAGS += $(SQLITE_CFLAGS)
 
-pythondir = $(pyexecdir)/isc
-pyexec_LTLIBRARIES = datasrc.la
+python_LTLIBRARIES = datasrc.la
 datasrc_la_SOURCES = datasrc.cc datasrc.h
 datasrc_la_SOURCES += client_python.cc client_python.h
 datasrc_la_SOURCES += iterator_python.cc iterator_python.h
diff --git a/src/lib/python/isc/datasrc/__init__.py b/src/lib/python/isc/datasrc/__init__.py
index 53711db..0b4ed98 100644
--- a/src/lib/python/isc/datasrc/__init__.py
+++ b/src/lib/python/isc/datasrc/__init__.py
@@ -1,12 +1,21 @@
 import sys
 import os
 
+# this setup is a temporary workaround to deal with the problem of
+# having both 'normal' python modules and a wrapper module
+# Once all programs use the new interface, we should remove the
+# old, and the setup can be made similar to that of the log wrappers.
+intree = False
 for base in sys.path[:]:
     datasrc_libdir = os.path.join(base, 'isc/datasrc/.libs')
     if os.path.exists(datasrc_libdir):
         sys.path.insert(0, datasrc_libdir)
+        intree = True
 
-from datasrc import *
+if intree:
+    from datasrc import *
+else:
+    from isc.datasrc.datasrc import *
 from isc.datasrc.sqlite3_ds import *
 from isc.datasrc.master import *
 
diff --git a/src/lib/python/isc/log/log.cc b/src/lib/python/isc/log/log.cc
index aa12664..5bb6a94 100644
--- a/src/lib/python/isc/log/log.cc
+++ b/src/lib/python/isc/log/log.cc
@@ -185,7 +185,7 @@ init(PyObject*, PyObject* args) {
     Py_RETURN_NONE;
 }
 
-// This initialization is for unit tests.  It allows message settings to be
+// This initialization is for unit tests.  It allows message settings to
 // be determined by a set of B10_xxx environment variables.  (See the
 // description of initLogger() for more details.)  The function has been named
 // resetUnitTestRootLogger() here as being more descriptive and




More information about the bind10-changes mailing list