Ejemplo n.º 1
0
/*
 * BIF implementations
 */
static void pd_hash_erase(Process *p, Eterm id, Eterm *ret)
{
    unsigned int hval;
    Eterm old;
    Eterm tmp;
    unsigned int range;

    *ret = am_undefined;
    if (p->dictionary == NULL) {
	return;
    }
    hval = pd_hash_value(p->dictionary, id);
    old = ARRAY_GET(p->dictionary, hval);
    if (is_boxed(old)) {	/* Tuple */
	ASSERT(is_tuple(old));
	if (EQ(tuple_val(old)[1], id)) {
	    array_put(&(p->dictionary), hval, NIL);
	    --(p->dictionary->numElements);
	    *ret = tuple_val(old)[2];
	}
    } else if (is_list(old)) {
	/* Find cons cell for identical value */
	Eterm* prev = &p->dictionary->data[hval];

	for (tmp = *prev; tmp != NIL; prev = &TCDR(tmp), tmp = *prev) {
	    if (EQ(tuple_val(TCAR(tmp))[1], id)) {
		*prev = TCDR(tmp);
		*ret = tuple_val(TCAR(tmp))[2];
		--(p->dictionary->numElements);
	    }
	}

	/* If there is only one element left in the list we must remove the list. */
	old = ARRAY_GET(p->dictionary, hval);
	ASSERT(is_list(old));
	if (is_nil(TCDR(old))) {
	    array_put(&p->dictionary, hval, TCAR(old));
	}
    } else if (is_not_nil(old)) {
#ifdef DEBUG
	erts_fprintf(stderr,
		     "Process dictionary for process %T is broken, trying to "
		     "display term found in line %d:\n"
		     "%T\n", p->common.id, __LINE__, old);
#endif
	erl_exit(1, "Damaged process dictionary found during erase/1.");
    }
    if ((range = HASH_RANGE(p->dictionary)) > INITIAL_SIZE && 
	range / 2  > (p->dictionary->numElements)) {
	shrink(p, ret);
    }
}
Ejemplo n.º 2
0
static void rm_watch(int wd, bool update_parent) {
  watch_node* node = table_get(watches, wd);
  if (node == NULL) {
    return;
  }

  userlog(LOG_DEBUG, "unwatching %s: %d (%p)", node->path, node->wd, node);

  if (inotify_rm_watch(inotify_fd, node->wd) < 0) {
    userlog(LOG_DEBUG, "inotify_rm_watch(%d:%s): %s", node->wd, node->path, strerror(errno));
  }

  for (int i=0; i<array_size(node->kids); i++) {
    watch_node* kid = array_get(node->kids, i);
    if (kid != NULL) {
      rm_watch(kid->wd, false);
    }
  }

  if (update_parent && node->parent != NULL) {
    for (int i=0; i<array_size(node->parent->kids); i++) {
      if (array_get(node->parent->kids, i) == node) {
        array_put(node->parent->kids, i, NULL);
        break;
      }
    }
  }

  array_delete(node->kids);
  free(node);
  table_put(watches, wd, NULL);
}
Ejemplo n.º 3
0
Archivo: array.c Proyecto: em-mo/TDDD56
struct array*
array_read(char * filename)
{
  int i;
  FILE * h;
  int num;
  value value;
  struct array * res;

  h = fopen(filename, "r");
  i = read_value(h, &num);
  assert(i > 0);
  
  res = array_alloc(num);

  num = 1;
  for (i = 0; i < res->capacity && num > 0; i++)
    {
      num = read_value(h, &value);
      array_put(res, value);
    }

  fclose(h);

  return res;
}
Ejemplo n.º 4
0
uint32_t watch_add(watch_t * self, const char *path, uint32_t events,
		   watch_callback_t * cb)
{
	if (unlikely(self == NULL))
		throw_unexpected(WATCH_NULL);

	if (access(path, F_OK) != 0)
		throw_errno(errno);

	uint32_t wd = inotify_add_watch(self->fd, path, events);
	if (unlikely((int)wd == -1))
		throw_errno(errno);

	if (cb != NULL)
		array_put(&self->callbacks, wd, cb, 1);

	return wd;
}
Ejemplo n.º 5
0
static bool process_inotify_event(struct inotify_event* event) {
  watch_node* node = table_get(watches, event->wd);
  if (node == NULL) {
    return true;
  }

  bool is_dir = (event->mask & IN_ISDIR) == IN_ISDIR;
  userlog(LOG_DEBUG, "inotify: wd=%d mask=%d dir=%d name=%s", event->wd, event->mask & (~IN_ISDIR), is_dir, node->path);

  memcpy(path_buf, node->path, node->path_len + 1);
  int path_len = node->path_len;
  if (event->len > 0) {
    path_buf[node->path_len] = '/';
    int name_len = strlen(event->name);
    memcpy(path_buf + path_len + 1, event->name, name_len + 1);
    path_len += name_len + 1;
  }

  if (is_dir && event->mask & (IN_CREATE | IN_MOVED_TO)) {
    int result = walk_tree(path_len, node, true, NULL);
    if (result < 0 && result != ERR_IGNORE && result != ERR_CONTINUE) {
      return false;
    }
  }

  if (is_dir && event->mask & (IN_DELETE | IN_MOVED_FROM)) {
    for (int i=0; i<array_size(node->kids); i++) {
      watch_node* kid = array_get(node->kids, i);
      if (kid != NULL && strncmp(path_buf, kid->path, kid->path_len) == 0) {
        rm_watch(kid->wd, false);
        array_put(node->kids, i, NULL);
        break;
      }
    }
  }

  if (callback != NULL) {
    (*callback)(path_buf, event->mask);
  }

  return true;
}
Ejemplo n.º 6
0
Archivo: rand.c Proyecto: grulg/tddd56
int
main(int argc, char ** argv)
{
	int i, max, min, count, amplitude;
	struct array * array;

	srandom(rdtsc() + time(NULL));

	if(argc < 4)
	{
		printf("Usage: %s <min_value> <max_value> <number of values>\n", argv[0]);
		return EXIT_FAILURE;
	}
	else
	{
		array_init(argc, argv);

		min = atoi(argv[1]);
		max = atoi(argv[2]);
		count = atoi(argv[3]);

		array = array_alloc(count);		

		amplitude = max - min + 1;

		for(i = 0; i < count; i++)
		{
			array_put(array, random() % amplitude + min);
		}

		printf("%d ", count);
		for(i = 0; i < count; i++)
		{
			printf("%d ", array_get(array, i));
		}
		
		array_free(array);
	}
	
	return 0;
}
Ejemplo n.º 7
0
static bool process_inotify_event(struct inotify_event* event) {
  watch_node* node = table_get(watches, event->wd);
  if (node == NULL) {
    return true;
  }

  userlog(LOG_DEBUG, "inotify: wd=%d mask=%d dir=%d name=%s",
      event->wd, event->mask & (~IN_ISDIR), (event->mask & IN_ISDIR) != 0, node->name);

  char path[PATH_MAX];
  strcpy(path, node->name);
  if (event->len > 0) {
    if (path[strlen(path) - 1] != '/') {
      strcat(path, "/");
    }
    strcat(path, event->name);
  }

  if ((event->mask & IN_CREATE || event->mask & IN_MOVED_TO) && event->mask & IN_ISDIR) {
    int result = walk_tree(path, node, NULL);
    if (result < 0 && result != ERR_IGNORE) {
      return false;
    }
  }

  if ((event->mask & IN_DELETE || event->mask & IN_MOVED_FROM) && event->mask & IN_ISDIR) {
    for (int i=0; i<array_size(node->kids); i++) {
      watch_node* kid = array_get(node->kids, i);
      if (kid != NULL && strcmp(kid->name, path) == 0) {
        rm_watch(kid->wd, false);
        array_put(node->kids, i, NULL);
        break;
      }
    }
  }

  if (callback != NULL) {
    (*callback)(path, event->mask);
  }
  return true;
}
Ejemplo n.º 8
0
static void grow(Process *p)
{
    unsigned int i,j;
    unsigned int steps = p->dictionary->homeSize / 5;
    Eterm l1,l2;
    Eterm l;
    Eterm *hp;
    unsigned int pos;
    unsigned int homeSize;
    int needed = 0;
    ProcDict *pd;
#ifdef DEBUG
    Eterm *hp_limit;
#endif

    HDEBUGF(("grow: steps = %d", steps));
    if (steps == 0)
	steps = 1;
    /* Dont grow over MAX_HASH */
    if ((MAX_HASH - steps) <= HASH_RANGE(p->dictionary)) {
	return;
    }

    /*
     * Calculate total number of heap words needed, and garbage collect
     * if necessary.
     */

    pd = p->dictionary;
    pos = pd->splitPosition;
    homeSize = pd->homeSize;
    for (i = 0; i < steps; ++i) {
	if (pos == homeSize) {
	    homeSize *= 2;
	    pos = 0;
	}
	l = ARRAY_GET(pd, pos);
	pos++;
	if (is_not_tuple(l)) {
	    while (l != NIL) {
		needed += 2;
		l = TCDR(l);
	    }
	}
    }
    if (HeapWordsLeft(p) < needed) {
	BUMP_REDS(p, erts_garbage_collect(p, needed, 0, 0));
    }
#ifdef DEBUG
    hp_limit = p->htop + needed;
#endif

    /*
     * Now grow.
     */

    for (i = 0; i < steps; ++i) {
	ProcDict *pd = p->dictionary;
	if (pd->splitPosition == pd->homeSize) {
	    pd->homeSize *= 2;
	    pd->splitPosition = 0;
	}
	pos = pd->splitPosition;
	++pd->splitPosition; /* For the hashes */
	l = ARRAY_GET(pd, pos);
	if (is_tuple(l)) {
	    if (pd_hash_value(pd, tuple_val(l)[1]) != pos) {
		array_put(&(p->dictionary), pos + 
			  p->dictionary->homeSize, l);
		array_put(&(p->dictionary), pos, NIL);
	    }
	} else {
	    l2 = NIL;
	    l1 = l;
	    for (j = 0; l1 != NIL; l1 = TCDR(l1))
		j += 2;
	    hp = HeapOnlyAlloc(p, j);
	
	    while (l != NIL) {
		if (pd_hash_value(pd, tuple_val(TCAR(l))[1]) == pos) 
		    l1 = CONS(hp, TCAR(l), l1);
		else
		    l2 = CONS(hp, TCAR(l), l2);
		hp += 2;
		l = TCDR(l);
	    }
	    if (l1 != NIL && TCDR(l1) == NIL)
		l1 = TCAR(l1);
	    if (l2 != NIL && TCDR(l2) == NIL)
		l2 = TCAR(l2);
	    ASSERT(hp <= hp_limit);
	    /* After array_put pd is no longer valid */
	    array_put(&(p->dictionary), pos, l1);
	    array_put(&(p->dictionary), pos + 
		      p->dictionary->homeSize, l2);
	}
    }

#ifdef HARDDEBUG
    dictionary_dump(p->dictionary,CERR);
#endif
}
Ejemplo n.º 9
0
static void shrink(Process *p, Eterm* ret) 
{
    unsigned int range = HASH_RANGE(p->dictionary);
    unsigned int steps = (range*3) / 10;
    Eterm hi, lo, tmp;
    unsigned int i;
    Eterm *hp;
#ifdef DEBUG
    Eterm *hp_limit;
#endif

    if (range - steps < INITIAL_SIZE) {
	steps = range - INITIAL_SIZE; 
    }

    for (i = 0; i < steps; ++i) {
	ProcDict *pd = p->dictionary;
	if (pd->splitPosition == 0) {
	    pd->homeSize /= 2;
	    pd->splitPosition = pd->homeSize;
	}
	--(pd->splitPosition);
	hi = ARRAY_GET(pd, (pd->splitPosition + pd->homeSize));
	lo = ARRAY_GET(pd, pd->splitPosition);
	if (hi != NIL) {
	    if (lo == NIL) {
		array_put(&(p->dictionary), pd->splitPosition, hi);
	    } else {
		int needed = 4;
		if (is_list(hi) && is_list(lo)) {
		    needed = 2*erts_list_length(hi);
		}
		if (HeapWordsLeft(p) < needed) {
		    BUMP_REDS(p, erts_garbage_collect(p, needed, ret, 1));
		    hi = pd->data[(pd->splitPosition + pd->homeSize)];
		    lo = pd->data[pd->splitPosition];
		}
#ifdef DEBUG
		hp_limit = p->htop + needed;
#endif
		if (is_tuple(lo)) {
		    if (is_tuple(hi)) {
			hp = HeapOnlyAlloc(p, 4);
			tmp = CONS(hp, hi, NIL);
			hp += 2;
			array_put(&(p->dictionary), pd->splitPosition, 
				  CONS(hp,lo,tmp));
			hp += 2;
			ASSERT(hp <= hp_limit);
		    } else { /* hi is a list */
			hp = HeapOnlyAlloc(p, 2);
			array_put(&(p->dictionary), pd->splitPosition, 
				  CONS(hp, lo, hi));
			hp += 2;
			ASSERT(hp <= hp_limit);
		    }
		} else { /* lo is a list */
		    if (is_tuple(hi)) {
			hp = HeapOnlyAlloc(p, 2);
			array_put(&(p->dictionary), pd->splitPosition, 
				  CONS(hp, hi, lo));
			hp += 2;
			ASSERT(hp <= hp_limit);

		    } else { /* Two lists */
			hp = HeapOnlyAlloc(p, needed);
			for (tmp = hi; tmp != NIL; tmp = TCDR(tmp)) {
			    lo = CONS(hp, TCAR(tmp), lo);
			    hp += 2;
			}
			ASSERT(hp <= hp_limit);
			array_put(&(p->dictionary), pd->splitPosition, lo);
		    }
		}
	    }
	}
	array_put(&(p->dictionary), (pd->splitPosition + pd->homeSize), NIL);
    }
    if (HASH_RANGE(p->dictionary) <= (p->dictionary->size / 4)) {
	array_shrink(&(p->dictionary), (HASH_RANGE(p->dictionary) * 3) / 2);
    }
}
Ejemplo n.º 10
0
static Eterm pd_hash_put(Process *p, Eterm id, Eterm value)
{ 
    unsigned int hval;
    Eterm *hp;
    Eterm tpl;
    Eterm old;
    Eterm tmp;
    int needed;
    int i = 0;
#ifdef DEBUG
    Eterm *hp_limit;
#endif

    if (p->dictionary == NULL) {
	/* Create it */
	array_put(&(p->dictionary), INITIAL_SIZE - 1, NIL);
	p->dictionary->homeSize = INITIAL_SIZE;
    }	
    hval = pd_hash_value(p->dictionary, id);
    old = ARRAY_GET(p->dictionary, hval);

    /*
     * Calculate the number of heap words needed and garbage
     * collect if necessary. (Might be a slight overestimation.)
     */
    needed = 3;			/* {Key,Value} tuple */
    if (is_boxed(old)) {
	/*
	 * We don't want to compare keys twice, so we'll always
	 * reserve the space for two CONS cells.
	 */
	needed += 2+2;
    } else if (is_list(old)) {
	i = 0;
	for (tmp = old; tmp != NIL && !EQ(tuple_val(TCAR(tmp))[1], id); tmp = TCDR(tmp)) {
	    ++i;
	}
	if (is_nil(tmp)) {
	    i = -1;
	    needed += 2;
	} else {
	    needed += 2*(i+1);
	}
    }
    if (HeapWordsLeft(p) < needed) {
	Eterm root[3];
	root[0] = id;
	root[1] = value;
	root[2] = old;
	BUMP_REDS(p, erts_garbage_collect(p, needed, root, 3));
	id = root[0];
	value = root[1];
	old = root[2];
    }
#ifdef DEBUG
    hp_limit = p->htop + needed;
#endif

    /*
     * Create the {Key,Value} tuple.
     */
    hp = HeapOnlyAlloc(p, 3);
    tpl = TUPLE2(hp, id, value);

    /*
     * Update the dictionary.
     */
    if (is_nil(old)) {
	array_put(&(p->dictionary), hval, tpl);
	++(p->dictionary->numElements);
    } else if (is_boxed(old)) {
	ASSERT(is_tuple(old));
	if (EQ(tuple_val(old)[1],id)) {
	    array_put(&(p->dictionary), hval, tpl);
	    return tuple_val(old)[2];
	} else {
	    hp = HeapOnlyAlloc(p, 4);
	    tmp = CONS(hp, old, NIL);
	    hp += 2;
	    ++(p->dictionary->numElements);
	    array_put(&(p->dictionary), hval, CONS(hp, tpl, tmp));
	    hp += 2;
	    ASSERT(hp <= hp_limit);
	}
    } else if (is_list(old)) {
	if (i == -1) {
	    /*
	     * New key. Simply prepend the tuple to the beginning of the list.
	     */
	    hp = HeapOnlyAlloc(p, 2);
	    array_put(&(p->dictionary), hval, CONS(hp, tpl, old));
	    hp += 2;
	    ASSERT(hp <= hp_limit);
	    ++(p->dictionary->numElements);
	} else {
	    /*
	     * i = Number of CDRs to skip to reach the changed element in the list.
	     *
	     * Replace old value in list. To avoid pointers from the old generation
	     * to the new, we must rebuild the list from the beginning up to and
	     * including the changed element.
	     */
	    Eterm nlist;
	    int j;

	    hp = HeapOnlyAlloc(p, (i+1)*2);
	    
	    /* Find the list element to change. */
	    for (j = 0, nlist = old; j < i; j++, nlist = TCDR(nlist)) {
		;
	    }
	    ASSERT(EQ(tuple_val(TCAR(nlist))[1], id));
	    nlist = TCDR(nlist); /* Unchanged part of list. */

	    /* Rebuild list before the updated element. */
	    for (tmp = old; i-- > 0; tmp = TCDR(tmp)) {
		nlist = CONS(hp, TCAR(tmp), nlist);
		hp += 2;
	    }
	    ASSERT(EQ(tuple_val(TCAR(tmp))[1], id));

	    /* Put the updated element first in the new list. */
	    nlist = CONS(hp, tpl, nlist);
	    hp += 2;
	    ASSERT(hp <= hp_limit);
	    array_put(&(p->dictionary), hval, nlist);
	    return tuple_val(TCAR(tmp))[2];
	}
    } else {
#ifdef DEBUG
	erts_fprintf(stderr,
		     "Process dictionary for process %T is broken, trying to "
		     "display term found in line %d:\n"
		     "%T\n", p->common.id, __LINE__, old);
#endif

	erl_exit(1, "Damaged process dictionary found during put/2.");
    }
    if (HASH_RANGE(p->dictionary) <= p->dictionary->numElements) {
	grow(p);
    }
    return am_undefined;
}
Ejemplo n.º 11
0
int main(int argc, char *argv[])
{
	struct array a;
	struct array_iterator ai;
	int i;
	int *t, *t_arr;
	
	while ((i = getopt(argc, argv, "vi:")) != -1) {
		switch (i) {
		    case 'v':
			++verbose;
			break;
		    case 'i':
			MAX_ITEMS = atoi(optarg);
			break;
		    default:
			fprintf(stderr, "bad option\n");
			exit(1);
		}
	}
	
	assert(t_arr = malloc(MAX_ITEMS * sizeof(int)));
	array_init(&a, 100);
	
	verbose_print(1, "start\n");
	for (i = 0; i < MAX_ITEMS; i++) {
		t = t_arr + i;
		*t = i;
		assert(array_put(&a, t) == i);
	}
	for (i = 0; i < MAX_ITEMS; i += 2) {
		t = t_arr + i;
		assert(array_remove(&a, t) == t);
	}
	for (i = 1; i < MAX_ITEMS; i += 2) {
		t = t_arr + i;
		assert(array_pop(&a) == t);
	}
	for (i = 0; i < MAX_ITEMS; i += 2) {
		t = t_arr + i;
		assert(array_put_at(&a, i, t) == NULL);
	}
	for (i = 1; i < MAX_ITEMS; i += 2) {
		t = t_arr + i;
		assert(array_put(&a, t) == i);
	}
	for (i = 0; i < MAX_ITEMS; i += 2) {
		t = t_arr + i;
		assert(array_remove_at(&a, i) == t);
	}
	array_iter_set(&ai, &a);
	i = 1;
	while ((t = array_iter_get(&ai))) {
		assert(*t == i);
		i += 2;
		verbose_print(2, "%d ", *t);
	}
	array_iter_end(&ai);
	printf("\n");
	
	array_free(&a);
	
	return 0;
}