Example #1
0
void Globber::UpdateIndex(const vector<ohfileinfo>& files, const path& indexpath, const opParameters& p )
{
	bool bForce = p.Force;

	if( !exists(indexpath) )
		bForce = true;

	//we need to determine if 
	//iterate over all files
	bool bNewer = false;
	if(!bForce)
	{
		time_t indextime = last_write_time(indexpath);
		time_t opcpptime = opPlatform::GetOpCppTimeStamp();

		for(size_t i = 0; i < files.size(); i++)
		{
			time_t ohtime = last_write_time(files[i].ohfilepath);
			
			time_t generatedtime = bheader? 
								   last_write_time(files[i].oohfilepath):
								   last_write_time(files[i].ocppfilepath);

			//the index condition is the important one
			//the header condition is not so important - that just says that an oh file wasn't build (oops)
			if( indextime < opcpptime )
			{
				if(p.Verbose)
					Log(opPlatform::GetOpCppExecutableName() + " newer than index, forcing glob");

				bNewer = true;
				break;
			}

			if( generatedtime > ohtime && generatedtime > indextime)
			{
				bNewer = true;
				break;
			}
		}
	}

	string indexname = bheader?"oohindex":"ocppindex";

	if(bNewer || bForce)
	{
		if(p.Verbose)
			Log(string("Globber: ") + indexname + " out of date, rebuilding...");
		WriteIndex<bheader>(files,indexpath,p);
	}
	else
	{
		if(p.Verbose)
			Log(string("Globber: ") + indexname + " up to date, skipping...");
	}
}
Example #2
0
void Rule::resolve()
{
    if (isResolved_)
        return;
    bool outOfDate = !exists(target_);
    auto ts = outOfDate ? 0 : last_write_time(target_);
    for (auto &d: dependencies_)
    {
        d->resolve();
        outOfDate = outOfDate || !exists(d->target_) || (ts < last_write_time(d->target_));
    }
    if (outOfDate)
        internalResolve();
    isResolved_ = true;
}
Example #3
0
// TODO: dependencies does track file paths, only names - this doesn't matter
// really.
bool opDriver::CheckDependencies() {
    const opParameters& p = opParameters::Get();

    bool bResult = false;

    int size = p.Depend.size();
    for (int i = 0; i < size; i++) {
        opString filestring = p.Depend[i];

        path filepath = filestring.GetString();

        if (exists(filepath)) {
            opString targetfile = filepath.leaf().c_str();

            targetfile += ".target";

            path targetpath =
                p.GeneratedDirectory.GetString() / targetfile.GetString();

            // if it doesn't exist we need to create it
            if (!exists(targetpath)) {
                create_directories(p.GeneratedDirectory.GetString());

                // just create a new empty target file
                boost::filesystem::ofstream target(targetpath);
                target << "target file used for opC++ -dependencies";
                bResult = true;
                continue;
            }

            // now check for the time
            time_t filetime = last_write_time(filepath);
            time_t targettime = last_write_time(targetpath);

            if (filetime > targettime) {
                // just create a new empty target file
                boost::filesystem::ofstream target(targetpath);
                target << "target file used for opC++ -dependencies";
                bResult = true;
                continue;
            }
        }
    }

    return bResult;
}
Example #4
0
	int64_t file_mod_time(const std::string& fname)
	{
		path p(fname);
		if(is_regular_file(p)) {
			return static_cast<int64_t>(last_write_time(p));
		} else {
			return 0;
		}
	}
Example #5
0
void SFTWorker::finishFile()
{
	m_hFh.close();

	std::string file = m_pCurFile->getFullPath();
	gcString str("{0}", m_pCurFile->getTimeStamp());

	try
	{
		ptime t(from_iso_string(str));
		bfs::path spath(file);

		tm pt_tm = to_tm(t);
		last_write_time(spath, mktime(&pt_tm));
	}
	catch (...)
	{
		Warning(gcString("Failed to change {0} time stamp to {1}.\n", m_pCurFile->getName(), str));
	}

	safe_delete(m_pBzs);

	std::string hash = "Failed to generate hash";

#ifdef NIX
	//struct stat s;
	bool isWinExe = false;
	
	if (file.size() > 4)
	{
		std::string lastFour(file.end() - 4, file.end());
		std::transform(lastFour.begin(), lastFour.end(), lastFour.begin(), ::toupper);
		if (lastFour == ".EXE")
			isWinExe = true;
	}
	
	//( && stat(file.c_str(), &s) == 0) 
	
	bool isExecutable = HasAnyFlags(m_pCurFile->getFlags(), MCFCore::MCFFileI::FLAG_XECUTABLE);

	if (isExecutable || isWinExe)
		chmod(file.c_str(), (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH));
#endif

	if (m_pCurFile->isZeroSize() || m_pCurFile->hashCheckFile(&hash))
	{
		m_pCT->endTask(m_uiId, BaseMCFThread::SF_STATUS_COMPLETE);
	}
	else
	{
		Warning(gcString("Hash check failed for file [{0}]: Cur: {1} !=  Should: {2}\n", m_pCurFile->getName(), hash, m_pCurFile->getCsum()));
		m_pCT->endTask(m_uiId, BaseMCFThread::SF_STATUS_HASHMISSMATCH);
	}
}
Example #6
0
bool opDriver::CodeCurrent() {
    // foreach dialect we have...
    // and all dependencies, are we up to date?
    // are we up to date?
    opSet<path>::iterator it = OhFiles.begin();
    opSet<path>::iterator end = OhFiles.end();

    time_t opcpptime = opPlatform::GetOpCppTimeStamp();

    while (it != end) {
        const path& ohfilepath = *it;

        // get the output path
        opString filestring = GetOutputPath(opParameters::Get(), ohfilepath);

        path oohfilepath = (filestring + ".ooh").GetString();
        path ocppfilepath = (filestring + ".ocpp").GetString();

        if (!exists(oohfilepath)) return false;

        if (!exists(ocppfilepath)) return false;

        time_t ohtime = last_write_time(ohfilepath);
        time_t oohtime = last_write_time(oohfilepath);
        time_t ocpptime = last_write_time(ocppfilepath);

        if (ohtime > oohtime || ohtime > ocpptime || opcpptime > oohtime ||
            opcpptime > ocpptime)
            return false;

        // now check dependencies
        FileNode file;
        file.LoadDependencies(filestring + ".depend");

        if (file.IsDependencyNewer(oohtime)) return false;

        ++it;
    }

    return true;
}
Example #7
0
int
chkAndResetRule( rsComm_t *rsComm ) {
//    char *configDir;
//    char rulesFileName[MAX_NAME_LEN];
    int status = 0;
    uint mtime;

//    configDir = getConfigDir();
//    snprintf( rulesFileName, MAX_NAME_LEN, "%s/reConfigs/core.re",
//              configDir );

    std::string re_full_path;
    irods::error ret = irods::get_full_path_for_config_file( "core.re", re_full_path );
    if ( !ret.ok() ) {
        irods::log( PASS( ret ) );
        return ret.code();
    }

    path p( re_full_path );
    if ( !exists( p ) ) {
        status = UNIX_FILE_STAT_ERR - errno;
        rodsLog( LOG_ERROR,
                 "chkAndResetRule: unable to read rule config file %s, status = %d",
                 re_full_path.c_str(), status );
        return ( status );
    }

    mtime = ( uint ) last_write_time( p );

    if ( CoreIrbTimeStamp == 0 ) {
        /* first time */
        CoreIrbTimeStamp = mtime;
        return ( 0 );
    }

    if ( mtime > CoreIrbTimeStamp ) {
        /* file has been changed */
        rodsLog( LOG_NOTICE,
                 "chkAndResetRule: reconf file %s has been changed. re-initializing",
                 re_full_path.c_str() );
        CoreIrbTimeStamp = mtime;
        clearCoreRule();
        /* The shared memory cache may have already been updated, do not force reload */
        status = initRuleEngine( RULE_ENGINE_TRY_CACHE, NULL, reRuleStr, reFuncMapStr, reVariableMapStr );
        if ( status < 0 ) {
            rodsLog( LOG_ERROR,
                     "chkAndResetRule: initRuleEngine error, status = %d", status );
        }
    }
    return status;
}
Example #8
0
time_t opDriver::GetDialectTimestamp(const opParameters& p) {
    // find the maximum timestamp on the dialects (input dialects, since we
    // output every time)
    time_t maxtime = 0;

    for (int i = 0; i < p.Dialects.size(); i++) {
        // TODO - use generated dialects instead..
        path filepath = p.Dialects[i].GetString();

        // doh file exists?
        if (exists(filepath)) {
            maxtime = max(last_write_time(filepath), maxtime);
        }
    }

    return maxtime;
}
Example #9
0
time_t opDriver::GetGeneratedDialectTimestamp(const opParameters& p) {
    // find the maximum timestamp on the dialects (input dialects, since we
    // output every time)
    time_t maxtime = 0;

    for (int i = 0; i < p.Dialects.size(); i++) {
        opString filestring = GetOutputPath(p, p.Dialects[i].GetString());

        path filepath = (filestring + ".ooh").GetString();

        // doh file exists?
        if (exists(filepath)) {
            maxtime = max(last_write_time(filepath), maxtime);
        }
    }

    return maxtime;
}
Example #10
0
  /** \param  path      the path to monitor
   *  \param  callback  the callback to notify if the path changes
   *  \param  call_now  will invoke the callback now
   */
  void insert(const std::string & path,
              const callback_t & callback,
              bool call_now = false )
  {
    boost::mutex::scoped_lock lock(m_file_mutex);

    m_file_callback[path] = callback;

    boost::filesystem::path p(path);
    std::time_t lw = last_write_time(p);
    if (lw != 0)
    {
      m_file_modified[path] = std::make_pair(lw, lw);
      if ( call_now )
        callback(CHANGED, path);
    }
    else
    {
      m_file_modified.erase(path);
      if ( call_now )
        callback(DELETED, path);
    }
  }
Example #11
0
file_cache::file::file(const std::string& name, bool read_from_disk) {
    path p(name);
    if (exists(p)) {
        if (is_regular_file(p)) {
            m_size = file_size(p);
            m_time = last_write_time(p);
            if (read_from_disk) {
                std::ifstream is(name, std::ifstream::binary);
                if (is) {
                    m_data.reserve(m_size);
                    std::copy(std::istreambuf_iterator<char>(is), std::istreambuf_iterator<char>(),
                              std::back_inserter(m_data));
                    m_good = true;
                } else {
                    log_err("can't open file " << name);
                }
            }
        } else {
            log_err(name << " is no file");
        }
    } else {
        log_err(name << " does not exists");
    }
}
Example #12
0
int bmx_filesystem_filetime(BBString * path) {
	boost::filesystem::path p(bbStringToPath(path));

	return last_write_time(p);
}
Example #13
0
/**
  * scan
  * 
  * starts from the given node and iterates through all
  * child directories and builds vectors of all file
  * and directory nodes in the FS
  * 
  * @param pnode pointer to DirInfo node to scan
  */
bool FileSystem::scan(DirInfo* pnode) {
    debugPrint("Scanning Node: " + pnode->getPath());

    // Check if given path exists
    if ( !boost::filesystem::exists( pnode->getPath() ) ) {
        cout << pnode->getPath() << " doesn't exist" << endl;
        return false;
    }

    if (pnode->isHidden()) {
        return false;
    }

    // Create a boost directory iterator
    boost::filesystem::directory_iterator end_itr;
    try {

    for ( boost::filesystem::directory_iterator itr( pnode->getPath() ); 
          itr != end_itr; 
          ++itr ) {

        // Is iterated object a directory
        if ( is_directory(itr->status()) ) {

            DirInfo* dir = new DirInfo(itr->path().filename().string(), pnode);

            // Keeps track of node to deconstruct pointer
            allNodes.push_back(dir);
            // All directories list (for quick dir operations)
            allDirs.push_back(dir);
            // Add this node to it's parent children list
            pnode->addChild(dir);

            // Create a boost path object to extract fs info
            boost::filesystem::path p(dir->getPath());
            dir->setModifyTime( last_write_time(p) );
            dir->isDir(true);

            // Recursively scan dirs
            scan(dir);

            // directory size is only available after all dir and files add their
            // sizes to their parent dirs to be added here
            pnode->addSize(dir->getSize());

        // If iterated object is not directory, then it must be a file
        } else {

            FileInfo* file = new FileInfo(itr->path().filename().string(), pnode);

            // Keeps track of node to deconstruct pointer
            allNodes.push_back(file);
            // All files list (for quick file operations)
            allFiles.push_back(file);
            // Add this node to it's parent children list
            pnode->addChild(file);

            // Create a boost path object to extract fs info
            boost::filesystem::path p(file->getPath());
            try {
                file->setSize( file_size(p) );
            } catch (boost::filesystem::filesystem_error err) {
                file->setSize( 0 );
            }

            try {
                file->setModifyTime( last_write_time(p) );
            } catch (boost::filesystem::filesystem_error err) {
                file->setModifyTime( 0 );
            }
            // Update parent size
            file->getParent()->addSize(file->getSize());

        }
    }
    } catch (boost::filesystem::filesystem_error) {
        cout << "Cannot open file: " << pnode->getPath() << ". Permission denied!" << endl;
    }
 
    return true;
}
Example #14
0
bool opDriver::DialectModeFile(const opParameters& p, const path& filename) {
    double totaltimestart = opTimer::GetTimeSeconds();

    opError::Clear();

    // output compiling -file- to std out
    if (!p.Silent) {
        Log(opString("Reading dialect ") + filename.string() + " ...");
    }

    // load the oh file, it will be tracked elsewhere
    DialectFileNode* filenode = FileNode::Load<DialectFileNode>(
        filename.string(), opScanner::SM_DialectMode);

    // filenode should be non-null even if there were errors
    assert(filenode);

    if (opError::HasErrors()) {
        if (p.PrintTree) filenode->PrintTree(filename.string());

        opError::Print();

        return false;
    }

    // check for file not found error
    // 	if (filenode->FileNotFoundError())
    // 	{
    // 		opError::Print();
    //
    // 		//this is ambiguous doh!
    // 		//TODO: fix this to be specific
    // 		Log(opString("Cannot open input file \"") + filename.string() +
    // "\"!"); 		return false;
    // 	}
    //
    // 	//check for scanner error
    // 	if(filenode->ScanError())
    // 	{
    // 		opError::Print();
    //
    // 		if (p.Verbose)
    // 		{
    // 			Log("Compilation failed!");
    // 			Log("");
    // 		}
    //
    // 		return false;
    // 	}
    //
    // 	//check for parser errors
    // 	if(filenode->AnyErrors())
    // 	{
    // 		//print the tree (failure)
    // 		if (p.PrintTree)
    // 			filenode->PrintTree(filename.string());
    //
    // 		opError::Print();
    //
    // 		if (p.Verbose)
    // 		{
    // 			Log("Compilation failed!");
    // 			Log("");
    // 		}
    //
    // 		return false;
    // 	}

    opString spath = GetOutputPath(p, filename);
    path oohpath = (spath + ".ooh").GetString();
    path ocpppath = (spath + ".ocpp").GetString();
    path outputpath = oohpath.branch_path();

    if (!exists(outputpath)) create_directories(outputpath);

    // handle dialect writing
    // we always want to read dialects though.
    bool bwrite = true;
    if (!p.Force) {
        // we want to rebuild upon upgrades / new builds
        if (exists(oohpath) && exists(filename)) {
            time_t oohtime = last_write_time(oohpath);
            time_t opcpptime = opPlatform::GetOpCppTimeStamp();
            time_t dohtime = GetDialectTimestamp(p);

            filenode->LoadDependencies(spath + ".depend");
            bool bNewDepend = filenode->IsDependencyNewer(oohtime);

            if (bNewDepend) {
                if (p.Verbose) {
                    Log("Included dialect newer than generated dialect file, "
                        "forcing recompile ...");
                    Log("");
                }
            } else if (oohtime < opcpptime) {
                if (p.Verbose) {
                    Log(opPlatform::GetOpCppExecutableName() +
                        " newer than generated dialect file, forcing recompile "
                        "...");
                    Log("");
                }
            } else if (oohtime <= dohtime) {
                if (p.Verbose) {
                    Log("Dialect newer than generated dialect file, forcing "
                        "recompile ...");
                    Log("");
                }
            } else if (oohtime > dohtime) {
                if (p.Verbose) Log(filename.string() + " is up to date");

                bwrite = false;
            }
        }
    }

    if (bwrite) {
        try {
            // Save dependencies file.
            opString dependpath = spath + ".depend";
            filenode->SaveDependencies(dependpath);

            // open the output files for the generated code...
            FileWriteStream hfile(oohpath.string());
            FileWriteStream sfile(ocpppath.string());

            if (hfile.is_open() && sfile.is_open()) {
                filenode->SetFiles(oohpath.string(), ocpppath.string());

                opDialectStream filestream(hfile, sfile);

                // add the pre-pend path (for relative #lines)
                filestream.SetDepths(oohpath.string());

                // files are open, now print to them
                filenode->PrintDialectNode(filestream);

                filestream.Output();
            } else {
                Log("Could not open output file(s)!");
                return false;
            }
        } catch (opException::opCPP_Exception&) {
        }

        // print xml!
        if (p.PrintXml) {
            try {
                path xmlpath = (spath + ".xml").GetString();

                // open the output files for the generated code...
                boost::filesystem::ofstream xfile(xmlpath);

                if (xfile.is_open()) {
                    opXmlStream filestream(xfile);

                    // files are open, now print to them
                    filenode->PrintXml(filestream);
                } else {
                    Log("Could not open output xml file!");
                    return false;
                }
            } catch (opException::opCPP_Exception&) {
                //??? ever
            }
        }
    }

    double totaltimeend = opTimer::GetTimeSeconds();
    double totaltimeMs = (totaltimeend - totaltimestart) * 1000.0;

    // print the tree (success)
    if (p.PrintTree) filenode->PrintTree(filename.string());

    // write the verbose compilation notice
    if (p.Verbose) {
        Log("");
        Log(opString("Dialect reading successful ... took ") + totaltimeMs +
            " ms (" + filenode->GetScanMs() + " scan ms, " +
            filenode->GetParseMs() + " parse ms)");
        Log("");
    }

    return true;
}
Example #15
0
// compiles a file in normal mode
bool opDriver::NormalModeFile(const opParameters& p, const path& filename) {
    double totaltimestart = opTimer::GetTimeSeconds();

    // build the output filename strings...
    // fix this for ../ case (convert to string and find & replace...)
    opString sfile = GetOutputPath(p, filename);

    path oohpath = (sfile + ".ooh").GetString();
    path ocpppath = (sfile + ".ocpp").GetString();

    path outputpath = oohpath.branch_path();

    if (!exists(outputpath)) create_directories(outputpath);

    // lets check the timestamp...
    if (!p.Force) {
        time_t ohtime = last_write_time(filename);

        // we want to rebuild upon upgrades / new builds
        time_t opcpptime = opPlatform::GetOpCppTimeStamp();

        if (exists(oohpath) && exists(ocpppath)) {
            time_t oohtime = last_write_time(oohpath);
            time_t ocpptime = last_write_time(ocpppath);

            time_t dohtime = GetGeneratedDialectTimestamp(p);

            FileNode tempfile;
            tempfile.LoadDependencies(sfile + ".depend");
            bool bNewDepend = tempfile.IsDependencyNewer(oohtime);

            if (bNewDepend) {
                if (p.Verbose) {
                    Log("Included file newer than generated file, forcing "
                        "recompile ...");
                    Log("");
                }
            }
            // up to date if ooh newer than oh, and ooh newer than opcpp build
            else if (oohtime < opcpptime || ocpptime < opcpptime) {
                if (p.Verbose) {
                    Log(opPlatform::GetOpCppExecutableName() +
                        " newer than generated file, forcing recompile ...");
                    Log("");
                }
            } else if (oohtime <= dohtime || ocpptime <= dohtime) {
                if (p.Verbose) {
                    Log("Dialect newer than generated file, forcing recompile "
                        "...");
                    Log("");
                }
            } else if (oohtime > ohtime && ocpptime > ohtime) {
                if (p.Verbose) Log(filename.string() + " is up to date");

                return true;
            }
        }
    }

    opError::Clear();

    // output compiling -file- to std out
    if (!p.Silent) {
        Log(opString("Compiling ") + filename.string() + " ...");
    }

    // load the oh file, it will be tracked elsewhere
    OPFileNode* filenode =
        FileNode::Load<OPFileNode>(filename.string(), opScanner::SM_NormalMode);

    // filenode should be non-null even if there were errors
    assert(filenode);

    if (opError::HasErrors()) {
        if (p.PrintTree) filenode->PrintTree(filename.string());

        opError::Print();
        return false;
    }

    // no errors, let's print the output files
    try {
        // Save dependencies file.
        opString dependpath = sfile + ".depend";
        filenode->SaveDependencies(dependpath);

        // open the output files for the generated code...
        FileWriteStream hfile(oohpath.string());
        FileWriteStream sfile(ocpppath.string());

        if (hfile.is_open() && sfile.is_open()) {
            filenode->SetFiles(oohpath.string(), ocpppath.string());

            opFileStream filestream(hfile, sfile);

            // add the pre-pend path (for relative #lines)
            filestream.SetDepths(oohpath.string());

            // files are open, now print to them
            filenode->PrintNode(filestream);

            filestream.Output();
        } else {
            Log("Could not open output file(s)!");
            return false;
        }
    } catch (opException::opCPP_Exception&) {
        //??? ever
    }

    // print xml!
    if (p.PrintXml) {
        try {
            path xmlpath = (sfile + ".xml").GetString();

            // open the output files for the generated code...
            boost::filesystem::ofstream xfile(xmlpath);

            if (xfile.is_open()) {
                opXmlStream filestream(xfile);

                // files are open, now print to them
                filenode->PrintXml(filestream);
            } else {
                Log("Could not open output xml file!");
                return false;
            }
        } catch (opException::opCPP_Exception&) {
            //??? ever
        }
    }

    // any errors left?
    // shouldn't be really
    opError::Print();

    double totaltimeend = opTimer::GetTimeSeconds();
    double totaltimeMs = (totaltimeend - totaltimestart) * 1000.0;

    // TODO: allow PrintTree to any stream
    //		and add support for PrintTree to file
    // print the AST to stdout
    if (p.PrintTree) filenode->PrintTree(filename.string());

    // write the verbose compilation notice
    if (p.Verbose) {
        Log("");
        Log(opString("Compilation successful ... took ") + totaltimeMs +
            " ms (" + filenode->GetScanMs() + " scan ms, " +
            filenode->GetParseMs() + " parse ms)");
    }

    return true;
}
Example #16
0
int
chkAndResetRule (rsComm_t *rsComm)
{
    char *configDir;
    char rulesFileName[MAX_NAME_LEN];
#ifndef USE_BOOST_FS
    struct stat statbuf;
#endif
    int status;
    ruleExecInfo_t rei;
    uint mtime;

    configDir = getConfigDir ();
#ifdef RULE_ENGINE_N
    snprintf (rulesFileName, MAX_NAME_LEN, "%s/reConfigs/core.re",
      configDir);
#else
    snprintf (rulesFileName, MAX_NAME_LEN, "%s/reConfigs/core.irb", 
      configDir); 
#endif
#ifdef USE_BOOST_FS
        path p (rulesFileName);
        if (!exists (p)) {
#else
    status = stat (rulesFileName, &statbuf);

    if (status != 0) {
#endif
	status = UNIX_FILE_STAT_ERR - errno;
        rodsLog (LOG_ERROR,
          "chkAndResetRule: unable to read rule config file %s, status = %d",
	  rulesFileName, status);
	return (status);
    }

#ifdef USE_BOOST_FS
    mtime = (uint) last_write_time (p);
#else
    mtime = (uint) statbuf.st_mtime;
#endif

    if (CoreIrbTimeStamp == 0) {
	/* first time */
	CoreIrbTimeStamp = mtime;
	return (0);
    }

    if (mtime > CoreIrbTimeStamp) {
	/* file has been changed */
        rodsLog (LOG_NOTICE,
          "chkAndResetRule: reconf file %s has been changed. re-initializing",
	  rulesFileName);
	CoreIrbTimeStamp = mtime;
	rei.rsComm = rsComm;
	clearCoreRule();
#ifdef RULE_ENGINE_N
	/* The shared memory cache may have already been updated, do not force reload */
	status = initRuleEngine(RULE_ENGINE_TRY_CACHE, NULL, reRuleStr, reFuncMapStr, reVariableMapStr);
#else
	msiAdmClearAppRuleStruct (&rei);
	status = initRuleEngine(NULL, reRuleStr, reFuncMapStr, reVariableMapStr);
#endif
        if (status < 0) {
            rodsLog (LOG_ERROR,
              "chkAndResetRule: initRuleEngine error, status = %d", status);
        }
    }
    return status;
}
void ReflectionParser::GenerateFiles(void)
{
    fs::path sourceRootDirectory( m_options.sourceRoot );
    fs::path outputFileDirectory( m_options.outputModuleFileDirectory );

    m_moduleFileHeaderTemplate = LoadTemplate( kTemplateModuleFileHeader );

    if (!m_moduleFileHeaderTemplate.isValid( ))
    {
        std::stringstream error;

        error << "Unable to compile module file header template." << std::endl;
        error << m_moduleFileHeaderTemplate.errorMessage( );

        throw std::exception( error.str( ).c_str( ) );
    }

    m_moduleFileSourceTemplate = LoadTemplate( kTemplateModuleFileSource );

    if (!m_moduleFileSourceTemplate.isValid( ))
    {
        std::stringstream error;

        error << "Unable to compile module file source template." << std::endl;
        error << m_moduleFileSourceTemplate.errorMessage( );

        throw std::exception( error.str( ).c_str( ) );
    }

    TemplateData moduleFilesData { TemplateData::Type::List };

    fs::path metaCacheFileName = m_options.outputModuleFileDirectory;

    metaCacheFileName /= ".meta-cache";

    auto metaCacheFileExists = exists( metaCacheFileName );

    std::string moduleFileCache;

    for (auto &file : m_moduleFiles)
    {
        fs::path filePath( file.first );

        // path relative to the source root
        auto relativeDir = utils::MakeRelativePath( sourceRootDirectory, filePath )
            .replace_extension( "" ).string( );

        if (relativeDir.find_first_of( ".." ) != std::string::npos)
            continue;

        auto outputFile = outputFileDirectory / relativeDir;
        auto outputFileHeader = change_extension( outputFile, "Generated.h" );
        auto outputFileSource = change_extension( outputFile, "Generated.cpp" );

        // module file name
        file.second.name = boost::regex_replace(
            relativeDir,
            kSpecialCharsRegex,
            "_"
        );

        moduleFileCache += file.second.name + '\n';

        TemplateData moduleFileData { TemplateData::Type::Object };

        moduleFileData[ "name" ] = file.second.name;
        moduleFileData[ "header" ] = outputFileHeader.string( );

        moduleFilesData << moduleFileData;

        // if the generated file header doesn't exist, we need to regenerate
        if (m_options.forceRebuild || !metaCacheFileExists || !exists( outputFileHeader ))
        {
            generateModuleFile( outputFileHeader, outputFileSource, file.first, file.second );

            continue;
        }

        auto lastSourceWrite = last_write_time( filePath );
        auto lastGeneratedWrite = last_write_time( outputFileHeader );

        // if the generated file is older than the source file, we need to regenerate
        if (lastSourceWrite > lastGeneratedWrite)
            generateModuleFile( outputFileHeader, outputFileSource, file.first, file.second );
    }

    fs::path moduleCacheFileName = m_options.outputModuleFileDirectory;

    moduleCacheFileName /= ".meta-cache";

    if (!m_options.forceRebuild && metaCacheFileExists)
    {
        std::ifstream cacheFile( moduleCacheFileName.string( ) );

        std::istreambuf_iterator<char> cacheFileBegin( cacheFile );
        std::istreambuf_iterator<char> cacheFileEnd( nullptr );
        
        // the cache is the same, so we don't need to write the source files
        if (utils::RangeEqual( 
                moduleFileCache.begin( ), moduleFileCache.end( ), 
                cacheFileBegin, cacheFileEnd 
            ))
        {
            return;
        }
    }

    // update the cache
    utils::WriteText(
        moduleCacheFileName.string( ),
        moduleFileCache
    );

    // module source file
    {
        auto sourceTemplate = LoadTemplate( kTemplateModuleSource );

        if (!sourceTemplate.isValid( ))
        {
            std::stringstream error;

            error << "Unable to compile module source template." << std::endl;
            error << sourceTemplate.errorMessage( );

            throw std::exception( error.str( ).c_str( ) );
        }

        TemplateData sourceData { TemplateData::Type::Object };

        addGlobalTemplateData( sourceData );

        sourceData[ "moduleFile" ] = moduleFilesData;

        COMPILE_TYPE_TEMPLATES( sourceData, "external", m_externals );

        fs::path sourcePath( m_options.outputModuleSource );

        fs::create_directory( sourcePath.parent_path( ) );

        utils::WriteText( 
            sourcePath.string( ),
            sourceTemplate.render( sourceData )
        );
    }
}
Example #18
0
  /// Entry point for the asynchronous monitor thread
  void run()
  {
    bool run = true;
    typedef std::pair< callback_t , std::pair< file_action, std::string> > notification;
    std::vector< notification> notifications;

    for (;;)
    {
      {
        // Lock and check m_run; if it was set to false, we must return ASAP
        boost::mutex::scoped_lock lock(m_run_mutex);
        run = m_run;
        if (!run)
          return;
        // We release the lock, block the thread until one second
        m_run_cond.timed_wait(lock, moost::thread::xtime_util::add_ms(moost::thread::xtime_util::now(), m_sleep_ms));
      }
      // If we are not running (e.g. when the destructor woke us up), return
      if (!run)
        return;

      // Clear the notifications vector where we will collect the events
      // that will be fired
      notifications.clear();
      {
        // Lock m_file_mutex while we are working on m_file_callback
        boost::mutex::scoped_lock lock(m_file_mutex);
        for (std::map<std::string, callback_t>::iterator it = m_file_callback.begin(); it != m_file_callback.end(); ++it)
        {
          boost::filesystem::path p(it->first);

          // Does the path exist?
          std::time_t lw = last_write_time(p);
          if (lw != 0)
          {
            // Check its last modification time and compare it with what we had earlier
            std::map< std::string, std::pair<time_t, time_t> >::iterator it_mod = m_file_modified.find(it->first);

            if (it_mod == m_file_modified.end())
            {
              // We haven't seen this file so far, so insert it into the
              // map and add a creation event that will be fired
              m_file_modified[it->first] = std::make_pair(lw, lw);
              notifications.push_back(std::make_pair(it->second, std::make_pair(CREATED, it->first)));
            }
            else
            {
              // only case we consider a real modification: prev prev mod != prev mod,
              // but this mod == prev mod
              // the idea is that we want to capture a write to a file,
              // but only notify when the write is finished

              /**
               * \todo This could cause problems with frequent writing.
               *       We should really use boost.interprocess file locking
               *       instead (when we get 1.36 everywhere)
               */
              if (lw == it_mod->second.second && it_mod->second.first != it_mod->second.second)
                notifications.push_back(std::make_pair(it->second, std::make_pair(CHANGED, it->first)));
              it_mod->second.first = it_mod->second.second;
              it_mod->second.second = lw;
            }
          }
          else
          {
            // The path does not exist. Did we have it before? If so, fire
            // a deletion event.
            std::map< std::string, std::pair<time_t, time_t> >::iterator it_mod = m_file_modified.find(it->first);
            if (it_mod != m_file_modified.end())
            {
              m_file_modified.erase(it_mod);
              notifications.push_back(std::make_pair(it->second, std::make_pair(DELETED, it->first)));
            }
          }
        }
      }

      // okay!  we've released our lock on m_file_callback and m_file_modified
      // so it's time to send off our notifications
      for (std::vector<notification>::iterator it = notifications.begin(); it != notifications.end(); ++it)
      {
        try
        {
          it->first(it->second.first, it->second.second);
        }
        catch (...)
        {
          // \todo  can we do better here than silently ignoring the exception?
        }
      }
    }
  }