gnss: use sendfile to upload xtra data

This should make the data upload much faster because it handles
incomplete writes better, and because it the kernel copies the data
between the files directly, and it doesn't get sent to userspace and
back.
This commit is contained in:
ArenM
2021-09-07 19:48:40 -04:00
parent 750c41cbb5
commit 6177c7167c

View File

@@ -8,8 +8,12 @@
#include "manager.h"
#include "at.h"
#include <sys/sendfile.h>
#include <sys/stat.h>
#include <errno.h>
#define BUFFER_SIZE 256
#define UPLOAD_DELAY 100000
#define UPLOAD_DELAY_US 10000
#define RESCHEDULE_IN_SECS 30
static void gnss_step(struct EG25Manager *manager);
@@ -297,39 +301,34 @@ static void init_assistance_data_upload(struct EG25Manager *manager)
static void upload_assistance_data(struct EG25Manager *manager)
{
char buffer[2*BUFFER_SIZE];
gint len;
gboolean success = TRUE;
gint error;
glong written_total = 0;
gint ret;
struct stat sb;
if (fstat(manager->gnss_assistance_fd, &sb) != 0) {
g_error("Unable to upload xtra data: %s", g_strerror(errno));
}
do {
errno = 0;
/* Copy downloaded XTRA assistance data to the modem over serial */
while((len = read(manager->gnss_assistance_fd, buffer, 2*BUFFER_SIZE)) > 0)
{
len = write(manager->at_fd, buffer, len);
if (len < 0) {
success = FALSE;
g_error("Writing GNSS assistance data failed: %d", len);
break;
}
usleep(UPLOAD_DELAY);
g_message("Uploaded %d bytes", len);
}
ret = sendfile(manager->at_fd, manager->gnss_assistance_fd, &written_total, sb.st_size);
error = errno;
usleep(UPLOAD_DELAY_US);
} while ((!error && written_total < sb.st_size) || (ret == -1 && error == EAGAIN));
/* Clear QFUPL AT command and process next */
at_next_command(manager);
/* Go to the next step if successful */
if (success) {
if (!error) {
g_message("Successfully uploaded %ld bytes to the modem", written_total);
manager->gnss_assistance_step++;
gnss_step(manager);
}
/* Restart upload */
else {
g_message ("Rescheduling upload because of failure in %ds",
RESCHEDULE_IN_SECS);
} else {
g_critical("Unable to upload xtra data: %s", g_strerror(error));
manager->gnss_assistance_step = EG25_GNSS_STEP_LAST;
g_timeout_add_seconds(RESCHEDULE_IN_SECS,
G_SOURCE_FUNC(gnss_upload_assistance_data),
manager);
}
}