Example #1
0
void http_response(struct data_node *p_node, int code)
{
	if (p_node->send.get_size > 0){
		return;
	}
	switch (code) {
		case 200:
			cache_add(&p_node->send,
					HTTP_RESP_INFO[p_node->http_info.hs.should_keep_alive],
					strlen(HTTP_RESP_INFO[p_node->http_info.hs.should_keep_alive]));
			break;
		case 400:
			cache_add(&p_node->send,
					HTTP_RESP_INFO[ 2 ],
					strlen(HTTP_RESP_INFO[ 2 ]));
			break;
		case 413:
			cache_add(&p_node->send,
					HTTP_RESP_INFO[ 3 ],
					strlen(HTTP_RESP_INFO[ 3 ]));
			break;
		case 500:
			cache_add(&p_node->send,
					HTTP_RESP_INFO[ 4 ],
					strlen(HTTP_RESP_INFO[ 4 ]));
			break;
		default:
			cache_add(&p_node->send,
					HTTP_RESP_INFO[ 5 ],
					strlen(HTTP_RESP_INFO[ 5 ]));
			break;
	}
}
Example #2
0
void a_mapcache_add ( GdkPixbuf *pixbuf, mapcache_extra_t extra, gint x, gint y, gint z, guint16 type, gint zoom, guint8 alpha, gdouble xshrinkfactor, gdouble yshrinkfactor, const gchar* name )
{
  guint nn = name ? g_str_hash ( name ) : 0;
  gchar *key = g_strdup_printf ( HASHKEY_FORMAT_STRING, type, x, y, z, zoom, nn, alpha, xshrinkfactor, yshrinkfactor );

  g_mutex_lock(mc_mutex);
  cache_add(key, pixbuf, extra);

  // TODO: that should be done on preference change only...
  max_cache_size = a_preferences_get(VIKING_PREFERENCES_NAMESPACE "mapcache_size")->u * 1024 * 1024;

  if ( cache_size > max_cache_size ) {
    if ( queue_tail ) {
      gchar *oldkey = list_shift_add_entry ( key );
      cache_remove(oldkey);

      while ( cache_size > max_cache_size &&
             (queue_tail->next != queue_tail) ) { /* make sure there's more than one thing to delete */
        oldkey = list_shift ();
        cache_remove(oldkey);
      }
    }
    /* chop off 'start' etc */
  } else {
    list_add_entry ( key );
    /* business as usual */
  }
  g_mutex_unlock(mc_mutex);

  static int tmp = 0;
  if ( (++tmp == 100 )) { g_debug("DEBUG: cache count=%d size=%u list count=%d\n", g_hash_table_size(cache), cache_size, queue_count ); tmp=0; }
}
Example #3
0
static struct submodule *lookup_or_create_by_name(struct submodule_cache *cache,
		const unsigned char *gitmodules_sha1, const char *name)
{
	struct submodule *submodule;
	struct strbuf name_buf = STRBUF_INIT;

	submodule = cache_lookup_name(cache, gitmodules_sha1, name);
	if (submodule)
		return submodule;

	submodule = xmalloc(sizeof(*submodule));

	strbuf_addstr(&name_buf, name);
	submodule->name = strbuf_detach(&name_buf, NULL);

	submodule->path = NULL;
	submodule->url = NULL;
	submodule->update_strategy.type = SM_UPDATE_UNSPECIFIED;
	submodule->update_strategy.command = NULL;
	submodule->fetch_recurse = RECURSE_SUBMODULES_NONE;
	submodule->ignore = NULL;
	submodule->branch = NULL;
	submodule->recommend_shallow = -1;

	hashcpy(submodule->gitmodules_sha1, gitmodules_sha1);

	cache_add(cache, submodule);

	return submodule;
}
Example #4
0
void a_mapcache_add ( GdkPixbuf *pixbuf, gint x, gint y, gint z, guint8 type, guint zoom, guint8 alpha, gdouble xshrinkfactor, gdouble yshrinkfactor )
{
  gchar *key = g_strdup_printf ( HASHKEY_FORMAT_STRING, x, y, z, type, zoom, alpha, xshrinkfactor, yshrinkfactor );
  static int tmp = 0;

  g_mutex_lock(mc_mutex);
  cache_add(key, pixbuf);

  // TODO: that should be done on preference change only...
  max_queue_size = a_preferences_get(VIKING_PREFERENCES_NAMESPACE "mapcache_size")->u * 1024 * 1024;

  if ( queue_size > max_queue_size ) {
    gchar *oldkey = list_shift_add_entry ( key );
    cache_remove(oldkey);

    while ( queue_size > max_queue_size &&
        (queue_tail->next != queue_tail) ) { /* make sure there's more than one thing to delete */
      oldkey = list_shift ();
      cache_remove(oldkey);
    }

    /* chop off 'start' etc */
  } else {
    list_add_entry ( key );
    /* business as usual */
  }
  g_mutex_unlock(mc_mutex);

  if ( (++tmp == 100 ))  { g_print("DEBUG: queue count=%d size=%u\n", queue_count, queue_size ); tmp=0; }
}
Example #5
0
int interrelate(int serverfd, int clientfd, char *buf, int idling
#ifdef PROXY_CACHE
		,char *objectbuf, struct status_line *status
#endif
		) {
	int count = 0;
	int nfds = (serverfd > clientfd ? serverfd : clientfd) + 1;
	int flag;
	fd_set rlist, xlist;
	FD_ZERO(&rlist);
	FD_ZERO(&xlist);

#ifdef PROXY_CACHE
	int objectlen = 0;
#endif

	while (1) {
		count++;

		FD_SET(clientfd, &rlist);
		FD_SET(serverfd, &rlist);
		FD_SET(clientfd, &xlist);
		FD_SET(serverfd, &xlist);

		struct timeval timeout = {2L, 0L};
		if ((flag = select(nfds, &rlist, NULL, &xlist, &timeout)) < 0)
			return flag;
		if (flag) {
			if (FD_ISSET(serverfd, &xlist) || FD_ISSET(clientfd, &xlist))
				break;
			if (FD_ISSET(serverfd, &rlist) &&
					((flag = transmit(serverfd, clientfd,
									  buf, &count
#ifdef PROXY_CACHE
									  ,objectbuf, &objectlen
#endif
									  )) < 0))
				return flag;
			if (flag == 0)
				break;
			if (FD_ISSET(clientfd, &rlist) &&
					((flag = transmit(clientfd, serverfd,
									  buf, &count
#ifdef PROXY_CACHE
									  ,NULL, NULL
#endif
									  )) < 0))
				return flag;
			if (flag == 0)
				break;
		}
		if (count >= idling)
			break;
	}
#ifdef PROXY_CACHE
	if (objectlen > 0 && cacheable(status))
		cache_add(status->line, objectbuf, objectlen);
#endif
	return 0;
}
Example #6
0
queue_file* queue_manager::open_file(const char* filePath, bool no_cache /* = true */)
{
	string home, queueName, queueSub, partName, extName;
	if (queue_manager::parse_filePath(filePath, &home, &queueName, &queueSub,
		&partName, &extName) == false)
	{
		logger_error("filePath(%s) invalid", filePath);
		return NULL;
	}

	queue_file* fp;

	// 如果该文件存在于内存中则直接返回之
	fp = cache_find(partName);
	if (fp != NULL)
	{
		if (no_cache)
		{
			logger_warn("file: %s locked", filePath);
			return NULL;
		}
		return fp;
	}

	// 从磁盘打开已经存在的队列文件
	fp = NEW queue_file;
	if (fp->open(home.c_str(), queueName.c_str(), queueSub.c_str(),
		partName.c_str(), extName.c_str()) == false)
	{
		delete fp;
		return NULL;
	}
	cache_add(fp);
	return fp;
}
Example #7
0
struct cache_object *cache_update_force(struct cache *c, void *ptr)
{
	struct cache_object *obj;
	int id;

	obj = cache_find(c, ptr, &id);
	if (obj) {
		if (obj->status != C_OBJ_DEAD) {
			cache_update(c, obj, id, ptr);
			return obj;
		} else {
			cache_del(c, obj);
			cache_object_free(obj);
		}
	}
	obj = cache_object_new(c, ptr);
	if (obj == NULL)
		return NULL;

	if (cache_add(c, obj, id) == -1) {
		cache_object_free(obj);
		return NULL;
	}

	return obj;
}
Example #8
0
/* write size bytes from buffer into cache block */
void
cache_write (block_sector_t bid, const void *buffer, int offset, int size)
{
	ASSERT(offset < BLOCK_SECTOR_SIZE);
	ASSERT(offset + size <= BLOCK_SECTOR_SIZE);

	/* find cache block */
	int cache_id = cache_find_block(bid, CACHE_WRITE);
        
	//if(((unsigned) buffer) == 134556864) printf("CACHE a, bid:%u\n", bid);

	/* if cache block not present, load */
	if(cache_id == -1)
	{
		cache_id = cache_add(bid);
		
		/* increment number of reader manually */
		cache[cache_id]->writer++;
	}
	
	//if(((unsigned) buffer) == 134556864) printf("CACHE b\n");
	
	ASSERT(cache_id != -1);

	/* copy buffer content into cache */
	memcpy (cache[cache_id]->kpage + offset, buffer, size);
	cache[cache_id]->accessed = true;
	cache[cache_id]->dirty = true;
	cache[cache_id]->writer--;

	if(CACHE_DEBUG) printf("wrote cache %u: @offset %i from buffer %x with size %i\n", (unsigned int) cache_id, offset, (unsigned int) buffer, size);
}
Example #9
0
/* read size bytes from block bid beginning at offset into buffer */
void
cache_read (block_sector_t bid, void * buffer, int offset, int size)
{
	ASSERT(offset < BLOCK_SECTOR_SIZE);

	int cache_id = cache_find_block(bid, CACHE_READ);
        
	/* if not found load into cache */
	if(cache_id == -1)
	{
		/* copy block from disk */
		cache_id = cache_add(bid);
		ASSERT(cache_id != -1);

		/* increment number of reader manually */
		cache[cache_id]->reader++;

		/* add read-ahead block */
		//TODO cache_readahead(bid + 1);
	}

	/* copy the corresponding section into buffer */
	memcpy (buffer, cache[cache_id]->kpage + offset, size);

	/* update cache flags */
	cache[cache_id]->accessed = true;
	cache[cache_id]->reader--;

	if(CACHE_DEBUG)  printf("read cache %u\n", (unsigned int) cache_id);

}
Example #10
0
static int read_map(const char *root, time_t now, struct lookup_context *ctxt)
{
	char key[KEY_MAX_LEN + 1];
	char mapent[MAPENT_MAX_LEN + 1];
	char *mapname;
	FILE *f;
	int  entry;
	time_t age = now ? now : time(NULL);

	mapname = alloca(strlen(ctxt->mapname) + 6);
	sprintf(mapname, "file:%s", ctxt->mapname);

	f = fopen(ctxt->mapname, "r");
	if (!f) {
		error(MODPREFIX "could not open map file %s", ctxt->mapname);
		return 0;
	}

	while(1) {
		entry = read_one(f, key, mapent);
		if (entry)
			cache_add(root, key, mapent, age);

		if (feof(f))
			break;
	}

	fclose(f);

	/* Clean stale entries from the cache */
	cache_clean(root, age);

	return 1;
}
Example #11
0
int mime_types_add(char *ext, char *mime, cache *c) {
	char *value = malloc(strlen(mime)+1);
	memcpy (value, mime, strlen(mime)+1);

	cache_add (c, ext, value);
	
	return 0;
}
Example #12
0
/* load read-ahead block */
void
cache_readahead (block_sector_t bid)
{
	/* if block is not in cache, load it */
	if (cache_find_block(bid,-1) == -1) {
		cache_add (bid);
	}
}
Example #13
0
int main(int argc, char *argv[]) {
	struct cache_t *cache;

	cache = cache_new();
	if (!cache) {
		fprintf(stderr, "unable to create cache: %s\n", strerror(errno));
		return 1;
	}

	cache_add(cache, "name", "neurodrone");
	cache_add(cache, "place", "US");
	cache_add(cache, "name1", "neurodrone_");
	fprintf(stdout, "deleted value: %s\n", cache_remove(cache, "name"));

	cache_free(cache);
	return 0;
}
Example #14
0
static int
cache_scan(Eet_File *ef,
           Eina_Inarray *stack, const char *path, const char *base_id,
           int priority, int recurse, int *changed)
{
    char *file_id = NULL;
    char id[PATH_MAX];
    Eina_Iterator *it;
    Eina_File_Direct_Info *info;
    struct stat st;
    int ret = 1;

    if (!ecore_file_is_dir(path)) return 1;
    if (stat(path, &st) == -1) return 1;
    if (eina_inarray_search(stack, &st, stat_cmp) >= 0) return 1;
    eina_inarray_push(stack, &st);

    it = eina_file_stat_ls(path);
    if (!it) goto end;
    id[0] = '\0';
    EINA_ITERATOR_FOREACH(it, info)
    {
        const char *fname = info->path + info->name_start;

        if (info->path[info->name_start] == '.') continue;
        if (base_id)
        {
            if (*base_id) snprintf(id, sizeof(id), "%s-%s", base_id, fname);
            else
            {
                strncpy(id, fname, PATH_MAX);
                id[PATH_MAX - 1] = 0;
            }
            file_id = id;
        }

        if (((info->type == EINA_FILE_LNK) && (ecore_file_is_dir(info->path))) ||
            (info->type == EINA_FILE_DIR))
        {
           if (recurse)
             {
                ret = cache_scan(ef, stack, info->path, file_id, priority, recurse, changed);
                if (!ret) break;
             }
        }
        else
        {
           ret = cache_add(ef, info->path, file_id, priority, changed);
           if (!ret) break;
        }
    }
    eina_iterator_free(it);
end:
    eina_inarray_pop(stack);
    return ret;
}
Example #15
0
static void cache_add_cache(struct peer_cache *dst, const struct peer_cache *add)
{
  int i, meta_size;
  const uint8_t *meta;

  meta = get_metadata(add, &meta_size);
  for (i = 0; nodeid(add, i); i++) {
    cache_add(dst,  nodeid(add, i), meta + (meta_size * i), meta_size);
  }
}
Example #16
0
queue_file* queue_manager::scan_next()
{
	if (m_scanDir == NULL)
		logger_fatal("call scan_open first!");

	queue_file* fp = NULL;
	string filePath;

	while (1)
	{
		// 扫描下一个磁盘文件
		const char* fileName = acl_scan_dir_next_file(m_scanDir);
		if (fileName == NULL)
			return NULL;

		string partName, extName;

		if (parse_fileName(fileName, &partName, &extName) == false)
			continue;
		// 如果该队列文件已经存在于内存队列中则跳过
		if (busy(partName.c_str()))
			continue;

		const char* path = acl_scan_dir_path(m_scanDir);
		if (path == NULL)
		{
			logger_error("acl_scan_dir_path error for %s", fileName);
			continue;
		}

		filePath.clear();
		filePath << path << PATH_SEP << fileName;
		fp = NEW queue_file;
		// 从磁盘打开已经存在的队列文件
		if (fp->open(filePath.c_str()) == false)
		{
			logger_error("open %s error(%s)", filePath.c_str(),
				acl_last_serror());
			delete fp;
			fp = NULL;
			continue;
		}
		if (cache_add(fp) == false)
		{
			logger_error("file(%s) locked", filePath.c_str());
			delete fp;
			fp = NULL;
			continue;
		}
		else
			break;
	}

	return fp;
}
Example #17
0
static int cyclon_add_neighbour(struct peersampler_context *context, struct nodeID *neighbour, const void *metadata, int metadata_size)
{
  if (!context->flying_cache) {
    context->flying_cache = rand_cache(context->local_cache, context->sent_entries - 1);
  }
  if (cache_add(context->local_cache, neighbour, metadata, metadata_size) < 0) {
    return -1;
  }

  return cyclon_query(context->pc, context->flying_cache, neighbour);
}
Example #18
0
queue_file* queue_manager::create_file(const char* extName)
{
	queue_file* fp = NEW queue_file;

	if (fp->create(m_home.c_str(), m_queueName.c_str(),
		extName, sub_width_) == false)
	{
		delete fp;
		return NULL;
	}

	if (cache_add(fp) == false)
		logger_fatal("%s already exist in table", fp->key());
	return fp;
}
Example #19
0
static int
cache_scan(const char *path, const char *base_id, int priority, int recurse, int *changed)
{
    char *file_id = NULL;
    char id[PATH_MAX];
    char buf[PATH_MAX];
    Eina_Iterator *it;
    Eina_File_Direct_Info *info;

    if (!ecore_file_is_dir(path)) return 1;

    it = eina_file_direct_ls(path);
    if (!it) return 1;

    id[0] = '\0';
    EINA_ITERATOR_FOREACH(it, info)
    {
        const char *fname;
       
        fname = info->path + info->name_start;
        if (base_id)
        {
            if (*base_id)
                snprintf(id, sizeof(id), "%s-%s", base_id, fname);
            else
                strcpy(id, fname);
            file_id = id;
        }

        snprintf(buf, sizeof(buf), "%s/%s", path, fname);
        if (ecore_file_is_dir(buf))
        {
            if (recurse)
                cache_scan(buf, file_id, priority, recurse, changed);
        }
        else
        {
            if (!cache_add(buf, file_id, priority, changed))
            {
                eina_iterator_free(it);
                return 0;
            }
        }
    }
    eina_iterator_free(it);
    return 1;
}
Example #20
0
static int ga_extcopy(GpuArray *dst, const GpuArray *src) {
  struct extcopy_args a, *aa;
  gpucontext *ctx = gpudata_context(dst->data);
  GpuElemwise *k = NULL;
  void *args[2];

  if (ctx != gpudata_context(src->data))
    return GA_INVALID_ERROR;

  a.itype = src->typecode;
  a.otype = dst->typecode;

  if (ctx->extcopy_cache != NULL)
    k = cache_get(ctx->extcopy_cache, &a);
  if (k == NULL) {
    gpuelemwise_arg gargs[2];
    gargs[0].name = "src";
    gargs[0].typecode = src->typecode;
    gargs[0].flags = GE_READ;
    gargs[1].name = "dst";
    gargs[1].typecode = dst->typecode;
    gargs[1].flags = GE_WRITE;
    k = GpuElemwise_new(ctx, "", "dst = src", 2, gargs, 0, 0);
    if (k == NULL)
      return GA_MISC_ERROR;
    aa = memdup(&a, sizeof(a));
    if (aa == NULL) {
      GpuElemwise_free(k);
      return GA_MEMORY_ERROR;
    }
    if (ctx->extcopy_cache == NULL)
      ctx->extcopy_cache = cache_twoq(4, 8, 8, 2, extcopy_eq, extcopy_hash,
                                      extcopy_free,
                                      (cache_freev_fn)GpuElemwise_free,
                                      ctx->err);
    if (ctx->extcopy_cache == NULL)
      return GA_MISC_ERROR;
    if (cache_add(ctx->extcopy_cache, aa, k) != 0)
      return GA_MISC_ERROR;
  }
  args[0] = (void *)src;
  args[1] = (void *)dst;
  return GpuElemwise_call(k, args, GE_BROADCAST);
}
Example #21
0
int app_lua_add_send_data(lua_State *L)
{
	size_t len = 0;
	int fd = lua_tointeger(L, 1);
	const char *data = lua_tolstring(L, 2, &len);

	if (data == NULL) {
		lua_pushboolean( L, 0 );
	}else{
		struct data_node *p_node = get_pool_addr( fd );
		int ok = cache_add(&p_node->send, data, len);
		if (ok == 0){
			lua_pushboolean( L, 1 );
		}else{
			lua_pushboolean( L, 0 );
		}
	}
	return 1;
}
Example #22
0
int api_hgetall(void *user, void *task)
{
	WORKER_PTHREAD *p_worker = (WORKER_PTHREAD *)user;
	struct smart_task_node *p_task = (struct smart_task_node *)task;
	struct data_node *p_node = get_pool_addr( p_task->sfd );

	char *p_buf = p_node->recv.buf_addr;
	struct redis_status *p_status = &p_node->redis_info.rs;

	if ( !strncmp(p_buf + p_status->key_offset[0], "BEELINE", 7) ){
		return entry_cmd_rlbr( p_node, 0 );
	}
	/*
	if ( !strncmp(p_buf + p_status->key_offset[0], "SCALLOP", 7) ){
		return entry_cmd_rlbr( p_node, 0 );
	}
	*/

	cache_add( &p_node->send, OPT_OK, strlen(OPT_OK) );
	return 0;
}
Example #23
0
int api_hmget(void *user, void *task)
{
	WORKER_PTHREAD *p_worker = (WORKER_PTHREAD *)user;
	struct smart_task_node *p_task = (struct smart_task_node *)task;
	struct data_node *p_node = get_pool_addr( p_task->sfd );

	char *p_buf = p_node->recv.buf_addr;
	struct redis_status *p_rst = &p_node->redis_info.rs;

	//printf("%d %s\n", p_rst->flen_array[0], p_buf + p_rst->fld_offset[0]);
	if ( !strncmp(p_buf + p_rst->fld_offset[0], "ERBR", MAX(p_rst->flen_array[0], 4)) ){
		return entry_cmd_erbr( p_node,
				strtoull(p_buf + p_rst->key_offset[0], NULL, 10) );
	}
	if ( !strncmp(p_buf + p_rst->fld_offset[0], "IRBR", MAX(p_rst->flen_array[0], 4)) ){
		return entry_cmd_irbr( p_node,
				strtoull(p_buf + p_rst->key_offset[0], NULL, 10) );
	}

	if ( !strncmp(p_buf + p_rst->fld_offset[0], "EROF", MAX(p_rst->flen_array[0], 4)) ){
		return entry_cmd_erof( p_node,
				strtoull(p_buf + p_rst->key_offset[0], NULL, 10) );
	}
	if ( !strncmp(p_buf + p_rst->fld_offset[0], "IROF", MAX(p_rst->flen_array[0], 4)) ){
		return entry_cmd_irof( p_node,
				strtoull(p_buf + p_rst->key_offset[0], NULL, 10) );
	}

	if ( !strncmp(p_buf + p_rst->fld_offset[0], "ENBR", MAX(p_rst->flen_array[0], 4)) ){
		return entry_cmd_enbr( p_node,
				strtoull(p_buf + p_rst->key_offset[0], NULL, 10) );
	}
	if ( !strncmp(p_buf + p_rst->fld_offset[0], "FNBR", MAX(p_rst->flen_array[0], 4)) ){
		return entry_cmd_fnbr( p_node,
				strtoull(p_buf + p_rst->key_offset[0], NULL, 10) );
	}

	cache_add( &p_node->send, OPT_MULTI_BULK_FALSE, strlen(OPT_MULTI_BULK_FALSE) );
	return 0;
}
static void external_cache_new(struct nf_conntrack *ct)
{
	struct cache_object *obj;
	int id;

	obj = cache_find(external, ct, &id);
	if (obj == NULL) {
retry:
		obj = cache_object_new(external, ct);
		if (obj == NULL)
			return;

		if (cache_add(external, obj, id) == -1) {
			cache_object_free(obj);
			return;
		}
	} else {
		cache_del(external, obj);
		cache_object_free(obj);
		goto retry;
	}
}
Example #25
0
	/*}}}*/
};
int
xchar_length (xchar_t ch) /*{{{*/
{
	return utf8_length_tab[ch];
}/*}}}*/
int
xchar_strict_length (xchar_t ch) /*{{{*/
{
	return utf8_strict_length_tab[ch];
}/*}}}*/
int
xchar_valid_position (const xchar_t *s, int length) /*{{{*/
{
# define	VALID(ccc)	(((ccc) & 0xc0) == 0x80)
	int	len, n;
	
	if (((len = xchar_strict_length (*s)) > 0) && (length >= len))
		for (n = len; n > 1; ) {
			--n;
			if (! VALID (*(s + n))) {
				len = -1;
				break;
			}
		}
	else
		len = -1;
	return len;
# undef		VALID	
}/*}}}*/
bool_t
xchar_valid (const xchar_t *s, int length) /*{{{*/
{
	int	n;
	
	while (length > 0)
		if ((n = xchar_valid_position (s, length)) > 0) {
			s += n;
			length -= n;
		} else
			break;
	return length == 0 ? true : false;
}/*}}}*/
const char *
xchar_to_char (const xchar_t *s) /*{{{*/
{
	return (const char *) s;
}/*}}}*/
const xchar_t *
char_2_xchar (const char *s) /*{{{*/
{
	return (const xchar_t *) s;
}/*}}}*/
const char *
byte_to_char (const byte_t *b) /*{{{*/
{
	return (const char *) b;
}/*}}}*/
int
xstrlen (const xchar_t *s) /*{{{*/
{
	int	len, clen;
	
	for (len = 0; *s; ++len) {
		clen = xchar_length (*s);
		while ((clen-- > 0) && *s)
			++s;
	}
	return len;
}/*}}}*/
int
xstrcmp (const xchar_t *s1, const char *s2) /*{{{*/
{
	return strcmp (xchar_to_char (s1), s2);
}/*}}}*/
int
xstrncmp (const xchar_t *s1, const char *s2, size_t n) /*{{{*/
{
	return strncmp (xchar_to_char (s1), s2, n);
}/*}}}*/
bool_t
xmlbuf_equal (xmlbuf_t *b1, xmlbuf_t *b2) /*{{{*/
{
	if ((! b1) && (! b2))
		return true;
	if (b1 && b2 && (b1 -> length == b2 -> length) &&
	    ((! b1 -> length) || (! memcmp (b1 -> buffer, b2 -> buffer, b1 -> length))))
		return true;
	return false;
}/*}}}*/
char *
xmlbuf_to_string (xmlbuf_t *b) /*{{{*/
{
	return buffer_copystring ((buffer_t *) b);
}/*}}}*/
long
xmlbuf_to_long (xmlbuf_t *b) /*{{{*/
{
	const char	*s = b ? buffer_string (b) : NULL;

	return s ? strtol (s, NULL, 0) : -1;
}/*}}}*/

static inline unsigned long
mkcp (const xchar_t *s, int *len) /*{{{*/
{
	unsigned long	cp;
	int		n;
	
	*len = xchar_length (*s);
	for (n = 0, cp = 0; n < *len; ++n) {
		cp <<= 8;
		cp |= s[n];
	}
	return cp;
}/*}}}*/
static inline const utfmap_t *
mapfind (const xchar_t *s, int *len, const utfmap_t *map, int msize) /*{{{*/
{
	unsigned long	cp;
	int		low, high, pos;
	int		dummy;

	cp = mkcp (s, len ? len : & dummy);
	for (low = 0, high = msize; low < high; ) {
		pos = (low + high) >> 1;
		if (map[pos].cp == cp)
			return & map[pos];
		else if (map[pos].cp < cp)
			low = pos + 1;
		else
			high = pos;
	}
	return NULL;
}/*}}}*/
static inline bool_t
isword (const xchar_t *s) /*{{{*/
{
	unsigned long	cp;
	int		len;
	
	cp = mkcp (s, & len);
	if (len == 1)
		return isalnum (s[0]) ? true : false;
	else {
		int	low, high, pos;
		
		for (low = 0, high = is_word_length; low < high;) {
			pos = (low + high) >> 1;
			if (is_word[pos] == cp)
				return true;
			if (is_word[pos] < cp)
				low = pos + 1;
			else
				high = pos;
		}
	}
	return false;
}/*}}}*/
static inline const xchar_t *
mapper (const utfmap_t *map, int msize, const xchar_t *s, int *slen, int *olen) /*{{{*/
{
	const utfmap_t	*m = mapfind (s, slen, map, msize);
	
	if (m) {
		if (olen)
			*olen = m -> dlen;
		return m -> dst;
	}
	return NULL;
}/*}}}*/
const xchar_t *
xtolower (const xchar_t *s, int *slen, int *olen) /*{{{*/
{
	return mapper (utflower, utflower_length, s, slen, olen);
}/*}}}*/
const xchar_t *
xtoupper (const xchar_t *s, int *slen, int *olen) /*{{{*/
{
	return mapper (utfupper, utfupper_length, s, slen, olen);
}/*}}}*/
const xchar_t *
xtotitle (const xchar_t *s, int *slen, int *olen) /*{{{*/
{
	return mapper (utftitle, utftitle_length, s, slen, olen);
}/*}}}*/
static xchar_t *
mappers (const xchar_t *s, int len, int *olen,
	 const xchar_t *(*first) (const xchar_t *, int *, int *),
	 const xchar_t *(*next) (const xchar_t *, int *, int *)) /*{{{*/
{
	xchar_t	*rc;
	int	rsize, ruse;
	
	rsize = len + 32;
	if (rc = (xchar_t *) malloc (rsize + 1)) {
		const xchar_t	*rplc;
		int		slen, rlen;
		bool_t		isfirst = true;
		bool_t		isletter;
		
		ruse = 0;
		while (len > 0) {
			if (next) {
				isletter = isword (s);
				if (isfirst || (! isletter)) {
					if (isletter) {
						rplc = (*first) (s, & slen, & rlen);
						isfirst = false;
					} else {
						rplc = NULL;
						mkcp (s, & slen);
						isfirst = true;
					}
				} else
					rplc = (*next) (s, & slen, & rlen);
			} else {
				rplc = (*first) (s, & slen, & rlen);
			}
			if (! rplc) {
				rplc = s;
				rlen = slen;
			}
			if (ruse + rlen > rsize) {
				rsize += 128;
				if (! (rc = realloc (rc, rsize + 1)))
					break;
			}
			while (rlen-- > 0)
				rc[ruse++] = *rplc++;
			len -= slen;
			s += slen;
		}
		if (rc) {
			rc[ruse] = 0;
			if (olen)
				*olen = ruse;
		}
	}
	return rc;
}/*}}}*/
xchar_t *
xlowern (const xchar_t *s, int len, int *olen) /*{{{*/
{
	return mappers (s, len, olen, xtolower, NULL);
}/*}}}*/
xchar_t *
xlower (const xchar_t *s, int *olen) /*{{{*/
{
	return mappers (s, strlen ((const char *) s), olen, xtolower, NULL);
}/*}}}*/
xchar_t *
xuppern (const xchar_t *s, int len, int *olen) /*{{{*/
{
	return mappers (s, len, olen, xtoupper, NULL);
}/*}}}*/
xchar_t *
xupper (const xchar_t *s, int *olen) /*{{{*/
{
	return mappers (s, strlen ((const char *) s), olen, xtoupper, NULL);
}/*}}}*/
xchar_t *
xtitlen (const xchar_t *s, int len, int *olen) /*{{{*/
{
	return mappers (s, len, olen, xtotitle, xtolower);
}/*}}}*/
xchar_t *
xtitle (const xchar_t *s, int *olen) /*{{{*/
{
	return mappers (s, strlen ((const char *) s), olen, xtotitle, xtolower);
}/*}}}*/

xconv_t *
xconv_free (xconv_t *xc) /*{{{*/
{
	if (xc) {
		if (xc -> lower)
			cache_free (xc -> lower);
		if (xc -> upper)
			cache_free (xc -> upper);
		if (xc -> title)
			cache_free (xc -> title);
		free (xc);
	}
	return NULL;
}/*}}}*/
xconv_t *
xconv_alloc (int cache_size) /*{{{*/
{
	xconv_t	*xc;
	
	if (xc = (xconv_t *) malloc (sizeof (xconv_t))) {
		xc -> csize = cache_size;
		xc -> lower = cache_alloc (xc -> csize);
		xc -> upper = cache_alloc (xc -> csize);
		xc -> title = cache_alloc (xc -> csize);
		if (! (xc -> lower && xc -> upper && xc -> title))
			xc = xconv_free (xc);
	}
	return xc;
}/*}}}*/
static inline const xchar_t *
converter (cache_t *c, xchar_t *(*func) (const xchar_t *, int, int *), const xchar_t *s, int slen, int *olen) /*{{{*/
{
	centry_t	*ce = cache_find (c, s, slen);
	
	if (! ce) {
		xchar_t	*rplc;
		int	rlen;
		
		if (rplc = (*func) (s, slen, & rlen)) {
			ce = cache_add (c, s, slen, rplc, rlen);
			free (rplc);
		}
	}
	if (ce) {
		*olen = ce -> dlen;
		return ce -> data;
	} else {
		*olen = slen;
		return s;
	}
}/*}}}*/
Example #26
0
static int cuda_extcopy(gpudata *input, size_t ioff, gpudata *output,
                        size_t ooff, int intype, int outtype,
                        unsigned int a_nd, const size_t *a_dims,
                        const ssize_t *a_str, unsigned int b_nd,
                        const size_t *b_dims, const ssize_t *b_str) {
  cuda_context *ctx = input->ctx;
  void *args[2];
  int res = GA_SYS_ERROR;
  unsigned int i;
  size_t nEls = 1, ls, gs;
  gpukernel *k;
  extcopy_args a, *aa;

  ASSERT_BUF(input);
  ASSERT_BUF(output);
  if (input->ctx != output->ctx)
    return GA_INVALID_ERROR;

  for (i = 0; i < a_nd; i++) {
    nEls *= a_dims[i];
  }
  if (nEls == 0) return GA_NO_ERROR;

  a.ind = a_nd;
  a.ond = b_nd;
  a.itype = intype;
  a.otype = outtype;
  a.ioff = ioff;
  a.ooff = ooff;
  a.idims = a_dims;
  a.odims = b_dims;
  a.istr = a_str;
  a.ostr = b_str;

  k = cache_get(ctx->extcopy_cache, &a);
  if (k == NULL) {
    res = gen_extcopy_kernel(&a, input->ctx, &k, nEls);
    if (res != GA_NO_ERROR)
      return res;

    /* Cache the kernel */
    aa = memdup(&a, sizeof(a));
    if (aa == NULL) goto done;
    aa->idims = memdup(a_dims, a_nd*sizeof(size_t));
    aa->odims = memdup(b_dims, b_nd*sizeof(size_t));
    aa->istr = memdup(a_str, a_nd*sizeof(ssize_t));
    aa->ostr = memdup(b_str, b_nd*sizeof(ssize_t));
    if (aa->idims == NULL || aa->odims == NULL ||
        aa->istr == NULL || aa->ostr == NULL) {
      extcopy_free(aa);
      goto done;
    }
    /* One ref is given to the cache, we manage the other */
    cuda_retainkernel(k);
    cache_add(ctx->extcopy_cache, aa, k);
  } else {
    /* This is our reference */
    cuda_retainkernel(k);
  }
done:

  /* Cheap kernel scheduling */
  res = cuda_property(NULL, NULL, k, GA_KERNEL_PROP_MAXLSIZE, &ls);
  if (res != GA_NO_ERROR) goto fail;

  gs = ((nEls-1) / ls) + 1;
  args[0] = input;
  args[1] = output;
  res = cuda_callkernel(k, 1, &ls, &gs, 0, args);

fail:
  /* We free our reference here */
  cuda_freekernel(k);
  return res;
}
Example #27
0
static gpukernel *cuda_newkernel(void *c, unsigned int count,
                                 const char **strings, const size_t *lengths,
                                 const char *fname, unsigned int argcount,
                                 const int *types, int flags, int *ret,
                                 char **err_str) {
    cuda_context *ctx = (cuda_context *)c;
    strb sb = STRB_STATIC_INIT;
    char *bin, *log = NULL;
    srckey k, *ak;
    binval *av;
    gpukernel *res;
    size_t bin_len = 0, log_len = 0;
    CUdevice dev;
    unsigned int i;
    int ptx_mode = 0;
    int binary_mode = 0;
    int major, minor;

    if (count == 0) FAIL(NULL, GA_VALUE_ERROR);

    if (flags & GA_USE_OPENCL)
      FAIL(NULL, GA_DEVSUP_ERROR);

    if (flags & GA_USE_BINARY) {
      // GA_USE_BINARY is exclusive
      if (flags & ~GA_USE_BINARY)
        FAIL(NULL, GA_INVALID_ERROR);
      // We need the length for binary data and there is only one blob.
      if (count != 1 || lengths == NULL || lengths[0] == 0)
        FAIL(NULL, GA_VALUE_ERROR);
    }

    cuda_enter(ctx);

    ctx->err = cuCtxGetDevice(&dev);
    if (ctx->err != CUDA_SUCCESS) {
      cuda_exit(ctx);
      FAIL(NULL, GA_IMPL_ERROR);
    }
    ctx->err = cuDeviceComputeCapability(&major, &minor, dev);
    if (ctx->err != CUDA_SUCCESS) {
      cuda_exit(ctx);
      FAIL(NULL, GA_IMPL_ERROR);
    }

    // GA_USE_CLUDA is done later
    // GA_USE_SMALL will always work
    if (flags & GA_USE_DOUBLE) {
      if (major < 1 || (major == 1 && minor < 3)) {
        cuda_exit(ctx);
        FAIL(NULL, GA_DEVSUP_ERROR);
      }
    }
    if (flags & GA_USE_COMPLEX) {
      // just for now since it is most likely broken
      cuda_exit(ctx);
      FAIL(NULL, GA_DEVSUP_ERROR);
    }
    // GA_USE_HALF should always work

    if (flags & GA_USE_PTX) {
      ptx_mode = 1;
    } else if (flags & GA_USE_BINARY) {
      binary_mode = 1;
    }

    if (binary_mode) {
      bin = memdup(strings[0], lengths[0]);
      bin_len = lengths[0];
      if (bin == NULL) {
        cuda_exit(ctx);
        FAIL(NULL, GA_MEMORY_ERROR);
      }
    } else {
      if (flags & GA_USE_CLUDA) {
        strb_appends(&sb, CUDA_PREAMBLE);
      }

      if (lengths == NULL) {
        for (i = 0; i < count; i++)
        strb_appends(&sb, strings[i]);
      } else {
        for (i = 0; i < count; i++) {
          if (lengths[i] == 0)
            strb_appends(&sb, strings[i]);
          else
            strb_appendn(&sb, strings[i], lengths[i]);
        }
      }

      strb_append0(&sb);

      if (strb_error(&sb)) {
        strb_clear(&sb);
        cuda_exit(ctx);
        return NULL;
      }

      if (ptx_mode) {
        bin = sb.s;
        bin_len = sb.l;
      } else {
        bin = NULL;
        if (compile_cache != NULL) {
          k.src = sb.s;
          k.len = sb.l;
          memcpy(k.arch, ctx->bin_id, BIN_ID_LEN);
          av = cache_get(compile_cache, &k);
          if (av != NULL) {
            bin = memdup(av->bin, av->len);
            bin_len = av->len;
          }
        }
        if (bin == NULL) {
          bin = call_compiler(sb.s, sb.l, ctx->bin_id, &bin_len,
                              &log, &log_len, ret);
        }
        if (bin == NULL) {
          if (err_str != NULL) {
            strb debug_msg = STRB_STATIC_INIT;

            // We're substituting debug_msg for a string with this first line:
            strb_appends(&debug_msg, "CUDA kernel build failure ::\n");

            /* Delete the final NUL */
            sb.l--;
            gpukernel_source_with_line_numbers(1, (const char **)&sb.s,
                                               &sb.l, &debug_msg);

            if (log != NULL) {
              strb_appends(&debug_msg, "\nCompiler log:\n");
              strb_appendn(&debug_msg, log, log_len);
              free(log);
            }
            *err_str = strb_cstr(&debug_msg);
            // *err_str will be free()d by the caller (see docs in kernel.h)
          }
          strb_clear(&sb);
          cuda_exit(ctx);
          return NULL;
        }
        if (compile_cache == NULL)
          compile_cache = cache_twoq(16, 16, 16, 8, src_eq, src_hash, src_free,
                                     bin_free);

        if (compile_cache != NULL) {
          ak = malloc(sizeof(*ak));
          av = malloc(sizeof(*av));
          if (ak == NULL || av == NULL) {
            free(ak);
            free(av);
            goto done;
          }
          ak->src = memdup(sb.s, sb.l);
          if (ak->src == NULL) {
            free(ak);
            free(av);
            goto done;
          }
          ak->len = sb.l;
          memmove(ak->arch, ctx->bin_id, BIN_ID_LEN);
          av->len = bin_len;
          av->bin = memdup(bin, bin_len);
          if (av->bin == NULL) {
            src_free(ak);
            free(av);
            goto done;
          }
          cache_add(compile_cache, ak, av);
        }
      done:
        strb_clear(&sb);
      }
    }

    res = calloc(1, sizeof(*res));
    if (res == NULL) {
      free(bin);
      cuda_exit(ctx);
      FAIL(NULL, GA_SYS_ERROR);
    }

    res->bin_sz = bin_len;
    res->bin = bin;

    res->refcnt = 1;
    res->argcount = argcount;
    res->types = calloc(argcount, sizeof(int));
    if (res->types == NULL) {
      _cuda_freekernel(res);
      cuda_exit(ctx);
      FAIL(NULL, GA_MEMORY_ERROR);
    }
    memcpy(res->types, types, argcount*sizeof(int));
    res->args = calloc(argcount, sizeof(void *));
    if (res->args == NULL) {
      _cuda_freekernel(res);
      cuda_exit(ctx);
      FAIL(NULL, GA_MEMORY_ERROR);
    }

    ctx->err = cuModuleLoadData(&res->m, bin);

    if (ctx->err != CUDA_SUCCESS) {
      _cuda_freekernel(res);
      cuda_exit(ctx);
      FAIL(NULL, GA_IMPL_ERROR);
    }

    ctx->err = cuModuleGetFunction(&res->k, res->m, fname);
    if (ctx->err != CUDA_SUCCESS) {
      _cuda_freekernel(res);
      cuda_exit(ctx);
      FAIL(NULL, GA_IMPL_ERROR);
    }

    res->ctx = ctx;
    ctx->refcnt++;
    cuda_exit(ctx);
    TAG_KER(res);
    return res;
}
Example #28
0
static void secure_beacon_recv(struct net_buf_simple *buf)
{
    u8_t *data, *net_id, *auth;
    struct bt_mesh_subnet *sub;
    u32_t iv_index;
    bool new_key, kr_change, iv_change;
    u8_t flags;

    if (buf->len < 21) {
        BT_ERR("Too short secure beacon (len %u)", buf->len);
        return;
    }

    sub = cache_check(buf->data);
    if (sub) {
        /* We've seen this beacon before - just update the stats */
        goto update_stats;
    }

    /* So we can add to the cache if auth matches */
    data = buf->data;

    flags = net_buf_simple_pull_u8(buf);
    net_id = buf->data;
    net_buf_simple_pull(buf, 8);
    iv_index = net_buf_simple_pull_be32(buf);
    auth = buf->data;

    BT_DBG("flags 0x%02x id %s iv_index 0x%08x",
           flags, bt_hex(net_id, 8), iv_index);

    sub = bt_mesh_subnet_find(net_id, flags, iv_index, auth, &new_key);
    if (!sub) {
        BT_DBG("No subnet that matched beacon");
        return;
    }

    if (sub->kr_phase == BT_MESH_KR_PHASE_2 && !new_key) {
        BT_WARN("Ignoring Phase 2 KR Update secured using old key");
        return;
    }

    cache_add(data, sub);

    /* If we have NetKey0 accept initiation only from it */
    if (bt_mesh_subnet_get(BT_MESH_KEY_PRIMARY) &&
        sub->net_idx != BT_MESH_KEY_PRIMARY) {
        BT_WARN("Ignoring secure beacon on non-primary subnet");
        goto update_stats;
    }

    BT_DBG("net_idx 0x%04x iv_index 0x%08x, current iv_index 0x%08x",
           sub->net_idx, iv_index, bt_mesh.iv_index);

    if (bt_mesh.ivu_initiator &&
        bt_mesh.iv_update == BT_MESH_IV_UPDATE(flags)) {
        bt_mesh_beacon_ivu_initiator(false);
    }

    iv_change = bt_mesh_net_iv_update(iv_index, BT_MESH_IV_UPDATE(flags));

    kr_change = bt_mesh_kr_update(sub, BT_MESH_KEY_REFRESH(flags), new_key);
    if (kr_change) {
        bt_mesh_net_beacon_update(sub);
    }

    if (iv_change) {
        /* Update all subnets */
        bt_mesh_net_sec_update(NULL);
    } else if (kr_change) {
        /* Key Refresh without IV Update only impacts one subnet */
        bt_mesh_net_sec_update(sub);
    }

update_stats:
    if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED &&
        sub->beacons_cur < 0xff) {
        sub->beacons_cur++;
    }
}
Example #29
0
static int ossfs_getattr(const char *path, struct stat *stbuf)
{
  gint res;
  OssObject *object;
  GError *error;
  gpointer value;
  gpointer st;
  GString *dir;

  g_debug("ossfs_getattr(path=%s)", path);
  memset(stbuf, 0, sizeof(struct stat));  
  if (cache_contains((gpointer)path)) {
    st = cache_lookup((gpointer)path);
    memcpy(stbuf, st, sizeof(struct stat));
    return 0;
  }

  if (g_strcmp0(path, "/") == 0) {
    stbuf->st_nlink = 1;
    stbuf->st_mode = default_mode | S_IFDIR;
    stbuf->st_uid = getuid();
    stbuf->st_gid = getgid();
    return 0;
  }

  object = oss_object_new(path);
  if (!object) return -ENOMEM;

  error = NULL;
  res = oss_object_head(service, object, &error);
  if (res) {
    oss_object_destroy(object);
    switch (error->code) {
    case OSS_ERROR_NO_SUCH_KEY:
      if (g_str_has_suffix(path, "/")) return -ENOENT;
      /* try to get path as directory */
      dir = g_string_new(path);
      if (dir == NULL) return -ENOMEM;
      g_string_append_c(dir, '/');
      g_message("try to get %s attribute", dir->str);
      if (g_hash_table_contains(cache, dir->str)) {
	st = g_hash_table_lookup(cache, dir->str);
	memcpy(stbuf, st, sizeof(struct stat));
	g_string_free(dir, TRUE);
	return 0;
      }
      object = oss_object_new(dir->str);
      g_string_free(dir, TRUE);
      if (!object) return -ENOMEM;

      error = NULL;
      res = oss_object_head(service, object, &error);
      if (res) {
	oss_object_destroy(object);
	switch (error->code) {
	case OSS_ERROR_NO_SUCH_KEY:
	  return -ENOENT;
        default:
          return -EIO;
	}
      }
      break; /* case OSS_ERROR_NO_SUCH_KEY */
    default:
      return -EIO;
    }
  }

  /* st_mode */
  value = g_hash_table_lookup(object->meta, OSS_META_MODE);
  if (value) {
    g_debug("%s: %s", OSS_META_MODE, (gchar*)value);
    stbuf->st_mode = g_ascii_strtoull((gchar*)value, NULL, 10);
  } else {
    stbuf->st_mode = default_mode;
    /* TODO: make sure how to test an object is a dir */
    if (g_str_has_suffix(object->key, "/")) {
      stbuf->st_mode |= S_IFDIR;
    } else {
      stbuf->st_mode |= S_IFREG;
    }
    g_debug("using default mode: %d", stbuf->st_mode);
  }

  stbuf->st_nlink = 1;
  stbuf->st_size = object->size;
  g_debug("size: %ld", (long)stbuf->st_size);
  if (S_ISREG(stbuf->st_mode)) {
    stbuf->st_blocks = stbuf->st_size / 512 + 1;
  }
  stbuf->st_uid = getuid();
  stbuf->st_gid = getgid();

  stbuf->st_mtime = parse_date_time_gmt(object->last_modified);

  st = g_memdup((gpointer)stbuf, sizeof(struct stat));
  cache_add(g_strdup(object->key), st);
  oss_object_destroy(object);
  return 0;
}
Example #30
0
File: nlmon.c Project: el8/nlmon
static void gather_data(struct taskstats *t)
{
	struct taskstat_delta *delta;
	struct hash_entry *h;

	if (!nr_cycles && !once) {
		ts_version = t->version;
		ts_size = sizeof(*t);
		output->print_banner(t);
		once = 1;
	}

	h = get_hash_entry(t->ac_pid);
	if (!h)
		DIE("hash entry missing for process %d!", t->ac_pid);
	if (t->ac_pid != h->tid)
		DIE("pid mismatch in hash!");

	// XXX this sucks, optimize later
	delta = malloc(sizeof(struct taskstat_delta));
	if (!delta)
		DIE_PERROR("malloc failed");
	memset(delta, 0, sizeof(struct taskstat_delta));
	delta->pid = h->tgid;
	delta->tid = t->ac_pid;

	__gather_data_sanity(h, t);

	delta->utime = t->ac_utime - h->utime;
	delta->stime = t->ac_stime - h->stime;
	delta->cpu_delay = t->cpu_delay_total - h->cpu_delay;
	delta->rss = t->coremem - h->rss;
	delta->io_rd_bytes = t->read_char - h->io_rd_bytes;
	delta->io_wr_bytes = t->write_char - h->io_wr_bytes;
	delta->blkio_delay = t->blkio_delay_total - h->blkio_delay;

	/* store new values */
	h->utime = t->ac_utime;
	h->stime = t->ac_stime;
	h->cpu_delay = t->cpu_delay_total;
	h->rss = t->coremem;
	h->io_rd_bytes = t->read_char;
	h->io_wr_bytes = t->write_char;
	h->blkio_delay = t->blkio_delay_total;

	put_hash_entry(t->ac_pid);

	if (t->ac_exitcode)
		DEBUG("exiting task: %d [%s]\n", t->ac_pid, t->ac_comm);

	current_sum_utime += delta->utime / 1000;
	current_sum_stime += delta->stime / 1000;

	if (!nr_cycles)
		return;

	/* only output if one value changed! */
	if (output_wanted(delta)) {
		// XXX optimize later, maybe pointer to task string in hash entry?
		memcpy(&delta->comm, t->ac_comm, TS_COMM_LEN);
		cache_add(delta);
	}
}