예제 #1
0
static void dns_ctx_release(dns_ctx_handle_t *h) {
  if(h->ns == NULL) {
    /* Special case for the default */
    noit_atomic_dec32(&h->refcnt);
    return;
  }
  pthread_mutex_lock(&dns_ctx_store_lock);
  if(noit_atomic_dec32(&h->refcnt) == 0) {
    /* I was the last one */
    assert(noit_hash_delete(&dns_ctx_store, h->ns, strlen(h->ns),
                            NULL, dns_ctx_handle_free));
  }
  pthread_mutex_unlock(&dns_ctx_store_lock);
}
예제 #2
0
int
stratcon_realtime_http_postresolve(eventer_t e, int mask, void *closure,
                                   struct timeval *now) {
  noit_http_session_ctx *ctx = closure;
  realtime_context *rc = ctx->dispatcher_closure;
  struct realtime_tracker *node;

  for(node = rc->checklist; node; node = node->next) {
    if(node->noit) {
      realtime_recv_ctx_t *rrctx;
      rrctx = calloc(1, sizeof(*rrctx));
      rrctx->ctx = ctx;
      rrctx->rt = node;
      stratcon_streamer_connection(NULL, node->noit,
                                   stratcon_realtime_recv_handler,
                                   NULL, rrctx,
                                   free_realtime_recv_ctx);
    }
    else
      noit_atomic_dec32(&ctx->ref_cnt);
  }
  if(ctx->ref_cnt == 1) {
    noit_http_response_end(ctx);
    clear_realtime_context(rc);
    if(ctx->conn.e) eventer_trigger(ctx->conn.e, EVENTER_WRITE);
  }
  return 0;
}
예제 #3
0
static int noit_lua_dns_lookup(lua_State *L) {
  dns_lookup_ctx_t *dlc, **holder;
  const char *c, *query = "", *ctype = "IN", *rtype = "A";
  char *ctype_up, *rtype_up, *d;
  void *vnv_pair;
  noit_lua_check_info_t *ci;

  ci = get_ci(L);
  assert(ci);

  holder = (dns_lookup_ctx_t **)lua_touserdata(L, lua_upvalueindex(1));
  if(holder != lua_touserdata(L,1))
    luaL_error(L, "Must be called as method\n");
  dlc = *holder;

  if(lua_gettop(L) > 1) query = lua_tostring(L, 2);
  if(lua_gettop(L) > 2) rtype = lua_tostring(L, 3);
  if(lua_gettop(L) > 3) ctype = lua_tostring(L, 4);

  ctype_up = alloca(strlen(ctype)+1);
  for(d = ctype_up, c = ctype; *c; d++, c++) *d = toupper(*c);
  *d = '\0';
  rtype_up = alloca(strlen(rtype)+1);
  for(d = rtype_up, c = rtype; *c; d++, c++) *d = toupper(*c);
  *d = '\0';

  if(!noit_hash_retrieve(&dns_ctypes, ctype_up, strlen(ctype_up), &vnv_pair))
    dlc->error = strdup("bad class");
  else
    dlc->query_ctype = ((struct dns_nameval *)vnv_pair)->val;

  if(!noit_hash_retrieve(&dns_rtypes, rtype_up, strlen(rtype_up), &vnv_pair)) 
    dlc->error = strdup("bad rr type");
  else
    dlc->query_rtype = ((struct dns_nameval *)vnv_pair)->val;

  dlc->active = 1;
  noit_atomic_inc32(&dlc->refcnt);
  if(!dlc->error) {
    int abs;
    if(!dns_ptodn(query, strlen(query), dlc->dn, sizeof(dlc->dn), &abs) ||
       !dns_submit_dn(dlc->h->ctx, dlc->dn, dlc->query_ctype, dlc->query_rtype,
                      abs | DNS_NOSRCH, NULL, dns_cb, dlc)) {
      dlc->error = strdup("submission error");
      noit_atomic_dec32(&dlc->refcnt);
    }
    else {
      struct timeval now;
      gettimeofday(&now, NULL);
      dns_timeouts(dlc->h->ctx, -1, now.tv_sec);
    }
  }
  if(dlc->error) {
    dlc->active = 0;
    luaL_error(L, "dns: %s\n", dlc->error);
  }
  return noit_lua_yield(ci, 0);
}
예제 #4
0
static int dns_module_dns_ctx_release(dns_ctx_handle_t *h) {
  int rv = 0, last;
  if(h->ns == NULL) {
    /* Special case for the default */
    noit_atomic_dec32(&h->refcnt);
    return rv;
  }
  pthread_mutex_lock(&dns_ctx_store_lock);
  last = noit_atomic_dec32(&h->refcnt);
  if(last == 0) {
    /* I was the last one */
    assert(noit_hash_delete(&dns_ctx_store, h->hkey, strlen(h->hkey),
                            NULL, dns_module_dns_ctx_handle_free));
    rv = 1;
  }
  pthread_mutex_unlock(&dns_ctx_store_lock);
  return rv;
}
예제 #5
0
void lookup_ctx_release(dns_lookup_ctx_t *v) {
  if(!v) return;
  if(v->error) free(v->error);
  v->error = NULL;
  if(noit_atomic_dec32(&v->refcnt) == 0) {
    dns_ctx_release(v->h);
    free(v);
  }
}
예제 #6
0
static void
free_realtime_recv_ctx(void *vctx) {
  realtime_recv_ctx_t *rrctx = vctx;
  noit_http_session_ctx *ctx = rrctx->ctx;
  realtime_context *rc = ctx->dispatcher_closure;

  if(noit_atomic_dec32(&ctx->ref_cnt) == 1) {
    noit_http_response_end(ctx);
    clear_realtime_context(rc);
    if(ctx->conn.e) eventer_trigger(ctx->conn.e, EVENTER_WRITE | EVENTER_EXCEPTION);
  }
  free(rrctx);
}
예제 #7
0
static void
filterset_free(void *vp) {
  filterset_t *fs = vp;
  filterrule_t *r;
  if(noit_atomic_dec32(&fs->ref_cnt) != 0) return;
  noitL(noit_error, "Freeing filterset [%d]: %s\n", fs->ref_cnt, fs->name);
  while(fs->rules) {
    r = fs->rules->next;
    filterrule_free(fs->rules);
    fs->rules = r;
  }
  if(fs->name) free(fs->name);
  free(fs);
}
예제 #8
0
void *
noit_jlog_thread_main(void *e_vptr) {
  int mask, bytes_read;
  eventer_t e = e_vptr;
  acceptor_closure_t *ac = e->closure;
  noit_jlog_closure_t *jcl = ac->service_ctx;
  char inbuff[sizeof(jlog_id)];

  eventer_set_fd_blocking(e->fd);

  while(1) {
    jlog_id client_chkpt;
    int sleeptime = (ac->cmd == NOIT_JLOG_DATA_TEMP_FEED) ?
                      1 : DEFAULT_SECONDS_BETWEEN_BATCHES;
    jlog_get_checkpoint(jcl->jlog, ac->remote_cn, &jcl->chkpt);
    jcl->count = jlog_ctx_read_interval(jcl->jlog, &jcl->start, &jcl->finish);
    if(jcl->count < 0) {
      char idxfile[PATH_MAX];
      noitL(noit_error, "jlog_ctx_read_interval: %s\n",
            jlog_ctx_err_string(jcl->jlog));
      switch (jlog_ctx_err(jcl->jlog)) {
        case JLOG_ERR_FILE_CORRUPT:
        case JLOG_ERR_IDX_CORRUPT:
          jlog_repair_datafile(jcl->jlog, jcl->start.log);
          jlog_repair_datafile(jcl->jlog, jcl->start.log + 1);
          noitL(noit_error,
                "jlog reconstructed, deleting corresponding index.\n");
          STRSETDATAFILE(jcl->jlog, idxfile, jcl->start.log);
          strlcat(idxfile, INDEX_EXT, sizeof(idxfile));
          unlink(idxfile);
          STRSETDATAFILE(jcl->jlog, idxfile, jcl->start.log + 1);
          strlcat(idxfile, INDEX_EXT, sizeof(idxfile));
          unlink(idxfile);
          goto alldone;
          break;
        default:
          goto alldone;
      }
    }
    if(jcl->count > MAX_ROWS_AT_ONCE) {
      /* Artificially set down the range to make the batches a bit easier
       * to handle on the stratcond/postgres end.
       * However, we must have more data, so drop the sleeptime to 0
       */
      jcl->count = MAX_ROWS_AT_ONCE;
      jcl->finish.marker = jcl->start.marker + jcl->count;
      sleeptime = 0;
    }
    if(jcl->count > 0) {
      if(noit_jlog_push(e, jcl)) {
        goto alldone;
      }
      /* Read our jlog_id accounting for possibly short reads */
      bytes_read = 0;
      while(bytes_read < sizeof(jlog_id)) {
        int len;
        if((len = e->opset->read(e->fd, inbuff + bytes_read,
                                 sizeof(jlog_id) - bytes_read,
                                 &mask, e)) <= 0)
          goto alldone;
        bytes_read += len;
      }
      memcpy(&client_chkpt, inbuff, sizeof(jlog_id));
      /* Fix the endian */
      client_chkpt.log = ntohl(client_chkpt.log);
      client_chkpt.marker = ntohl(client_chkpt.marker);
  
      if(memcmp(&jcl->chkpt, &client_chkpt, sizeof(jlog_id))) {
        noitL(noit_error,
              "client %s submitted invalid checkpoint %u:%u expected %u:%u\n",
              ac->remote_cn, client_chkpt.log, client_chkpt.marker,
              jcl->chkpt.log, jcl->chkpt.marker);
        goto alldone;
      }
      gettimeofday(&jcl->feed_stats->last_checkpoint, NULL);
      jlog_ctx_read_checkpoint(jcl->jlog, &jcl->chkpt);
    }
    else {
      /* we have nothing to write -- maybe we have no checks configured...
       * If this is the case "forever", the remote might disconnect and
       * we would never know. Do the painful work of detecting a
       * disconnected client.
       */
      struct pollfd pfd;
      pfd.fd = e->fd;
      pfd.events = POLLIN | POLLHUP | POLLRDNORM;
      pfd.revents = 0;
      if(poll(&pfd, 1, 0) != 0) {
        /* normally, we'd recv PEEK|DONTWAIT.  However, the client should
         * not be writing to us.  So, we know we can't have any legitimate
         * data on this socket (true even though this is SSL). So, if we're
         * here then "shit went wrong"
         */
        noitL(noit_error, "jlog client %s disconnected while idle\n",
              ac->remote_cn);
        goto alldone;
      }
    }
    if(sleeptime) sleep(sleeptime);
  }

 alldone:
  e->opset->close(e->fd, &mask, e);
  noit_atomic_dec32(&jcl->feed_stats->connections);
  noit_jlog_closure_free(jcl);
  acceptor_closure_free(ac);
  return NULL;
}