private void validateCurrentSnapshot() throws CommandProcessorException {
    int retryShapshotCount = 0;
    
    int maxRetrySnapshotCount = HiveConf.getIntVar(driverContext.getConf(),
        HiveConf.ConfVars.HIVE_TXN_MAX_RETRYSNAPSHOT_COUNT);
    try {
      do {
        driverContext.setOutdatedTxn(false);
        // Inserts will not invalidate the snapshot, that could cause duplicates.
        
        if (!driverTxnHandler.isValidTxnListState()) {
          LOG.info("Re-compiling after acquiring locks, attempt #" + retryShapshotCount);
          HiveTxnManager txnMgr = driverContext.getTxnManager();
          // Snapshot was outdated when locks were acquired, hence regenerate context, txn list and retry.
          // TODO: Lock acquisition should be moved before analyze, this is a bit hackish.
          // Currently, we acquire a snapshot, compile the query with that snapshot, and then - acquire locks.
          // If snapshot is still valid, we continue as usual.
          // But if snapshot is not valid, we recompile the query.
          if (driverContext.isOutdatedTxn()) {
            // Later transaction invalidated the snapshot, a new transaction is required
            LOG.info("Snapshot is outdated, re-initiating transaction ...");
            txnMgr.rollbackTxn();

            String userFromUGI = DriverUtils.getUserFromUGI(driverContext);
            txnMgr.openTxn(context, userFromUGI, driverContext.getTxnType());
            lockAndRespond();
          } else {
            // We need to clear the possibly cached writeIds for the prior transaction, so new writeIds
            // are allocated since writeIds need to be committed in increasing order. It helps in cases
            // like:
            // txnId   writeId
            // 10      71  <--- commit first
            // 11      69
            // 12      70
            // in which the transaction is not out of date, but the writeId would not be increasing.
            // This would be a problem in an UPDATE, since it would end up generating delete
            // deltas for a future writeId - which in turn causes scans to not think they are deleted.
            // The scan basically does last writer wins for a given row which is determined by
            // max(committingWriteId) for a given ROW__ID(originalWriteId, bucketId, rowId). So the
            // data add ends up being > than the data delete.
            txnMgr.clearCaches();
          }
          driverContext.getConf().unset(ValidTxnList.VALID_TXNS_KEY);
          driverContext.setRetrial(true);

          compileInternal(context.getCmd(), true);

          if (driverContext.getPlan().hasAcidResourcesInQuery()) {
            driverTxnHandler.recordValidWriteIds();
            driverTxnHandler.setWriteIdForAcidFileSinks();
          }
          // Since we're reusing the compiled plan, we need to update its start time for current run
          driverContext.getPlan().setQueryStartTime(
              driverContext.getQueryDisplay().getQueryStartTime());
          driverContext.setRetrial(false);
        }
        // Re-check snapshot only in case we had to release locks and open a new transaction,
        // otherwise exclusive locks should protect output tables/partitions in snapshot from concurrent writes.
      } while (driverContext.isOutdatedTxn() && ++retryShapshotCount <= maxRetrySnapshotCount);

    } catch (LockException | SemanticException e) {
      DriverUtils.handleHiveException(driverContext, e, 13, null);
    }

    if (retryShapshotCount > maxRetrySnapshotCount) {
      // Throw exception
      HiveException e = new HiveException(
          "Operation could not be executed, " + SNAPSHOT_WAS_OUTDATED_WHEN_LOCKS_WERE_ACQUIRED + ".");
      DriverUtils.handleHiveException(driverContext, e, 14, null);
    }
  }
Checks if the recorded snapshot is up-to-date
ql/src/java/org/apache/hadoop/hive/ql/Driver.java