diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b9e68ad121eb662b9325827ffa4277b802907b18..1810aab8f44f034623e306cb93c8fd690fc99fbb 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -6,7 +6,27 @@ stages: - build - test -build: +release_build: + stage: build + script: + - export LD_LIBRARY_PATH=/usr/local/lib:/usr/local/lib64 + - export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:/usr/local/lib64/pkgconfig + - mkdir -p build + - cd build + - cmake + -DCMAKE_BUILD_TYPE:STRING=Release + -DCMAKE_PREFIX_PATH:STRING=/usr/local + -DCMAKE_INSTALL_PREFIX:STRING=${CI_PROJECT_DIR}/compiled + -DSCORD_BUILD_EXAMPLES:BOOL=ON + -DSCORD_BUILD_TESTS:BOOL=ON + -DSCORD_TRANSPORT_LIBRARY=libfabric + -DSCORD_TRANSPORT_PROTOCOL=ofi+tcp + -DSCORD_BIND_ADDRESS=127.0.0.1 + -DSCORD_BIND_PORT=52000 + .. + - make -j$(nproc) install + +debug_build: stage: build script: - export LD_LIBRARY_PATH=/usr/local/lib:/usr/local/lib64 @@ -45,7 +65,7 @@ build: # run RPC tests using the binary built before rpc: stage: test - needs: [build] + needs: [debug_build] script: - export ASAN_OPTIONS=detect_odr_violation=0:detect_leaks=0 - export LSAN_OPTIONS=verbosity=1:log_threads=1:suppressions=${CI_PROJECT_DIR}/tests/LSanSuppress.supp @@ -62,7 +82,7 @@ rpc: # run unit tests unit: stage: test - needs: [build] + needs: [debug_build] script: - export ASAN_OPTIONS=detect_odr_violation=0 - export LSAN_OPTIONS=verbosity=1:log_threads=1:suppressions=${CI_PROJECT_DIR}/tests/LSanSuppress.supp diff --git a/examples/c/ADM_deploy_adhoc_storage.c b/examples/c/ADM_deploy_adhoc_storage.c index 05d1ad4ceda80940e163b68da81034b144bc893f..8f476ff292f37d206c509367218b10afc21eb88d 100644 --- a/examples/c/ADM_deploy_adhoc_storage.c +++ b/examples/c/ADM_deploy_adhoc_storage.c @@ -25,7 +25,6 @@ #include #include #include -#include #include "common.h" #define NADHOC_NODES 25 @@ -41,58 +40,108 @@ main(int argc, char* argv[]) { exit(EXIT_FAILURE); } - int exit_status = EXIT_SUCCESS; - ADM_server_t server = ADM_server_create("tcp", argv[1]); + int exit_status = EXIT_FAILURE; + ADM_return_t ret = ADM_SUCCESS; + ADM_server_t server = NULL; - ADM_node_t* adhoc_nodes = prepare_nodes(NADHOC_NODES); - assert(adhoc_nodes); - ADM_dataset_t* inputs = prepare_datasets("input-dataset-%d", NINPUTS); - assert(inputs); - ADM_dataset_t* outputs = prepare_datasets("output-dataset-%d", NOUTPUTS); - assert(outputs); + // adhoc information + const char* adhoc_name = "adhoc_storage_42"; - ADM_adhoc_resources_t adhoc_resources = - ADM_adhoc_resources_create(adhoc_nodes, NADHOC_NODES); - assert(adhoc_resources); + ADM_node_t* adhoc_nodes = NULL; + ADM_adhoc_resources_t adhoc_resources = NULL; + ADM_adhoc_context_t adhoc_ctx = NULL; + ADM_adhoc_context_t new_adhoc_ctx = NULL; + ADM_storage_t adhoc_storage = NULL; - ADM_adhoc_context_t ctx = ADM_adhoc_context_create( - ADM_ADHOC_MODE_SEPARATE_NEW, ADM_ADHOC_ACCESS_RDWR, adhoc_resources, - 100, false); - assert(ctx); - const char* name = "adhoc_storage_42"; + // Let's prepare all the information required by the API calls. + // ADM_update_adhoc_storage() obviously requires an adhoc storage to have + // been registered onto the system, so let's prepare first the data required + // to call ADM_register_adhoc_storage(): - ADM_storage_t adhoc_storage; - ADM_return_t ret = ADM_register_adhoc_storage( - server, name, ADM_STORAGE_GEKKOFS, ctx, &adhoc_storage); + // 1. the jobs required by the associated adhoc storage + adhoc_nodes = prepare_nodes(NADHOC_NODES); - if(ret != ADM_SUCCESS) { - fprintf(stderr, - "ADM_register_adhoc_storage() remote procedure not completed " - "successfully: %s\n", + if(adhoc_nodes == NULL) { + fprintf(stderr, "Fatal error preparing adhoc nodes\n"); + goto cleanup; + } + + // 2. the adhoc storage resources + adhoc_resources = ADM_adhoc_resources_create(adhoc_nodes, NADHOC_NODES); + + if(adhoc_resources == NULL) { + fprintf(stderr, "Fatal error preparing adhoc resources\n"); + goto cleanup; + } + + // 3. the adhoc storage execution context + adhoc_ctx = ADM_adhoc_context_create(ADM_ADHOC_MODE_SEPARATE_NEW, + ADM_ADHOC_ACCESS_RDWR, adhoc_resources, + 100, false); + + if(adhoc_ctx == NULL) { + fprintf(stderr, "Fatal error preparing adhoc context\n"); + goto cleanup; + } + + + // All the information required by the ADM_register_adhoc_storage() API is + // now ready. Let's actually contact the server: + + // 1. Find the server endpoint + if((server = ADM_server_create("tcp", argv[1])) == NULL) { + fprintf(stderr, "Fatal error creating server\n"); + goto cleanup; + } + + // 2. Register the adhoc storage + if(ADM_register_adhoc_storage(server, adhoc_name, ADM_STORAGE_GEKKOFS, + adhoc_ctx, &adhoc_storage) != ADM_SUCCESS) { + fprintf(stderr, "ADM_register_adhoc_storage() failed: %s\n", ADM_strerror(ret)); - exit_status = EXIT_FAILURE; goto cleanup; } - fprintf(stdout, "ADM_register_adhoc_storage() remote procedure completed " - "successfully\n"); - ret = ADM_deploy_adhoc_storage(server, adhoc_storage); + // Now that we have an existing adhoc storage registered into the + // system, let's prepare a new execution context for the adhoc + // storage system + + new_adhoc_ctx = ADM_adhoc_context_create(ADM_ADHOC_MODE_SEPARATE_NEW, + ADM_ADHOC_ACCESS_RDWR, + adhoc_resources, 200, false); + + if(new_adhoc_ctx == NULL) { + fprintf(stderr, "Fatal error preparing new adhoc context\n"); + goto cleanup; + } - if(ret != ADM_SUCCESS) { - fprintf(stderr, - "ADM_deploy_adhoc_storage() remote procedure not completed " - "successfully: %s\n", + // We can now request the deployment to the server + if((ret = ADM_deploy_adhoc_storage(server, adhoc_storage)) != ADM_SUCCESS) { + fprintf(stderr, "ADM_deploy_adhoc_storage() failed: %s\n", ADM_strerror(ret)); - exit_status = EXIT_FAILURE; goto cleanup; } - fprintf(stdout, "ADM_deploy_adhoc_storage() remote procedure completed " - "successfully\n"); + // At this point, the adhoc storage has been updated... + exit_status = EXIT_SUCCESS; + + // Once the adhoc storage is no longer required we need to notify the server + if((ret = ADM_remove_adhoc_storage(server, adhoc_storage)) != ADM_SUCCESS) { + fprintf(stderr, "ADM_remove_adhoc_storage() failed: %s\n", + ADM_strerror(ret)); + adhoc_storage = NULL; + exit_status = EXIT_FAILURE; + // intentionally fall through... + } + cleanup: ADM_server_destroy(server); + ADM_adhoc_context_destroy(new_adhoc_ctx); + ADM_adhoc_context_destroy(adhoc_ctx); + ADM_adhoc_resources_destroy(adhoc_resources); + destroy_nodes(adhoc_nodes, NADHOC_NODES); exit(exit_status); } diff --git a/examples/c/ADM_register_adhoc_storage.c b/examples/c/ADM_register_adhoc_storage.c index 70888670dd68cc5a40ea481713a277962499287c..25abdc2dc0de0f86b9c794e7f06c6a638dea9bc4 100644 --- a/examples/c/ADM_register_adhoc_storage.c +++ b/examples/c/ADM_register_adhoc_storage.c @@ -25,7 +25,6 @@ #include #include #include -#include #include "common.h" #define NADHOC_NODES 25 @@ -41,44 +40,83 @@ main(int argc, char* argv[]) { exit(EXIT_FAILURE); } - int exit_status = EXIT_SUCCESS; - ADM_server_t server = ADM_server_create("tcp", argv[1]); + int exit_status = EXIT_FAILURE; + ADM_return_t ret = ADM_SUCCESS; + ADM_server_t server = NULL; - ADM_node_t* adhoc_nodes = prepare_nodes(NADHOC_NODES); - assert(adhoc_nodes); - ADM_dataset_t* inputs = prepare_datasets("input-dataset-%d", NINPUTS); - assert(inputs); - ADM_dataset_t* outputs = prepare_datasets("output-dataset-%d", NOUTPUTS); - assert(outputs); + // adhoc information + const char* adhoc_name = "adhoc_storage_42"; + ADM_node_t* adhoc_nodes = NULL; + ADM_adhoc_resources_t adhoc_resources = NULL; + ADM_adhoc_context_t adhoc_ctx = NULL; + ADM_storage_t adhoc_storage = NULL; - ADM_adhoc_resources_t adhoc_resources = - ADM_adhoc_resources_create(adhoc_nodes, NADHOC_NODES); - assert(adhoc_resources); + // Let's prepare all the information required by the API calls. + // ADM_register_adhoc_storage() requires a set of nodes for the adhoc + // storage to use and an appropriate execution context defining how it + // should behave: - ADM_adhoc_context_t ctx = ADM_adhoc_context_create( - ADM_ADHOC_MODE_SEPARATE_NEW, ADM_ADHOC_ACCESS_RDWR, adhoc_resources, - 100, false); - assert(ctx); + // 1. prepare the nodes + adhoc_nodes = prepare_nodes(NADHOC_NODES); - const char* name = "adhoc_storage_42"; + if(adhoc_nodes == NULL) { + fprintf(stderr, "Fatal error preparing adhoc nodes\n"); + goto cleanup; + } + + // 2. define the adhoc storage resources + adhoc_resources = ADM_adhoc_resources_create(adhoc_nodes, NADHOC_NODES); + + if(adhoc_resources == NULL) { + fprintf(stderr, "Fatal error preparing adhoc resources\n"); + goto cleanup; + } + + // 3. define the adhoc execution context + adhoc_ctx = ADM_adhoc_context_create(ADM_ADHOC_MODE_SEPARATE_NEW, + ADM_ADHOC_ACCESS_RDWR, adhoc_resources, + 100, false); + + if(adhoc_ctx == NULL) { + fprintf(stderr, "Fatal error preparing adhoc context\n"); + goto cleanup; + } - ADM_storage_t adhoc_storage; - ADM_return_t ret = ADM_register_adhoc_storage( - server, name, ADM_STORAGE_GEKKOFS, ctx, &adhoc_storage); + // All the information required by the ADM_register_adhoc_storage() API is + // now ready. Let's actually contact the server: - if(ret != ADM_SUCCESS) { - fprintf(stderr, - "ADM_register_adhoc_storage() remote procedure not completed " - "successfully: %s\n", + // 1. Find the server endpoint + if((server = ADM_server_create("tcp", argv[1])) == NULL) { + fprintf(stderr, "Fatal error creating server\n"); + goto cleanup; + } + + // 2. Register the adhoc storage + if(ADM_register_adhoc_storage(server, adhoc_name, ADM_STORAGE_GEKKOFS, + adhoc_ctx, &adhoc_storage) != ADM_SUCCESS) { + fprintf(stderr, "ADM_register_adhoc_storage() failed: %s\n", ADM_strerror(ret)); - exit_status = EXIT_FAILURE; goto cleanup; } - fprintf(stdout, "ADM_register_adhoc_storage() remote procedure completed " - "successfully\n"); + // The adhoc storage is now registered into the system :) + exit_status = EXIT_SUCCESS; + + // Once the adhoc storage is no longer required we need to notify the server + if((ret = ADM_remove_adhoc_storage(server, adhoc_storage)) != ADM_SUCCESS) { + fprintf(stderr, "ADM_remove_adhoc_storage() failed: %s\n", + ADM_strerror(ret)); + adhoc_storage = NULL; + exit_status = EXIT_FAILURE; + // intentionally fall through... + } cleanup: ADM_server_destroy(server); + + ADM_adhoc_context_destroy(adhoc_ctx); + ADM_adhoc_resources_destroy(adhoc_resources); + destroy_nodes(adhoc_nodes, NADHOC_NODES); + exit(exit_status); } diff --git a/examples/c/ADM_register_job.c b/examples/c/ADM_register_job.c index 09147bd645471d989da165db20692f1cf8ec9af9..3e44467e6b49dea01e9867455689ec9c80ee3fd7 100644 --- a/examples/c/ADM_register_job.c +++ b/examples/c/ADM_register_job.c @@ -25,7 +25,6 @@ #include #include #include -#include #include "common.h" #define NJOB_NODES 50 @@ -42,82 +41,158 @@ main(int argc, char* argv[]) { exit(EXIT_FAILURE); } - int exit_status = EXIT_SUCCESS; - ADM_server_t server = ADM_server_create("tcp", argv[1]); - - ADM_job_t job; - ADM_node_t* job_nodes = prepare_nodes(NJOB_NODES); - assert(job_nodes); - ADM_node_t* adhoc_nodes = prepare_nodes(NADHOC_NODES); - assert(adhoc_nodes); - ADM_dataset_t* inputs = prepare_datasets("input-dataset-%d", NINPUTS); - assert(inputs); - ADM_dataset_t* outputs = prepare_datasets("output-dataset-%d", NOUTPUTS); - assert(outputs); - - ADM_job_resources_t job_resources = - ADM_job_resources_create(job_nodes, NJOB_NODES); - assert(job_resources); - - ADM_adhoc_resources_t adhoc_resources = - ADM_adhoc_resources_create(adhoc_nodes, NADHOC_NODES); - assert(adhoc_resources); - - ADM_adhoc_context_t ctx = ADM_adhoc_context_create( - ADM_ADHOC_MODE_SEPARATE_NEW, ADM_ADHOC_ACCESS_RDWR, adhoc_resources, - 100, false); - assert(ctx); - - const char* name = "adhoc_storage_42"; - - ADM_storage_t adhoc_storage; - ADM_return_t ret = ADM_register_adhoc_storage( - server, name, ADM_STORAGE_GEKKOFS, ctx, &adhoc_storage); - - if(ret != ADM_SUCCESS) { - fprintf(stderr, - "ADM_register_adhoc_storage() remote procedure not completed " - "successfully: %s\n", - ADM_strerror(ret)); - exit_status = EXIT_FAILURE; + int exit_status = EXIT_FAILURE; + ADM_return_t ret = ADM_SUCCESS; + ADM_server_t server = NULL; + + // adhoc information + const char* adhoc_name = "adhoc_storage_42"; + ADM_node_t* adhoc_nodes = NULL; + ADM_adhoc_resources_t adhoc_resources = NULL; + ADM_adhoc_context_t adhoc_ctx = NULL; + ADM_storage_t adhoc_storage = NULL; + + // job information + ADM_node_t* job_nodes = NULL; + ADM_job_t job = NULL; + ADM_job_resources_t job_resources = NULL; + ADM_job_requirements_t reqs = NULL; + uint64_t slurm_job_id = 42; + ADM_dataset_t* inputs = NULL; + ADM_dataset_t* outputs = NULL; + + // Let's prepare all the information required by the API calls. + // ADM_register_job() often requires an adhoc storage to have been + // registered onto the system, so let's prepare first the data required + // to call ADM_register_adhoc_storage(): + + // 1. the jobs required by the associated adhoc storage + adhoc_nodes = prepare_nodes(NADHOC_NODES); + + if(adhoc_nodes == NULL) { + fprintf(stderr, "Fatal error preparing adhoc nodes\n"); goto cleanup; } - ADM_job_requirements_t reqs = ADM_job_requirements_create( - inputs, NINPUTS, outputs, NOUTPUTS, adhoc_storage); - assert(reqs); + // 2. the adhoc storage resources + adhoc_resources = ADM_adhoc_resources_create(adhoc_nodes, NADHOC_NODES); - uint64_t slurm_job_id = 42; - ret = ADM_register_job(server, job_resources, reqs, slurm_job_id, &job); + if(adhoc_resources == NULL) { + fprintf(stderr, "Fatal error preparing adhoc resources\n"); + goto cleanup; + } + + // 3. the adhoc storage execution context + adhoc_ctx = ADM_adhoc_context_create(ADM_ADHOC_MODE_SEPARATE_NEW, + ADM_ADHOC_ACCESS_RDWR, adhoc_resources, + 100, false); + + if(adhoc_ctx == NULL) { + fprintf(stderr, "Fatal error preparing adhoc context\n"); + goto cleanup; + } - if(ret != ADM_SUCCESS) { - fprintf(stderr, - "ADM_register_job() remote procedure not completed " - "successfully: %s\n", + + // All the information required by the ADM_register_adhoc_storage() API is + // now ready. Let's actually contact the server: + + // 1. Find the server endpoint + if((server = ADM_server_create("tcp", argv[1])) == NULL) { + fprintf(stderr, "Fatal error creating server\n"); + goto cleanup; + } + + // 2. Register the adhoc storage + if(ADM_register_adhoc_storage(server, adhoc_name, ADM_STORAGE_GEKKOFS, + adhoc_ctx, &adhoc_storage) != ADM_SUCCESS) { + fprintf(stderr, "ADM_register_adhoc_storage() failed: %s\n", ADM_strerror(ret)); - exit_status = EXIT_FAILURE; goto cleanup; } - fprintf(stdout, "ADM_register_job() remote procedure completed " - "successfully\n"); -cleanup: - for(int i = 0; i < NINPUTS; ++i) { - ADM_dataset_destroy(inputs[i]); + // Now that we have an existing adhoc storage registered into the + // system, let's prepare all the information for actually registering the + // job with ADM_register_job(): + + // 1. the job's resources + job_nodes = prepare_nodes(NJOB_NODES); + + if(job_nodes == NULL) { + fprintf(stderr, "Fatal error preparing job nodes\n"); + goto cleanup; } - for(int i = 0; i < NOUTPUTS; ++i) { - ADM_dataset_destroy(outputs[i]); + job_resources = ADM_job_resources_create(job_nodes, NJOB_NODES); + + if(job_resources == NULL) { + fprintf(stderr, "Fatal error preparing job resources\n"); + goto cleanup; } - ADM_storage_destroy(adhoc_storage); + // 2. the job's requirements + inputs = prepare_datasets("input-dataset-%d", NINPUTS); - ADM_adhoc_context_destroy(ctx); + if(inputs == NULL) { + fprintf(stderr, "Fatal error preparing input datasets\n"); + goto cleanup; + } - ADM_job_requirements_destroy(reqs); + outputs = prepare_datasets("output-dataset-%d", NOUTPUTS); + + if(outputs == NULL) { + fprintf(stderr, "Fatal error preparing output datasets\n"); + goto cleanup; + } + + if((reqs = ADM_job_requirements_create(inputs, NINPUTS, outputs, NOUTPUTS, + adhoc_storage)) == NULL) { + fprintf(stderr, "ADM_job_requirements_create() failed"); + goto cleanup; + } + + + // All the information required by the ADM_register_job() API is now ready. + // Let's actually contact the server: + if(ADM_register_job(server, job_resources, reqs, slurm_job_id, &job) != + ADM_SUCCESS) { + fprintf(stderr, "ADM_register_job() failed: %s\n", ADM_strerror(ret)); + goto cleanup; + } + + // At this point, the job can execute... + exit_status = EXIT_SUCCESS; - ADM_remove_job(server, job); + // When the job finishes, it is necessary to notify the server + if((ret = ADM_remove_job(server, job)) != ADM_SUCCESS) { + fprintf(stderr, "ADM_remove_job() failed: %s\n", ADM_strerror(ret)); + job = NULL; + exit_status = EXIT_FAILURE; + // intentionally fall through... + } + + // It is also nice to remove the adhoc storage instance once it's no + // longer needed + if((ret = ADM_remove_adhoc_storage(server, adhoc_storage)) != ADM_SUCCESS) { + fprintf(stderr, "ADM_remove_adhoc_storage() failed: %s\n", + ADM_strerror(ret)); + adhoc_storage = NULL; + exit_status = EXIT_FAILURE; + // intentionally fall through... + } + +cleanup: ADM_server_destroy(server); + + ADM_job_requirements_destroy(reqs); + destroy_datasets(outputs, NOUTPUTS); + destroy_datasets(inputs, NINPUTS); + ADM_job_resources_destroy(job_resources); + destroy_nodes(job_nodes, NJOB_NODES); + + ADM_adhoc_context_destroy(adhoc_ctx); + ADM_adhoc_resources_destroy(adhoc_resources); + destroy_nodes(adhoc_nodes, NADHOC_NODES); + exit(exit_status); } diff --git a/examples/c/ADM_register_pfs_storage.c b/examples/c/ADM_register_pfs_storage.c index d5c86e0be58ed0bb5f226839b4281c587d20e5c3..413f22e140736b852f957872fb1b460104ed8b29 100644 --- a/examples/c/ADM_register_pfs_storage.c +++ b/examples/c/ADM_register_pfs_storage.c @@ -43,15 +43,6 @@ main(int argc, char* argv[]) { int exit_status = EXIT_SUCCESS; ADM_server_t server = ADM_server_create("tcp", argv[1]); - ADM_dataset_t* inputs = prepare_datasets("input-dataset-%d", NINPUTS); - assert(inputs); - ADM_dataset_t* outputs = prepare_datasets("output-dataset-%d", NOUTPUTS); - assert(outputs); - - ADM_job_requirements_t reqs = ADM_job_requirements_create( - inputs, NINPUTS, outputs, NOUTPUTS, NULL); - assert(reqs); - ADM_storage_t pfs_storage; ADM_pfs_context_t ctx = ADM_pfs_context_create("/gpfs"); diff --git a/examples/c/ADM_remove_adhoc_storage.c b/examples/c/ADM_remove_adhoc_storage.c index 98a7459674d7aae93d53cdf45955cf931a263b6d..34a0dca670ae381ae5c6bd8a6ad85283ff6f2ecd 100644 --- a/examples/c/ADM_remove_adhoc_storage.c +++ b/examples/c/ADM_remove_adhoc_storage.c @@ -25,7 +25,6 @@ #include #include #include -#include #include "common.h" #define NADHOC_NODES 25 @@ -41,58 +40,87 @@ main(int argc, char* argv[]) { exit(EXIT_FAILURE); } - int exit_status = EXIT_SUCCESS; - ADM_server_t server = ADM_server_create("tcp", argv[1]); + int exit_status = EXIT_FAILURE; + ADM_return_t ret = ADM_SUCCESS; + ADM_server_t server = NULL; - ADM_node_t* adhoc_nodes = prepare_nodes(NADHOC_NODES); - assert(adhoc_nodes); - ADM_dataset_t* inputs = prepare_datasets("input-dataset-%d", NINPUTS); - assert(inputs); - ADM_dataset_t* outputs = prepare_datasets("output-dataset-%d", NOUTPUTS); - assert(outputs); + // adhoc information + const char* adhoc_name = "adhoc_storage_42"; - ADM_adhoc_resources_t adhoc_resources = - ADM_adhoc_resources_create(adhoc_nodes, NADHOC_NODES); - assert(adhoc_resources); + ADM_node_t* adhoc_nodes = NULL; + ADM_adhoc_resources_t adhoc_resources = NULL; + ADM_adhoc_context_t adhoc_ctx = NULL; + ADM_storage_t adhoc_storage = NULL; - ADM_adhoc_context_t ctx = ADM_adhoc_context_create( - ADM_ADHOC_MODE_SEPARATE_NEW, ADM_ADHOC_ACCESS_RDWR, adhoc_resources, - 100, false); - assert(ctx); - const char* name = "adhoc_storage_42"; + // Let's prepare all the information required by the API calls. + // ADM_remove_adhoc_storage() obviously requires an adhoc storage to have + // been registered onto the system, so let's prepare first the data required + // to call ADM_register_adhoc_storage(): - ADM_storage_t adhoc_storage; - ADM_return_t ret = ADM_register_adhoc_storage( - server, name, ADM_STORAGE_GEKKOFS, ctx, &adhoc_storage); + // 1. the jobs required by the associated adhoc storage + adhoc_nodes = prepare_nodes(NADHOC_NODES); - if(ret != ADM_SUCCESS) { - fprintf(stderr, - "ADM_register_adhoc_storage() remote procedure not completed " - "successfully: %s\n", + if(adhoc_nodes == NULL) { + fprintf(stderr, "Fatal error preparing adhoc nodes\n"); + goto cleanup; + } + + // 2. the adhoc storage resources + adhoc_resources = ADM_adhoc_resources_create(adhoc_nodes, NADHOC_NODES); + + if(adhoc_resources == NULL) { + fprintf(stderr, "Fatal error preparing adhoc resources\n"); + goto cleanup; + } + + // 3. the adhoc storage execution context + adhoc_ctx = ADM_adhoc_context_create(ADM_ADHOC_MODE_SEPARATE_NEW, + ADM_ADHOC_ACCESS_RDWR, adhoc_resources, + 100, false); + + if(adhoc_ctx == NULL) { + fprintf(stderr, "Fatal error preparing adhoc context\n"); + goto cleanup; + } + + + // All the information required by the ADM_register_adhoc_storage() API is + // now ready. Let's actually contact the server: + + // 1. Find the server endpoint + if((server = ADM_server_create("tcp", argv[1])) == NULL) { + fprintf(stderr, "Fatal error creating server\n"); + goto cleanup; + } + + // 2. Register the adhoc storage + if(ADM_register_adhoc_storage(server, adhoc_name, ADM_STORAGE_GEKKOFS, + adhoc_ctx, &adhoc_storage) != ADM_SUCCESS) { + fprintf(stderr, "ADM_register_adhoc_storage() failed: %s\n", ADM_strerror(ret)); - exit_status = EXIT_FAILURE; goto cleanup; } - fprintf(stdout, "ADM_register_adhoc_storage() remote procedure completed " - "successfully\n"); - ret = ADM_remove_adhoc_storage(server, adhoc_storage); + // Now that we have an existing adhoc storage registered into the system + // we can try to remove it... - if(ret != ADM_SUCCESS) { - fprintf(stderr, - "ADM_remove_adhoc_storage() remote procedure not completed " - "successfully: %s\n", + if((ret = ADM_remove_adhoc_storage(server, adhoc_storage)) != ADM_SUCCESS) { + fprintf(stderr, "ADM_remove_adhoc_storage() failed: %s\n", ADM_strerror(ret)); - exit_status = EXIT_FAILURE; goto cleanup; } - fprintf(stdout, "ADM_remove_adhoc_storage() remote procedure completed " - "successfully\n"); + // Everything is fine now... + exit_status = EXIT_SUCCESS; cleanup: ADM_server_destroy(server); + + ADM_adhoc_context_destroy(adhoc_ctx); + ADM_adhoc_resources_destroy(adhoc_resources); + destroy_nodes(adhoc_nodes, NADHOC_NODES); + exit(exit_status); } diff --git a/examples/c/ADM_update_adhoc_storage.c b/examples/c/ADM_update_adhoc_storage.c index 3024bdb98620f9647fcce5c6fbca05a1ae9cbe75..2c58d640a85261097c8eb6f9e640d8a7f30dbcd7 100644 --- a/examples/c/ADM_update_adhoc_storage.c +++ b/examples/c/ADM_update_adhoc_storage.c @@ -25,7 +25,6 @@ #include #include #include -#include #include "common.h" #define NADHOC_NODES 25 @@ -41,77 +40,109 @@ main(int argc, char* argv[]) { exit(EXIT_FAILURE); } - int exit_status = EXIT_SUCCESS; - ADM_server_t server = ADM_server_create("tcp", argv[1]); + int exit_status = EXIT_FAILURE; + ADM_return_t ret = ADM_SUCCESS; + ADM_server_t server = NULL; - ADM_node_t* adhoc_nodes = prepare_nodes(NADHOC_NODES); - assert(adhoc_nodes); - ADM_dataset_t* inputs = prepare_datasets("input-dataset-%d", NINPUTS); - assert(inputs); - ADM_dataset_t* outputs = prepare_datasets("output-dataset-%d", NOUTPUTS); - assert(outputs); + // adhoc information + const char* adhoc_name = "adhoc_storage_42"; - ADM_adhoc_resources_t adhoc_resources = - ADM_adhoc_resources_create(adhoc_nodes, NADHOC_NODES); - assert(adhoc_resources); + ADM_node_t* adhoc_nodes = NULL; + ADM_adhoc_resources_t adhoc_resources = NULL; + ADM_adhoc_context_t adhoc_ctx = NULL; + ADM_adhoc_context_t new_adhoc_ctx = NULL; + ADM_storage_t adhoc_storage = NULL; - ADM_adhoc_context_t ctx = ADM_adhoc_context_create( - ADM_ADHOC_MODE_SEPARATE_NEW, ADM_ADHOC_ACCESS_RDWR, adhoc_resources, - 100, false); - assert(ctx); - const char* name = "adhoc_storage_42"; + // Let's prepare all the information required by the API calls. + // ADM_update_adhoc_storage() obviously requires an adhoc storage to have + // been registered onto the system, so let's prepare first the data required + // to call ADM_register_adhoc_storage(): - ADM_storage_t adhoc_storage; - ADM_return_t ret = ADM_register_adhoc_storage( - server, name, ADM_STORAGE_GEKKOFS, ctx, &adhoc_storage); + // 1. the jobs required by the associated adhoc storage + adhoc_nodes = prepare_nodes(NADHOC_NODES); - if(ret != ADM_SUCCESS) { - fprintf(stderr, - "ADM_register_adhoc_storage() remote procedure not completed " - "successfully: %s\n", - ADM_strerror(ret)); - exit_status = EXIT_FAILURE; + if(adhoc_nodes == NULL) { + fprintf(stderr, "Fatal error preparing adhoc nodes\n"); + goto cleanup; + } + + // 2. the adhoc storage resources + adhoc_resources = ADM_adhoc_resources_create(adhoc_nodes, NADHOC_NODES); + + if(adhoc_resources == NULL) { + fprintf(stderr, "Fatal error preparing adhoc resources\n"); goto cleanup; } - fprintf(stdout, "ADM_register_adhoc_storage() remote procedure completed " - "successfully\n"); + // 3. the adhoc storage execution context + adhoc_ctx = ADM_adhoc_context_create(ADM_ADHOC_MODE_SEPARATE_NEW, + ADM_ADHOC_ACCESS_RDWR, adhoc_resources, + 100, false); + + if(adhoc_ctx == NULL) { + fprintf(stderr, "Fatal error preparing adhoc context\n"); + goto cleanup; + } - ADM_adhoc_context_t new_ctx = ADM_adhoc_context_create( - ADM_ADHOC_MODE_SEPARATE_NEW, ADM_ADHOC_ACCESS_RDWR, adhoc_resources, - 200, false); - assert(new_ctx); - ret = ADM_update_adhoc_storage(server, new_ctx, adhoc_storage); + // All the information required by the ADM_register_adhoc_storage() API is + // now ready. Let's actually contact the server: + + // 1. Find the server endpoint + if((server = ADM_server_create("tcp", argv[1])) == NULL) { + fprintf(stderr, "Fatal error creating server\n"); + goto cleanup; + } - if(ret != ADM_SUCCESS) { - fprintf(stderr, - "ADM_update_adhoc_storage() remote procedure not completed " - "successfully: %s\n", + // 2. Register the adhoc storage + if(ADM_register_adhoc_storage(server, adhoc_name, ADM_STORAGE_GEKKOFS, + adhoc_ctx, &adhoc_storage) != ADM_SUCCESS) { + fprintf(stderr, "ADM_register_adhoc_storage() failed: %s\n", ADM_strerror(ret)); - exit_status = EXIT_FAILURE; goto cleanup; } - fprintf(stdout, "ADM_update_adhoc_storage() remote procedure completed " - "successfully\n"); -cleanup: - for(int i = 0; i < NINPUTS; ++i) { - ADM_dataset_destroy(inputs[i]); + // Now that we have an existing adhoc storage registered into the + // system, let's prepare a new execution context for the adhoc + // storage system + + new_adhoc_ctx = ADM_adhoc_context_create(ADM_ADHOC_MODE_SEPARATE_NEW, + ADM_ADHOC_ACCESS_RDWR, + adhoc_resources, 200, false); + + if(new_adhoc_ctx == NULL) { + fprintf(stderr, "Fatal error preparing new adhoc context\n"); + goto cleanup; } - for(int i = 0; i < NOUTPUTS; ++i) { - ADM_dataset_destroy(outputs[i]); + // We can now request the update to the server + if((ret = ADM_update_adhoc_storage(server, new_adhoc_ctx, adhoc_storage)) != + ADM_SUCCESS) { + fprintf(stderr, "ADM_update_adhoc_storage() failed: %s\n", + ADM_strerror(ret)); + goto cleanup; } - ADM_storage_destroy(adhoc_storage); + // At this point, the adhoc storage has been updated... + exit_status = EXIT_SUCCESS; - ADM_adhoc_context_destroy(ctx); + // Once the adhoc storage is no longer required we need to notify the server + if((ret = ADM_remove_adhoc_storage(server, adhoc_storage)) != ADM_SUCCESS) { + fprintf(stderr, "ADM_remove_adhoc_storage() failed: %s\n", + ADM_strerror(ret)); + adhoc_storage = NULL; + exit_status = EXIT_FAILURE; + // intentionally fall through... + } - ADM_adhoc_context_destroy(new_ctx); +cleanup: ADM_server_destroy(server); + ADM_adhoc_context_destroy(new_adhoc_ctx); + ADM_adhoc_context_destroy(adhoc_ctx); + ADM_adhoc_resources_destroy(adhoc_resources); + destroy_nodes(adhoc_nodes, NADHOC_NODES); exit(exit_status); } diff --git a/examples/c/common.c b/examples/c/common.c index ccb779b479865771992171b8f211fe4ec260e290..19c7ece29fb6b1b6ca769ff85826b92c53eb08a7 100644 --- a/examples/c/common.c +++ b/examples/c/common.c @@ -27,6 +27,22 @@ prepare_nodes(size_t n) { return nodes; } +void +destroy_nodes(ADM_node_t nodes[], size_t n) { + + if(!nodes) { + return; + } + + for(size_t i = 0; i < n; ++i) { + if(nodes[i]) { + ADM_node_destroy(nodes[i]); + } + } + + free(nodes); +} + ADM_dataset_t* prepare_datasets(const char* pattern, size_t n) { @@ -52,6 +68,10 @@ prepare_datasets(const char* pattern, size_t n) { void destroy_datasets(ADM_dataset_t datasets[], size_t n) { + if(!datasets) { + return; + } + for(size_t i = 0; i < n; ++i) { if(datasets[i]) { ADM_dataset_destroy(datasets[i]); @@ -83,6 +103,10 @@ prepare_qos_limits(size_t n) { void destroy_qos_limits(ADM_qos_limit_t* limits, size_t n) { + if(!limits) { + return; + } + for(size_t i = 0; i < n; ++i) { if(limits[i]) { ADM_qos_limit_destroy(limits[i]); diff --git a/examples/c/common.h b/examples/c/common.h index 43e0536ee863c8c60df3ded0ff2c4cd88e247ef4..92f0d9c1793a87fcbaa6dcb6ca719516816932ab 100644 --- a/examples/c/common.h +++ b/examples/c/common.h @@ -6,6 +6,9 @@ ADM_node_t* prepare_nodes(size_t n); +void +destroy_nodes(ADM_node_t nodes[], size_t n); + ADM_dataset_t* prepare_datasets(const char* pattern, size_t n);