/* match will find a child in the parent, and either replace (if it's an insert) or remove (if data is NULL) */ int xdb_act(xdbcache xc, jid owner, char *ns, char *act, char *match, xmlnode data) { xdbrequest_p cur; struct timeval tv; if (xc->shutdown) return 1; if (xc == NULL || owner == NULL || ns == NULL) { log_alert("xdb_set", "Programming Error: xdb_set() called with NULL\n"); return 1; } log_debug("XDB SET"); cur = malloc(sizeof(xdbrequest_t)); memset(cur, 0, sizeof(xdbrequest_t)); cur->set = 1; cur->data = data; cur->ns = ns; cur->owner = owner; cur->act = act; cur->match = match; gettimeofday(&tv, NULL); cur->sent = tv.tv_sec; SEM_LOCK(xc->sem); cur->id = xc->id++; cur->next = xc->first; xc->first = cur; SEM_UNLOCK(xc->sem); /* send it on it's way */ xdb_deliver(xc->i, cur, 0); cur->external = 1; /* if it hasn't already returned, we should block here until it returns */ while (cur->preblock != 1) usleep(10); /* if it didn't actually get set, flag that */ if (cur->data == NULL) { free(cur); return 1; } xmlnode_free(cur->data); free(cur); return 0; }
/* match will find a child in the parent, and either replace (if it's an insert) or remove (if data is NULL) */ int xdb_act(xdbcache xc, jid owner, char *ns, char *act, char *match, xmlnode data) { xdbcache newx; pool p; if(xc == NULL || owner == NULL || ns == NULL) { fprintf(stderr,"Programming Error: xdb_set() called with NULL\n"); return 1; } log_debug(ZONE,"XDB SET"); /* init this newx */ p = pool_new(); newx = pmalloco(p, sizeof(_xdbcache)); newx->i = xc->i; newx->set = 1; newx->data = data; newx->ns = ns; newx->act = act; newx->match = match; newx->owner = owner; newx->sent = time(NULL); newx->preblock = 0; /* flag */ pthread_mutex_lock(&(xc->sem)); newx->id = xc->id++; newx->next = xc->next; newx->prev = xc; newx->next->prev = newx; xc->next = newx; pthread_mutex_unlock(&(xc->sem)); /* send it on it's way */ xdb_deliver(xc->i, newx,0); /* if it hasn't already returned, we should block here until it returns */ while (newx->preblock != 1) usleep(10); /* if it didn't actually get set, flag that */ if(newx->data == NULL) { pool_free(p); return 1; } xmlnode_free(newx->data); pool_free(p); return 0; }
/* blocks until namespace is retrieved, host must map back to this service! */ xmlnode xdb_get(xdbcache xc, jid owner, char *ns) { xdbcache newx; xmlnode x; pool p; if(xc == NULL || owner == NULL || ns == NULL) { fprintf(stderr,"Programming Error: xdb_get() called with NULL\n"); return NULL; } log_debug(ZONE,"XDB GET"); /* init this newx */ p = pool_new(); newx = pmalloco(p, sizeof(_xdbcache)); newx->i = xc->i; newx->set = 0; newx->data = NULL; newx->ns = ns; newx->owner = owner; newx->sent = time(NULL); newx->preblock = 0; /* flag */ pthread_mutex_lock(&(xc->sem)); newx->id = xc->id++; newx->next = xc->next; newx->prev = xc; newx->next->prev = newx; xc->next = newx; pthread_mutex_unlock(&(xc->sem)); /* send it on it's way */ xdb_deliver(xc->i, newx,0); /* if it hasn't already returned, we should block here until it returns */ while (newx->preblock != 1) usleep(10); /* newx.data is now the returned xml packet */ /* return the xmlnode inside <xdb>...</xdb> */ for(x = xmlnode_get_firstchild(newx->data); x != NULL && xmlnode_get_type(x) != NTYPE_TAG; x = xmlnode_get_nextsibling(x)); /* there were no children (results) to the xdb request, free the packet */ if(x == NULL) xmlnode_free(newx->data); pool_free(p); return x; }
/** resend packets. heartbeat thread */ result xdb_thump(void *arg) { xdbcache xc = (xdbcache)arg; xdbcache cur, next; int now = time(NULL); pthread_mutex_lock(&(xc->sem)); /* spin through the cache looking for stale requests */ cur = xc->next; while(cur != xc) { next = cur->next; /* really old ones get wacked */ if((now - cur->sent) > 30) { /* remove from ring */ cur->prev->next = cur->next; cur->next->prev = cur->prev; /* make sure it's null as a flag for xdb_set's */ cur->data = NULL; /* free the thread! */ cur->preblock = 1; cur = next; continue; } /* resend the waiting ones every so often */ if((now - cur->sent) > 10) { log_alert(ZONE,"Resend xdb packet"); xdb_deliver(xc->i, cur,1); } /* cur could have been free'd already on it's thread */ cur = next; } pthread_mutex_unlock(&(xc->sem)); return r_DONE; }
/** resend packets. heartbeat thread */ result xdb_thump(void *arg) { xdbcache xc = (xdbcache) arg; xdbrequest_p cur, next, last; struct timeval tv; time_t now; if (xc->shutdown) return r_UNREG; gettimeofday(&tv, NULL); now = tv.tv_sec; SEM_LOCK(xc->sem); /* spin through the cache looking for stale requests */ for (last = NULL, cur = xc->first; cur;) { next = cur->next; if ((cur->external) && ((now - cur->sent) > 30)) { if (!last) xc->first = next; else last->next = next; cur->data = NULL; cur->preblock = 1; } else { last = cur; if ((cur->external) && ((now - cur->sent) > 10)) { log_alert("xdb", "Resend xdb packet"); xdb_deliver(xc->i, cur, 1); } } cur = next; } SEM_UNLOCK(xc->sem); return r_DONE; }
/* blocks until namespace is retrieved, host must map back to this service! */ xmlnode xdb_get(xdbcache xc, jid owner, char *ns) { xdbrequest_p cur; xmlnode x; struct timeval tv; if (xc->shutdown) return NULL; if (xc == NULL || owner == NULL || ns == NULL) { if (ns) { log_alert("xdb_get", "Programming Error: xdb_get() called with NULL ns: %s\n", ns); } else { log_alert("xdb_get", "Programming Error: xdb_get() called with NULL ns: NULL\n"); } if (owner) { log_alert("owner", "%s", jid_full(owner)); } return NULL; } log_debug("XDB GET"); /* init this newx */ cur = malloc(sizeof(xdbrequest_t)); memset(cur, 0, sizeof(xdbrequest_t)); // cur->set = 0; // cur->data = NULL; cur->ns = ns; cur->owner = owner; gettimeofday(&tv, NULL); cur->sent = tv.tv_sec; SEM_LOCK(xc->sem); cur->id = xc->id++; cur->next = xc->first; xc->first = cur; SEM_UNLOCK(xc->sem); /* send it on it's way */ xdb_deliver(xc->i, cur, 0); cur->external = 1; /* if it hasn't already returned, we should block here until it returns */ while (cur->preblock != 1) usleep(10); /* newx.data is now the returned xml packet */ /* return the xmlnode inside <xdb>...</xdb> */ for (x = xmlnode_get_firstchild(cur->data); x != NULL && xmlnode_get_type(x) != NTYPE_TAG; x = xmlnode_get_nextsibling(x)); /* there were no children (results) to the xdb request, free the packet */ if (x == NULL) xmlnode_free(cur->data); free(cur); return x; }