Skip to content

Commit

Permalink
Move locking functionality into libprofilemanifest and modify the dbu…
Browse files Browse the repository at this point in the history
…s-service and run-activity tools to use it
  • Loading branch information
svanderburg committed Jan 29, 2018
1 parent c7577c4 commit b58a338
Show file tree
Hide file tree
Showing 9 changed files with 200 additions and 295 deletions.
150 changes: 13 additions & 137 deletions src/dbus-service/locking.c
Expand Up @@ -18,163 +18,39 @@
*/

#include "locking.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "state-management.h"
#include "procreact_pid.h"
#include <procreact_pid.h>
#include <procreact_future.h>
#include <profilelocking.h>

extern char *tmpdir;

static int lock_or_unlock_services(int log_fd, GPtrArray *profile_manifest_array, gchar *action, pid_t (*notify_function) (gchar *type, gchar *container, gchar *component, int stdout, int stderr))
{
unsigned int i;
int exit_status = TRUE;

/* Notify all services for a lock or unlock */
for(i = 0; i < profile_manifest_array->len; i++)
{
ProfileManifestEntry *entry = g_ptr_array_index(profile_manifest_array, i);
pid_t pid;
ProcReact_Status status;
int result;

dprintf(log_fd, "Notifying %s on %s: of type: %s in container: %s\n", action, entry->service, entry->type, entry->container);
pid = notify_function(entry->type, entry->container, entry->service, log_fd, log_fd);
result = procreact_wait_for_boolean(pid, &status);

if(status != PROCREACT_STATUS_OK || !result)
{
dprintf(log_fd, "Cannot %s service!\n", action);
exit_status = FALSE;
}
}

return exit_status;
}

static int unlock_services(int log_fd, GPtrArray *profile_manifest_array)
{
return lock_or_unlock_services(log_fd, profile_manifest_array, "unlock", statemgmt_unlock_component);
}

static int lock_services(int log_fd, GPtrArray *profile_manifest_array)
{
return lock_or_unlock_services(log_fd, profile_manifest_array, "lock", statemgmt_lock_component);
}

static gchar *create_lock_filename(gchar *profile)
{
return g_strconcat(tmpdir, "/disnix-", profile, ".lock", NULL);
}

static int lock_profile(int log_fd, gchar *profile)
{
int fd, status;
gchar *lock_filename = create_lock_filename(profile);

/* If no lock exists, try to create one */
if((fd = open(lock_filename, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR)) == -1)
{
dprintf(log_fd, "Cannot exclusively open the lock file!\n");
status = FALSE;
}
else
{
close(fd);
status = TRUE;
}

g_free(lock_filename);
return status;
}

static int unlock_profile(int log_fd, gchar *profile)
{
gchar *lock_filename = create_lock_filename(profile);
int status;

if(unlink(lock_filename) == -1)
{
dprintf(log_fd, "There is no lock file!\n");
status = FALSE;
}
else
status = TRUE;

/* Cleanup */
g_free(lock_filename);

return status;
}

int acquire_locks(int log_fd, GPtrArray *profile_manifest_array, gchar *profile)
{
if(lock_services(log_fd, profile_manifest_array)) /* Attempt to acquire locks from the services */
return lock_profile(log_fd, profile); /* Finally, lock the profile */
else
{
unlock_services(log_fd, profile_manifest_array);
return FALSE;
}
}

pid_t acquire_locks_async(int log_fd, GPtrArray *profile_manifest_array, gchar *profile)
pid_t acquire_locks_async(int log_fd, gchar *tmpdir, GPtrArray *profile_manifest_array, gchar *profile)
{
pid_t pid = fork();

if(pid == 0)
_exit(!acquire_locks(log_fd, profile_manifest_array, profile));

return pid;
}
_exit(!acquire_locks(log_fd, tmpdir, profile_manifest_array, profile));

int release_locks(int log_fd, GPtrArray *profile_manifest_array, gchar *profile)
{
int status = TRUE;

if(profile_manifest_array == NULL)
{
dprintf(log_fd, "Corrupt profile manifest: a service or type is missing!\n");
status = FALSE;
}
else
{
if(!unlock_services(log_fd, profile_manifest_array))
{
dprintf(log_fd, "Failed to send unlock notification to old services!\n");
status = FALSE;
}
}

if(!unlock_profile(log_fd, profile))
status = FALSE; /* There was no lock -> fail */

return status;
return pid;
}

pid_t release_locks_async(int log_fd, GPtrArray *profile_manifest_array, gchar *profile)
pid_t release_locks_async(int log_fd, gchar *tmpdir, GPtrArray *profile_manifest_array, gchar *profile)
{
pid_t pid = fork();

if(pid == 0)
_exit(!release_locks(log_fd, profile_manifest_array, profile));
_exit(!release_locks(log_fd, tmpdir, profile_manifest_array, profile));

return pid;
}

ProcReact_Future query_installed_services(GPtrArray *profile_manifest_array)
{
ProcReact_Future future = procreact_initialize_future(procreact_create_string_array_type('\n'));

if(future.pid == 0)
{
print_text_from_profile_manifest_array(profile_manifest_array, future.fd);
_exit(0);
}

return future;
}
26 changes: 2 additions & 24 deletions src/dbus-service/locking.h
Expand Up @@ -25,37 +25,15 @@
#include <procreact_future.h>
#include <profilemanifest.h>

/**
* Attempts to lock the disnix service instance by consulting the services in
* the profile manifest and by locking the Disnix service itself.
*
* @param log_fd File descriptor of the log file that shows the output
* @param profile_manifest_array An array of profile manifest entries
* @param profile Name of the profile to take the manifest from
* @return TRUE if and only if the locking succeeded
*/
int acquire_locks(int log_fd, GPtrArray *profile_manifest_array, gchar *profile);

/**
* Asynchronously executes the acquire_locks() operation in a child process.
*/
pid_t acquire_locks_async(int log_fd, GPtrArray *profile_manifest_array, gchar *profile);

/**
* Attempts to unlock the disnix service by consulting the services in the
* profile manifest and by unlocking the Disnix service itself.
*
* @param log_fd File descriptor of the log file that shows the output
* @param profile_manifest_array An array of profile manifest entries
* @param profile Name of the profile to take the manifest from
* @return TRUE if and only if the unlocking succeeded
*/
int release_locks(int log_fd, GPtrArray *profile_manifest_array, gchar *profile);
pid_t acquire_locks_async(int log_fd, gchar *tmpdir, GPtrArray *profile_manifest_array, gchar *profile);

/**
* Asynchronously executes the release_locks() operation in a child process.
*/
pid_t release_locks_async(int log_fd, GPtrArray *profile_manifest_array, gchar *profile);
pid_t release_locks_async(int log_fd, gchar *tmpdir, GPtrArray *profile_manifest_array, gchar *profile);

/**
* Queries all the properties of the entries stored in the profile manifest.
Expand Down
4 changes: 2 additions & 2 deletions src/dbus-service/methods.c
Expand Up @@ -275,7 +275,7 @@ gboolean on_handle_lock(OrgNixosDisnixDisnix *object, GDBusMethodInvocation *inv
}
else
{
signal_boolean_result(acquire_locks_async(log_fd, profile_manifest_array, (gchar*)arg_profile), object, arg_pid, log_fd);
signal_boolean_result(acquire_locks_async(log_fd, tmpdir, profile_manifest_array, (gchar*)arg_profile), object, arg_pid, log_fd);

/* Cleanup */
delete_profile_manifest_array(profile_manifest_array);
Expand All @@ -301,7 +301,7 @@ gboolean on_handle_unlock(OrgNixosDisnixDisnix *object, GDBusMethodInvocation *i

/* Unlock the Disnix instance */
profile_manifest_array = create_profile_manifest_array_from_current_deployment(LOCALSTATEDIR, (gchar*)arg_profile);
signal_boolean_result(release_locks_async(log_fd, profile_manifest_array, (gchar*)arg_profile), object, arg_pid, log_fd);
signal_boolean_result(release_locks_async(log_fd, tmpdir, profile_manifest_array, (gchar*)arg_profile), object, arg_pid, log_fd);

/* Cleanup */
delete_profile_manifest_array(profile_manifest_array);
Expand Down
10 changes: 5 additions & 5 deletions src/diagnose/diagnose.c
Expand Up @@ -18,11 +18,11 @@
*/

#include "diagnose.h"
#include "manifest.h"
#include "activationmapping.h"
#include "targets.h"
#include "client-interface.h"
#include "procreact_pid.h"
#include <manifest.h>
#include <activationmapping.h>
#include <targets.h>
#include <client-interface.h>
#include <procreact_pid.h>

int diagnose(char *service_name, const char *manifest_file, const gchar *coordinator_profile_path, gchar *profile, char *container_filter, char *target_filter, char *command)
{
Expand Down
8 changes: 4 additions & 4 deletions src/libprofilemanifest/Makefile.am
@@ -1,6 +1,6 @@
pkglib_LTLIBRARIES = libprofilemanifest.la
pkginclude_HEADERS = profilemanifest.h profilemanifesttarget.h
pkginclude_HEADERS = profilemanifest.h profilemanifesttarget.h profilelocking.h

libprofilemanifest_la_SOURCES = profilemanifest.c profilemanifesttarget.c
libprofilemanifest_la_CFLAGS = $(GLIB2_CFLAGS) -I../libprocreact -I../libmodel
libprofilemanifest_la_LIBADD = $(GLIB2_LIBS) ../libprocreact/libprocreact.la ../libmodel/libmodel.la
libprofilemanifest_la_SOURCES = profilemanifest.c profilemanifesttarget.c profilelocking.c
libprofilemanifest_la_CFLAGS = $(GLIB2_CFLAGS) -I../libprocreact -I../libmodel -I../libstatemgmt
libprofilemanifest_la_LIBADD = $(GLIB2_LIBS) ../libprocreact/libprocreact.la ../libmodel/libmodel.la ../libstatemgmt/libstatemgmt.la
124 changes: 124 additions & 0 deletions src/libprofilemanifest/profilelocking.c
@@ -0,0 +1,124 @@
#include "profilelocking.h"
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <state-management.h>
#include "profilemanifest.h"

static int lock_or_unlock_services(int log_fd, GPtrArray *profile_manifest_array, gchar *action, pid_t (*notify_function) (gchar *type, gchar *container, gchar *component, int stdout, int stderr))
{
unsigned int i;
int exit_status = TRUE;

/* Notify all services for a lock or unlock */
for(i = 0; i < profile_manifest_array->len; i++)
{
ProfileManifestEntry *entry = g_ptr_array_index(profile_manifest_array, i);
pid_t pid;
ProcReact_Status status;
int result;

dprintf(log_fd, "Notifying %s on %s: of type: %s in container: %s\n", action, entry->service, entry->type, entry->container);
pid = notify_function(entry->type, entry->container, entry->service, log_fd, log_fd);
result = procreact_wait_for_boolean(pid, &status);

if(status != PROCREACT_STATUS_OK || !result)
{
dprintf(log_fd, "Cannot %s service!\n", action);
exit_status = FALSE;
}
}

return exit_status;
}

static int unlock_services(int log_fd, GPtrArray *profile_manifest_array)
{
return lock_or_unlock_services(log_fd, profile_manifest_array, "unlock", statemgmt_unlock_component);
}

static int lock_services(int log_fd, GPtrArray *profile_manifest_array)
{
return lock_or_unlock_services(log_fd, profile_manifest_array, "lock", statemgmt_lock_component);
}

static gchar *create_lock_filename(gchar *tmpdir, gchar *profile)
{
return g_strconcat(tmpdir, "/disnix-", profile, ".lock", NULL);
}

static int lock_profile(int log_fd, gchar *tmpdir, gchar *profile)
{
int fd, status;
gchar *lock_filename = create_lock_filename(tmpdir, profile);

/* If no lock exists, try to create one */
if((fd = open(lock_filename, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR)) == -1)
{
dprintf(log_fd, "Cannot exclusively open the lock file!\n");
status = FALSE;
}
else
{
close(fd);
status = TRUE;
}

g_free(lock_filename);
return status;
}

static int unlock_profile(int log_fd, gchar *tmpdir, gchar *profile)
{
gchar *lock_filename = create_lock_filename(tmpdir, profile);
int status;

if(unlink(lock_filename) == -1)
{
dprintf(log_fd, "There is no lock file!\n");
status = FALSE;
}
else
status = TRUE;

/* Cleanup */
g_free(lock_filename);

return status;
}

int acquire_locks(int log_fd, gchar *tmpdir, GPtrArray *profile_manifest_array, gchar *profile)
{
if(lock_services(log_fd, profile_manifest_array)) /* Attempt to acquire locks from the services */
return lock_profile(log_fd, tmpdir, profile); /* Finally, lock the profile */
else
{
unlock_services(log_fd, profile_manifest_array);
return FALSE;
}
}

int release_locks(int log_fd, gchar *tmpdir, GPtrArray *profile_manifest_array, gchar *profile)
{
int status = TRUE;

if(profile_manifest_array == NULL)
{
dprintf(log_fd, "Corrupt profile manifest: a service or type is missing!\n");
status = FALSE;
}
else
{
if(!unlock_services(log_fd, profile_manifest_array))
{
dprintf(log_fd, "Failed to send unlock notification to old services!\n");
status = FALSE;
}
}

if(!unlock_profile(log_fd, tmpdir, profile))
status = FALSE; /* There was no lock -> fail */

return status;
}

0 comments on commit b58a338

Please sign in to comment.