Ejemplo n.º 1
0
void ServerConfig::CrossCheckConnectBlocks(ServerConfig* current)
{
	typedef std::map<std::string, ConnectClass*> ClassMap;
	ClassMap oldBlocksByMask;
	if (current)
	{
		for(ClassVector::iterator i = current->Classes.begin(); i != current->Classes.end(); ++i)
		{
			ConnectClass* c = *i;
			if (c->name.substr(0, 8) != "unnamed-")
			{
				oldBlocksByMask["n" + c->name] = c;
			}
			else if (c->type == CC_ALLOW || c->type == CC_DENY)
			{
				std::string typeMask = (c->type == CC_ALLOW) ? "a" : "d";
				typeMask += c->host;
				oldBlocksByMask[typeMask] = c;
			}
		}
	}

	int blk_count = config_data.count("connect");
	if (blk_count == 0)
	{
		// No connect blocks found; make a trivial default block
		std::vector<KeyVal>* items;
		ConfigTag* tag = ConfigTag::create("connect", "<auto>", 0, items);
		items->push_back(std::make_pair("allow", "*"));
		config_data.insert(std::make_pair("connect", tag));
		blk_count = 1;
	}

	Classes.resize(blk_count);
	std::map<std::string, int> names;

	bool try_again = true;
	for(int tries=0; try_again; tries++)
	{
		try_again = false;
		ConfigTagList tags = ConfTags("connect");
		int i=0;
		for(ConfigIter it = tags.first; it != tags.second; ++it, ++i)
		{
			ConfigTag* tag = it->second;
			if (Classes[i])
				continue;

			ConnectClass* parent = NULL;
			std::string parentName = tag->getString("parent");
			if (!parentName.empty())
			{
				std::map<std::string,int>::iterator parentIter = names.find(parentName);
				if (parentIter == names.end())
				{
					try_again = true;
					// couldn't find parent this time. If it's the last time, we'll never find it.
					if (tries >= blk_count)
						throw CoreException("Could not find parent connect class \"" + parentName + "\" for connect block at " + tag->getTagLocation());
					continue;
				}
				parent = Classes[parentIter->second];
			}

			std::string name = tag->getString("name");
			std::string mask, typeMask;
			char type;

			if (tag->readString("allow", mask, false))
			{
				type = CC_ALLOW;
				typeMask = 'a' + mask;
			}
			else if (tag->readString("deny", mask, false))
			{
				type = CC_DENY;
				typeMask = 'd' + mask;
			}
			else if (!name.empty())
			{
				type = CC_NAMED;
				mask = name;
				typeMask = 'n' + mask;
			}
			else
			{
				throw CoreException("Connect class must have allow, deny, or name specified at " + tag->getTagLocation());
			}

			if (name.empty())
			{
				name = "unnamed-" + ConvToStr(i);
			}
			else
			{
				typeMask = 'n' + name;
			}

			if (names.find(name) != names.end())
				throw CoreException("Two connect classes with name \"" + name + "\" defined!");
			names[name] = i;

			ConnectClass* me = parent ?
				new ConnectClass(tag, type, mask, *parent) :
				new ConnectClass(tag, type, mask);

			me->name = name;

			me->registration_timeout = tag->getInt("timeout", me->registration_timeout);
			me->pingtime = tag->getInt("pingfreq", me->pingtime);
			std::string sendq;
			if (tag->readString("sendq", sendq))
			{
				// attempt to guess a good hard/soft sendq from a single value
				long value = atol(sendq.c_str());
				if (value > 16384)
					me->softsendqmax = value / 16;
				else
					me->softsendqmax = value;
				me->hardsendqmax = value * 8;
			}
			me->softsendqmax = tag->getInt("softsendq", me->softsendqmax);
			me->hardsendqmax = tag->getInt("hardsendq", me->hardsendqmax);
			me->recvqmax = tag->getInt("recvq", me->recvqmax);
			me->penaltythreshold = tag->getInt("threshold", me->penaltythreshold);
			me->commandrate = tag->getInt("commandrate", me->commandrate);
			me->fakelag = tag->getBool("fakelag", me->fakelag);
			me->maxlocal = tag->getInt("localmax", me->maxlocal);
			me->maxglobal = tag->getInt("globalmax", me->maxglobal);
			me->maxchans = tag->getInt("maxchans", me->maxchans);
			me->maxconnwarn = tag->getBool("maxconnwarn", me->maxconnwarn);
			me->limit = tag->getInt("limit", me->limit);
			me->nouserdns = tag->getBool("nouserdns", me->nouserdns);

			ClassMap::iterator oldMask = oldBlocksByMask.find(typeMask);
			if (oldMask != oldBlocksByMask.end())
			{
				ConnectClass* old = oldMask->second;
				oldBlocksByMask.erase(oldMask);
				old->Update(me);
				delete me;
				me = old;
			}
			Classes[i] = me;
		}
	}
}
Ejemplo n.º 2
0
/**
 * Controller helper routine.
 *
 * Wait for the next running slave to finish a task.  Note that if no
 * slaves are currently processing tasks, this routine will block forever!
 */
int ctrlWaitForSlave() {
    long result;
    MPI_Status status;
    MPI_Recv(&result, 1, MPI_LONG, MPI_ANY_SOURCE, TAG_RESULT, MPI_COMM_WORLD,
        &status);
    nRunningSlaves--;

    int slave = status.MPI_SOURCE;
    ctrlLogStamp() << "Task completed by slave " << slave << "." << std::endl;

    char triLabel[MAX_TRI_LABEL_LEN + 1];

    if (result == RESULT_OK || result == RESULT_HAS_NEW) {
        if (result == RESULT_HAS_NEW) {
            // The original packet label comes through first so we can
            // write it to the log.  It will come through again shortly
            // as part of the set of equivalent triangulations.
            MPI_Recv(triLabel, MAX_TRI_LABEL_LEN + 1, MPI_CHAR, slave,
                TAG_RESULT_DATA, MPI_COMM_WORLD, &status);
            ctrlLogStamp() << "WARNING: Has unseen equivalent: " << triLabel
                << std::endl;
            nHasNew++;
        }

        equivs.clear();

        NPacket* p;
        NTriangulation* tri;
        while (1) {
            MPI_Recv(triLabel, MAX_TRI_LABEL_LEN + 1, MPI_CHAR, slave,
                TAG_RESULT_DATA, MPI_COMM_WORLD, &status);
            if (*triLabel == 0)
                break;

            p = tree->findPacketLabel(triLabel);
            if (! p) {
                ctrlLogStamp() << "ERROR: Returned equivalent [" << triLabel
                    << "] not found." << std::endl;
                hasError = true;
            } else {
                tri = dynamic_cast<NTriangulation*>(p);
                if (! tri) {
                    ctrlLogStamp() << "ERROR: Returned equivalent [" << triLabel
                        << "] is not a triangulation!" << std::endl;
                    hasError = true;
                } else
                    equivs.insert(tri);
            }
        }
        ctrlLogStamp() << "Resulting set contains "
            << equivs.size() << " equivalent(s)." << std::endl;

        // In equivs we now have a list of all triangulations
        // equivalent to orig.

        // Is this an equivalence class we're already seen?
        TriSet::iterator tit;
        ClassMap::iterator cit, cit2;
        for (tit = equivs.begin(); tit != equivs.end(); tit++) {
            cit = eClass.find(*tit);
            if (cit != eClass.end())
                break;
        }
        if (tit != equivs.end()) {
            // We found an equivalence class.  Insert everything we
            // haven't seen yet, and merge the classes of everything
            // we have.
            int c, cOld;
            c = cit->second;
            for (tit = equivs.begin(); tit != equivs.end(); tit++) {
                cit = eClass.find(*tit);
                if (cit == eClass.end())
                    eClass.insert(std::make_pair(*tit, c));
                else if (cit->second != c) {
                    // Merge the two equivalence classes.
                    cOld = cit->second;
                    for (cit = eClass.begin(); cit != eClass.end(); cit++)
                        if (cit->second == cOld)
                            cit->second = c;
                    nClasses--;
                }
            }
        } else {
            // No such equivalence class.  Insert everything.
            int c = nextClass++;
            for (tit = equivs.begin(); tit != equivs.end(); tit++)
                eClass.insert(std::make_pair(*tit, c));
            nClasses++;
        }
    } else if (result == RESULT_NON_MINIMAL) {
        MPI_Recv(triLabel, MAX_TRI_LABEL_LEN + 1, MPI_CHAR, slave,
            TAG_RESULT_DATA, MPI_COMM_WORLD, &status);
        ctrlLogStamp() << "Non-minimal triangulation: " << triLabel
            << std::endl;

        nNonMin++;
    } else if (result == RESULT_ERR) {
        char errMsg[MAX_ERR_MSG_LEN + 1];
        MPI_Recv(errMsg, MAX_ERR_MSG_LEN + 1, MPI_CHAR, slave,
            TAG_RESULT_DATA, MPI_COMM_WORLD, &status);

        ctrlLogStamp() << "ERROR: " << errMsg << std::endl;
        hasError = true;
    } else {
        ctrlLogStamp() << "ERROR: Unknown result code " << result
            << " received from slave." << std::endl;
        hasError = true;
    }

    return slave;
}
Ejemplo n.º 3
0
/**
 * Main routine for the controller.
 */
int mainController() {
    NTriangulation* t;

    // Start logging.
    logger.open(logFile);
    if (! logger) {
        fprintf(stderr, "Could not open %s for writing.\n", logFile);
        return 1;
    }

    // Do it.
    for (NPacket* p = tree; p; p = p->nextTreePacket())
        if (p->type() == PACKET_TRIANGULATION) {
            nTris++;
            ctrlFarmTri(static_cast<NTriangulation*>(p));
        }

    // Kill off any slaves that never started working, since there are no
    // tasks left to give them.
    if (nRunningSlaves < nSlaves)
        for (int i = nRunningSlaves; i < nSlaves; i++)
            ctrlStopSlave(i + 1);

    // Wait for remaining slaves to finish.
    while (nRunningSlaves > 0)
        ctrlFarmTri(0);

    // Done!
    ctrlLogStamp() << "All slaves finished." << std::endl;

    // Write the summary of results.
    if (nClasses) {
        printf("EQUIVALENCE CLASSES:\n\n");

        if (outFile) {
            newTree = new NContainer();
            newTree->setLabel("Equivalence Classes");
        }

        int classNum = 1;
        std::string className;
        NContainer* classCnt = 0;

        ClassMap::iterator cit, cit2;
        int c;
        for (cit = eClass.begin(); cit != eClass.end(); cit++)
            if (cit->second >= 0) {
                // The first triangulation of a new equivalence class.
                c = cit->second;

                std::ostringstream s;
                s << "Class " << classNum << " : " <<
                    cit->first->homology().str();
                className = s.str();
                classNum++;

                printf("%s\n\n", className.c_str());
                if (outFile) {
                    classCnt = new NContainer();
                    classCnt->setLabel(className);
                    newTree->insertChildLast(classCnt);
                }

                // Find the triangulations in this class, and erase the
                // class as we go.
                for (cit2 = cit; cit2 != eClass.end(); cit2++)
                    if (cit2->second == c) {
                        printf("    %s\n",
                            cit2->first->label().c_str());
                        if (outFile) {
                            t = new NTriangulation(*(cit2->first));
                            t->setLabel(cit2->first->label());
                            classCnt->insertChildLast(t);
                        }

                        cit2->second = -1;
                    }

                printf("\n");
            }
    }

    printf("Final statistics:\n");
    printf("    Triangulations read:            %ld\n", nTris);
    printf("    Equivalence classes:            %ld\n", nClasses);
    printf("    Non-minimal triangulations:     %ld\n", nNonMin);
    printf("    Triangulations with new equivs: %ld\n", nHasNew);

    // Are we saving results?
    if (outFile && newTree) {
        ctrlLogStamp() << "Saving results to " << outFile << "." << std::endl;
        newTree->save(outFile);
    } else
        ctrlLogStamp() << "Not saving results." << std::endl;

    // Clean up and exit.
    if (newTree)
        delete newTree;

    if (hasError) {
        ctrlLogStamp() << "ERROR: One or more errors occurred; "
            "read back through the log for details." << std::endl;
        printf("\nERROR: One or more errors occurred.\n");
        printf(  "       Please read through the log file %s for details.\n",
            logFile);
    } else
        ctrlLogStamp() << "All done." << std::endl;

    return 0;
}
Ejemplo n.º 4
0
void processTree() {
    TriSet::iterator tit;
    ClassMap::iterator cit, cit2;
    int c, cOld;
    NTriangulation* t;

    for (NPacket* p = tree; p; p = p->nextTreePacket())
        if (p->type() == PACKET_TRIANGULATION) {
            // A triangulation to process.
            t = static_cast<NTriangulation*>(p);
            fprintf(stderr, "Processing %s ...\n", t->label().c_str());
            nTris++;

            nonMin = false;
            orig = static_cast<NTriangulation*>(p);
            equivs.clear();
            equivs.insert(orig);

            tryMovesUp(orig, argUp);

            if (nonMin) {
                allNonMin.push_back(orig);
                nNonMin++;
                continue;
            }

            // In equivs we now have a list of all triangulations
            // equivalent to orig.

            // Is this an equivalence class we're already seen?
            for (tit = equivs.begin(); tit != equivs.end(); tit++) {
                cit = eClass.find(*tit);
                if (cit != eClass.end())
                    break;
            }
            if (tit != equivs.end()) {
                // We found an equivalence class.  Insert everything we
                // haven't seen yet, and merge the classes of everything
                // we have.
                c = cit->second;
                for (tit = equivs.begin(); tit != equivs.end(); tit++) {
                    cit = eClass.find(*tit);
                    if (cit == eClass.end())
                        eClass.insert(std::make_pair(*tit, c));
                    else if (cit->second != c) {
                        // Merge the two equivalence classes.
                        cOld = cit->second;
                        for (cit = eClass.begin(); cit != eClass.end(); cit++)
                            if (cit->second == cOld)
                                cit->second = c;
                        nClasses--;
                    }
                }
            } else {
                // No such equivalence class.  Insert everything.
                c = nextClass++;
                for (tit = equivs.begin(); tit != equivs.end(); tit++)
                    eClass.insert(std::make_pair(*tit, c));
                nClasses++;
            }
        }

    // Finished progress reporting.
    fprintf(stderr, "\n");

    // Write the summary of results.
    if (! allNonMin.empty()) {
        printf("NON-MINIMAL TRIANGULATIONS:\n\n");
        for (std::list<NTriangulation*>::const_iterator it = allNonMin.begin();
                it != allNonMin.end(); it++)
            printf("    %s\n", (*it)->label().c_str());
        printf("\n");
    }

    if (nClasses) {
        printf("EQUIVALENCE CLASSES:\n\n");

        if (outFile) {
            newTree = new NContainer();
            newTree->setLabel("Equivalence Classes");
        }

        int classNum = 1;
        std::string className;
        NContainer* classCnt = 0;

        for (cit = eClass.begin(); cit != eClass.end(); cit++)
            if (cit->second >= 0) {
                // The first triangulation of a new equivalence class.
                c = cit->second;

                std::ostringstream s;
                s << "Class " << classNum << " : " <<
                  cit->first->homology().str();
                className = s.str();
                classNum++;

                printf("%s\n\n", className.c_str());
                if (outFile) {
                    classCnt = new NContainer();
                    classCnt->setLabel(className);
                    newTree->insertChildLast(classCnt);
                }

                // Find the triangulations in this class, and erase the
                // class as we go.
                for (cit2 = cit; cit2 != eClass.end(); cit2++)
                    if (cit2->second == c) {
                        printf("    %s\n",
                               cit2->first->label().c_str());
                        if (outFile) {
                            t = new NTriangulation(*(cit2->first));
                            t->setLabel(cit2->first->label());
                            classCnt->insertChildLast(t);
                        }

                        cit2->second = -1;
                    }

                printf("\n");
            }
    }

    printf("Final statistics:\n");
    printf("    Triangulations read:        %ld\n", nTris);
    printf("    Equivalence classes:        %ld\n", nClasses);
    printf("    New triangulations:         %ld\n", nNew);
    printf("    Non-minimal triangulations: %ld\n", nNonMin);
}