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

View graph invalid on WriteUnitOfWork rollback

    • Type: Icon: Bug Bug
    • Resolution: Done
    • Priority: Icon: Major - P3 Major - P3
    • 3.3.14
    • Affects Version/s: None
    • Component/s: Storage
    • Major Change
    • ALL
    • Hide

      Reproducible via WIP fsm test for views cycle detection (SERVER-25808):

      'use strict';
      
      /**
       * view_catalog_cycle_with_drop.js
       *
       *
       */
      
      load('jstests/concurrency/fsm_workload_helpers/drop_utils.js');  // for dropCollections
      
      var $config = (function() {
      
          var data = {
              // Use the workload name as a prefix for the view names,
              // since the workload name is assumed to be unique.
              prefix: 'view_catalog_cycle_with_drop',
              viewList: ["viewA", "viewB", "viewC"],
          };
      
          function assertIfNotOKAndNotCode(result, code) {
              assertAlways(result.ok === 1 || (result.ok === 0 && result.code !== code, tojson(result)));
          }
      
          var states = (function() {
              function init(db, colName) {
              }
      
              function remapViewToView(db, colName) {
                  let fromName = this.viewList[Random.randInt(3)];
                  let toName = this.viewList[Random.randInt(3)];
                  let res = db.runCommand({collMod: fromName, viewOn: toName, pipeline: []});
                  assertIfNotOKAndNotCode(res, ErrorCodes.GraphContainsCycle);
              }
      
              function readFromView(db, colName) {
                  let viewName = this.viewList[Random.randInt(3)];
                  assert.commandWorked(db.runCommand({find: viewName}),
                                       viewName + ": " + tojson(db.runCommand({listCollections: 1})));
              }
      
              return {
                  init: init,
                  remapViewToView: remapViewToView,
                  readFromView: readFromView
              };
      
          })();
      
          var transitions = {
              init: {remapViewToView: .75, readFromView: .25},
              remapViewToView: {remapViewToView: .75, readFromView: .25},
              readFromView: {remapViewToView: .50, readFromView: .50},
          };
      
      
          function setup(db, collName, cluster) {
              // Setup base collection & populate.
              let col = db[collName];
      
              assertAlways.writeOK(col.insert({x: 1}));
      
              for (var i in this.viewList) {
                  db.createView(this.viewList[i], collName, []);
              }
      
              jsTest.log(tojson(db.runCommand({listCollections: 1})));
          };
      
          function teardown(db, collName, cluster) {
              var pattern = new RegExp('^' + this.prefix + '_\\d+$');
              dropCollections(db, pattern);
          };
      
          return {
              threadCount: 100,
              iterations: 100,
              data: data,
              states: states,
              transitions: transitions,
              setup: setup,
              teardown: teardown,
          };
      
      })();
      
      Show
      Reproducible via WIP fsm test for views cycle detection ( SERVER-25808 ): 'use strict' ; /** * view_catalog_cycle_with_drop.js * * */ load( 'jstests/concurrency/fsm_workload_helpers/drop_utils.js' ); // for dropCollections var $config = (function() { var data = { // Use the workload name as a prefix for the view names, // since the workload name is assumed to be unique. prefix: 'view_catalog_cycle_with_drop' , viewList: [ "viewA" , "viewB" , "viewC" ], }; function assertIfNotOKAndNotCode(result, code) { assertAlways(result.ok === 1 || (result.ok === 0 && result.code !== code, tojson(result))); } var states = (function() { function init(db, colName) { } function remapViewToView(db, colName) { let fromName = this .viewList[Random.randInt(3)]; let toName = this .viewList[Random.randInt(3)]; let res = db.runCommand({collMod: fromName, viewOn: toName, pipeline: []}); assertIfNotOKAndNotCode(res, ErrorCodes.GraphContainsCycle); } function readFromView(db, colName) { let viewName = this .viewList[Random.randInt(3)]; assert .commandWorked(db.runCommand({find: viewName}), viewName + ": " + tojson(db.runCommand({listCollections: 1}))); } return { init: init, remapViewToView: remapViewToView, readFromView: readFromView }; })(); var transitions = { init: {remapViewToView: .75, readFromView: .25}, remapViewToView: {remapViewToView: .75, readFromView: .25}, readFromView: {remapViewToView: .50, readFromView: .50}, }; function setup(db, collName, cluster) { // Setup base collection & populate. let col = db[collName]; assertAlways.writeOK(col.insert({x: 1})); for ( var i in this .viewList) { db.createView( this .viewList[i], collName, []); } jsTest.log(tojson(db.runCommand({listCollections: 1}))); }; function teardown(db, collName, cluster) { var pattern = new RegExp( '^' + this .prefix + '_\\d+$' ); dropCollections(db, pattern); }; return { threadCount: 100, iterations: 100, data: data, states: states, transitions: transitions, setup: setup, teardown: teardown, }; })();

      ViewCatalog::_upsertIntoGraph sets _viewGraphNeedsRefresh to false on successful insert, but does not take into account post-insert rollback. This can lead to successful creation of view definition cycles.

      _viewGraphNeedsRefresh should be set back to true on rollback.

            Assignee:
            james.wahlin@mongodb.com James Wahlin
            Reporter:
            james.wahlin@mongodb.com James Wahlin
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: