Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-60909

Incorrect use of BSONObjBuilder in mongos explain

    XMLWordPrintable

Details

    • Bug
    • Status: In Code Review
    • Minor - P4
    • Resolution: Unresolved
    • 5.0.3-rc0, 4.2.17, 4.4.10
    • None
    • None
    • None
    • ALL
    • 23

    Description

      In this mongos explain logic, we continue writing to a BSONArrayBuilder after calling done() on it, and further, after opening a new BSONArrayBuilder. This can cause mongos to return strange (and arguably, garbage) results, where a BSON array's first key is "1" instead of "0." We should change this logic in cluster_explain.cpp to use BSONArrayBuilder correctly.
       

      I've copied and pasted the code below and added my notes:

          BSONArrayBuilder execShardsBuilder(executionStagesBob.subarrayStart("shards"));
          for (size_t i = 0; i < shardResponses.size(); i++) {
              auto responseData = shardResponses[i].swResponse.getValue().data;
       
              BSONObjBuilder singleShardBob(execShardsBuilder.subobjStart());
              BSONObj execStats = responseData["executionStats"].Obj();
       
              singleShardBob.append("shardName", shardResponses[i].shardId.toString());
              appendElementsIfRoom(&singleShardBob, execStats);
              singleShardBob.doneFast();
          }
          execShardsBuilder.doneFast();
       
          executionStagesBob.doneFast();
       
          if (!firstShardResponseData["executionStats"].Obj().hasField("allPlansExecution")) {
              // The shards don't have execution stats for all plans, so we're done.
              executionStatsBob.doneFast();
              return;
          }
       
          // Add the allPlans stats from each shard.
          BSONArrayBuilder allPlansExecBob(executionStatsBob.subarrayStart("allPlansExecution"));    // NOTE(ianb): Notice how 'allPlansExecBob' is never used.
          for (size_t i = 0; i < shardResponses.size(); i++) {
              auto responseData = shardResponses[i].swResponse.getValue().data;
              // NOTE(ianb): Notice how we're using 'execShardsBuilder' even though we already called done() on that above.
              BSONObjBuilder singleShardBob(execShardsBuilder.subobjStart());
              singleShardBob.append("shardName", shardResponses[i].shardId.toString());
       
              BSONObj execStats = responseData["executionStats"].Obj();
              vector<BSONElement> allPlans = execStats["allPlansExecution"].Array();
       
              BSONArrayBuilder innerArrayBob(singleShardBob.subarrayStart("allPlans"));
              for (size_t j = 0; j < allPlans.size(); j++) {
                  appendToArrayIfRoom(&innerArrayBob, allPlans[j]);
              }
              innerArrayBob.done();
       
              singleShardBob.doneFast();
          }
          allPlansExecBob.doneFast();
       
          executionStatsBob.doneFast();
      }
      

      Attachments

        Issue Links

          Activity

            People

              ted.tuckman@mongodb.com Ted Tuckman
              ian.boros@mongodb.com Ian Boros
              Votes:
              0 Vote for this issue
              Watchers:
              10 Start watching this issue

              Dates

                Created:
                Updated: