Status BtreeBasedAccessMethod::validateUpdate(const BSONObj &from,
                                                  const BSONObj &to,
                                                  const DiskLoc &record,
                                                  const InsertDeleteOptions &options,
                                                  UpdateTicket* status) {

        BtreeBasedPrivateUpdateData *data = new BtreeBasedPrivateUpdateData();
        status->_indexSpecificUpdateData.reset(data);

        getKeys(from, &data->oldKeys);
        getKeys(to, &data->newKeys);
        data->loc = record;
        data->dupsAllowed = options.dupsAllowed;

        setDifference(data->oldKeys, data->newKeys, &data->removed);
        setDifference(data->newKeys, data->oldKeys, &data->added);

        bool checkForDups = !data->added.empty()
            && (KeyPattern::isIdKeyPattern(_descriptor->keyPattern()) || _descriptor->unique())
            && !options.dupsAllowed;

        if (checkForDups) {
            for (vector<BSONObj*>::iterator i = data->added.begin(); i != data->added.end(); i++) {
                Status check = _newInterface->dupKeyCheck(**i, record);
                if (!check.isOK()) {
                    status->_isValid = false;
                    return check;
                }
            }
        }

        status->_isValid = true;

        return Status::OK();
    }
Esempio n. 2
0
File: list.cpp Progetto: EBone/Faust
Tree setDifference (Tree A, Tree B)
{
	if (isNil(A)) 		return A;
	if (isNil(B)) 		return A;
	if (hd(A) == hd(B)) return setDifference(tl(A),tl(B));
	if (hd(A) < hd(B)) 	return cons(hd(A), setDifference(tl(A),B));
	/* (hd(A) > hd(B)*/	return setDifference(A,tl(B));
}
Esempio n. 3
0
Status IndexAccessMethod::validateUpdate(OperationContext* txn,
                                         const BSONObj& from,
                                         const BSONObj& to,
                                         const RecordId& record,
                                         const InsertDeleteOptions& options,
                                         UpdateTicket* ticket,
                                         const MatchExpression* indexFilter) {
    if (!indexFilter || indexFilter->matchesBSON(from)) {
        // There's no need to compute the prefixes of the indexed fields that possibly caused the
        // index to be multikey when the old version of the document was written since the index
        // metadata isn't updated when keys are deleted.
        MultikeyPaths* multikeyPaths = nullptr;
        getKeys(from, &ticket->oldKeys, multikeyPaths);
    }

    if (!indexFilter || indexFilter->matchesBSON(to)) {
        getKeys(to, &ticket->newKeys, &ticket->newMultikeyPaths);
    }

    ticket->loc = record;
    ticket->dupsAllowed = options.dupsAllowed;

    std::tie(ticket->removed, ticket->added) = setDifference(ticket->oldKeys, ticket->newKeys);

    ticket->_isValid = true;

    return Status::OK();
}
Esempio n. 4
0
 void getIndexChanges(vector<IndexChanges>& v, NamespaceDetails& d, BSONObj newObj, BSONObj oldObj, bool &changedId) {
     int z = d.nIndexesBeingBuilt();
     v.resize(z);
     for( int i = 0; i < z; i++ ) {
         IndexDetails& idx = d.idx(i);
         BSONObj idxKey = idx.info.obj().getObjectField("key"); // eg { ts : 1 }
         IndexChanges& ch = v[i];
         idx.getKeysFromObject(oldObj, ch.oldkeys);
         idx.getKeysFromObject(newObj, ch.newkeys);
         if( ch.newkeys.size() > 1 )
             d.setIndexIsMultikey(i);
         setDifference(ch.oldkeys, ch.newkeys, ch.removed);
         setDifference(ch.newkeys, ch.oldkeys, ch.added);
         if ( ch.removed.size() > 0 && ch.added.size() > 0 && idx.isIdIndex() ) {
             changedId = true;
         }
     }
 }
Esempio n. 5
0
    Status IndexAccessMethod::validateUpdate(OperationContext* txn,
                                             const BSONObj &from,
                                             const BSONObj &to,
                                             const RecordId &record,
                                             const InsertDeleteOptions &options,
                                             UpdateTicket* ticket) {

        getKeys(from, &ticket->oldKeys);
        getKeys(to, &ticket->newKeys);
        ticket->loc = record;
        ticket->dupsAllowed = options.dupsAllowed;

        setDifference(ticket->oldKeys, ticket->newKeys, &ticket->removed);
        setDifference(ticket->newKeys, ticket->oldKeys, &ticket->added);

        ticket->_isValid = true;

        return Status::OK();
    }
Esempio n. 6
0
Status IndexAccessMethod::validateUpdate(OperationContext* txn,
                                         const BSONObj& from,
                                         const BSONObj& to,
                                         const RecordId& record,
                                         const InsertDeleteOptions& options,
                                         UpdateTicket* ticket,
                                         const MatchExpression* indexFilter) {
    if (indexFilter == NULL || indexFilter->matchesBSON(from))
        getKeys(from, &ticket->oldKeys);
    if (indexFilter == NULL || indexFilter->matchesBSON(to))
        getKeys(to, &ticket->newKeys);
    ticket->loc = record;
    ticket->dupsAllowed = options.dupsAllowed;

    setDifference(ticket->oldKeys, ticket->newKeys, &ticket->removed);
    setDifference(ticket->newKeys, ticket->oldKeys, &ticket->added);

    ticket->_isValid = true;

    return Status::OK();
}
Status BtreeBasedAccessMethod::validateUpdate(OperationContext* txn,
                                              const BSONObj& from,
                                              const BSONObj& to,
                                              const RecordId& record,
                                              const InsertDeleteOptions& options,
                                              UpdateTicket* status) {
    BtreeBasedPrivateUpdateData* data = new BtreeBasedPrivateUpdateData();
    status->_indexSpecificUpdateData.reset(data);

    getKeys(from, &data->oldKeys);
    getKeys(to, &data->newKeys);
    data->loc = record;
    data->dupsAllowed = options.dupsAllowed;

    setDifference(data->oldKeys, data->newKeys, &data->removed);
    setDifference(data->newKeys, data->oldKeys, &data->added);

    status->_isValid = true;

    return Status::OK();
}
Esempio n. 8
0
/**
* @brief Finds a next SCC and its represent and returns them.
*
* @param[in] sccs All SCCs in the call graph.
* @param[in] computedFuncs Functions that already have been included in
*                          FuncInfoCompOrder::order.
* @param[in] remainingFuncs Functions that haven't been included in
*                           FuncInfoCompOrder::order.
*
* @par Preconditions
*  - @a remainingFuncs is non-empty
*  - @a remainingFuncs doesn't contain a function which calls just functions
*    from @a computedFuncs.
*/
CallInfoObtainer::SCCWithRepresent CallInfoObtainer::findNextSCC(const FuncSetSet &sccs,
		const FuncSet &computedFuncs, const FuncSet &remainingFuncs) const {
	PRECONDITION(!remainingFuncs.empty(), "it should not be empty");

	//
	// We try to locate an SCC whose members call just the functions in
	// the SCC or in computedFuncs. Then, if the found SCC contains a function
	// from remainingFuncs, return the function.
	//
	// For every SCC...
	for (const auto &scc : sccs) {
		bool sccFound = true;
		ShPtr<Function> funcFromRemainingFuncs;
		// For every function in the SCC...
		for (const auto &func : scc) {
			// Check whether the function calls just the functions in the SCC
			// or in computedFuncs.
			ShPtr<CG::CalledFuncs> calledFuncs(cg->getCalledFuncs(func));
			FuncSet mayCall(setUnion(scc, computedFuncs));
			if (!setDifference(calledFuncs->callees, mayCall).empty()) {
				sccFound = false;
			} else {
				// Have we encountered a function from remainingFuncs?
				if (hasItem(remainingFuncs, func)) {
					funcFromRemainingFuncs = func;
				}
			}
		}
		if (sccFound && funcFromRemainingFuncs) {
			return SCCWithRepresent(scc, funcFromRemainingFuncs);
		}
	}

	// TODO Can this happen?
	printWarningMessage("[SCCComputer] No viable SCC has been found.");
	FuncSet scc;
	ShPtr<Function> func(*(remainingFuncs.begin()));
	scc.insert(func);
	return SCCWithRepresent(scc, func);
}
/**
* @brief Computes the FuncInfo and returns it.
*/
ShPtr<OptimFuncInfo> OptimFuncInfoCFGTraversal::performComputation() {
	// First, we pre-compute varsAlwaysModifiedBeforeRead. The reason is that
	// their computation differs from the computation of the rest of the sets.
	precomputeAlwaysModifiedVarsBeforeRead();

	// Every function's body is of the following form:
	//
	//    (1) definitions of local variables, including assignments of global
	//        variables into local variables
	//    (2) other statements
	//
	// We store which variables are read/modified in (1). Then, we start the
	// traversal from (2). During the traversal, we check which variables are
	// read/modified and update funcInfo accordingly. The stored information
	// from (1) is used to compute the set of global variables which are read
	// in the function, but not modified.
	//
	// To give a specific example, consider the following code:
	//
	// def func(mango):
	//    global orange
	//    global plum
	//    lychee = orange
	//    achira = plum
	//    orange = mango
	//    plum = rand()
	//    result = plum * apple + orange
	//    orange = lychee
	//    plum = achira
	//    return result
	//
	// Here, even though the global variable orange is modified, its value
	// before calling func() is the same as after calling func(). Indeed, its
	// value is restored before the return statement. Hence, we may put it into
	// funcInfo->varsWithNeverChangedValue.
	// TODO Implement a more robust analysis.
	ShPtr<Statement> currStmt = traversedFunc->getBody();
	while (isVarDefOrAssignStmt(currStmt)) {
		updateFuncInfo(currStmt);

		ShPtr<Expression> lhs(getLhs(currStmt));
		ShPtr<Expression> rhs(getRhs(currStmt));

		// If there is no right-hand side, it is a VarDefStmt with no
		// initializer, which we may skip.
		if (!rhs) {
			currStmt = currStmt->getSuccessor();
			continue;
		}

		// If there are any function calls or dereferences, we have reached
		// (2).
		ShPtr<ValueData> currStmtData(va->getValueData(currStmt));
		if (currStmtData->hasCalls() || currStmtData->hasDerefs()) {
			break;
		}

		// Check whether the statement is of the form localVar = globalVar.
		ShPtr<Variable> localVar(cast<Variable>(lhs));
		ShPtr<Variable> globalVar(cast<Variable>(rhs));
		if (!localVar || !globalVar || hasItem(globalVars, localVar) ||
				!hasItem(globalVars, globalVar)) {
			// It is not of the abovementioned form, so skip it.
			currStmt = currStmt->getSuccessor();
			continue;
		}

		storedGlobalVars[globalVar] = localVar;
		currStmt = currStmt->getSuccessor();
	}

	// Perform the traversal only if we haven't reached the end of the function
	// yet. Since empty statements are not present in a CFG, skip them before
	// the traversal.
	if ((currStmt = skipEmptyStmts(currStmt))) {
		performTraversal(currStmt);
	}

	// We use the exit node of the CFG to check that every variable from
	// storedGlobalVars is retrieved its original value before every return.
	ShPtr<CFG::Node> exitNode(cfg->getExitNode());
	// For every predecessor of the exit node...
	for (auto i = exitNode->pred_begin(), e = exitNode->pred_end(); i != e; ++i) {
		bool checkingShouldContinue = checkExitNodesPredecessor((*i)->getSrc());
		if (!checkingShouldContinue) {
			break;
		}
	}

	// Update funcInfo using the remaining variables in storedGlobalVars.
	for (const auto &p : storedGlobalVars) {
		funcInfo->varsWithNeverChangedValue.insert(p.first);
	}

	// Update funcInfo->never{Read,Modified}Vars by global variables which are
	// untouched in this function.
	for (auto i = module->global_var_begin(), e = module->global_var_end();
			i != e; ++i) {
		ShPtr<Variable> var((*i)->getVar());
		if (!hasItem(funcInfo->mayBeReadVars, var) &&
				!hasItem(funcInfo->mayBeModifiedVars, var)) {
			funcInfo->neverReadVars.insert(var);
			funcInfo->neverModifiedVars.insert(var);
		}
	}

	// If the cfg contains only a single non-{entry,exit} node, every
	// mayBe{Read,Modifed} variable can be turned into a always{Read,Modified}
	// variable.
	if (cfg->getNumberOfNodes() == 3) {
		addToSet(funcInfo->mayBeReadVars, funcInfo->alwaysReadVars);
		addToSet(funcInfo->mayBeModifiedVars, funcInfo->alwaysModifiedVars);
	}

	// Add all variables which are never read and never modified to
	// varsWithNeverChangedValue.
	VarSet neverReadAndModifedVars(setIntersection(funcInfo->neverReadVars,
		funcInfo->neverModifiedVars));
	addToSet(neverReadAndModifedVars, funcInfo->varsWithNeverChangedValue);

	// Add all global variables are not read in this function into
	// varsAlwaysModifiedBeforeRead.
	addToSet(setDifference(globalVars, funcInfo->mayBeReadVars),
		funcInfo->varsAlwaysModifiedBeforeRead);

	return funcInfo;
}