And the files that actually handler the tender phase now.
authorroot <root@xenapi.xen>
Fri, 3 Oct 2008 22:07:28 +0000 (4 00:07 +0200)
committerroot <root@xenapi.xen>
Fri, 3 Oct 2008 22:07:28 +0000 (4 00:07 +0200)
handler_virt_tender.c [new file with mode: 0644]
handler_virt_tender.h [new file with mode: 0644]

diff --git a/handler_virt_tender.c b/handler_virt_tender.c
new file mode 100644 (file)
index 0000000..7a6e44a
--- /dev/null
@@ -0,0 +1,208 @@
+#include "handler_virt.h"
+#include "handler_clusterstats.h"
+#include "handler_virt_tender.h"
+#include <cherokee/cherokee.h>
+#include <float.h>
+
+#include <avahi-client/client.h>
+#include <avahi-client/publish.h>
+#include <avahi-client/lookup.h>
+
+#include <avahi-common/alternative.h>
+#include <avahi-common/simple-watch.h>
+#include <avahi-common/malloc.h>
+#include <avahi-common/error.h>
+#include <avahi-common/timeval.h>
+
+static void entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state, AVAHI_GCC_UNUSED void *userdata) {
+    switch (state) {
+        case AVAHI_ENTRY_GROUP_ESTABLISHED :
+            /* The entry group has been established successfully */
+            break;
+
+        case AVAHI_ENTRY_GROUP_COLLISION : {
+            /* A service name collision with a remote service
+             * happened. */
+            break;
+        }
+
+        case AVAHI_ENTRY_GROUP_FAILURE :
+            /* Some kind of failure happened while we were registering our services */
+            break;
+
+        case AVAHI_ENTRY_GROUP_UNCOMMITED:
+        case AVAHI_ENTRY_GROUP_REGISTERING:
+            ;
+    }
+}
+
+static void tender_resolve_callback(
+    AvahiServiceResolver *r,
+    AVAHI_GCC_UNUSED AvahiIfIndex interface,
+    AVAHI_GCC_UNUSED AvahiProtocol protocol,
+    AvahiResolverEvent event,
+    const char *name,
+    const char *type,
+    const char *domain,
+    const char *host_name,
+    const AvahiAddress *address,
+    uint16_t port,
+    AvahiStringList *txt,
+    AvahiLookupResultFlags flags,
+    void* userdata) {
+
+    tender_t *tender = userdata;
+
+    assert(r);
+
+    /* Called whenever a service has been resolved successfully or timed out */
+
+    switch (event) {
+        case AVAHI_RESOLVER_FAILURE:
+            // fprintf(stderr, "(Resolver) FAILURE!\n");
+            avahi_service_resolver_free(r);
+            break;
+
+        case AVAHI_RESOLVER_FOUND: {
+            char a[AVAHI_ADDRESS_STR_MAX], *t;
+            AvahiStringList *needle;
+
+//            fprintf(stderr, "(Resolver) Service '%s' of type '%s' in domain '%s':\n", name, type, domain);
+
+            avahi_address_snprint(a, sizeof(a), address);
+            t = avahi_string_list_to_string(txt);
+/*            fprintf(stderr,
+                    "\t%s:%u (%s)\n"
+                    "\tTXT=%s\n"
+                    "\tcookie is %u\n"
+                    "\tis_local: %i\n"
+                    "\tour_own: %i\n"
+                    "\twide_area: %i\n"
+                    "\tmulticast: %i\n"
+                    "\tcached: %i\n",
+                    host_name, port, a,
+                    t,
+                    avahi_string_list_get_service_cookie(txt),
+                    !!(flags & AVAHI_LOOKUP_RESULT_LOCAL),
+                    !!(flags & AVAHI_LOOKUP_RESULT_OUR_OWN),
+                    !!(flags & AVAHI_LOOKUP_RESULT_WIDE_AREA),
+                    !!(flags & AVAHI_LOOKUP_RESULT_MULTICAST),
+                    !!(flags & AVAHI_LOOKUP_RESULT_CACHED));*/
+
+
+            avahi_free(t);
+
+            if (tender->name) {
+                unsigned int len = strlen(tender->name);
+                if (strlen(name) > len && name[len] == '.' && strncmp(tender->name, name, len) == 0) {
+                    if ((needle = avahi_string_list_find (txt, "cost")) != NULL) {
+
+                        float amount;
+                        char *cost;
+                        avahi_string_list_get_pair (needle, NULL, &cost, NULL);
+                        amount = atof(cost);
+
+                        TRACE("tender", "%s will run %s for the cost of L$W %f\n", host_name, tender->name, amount);
+                        if (amount < tender->cost) {
+                            /* TODO: LOCK */
+                            tender->cost = amount;
+                            tender->dom = strdup(host_name);
+                            TRACE("tender", "We will consider his offer!");
+                        }
+
+                        avahi_free(cost);
+                    }
+                }
+            }
+            break;
+        }
+    }
+}
+
+static void tender_browse_callback(
+    AvahiServiceBrowser *b,
+    AvahiIfIndex interface,
+    AvahiProtocol protocol,
+    AvahiBrowserEvent event,
+    const char *name,
+    const char *type,
+    const char *domain,
+    AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
+    void* userdata) {
+        AvahiClient *c;
+        assert(b);
+
+        c = avahi_service_browser_get_client(b);
+
+    /* Called whenever a new services becomes available on the LAN or is removed from the LAN */
+
+    switch (event) {
+        case AVAHI_BROWSER_FAILURE:
+            fprintf(stderr, "(Browser) %s\n", avahi_strerror(avahi_client_errno(c)));
+            return;
+
+        case AVAHI_BROWSER_NEW:
+            fprintf(stderr, "(Browser) NEW: service '%s' of type '%s' in domain '%s'\n", name, type, domain);
+
+            /* We ignore the returned resolver object. In the callback
+               function we free it. If the server is terminated before
+               the callback function is called the server will free
+               the resolver for us. */
+
+            if (!(avahi_service_resolver_new(c, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, 0, tender_resolve_callback, userdata)))
+                fprintf(stderr, "Failed to resolve service '%s': %s\n", name, avahi_strerror(avahi_client_errno(c)));
+
+            break;
+
+        case AVAHI_BROWSER_REMOVE:
+            fprintf(stderr, "%s, (Browser) REMOVE: service '%s' of type '%s' in domain '%s'\n", __func__, name, type, domain);
+            break;
+
+        case AVAHI_BROWSER_ALL_FOR_NOW:
+        case AVAHI_BROWSER_CACHE_EXHAUSTED:
+            fprintf(stderr, "(Browser) %s\n", event == AVAHI_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW");
+            break;
+    }
+}
+
+char * create_tender(cherokee_handler_virt_t *hdl, const char *name, unsigned long memory) {
+    char txt[255];
+    tender_t best_tender;
+
+    snprintf(txt, 253, "memory=%lu", memory);
+    txt[254] = '\0';
+    
+    best_tender.name = name;
+    best_tender.cost = FLT_MAX;
+    best_tender.dom  = NULL;
+
+    avahi_threaded_poll_lock(HDL_CLUSTERSTATS_PROPS(hdl)->threaded_poll);
+    AvahiServiceBrowser *sb = avahi_service_browser_new(HDL_CLUSTERSTATS_PROPS(hdl)->client, AVAHI_IF_UNSPEC, 
+                                                        AVAHI_PROTO_UNSPEC, "_tender._tcp",
+                                                        NULL, 0, tender_browse_callback, &best_tender);
+
+    if (sb == NULL) {
+        TRACE("avahi", "For whatever reason the sb is NULL\n");
+    } else {
+        AvahiEntryGroup *group = avahi_entry_group_new(HDL_CLUSTERSTATS_PROPS(hdl)->client, entry_group_callback, NULL);
+    
+        if (group == NULL) {
+            TRACE("avahi", "For whatever reason the group is NULL\n");
+        } else {
+            avahi_entry_group_add_service(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0,
+                                          best_tender.name, "_offer._tcp", NULL, NULL, 651, txt, NULL, NULL);
+            avahi_entry_group_commit(group);
+            avahi_threaded_poll_unlock(HDL_CLUSTERSTATS_PROPS(hdl)->threaded_poll);
+
+            sleep(3); /* we are for quick bidding ;) */
+
+            avahi_threaded_poll_lock(HDL_CLUSTERSTATS_PROPS(hdl)->threaded_poll);
+            avahi_entry_group_free(group);
+        }
+                            
+        avahi_service_browser_free(sb);
+    }
+    avahi_threaded_poll_unlock(HDL_CLUSTERSTATS_PROPS(hdl)->threaded_poll);
+
+    return best_tender.dom;
+}
diff --git a/handler_virt_tender.h b/handler_virt_tender.h
new file mode 100644 (file)
index 0000000..0d9355e
--- /dev/null
@@ -0,0 +1 @@
+char * create_tender(cherokee_handler_virt_t *hdl, const char *name, unsigned long memory);