Example #1
0
static GList*
zapi_list_aggregates(na_server_t *s, GError **err)
{
	GList *la;
	na_elem_t *out, *in;
	na_elem_t *aggr_info_array, *aggr_info;
	na_elem_iter_t iter_aggr;

	XTRACE("Entering");

	in = na_elem_new("aggr-list-info");
	out = na_server_invoke_elem(s, in);
	na_elem_free(in);

	if (!out) {
		GSETERROR(err, "ZAPI error : no output");
		LOG_RETURN(NULL,"Failure (zapi error)");
	}
	if (na_results_status(out) != NA_OK) {
		na_elem_free(out);
		GSETERROR(err, "NetApp filer error : (%d) %s", na_results_errno(out), na_results_reason(out));
		LOG_RETURN(NULL,"Failure (server)");
	}

	la = NULL;
	aggr_info_array = na_elem_child(out, "aggregates");
	for (iter_aggr=na_child_iterator(aggr_info_array); (aggr_info=na_iterator_next(&iter_aggr)) ;) {
		const char *aname;
		aname = na_child_get_string(aggr_info,"name");
		la = g_list_append(la, g_strdup(aname));
	}
	
	na_elem_free(out);
	LOG_RETURN(la,"Success");
}
Example #2
0
struct volume_s*
netapp_get_volume(struct filer_s *filer, const char *name, GError **error)
{
	register int rc;
	struct volume_s **vol_ptr;
	struct enterprise_s *enterprise;

	XTRACE("Entering");
	
	enterprise = filer->enterprise;

	if (!netapp_refresh_fixed_filer_data(filer, error)) {
		GSETERROR(error, "Uncomplete or too old filer data");
		LOG_RETURN(NULL, "Failure (uncomplete info)");
	}

	for (vol_ptr=filer->ctx->fixed.volumes; *vol_ptr ;vol_ptr++) {
		XTRACE("Comparing [%s] to [%s]", enterprise->get_name(*vol_ptr), name);
		rc = g_ascii_strcasecmp(enterprise->get_name(*vol_ptr), name);
		if (rc == 0)
			return *vol_ptr;
	}

	LOG_RETURN(NULL, "Failure (not found)");
}
Example #3
0
static gboolean
netapp_refresh_volumes_list(struct filer_s *filer, GError **error)
{
	struct volume_s **new_volumes, **ptr_vol, **old_vol;

	XTRACE("Entering");

	if (!(new_volumes = netapp_load_volumes(filer, error))) {
		GSETERROR(error, "Failed to refresh the volume list");
		LOG_RETURN(FALSE,"Failure (volumes list loading)");
	}

	if (!filer->ctx->fixed.volumes) {
		filer->ctx->fixed.volumes = new_volumes;
		LOG_RETURN(TRUE,"Success (first loading)");
	}

	/* merge the old volumes on the old volumes in the new,
	 * this will copy the volume statistics, then keep only
	 * the latest volume list */
	for (ptr_vol=new_volumes; *ptr_vol ;ptr_vol++) {
		for (old_vol=filer->ctx->fixed.volumes; *old_vol ;old_vol++) {
			if (0 == g_ascii_strcasecmp((*ptr_vol)->path, (*old_vol)->path)) {
				memcpy(*ptr_vol, *old_vol, sizeof(struct volume_s));
				break;
			}
		}
	}
	
	netapp_free_volume_array(filer->ctx->fixed.volumes);
	filer->ctx->fixed.volumes = new_volumes;
	LOG_RETURN(TRUE,"Success (reload)");
}
Example #4
0
/**
 * Get the prompt string.
 */
char* get_prompt() {
  LOG_ENTRY;
  getcwd(prompt_buffer, PROMPT_BUFFER_SIZE);
  #if DEBUG
    LOG_RETURN(prompt_buffer);
  #else
    LOG_RETURN(strrchr(prompt_buffer, '/') + 1);
  #endif
}
Example #5
0
/**
 * Returns true if a string is all whitespace characters.
 */
bool str_is_whitespace(char* str) {
  LOG_ENTRY;
  char* c;
  for (c = str; c && *c; c++) {
    if (!(*c == ' ' || *c == '\t' || *c == '\n')) {
      LOG_RETURN(false);
    }
  }
  LOG_RETURN(true);
}
Example #6
0
static GHashTable*
zapi_get_disk2aggr(na_server_t *s, GError **err)
{
	GHashTable *ht;
	na_elem_t *out, *in;
	na_elem_t *disk_info_array, *disk_info;
	na_elem_iter_t iter_disk;

	XTRACE("Entering");

	/* the target aggregate is optional, and that is fine, we will
	 * get the information about all the agregates */
	in = na_elem_new("disk-list-info");
	out = na_server_invoke_elem(s, in);

	/* Error management */
	if (!out) {
		na_elem_free(in);
		GSETERROR(err, "ZAPI error : no output");
		LOG_RETURN(NULL,"Failure (zapi error)");
	}
	if (na_results_status(out) != NA_OK) {
		na_elem_free(in);
		na_elem_free(out);
		GSETERROR(err, "NetApp filer error : (%d) %s", na_results_errno(out), na_results_reason(out));
		LOG_RETURN(NULL,"Failure (server)");
	}

	/* Reply's content handling */
	ht = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
	disk_info_array = na_elem_child(out,"disk-details");
	for (iter_disk=na_child_iterator(disk_info_array); (disk_info=na_iterator_next(&iter_disk)) ;) {
		const char *aname, *dname;

		/* normal case for flex-vol */
		aname = na_child_get_string(disk_info,"aggregate");
		
		if (!aname) /* special case for trad-vol volumes */
			aname = na_child_get_string(disk_info,"volume");
			
		if (aname) {
			dname = na_child_get_string(disk_info,"disk-uid");
		 	g_hash_table_insert(ht, g_strdup(dname), g_strdup(aname));
			XTRACE("Saved : disk[%s] -> aggr[%s]", dname, aname);
		}
	}
	
	na_elem_free(in);
	na_elem_free(out);
	LOG_RETURN(ht,"Success");
}
Example #7
0
/**
 * Change Directory.
 */
bool change_directory(void) {
  LOG_ENTRY;
  int input_length = strlen(input_buffer);

  char target_dir [input_length - 3];
  memcpy(target_dir, input_buffer + 3, input_length - 3);
  target_dir[input_length-3-1] = '\0';

  if(chdir(target_dir)) {
    printf("%s: %s", CHANGE_DIR_ERROR_MSG, strerror(errno));
    LOG_RETURN(false);
  }
  LOG_RETURN(true);
}
Example #8
0
/**
 * Handle Input.
 */
bool handle_input(void) {
  LOG_ENTRY;
  if (is_quit_command(input_buffer)) {
    exit_shell();
    LOG_RETURN(false);
  } else if (is_cd_command(input_buffer)) {
    change_directory();
    LOG_RETURN(false);
  } else if (str_is_whitespace(input_buffer)) {
    LOG_RETURN(false);
  } else {
    input_tokens = tokenize(input_buffer);
    LOG_RETURN(true);
  }
}
Example #9
0
gboolean
netapp_api_init(struct enterprise_s *e, GError **err)
{
	gchar str_err[1024];

	(void) e;

	memset(str_err, 0x00, sizeof(str_err));
	if (!na_startup(str_err, sizeof(str_err))) {
		GSETERROR(err, "Netapp OnTap management API failure init : %.*s",
			sizeof(str_err), str_err);
		LOG_RETURN(FALSE,"Failure");
	}

	LOG_RETURN(TRUE,"Success");
}
Example #10
0
/**
 * Handle exit status.
 */
void handle_exit_status(int status) {
  LOG_ENTRY;
  if (WEXITSTATUS(status)) {
    printf("%s %d\n", CHILD_STATUS_ERROR_MSG, WEXITSTATUS(status));
  }
  LOG_RETURN();
}
Example #11
0
static gboolean
netapp_refresh_fixed_filer_data(struct filer_s *filer, GError **err)
{
	register gboolean time_is_up;
	
	time_is_up = filer->ctx->fixed.last_update + 60L < time(0);

	if (time_is_up || !filer->ctx->fixed.volumes) {
		GHashTable *ht_vol2aggr, *ht_disk2aggr;
		GList *aggregates;
		
		if (!netapp_refresh_network_definitions(filer, err))
			LOG_RETURN(FALSE,"Failure (network)");
		if (!netapp_refresh_volumes_list(filer, err))
			LOG_RETURN(FALSE,"Failure (volumes)");
		
		aggregates = zapi_list_aggregates(filer->ctx->na_session, err);
		if (aggregates) {
			if (filer->ctx->fixed.aggregates) {
				g_list_foreach (filer->ctx->fixed.aggregates, (GFunc)g_free, NULL);
				g_list_free(filer->ctx->fixed.aggregates);
			}
			filer->ctx->fixed.aggregates = aggregates;
		}
			
		ht_vol2aggr = zapi_get_vol2aggr(filer->ctx->na_session, err);
		if (ht_vol2aggr) {
			if (filer->ctx->fixed.vol2aggr)
				g_hash_table_destroy(filer->ctx->fixed.vol2aggr);
			filer->ctx->fixed.vol2aggr = ht_vol2aggr;
			XTRACE("Mappings saved : vol2aggr (%u)", g_hash_table_size(filer->ctx->fixed.vol2aggr));
		}
		
		ht_disk2aggr = zapi_get_disk2aggr(filer->ctx->na_session, err);
		if (ht_disk2aggr) {
			if (filer->ctx->fixed.disk2aggr)
				g_hash_table_destroy(filer->ctx->fixed.disk2aggr);
			filer->ctx->fixed.disk2aggr = ht_disk2aggr;
			XTRACE("Mappings saved : disk2aggr (%u)", g_hash_table_size(filer->ctx->fixed.disk2aggr));
		}
	}

	filer->ctx->fixed.last_update = time(0);
	LOG_RETURN(TRUE, "Success (filer fixed data reloaded)");
}
Example #12
0
/* Retrieve a list of Aggregate-to-Volume list
 * covering all the aggregates of the given filer */
static GHashTable*
zapi_get_vol2aggr(na_server_t *s, GError **err)
{
	GHashTable *ht;
	na_elem_t *out, *in;
	na_elem_t *vol_info_array, *vol_info, *aggr_info_array, *aggr_info;
	na_elem_iter_t iter_aggr, iter_vol;

	XTRACE("Entering");
	
	/* the target aggregate is optional, and that is fine, we will
	 * get the information about all the agregates */
	in = na_elem_new("aggr-list-info");
	out = na_server_invoke_elem(s, in);
	na_elem_free(in);

	/* Error management */
	if (!out) {
		GSETERROR(err, "ZAPI error : no output");
		LOG_RETURN(NULL,"Failure (zapi error)");
	}
	if (na_results_status(out) != NA_OK) {
		na_elem_free(out);
		GSETERROR(err, "NetApp filer error : (%d) %s", na_results_errno(out), na_results_reason(out));
		LOG_RETURN(NULL,"Failure (server)");
	}

	/* Reply's content handling */
	ht = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
	aggr_info_array = na_elem_child(out, "aggregates");
	for (iter_aggr=na_child_iterator(aggr_info_array); (aggr_info=na_iterator_next(&iter_aggr)) ;) {
		vol_info_array = na_elem_child(aggr_info,"volumes");
		for (iter_vol=na_child_iterator(vol_info_array); (vol_info=na_iterator_next(&iter_vol)) ;) {
			const char *vname, *aname;

			vname = na_child_get_string(vol_info,"name");
			aname = na_child_get_string(aggr_info,"name");
			g_hash_table_insert(ht, g_strdup(vname), g_strdup(aname));
			XTRACE("Saved : vol[%s] -> agr[%s]", vname, aname);
		}
	}
	
	na_elem_free(out);
	LOG_RETURN(ht,"Success");
}
Example #13
0
gboolean
netapp_api_close(struct enterprise_s *e, GError **err)
{
	(void) e;
	(void) err;

	XTRACE("Entering");
	na_shutdown();
	LOG_RETURN(TRUE,"Success");
}
Example #14
0
gboolean
netapp_monitor_volume(struct volume_s *vol, struct volume_statistics_s *st, GError **err)
{
	struct filer_s *filer;
	
	XTRACE("Entering [%s -> %s]", vol->path, vol->name);
	filer = vol->filer;
	
	if (!netapp_refresh_fixed_filer_data(filer, err)) {
		GSETERROR(err, "Uncomplete or too old filer data");
		LOG_RETURN(FALSE, "Failure (uncomplete info)");
	}

	/* Collect FS-dependant DATA */
	if (!snmp_get_template_int(filer->ctx->session, oid_fsUsedSpace, oid_fsUsedSpace_size,
			netapp_get_volume_id(vol), &(st->used_space), err)) {
		GSETERROR(err, "Failed to get the FS usage of this volume");
		LOG_RETURN(FALSE,"Failure (FS usage)");
	}
	if (!snmp_get_template_int(filer->ctx->session, oid_fsFreeSpace, oid_fsFreeSpace_size,
			netapp_get_volume_id(vol), &(st->free_space), err)) {
		GSETERROR(err, "Failed to get the FS availability of this volume");
		LOG_RETURN(FALSE,"Failure (FS availability)");
	}
	XTRACE("Space usage : used=%"G_GINT64_FORMAT" free=%"G_GINT64_FORMAT,
		st->used_space, st->free_space);

	/* Now get the Filer-dependant data */
	st->cpu_idle = filer->ctx->variable.cpu_idle;
	st->net_idle = filer->ctx->variable.net_idle;

	st->io_idle = netapp_get_volume_disk_idle(filer, vol, err);
	if (st->io_idle < 0) {
		GSETERROR(err, "Failed to collect the disk-idle for vol [%s]", vol->path);
		LOG_RETURN(FALSE,"Failure (disk idle)");
	}

	st->perf_idle = 100LL;

	LOG_RETURN(TRUE, "Success (net=%"G_GINT64_FORMAT" cpu=%"G_GINT64_FORMAT")", st->net_idle, st->cpu_idle);
}
Example #15
0
static gboolean
netapp_refresh_network_definitions(struct filer_s *filer, GError **err)
{
	oid itfIndex;
	gint64 itfSpeed;
	
	XTRACE("Entering");
	
	if (!snmp_get_interface_index(filer->ctx->session, &itfIndex, err)) {
		GSETERROR(err, "Interface index not found");
		LOG_RETURN(FALSE,"Failure (interface index)");
	}
	if (!snmp_get_interface_speed(filer->ctx->session, itfIndex, &itfSpeed, err)) {
		GSETERROR(err, "Interface speed not found for index=%u", itfIndex);
		LOG_RETURN(FALSE,"Failure (interface bandwith)");
	}

	filer->ctx->fixed.net_itf_index = itfIndex;
	filer->ctx->fixed.net_in_max = filer->ctx->fixed.net_out_max = itfSpeed;
	LOG_RETURN(TRUE,"Success");
}
Example #16
0
static struct filer_ctx_s*
netapp_init_filer(struct filer_s *filer, GError **err)
{
	struct filer_ctx_s *ctx;

	XTRACE("Entering");
	(void) filer;
	
	ctx = g_try_malloc0(sizeof(*ctx));
	if (!ctx) {
		GSETERROR(err,"Memory allocation failure");
		LOG_RETURN(NULL,"Failure (memory)");
	}

	/* Inits the SNMP session for this Filer */
	ctx->session = snmp_init(&(ctx->snmp_session), filer->str_addr, &(filer->auth.snmp), err);
	if (!ctx->session) {
		g_free(ctx);
		GSETERROR(err,"SNMP session error");
		LOG_RETURN(NULL,"Failure (snmp)");
	}

	/* Inits the Zapi session */
	ctx->na_session = na_server_open(filer->str_addr, 1, 0);
	if (!ctx->na_session) {
		snmp_close(ctx->session);
		g_free(ctx);
		GSETERROR(err,"OnTap Management API error : failed to start a session");
		LOG_RETURN(NULL,"Failure (na_session)");
	}
	na_server_style(ctx->na_session, NA_STYLE_LOGIN_PASSWORD);
	na_server_set_transport_type(ctx->na_session, NA_SERVER_TRANSPORT_HTTP, NULL);
	na_server_adminuser(ctx->na_session, filer->auth.filer.user, filer->auth.filer.passwd);
	
	return ctx;
}
Example #17
0
/**
 * Free Input Tokens.
 */
void free_input_tokens(void) {
  LOG_ENTRY;
  #if DEBUG
  int free_count = 0;
  #endif
  if (input_tokens && *input_tokens) {
    char** foo;
    for (foo = input_tokens; foo && *foo; foo++) {
      #if DEBUG
      free_count++;
      #endif
      free(*foo);
    }
    #if DEBUG
    printf("%d tokens freed\n", free_count);
    #endif
    free(input_tokens);
  }
  LOG_RETURN();
}
Example #18
0
/**
 * Main
 */
int main(int argc, char* argv[], char* envp[]) {
  LOG_ENTRY;
  parse_args(argc, argv);
  input_buffer = calloc(INPUT_BUFFER_SIZE, sizeof(char));
  prompt_buffer = calloc(PROMPT_BUFFER_SIZE, sizeof(char));
  while(1) {
    display_prompt();
    if(read_input() != NULL) {
      bool valid = handle_input();
      if (valid) {
	pid_t child_pid = fork();
	int status;
	if(child_pid) { //parent-execution
	  struct rusage child_info;
	  wait4(child_pid, &status, 0, &child_info);
	  if (display_child_time) {
	    printf(CHILD_EXECUTION_TIME_FMT,
		   (float) (child_info.ru_stime.tv_sec + child_info.ru_utime.tv_sec) +
		   (float) (child_info.ru_stime.tv_usec + child_info.ru_utime.tv_usec) / 1000000);
	  }
	  CHILD_OUT_END;
	  handle_exit_status(status);
	} else { //child execution
	  child_execute_input(envp);
	}
      }
    } else {
      printf(EOF_ERROR_MSG);
      exit_shell();
    }
#if DEBUG
    dump_buffers();
    #endif
  }
  LOG_RETURN(0);
}
Example #19
0
static GHashTable*
zapi_get_disk2idle(na_server_t *s, GError **err)
{
	GHashTable *ht;
	na_elem_t *out, *in;
	na_elem_t *instances, *instance;
	na_elem_iter_t iter_c, iter_i;

	XTRACE("Entering");

	in = na_elem_new("perf-object-get-instances");
	na_child_add_string(in, "objectname", "disk");

	do {
		na_elem_t *counters = na_elem_new("counters");
		na_child_add_string(counters, "counter", "disk_busy");
		na_child_add_string(counters, "counter", "base_for_disk_busy");
		na_child_add(in, counters);
	} while (0);

	out = na_server_invoke_elem(s, in);
	na_elem_free(in);
	
	/* Error management */
	if (!out) {
		GSETERROR(err, "ZAPI error : no output");
		LOG_RETURN(NULL,"Failure (zapi error)");
	}
	if (na_results_status(out) != NA_OK) {
		na_elem_free(out);
		GSETERROR(err, "NetApp filer error : (%d) %s", na_results_errno(out), na_results_reason(out));
		LOG_RETURN(NULL,"Failure (server)");
	}

	/* Reply's content handling */
	ht = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
	instances = na_elem_child(out, "instances");
	for (iter_i=na_child_iterator(instances); (instance = na_iterator_next(&iter_i)); ) {
		const char *iname;
		na_elem_t *counters, *counter;
		gint64 busy=1, busy_base=0;
		gint idle;

		iname = na_child_get_string(instance, "name");
		counters = na_elem_child(instance, "counters");

		for (iter_c=na_child_iterator(counters); (counter = na_iterator_next(&iter_c)) ; ) {
			const char *cname;
			gint i;

			cname = na_child_get_string(counter, "name");
			i = na_child_get_int(counter, "value", 0);
			if (cname && *cname=='b' && 0==g_ascii_strcasecmp(cname,"base_for_disk_busy"))
				busy_base = i>0 ? i : 1;
			if (cname && *cname=='d' && 0==g_ascii_strcasecmp(cname,"disk_busy"))
				busy = i>0 ? i : 1;
		}

		busy_base /= busy;
		idle = 100LL - busy_base;
		g_hash_table_insert(ht, g_strdup(iname), GINT_TO_POINTER(idle));
		XTRACE("Saved : disk[%s] -> idle[%d]", iname, idle);
	}
	
	na_elem_free(out);
	LOG_RETURN(ht,"Success");
}
Example #20
0
/**
 * Read Input.
 */
char* read_input(void) {
  LOG_ENTRY;
  char* x = (char*)fgets(input_buffer, INPUT_BUFFER_SIZE, stdin);
  LOG_RETURN(x);
}
Example #21
0
static gboolean
netapp_refresh_filer_data(struct filer_s *filer, GError **err)
{
	gint64 in64, out64;
	gdouble in_idle, out_idle;
	GHashTable *ht_disk2idle;
	
	GList *l;
	GHashTableIter iter;
	GHashTable *ht_disk_counters;
	gpointer k, v;

	XTRACE("Entering");
	
	if (!netapp_refresh_fixed_filer_data(filer, err)) {
		GSETERROR(err, "Uncomplete or too old filer data");
		LOG_RETURN(FALSE, "Failure (uncomplete info)");
	}

	/* get CPU-idle */
	if (!snmp_get_template_int(filer->ctx->session, oid_cpuIdle, oid_cpuIdle_size,
			0, &(filer->ctx->variable.cpu_idle), err)) {
		GSETERROR(err, "Failed to get network output on interface %d", filer->ctx->fixed.net_itf_index);
		LOG_RETURN(FALSE, "Failure (oid_ifNetOut)");
	}
	XTRACE("cpuIdle = %"G_GINT64_FORMAT, filer->ctx->variable.cpu_idle);
	
	/* compute IO-idle */
	if (!snmp_get_template_int(filer->ctx->session, oid_ifNetIn, oid_ifNetIn_size,
			filer->ctx->fixed.net_itf_index, &in64, err)) {
		GSETERROR(err, "Failed to get network input on interface %d", filer->ctx->fixed.net_itf_index);
		LOG_RETURN(FALSE, "Failure (oid_ifNetIn)");
	}
	XTRACE("ifNetIn = %"G_GINT64_FORMAT, in64);
	
	if (!snmp_get_template_int(filer->ctx->session, oid_ifNetOut, oid_ifNetOut_size,
			filer->ctx->fixed.net_itf_index, &out64, err)) {
		GSETERROR(err, "Failed to get network output on interface %d", filer->ctx->fixed.net_itf_index);
		LOG_RETURN(FALSE, "Failure (oid_ifNetOut)");
	}
	XTRACE("ifNetOut = %"G_GINT64_FORMAT, out64);
	
	if (filer->ctx->variable.net_in_last > in64)
		in_idle = 99.0;
	else {
		in_idle = in64 - filer->ctx->variable.net_in_last;
		in_idle /= 1.0 * filer->ctx->fixed.net_in_max;
		in_idle = 100.0 * (1.0 - in_idle);
	}

	if (filer->ctx->variable.net_out_last > out64)
		out_idle = 99.0;
	else {
		out_idle = out64 - filer->ctx->variable.net_out_last;
		out_idle /= 1.0 * filer->ctx->fixed.net_out_max;
		out_idle = 100.0 * (1.0 - out_idle);
	}

	filer->ctx->variable.net_idle = floor(MIN(in_idle,out_idle));
	filer->ctx->variable.net_out_last = out64;
	filer->ctx->variable.net_in_last = in64;

	/* --------------------- */
	/* Collect the disk-idle */
	/* --------------------- */
	if (!filer->ctx->variable.aggr2idle)
		filer->ctx->variable.aggr2idle = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);

	ht_disk2idle = zapi_get_disk2idle(filer->ctx->na_session, err);
	if (!ht_disk2idle) {
		GSETERROR(err,"Failed to collect the filer's disk-idle");
		LOG_RETURN(FALSE,"Failure (Disk-idle)");
	}

	ht_disk_counters = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
	
	/* reset the counters and accumulators */
	for (l=filer->ctx->fixed.aggregates; l ; l=l->next) {
		g_hash_table_insert(ht_disk_counters, g_strdup(l->data), GINT_TO_POINTER(0));
		g_hash_table_insert(filer->ctx->variable.aggr2idle, g_strdup(l->data), GINT_TO_POINTER(0));
	}
	
	g_hash_table_iter_init(&iter, ht_disk2idle);
	while (g_hash_table_iter_next(&iter,&k,&v)) {
		gchar *aggr_name;
		
		aggr_name = g_hash_table_lookup(filer->ctx->fixed.disk2aggr, k);
		if (aggr_name) {
			gpointer p_count, p_sum;
			gint count, sum;

			p_count = g_hash_table_lookup(ht_disk_counters, aggr_name);
			p_sum = g_hash_table_lookup(filer->ctx->variable.aggr2idle, aggr_name);

			count = GPOINTER_TO_INT(p_count) + 1;
			sum = GPOINTER_TO_INT(p_sum) + GPOINTER_TO_INT(v);
			
			g_hash_table_insert(ht_disk_counters, aggr_name, GINT_TO_POINTER(count));
			g_hash_table_insert(filer->ctx->variable.aggr2idle, g_strdup(aggr_name), GINT_TO_POINTER(sum));
			XTRACE("aggr[%s] count[%d] sum[%d]", aggr_name, count, sum);
		}
	}

	for (l=filer->ctx->fixed.aggregates; l ; l=l->next) {
		gchar *aggr_name;
		gpointer p_count, p_sum;
		gint idle;
		
		aggr_name = l->data;
		
		p_count = g_hash_table_lookup(ht_disk_counters, aggr_name);
		p_sum = g_hash_table_lookup(filer->ctx->variable.aggr2idle, aggr_name);

		idle = 0;
		if (p_count && p_sum)
			idle = GPOINTER_TO_INT(p_sum) / GPOINTER_TO_INT(p_count);
		
		XTRACE("TOTAL : aggr[%s] sum[%d] count[%d] idle=[%d]", aggr_name,
			GPOINTER_TO_INT(p_sum), GPOINTER_TO_INT(p_count), idle);

		g_hash_table_insert(filer->ctx->variable.aggr2idle, g_strdup(aggr_name), GINT_TO_POINTER(idle));
	}

	g_hash_table_destroy(ht_disk_counters);

	/* Well... everything seems to have heppened fine! */
	LOG_RETURN(TRUE,"Success (idle=%"G_GINT64_FORMAT" out=%"G_GINT64_FORMAT" in=%"G_GINT64_FORMAT")",
		filer->ctx->variable.net_idle, out64, in64);
}