This repository has been archived on 2020-04-11. You can view files and clone it, but cannot push or open issues or pull requests.
gnoemoe/src/mcp/gm-mcp-negotiate.c
2005-11-06 16:38:51 +00:00

296 lines
7.9 KiB
C

#include <glib-object.h>
#include <string.h>
#include "gm-mcp-negotiate.h"
#include "gm-mcp.h"
#include "gm-mcp-session.h"
#include "gm-mcp-package.h"
#include "../gm-debug.h"
#include "../gm-support.h"
#define GM_MCP_NEGOTIATE_GET_PRIVATE(object)( \
G_TYPE_INSTANCE_GET_PRIVATE((object), \
GM_TYPE_MCP_NEGOTIATE, GmMcpNegotiatePrivate))
typedef struct _PackageInfo {
GmMcpPackageClass *klass;
gdouble version;
} PackageInfo;
struct _GmMcpNegotiatePrivate {
GList *packages;
};
/* Signals
enum {
PROTO
NUM_SIGNALS
};
static guint gm_mcp_negotiate_signals[NUM_SIGNALS] = {0};*/
void gm_mcp_negotiate_handle_simple(GmMcpPackage *package, gchar *suffix,
GList *fields);
static void gm_mcp_negotiate_init(GmMcpNegotiate *self);
static void gm_mcp_negotiate_class_init(GmMcpNegotiateClass *klass);
//static void gm_mcp_negotiate_class_finalize(gpointer klass,
// gpointer klass_data);
static gpointer gm_mcp_negotiate_parent_class = NULL;
static void gm_mcp_negotiate_class_intern_init(gpointer klass) {
gm_mcp_negotiate_parent_class = g_type_class_peek_parent(klass);
gm_mcp_negotiate_class_init((GmMcpNegotiateClass *) klass);
}
GType
gm_mcp_negotiate_get_type() {
static GType g_define_type_id = 0;
if (G_UNLIKELY(g_define_type_id == 0)) {
static const GTypeInfo g_define_type_info = {
sizeof (GmMcpNegotiateClass),
(GBaseInitFunc) NULL,
(GBaseFinalizeFunc) NULL,
(GClassInitFunc) gm_mcp_negotiate_class_intern_init,
(GClassFinalizeFunc) NULL, //gm_mcp_negotiate_class_finalize,
NULL, /* class_data */
sizeof (GmMcpNegotiate),
0, /* n_preallocs */
(GInstanceInitFunc) gm_mcp_negotiate_init,
NULL /* value_table */
};
g_define_type_id = g_type_register_static(GM_TYPE_MCP_PACKAGE,
"GmMcpNegotiate", &g_define_type_info, (GTypeFlags) 0);
}
return g_define_type_id; \
}
static void
gm_mcp_negotiate_finalize(GObject *object) {
//GmMcpNegotiate *obj = GM_MCP_NEGOTIATE(object);
G_OBJECT_CLASS(gm_mcp_negotiate_parent_class)->finalize(object);
}
/*static void
gm_mcp_negotiate_class_finalize(gpointer klass, gpointer klass_data) {
GmMcpPackageClass *pklass = GM_MCP_PACKAGE_CLASS(klass);
g_list_free(pklass->depends);
g_list_free(pklass->overrides);
}*/
static void
gm_mcp_negotiate_class_init(GmMcpNegotiateClass *klass) {
GObjectClass *object_class = G_OBJECT_CLASS(klass);
GmMcpPackageClass *pklass = GM_MCP_PACKAGE_CLASS(klass);
object_class->finalize = gm_mcp_negotiate_finalize;
/*gm_mcp_negotiate_signals[PROTO] =
g_signal_new("proto",
G_OBJECT_CLASS_TYPE(object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(GmMcpNegotiateClass, proto),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0);*/
pklass->name = "mcp-negotiate";
pklass->handle_simple = &gm_mcp_negotiate_handle_simple;
g_type_class_add_private(object_class, sizeof(GmMcpNegotiatePrivate));
}
static void
gm_mcp_negotiate_init(GmMcpNegotiate *obj) {
obj->priv = GM_MCP_NEGOTIATE_GET_PRIVATE(obj);
obj->priv->packages = NULL;
}
PackageInfo *
gm_mcp_negotiate_find_package(GmMcpNegotiate *package, gchar *name) {
PackageInfo *pinfo;
GList *elem;
for (elem = package->priv->packages; elem; elem = elem->next) {
pinfo = (PackageInfo *)(elem->data);
if (strcasecmp(pinfo->klass->name, name) == 0) {
return pinfo;
}
}
return NULL;
}
void
gm_mcp_negotiate_fix_overrides(GmMcpNegotiate *package) {
GList *l, *item, *over;
PackageInfo *pinfo, *pover;
gchar *name;
l = g_list_copy(package->priv->packages);
for (item = l; item; item = item->next) {
pinfo = (PackageInfo *)(item);
for (over = pinfo->klass->overrides; over; over = over->next) {
name = (gchar *)(over->data);
if ((pover = gm_mcp_negotiate_find_package(package, name))) {
gm_debug_msg(DEBUG_MCP, "GmMcpNegotiate.FixOverrides: package %s "
"overrides %s", pinfo->klass->name, pover->klass->name);
package->priv->packages = g_list_remove(
package->priv->packages, pover);
}
}
}
g_list_free(l);
}
void
gm_mcp_negotiate_fix_depends(GmMcpNegotiate *package) {
PackageInfo *pinfo, *pdep;
GList *l, *item, *dep;
gchar *name;
l = g_list_copy(package->priv->packages);
for (item = l; item; item = item->next) {
pinfo = (PackageInfo *)(item->data);
for (dep = pinfo->klass->depends; dep; dep = dep->next) {
name = (gchar *)(dep->data);
if (!(pdep = gm_mcp_negotiate_find_package(package, name))) {
gm_debug_msg(DEBUG_MCP, "GmMcpNegotiate.FixDepends: package %s depends "
"on %s, but %s is not supported", pinfo->klass->name,
name, name);
// Remove package because depencendies are not met
package->priv->packages = g_list_remove(
package->priv->packages, pinfo);
break;
} else {
// Make sure this dependency is loaded before the package
package->priv->packages = g_list_remove(
package->priv->packages, pdep);
package->priv->packages = g_list_insert_before(
package->priv->packages,
g_list_find(package->priv->packages, pinfo), pdep);
}
}
}
g_list_free(l);
}
/* Public */
GmMcpNegotiate *
gm_mcp_negotiate_new() {
GmMcpNegotiate *obj = GM_MCP_NEGOTIATE(g_object_new(GM_TYPE_MCP_NEGOTIATE,
NULL));
return obj;
}
/* Private */
gboolean
gm_mcp_negotiate_send_can(GmMcpPackageClass *klass, gpointer user_data) {
GmMcpNegotiate *package = GM_MCP_NEGOTIATE(user_data);
gchar *min_v, *max_v;
min_v = g_strdup_printf("%'.1f", klass->min_version);
gm_fix_decimal_point_rev(min_v, strlen(min_v));
max_v = g_strdup_printf("%'.1f", klass->max_version);
gm_fix_decimal_point_rev(max_v, strlen(max_v));
gm_mcp_session_send_simple(GM_MCP_PACKAGE_SESSION(package),
"mcp-negotiate-can", "package", klass->name, "min-version",
min_v, "max-version", max_v, NULL);
g_free(min_v);
g_free(max_v);
return FALSE;
}
void
gm_mcp_negotiate_handle_simple(GmMcpPackage *package, gchar *suffix,
GList *fields) {
gchar const *pname;
GmMcpPackageClass *pklass;
GmMcpNegotiate *negotiate = GM_MCP_NEGOTIATE(package);
PackageInfo *pinfo;
double version;
gchar const *min_v, *max_v;
gchar *cmin, *cmax;
GList *elem;
if (strcasecmp(suffix, "can") == 0) {
// Fields has package, min-version, max-version
pname = gm_mcp_find_value(fields, "package");
pklass = gm_mcp_session_find_package_class(pname);
if (pklass) {
min_v = gm_mcp_find_value(fields, "min-version");
cmin = gm_fix_decimal_point(g_strdup(min_v), strlen(min_v));
max_v = gm_mcp_find_value(fields, "max-version");
cmax = gm_fix_decimal_point(g_strdup(max_v), strlen(max_v));
version = gm_mcp_get_version(pklass->min_version,
pklass->max_version, g_ascii_strtod(min_v, NULL),
g_ascii_strtod(max_v, NULL));
g_free(cmin);
g_free(cmax);
if (version > 0.0) {
gm_debug_msg(DEBUG_MCP, "GmMcpNegotiate.HandleSimple: %s, "
"package is supported", pname);
pinfo = g_new(PackageInfo, 1);
pinfo->klass = pklass;
pinfo->version = version;
negotiate->priv->packages = g_list_append(
negotiate->priv->packages, pinfo);
} else {
gm_debug_msg(DEBUG_MCP, "GmMcpNegotiate.HandleSimple: %s, package "
"supported but wrong version!", pname);
}
} else {
gm_debug_msg(DEBUG_MCP, "GmMcpNegotiate.HandleSimple: %s, package is not "
"supported!", pname);
}
} else if (strcasecmp(suffix, "end") == 0) {
gm_mcp_session_package_class_for_each(gm_mcp_negotiate_send_can,
(gpointer)(negotiate));
gm_mcp_session_send_simple(GM_MCP_PACKAGE_SESSION(negotiate),
"mcp-negotiate-end", NULL);
gm_mcp_negotiate_fix_overrides(negotiate);
gm_mcp_negotiate_fix_depends(negotiate);
for (elem = negotiate->priv->packages; elem; elem = elem->next) {
pinfo = (PackageInfo *)(elem->data);
gm_mcp_session_create_package(GM_MCP_PACKAGE_SESSION(negotiate),
pinfo->klass, pinfo->version);
g_free(pinfo);
}
g_list_free(negotiate->priv->packages);
negotiate->priv->packages = NULL;
}
}