Exemplo n.º 1
0
/* Update metric oldest and latest timestamps when removing old values */
void pg_cache_update_metric_times(struct pg_cache_page_index *page_index)
{
    Pvoid_t *firstPValue, *lastPValue;
    Word_t firstIndex, lastIndex;
    struct rrdeng_page_cache_descr *descr;
    usec_t oldest_time = INVALID_TIME;
    usec_t latest_time = INVALID_TIME;

    uv_rwlock_rdlock(&page_index->lock);
    /* Find first page in range */
    firstIndex = (Word_t)0;
    firstPValue = JudyLFirst(page_index->JudyL_array, &firstIndex, PJE0);
    if (likely(NULL != firstPValue)) {
        descr = *firstPValue;
        oldest_time = descr->start_time;
    }
    lastIndex = (Word_t)-1;
    lastPValue = JudyLLast(page_index->JudyL_array, &lastIndex, PJE0);
    if (likely(NULL != lastPValue)) {
        descr = *lastPValue;
        latest_time = descr->end_time;
    }
    uv_rwlock_rdunlock(&page_index->lock);

    if (unlikely(NULL == firstPValue)) {
        assert(NULL == lastPValue);
        page_index->oldest_time = page_index->latest_time = INVALID_TIME;
        return;
    }
    page_index->oldest_time = oldest_time;
    page_index->latest_time = latest_time;
}
Exemplo n.º 2
0
void RefMap::free()
{
  unsigned long idx = 0;
  Node** pp = (Node**) JudyLFirst(nodes, &idx, NULL);
  while (pp != NULL)
  {
    free_node(*pp);
    pp = (Node**) JudyLNext(nodes, &idx, NULL);
  }
  JudyLFreeArray(&nodes, NULL);

  if (overflow != NULL) { free_node(overflow); overflow = NULL; }
}
Exemplo n.º 3
0
int
JudyLDup(PPvoid_t PPDest, Pvoid_t PSource, JError_t * PJError)
{
    Pvoid_t   newJArray = 0;            // new JudyL array to ppopulate
    Word_t    kindex;                   // Key/index
    int       Ins_rv = 0;               // Insert return value

    for (kindex = 0L, Ins_rv = JudyLFirst(PSource, &kindex, PJError);
         Ins_rv == 1; Ins_rv = JudyLNext(PSource, &kindex, PJError))
    {
        Ins_rv = JudyLSet(&newJArray, kindex, PJError);
    }
    if (Ins_rv == JERR)
        return Ins_rv;

    *PPDest = newJArray;
    return Ins_rv;
}                                       /*  JudyLDup */
Exemplo n.º 4
0
unsigned long flx_collector_t::sweep()
{
  if(debug)
    fprintf(stderr,"Collector: Sweep, garbage bit value=%d\n",(int)parity);
  unsigned long sweeped = 0;
  void *current = NULL;
  Word_t *pshape = (Word_t*)JudyLFirst(j_shape,(Word_t*)&current,&je);
  if(pshape==(Word_t*)PPJERR)judyerror("sweep");

  while(pshape!=NULL)
  {
    if((*pshape & 1) == (parity & 1UL))
    {
      if(debug)
        fprintf(stderr,"Garbage %p=%s\n",current,((gc_shape_t*)(*pshape & ~1UL))->cname);
      ++ sweeped;
      //fprintf(stderr,"Unlinking ..\n");
      unlink(current);
      //fprintf(stderr,"Posting delete ..\n");
      post_delete(current);
      //fprintf(stderr,"Reaping done\n");
    }
    else
      if(debug)
        fprintf(stderr,"Reachable %p=%s\n",current,((gc_shape_t*)(*pshape & ~1UL))->cname);

    //fprintf(stderr,"Calling Judy for next object\n");
    pshape = (Word_t*)JudyLNext(j_shape,(Word_t*)(void*)&current,&je);
    //fprintf(stderr,"Judy got next object %p\n",pshape);
  }

  parity = !parity;
  if(debug)
    fprintf(stderr,"Sweeped %ld\n",sweeped);
  return reap();
}
Exemplo n.º 5
0
FUNCTION Word_t JUDY_EXTERN Judy1Count
#else
FUNCTION Word_t JUDY_EXTERN JudyLCount
#endif
        (
	Pcvoid_t  PArray,	// JRP to first branch/leaf in SM.
	Word_t	  Index1,	// starting Index.
	Word_t	  Index2,	// ending Index.
	PJError_t PJError	// optional, for returning error info.
        )
{
	jpm_t	  fakejpm;	// local temporary for small arrays.
	Pjpm_t	  Pjpm;		// top JPM or local temporary for error info.
	jp_t	  fakejp;	// constructed for calling j__udy1LCountSM().
	Pjp_t	  Pjp;		// JP to pass to j__udy1LCountSM().
	Word_t	  pop1;		// total for the array.
	Word_t	  pop1above1;	// indexes at or above Index1, inclusive.
	Word_t	  pop1above2;	// indexes at or above Index2, exclusive.
	int	  retcode;	// from Judy*First() calls.
JUDYLCODE(PPvoid_t PPvalue);	// from JudyLFirst() calls.


// CHECK FOR SHORTCUTS:
//
// As documented, return C_JERR if the Judy array is empty or Index1 > Index2.

	if ((PArray == (Pvoid_t) NULL) || (Index1 > Index2))
	{
	    JU_SET_ERRNO(PJError, JU_ERRNO_NONE);
	    return(C_JERR);
	}

// If Index1 == Index2, simply check if the specified Index is set; pass
// through the return value from Judy1Test() or JudyLGet() with appropriate
// translations.

	if (Index1 == Index2)
	{
#ifdef JUDY1
	    retcode = Judy1Test(PArray, Index1, PJError);

	    if (retcode == JERRI) return(C_JERR);	// pass through error.

	    if (retcode == 0)
	    {
		JU_SET_ERRNO(PJError, JU_ERRNO_NONE);
		return(C_JERR);
	    }
#else
	    PPvalue = JudyLGet(PArray, Index1, PJError);

	    if (PPvalue == PPJERR) return(C_JERR);	// pass through error.

	    if (PPvalue == (PPvoid_t) NULL)		// Index is not set.
	    {
		JU_SET_ERRNO(PJError, JU_ERRNO_NONE);
		return(C_JERR);
	    }
#endif
	    return(1);					// single index is set.
	}


// CHECK JRP TYPE:
//
// Use an if/then for speed rather than a switch, and put the most common cases
// first.
//
// Note:  Since even cJU_LEAFW types require counting between two Indexes,
// prepare them here for common code below that calls j__udy1LCountSM(), rather
// than handling them even more specially here.

	if (JU_LEAFW_POP0(PArray) < cJU_LEAFW_MAXPOP1) // must be a LEAFW
	{
	    Pjlw_t Pjlw	   = P_JLW(PArray);	// first word of leaf.
	    Pjpm	   = & fakejpm;
	    Pjp		   = & fakejp;
	    Pjp->jp_Addr   = (Word_t) Pjlw;
	    Pjp->jp_Type   = cJU_LEAFW;
	    Pjpm->jpm_Pop0 = Pjlw[0];		// from first word of leaf.
	    pop1	   = Pjpm->jpm_Pop0 + 1;
	}
	else
	{
	    Pjpm = P_JPM(PArray);
	    Pjp	 = &(Pjpm->jpm_JP);
	    pop1 = (Pjpm->jpm_Pop0) + 1;	// note: can roll over to 0.

#if (defined(JUDY1) && (! defined(JU_64BIT)))
	    if (pop1 == 0)		// rare special case of full array:
	    {
		Word_t count = Index2 - Index1 + 1;	// can roll over again.

		if (count == 0)
		{
		    JU_SET_ERRNO(PJError, JU_ERRNO_FULL);
		    return(C_JERR);
		}
		return(count);
	    }
#else
	    assert(pop1);	// JudyL or 64-bit cannot create a full array!
#endif
	}


// COUNT POP1 ABOVE INDEX1, INCLUSIVE:

	assert(pop1);		// just to be safe.

	if (Index1 == 0)	// shortcut, pop1above1 is entire population:
	{
	    pop1above1 = pop1;
	}
	else			// find first valid Index above Index1, if any:
	{
#ifdef JUDY1
	    if ((retcode = Judy1First(PArray, & Index1, PJError)) == JERRI)
		return(C_JERR);			// pass through error.
#else
	    if ((PPvalue = JudyLFirst(PArray, & Index1, PJError)) == PPJERR)
		return(C_JERR);			// pass through error.

	    retcode = (PPvalue != (PPvoid_t) NULL);	// found a next Index.
#endif

// If theres no Index at or above Index1, just return C_JERR (early exit):

	    if (retcode == 0)
	    {
		JU_SET_ERRNO(PJError, JU_ERRNO_NONE);
		return(C_JERR);
	    }

// If a first/next Index was found, call the counting motor starting with that
// known valid Index, meaning the return should be positive, not C_JERR except
// in case of a real error:

	    if ((pop1above1 = j__udy1LCountSM(Pjp, Index1, Pjpm)) == C_JERR)
	    {
		JU_COPY_ERRNO(PJError, Pjpm);	// pass through error.
		return(C_JERR);
	    }
	}


// COUNT POP1 ABOVE INDEX2, EXCLUSIVE, AND RETURN THE DIFFERENCE:
//
// In principle, calculate the ordinal of each Index and take the difference,
// with caution about off-by-one errors due to the specified Indexes being set
// or unset.  In practice:
//
// - The ordinals computed here are inverse ordinals, that is, the populations
//   ABOVE the specified Indexes (Index1 inclusive, Index2 exclusive), so
//   subtract pop1above2 from pop1above1, rather than vice-versa.
//
// - Index1s result already includes a count for Index1 and/or Index2 if
//   either is set, so calculate pop1above2 exclusive of Index2.
//
// TBD:  If Index1 and Index2 fall in the same expanse in the top-state
// branch(es), would it be faster to walk the SM only once, to their divergence
// point, before calling j__udy1LCountSM() or equivalent?  Possibly a non-issue
// if a top-state pop1 becomes stored with each Judy1 array.  Also, consider
// whether the first call of j__udy1LCountSM() fills the cache, for common tree
// branches, for the second call.
//
// As for pop1above1, look for shortcuts for special cases when pop1above2 is
// zero.  Otherwise call the counting "motor".

	    assert(pop1above1);		// just to be safe.

	    if (Index2++ == cJU_ALLONES) return(pop1above1); // Index2 at limit.

#ifdef JUDY1
	    if ((retcode = Judy1First(PArray, & Index2, PJError)) == JERRI)
		return(C_JERR);
#else
	    if ((PPvalue = JudyLFirst(PArray, & Index2, PJError)) == PPJERR)
		return(C_JERR);

	    retcode = (PPvalue != (PPvoid_t) NULL);	// found a next Index.
#endif
	    if (retcode == 0) return(pop1above1);  // no Index above Index2.

// Just as for Index1, j__udy1LCountSM() cannot return 0 (locally == C_JERR)
// except in case of a real error:

	    if ((pop1above2 = j__udy1LCountSM(Pjp, Index2, Pjpm)) == C_JERR)
	    {
		JU_COPY_ERRNO(PJError, Pjpm);		// pass through error.
		return(C_JERR);
	    }

	    if (pop1above1 == pop1above2)
	    {
		JU_SET_ERRNO(PJError, JU_ERRNO_NONE);
		return(C_JERR);
	    }

	    return(pop1above1 - pop1above2);

} // Judy1Count() / JudyLCount()
Exemplo n.º 6
0
Arquivo: subreq.c Projeto: dimarik/ugh
int ugh_subreq_gen(ugh_subreq_t *r, strp u_host)
{
	ugh_client_t *c = r->c;

	/* generate request line */

	if (0 == r->u.uri.size)
	{
		aux_buffer_printf(&r->b_send, c->pool, "%s %.*s%s%.*s %s" CRLF
			, ugh_method_string[r->method]
			, (int) c->uri.size, c->uri.data
			, c->args.size ? "?" : ""
			, (int) c->args.size, c->args.data
			, ugh_version_string[c->version]
		);
	}
	else if (0 == r->u.args.size)
	{
		aux_buffer_printf(&r->b_send, c->pool, "%s %.*s%s%.*s %s" CRLF
			, ugh_method_string[r->method]
			, (int) r->u.uri.size, r->u.uri.data
			, c->args.size ? "?" : ""
			, (int) c->args.size, c->args.data
			, ugh_version_string[c->version]
		);
	}
	else
	{
		aux_buffer_printf(&r->b_send, c->pool, "%s %.*s?%.*s %s" CRLF
			, ugh_method_string[r->method]
			, (int) r->u.uri.size, r->u.uri.data
			, (int) r->u.args.size, r->u.args.data
			, ugh_version_string[c->version]
		);
	}

	/* copy original request headers, change host header with new value */

	Word_t idx = 0;
	void **vptr;

	for (vptr = JudyLFirst(c->headers_hash, &idx, PJE0); NULL != vptr;
		 vptr = JudyLNext (c->headers_hash, &idx, PJE0))
	{
		ugh_header_t *h = *vptr;

		if (4 == h->key.size && aux_hash_key_lc_header("Host", 4) == aux_hash_key_lc_header(h->key.data, h->key.size))
		{
			aux_buffer_printf(&r->b_send, c->pool, "Host: %.*s" CRLF
				, (int) u_host->size, u_host->data
			);
		}
		else if (14 == h->key.size && aux_hash_key_lc_header("Content-Length", 14) == aux_hash_key_lc_header(h->key.data, h->key.size) && r->method == UGH_HTTP_GET)
		{
			continue; /* remove Content-Length header if it was in original request, but this request is GET */
		}
		else
		{
			aux_buffer_printf(&r->b_send, c->pool, "%.*s: %.*s" CRLF
				, (int) h->key.size, h->key.data
				, (int) h->value.size, h->value.data
			);
		}
	}

	if (NULL != r->request_body.data)
	{
		if (r->c->method != UGH_HTTP_POST) /* don't write new Content-Length if it was in original request */
		{
			aux_buffer_printf(&r->b_send, c->pool, "Content-Length: %"PRIuMAX CRLF
				, (uintmax_t) r->request_body.size
			);
		}

		/* TODO Content-Type */

		aux_buffer_strcpy(&r->b_send, c->pool, CRLF);

		aux_buffer_memcpy(&r->b_send, c->pool, r->request_body.data, r->request_body.size);
	}
	else
	{
		aux_buffer_strcpy(&r->b_send, c->pool, CRLF);
	}

	/* log_debug("ugh_subreq(%.*s)", (int) r->buf_send.size, r->buf_send.data); */

	return 0;
}
Exemplo n.º 7
0
/*
 * Searches for a page and triggers disk I/O if necessary and possible.
 * Does not get a reference.
 * Returns page index pointer for given metric UUID.
 */
struct pg_cache_page_index *
        pg_cache_preload(struct rrdengine_instance *ctx, uuid_t *id, usec_t start_time, usec_t end_time)
{
    struct page_cache *pg_cache = &ctx->pg_cache;
    struct rrdeng_page_cache_descr *descr = NULL, *preload_array[PAGE_CACHE_MAX_PRELOAD_PAGES];
    int i, j, k, count, found;
    unsigned long flags;
    Pvoid_t *PValue;
    struct pg_cache_page_index *page_index;
    Word_t Index;
    uint8_t failed_to_reserve;

    uv_rwlock_rdlock(&pg_cache->metrics_index.lock);
    PValue = JudyHSGet(pg_cache->metrics_index.JudyHS_array, id, sizeof(uuid_t));
    if (likely(NULL != PValue)) {
        page_index = *PValue;
    }
    uv_rwlock_rdunlock(&pg_cache->metrics_index.lock);
    if (NULL == PValue) {
        debug(D_RRDENGINE, "%s: No page was found to attempt preload.", __func__);
        return NULL;
    }

    uv_rwlock_rdlock(&page_index->lock);
    /* Find first page in range */
    found = 0;
    Index = (Word_t)(start_time / USEC_PER_SEC);
    PValue = JudyLLast(page_index->JudyL_array, &Index, PJE0);
    if (likely(NULL != PValue)) {
        descr = *PValue;
        if (is_page_in_time_range(descr, start_time, end_time)) {
            found = 1;
        }
    }
    if (!found) {
        Index = (Word_t)(start_time / USEC_PER_SEC);
        PValue = JudyLFirst(page_index->JudyL_array, &Index, PJE0);
        if (likely(NULL != PValue)) {
            descr = *PValue;
            if (is_page_in_time_range(descr, start_time, end_time)) {
                found = 1;
            }
        }
    }
    if (!found) {
        uv_rwlock_rdunlock(&page_index->lock);
        debug(D_RRDENGINE, "%s: No page was found to attempt preload.", __func__);
        return page_index;
    }

    for (count = 0 ;
         descr != NULL && is_page_in_time_range(descr, start_time, end_time);
         PValue = JudyLNext(page_index->JudyL_array, &Index, PJE0),
         descr = unlikely(NULL == PValue) ? NULL : *PValue) {
        /* Iterate all pages in range */

        if (unlikely(0 == descr->page_length))
            continue;
        uv_mutex_lock(&descr->mutex);
        flags = descr->flags;
        if (pg_cache_can_get_unsafe(descr, 0)) {
            if (flags & RRD_PAGE_POPULATED) {
                /* success */
                uv_mutex_unlock(&descr->mutex);
                debug(D_RRDENGINE, "%s: Page was found in memory.", __func__);
                continue;
            }
        }
        if (!(flags & RRD_PAGE_POPULATED) && pg_cache_try_get_unsafe(descr, 1)) {
            preload_array[count++] = descr;
            if (PAGE_CACHE_MAX_PRELOAD_PAGES == count) {
                uv_mutex_unlock(&descr->mutex);
                break;
            }
        }
        uv_mutex_unlock(&descr->mutex);

    };
    uv_rwlock_rdunlock(&page_index->lock);

    failed_to_reserve = 0;
    for (i = 0 ; i < count && !failed_to_reserve ; ++i) {
        struct rrdeng_cmd cmd;
        struct rrdeng_page_cache_descr *next;

        descr = preload_array[i];
        if (NULL == descr) {
            continue;
        }
        if (!pg_cache_try_reserve_pages(ctx, 1)) {
            failed_to_reserve = 1;
            break;
        }
        cmd.opcode = RRDENG_READ_EXTENT;
        cmd.read_extent.page_cache_descr[0] = descr;
        /* don't use this page again */
        preload_array[i] = NULL;
        for (j = 0, k = 1 ; j < count ; ++j) {
            next = preload_array[j];
            if (NULL == next) {
                continue;
            }
            if (descr->extent == next->extent) {
                /* same extent, consolidate */
                if (!pg_cache_try_reserve_pages(ctx, 1)) {
                    failed_to_reserve = 1;
                    break;
                }
                cmd.read_extent.page_cache_descr[k++] = next;
                /* don't use this page again */
                preload_array[j] = NULL;
            }
        }
        cmd.read_extent.page_count = k;
        rrdeng_enq_cmd(&ctx->worker_config, &cmd);
    }
    if (failed_to_reserve) {
        debug(D_RRDENGINE, "%s: Failed to reserve enough memory, canceling I/O.", __func__);
        for (i = 0 ; i < count ; ++i) {
            descr = preload_array[i];
            if (NULL == descr) {
                continue;
            }
            pg_cache_put(descr);
        }
    }
    if (!count) {
        /* no such page */
        debug(D_RRDENGINE, "%s: No page was eligible to attempt preload.", __func__);
    }
    return page_index;
}
Exemplo n.º 8
0
int ugh_client_send(ugh_client_t *c, int status)
{
#if 0
	if (0 == c->content_type.size)
	{
		c->content_type.size = sizeof("text/plain") - 1;
		c->content_type.data = "text/plain";
	}
#endif

	size_t i;

	for (i = 0; i < ugh_module_handles_size; ++i)
	{
		c->bufs_sumlen += c->bufs[i].size;
	}

	c->buf_send.data = (char *) aux_pool_nalloc(c->pool, UGH_HEADER_BUF);
	c->buf_send.size = snprintf(c->buf_send.data, UGH_HEADER_BUF,
		"HTTP/1.1 %s"              CRLF
		"Server: ugh/"UGH_VERSION  CRLF
		"Content-Length: %"PRIuMAX CRLF
		"Connection: close"        CRLF
		/* "Content-Type: %.*s"       CRLF */
		, ugh_status_header[status]
		, (uintmax_t) c->bufs_sumlen
		/* , (int) c->content_type.size, c->content_type.data */
	);

	void **vptr;
	Word_t idx = 0;

	for (vptr = JudyLFirst(c->headers_out_hash, &idx, PJE0); vptr; vptr = JudyLNext(c->headers_out_hash, &idx, PJE0))
	{
		ugh_header_t *h = *vptr;

		c->buf_send.size += snprintf(c->buf_send.data + c->buf_send.size, UGH_HEADER_BUF - c->buf_send.size,
			"%.*s: %.*s" CRLF, (int) h->key.size, h->key.data, (int) h->value.size, h->value.data);
	}

#if 0
	if (0 != c->location.size)
	{
		c->buf_send.size += snprintf(c->buf_send.data + c->buf_send.size, UGH_HEADER_BUF - c->buf_send.size,
			"Location: %.*s" CRLF, (int) c->location.size, c->location.data);
	}
#endif

	int rc;
	idx = 0;

	for (rc = Judy1First(c->cookies_out_hash, &idx, PJE0); rc; rc = Judy1Next(c->cookies_out_hash, &idx, PJE0))
	{
		strp cookie = (strp) idx;

		c->buf_send.size += snprintf(c->buf_send.data + c->buf_send.size, UGH_HEADER_BUF - c->buf_send.size,
			"Set-Cookie: %.*s" CRLF, (int) cookie->size, cookie->data);
	}

	c->buf_send.size += snprintf(c->buf_send.data + c->buf_send.size, UGH_HEADER_BUF - c->buf_send.size, CRLF);

	log_notice("access %s:%u '%.*s%s%.*s' %.*s %"PRIuMAX, inet_ntoa(c->addr.sin_addr), ntohs(c->addr.sin_port), (int) c->uri.size, c->uri.data,
		c->args.size ? "?" : "", (int) c->args.size, c->args.data, 3, ugh_status_header[status],
		(uintmax_t) c->bufs_sumlen);

	ev_io_start(loop, &c->wev_send);

	return 0;
}