/* * Invoked once on module load. * * This routine should return 0 on success, and -1 otherwise. */ int codegen_init(hsignature_t *sig) { const char *url; hcfg_t *cfg; url = session_getcfg(CFGKEY_TARGET_URL); if (!url || url[0] == '\0') { session_error("Destination URL for" " generated code objects not specified"); return -1; } url = session_getcfg(CFGKEY_SERVER_URL); if (!url || url[0] == '\0') { session_error("Codegen server URL not specified"); return -1; } sockfd = url_connect(url); if (sockfd == -1) { session_error("Invalid codegen server URL"); return -1; } /* In the future, we should rewrite the code generator system to * avoid using hmesg_t types. Until then, generate a fake * HMESG_SESSION message to maintain compatibility. */ mesg = HMESG_INITIALIZER; hsignature_copy(&mesg.data.session.sig, sig); cfg = hcfg_alloc(); hcfg_set(cfg, CFGKEY_SERVER_URL, session_getcfg(CFGKEY_SERVER_URL)); hcfg_set(cfg, CFGKEY_TARGET_URL, session_getcfg(CFGKEY_TARGET_URL)); hcfg_set(cfg, CFGKEY_REPLY_URL, session_getcfg(CFGKEY_REPLY_URL)); hcfg_set(cfg, CFGKEY_SLAVE_LIST, session_getcfg(CFGKEY_SLAVE_LIST)); hcfg_set(cfg, CFGKEY_SLAVE_PATH, session_getcfg(CFGKEY_SLAVE_PATH)); mesg.data.session.cfg = cfg; mesg.type = HMESG_SESSION; mesg.status = HMESG_STATUS_REQ; if (mesg_send(sockfd, &mesg) < 1) return -1; if (mesg_recv(sockfd, &mesg) < 1) return -1; if (callback_generate(sockfd, codegen_callback) != 0) { session_error("Could not register callback for codegen plugin"); return -1; } return 0; }
int hcfg_deserialize(hcfg_t *cfg, char *buf) { int count, total; unsigned int i, kcount, logsize; const char *key, *val; if (sscanf(buf, " hcfg:%u %u%n", &kcount, &logsize, &count) < 2) goto invalid; total = count; if (hash_resize(cfg, logsize) < 0) goto error; for (i = 0; i < kcount; ++i) { count = scanstr_serial(&key, buf + total); if (count < 0) goto invalid; total += count; count = scanstr_serial(&val, buf + total); if (count < 0) goto invalid; total += count; if (hcfg_set(cfg, key, val) < 0) goto error; } return total; invalid: errno = EINVAL; error: return -1; }
char *harmony_setcfg(hdesc_t *hdesc, const char *key, const char *val) { char *buf; int retval; if (hdesc->state < HARMONY_STATE_CONNECTED) { /* User must be preparing for a new session since we're not * connected yet. Store the key/value pair in a local cache. */ buf = stralloc( hcfg_get(hdesc->sess.cfg, key) ); hcfg_set(hdesc->sess.cfg, key, val); return buf; } if (!key) { hdesc->errstr = "Invalid key string."; errno = EINVAL; return NULL; } buf = sprintf_alloc("%s=%s", key, val ? val : ""); if (!buf) { hdesc->errstr = "Internal memory allocation error."; return NULL; } /* Prepare a Harmony message. */ hmesg_scrub(&hdesc->mesg); hdesc->mesg.data.string = buf; retval = send_request(hdesc, HMESG_SETCFG); free(buf); if (retval < 0) return NULL; if (hdesc->mesg.status != HMESG_STATUS_OK) { hdesc->errstr = "Invalid message received from server."; errno = EINVAL; return NULL; } /* It is the user's responsibility to free this memory. */ return stralloc(hdesc->mesg.data.string); }
int harmony_join(hdesc_t *hdesc, const char *host, int port, const char *name) { int i, perf_len; int apply_argv = (hdesc->state < HARMONY_STATE_CONNECTED); char *cfgval; /* Verify that we have *at least* one variable bound, and that * this descriptor isn't already associated with a tuning * session. */ if (hdesc->ptr_len == 0) { hdesc->errstr = "No variables bound to Harmony session"; errno = EINVAL; return -1; } if (hdesc->state >= HARMONY_STATE_READY) { hdesc->errstr = "Descriptor already joined with an existing session"; errno = EINVAL; return -1; } if (hdesc->state == HARMONY_STATE_INIT) { hdesc->socket = tcp_connect(host, port); if (hdesc->socket < 0) { hdesc->errstr = "Error establishing TCP connection with server"; return -1; } if (hdesc->id == NULL) hdesc->id = default_id(hdesc->socket); hdesc->state = HARMONY_STATE_CONNECTED; hdesc->sess.sig.name = stralloc(name); if (!hdesc->sess.sig.name) { hdesc->errstr = "Error allocating memory for signature name"; return -1; } } /* Prepare a Harmony message. */ hmesg_scrub(&hdesc->mesg); hdesc->mesg.data.join = HSIGNATURE_INITIALIZER; if (hsignature_copy(&hdesc->mesg.data.join, &hdesc->sess.sig) < 0) { hdesc->errstr = "Internal error copying signature data"; return -1; } /* send the client registration message */ if (send_request(hdesc, HMESG_JOIN) != 0) return -1; if (hdesc->mesg.status != HMESG_STATUS_OK) { hdesc->errstr = "Invalid message received"; errno = EINVAL; return -1; } hsignature_fini(&hdesc->sess.sig); if (hsignature_copy(&hdesc->sess.sig, &hdesc->mesg.data.join) < 0) { hdesc->errstr = "Error copying received signature structure"; return -1; } /* Apply argv configuration directives now, if necessary. */ if (apply_argv) { for (i = 0; i < hdesc->cmd_len; ++i) { char *key, *val, *cpy; cpy = stralloc(hdesc->cmd[i]); if (hcfg_parse(cpy, &key, &val)) { /* This should never fail, but just in case. */ hdesc->errstr = "Error parsing argv config directive."; return -1; } if (hcfg_set(hdesc->sess.cfg, key, val)) { hdesc->errstr = "Error applying argv config directive."; return -1; } free(cpy); } } cfgval = harmony_getcfg(hdesc, CFGKEY_PERF_COUNT); if (cfgval) { perf_len = atoi(cfgval); if (perf_len < 1) { hdesc->errstr = "Invalid value for " CFGKEY_PERF_COUNT; return -1; } free(cfgval); } else { perf_len = DEFAULT_PERF_COUNT; } hdesc->perf = hperf_alloc(perf_len); if (!hdesc->perf) { hdesc->errstr = "Error allocating performance array."; return -1; } hdesc->state = HARMONY_STATE_READY; return 0; }
int harmony_launch(hdesc_t *hdesc, const char *host, int port) { int i; /* Sanity check input */ if (hdesc->sess.sig.range_len < 1) { hdesc->errstr = "No tuning variables defined"; errno = EINVAL; return -1; } if (!host && !getenv("HARMONY_S_HOST")) { char *path; const char *home; /* Provide a default name, if one isn't defined. */ if (!hdesc->sess.sig.name) { if (hsignature_name(&hdesc->sess.sig, "NONAME")) return -1; } /* Find the Active Harmony installation. */ home = getenv("HARMONY_HOME"); if (!home) { hdesc->errstr = "No host or HARMONY_HOME specified"; return -1; } if (hcfg_set(hdesc->sess.cfg, CFGKEY_HARMONY_HOME, home) != 0) { hdesc->errstr = "Could not set " CFGKEY_HARMONY_HOME; return -1; } /* Fork a local tuning session. */ path = sprintf_alloc("%s/libexec/session-core", home); hdesc->socket = socket_launch(path, NULL, NULL); free(path); } else { hdesc->socket = tcp_connect(host, port); } if (hdesc->socket < 0) { hdesc->errstr = strerror(errno); return -1; } /* Prepare a default client id, if necessary. */ if (hdesc->id == NULL) hdesc->id = default_id(hdesc->socket); hdesc->state = HARMONY_STATE_CONNECTED; /* Apply argv configuration directives now, if necessary. */ for (i = 0; i < hdesc->cmd_len; ++i) { char *key, *val, *cpy; cpy = stralloc(hdesc->cmd[i]); if (hcfg_parse(cpy, &key, &val) == NULL) { /* This should never fail, but just in case. */ hdesc->errstr = "Internal error parsing argv config directive."; return -1; } if (hcfg_set(hdesc->sess.cfg, key, val) != 0) { hdesc->errstr = "Internal error applying argv config directive."; return -1; } free(cpy); } /* Prepare a Harmony message. */ hmesg_scrub(&hdesc->mesg); hsession_init(&hdesc->mesg.data.session); hsession_copy(&hdesc->mesg.data.session, &hdesc->sess); return send_request(hdesc, HMESG_SESSION); }
int harmony_layer_list(hdesc_t *hdesc, const char *list) { return hcfg_set(hdesc->sess.cfg, CFGKEY_SESSION_LAYERS, list); }
int harmony_strategy(hdesc_t *hdesc, const char *strategy) { return hcfg_set(hdesc->sess.cfg, CFGKEY_SESSION_STRATEGY, strategy); }