diff --git a/src/include/xce/types.h b/src/include/xce/types.h index 8e81bb34..b8bd359c 100644 --- a/src/include/xce/types.h +++ b/src/include/xce/types.h @@ -333,6 +333,7 @@ typedef struct { char* user_group; char* job_description; char* resreq; + char* from_host; } job_submit_data_t; typedef struct { diff --git a/src/lib/jobj.c b/src/lib/jobj.c index d4a5bd06..dd2c3a3e 100644 --- a/src/lib/jobj.c +++ b/src/lib/jobj.c @@ -148,6 +148,7 @@ static int jobsub_init(meta_obj_t* obj, va_list ap) dst->user_group = makeString(src->user_group); dst->job_description = makeString(src->job_description); dst->resreq = makeString(src->resreq); + dst->from_host = makeString(src->from_host); if (!(EQUAL_STRING(dst->queue, src->queue) && EQUAL_STRING(dst->user, src->user) @@ -155,7 +156,8 @@ static int jobsub_init(meta_obj_t* obj, va_list ap) && EQUAL_STRING(dst->project_name, src->project_name) && EQUAL_STRING(dst->user_group, src->user_group) && EQUAL_STRING(dst->job_description, src->job_description) - && EQUAL_STRING(dst->resreq, src->resreq))) { + && EQUAL_STRING(dst->resreq, src->resreq) + && EQUAL_STRING(dst->from_host, src->from_host))) { jobsub_destroy(obj); return -ENOMEM; } @@ -177,6 +179,7 @@ static void jobsub_destroy(meta_obj_t* obj) dereference(jobsub->user_group); dereference(jobsub->job_description); dereference(jobsub->resreq); + dereference(jobsub->from_host); if (jobsub->start_info != NULL) { dereference(jobsub->start_info); } diff --git a/src/lib/testsuite/test_jobj.c b/src/lib/testsuite/test_jobj.c index 892150fc..641d966a 100644 --- a/src/lib/testsuite/test_jobj.c +++ b/src/lib/testsuite/test_jobj.c @@ -110,7 +110,8 @@ static void test_jobsub_create(void) .project_name = "default", .user_group = NULL, .job_description = "no description", - .resreq = "type == any" }; + .resreq = "type == any", + .from_host = "review-client" }; job_submit_data_t* s2 = NULL; rc = xstring_table_init(32); @@ -137,7 +138,9 @@ static void test_jobsub_create(void) && EQUAL_STRING(s2->job_name, "J1") && EQUAL_STRING(s2->project_name, "default") && EQUAL_STRING(s2->job_description, "no description") - && EQUAL_STRING(s2->resreq, "type == any") && (s2->mintasks == 1) + && EQUAL_STRING(s2->resreq, "type == any") + && EQUAL_STRING(s2->from_host, "review-client") + && (s2->mintasks == 1) && (s2->maxtasks == 5) && (s2->user_group == NULL)); job_obj_fini(); @@ -165,7 +168,8 @@ static void test_jobsub_share(void) .project_name = "default", .user_group = NULL, .job_description = "no description", - .resreq = "type == any" }; + .resreq = "type == any", + .from_host = "review-client" }; job_submit_data_t* s2 = NULL; job_submit_data_t* s3 = NULL; @@ -193,7 +197,9 @@ static void test_jobsub_share(void) && EQUAL_STRING(s2->job_name, "J1") && EQUAL_STRING(s2->project_name, "default") && EQUAL_STRING(s2->job_description, "no description") - && EQUAL_STRING(s2->resreq, "type == any") && (s2->mintasks == 1) + && EQUAL_STRING(s2->resreq, "type == any") + && EQUAL_STRING(s2->from_host, "review-client") + && (s2->mintasks == 1) && (s2->maxtasks == 5) && (s2->user_group == NULL)); s3 = makeJobsub(&jobsub1); @@ -204,6 +210,51 @@ static void test_jobsub_share(void) xstring_table_fini(); } +/* bug-1676: from_host must participate in makeJobsub's content-dedup + * identity, not just be silently dropped or ignored -- two submissions + * differing ONLY in from_host must NOT collapse to the same interned + * object (they are genuinely different submissions from different + * clients), while an identical from_host still dedupes like every other + * field (test_jobsub_share above). */ +static void test_jobsub_from_host_distinguishes_identity(void) +{ + int rc; + job_submit_data_t jobsub_a = { .queue = "xce", + .user = "rshen", + .mintasks = 1, + .maxtasks = 5, + .job_name = "J1", + .resreq = "type == any", + .from_host = "client-a" }; + job_submit_data_t jobsub_b = { .queue = "xce", + .user = "rshen", + .mintasks = 1, + .maxtasks = 5, + .job_name = "J1", + .resreq = "type == any", + .from_host = "client-b" }; + job_submit_data_t* sa = NULL; + job_submit_data_t* sb = NULL; + + rc = xstring_table_init(32); + TEST_ASSERT_TRUE(rc >= 0); + + rc = job_obj_init(31, 31); + TEST_ASSERT_TRUE(rc >= 0); + + sa = makeJobsub(&jobsub_a); + sb = makeJobsub(&jobsub_b); + + TEST_ASSERT_TRUE(sa != NULL); + TEST_ASSERT_TRUE(sb != NULL); + TEST_ASSERT_TRUE(sa != sb); + TEST_ASSERT_TRUE(EQUAL_STRING(sa->from_host, "client-a")); + TEST_ASSERT_TRUE(EQUAL_STRING(sb->from_host, "client-b")); + + job_obj_fini(); + xstring_table_fini(); +} + static void test_job_create(void) { int rc; @@ -230,7 +281,8 @@ static void test_job_create(void) .project_name = "default", .user_group = NULL, .job_description = "no description", - .resreq = "type == any" }; + .resreq = "type == any", + .from_host = "review-client" }; xce_job_t job1 = { .submit = &jobsub1 }; job_t* j2 = NULL; time_t now = time(NULL); @@ -278,6 +330,7 @@ static void test_job_create(void) && EQUAL_STRING(j2->job.submit->project_name, "default") && EQUAL_STRING(j2->job.submit->job_description, "no description") && EQUAL_STRING(j2->job.submit->resreq, "type == any") + && EQUAL_STRING(j2->job.submit->from_host, "review-client") && (j2->job.submit->mintasks == 1) && (j2->job.submit->maxtasks == 5) && (j2->job.submit->user_group == NULL)); @@ -295,5 +348,6 @@ void test_jobobj(void) RUN_TEST(test_startinfo_share); RUN_TEST(test_jobsub_create); RUN_TEST(test_jobsub_share); + RUN_TEST(test_jobsub_from_host_distinguishes_identity); RUN_TEST(test_job_create); } diff --git a/src/schema/controller.capnp b/src/schema/controller.capnp index 42df5db3..dd756cd7 100644 --- a/src/schema/controller.capnp +++ b/src/schema/controller.capnp @@ -531,6 +531,7 @@ struct JobSubmitData $C.mapname("job_submit_data_t") { description @7: Text $C.mapname("job_description"); resreq @8: Text; startinfo @9: JobStartInfo $C.mapname("start_info"); + fromHost @10: Text $C.mapname("from_host"); } struct JobSubmit $C.mapname("xce_job_submit_t") {