]> git.ipfire.org Git - pakfire.git/commitdiff
job: Implement some way to submit the job result
authorMichael Tremer <michael.tremer@ipfire.org>
Thu, 26 Jun 2025 16:00:41 +0000 (16:00 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 26 Jun 2025 16:00:41 +0000 (16:00 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/pakfire/client.c
src/pakfire/client.h
src/pakfire/job.c

index 362e2b5a9de8aa71f4597d382f159d3e7fdfdcda..dab66c8fe49211b61c0a40b8ce7f872c269b111f 100644 (file)
@@ -1414,3 +1414,58 @@ ERROR:
 
        return r;
 }
+
+/*
+       This is called when a job has finished.
+*/
+int pakfire_client_job_finished(struct pakfire_client* self,
+               const char* job_id, const char* logfile, char** packages) {
+       struct json_object* request = NULL;
+       struct pakfire_xfer* xfer = NULL;
+       int r;
+
+       // Create a new request object
+       r = pakfire_json_new_object(&request);
+       if (r < 0)
+               goto ERROR;
+
+       // XXX Add status
+
+       // Add the logfile
+       if (logfile) {
+               r = pakfire_json_add_string(request, "logfile", logfile);
+               if (r < 0)
+                       goto ERROR;
+       }
+
+       // Add the packages
+       if (packages) {
+               r = pakfire_json_add_string_array(request, "packages", packages);
+               if (r < 0)
+                       goto ERROR;
+       }
+
+       // Create a new transfer
+       r = pakfire_client_xfer_create(&xfer, self, "/api/v1/jobs/%s", job_id);
+       if (r < 0)
+               goto ERROR;
+
+       // Enable authentication
+       r = pakfire_client_xfer_auth(self, xfer);
+       if (r < 0)
+               goto ERROR;
+
+       // Set the request body
+       r = pakfire_xfer_set_json_payload(xfer, request);
+       if (r < 0)
+               goto ERROR;
+
+       // Enqueue the transfer
+       r = pakfire_httpclient_enqueue(self->httpclient, xfer);
+
+ERROR:
+       if (xfer)
+               pakfire_xfer_unref(xfer);
+
+       return r;
+}
index 59b4bd191c24f312d2493e8af71a6c168c57a186..b19346d2b5591378ed2e545eb7a6600c073d8e67 100644 (file)
@@ -110,4 +110,9 @@ int pakfire_client_create_repo(struct pakfire_client* client,
 int pakfire_client_delete_repo(struct pakfire_client* client,
        const char* distro, const char* name);
 
+// Jobs
+
+int pakfire_client_job_finished(struct pakfire_client* self,
+       const char* job_id, const char* logfile, char** packages);
+
 #endif /* PAKFIRE_CLIENT_H */
index b6a39e9494eef79673ad6472b0d369829e13bafa..3514e3b04d9bb095930329764bab010afb8a16b8 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <fts.h>
 #include <limits.h>
 #include <linux/sched.h>
 #include <unistd.h>
@@ -43,6 +44,7 @@
 #include <pakfire/log_buffer.h>
 #include <pakfire/log_stream.h>
 #include <pakfire/logging.h>
+#include <pakfire/path.h>
 #include <pakfire/proctitle.h>
 #include <pakfire/string.h>
 #include <pakfire/syscalls.h>
@@ -116,6 +118,9 @@ struct pakfire_job {
        struct pakfire_job_uploads {
                char* logfile;
                char** packages;
+
+               // Count how many uploads are running
+               int running;
        } uploads;
 };
 
@@ -276,42 +281,99 @@ static void pakfire_job_free(struct pakfire_job* job) {
        free(job);
 }
 
-static int pakfire_job_xfer_create(struct pakfire_xfer** xfer,
-       struct pakfire_job* job, const char* url, ...) __attribute__((format(printf, 3, 4)));
 
-static int pakfire_job_xfer_create(struct pakfire_xfer** xfer,
-               struct pakfire_job* job, const char* url, ...) {
-       struct pakfire_xfer* x = NULL;
-       va_list args;
+static int pakfire_job_finished(struct pakfire_job* self) {
        int r;
 
-       va_start(args, url);
-
-       // Create a new xfer
-       r = pakfire_xfer_create(&x, job->ctx, url, args);
+       // Submit the request
+       r = pakfire_client_job_finished(self->client,
+                       self->id, self->uploads.logfile, self->uploads.packages);
        if (r < 0)
-               goto ERROR;
+               ERROR(self->ctx, "Failed to submit the finish request: %s\n", strerror(-r));
 
-#if 0
-       // Set the base URL
-       r = pakfire_xfer_set_baseurl(x, pakfire_daemon_url(job->daemon));
-       if (r < 0)
-               goto ERROR;
-#endif
+       // Let the builder know this is finished
+       return pakfire_builder_job_finished(self->builder, self);
+}
+
+static int pakfire_job_package_uploaded(struct pakfire_client* client,
+               pakfire_client_upload_status status, const char* path, const char* uuid, void* data) {
+       struct pakfire_job* self = data;
+       int r;
 
-       // Success
-       *xfer = pakfire_xfer_ref(x);
+       // Now we have one less uploads running
+       self->uploads.running--;
 
-ERROR:
-       if (x)
-               pakfire_xfer_unref(x);
-       va_end(args);
+       switch (status) {
+               case PAKFIRE_CLIENT_UPLOAD_SUCCESSFUL:
+                       // Store the ID of the upload
+                       r = pakfire_strings_append(&self->uploads.packages, uuid);
+                       if (r < 0)
+                               return r;
+                       break;
 
-       return r;
+               default:
+                       ERROR(self->ctx, "Failed to upload %s: %s\n", path, strerror(status));
+
+                       // XXX What do we do here?
+
+                       return status;
+       }
+
+       // Don't do anything if there are any other uploads still running
+       if (self->uploads.running)
+               return 0;
+
+       // Finish the job
+       return pakfire_job_finished(self);
 }
 
 static int pakfire_job_upload_packages(struct pakfire_job* self) {
-       return 0; // XXX TODO
+       FTSENT* entry = NULL;
+       FTS* fts = NULL;
+       int r = 0;
+
+       char* paths[] = {
+               self->resultdir, NULL,
+       };
+
+       // Open the path
+       fts = fts_open(paths, FTS_PHYSICAL|FTS_NOCHDIR|FTS_NOSTAT, NULL);
+       if (!fts) {
+               ERROR(self->ctx, "Could not open %s: %m\n", self->resultdir);
+               r = -errno;
+               goto ERROR;
+       }
+
+       // Scan for everything
+       for (;;) {
+               // Fetch the next entry
+               entry = fts_read(fts);
+               if (!entry)
+                       break;
+
+               // We only care about actual files
+               if (!(entry->fts_info & FTS_F))
+                       continue;
+
+               // Skip anything that doesn't have the correct file extension
+               if (!pakfire_path_match("**.pfm", entry->fts_path))
+                       continue;
+
+               // Upload the package
+               r = pakfire_client_upload(self->client, entry->fts_path, entry->fts_name,
+                               pakfire_job_package_uploaded, self);
+               if (r < 0)
+                       goto ERROR;
+
+               // Now there is one more upload running
+               self->uploads.running++;
+       }
+
+ERROR:
+       if (fts)
+               fts_close(fts);
+
+       return r;
 }
 
 /*
@@ -344,98 +406,13 @@ static int pakfire_job_logfile_uploaded(struct pakfire_client* client,
        return pakfire_job_upload_packages(self);
 }
 
-/*
-       Called when the job has finished with status as the error code.
-*/
-static int pakfire_job_finished(struct pakfire_job* job, const siginfo_t* si) {
-       struct pakfire_xfer* xfer = NULL;
-       const char* filename = NULL;
-       const char* path = NULL;
-       int r;
-
-       // Close the log file
-       r = pakfire_log_file_close(job->log.file);
-       if (r < 0) {
-               ERROR(job->ctx, "Could not close the log file: %s\n", strerror(-r));
-               goto ERROR;
-       }
-
-       // Fetch the filename of the log file
-       filename = pakfire_log_file_filename(job->log.file);
-       if (!filename) {
-               ERROR(job->ctx, "Log file has no filename\n");
-               r = -EINVAL;
-               goto ERROR;
-       }
-
-       // Fetch the path of the log file
-       path = pakfire_log_file_path(job->log.file);
-       if (!path) {
-               ERROR(job->ctx, "Log file has no path\n");
-               r = -EINVAL;
-               goto ERROR;
-       }
-
-       // Upload the log file
-       r = pakfire_client_upload(job->client, path, filename, pakfire_job_logfile_uploaded, job);
-       if (r < 0) {
-               ERROR(job->ctx, "Could not upload the log file: %s\n", strerror(-r));
-               goto ERROR;
-       }
-
-#if 0
-       // Create a new xfer
-       r = pakfire_job_xfer_create(&xfer, job, "/api/v1/jobs/%s/finished", job->id);
-       if (r < 0)
-               goto ERROR;
-
-       // Enable authentication
-       r = pakfire_xfer_auth(xfer);
-       if (r < 0)
-               goto ERROR;
-
-       // Has the job been successful?
-       r = pakfire_xfer_add_param(xfer, "success", "%s", (status == 0) ? "true" : "false");
-       if (r < 0)
-               goto ERROR;
-
-       // Logfile
-       if (logfile) {
-               r = pakfire_xfer_add_param(xfer, "logfile", "%s", logfile);
-               if (r)
-                       goto ERROR;
-       }
-
-       // Packages
-       if (job->uploads) {
-               for (char** upload = job->uploads; *upload; upload++) {
-                       r = pakfire_xfer_add_param(xfer, "package", "%s", *upload);
-                       if (r < 0)
-                               goto ERROR;
-               }
-       }
-
-       // Send the request
-       r = pakfire_xfer_run_api_request(xfer, NULL, NULL);
-       if (r < 0)
-               goto ERROR;
-#endif
-
-       // Let the builder know this is finished
-       r = pakfire_builder_job_finished(job->builder, job);
-
-ERROR:
-       if (xfer)
-               pakfire_xfer_unref(xfer);
-
-       return r;
-}
-
 static int pakfire_job_result(struct pakfire_ctx* ctx, struct pakfire* pakfire,
                struct pakfire_build* build, struct pakfire_archive* archive, void* data) {
-       struct pakfire_job* job = data;
+       struct pakfire_job* self = data;
        struct pakfire_package* pkg = NULL;
-       char* uuid = NULL;
+       const char* filename = NULL;
+       const char* nevra = NULL;
+       char path[PATH_MAX];
        int r;
 
        // Fetch package metadata
@@ -444,45 +421,34 @@ static int pakfire_job_result(struct pakfire_ctx* ctx, struct pakfire* pakfire,
                goto ERROR;
 
        // Fetch NEVRA
-       const char* nevra = pakfire_package_get_string(pkg, PAKFIRE_PKG_NEVRA);
+       nevra = pakfire_package_get_string(pkg, PAKFIRE_PKG_NEVRA);
        if (!nevra) {
                r = -EINVAL;
                goto ERROR;
        }
 
        // Fetch filename
-       const char* filename = pakfire_package_get_filename(pkg);
+       filename = pakfire_package_get_filename(pkg);
        if (!filename) {
                r = -EINVAL;
                goto ERROR;
        }
 
-       // Fetch path
-       const char* path = pakfire_archive_get_path(archive);
-       if (!path) {
-               r = -EINVAL;
+       // Make the path
+       r = pakfire_path_format(path, "%s/%s", self->resultdir, filename);
+       if (r < 0)
                goto ERROR;
-       }
 
-#if 0
-       // Upload the file
-       r = pakfire_client_upload(job->client, path, filename, &uuid);
+       // Copy the archive to the result directory
+       r = pakfire_archive_copy(archive, path);
        if (r < 0) {
-               ERROR(job->ctx, "Could not upload %s: %s\n", nevra, strerror(-r));
+               ERROR(self->ctx, "Failed to copy %s to %s: %s\n", nevra, path, strerror(-r));
                goto ERROR;
        }
-#endif
-
-       // Store the ID of the upload
-       r = pakfire_strings_append(&job->uploads.packages, uuid);
-       if (r < 0)
-               goto ERROR;
 
 ERROR:
        if (pkg)
                pakfire_package_unref(pkg);
-       if (uuid)
-               free(uuid);
 
        return r;
 }
@@ -492,6 +458,10 @@ ERROR:
 */
 static int pakfire_job_exited(sd_event_source* s, const siginfo_t* si, void* data) {
        struct pakfire_job* job = data;
+       struct pakfire_xfer* xfer = NULL;
+       const char* filename = NULL;
+       const char* path = NULL;
+       int r;
 
        switch (si->si_code) {
                case CLD_EXITED:
@@ -511,8 +481,41 @@ static int pakfire_job_exited(sd_event_source* s, const siginfo_t* si, void* dat
                        break;
        }
 
-       // Signal that the job has finished
-       return pakfire_job_finished(job, si);
+       // Close the log file
+       r = pakfire_log_file_close(job->log.file);
+       if (r < 0) {
+               ERROR(job->ctx, "Could not close the log file: %s\n", strerror(-r));
+               goto ERROR;
+       }
+
+       // Fetch the filename of the log file
+       filename = pakfire_log_file_filename(job->log.file);
+       if (!filename) {
+               ERROR(job->ctx, "Log file has no filename\n");
+               r = -EINVAL;
+               goto ERROR;
+       }
+
+       // Fetch the path of the log file
+       path = pakfire_log_file_path(job->log.file);
+       if (!path) {
+               ERROR(job->ctx, "Log file has no path\n");
+               r = -EINVAL;
+               goto ERROR;
+       }
+
+       // Upload the log file
+       r = pakfire_client_upload(job->client, path, filename, pakfire_job_logfile_uploaded, job);
+       if (r < 0) {
+               ERROR(job->ctx, "Could not upload the log file: %s\n", strerror(-r));
+               goto ERROR;
+       }
+
+ERROR:
+       if (xfer)
+               pakfire_xfer_unref(xfer);
+
+       return r;
 }
 
 static int pakfire_job_send_log(struct pakfire_job* job, int priority, const char* line, size_t length) {