void GPUERT::deviceHandler(){
		m_devId = m_gfxMgr->createDeviceContext(m_devId);
		calculateMaxNodes(m_devId);
		initResources();

		m_constantsBagging.cb_baggingActivated = false;
		TimerPtr timerKernel = TimerPtr(new boost::timer);

		TimerPtr timer = TimerPtr(new boost::timer);
		TimerPtr timerTotal = TimerPtr(new boost::timer);

		m_internalNodes = 0, m_leafNodes = 0;
		int treesLeft = m_numTrees;
		int treesToLaunch = m_maxTreesPerIteration;
		int lastLaunch = 0;
		int checkSum = m_maxTreesPerIteration;
		int newNodes = m_maxTreesPerIteration;
		std::vector<int> checkVars(4,0);

		m_buildTime = 0;
		m_baggingTime = 0;
		m_classificationTime = 0;
		m_depth = 0;

		timerTotal->restart();
		int numIter = ceil(float(m_numTrees)/float(m_maxTreesPerIteration));
		for(unsigned int j=0; j<numIter; ++j){
			checkSum = treesToLaunch;
			newNodes = treesToLaunch;
			m_constants.cb_nodeBufferStart = 0;
			m_constants.cb_nodeIdFlip = 0;

			initResourceBatch(lastLaunch == treesToLaunch);
			lastLaunch = treesToLaunch;

			treesLeft -= treesToLaunch;
			timer->restart();
			for(unsigned int i=0; i<m_MaxDepth; ++i){
				if(i > m_depth)
					m_depth = i;

				assert(newNodes < m_maxNodesPerIteration);
				int nodeLimit = 10000;
				int innerNodes = newNodes;
				int numInnerIter = ceil(float(innerNodes)/float(nodeLimit));
				int launchCount = 0;

				m_constants.cb_availableNodes = newNodes;
				m_constants.cb_numFeatures = 0;
				timerKernel->restart();
				for(unsigned int k=0; k<m_numFeatures; ++k){
					innerNodes = newNodes;
					numInnerIter = ceil(float(innerNodes)/float(nodeLimit));
					launchCount = 0;

					// Best split kernel
					m_gfxMgr->setGPUBuffer(m_devId,m_setBufferIdsExFindSplit,m_setResourceTypesExFindSplit);
					m_gfxMgr->setGPUProgram(m_devId,m_gpuFunctionIds["RFP_ExFindSplit"]);

					innerNodes = newNodes;
					launchCount = 0;
					m_constants.cb_currentDepth = 0;
					for(unsigned int l=0; l<numInnerIter; ++l){
						launchCount = innerNodes > nodeLimit ? nodeLimit : innerNodes;
						
						m_gfxMgr->copyToGPU(m_devId,m_bufferIds["RFB_constants"],&ConstantUpdate(&m_constants,KID_ExtremeFindSplit),sizeof(m_constants));
						m_gfxMgr->launchComputation(m_devId,launchCount*thread_group_size,1,1);

						m_constants.cb_currentDepth += launchCount;
						innerNodes -= launchCount;
						if(innerNodes <= 0)
							break;
					}
					++m_constants.cb_numFeatures;
				}
				if(m_kernelSpecificTimings){
					m_gfxMgr->syncDevice(m_devId);
					m_kernelTimes[L"RFP_ExFindSplit"] += timerKernel->elapsed();
				}

				innerNodes = newNodes;
				launchCount = 0;
				m_constants.cb_currentDepth = 0;
				m_gfxMgr->setGPUBuffer(m_devId,m_setBufferIdsExMakeSplit,m_setResourceTypesExMakeSplit);
				m_gfxMgr->setGPUProgram(m_devId,m_gpuFunctionIds["RFP_ExMakeSplit"]);

				// Split data
				timerKernel->restart();
				for(unsigned int k=0; k<numInnerIter; ++k){
					launchCount = innerNodes > nodeLimit ? nodeLimit : innerNodes;
						
					m_gfxMgr->copyToGPU(m_devId,m_bufferIds["RFB_constants"],&ConstantUpdate(&m_constants,KID_ExtremeMakeSplit),sizeof(m_constants));
					m_gfxMgr->launchComputation(m_devId,launchCount*thread_group_size,1,1);

					m_constants.cb_currentDepth += launchCount;
					innerNodes -= launchCount;
					if(innerNodes <= 0)
						break;
				}
				if(m_kernelSpecificTimings){
					m_gfxMgr->syncDevice(m_devId);
					m_kernelTimes[L"RFP_ExMakeSplit"] += timerKernel->elapsed();
				}

				// Swap buffer to avoid unecessary copying
				int tmpBuffId = m_bufferIds["RFB_nodeIndices"];
				m_bufferIds["RFB_nodeIndices"] = m_bufferIds["RFB_nodeIndicesMirror"];
				m_bufferIds["RFB_nodeIndicesMirror"] = tmpBuffId;
				setBufferSettings();

				m_constants.cb_currentDepth = i;

				// Evaluate splits
				timerKernel->restart();
				m_gfxMgr->setGPUBuffer(m_devId,m_setBufferIdsExCreateNodes,m_setResourceTypesExCreateNodes);
				m_gfxMgr->copyToGPU(m_devId,m_bufferIds["RFB_constants"],&ConstantUpdate(&m_constants,KID_ExtremeCreateNodes),sizeof(m_constants));
				m_gfxMgr->setGPUProgram(m_devId,m_gpuFunctionIds["RFP_ExCreateNodes"]);
				m_gfxMgr->launchComputation(m_devId,newNodes,1,1);

				// Get continuation variables
				m_gfxMgr->copyFromGPU(m_devId,m_bufferIds["RFB_checkVariables"],&checkVars[0],checkVars.size()*sizeof(int));
				if(m_kernelSpecificTimings){
					m_gfxMgr->syncDevice(m_devId);
					m_kernelTimes[L"RFP_ExCreateNd"] += timerKernel->elapsed();
				}
			
				m_constants.cb_nodeBufferStart = checkSum;
				checkSum = checkVars[2];
				m_leafNodes += checkVars[3];
				newNodes = checkSum;
				m_internalNodes += checkSum;

				checkVars[1] = 0;
				checkVars[2] = 0;
				checkVars[3] = 0;
				m_gfxMgr->copyToGPU(m_devId,m_bufferIds["RFB_checkVariables"],&checkVars[0],checkVars.size()*sizeof(int));
				m_constants.cb_nodeIdFlip = (m_constants.cb_nodeIdFlip == 0) ? 1 : 0;

				if(newNodes <= 0)
					break;
			}
			m_buildTime += timer->elapsed();

			// Vote on test instances
			timer->restart();
			runClassificationProcess(treesToLaunch);
			m_classificationTime += timer->elapsed();

			if(m_saveModel)
				getResultsFromGPU();

			m_data->m_gui->setProgressBar(IDC_PROGRESSBAR_PROGRESS,100,(float(m_numTrees-treesLeft)/float(m_numTrees))*100);
			if(treesLeft != 0 && treesLeft < m_maxTreesPerIteration){
				treesToLaunch = treesLeft;
				m_maxTreesPerIteration = treesToLaunch;
			}
		}

		getVotesFromGPU();
		m_totalTime = timerTotal->elapsed();
		m_bar->wait();
	}
Example #2
0
SEXP fmelt(SEXP DT, SEXP id, SEXP measure, SEXP varfactor, SEXP valfactor, SEXP var_name, SEXP val_name, SEXP na_rm, SEXP drop_levels, SEXP print_out) {
    
    int i, j, k, nrow, ncol, protecti=0, lids=-1, lvalues=-1, totlen=0, counter=0, thislen=0;
    SEXP thiscol, ans, dtnames, ansnames, idcols, valuecols, levels, factorLangSxp;
    SEXP vars, target, idxkeep = R_NilValue, thisidx = R_NilValue;
    Rboolean isfactor=FALSE, isidentical=TRUE, narm = FALSE, droplevels=FALSE, verbose=FALSE;
    SEXPTYPE valtype=NILSXP;
    size_t size;

    if (TYPEOF(DT) != VECSXP) error("Input is not of type VECSXP, expected a data.table, data.frame or list");
    if (TYPEOF(valfactor) != LGLSXP) error("Argument 'value.factor' should be logical TRUE/FALSE");
    if (TYPEOF(varfactor) != LGLSXP) error("Argument 'variable.factor' should be logical TRUE/FALSE");
    if (TYPEOF(na_rm) != LGLSXP) error("Argument 'na.rm' should be logical TRUE/FALSE");
    if (LOGICAL(na_rm)[0] == TRUE) narm = TRUE;
    if (TYPEOF(print_out) != LGLSXP) error("Argument 'verbose' should be logical TRUE/FALSE");
    if (LOGICAL(print_out)[0] == TRUE) verbose = TRUE;
    // check for var and val names
    if (TYPEOF(var_name) != STRSXP || length(var_name) != 1) error("Argument 'variable.name' must be a character vector of length 1");
    if (TYPEOF(val_name) != STRSXP || length(val_name) != 1) error("Argument 'value.name' must be a character vector of length 1");

    // droplevels future feature request, maybe... should ask on data.table-help
    // if (!isLogical(drop_levels)) error("Argument 'drop.levels' should be logical TRUE/FALSE");
    // if (LOGICAL(drop_levels)[0] == TRUE) droplevels = TRUE;
    // if (droplevels && !narm) warning("Ignoring argument 'drop.levels'. 'drop.levels' should be set to remove any unused levels as a result of setting 'na.rm=TRUE'. Here there is nothing to do because 'na.rm=FALSE'");
    
    ncol = LENGTH(DT);
    nrow = length(VECTOR_ELT(DT, 0));
    if (ncol <= 0) {
        warning("ncol(data) is 0. Nothing to do, returning original data.table.");
        return(DT);
    }
    PROTECT(dtnames = getAttrib(DT, R_NamesSymbol)); protecti++;
    if (isNull(dtnames)) error("names(data) is NULL. Please report to data.table-help");
    
    vars = checkVars(DT, id, measure, verbose);
    PROTECT(idcols = VECTOR_ELT(vars, 0)); protecti++;
    PROTECT(valuecols = VECTOR_ELT(vars, 1)); protecti++; // <~~~ not protecting vars leads to  segfault (on big data)
    
    lids = length(idcols);
    lvalues = length(valuecols);
    
    // edgecase where lvalues = 0 and lids > 0
    if (lvalues == 0 && lids > 0) {
        if (verbose) Rprintf("length(measure.var) is 0. Edge case detected. Nothing to melt. Returning data.table with all 'id.vars' which are columns %s\n", CHAR(STRING_ELT(concat(dtnames, idcols), 0)));
        PROTECT(ansnames = allocVector(STRSXP, lids)); protecti++;
        PROTECT(ans = allocVector(VECSXP, lids)); protecti++;
        for (i=0; i<lids; i++) {
            SET_VECTOR_ELT(ans, i, VECTOR_ELT(DT, INTEGER(idcols)[i]-1));
            SET_STRING_ELT(ansnames, i, STRING_ELT(dtnames, INTEGER(idcols)[i]-1));
        }
        setAttrib(ans, R_NamesSymbol, ansnames);
        UNPROTECT(protecti);
        return(ans);
    }
    if (lvalues == 0 && lids == 0 && verbose)
        Rprintf("length(measure.var) and length(id.var) are both 0. Edge case detected. Nothing to melt.\n"); // <~~ don't think this will ever happen though with all the checks
    // set names for 'ans' - the output list
    PROTECT(ansnames = allocVector(STRSXP, lids+2)); protecti++;
    for (i=0; i<lids; i++) {
        SET_STRING_ELT(ansnames, i, STRING_ELT(dtnames, INTEGER(idcols)[i]-1));
    }
    SET_STRING_ELT(ansnames, lids, mkChar(CHAR(STRING_ELT(var_name, 0)))); // mkChar("variable")
    SET_STRING_ELT(ansnames, lids+1, mkChar(CHAR(STRING_ELT(val_name, 0)))); // mkChar("value")
    
    // get "value" column
    for (i=0; i<lvalues; i++) {
        thiscol = VECTOR_ELT(DT, INTEGER(valuecols)[i]-1);
        if (!isfactor && isFactor(thiscol)) isfactor = TRUE;
        if (TYPEOF(thiscol) > valtype) valtype = TYPEOF(thiscol);
    }
    if (isfactor && valtype != VECSXP) valtype = STRSXP;

    for (i=0; i<lvalues; i++) {
        thiscol = VECTOR_ELT(DT, INTEGER(valuecols)[i]-1);
        if (TYPEOF(thiscol) != valtype && isidentical) {
            if (!(isFactor(thiscol) && valtype == STRSXP)) {
                isidentical = FALSE; // for Date like column (not implemented for now)
                warning("All 'measure.vars are NOT of the SAME type. By order of hierarchy, the molten data value column will be of type '%s'. Therefore all measure variables that are not of type '%s' will be coerced to. Check the DETAILS section of ?melt.data.table for more on coercion.\n", type2char(valtype), type2char(valtype));
                break;
            }
        }
    }

    if (valtype == VECSXP && narm) {
        narm = FALSE;
        if (verbose) Rprintf("The molten data value type is a list. 'na.rm=TRUE' is therefore ignored.\n");
    }
    if (narm) {
        PROTECT(idxkeep = allocVector(VECSXP, lvalues)); protecti++;
        for (i=0; i<lvalues; i++) {
            SET_VECTOR_ELT(idxkeep, i, which_notNA(VECTOR_ELT(DT, INTEGER(valuecols)[i]-1)));
            totlen += length(VECTOR_ELT(idxkeep, i));
        }
    } else 
        totlen = nrow * lvalues;
    
    PROTECT(ans = allocVector(VECSXP, lids + 2)); protecti++;
    target = PROTECT(allocVector(valtype, totlen));
    for (i=0; i<lvalues; i++) {
        thiscol = VECTOR_ELT(DT, INTEGER(valuecols)[i]-1);
        if (isFactor(thiscol))
            thiscol = asCharacterFactor(thiscol);
        if (TYPEOF(thiscol) != valtype && !isFactor(thiscol)) {
            // thiscol = valtype == STRSXP ? PROTECT(coerce_to_char(thiscol, R_GlobalEnv)) : PROTECT(coerceVector(thiscol, valtype));
            // protecti++; // for now, no preserving of class attributes
            thiscol = PROTECT(coerceVector(thiscol, valtype)); protecti++;
        }
        size = SIZEOF(thiscol);
        if (narm) {
            thisidx = VECTOR_ELT(idxkeep, i);
            thislen = length(thisidx);
        }
        switch(valtype) {
            case VECSXP :
            if (narm) {
                for (j=0; j<thislen; j++)
                    SET_VECTOR_ELT(target, counter + j, VECTOR_ELT(thiscol, INTEGER(thisidx)[j]-1));
            } else {
                for (j=0; j<nrow; j++) SET_VECTOR_ELT(target, i*nrow + j, VECTOR_ELT(thiscol, j));
            }
            break;
            case STRSXP :
            if (narm) {
                for (j=0; j<thislen; j++)
                    SET_STRING_ELT(target, counter + j, STRING_ELT(thiscol, INTEGER(thisidx)[j]-1));
            } else {
                for (j=0; j<nrow; j++) SET_STRING_ELT(target, i*nrow + j, STRING_ELT(thiscol, j));
            }
            break;
            case REALSXP : 
            if (narm) {
                for (j=0; j<thislen; j++)
                    REAL(target)[counter + j] = REAL(thiscol)[INTEGER(thisidx)[j]-1];
            } else {
                memcpy((char *)DATAPTR(target)+i*nrow*size, (char *)DATAPTR(thiscol), nrow*size);
            }
            break;
            case INTSXP : 
            if (narm) {
                for (j=0; j<thislen; j++)
                    INTEGER(target)[counter + j] = INTEGER(thiscol)[INTEGER(thisidx)[j]-1];
            } else {
                memcpy((char *)DATAPTR(target)+i*nrow*size, (char *)DATAPTR(thiscol), nrow*size);
            }
            break;
            case LGLSXP :
            if (narm) {
                for (j=0; j<thislen; j++)
                    LOGICAL(target)[counter + j] = LOGICAL(thiscol)[INTEGER(thisidx)[j]-1];
            } else {
                memcpy((char *)DATAPTR(target)+i*nrow*size, (char *)DATAPTR(thiscol), nrow*size);
            }
            break;
            default : error("Unknown column type '%s' for column '%s' in 'data'", type2char(TYPEOF(thiscol)), CHAR(STRING_ELT(dtnames, INTEGER(valuecols)[i]-1)));
        }
        if (narm) counter += thislen;
        // if (isidentical && valtype != VECSXP) // for now, no preserving of class attributes
        //     setAttrib(target, R_ClassSymbol, getAttrib(VECTOR_ELT(DT, INTEGER(valuecols)[0]-1), R_ClassSymbol)); // for Date like column
    }
    // check for factor
    if (LOGICAL(valfactor)[0] == TRUE && valtype == VECSXP) warning("argument 'value.factor' ignored because 'value' column is a list\n");
    if (LOGICAL(valfactor)[0] == TRUE && valtype != VECSXP) {
        PROTECT(factorLangSxp = allocList(2));
        SET_TYPEOF(factorLangSxp, LANGSXP);
        SETCAR(factorLangSxp, install("factor"));
        SETCAR(CDR(factorLangSxp), target);
        SET_VECTOR_ELT(ans, lids+1, eval(factorLangSxp, R_GlobalEnv)); // last column
        UNPROTECT(1); // factorLangSxp
    } else 
        SET_VECTOR_ELT(ans, lids+1, target);    
    UNPROTECT(1); // target
    
    // get "variable" column
    counter = 0, i=0;
    target = PROTECT(allocVector(INTSXP, totlen));
     for (j=0; j<lvalues; j++) {
        if (narm) {
            thislen = length(VECTOR_ELT(idxkeep, j));
            for (k=0; k<thislen; k++)
                INTEGER(target)[counter + k] = i+1;
            counter += thislen;
            if (thislen > 0 || !droplevels) i++;
        } else {
            for (k=0; k<nrow; k++)
                INTEGER(target)[nrow*j + k] = j+1;
        }
    }
    setAttrib(target, R_ClassSymbol, mkString("factor"));
    if (narm && droplevels) {
        counter = 0;
        for (j=0; j<lvalues; j++) {
            if (length(VECTOR_ELT(idxkeep, j)) > 0) counter++;
        }
    } else counter = lvalues;
    levels = PROTECT(allocVector(STRSXP, counter));
    i = 0;
    for (j=0; j<lvalues; j++) {
        if (narm && droplevels) {
            if (length(VECTOR_ELT(idxkeep, j)) > 0)
                SET_STRING_ELT(levels, i++, STRING_ELT(dtnames, INTEGER(valuecols)[j]-1));
        } else 
            SET_STRING_ELT(levels, j, STRING_ELT(dtnames, INTEGER(valuecols)[j]-1));
    }
    setAttrib(target, R_LevelsSymbol, levels);
    UNPROTECT(1); // levels
    if (LOGICAL(varfactor)[0] == FALSE)
        target = asCharacterFactor(target);
    SET_VECTOR_ELT(ans, lids, target);
    UNPROTECT(1); // target
    
    // generate idcols (left part)
    for (i=0; i<lids; i++) {
        counter = 0;
        thiscol = VECTOR_ELT(DT, INTEGER(idcols)[i]-1);
        size = SIZEOF(thiscol);
        target = PROTECT(allocVector(TYPEOF(thiscol), totlen)); 
        switch(TYPEOF(thiscol)) {
            case REALSXP :
            if (narm) {
                for (j=0; j<lvalues; j++) {
                    thisidx = PROTECT(VECTOR_ELT(idxkeep, j));
                    thislen = length(thisidx);
                    for (k=0; k<thislen; k++)
                        REAL(target)[counter + k] = REAL(thiscol)[INTEGER(thisidx)[k]-1];
                    counter += thislen;
                    UNPROTECT(1); // thisidx
                } 
            } else { 
                for (j=0; j<lvalues; j++)
                    memcpy((char *)DATAPTR(target)+j*nrow*size, (char *)DATAPTR(thiscol), nrow*size);
            }
            break;
            case INTSXP :
            if (narm) {
                for (j=0; j<lvalues; j++) {
                    thisidx = PROTECT(VECTOR_ELT(idxkeep, j));
                    thislen = length(thisidx);
                    for (k=0; k<thislen; k++)
                        INTEGER(target)[counter + k] = INTEGER(thiscol)[INTEGER(thisidx)[k]-1];
                    counter += thislen;
                    UNPROTECT(1); // thisidx
                } 
            } else {
                for (j=0; j<lvalues; j++)
                    memcpy((char *)DATAPTR(target)+j*nrow*size, (char *)DATAPTR(thiscol), nrow*size);
            }
            break;
            case LGLSXP :
            if (narm) {
                for (j=0; j<lvalues; j++) {
                    thisidx = PROTECT(VECTOR_ELT(idxkeep, j));
                    thislen = length(thisidx);
                    for (k=0; k<thislen; k++)
                        LOGICAL(target)[counter + k] = LOGICAL(thiscol)[INTEGER(thisidx)[k]-1];
                    counter += thislen;
                    UNPROTECT(1); // thisidx
                } 
            } else {
                for (j=0; j<lvalues; j++)
                    memcpy((char *)DATAPTR(target)+j*nrow*size, (char *)DATAPTR(thiscol), nrow*size);
            }
            break;
            case STRSXP :
            if (narm) {
                for (j=0; j<lvalues; j++) {
                    thisidx = PROTECT(VECTOR_ELT(idxkeep, j));
                    thislen = length(thisidx);
                    for (k=0; k<thislen; k++)
                        SET_STRING_ELT(target, counter + k, STRING_ELT(thiscol, INTEGER(thisidx)[k]-1));
                    counter += thislen;
                    UNPROTECT(1); // thisidx
                } 
            } else {
                // SET_STRING_ELT for j=0 and memcpy for j>0, WHY?
                // From assign.c's memcrecycle - only one SET_STRING_ELT per RHS item is needed to set generations (overhead)
                for (k=0; k<nrow; k++) SET_STRING_ELT(target, k, STRING_ELT(thiscol, k));
                for (j=1; j<lvalues; j++)
                    memcpy((char *)DATAPTR(target)+j*nrow*size, (char *)DATAPTR(target), nrow*size);
            }
            break;
            case VECSXP :
            for (j=0; j<lvalues; j++) {
                for (k=0; k<nrow; k++) {
                    SET_VECTOR_ELT(target, j*nrow + k, VECTOR_ELT(thiscol, k));
                }
            }
            break;
            default : error("Unknown column type '%s' for column '%s' in 'data'", type2char(TYPEOF(thiscol)), CHAR(STRING_ELT(dtnames, INTEGER(idcols)[i]-1)));
        }
        copyMostAttrib(thiscol, target); // all but names,dim and dimnames. And if so, we want a copy here, not keepattr's SET_ATTRIB.
        SET_VECTOR_ELT(ans, i, target);
        UNPROTECT(1); // target
    }
                
    setAttrib(ans, R_NamesSymbol, ansnames);
    UNPROTECT(protecti);
    return(ans);
}
Example #3
0
int main(int argc, char* argv[]) {
  int sock;                        //Socket descriptor
  struct sockaddr_in servAddr; //Echo server address
  char* lineBuffer;                //String to send to server
  char* tempBuffer;                //Temporary Buffer for Storage
  char recvBuffer[RCVBUFSIZE];
  int bytesRcvd, totalBytesRcvd;   //Bytes read in single recv & total
  FILE* in;                        //MEClient.txt, if passed
  FILE* out;                       //MEClient.log, logfile of correspondance
  struct hostent* he;              //Used to get IP information from hostname
  int usrAuth = -1;
  char* token;
  int i, doneSig;

  if (argc < 2) { //Test for correct number of arguments
    fprintf(stderr,"Usage: %s <Server Machine Name> [MEClient.txt]\n", argv[0]);
    exit(1);
  }

  if (argc == 3)              //If file is passed in
    in = fopen(argv[2], "r"); //Create a file descriptor for the input file
  else
    in = stdin;               //Otherwise, use Standard In

  out = fopen("MEClient.log", "w"); //Open log file

  if (in == NULL)
    DieWithError("Error Opening File for Reading");

  //Construct the Server Address Structure
  memset(&servAddr, 0, sizeof(servAddr)); //Zero out structure
  if((he = gethostbyname(argv[1])) == NULL)
    DieWithError("Error resolving Server IP");
  memcpy(&servAddr.sin_addr, he->h_addr_list[0], he->h_length); //Set address
  servAddr.sin_family = AF_INET;                                //Family
  servAddr.sin_port = htons(1100);                              //Well-Known Port

  lineBuffer = (char*) malloc(LINEBUFSIZE);
  tempBuffer = (char*) malloc(LINEBUFSIZE);
  token      = (char*) malloc(LINEBUFSIZE);
  while(1) { //Run forever; quit function will eventually end the program
    fgets(lineBuffer, LINEBUFSIZE, in); //Gets line from MEClient.txt
    fprintf(out, lineBuffer);            //Write command to log file
    strncpy(tempBuffer, lineBuffer, LINEBUFSIZE);
    token = strtok(tempBuffer, " ");

    //Login Command
    if(strncasecmp(token, "login", 5)==0) {
      token = strtok(NULL, " ");   //Token is user's name

      //Log in user, and set authorization level
      if(strncmp(token, "FEMA", 4)==0 || strncmp(token, "Query", 5)==0) {
        if(usrAuth != -1)
          puts("ERROR: User already logged in");
        else{
          //Create a reliable, stream socket using TCP
          if ((sock = socket(AF_INET, SOCK_STREAM, 0))<0)
            DieWithError("socket() failed");
          //Establish a connection to the ME Server
          if (connect(sock, (struct sockaddr*)&servAddr, sizeof(servAddr))<0)
            DieWithError("connect() failed");
          //Return 1 for FEMA, 0 for Query
          usrAuth = ((strncmp(token, "FEMA", 4)==0) ? 1 : 0);

          if (send(sock, lineBuffer, RCVBUFSIZE, 0)!= RCVBUFSIZE)
            DieWithError("send() sent a different nuber of bytes than expected");
          bytesRcvd = 0;
          totalBytesRcvd = 0;
          while (totalBytesRcvd < RCVBUFSIZE) {
            //Receive up to the buffer size
            if ((bytesRcvd = recv(sock, recvBuffer, RCVBUFSIZE, 0))<=0)
              DieWithError("recv() failed or connection closed prematurely");
            totalBytesRcvd += bytesRcvd; //Keep tally of total bytes
          }
          printf(recvBuffer); //Print server's response
          fprintf(out, recvBuffer); //Write to log file
        }
      }
      else
        puts("ERROR: Invalid login name");
    }

    //Add / Update Command
    else if ((strncasecmp(token, "add", 3)==0 || strncasecmp(token, "update", 6)==0) && usrAuth==1) {
      strcpy(tempBuffer, lineBuffer);
      if (checkVars(tempBuffer, 5)) {
        if (send(sock, lineBuffer, RCVBUFSIZE, 0)!= RCVBUFSIZE)
          DieWithError("send() sent a different nuber of bytes than expected");
        bytesRcvd = 0;
        totalBytesRcvd = 0;
        while (totalBytesRcvd < RCVBUFSIZE) {
          //Receive up to the buffer size
          if ((bytesRcvd = recv(sock, recvBuffer, RCVBUFSIZE, 0))<=0)
            DieWithError("recv() failed or connection closed prematurely");
          totalBytesRcvd += bytesRcvd; //Keep tally of total bytes
        }
        printf(recvBuffer); //Print server's response
        fprintf(out, recvBuffer); //Write to log file
      }
      else
        puts("ERROR: Wrong number of variables.");
    }

    //Remove Command
    else if (strncasecmp(token, "remove", 6)==0 && usrAuth==1) {
      if (send(sock, lineBuffer, RCVBUFSIZE, 0)!= RCVBUFSIZE)
        DieWithError("send() sent a different nuber of bytes than expected");
      bytesRcvd = 0;
      totalBytesRcvd = 0;
      while (totalBytesRcvd < RCVBUFSIZE) {
        //Receive up to the buffer size
        if ((bytesRcvd = recv(sock, recvBuffer, RCVBUFSIZE, 0))<=0)
          DieWithError("recv() failed or connection closed prematurely");
        totalBytesRcvd += bytesRcvd; //Keep tally of total bytes
      }
      printf(recvBuffer); //Print server's response
      fprintf(out, recvBuffer); //Write to log file
    }

    //Find / List / Locate Command
    else if ((strncasecmp(token, "find", 4)==0 || strncasecmp(token, "list", 4)==0 || strncasecmp(token, "locate", 6)==0) && usrAuth!=-1) {
      strcpy(tempBuffer, lineBuffer);
      if(strncasecmp(token, "locate", 6)==0 && checkTooMany(tempBuffer, 2)==1) {
        puts("ERROR: Wrong number of variables.");
        fprintf(out, "ERROR: Wrong number of variables.\n");
        continue;
      }

      if (send(sock, lineBuffer, RCVBUFSIZE, 0)!= RCVBUFSIZE)
        DieWithError("send() sent a different nuber of bytes than expected");

      doneSig = 1;
      while(doneSig) {
        bytesRcvd = 0;
        totalBytesRcvd = 0;
        while (totalBytesRcvd < RCVBUFSIZE) {
          //Receive up to the buffer size
          if ((bytesRcvd = recv(sock, recvBuffer, RCVBUFSIZE, 0))<=0)
            DieWithError("recv() failed or connection closed prematurely");
          totalBytesRcvd += bytesRcvd; //Keep tally of total bytes
        }
        if(strcasecmp(recvBuffer, "S: Search Complete.") == 0)
          doneSig = 0; //Done Receiving
        else {
          printf(recvBuffer); //Print server's response
          fprintf(out, recvBuffer); //Write to log file
        }
      }
    }

    //Quit Command
    else if (strncasecmp(token, "quit", 4)==0 && usrAuth!=-1) {
      token = strtok(NULL, " ");        //Token is EOF marker (if passed)
      usrAuth = -1;                     //Reset authentication level

      if (send(sock, lineBuffer, RCVBUFSIZE, 0)!= RCVBUFSIZE)
        DieWithError("send() sent a different nuber of bytes than expected");

      for(i=0; i<3; i++) { //Receive and print two messages from the server
        bytesRcvd = 0;
        totalBytesRcvd = 0;
        while (totalBytesRcvd < RCVBUFSIZE) {
          //Receive up to the buffer size
          if ((bytesRcvd = recv(sock, recvBuffer, RCVBUFSIZE, 0))<=0)
            DieWithError("recv() failed or connection closed prematurely");
          totalBytesRcvd += bytesRcvd; //Keep tally of total bytes
        }
        printf(recvBuffer);
        fprintf(out, recvBuffer); //Write to log file
      }

      if (token != NULL && strncmp(token, "EOF", 3)==0) {

      for(i=0; i<2; i++) { //Receive and print two messages from the server
        bytesRcvd = 0;
        totalBytesRcvd = 0;
        while (totalBytesRcvd < RCVBUFSIZE) {
          //Receive up to the buffer size
          if ((bytesRcvd = recv(sock, recvBuffer, RCVBUFSIZE, 0))<=0)
            DieWithError("recv() failed or connection closed prematurely");
          totalBytesRcvd += bytesRcvd; //Keep tally of total bytes
        }
        printf(recvBuffer);
        fprintf(out, recvBuffer); //Write to log file
      }

        close(sock);
        fclose(in);
        fclose(out);
        exit(0); //If EOF string passed, we're done
      }
      else
        close(sock);
    }

    else {                       //User either entered a bad command, or they
      puts("ERROR: Bad Command");//had the wrong authentication level
      fprintf(out, "ERROR: Bad Command\n");
    }
  }
}