static Pvoid_t tokenize_uris(htmlDocPtr doc, Pvoid_t features) { xmlTextReaderPtr reader = xmlReaderWalker(doc); while (xmlTextReaderRead(reader)) { int type = xmlTextReaderNodeType(reader); if (type == XML_ELEMENT_NODE) { char *uri = (char *) xmlTextReaderGetAttribute(reader, BAD_CAST "href"); if (uri) { features = tokenize_uri(uri, features); free(uri); } uri = (char*) xmlTextReaderGetAttribute(reader, BAD_CAST "src"); if (uri) { features = tokenize_uri(uri, features); free(uri); } } } xmlFreeTextReader(reader); return features; }
Pvoid_t atom_tokenize(const char * atom) { Pvoid_t features = NULL; if (atom) { xmlDocPtr doc = xmlParseDoc(BAD_CAST atom); if (doc) { xmlXPathContextPtr context = xmlXPathNewContext(doc); xmlXPathRegisterNs(context, BAD_CAST "atom", BAD_CAST "http://www.w3.org/2005/Atom"); char *html = get_element_value(context, "/atom:entry/atom:content/text()"); if (html) { features = html_tokenize_into_features(html, features); xmlFree(html); } char *title = get_element_value(context, "/atom:entry/atom:title/text()"); if (title) { features = tokenize_text(title, strlen(title), features); xmlFree(title); } char *author = get_element_value(context, "/atom:entry/atom:author/atom:name/text()"); if (author) { features = add_token(author, features); xmlFree(author); } char *link = get_attribute_value(context, "/atom:entry/atom:link[@rel='alternate']", "href"); if (link) { features = tokenize_uri(link, features); xmlFree(link); } xmlXPathFreeContext(context); } xmlFreeDoc(doc); } return features; }
//! //! //! //! @param[in] pMeta a pointer to the node controller (NC) metadata structure //! @param[in] serviceIds a list of service info. //! @param[in] serviceIdsLen the number of service info in the serviceIds list //! @param[out] outStatuses list of service status //! @param[out] outStatusesLen number of service status in the outStatuses list //! //! @return //! //! @pre //! //! @note //! int doDescribeServices(ncMetadata * pMeta, serviceInfoType * serviceIds, int serviceIdsLen, serviceStatusType ** outStatuses, int *outStatusesLen) { int rc = 0; int i = 0; int j = 0; int port = 0; char uri[MAX_PATH] = { 0 }; char uriType[32] = { 0 }; char host[MAX_PATH] = { 0 }; char path[MAX_PATH] = { 0 }; serviceStatusType *myStatus = NULL; int do_report_cluster = 1; // always do report on the cluster, otherwise CC won't get ENABLED int do_report_nodes = 0; int do_report_all = 0; char *my_partition = NULL; rc = initialize(pMeta, TRUE); // DescribeServices is the only authoritative source of epoch if (rc) { return (1); } LOGDEBUG("invoked: userId=%s, serviceIdsLen=%d\n", SP(pMeta ? pMeta->userId : "UNKNOWN"), serviceIdsLen); //! @TODO for now, return error if list of services is passed in as parameter /* if (serviceIdsLen > 0) { LOGERROR("DescribeServices(): received non-zero number of input services, returning fail\n"); *outStatusesLen = 0; *outStatuses = NULL; return(1); } */ sem_mywait(CONFIG); { if (!strcmp(config->ccStatus.serviceId.name, "self")) { for (i = 0; i < serviceIdsLen; i++) { LOGDEBUG("received input serviceId[%d]\n", i); if (strlen(serviceIds[i].type)) { if (!strcmp(serviceIds[i].type, "cluster")) { snprintf(uri, MAX_PATH, "%s", serviceIds[i].uris[0]); rc = tokenize_uri(uri, uriType, host, &port, path); if (strlen(host)) { LOGDEBUG("setting local serviceId to input serviceId (type=%s name=%s partition=%s)\n", SP(serviceIds[i].type), SP(serviceIds[i].name), SP(serviceIds[i].partition)); memcpy(&(config->ccStatus.serviceId), &(serviceIds[i]), sizeof(serviceInfoType)); } } else if (!strcmp(serviceIds[i].type, "node")) { do_report_nodes = 1; // report on node services if requested explicitly } } } } } sem_mypost(CONFIG); if (serviceIdsLen < 1) { // if the describe request is not specific, report on everything do_report_cluster = 1; do_report_nodes = 1; do_report_all = 1; } else { // if the describe request is specific, identify which types are requested do_report_cluster = 0; do_report_nodes = 0; do_report_all = 0; for (i = 0; i < serviceIdsLen; i++) { LOGDEBUG("received input serviceId[%d]: %s %s %s %s\n", i, serviceIds[i].type, serviceIds[i].partition, serviceIds[i].name, serviceIds[i].uris[0]); if (strlen(serviceIds[i].type)) { if (!strcmp(serviceIds[i].type, "cluster")) { do_report_cluster = 1; // report on cluster services if requested explicitly } else if (!strcmp(serviceIds[i].type, "node")) { do_report_nodes++; // count number of and report on node services if requested explicitly } } } } for (i = 0; i < 16; i++) { if (strlen(config->services[i].type)) { LOGDEBUG("internal serviceInfos type=%s name=%s partition=%s urisLen=%d\n", config->services[i].type, config->services[i].name, config->services[i].partition, config->services[i].urisLen); if (!strcmp(config->services[i].type, "cluster")) { my_partition = config->services[i].partition; } for (j = 0; j < MAX_SERVICE_URIS; j++) { if (strlen(config->services[i].uris[j])) { LOGDEBUG("internal serviceInfos\t uri[%d]:%s\n", j, config->services[i].uris[j]); } } } } for (i = 0; i < 16; i++) { if (strlen(config->disabledServices[i].type)) { LOGDEBUG("internal disabled serviceInfos type=%s name=%s partition=%s urisLen=%d\n", config->disabledServices[i].type, config->disabledServices[i].name, config->disabledServices[i].partition, config->disabledServices[i].urisLen); for (j = 0; j < MAX_SERVICE_URIS; j++) { if (strlen(config->disabledServices[i].uris[j])) { LOGDEBUG("internal disabled serviceInfos\t uri[%d]:%s\n", j, config->disabledServices[i].uris[j]); } } } } for (i = 0; i < 16; i++) { if (strlen(config->notreadyServices[i].type)) { LOGDEBUG("internal not ready serviceInfos type=%s name=%s partition=%s urisLen=%d\n", config->notreadyServices[i].type, config->notreadyServices[i].name, config->notreadyServices[i].partition, config->notreadyServices[i].urisLen); for (j = 0; j < MAX_SERVICE_URIS; j++) { if (strlen(config->notreadyServices[i].uris[j])) { LOGDEBUG("internal not ready serviceInfos\t uri[%d]:%s\n", j, config->notreadyServices[i].uris[j]); } } } } *outStatusesLen = 0; *outStatuses = NULL; if (do_report_cluster) { (*outStatusesLen) += 1; *outStatuses = EUCA_ZALLOC(1, sizeof(serviceStatusType)); if (!*outStatuses) { LOGFATAL("out of memory!\n"); unlock_exit(1); } myStatus = *outStatuses; snprintf(myStatus->localState, 32, "%s", config->ccStatus.localState); // ENABLED, DISABLED, STOPPED, NOTREADY snprintf(myStatus->details, 1024, "%s", config->ccStatus.details); // string that gets printed by 'euca-describe-services -E' myStatus->localEpoch = config->ccStatus.localEpoch; memcpy(&(myStatus->serviceId), &(config->ccStatus.serviceId), sizeof(serviceInfoType)); LOGDEBUG("external services\t uri[%d]: %s %s %s %s %s\n", 0, myStatus->serviceId.type, myStatus->serviceId.partition, myStatus->serviceId.name, myStatus->localState, myStatus->serviceId.uris[0]); } if (do_report_nodes) { extern ccResourceCache *resourceCache; ccResourceCache resourceCacheLocal; sem_mywait(RESCACHE); memcpy(&resourceCacheLocal, resourceCache, sizeof(ccResourceCache)); sem_mypost(RESCACHE); if (resourceCacheLocal.numResources > 0 && my_partition != NULL) { // parition is unknown at early stages of CC initialization for (int idIdx = 0; idIdx < serviceIdsLen; idIdx++) { if (do_report_all || !strcmp(serviceIds[idIdx].type, "node")) { for (int rIdx = 0; rIdx < resourceCacheLocal.numResources; rIdx++) { ccResource *r = resourceCacheLocal.resources + rIdx; if (do_report_all || (strlen(serviceIds[idIdx].name) && strlen(r->ip) && !strcmp(serviceIds[idIdx].name, r->ip))) { // we have a node that we want to report about (*outStatusesLen) += 1; *outStatuses = EUCA_REALLOC(*outStatuses, *outStatusesLen, sizeof(serviceStatusType)); if (*outStatuses == NULL) { LOGFATAL("out of memory! (outStatusesLen=%d)\n", *outStatusesLen); unlock_exit(1); } myStatus = *outStatuses + *outStatusesLen - 1; { int resState = r->state; int resNcState = r->ncState; char *state = "BUGGY"; char *msg = ""; if (resState == RESUP) { if (resNcState == ENABLED) { state = "ENABLED"; msg = "the node is operating normally"; } else if (resNcState == STOPPED) { state = "STOPPED"; msg = "the node is not accepting new instances"; } else if (resNcState == NOTREADY) { state = "NOTREADY"; if (strnlen(r->nodeMessage, 1024)) { msg = r->nodeMessage; } else { msg = "the node is currently experiencing problems and needs attention"; } } } else if (resState == RESASLEEP || resState == RESWAKING) { state = "NOTREADY"; msg = "the node is currently in the sleep state"; } else if (resState == RESDOWN) { state = "NOTREADY"; if (strnlen(r->nodeMessage, 1024)) { msg = r->nodeMessage; } else { msg = "the node is not responding to the cluster controller"; } } snprintf(myStatus->localState, 32, "%s", state); snprintf(myStatus->details, 1024, "%s", msg); // string that gets printed by 'euca-describe-services -E' } myStatus->localEpoch = config->ccStatus.localEpoch; sprintf(myStatus->serviceId.type, "node"); sprintf(myStatus->serviceId.name, r->hostname); sprintf(myStatus->serviceId.partition, config->ccStatus.serviceId.partition); sprintf(myStatus->serviceId.uris[0], r->ncURL); myStatus->serviceId.urisLen = 1; LOGDEBUG("external services\t uri[%d]: %s %s %s %s %s\n", idIdx, myStatus->serviceId.type, myStatus->serviceId.partition, myStatus->serviceId.name, myStatus->localState, myStatus->serviceId.uris[0]); } } } } } } LOGDEBUG("done\n"); return (0); }
//! //! Function description. //! //! @param[in] file //! @param[in] file_updated //! //! @return //! //! @see //! //! @pre List of pre-conditions //! //! @post List of post conditions //! //! @note //! int atomic_file_get(atomic_file * file, int *file_updated) { int port = 0; int fd = 0; int ret = 0; int rc = 0; char *hash = NULL; char type[32] = ""; char hostname[512] = ""; char path[MAX_PATH] = ""; char tmpsource[MAX_PATH] = ""; char tmppath[MAX_PATH] = ""; if (!file || !file_updated) { return (1); } ret = 0; *file_updated = 0; snprintf(file->tmpfile, MAX_PATH, "%s", file->tmpfilebase); fd = safe_mkstemp(file->tmpfile); if (fd < 0) { LOGERROR("cannot open tmpfile '%s'\n", file->tmpfile); return (1); } chmod(file->tmpfile, 0644); close(fd); snprintf(tmpsource, MAX_PATH, "%s", file->source); type[0] = tmppath[0] = path[0] = hostname[0] = '\0'; port = 0; tokenize_uri(tmpsource, type, hostname, &port, tmppath); snprintf(path, MAX_PATH, "/%s", tmppath); if (!strcmp(type, "http")) { rc = http_get_timeout(file->source, file->tmpfile, 0, 0, 10, 15); if (rc) { LOGERROR("http client failed to fetch file URL=%s\n", file->source); ret = 1; } } else if (!strcmp(type, "file")) { if (!strlen(path) || copy_file(path, file->tmpfile)) { LOGERROR("could not copy source file (%s) to dest file (%s)\n", path, file->tmpfile); ret = 1; } } else { LOGWARN("BUG: incompatible URI type (only support http, file): (%s)\n", type); ret = 1; } if (!ret) { if (file->tosort) { rc = atomic_file_sort_tmpfile(file); if (rc) { LOGWARN("could not sort tmpfile (%s) inplace\n", file->tmpfile); } } // do checksum - only copy if file has changed hash = file2md5str(file->tmpfile); if (!hash) { LOGERROR("could not compute hash of tmpfile (%s)\n", file->tmpfile); ret = 1; } else { if (file->currhash) EUCA_FREE(file->currhash); file->currhash = hash; if (check_file(file->dest) || strcmp(file->currhash, file->lasthash)) { // hashes are different, put new file in place LOGINFO("source and destination file contents have changed, triggering update of dest (%s)\n", file->dest); LOGDEBUG("renaming file %s -> %s\n", file->tmpfile, file->dest); if (rename(file->tmpfile, file->dest)) { LOGERROR("could not rename local copy to dest (%s -> %s)\n", file->tmpfile, file->dest); ret = 1; } else { EUCA_FREE(file->lasthash); file->lasthash = strdup(file->currhash); *file_updated = 1; } } } } unlink(file->tmpfile); return (ret); }
int doDescribeServices(ncMetadata *ccMeta, serviceInfoType *serviceIds, int serviceIdsLen, serviceStatusType **outStatuses, int *outStatusesLen) { int i, rc, ret=0; serviceStatusType *myStatus=NULL; rc = initialize(ccMeta); if (rc) { return(1); } logprintfl(EUCAINFO, "DescribeServices(): called\n"); logprintfl(EUCADEBUG, "DescribeServices(): params: userId=%s, serviceIdsLen=%d\n", SP(ccMeta ? ccMeta->userId : "UNSET"), serviceIdsLen); // TODO: for now, return error if list of services is passed in as parameter /* if (serviceIdsLen > 0) { logprintfl(EUCAERROR, "DescribeServices(): received non-zero number of input services, returning fail\n"); *outStatusesLen = 0; *outStatuses = NULL; return(1); } */ sem_mywait(CONFIG); if (!strcmp(config->ccStatus.serviceId.name, "self")) { for (i=0; i<serviceIdsLen; i++) { logprintfl(EUCADEBUG, "DescribeServices(): received input serviceId[%d]\n", i); if (strlen(serviceIds[i].type)) { if (!strcmp(serviceIds[i].type, "cluster")) { char uri[MAX_PATH], uriType[32], host[MAX_PATH], path[MAX_PATH]; int port; snprintf(uri, MAX_PATH, "%s", serviceIds[i].uris[0]); rc = tokenize_uri(uri, uriType, host, &port, path); if (strlen(host)) { logprintfl(EUCADEBUG, "DescribeServices(): setting local serviceId to input serviceId (type=%s name=%s partition=%s)\n", SP(serviceIds[i].type), SP(serviceIds[i].name), SP(serviceIds[i].partition)); memcpy(&(config->ccStatus.serviceId), &(serviceIds[i]), sizeof(serviceInfoType)); } } } } } sem_mypost(CONFIG); for (i=0; i<16; i++) { int j; if (strlen(config->services[i].type)) { logprintfl(EUCADEBUG, "DescribeServices(): internal serviceInfos type=%s name=%s partition=%s urisLen=%d\n", config->services[i].type, config->services[i].name, config->services[i].partition, config->services[i].urisLen); for (j=0; j<8; j++) { if (strlen(config->services[i].uris[j])) { logprintfl(EUCADEBUG, "DescribeServices(): internal serviceInfos\t uri[%d]:%s\n", j, config->services[i].uris[j]); } } } } for (i=0; i<16; i++) { int j; if (strlen(config->disabledServices[i].type)) { logprintfl(EUCADEBUG, "DescribeServices(): internal disabled serviceInfos type=%s name=%s partition=%s urisLen=%d\n", config->disabledServices[i].type, config->disabledServices[i].name, config->disabledServices[i].partition, config->disabledServices[i].urisLen); for (j=0; j<8; j++) { if (strlen(config->disabledServices[i].uris[j])) { logprintfl(EUCADEBUG, "DescribeServices(): internal disabled serviceInfos\t uri[%d]:%s\n", j, config->disabledServices[i].uris[j]); } } } } for (i=0; i<16; i++) { int j; if (strlen(config->notreadyServices[i].type)) { logprintfl(EUCADEBUG, "DescribeServices(): internal not ready serviceInfos type=%s name=%s partition=%s urisLen=%d\n", config->notreadyServices[i].type, config->notreadyServices[i].name, config->notreadyServices[i].partition, config->notreadyServices[i].urisLen); for (j=0; j<8; j++) { if (strlen(config->notreadyServices[i].uris[j])) { logprintfl(EUCADEBUG, "DescribeServices(): internal not ready serviceInfos\t uri[%d]:%s\n", j, config->notreadyServices[i].uris[j]); } } } } *outStatusesLen = 1; *outStatuses = malloc(sizeof(serviceStatusType)); if (!*outStatuses) { logprintfl(EUCAFATAL, "DescribeServices(): out of memory!\n"); unlock_exit(1); } myStatus = *outStatuses; snprintf(myStatus->localState, 32, "%s", config->ccStatus.localState); snprintf(myStatus->details, 1024, "%s", config->ccStatus.details); myStatus->localEpoch = config->ccStatus.localEpoch; memcpy(&(myStatus->serviceId), &(config->ccStatus.serviceId), sizeof(serviceInfoType)); logprintfl(EUCAINFO, "DescribeServices(): done\n"); return(0); }
//! //! Function description. //! //! @param[in] file //! @param[in] file_updated //! //! @return //! //! @see //! //! @pre List of pre-conditions //! //! @post List of post conditions //! //! @note //! int atomic_file_get(atomic_file * file, boolean * file_updated) { int port = 0; int fd = 0; int ret = 0; int rc = 0; char *hash = NULL; char type[32] = ""; char hostname[512] = ""; char path[EUCA_MAX_PATH] = ""; char tmpsource[EUCA_MAX_PATH] = ""; char tmppath[EUCA_MAX_PATH] = ""; if (!file || !file_updated) { return (1); } ret = 0; *file_updated = FALSE; snprintf(file->tmpfile, EUCA_MAX_PATH, "%s", file->tmpfilebase); fd = safe_mkstemp(file->tmpfile); if (fd < 0) { LOGERROR("cannot open tmpfile '%s': check permissions\n", file->tmpfile); return (1); } if (chmod(file->tmpfile, 0600)) { LOGWARN("chmod failed: was able to create tmpfile '%s', but could not change file permissions\n", file->tmpfile); } close(fd); snprintf(tmpsource, EUCA_MAX_PATH, "%s", file->source); type[0] = tmppath[0] = path[0] = hostname[0] = '\0'; port = 0; tokenize_uri(tmpsource, type, hostname, &port, tmppath); snprintf(path, EUCA_MAX_PATH, "/%s", tmppath); if (!strcmp(type, "http")) { rc = http_get_timeout(file->source, file->tmpfile, 0, 0, 10, 15, NULL); if (rc) { LOGERROR("http client failed to fetch file URL=%s: check http server status\n", file->source); ret = 1; } } else if (!strcmp(type, "file")) { if (!strlen(path) || copy_file(path, file->tmpfile)) { LOGERROR("could not copy source file (%s) to dest file (%s): check permissions\n", path, file->tmpfile); ret = 1; } } else { LOGWARN("BUG: incompatible URI type (%s) passed to routine (only supports http, file)\n", type); ret = 1; } if (!ret) { if (file->dosort) { rc = atomic_file_sort_tmpfile(file); if (rc) { LOGWARN("could not sort tmpfile (%s) inplace: continuing without sort\n", file->tmpfile); } } // do checksum - only copy if file has changed hash = file2md5str(file->tmpfile); if (!hash) { LOGERROR("could not compute hash of tmpfile (%s): check permissions\n", file->tmpfile); ret = 1; } else { if (file->currhash) EUCA_FREE(file->currhash); file->currhash = hash; if (check_file(file->dest) || strcmp(file->currhash, file->lasthash)) { // hashes are different, put new file in place LOGDEBUG("update triggered due to file update (%s)\n", file->dest); LOGDEBUG("source and destination file contents have become different, triggering update of dest (%s)\n", file->dest); LOGDEBUG("renaming file %s -> %s\n", file->tmpfile, file->dest); if (rename(file->tmpfile, file->dest)) { LOGERROR("could not rename (move) source file '%s' to dest file '%s': check permissions\n", file->tmpfile, file->dest); ret = 1; } else { EUCA_FREE(file->lasthash); file->lasthash = strdup(file->currhash); *file_updated = TRUE; } } } } unlink(file->tmpfile); return (ret); }