Example #1
0
int filecache_retrieve(TARGET *t, MD5SUM buildmd5sum)
{
	MD5SUM blobmd5sum;
	MD5SUM copymd5sum;
	time_t time;

	/* if the target is available in the cache */
	const char *cachedname = filecache_getfilename(t, buildmd5sum, 0);
	if (!cachedname)
		return 0;

	if (!filecache_findlink(cachedname, blobmd5sum))
	{
		if( DEBUG_MD5HASH)
		{
			printf("Cannot find %s in cache as %s\n", t->name, cachedname);
			filecache_disable(t);
		}
		return 0;
	}

	getcachedmd5sum( t, 1 );

	if ( file_time( t->boundname, &time ) == 0 )
	{
		if (memcmp(blobmd5sum, t->contentmd5sum, sizeof(MD5SUM)) == 0)
		{
			if (!(t->flags & T_FLAG_NOCARE))
#ifdef _MSC_VER
				_utime(t->boundname, NULL);
#else
				utime(t->boundname, NULL);
#endif
			printf("%s is already the proper cached target.\n", t->name);
			return 1;
		}
	}

	cachedname = filecache_getfilename(t, blobmd5sum, ".blob");

	/* try to get it from the cache */
	if (copyfile(t->boundname, cachedname, &copymd5sum)  &&  memcmp(copymd5sum, blobmd5sum, sizeof(MD5SUM)) == 0)
	{
		printf( "Using cached %s\n", t->name );
		return 1;
	}
	else if (!(t->flags & T_FLAG_OPTIONALFILECACHE))
	{
		printf( "Cannot retrieve %s from cache (will build normally)\n", t->name );
		return 0;
	}

	if( DEBUG_MD5HASH)
	{
		printf( "Cannot find %s in cache as %s\n", t->name, cachedname );
	}

	return 0;
}
Example #2
0
int checksum_retrieve(TARGET *t, MD5SUM buildmd5sum)
{
	CHECKSUMDATA cachedata, *c = &cachedata;
	char buildmd5sumstring[33];

	checksums_readfile();

	strcpy(buildmd5sumstring, md5tostring(buildmd5sum));
	c->boundname = buildmd5sumstring;

	if (!hashcheck(checksumhash, (HASHDATA **)&c)) {
		return 0;
	}

	getcachedmd5sum(t, 0);

	if (t->contentchecksum  &&  t->contentchecksum->mtime != 0  &&  memcmp( c->contentmd5sum, t->contentchecksum->contentmd5sum, MD5_SUMSIZE ) == 0 )
	{
		time_t time;
#ifdef _MSC_VER
		_utime(t->boundname, NULL);
#else
		utime(t->boundname, NULL);
#endif
		file_time(t->boundname, &time);
		t->contentchecksum->mtime = time;
		t->contentchecksum->age = 0;
		checksumsdirty = 1;

		//printf("JAMDEBUG: %s is already the proper cached target.\n", t->name);
		return 1;
	}
	else
	{
		memset(&c->contentmd5sum, 0, MD5_SUMSIZE);
	}

	return 0;
}
Example #3
0
static void
make1b( TARGET *t )
{
	TARGETS	*c;
	const char *failed;
#ifdef OPT_MULTIPASS_EXT
	int missing;
#endif
#ifdef OPT_BUILTIN_NEEDS_EXT
	int childmightnotupdate;
	int childscancontents;
	int childupdated;
#endif

#ifdef OPT_DEBUG_MAKE1_LOG_EXT
	if (DEBUG_MAKE1) {
	    printf( "make1b\t--\t%s (asynccnt %d)\n" ,
		    t->name, t->asynccnt);
	}
#endif
	/* If any dependents are still outstanding, wait until they */
	/* call make1b() to signal their completion. */

	if( --t->asynccnt )
	    return;

#ifdef OPT_INTERRUPT_FIX
	if( intr )
	    return;
#endif

	failed = "dependents";
#ifdef OPT_MULTIPASS_EXT
	missing = 0;
#endif
#ifdef OPT_BUILTIN_NEEDS_EXT
	childmightnotupdate = 0;
	childscancontents = 0;
	childupdated = 0;
#endif

#ifdef OPT_SEMAPHORE
	if( t->semaphore && t->semaphore->asynccnt )
	{
	    /* We can't launch yet.  Try again when the semaphore is free */
#ifdef OPT_BUILTIN_NEEDS_EXT
	    t->semaphore->parents = targetentry( t->semaphore->parents, t, 0 );
#else
	    t->semaphore->parents = targetentry( t->semaphore->parents, t );
#endif
	    t->asynccnt++;

	    if( DEBUG_EXECCMD )
		printf( "SEM: %s is busy, delaying launch of %s\n",
			t->semaphore->name, t->name);
	    return;
	}
#endif
	/* Now ready to build target 't'... if dependents built ok. */

	/* Collect status from dependents */

	for( c = t->depends; c; c = c->next ) {
	    if ( !(t->flags & T_FLAG_INTERNAL) && c->target->asynccnt ) {
//			printf("warning: Trying to build '%s' before dependent '%s' is done!\n", t->name, c->target->name);
		}
#ifdef OPT_BUILTIN_NEEDS_EXT
	    /* Only test a target's MightNotUpdate flag if the target's build was successful. */
	    if( c->target->status == EXEC_CMD_OK ) {
		if ( c->target->flags & T_FLAG_MIGHTNOTUPDATE ) {
		    time_t timestamp;

		    /* Mark that we've seen a MightNotUpdate flag in this set of children. */
		    childmightnotupdate = 1;

		    /* Grab the generated target's timestamp. */
		    if ( file_time( c->target->boundname, &timestamp ) == 0 ) {
			/* If the child's timestamp is greater that the target's timestamp, then it updated. */
				if ( timestamp > t->time ) {
					if ( c->target->flags & T_FLAG_SCANCONTENTS ) {
						childscancontents = 1;
						if ( getcachedmd5sum( c->target, 1 ) )
							childupdated = 1;
					} else
						childupdated = 1;
				} else {
					childscancontents = 1;
				}
		    }
		}
		/* If it didn't have the MightNotUpdate flag but did update, mark it. */
		else if ( c->target->fate > T_FATE_STABLE  &&  !c->needs ) {
			if ( c->target->flags & T_FLAG_SCANCONTENTS ) {
				childscancontents = 1;
				if ( getcachedmd5sum( c->target, 1 ) )
					childupdated = 1;
			} else
				childupdated = 1;
		}
	    }
#endif

	    if( c->target->status > t->status )
	{
	    failed = c->target->name;
	    t->status = c->target->status;
#ifdef OPT_MULTIPASS_EXT
		if ( ( c->target->fate == T_FATE_MISSING  &&  ! ( c->target->flags & T_FLAG_NOCARE )  &&  !c->target->actions ) || t->status == EXEC_CMD_NEXTPASS )
		{
			missing = 1;
			if ( queuedjamfiles )
			{
				ACTIONS *actions;

				t->status = EXEC_CMD_NEXTPASS;

				for( actions = t->actions; actions; actions = actions->next )
				{
					actions->action->pass++;
				}
			}
		}
#endif
	}

#ifdef OPT_NOCARE_NODES_EXT
	/* CWM */
	/* If actions on deps have failed, but if this is a 'nocare' target */
	/* then continue anyway. */

	if( ( t->flags & T_FLAG_NOCARE ) && t->status == EXEC_CMD_FAIL )
	{
		printf( "...dependency on %s failed, but don't care...\n", t->name );
		t->status = EXEC_CMD_OK;
	}
#endif
	}

#ifdef OPT_BUILTIN_NEEDS_EXT
	/* If we found a MightNotUpdate flag and there was an update, mark the fate as updated. */
	if ( childmightnotupdate  &&  childupdated  &&  t->fate == T_FATE_STABLE )
	      t->fate = T_FATE_UPDATE;
	if ( childscancontents ) {
		if ( !childupdated ) {
			if ( t->includes ) {
				for( c = t->includes->depends; c; c = c->next ) {
					if ( c->target->fate > T_FATE_STABLE  &&  !c->needs ) {
						if ( c->target->flags & T_FLAG_SCANCONTENTS ) {
							if ( getcachedmd5sum( c->target, 1 )  ||  !md5matchescommandline( c->target ) ) {
								childupdated = 1;
								break;
							}
						} else {
							childupdated = 1;
							break;
						}
					}
				}
			}

			if ( !childupdated )
				t->fate = T_FATE_STABLE;
		} else if ( t->fate == T_FATE_STABLE )
			t->fate = T_FATE_UPDATE;
	}
	if ( t->fate == T_FATE_UPDATE  &&  !childupdated  &&  t->status != EXEC_CMD_NEXTPASS )
		if ( md5matchescommandline( t ) )
		    t->fate = T_FATE_STABLE;
	if ( t->flags & ( T_FLAG_MIGHTNOTUPDATE | T_FLAG_SCANCONTENTS )  &&  t->actions ) {
#ifdef OPT_ACTIONS_WAIT_FIX
	    /* See http://maillist.perforce.com/pipermail/jamming/2003-December/002252.html */
	    /* Determine if an action is already running on behalf of another target, and if so, */
	    /* bail out of make1b() prior to calling make1cmds() by adding more parents to the */
	    /* in-progress target and incrementing the asynccnt of the new target. */
	    make1wait( t );
	    if ( t->asynccnt != 0 )
		return;
#endif
	}
#endif

	/* If actions on deps have failed, bail. */
	/* Otherwise, execute all actions to make target */

#ifdef OPT_MULTIPASS_EXT
	if( t->status == EXEC_CMD_FAIL && t->actions && !missing )
#else
	if( t->status == EXEC_CMD_FAIL && t->actions )
#endif
	{
	    ++counts->skipped;
	    printf( "*** skipped %s for lack of %s...\n", t->name, failed );
	}

	if( t->status == EXEC_CMD_OK )
	    switch( t->fate )
	{
	case T_FATE_INIT:
	case T_FATE_MAKING:
	    /* shouldn't happen */

	case T_FATE_STABLE:
	case T_FATE_NEWER:
	    break;

	case T_FATE_CANTFIND:
	case T_FATE_CANTMAKE:
	    t->status = EXEC_CMD_FAIL;
	    break;

	case T_FATE_ISTMP:
	    if( DEBUG_MAKEQ )
		printf( "*** using %s...\n", t->name );
	    break;

	case T_FATE_TOUCHED:
	case T_FATE_MISSING:
	case T_FATE_NEEDTMP:
	case T_FATE_OUTDATED:
	case T_FATE_UPDATE:
	    /* Set "on target" vars, build actions, unset vars */
	    /* Set "progress" so that make1c() counts this target among */
	    /* the successes/failures. */

#ifdef OPT_DEBUG_MAKE1_LOG_EXT
	    if (DEBUG_MAKE1) {
		printf( "make1b\t--\t%s (has actions)\n" , t->name );
	    }
#endif
	    if( t->actions )
	    {
#ifdef OPT_ACTIONS_WAIT_FIX
		/* See http://maillist.perforce.com/pipermail/jamming/2003-December/002252.html */
		/* Determine if an action is already running on behalf of another target, and if so, */
		/* bail out of make1b() prior to calling make1cmds() by adding more parents to the */
		/* in-progress target and incrementing the asynccnt of the new target. */
		make1wait( t );
		if ( t->asynccnt != 0 )
		    return;
#endif
		++counts->total;

#ifndef OPT_IMPROVED_PROGRESS_EXT
		if( DEBUG_MAKE && !( counts->total % 100 ) )
		    printf( "*** on %dth target...\n", counts->total );
#else
		{
		    double est_remaining;

		    est_remaining =
			progress_update(globs.progress, counts->total);

		    if (est_remaining > 0) {
			int minutes = (int)est_remaining / 60;
			int seconds = (int)est_remaining % 60;

			if (minutes > 0 || seconds > 0) {
			    printf("*** completed %.0f%% (",
				   ((double)counts->total * 100 /
				    globs.updating));
			    if (minutes > 0)
				printf("%d min ", minutes);
			    if (seconds >= 0)
				printf("%d sec ", seconds);
			    printf("remaining)...\n");
			}
		    }
		}
#endif

#ifdef OPT_BUILTIN_MD5CACHE_EXT
		pushsettings( t->settings );
		filecache_fillvalues( t );
		popsettings( t->settings );
		t->cmds = (char *)make1cmds( t, t->actions );
#else
		pushsettings( t->settings );
		t->cmds = (char *)make1cmds( t->actions );
		popsettings( t->settings );
#endif

		t->progress = T_MAKE_RUNNING;
	    }

	    break;
	}

#ifdef OPT_SEMAPHORE
	/* If there is a semaphore, indicate that its in use */
	if( t->semaphore )
	{
	    ++(t->semaphore->asynccnt);

	    if( DEBUG_EXECCMD )
		printf( "SEM: %s now used by %s\n", t->semaphore->name,
		       t->name );
	}
#endif
	/* Call make1c() to begin the execution of the chain of commands */
	/* needed to build target.  If we're not going to build target */
	/* (because of dependency failures or because no commands need to */
	/* be run) the chain will be empty and make1c() will directly */
	/* signal the completion of target. */

	make1c( t );
}
Example #4
0
void filecache_update(TARGET *t, MD5SUM buildmd5sum)
{
	MD5SUM blobmd5sum;
	int haveblobmd5sum = 0;
	const char *cachedname;
	const char *blobname;
	int cacheerror;

	if (!t->filecache_generate)
		return;

	/* If the buildmd5sum is empty, then the file doesn't exist. */
	cacheerror = ismd5empty(buildmd5sum);
	if (cacheerror)
		return;

	haveblobmd5sum = 0;
	cachedname = filecache_getfilename(t, buildmd5sum, NULL);
	if (!cachedname)
		return;

	/* Search for the appropriate .link file that matches the target. */
	haveblobmd5sum = filecache_findlink(cachedname, blobmd5sum);

	/* If we weren't able to determine the target md5sum, do it now. */
	if (!haveblobmd5sum)
	{
		getcachedmd5sum( t, 1 );
		memcpy(blobmd5sum, t->contentchecksum->contentmd5sum, MD5_SUMSIZE);
		if (ismd5empty(t->contentchecksum->contentmd5sum))
			return;
	}

	{
		/* Is the blob already there? */
		time_t blobtime;
		blobname = filecache_getfilename(t, blobmd5sum, ".blob");
		if (file_time(blobname, &blobtime) == -1)
		{
			time_t blobpartialtime;
			const char *blobpartialname;

			if(DEBUG_MD5HASH)
				printf("Caching %s as %s\n", t->name, cachedname);
			else
				printf("Caching %s\n", t->name);

			/* Write the new .blob to the cache. */
			blobpartialname = filecache_getfilename(t, blobmd5sum, ".blob.partial");
			if (file_time(blobpartialname, &blobpartialtime) == -1)
			{
				if (copyfile(blobpartialname, t->boundname, &blobmd5sum) == 0  ||
					rename(blobpartialname, blobname) != 0)
				{
					printf("** Unable to write %s to cache.\n", t->name);
					filecache_disable(t);
					return;
				}
			}
		}
	}

	/* Write the new .link file to the cache. */
	{
		FILE *file;
		BUFFER linknamebuff;
		buffer_init(&linknamebuff);
		buffer_addstring(&linknamebuff, cachedname, strlen(cachedname));
		buffer_addchar(&linknamebuff, '-');
		buffer_addstring(&linknamebuff, md5tostring(blobmd5sum), 32);
		buffer_addstring(&linknamebuff, ".link", 5);
		buffer_addchar(&linknamebuff, 0);

		file_mkdir(buffer_ptr(&linknamebuff));
		file = fopen(buffer_ptr(&linknamebuff), "wb");
		if (file)
		{
			write_md5sum(file, blobmd5sum);
			write_string(file, t->name);
			fclose(file);
		}

		buffer_free(&linknamebuff);
	}
}