Esempio n. 1
0
static int daq2_handle_driver(const char *attrib, const char *value)
{
	if (MATCH_ATTRIB("dds_mode")) {
		dac_data_manager_set_dds_mode(dac_tx_manager,
				DAC_DEVICE, 1, atoi(value));
	} else if (!strncmp(attrib, "tx_channel_", sizeof("tx_channel_") - 1)) {
		int tx = atoi(attrib + sizeof("tx_channel_") - 1);
		dac_data_manager_set_tx_channel_state(
				dac_tx_manager, tx, !!atoi(value));
	} else if (MATCH_ATTRIB("dac_buf_filename")) {
		if (dac_data_manager_get_dds_mode(dac_tx_manager,
					DAC_DEVICE, 1) == DDS_BUFFER)
			dac_data_manager_set_buffer_chooser_filename(
					dac_tx_manager, value);
	} else if (MATCH_ATTRIB("SYNC_RELOAD")) {
		if (can_update_widgets) {
			rx_update_values();
			tx_update_values();
			dac_data_manager_update_iio_widgets(dac_tx_manager);
		}
	} else {
		return -EINVAL;
	}

	return 0;
}
Esempio n. 2
0
static int dmm_handle_driver(struct osc_plugin *plugin, const char *attrib, const char *value)
{
	GtkTreeIter iter;
	char *device, *channel, tmp[256];
	gboolean loop;
	unsigned int enabled;

	if (MATCH_ATTRIB("device_list")) {
		GtkTreeModel *model = GTK_TREE_MODEL(device_list_store);
		loop = gtk_tree_model_get_iter_first(model, &iter);
		while (loop) {
			gtk_tree_model_get(model, &iter, 0,
					&device, 1, &enabled, -1);
			/* load/restore */
			if (strstr(value, device)) {
				enabled = value[strlen(value) - 1] == '1';
				gtk_list_store_set(device_list_store,
						&iter, 1, enabled, -1);
			}
			g_free(device);
			loop = gtk_tree_model_iter_next(model, &iter);
		}
		build_channel_list();

	} else if (MATCH_ATTRIB("channel_list")) {
		GtkTreeModel *model = GTK_TREE_MODEL(channel_list_store);
		loop = gtk_tree_model_get_iter_first(model, &iter);
		while (loop) {
			gtk_tree_model_get(model, &iter, 1,
					&enabled, 2, &device, 3, &channel, -1);
			/* load/restore */
			sprintf(tmp, "%s:%s", device, channel);
			if (strstr(value, tmp)) {
				enabled = 1;
				gtk_list_store_set(channel_list_store,
					&iter, 1, enabled, -1);
			}
			g_free(channel);
			g_free(device);
			loop = gtk_tree_model_iter_next(model, &iter);
		}

	} else if (MATCH_ATTRIB("running")) {
		/* load/restore */
		gtk_toggle_tool_button_set_active(
				GTK_TOGGLE_TOOL_BUTTON(dmm_button),
				!strcmp(value, "Yes"));
	} else {
		return -EINVAL;
	}

	return 0;
}
Esempio n. 3
0
static int pr_config_handle_driver(const char *attrib, const char *value)
{
	if (MATCH_ATTRIB("config_file")) {
		pr_config_file_apply(value);
	} else if (MATCH_ATTRIB("adc_active")) {
		gtk_combo_box_set_active(GTK_COMBO_BOX(regmap_select),
				atoi(value) ? ADC_REGMAP : DAC_REGMAP);
	} else {
		return -EINVAL;
	}

	return 0;
}
static int fmcomms2adv_handle_driver(struct osc_plugin *plugin, const char *attrib, const char *value)
{
	int ret = 0;

	if (MATCH_ATTRIB("calibrate")) {
		/* Set a timer for 20 seconds that calibration should succeed within. */
		struct timespec ts_current, ts_end;
		unsigned long long nsecs;
		clock_gettime(CLOCK_MONOTONIC, &ts_current);
		nsecs = ts_current.tv_nsec + (20000 * pow(10.0, 6));
		ts_end.tv_sec = ts_current.tv_sec + (nsecs / pow(10.0, 9));
		ts_end.tv_nsec = nsecs % (unsigned long long) pow(10.0, 9);

		do_calibration(NULL, NULL);
		while (!auto_calibrate && (timespeccmp(&ts_current, &ts_end, >) == 0)) {
			gtk_main_iteration();
			clock_gettime(CLOCK_MONOTONIC, &ts_current);
		}

		/* Calibration timed out or failed, probably running an old board
		 * without an ADF5355 on it.
		 */
		if (auto_calibrate < 0) {
			fprintf(stderr, "FMCOMMS5 calibration failed.\n");
			ret = -1;
		}

		/* reset calibration completion flag */
		auto_calibrate = 0;
	} else if (MATCH_ATTRIB("SYNC_RELOAD") && atoi(value)) {
static char *handle_item(struct osc_plugin *plugin, const char *attrib,
			 const char *value)
{
	int i;

	if (MATCH_ATTRIB(SYNC_RELOAD)) {
		if (value) {
			for (i = 0; i < ARRAY_SIZE(attrs); i++)
				update_widget(builder, &attrs[i]);
			gtk_button_clicked(GTK_BUTTON(gtk_builder_get_object(builder,
					"initialize")));
		} else {
			return "1";
		}
	} else {
		if (value) {
			printf("Unhandled tokens in ini file,\n"
				"\tSection %s\n\tAtttribute : %s\n\tValue: %s\n",
				"FMComms2 Advanced", attrib, value);
			return "FAIL";
		}
	}

	return NULL;
}
Esempio n. 6
0
static int fmcomms2_handle_driver(const char *attrib, const char *value)
{
	if (MATCH_ATTRIB("load_fir_filter_file")) {
		if (value[0]) {
			load_fir_filter(value);
			gtk_file_chooser_set_filename(
					GTK_FILE_CHOOSER(filter_fir_config),
					value);
		}
	} else if (MATCH_ATTRIB("dds_mode_tx1")) {
		dac_data_manager_set_dds_mode(dac_tx_manager,
				DDS_DEVICE, 1, atoi(value));
	} else if (MATCH_ATTRIB("dds_mode_tx2")) {
		dac_data_manager_set_dds_mode(dac_tx_manager,
				DDS_DEVICE, 2, atoi(value));
	} else if (MATCH_ATTRIB("global_settings_show")) {
		gtk_toggle_tool_button_set_active(
				section_toggle[SECTION_GLOBAL], !!atoi(value));
		hide_section_cb(section_toggle[SECTION_GLOBAL],
				section_setting[SECTION_GLOBAL]);
	} else if (MATCH_ATTRIB("tx_show")) {
		gtk_toggle_tool_button_set_active(
				section_toggle[SECTION_TX], !!atoi(value));
		hide_section_cb(section_toggle[SECTION_TX],
				section_setting[SECTION_TX]);
	} else if (MATCH_ATTRIB("rx_show")) {
		gtk_toggle_tool_button_set_active(
				section_toggle[SECTION_RX], !!atoi(value));
		hide_section_cb(section_toggle[SECTION_RX],
				section_setting[SECTION_RX]);
	} else if (MATCH_ATTRIB("fpga_show")) {
		gtk_toggle_tool_button_set_active(
				section_toggle[SECTION_FPGA], !!atoi(value));
		hide_section_cb(section_toggle[SECTION_FPGA],
				section_setting[SECTION_FPGA]);
	} else if (!strncmp(attrib, "tx_channel_", sizeof("tx_channel_") - 1)) {
		int tx = atoi(attrib + sizeof("tx_channel_") - 1);
		dac_data_manager_set_tx_channel_state(
				dac_tx_manager, tx, !!atoi(value));
	} else if (MATCH_ATTRIB("dac_buf_filename")) {
		dac_data_manager_set_buffer_chooser_filename(
				dac_tx_manager, value);
	} else if (MATCH_ATTRIB("SYNC_RELOAD")) {
		if (can_update_widgets)
			reload_button_clicked(NULL, NULL);
	} else {
		return -EINVAL;
	}

	return 0;
}
static int ad9739a_handle_driver(struct osc_plugin *plugin, const char *attrib, const char *value)
{
	if (MATCH_ATTRIB("dds_mode")) {
		dac_data_manager_set_dds_mode(dac_tx_manager,
				DAC_DEVICE, 1, atoi(value));
	} else if (!strncmp(attrib, "tx_channel_", sizeof("tx_channel_") - 1)) {
		int tx = atoi(attrib + sizeof("tx_channel_") - 1);
		dac_data_manager_set_tx_channel_state(
				dac_tx_manager, tx, !!atoi(value));
	} else if (MATCH_ATTRIB("dac_buf_filename")) {
		if (dac_data_manager_get_dds_mode(dac_tx_manager,
					DAC_DEVICE, 1) == DDS_BUFFER)
			dac_data_manager_set_buffer_chooser_filename(
					dac_tx_manager, value);
	} else if (MATCH_ATTRIB("SYNC_RELOAD")) {
		if (can_update_widgets) {
			reload_button_clicked(NULL, NULL);
		}
	} else {
		return -EINVAL;
	}

	return 0;
}
Esempio n. 8
0
static int fmcomms2adv_handle_driver(const char *attrib, const char *value)
{
	if (MATCH_ATTRIB("calibrate")) {
		do_calibration(NULL, NULL);

		while (!auto_calibrate)
			gtk_main_iteration();
	} else {
		fprintf(stderr, "Unknown token in ini file; key:'%s' value:'%s'\n",
				attrib, value);
		return -EINVAL;
	}

	return 0;
}
Esempio n. 9
0
static char *scpi_handle_profile(struct osc_plugin *plugin, const char *attrib,
		const char *value)
{
	gchar **elems, **min_max;
	char *buf;
	int i;
	double lvl;
	long long j;
	FILE *fd;

	if (value)
		buf = NULL;
	else {
		buf = malloc(128);
		memset(buf, 0, 128);
	}

	current_instrument = NULL;

	elems = g_strsplit(attrib, ".", 0);
	if (!strncmp(elems[0], "rx", 2))
		current_instrument = &spectrum_analyzer;
	if (!strncmp(elems[0], "tx", 2))
		current_instrument = &signal_generator;

	if (!current_instrument)
		return NULL;

	if (strcmp(elems[1], SERIAL_TOK) == 0) {
		if (value) {
			if (atoi(value) == 1)
				current_instrument->serial = TRUE;
		} else {
			if (current_instrument->serial)
				sprintf(buf, "1");
		}
	} else if (strcmp(elems[1], NET_TOK) == 0) {
		if (value) {
			if (atoi(value) == 1)
				current_instrument->network = TRUE;
		} else {
			if (current_instrument->network)
				sprintf(buf, "1");
		}
	} else if (strcmp(elems[1], REGEX_TOK) == 0) {
		if (value) {
			current_instrument->id_regex = strdup(value);
		} else {
			if (current_instrument->id_regex)
				sprintf(buf, "%s", current_instrument->id_regex);
		}
	} else if (strcmp(elems[1], IP_TOK) == 0) {
		if (value) {
			current_instrument->ip_address = strdup(value);
		} else {
			if (current_instrument->ip_address && current_instrument->network)
				sprintf(buf, "%s", current_instrument->ip_address);
		}
	} else if (strcmp(elems[1], TTY_TOK) == 0) {
		if (value) {
			current_instrument->tty_path = strdup(value);
		} else {
			if (current_instrument->tty_path && current_instrument->serial)
				sprintf(buf, "%s", current_instrument->tty_path);
		}
	} else if (strcmp(elems[1], GPIB_TOK) == 0) {
		if (value) {
			current_instrument->gpib_addr = atoi(value);
		} else {
			if (current_instrument->gpib_addr && current_instrument->serial)
				sprintf(buf, "%i", current_instrument->gpib_addr);
		}
	} else
	/* There are some things testers need to add by hand to do things */
	if (strcmp(elems[1], CON_TOK) == 0) {
		if (value) {
			if (atoi(value) == 1)
				if (scpi_connect(current_instrument) != 0)
					return "FAIL";
		}
		/* We don't save the connect state */
	} else if (MATCH_ATTRIB("tx.freq")) {
		if (value)
			tx_freq_set_Hz(&signal_generator, atoll(value));
		/* We don't save the frequency */
	} else if (MATCH_ATTRIB("tx.mag")) {
		if (value)
			tx_mag_set_dBm(&signal_generator, atof(value));
		/* Don't save the magintude */
	} else if (MATCH_ATTRIB("tx.on")) {
		if (value)
			tx_output_set(&signal_generator, atoi(value));
		/* Don't save the on/off state */
	} else if (MATCH_ATTRIB("rx.setup")) {
		if (value)
			scpi_rx_setup(&spectrum_analyzer);
	} else if (MATCH_ATTRIB("rx.center")) {
		if (value)
			scpi_rx_set_center_frequency(atoll(value));
	} else if (MATCH_ATTRIB("rx.span")) {
		if (value)
			scpi_rx_set_span_frequency(atoll(value));
	} else if (!strncmp(attrib, "rx.marker", strlen("rx.marker"))) {
		if (value) {
			i = atoi(&attrib[strlen("rx.marker")]);
			j = atoll(value);
			if (i && j)
				scpi_rx_set_marker_freq(i, j);
			else
				printf("problems with %s = %s\n", attrib, value);
		}
	} else if (!strncmp(attrib, "rx.log.marker", strlen("rx.log.marker"))) {
		if (value) {
			i = atoi(&attrib[strlen("rx.log.marker")]);
			if (i) {
				scpi_rx_get_marker_level(i, true, &lvl);
				fd = fopen(value, "a");
				if (!fd)
					return NULL;

				fprintf (fd, "%f, ", lvl);
				fclose (fd);
			}
		}
	} else if (!strncmp(attrib, "rx.test.marker", strlen("rx.test.marker"))) {
		if (value) {
			i = atoi(&attrib[strlen("rx.test.marker")]);
			if (i) {
				scpi_rx_get_marker_level(i, true, &lvl);
				min_max = g_strsplit(value, " ", 0);
				if (lvl >= atof(min_max[1]) && lvl <= atof(min_max[0])) {
					printf("Marker%i (%f) didn't match requirements (%f - %f)\n",
						i, lvl, atof(min_max[0]), atof(min_max[1]));
					return "FAIL";
				}
			} else {
				return "FAIL";
			}
		}
	} else {
		printf("Unhandled tokens in ini file,\n"
				"\tSection %s\n\tAtttribute : %s\n\tValue: %s\n",
				"SCPI", attrib, value);
		if (value)
			return "FAIL";
	}

	return buf;
}
Esempio n. 10
0
int cssstat(const char *filename) {
  struct _hash_drv_map map;
  hash_drv_header_t header;
  hash_drv_spam_record_t rec;
  unsigned long filepos = sizeof(struct _hash_drv_header);
  unsigned long nfree = 0, nused = 0;
  unsigned long efree, eused;
  unsigned long extents = 0;
  unsigned long i;

  unsigned long hash_rec_max = HASH_REC_MAX;
  unsigned long max_seek     = HASH_SEEK_MAX;
  unsigned long max_extents  = 0;
  unsigned long extent_size  = HASH_EXTENT_MAX;
  int flags = 0;

  if (READ_ATTRIB("HashRecMax"))
    hash_rec_max = strtol(READ_ATTRIB("HashRecMax"), NULL, 0);

  if (READ_ATTRIB("HashExtentSize"))
    extent_size = strtol(READ_ATTRIB("HashExtentSize"), NULL, 0);

  if (READ_ATTRIB("HashMaxExtents"))
    max_extents = strtol(READ_ATTRIB("HashMaxExtents"), NULL, 0);

  if (MATCH_ATTRIB("HashAutoExtend", "on"))
    flags = HMAP_AUTOEXTEND;

  if (READ_ATTRIB("HashMaxSeek"))
     max_seek = strtol(READ_ATTRIB("HashMaxSeek"), NULL, 0);

  if (_hash_drv_open(filename, &map, 0, max_seek, 
                     max_extents, extent_size, 0, flags))
  {
    return EFAILURE;
  }

  header = map.addr;
  printf("filename %s length %ld\n", filename, (long) map.file_len);

  while(filepos < map.file_len) {
    printf("extent %lu: record length %lu\n", extents, 
      (unsigned long) header->hash_rec_max);
    efree = eused = 0;
    for(i=0;i<header->hash_rec_max;i++) {
      rec = map.addr+filepos;
      if (rec->hashcode) {
        eused++; 
        nused++;
      } else {
        efree++;
        nfree++;
      }
      filepos += sizeof(struct _hash_drv_spam_record);
    }
    header = map.addr + filepos;
    filepos += sizeof(struct _hash_drv_header);
    extents++;

    printf("\textent records used %lu\n", eused);
    printf("\textent records free %lu\n", efree);
  }

  _hash_drv_close(&map);

  printf("total database records used %lu\n", nused);
  printf("total database records free %lu\n", nfree);
  printf("total extents               %lu\n", extents);
  return 0;
}
Esempio n. 11
0
int
dspam_init_driver (DRIVER_CTX *DTX)
{
  DSPAM_CTX *CTX;
  char *HashConcurrentUser;
#ifdef DAEMON
   unsigned long connection_cache = 1;
#endif

  if (DTX == NULL) 
    return 0;

  CTX = DTX->CTX;
  HashConcurrentUser = READ_ATTRIB("HashConcurrentUser");

#ifdef DAEMON

  /*
   *  Stateful concurrent hash databases are preloaded into memory and
   *  shared using a reader-writer lock. At the present moment, only a single
   *  user can be loaded into any instance of the daemon, so it is only useful
   *  if you are running with a system-wide filtering user. 
   */

  if (DTX->flags & DRF_STATEFUL) {
    char filename[MAX_FILENAME_LENGTH];
    hash_drv_map_t map;
    unsigned long hash_rec_max = HASH_REC_MAX;
    unsigned long max_seek     = HASH_SEEK_MAX;
    unsigned long max_extents  = 0;
    unsigned long extent_size  = HASH_EXTENT_MAX;
    int pctincrease = 0;
    int flags = HMAP_AUTOEXTEND;
    int ret, i;

    if (READ_ATTRIB("HashConnectionCache") && !HashConcurrentUser)
      connection_cache = strtol(READ_ATTRIB("HashConnectionCache"), NULL, 0);

    DTX->connection_cache = connection_cache;

    if (READ_ATTRIB("HashRecMax"))
      hash_rec_max = strtol(READ_ATTRIB("HashRecMax"), NULL, 0);

    if (READ_ATTRIB("HashExtentSize"))
      extent_size = strtol(READ_ATTRIB("HashExtentSize"), NULL, 0);

    if (READ_ATTRIB("HashMaxExtents"))
      max_extents = strtol(READ_ATTRIB("HashMaxExtents"), NULL, 0);

    if (!MATCH_ATTRIB("HashAutoExtend", "on"))
      flags = 0;

    if (READ_ATTRIB("HashPctIncrease")) {
      pctincrease = atoi(READ_ATTRIB("HashPctIncrease"));
      if (pctincrease > 100) {
          LOG(LOG_ERR, "HashPctIncrease out of range; ignoring");
          pctincrease = 0;
      }
    }

    if (READ_ATTRIB("HashMaxSeek"))
       max_seek = strtol(READ_ATTRIB("HashMaxSeek"), NULL, 0);

    /* Connection array (just one single connection for hash_drv) */
    DTX->connections = calloc(1, sizeof(struct _ds_drv_connection *) * connection_cache);
    if (DTX->connections == NULL) 
      goto memerr;

    /* Initialize Connections */
    for(i=0;i<connection_cache;i++) {
      DTX->connections[i] = calloc(1, sizeof(struct _ds_drv_connection));
      if (DTX->connections[i] == NULL) 
        goto memerr;

      /* Our connection's storage structure */
      if (HashConcurrentUser) {
        DTX->connections[i]->dbh = calloc(1, sizeof(struct _hash_drv_map));
        if (DTX->connections[i]->dbh == NULL) 
          goto memerr;
        pthread_rwlock_init(&DTX->connections[i]->rwlock, NULL);
      } else {
        DTX->connections[i]->dbh = NULL;
        pthread_mutex_init(&DTX->connections[i]->lock, NULL);
      }
    }

    /* Load concurrent database into resident memory */
    if (HashConcurrentUser) {
      map = (hash_drv_map_t) DTX->connections[0]->dbh;

      /* Tell the server our connection lock will be reader/writer based */
      if (!(DTX->flags & DRF_RWLOCK))
        DTX->flags |= DRF_RWLOCK;

      _ds_userdir_path(filename, DTX->CTX->home, HashConcurrentUser, "css");
      _ds_prepare_path_for(filename);
      LOGDEBUG("preloading %s into memory via mmap()", filename);
      ret = _hash_drv_open(filename, map, hash_rec_max, 
          max_seek, max_extents, extent_size, pctincrease, flags); 

      if (ret) {
        LOG(LOG_CRIT, "_hash_drv_open(%s) failed on error %d: %s", 
                      filename, ret, strerror(errno)); 
        free(DTX->connections[0]->dbh);
        free(DTX->connections[0]);
        free(DTX->connections);
        return EFAILURE;
      }
    }
  }
#endif

  return 0;

#ifdef DAEMON
memerr:
  if (DTX) {
    if (DTX->connections) {
      int i;
      for(i=0;i<connection_cache;i++) {
        if (DTX->connections[i]) 
          free(DTX->connections[i]->dbh);
        free(DTX->connections[i]);
      }
    }
    free(DTX->connections);
  }
  LOG(LOG_CRIT, ERR_MEM_ALLOC);
  return EUNKNOWN;
#endif
  
}
Esempio n. 12
0
int
_ds_init_storage (DSPAM_CTX * CTX, void *dbh)
{
  struct _hash_drv_storage *s = NULL;
  hash_drv_map_t map = NULL;
  int ret;

  if (CTX == NULL)
    return EINVAL;

  if (!CTX->home) {
    LOG(LOG_ERR, ERR_AGENT_DSPAM_HOME);
    return EINVAL;
  }

  if (CTX->flags & DSF_MERGED) {
    LOG(LOG_ERR, ERR_DRV_NO_MERGED);
    return EINVAL;
  }

  if (CTX->storage)
    return EINVAL;

  /* Persistent driver storage */

  s = calloc (1, sizeof (struct _hash_drv_storage));
  if (s == NULL)
  {
    LOG(LOG_CRIT, ERR_MEM_ALLOC);
    return EUNKNOWN;
  }

  /* If running in HashConcurrentUser mode, use existing hash mapping */

  if (dbh) {
    map = dbh;
    s->dbh_attached = 1;
  } else {
    map = calloc(1, sizeof(struct _hash_drv_map));
    if (!map) {
      LOG(LOG_CRIT, ERR_MEM_ALLOC);
      free(s);
      return EUNKNOWN;
    }
    s->dbh_attached = 0;
  }

  s->map = map;

  /* Mapping defaults */

  s->hash_rec_max = HASH_REC_MAX;
  s->max_seek     = HASH_SEEK_MAX;
  s->max_extents  = 0;
  s->extent_size  = HASH_EXTENT_MAX;
  s->pctincrease  = 0;
  s->flags        = HMAP_AUTOEXTEND;

  if (READ_ATTRIB("HashRecMax"))
    s->hash_rec_max = strtol(READ_ATTRIB("HashRecMax"), NULL, 0);

  if (READ_ATTRIB("HashExtentSize"))
    s->extent_size = strtol(READ_ATTRIB("HashExtentSize"), NULL, 0);

  if (READ_ATTRIB("HashMaxExtents"))
    s->max_extents = strtol(READ_ATTRIB("HashMaxExtents"), NULL, 0);

  if (!MATCH_ATTRIB("HashAutoExtend", "on"))
    s->flags = 0;

  if (READ_ATTRIB("HashPctIncrease")) {
    s->pctincrease = atoi(READ_ATTRIB("HashPctIncrease"));
    if (s->pctincrease > 100) {
        LOG(LOG_ERR, "HashPctIncrease out of range; ignoring");
        s->pctincrease = 0;
    }
  }

  if (READ_ATTRIB("HashMaxSeek"))
    s->max_seek = strtol(READ_ATTRIB("HashMaxSeek"), NULL, 0);

  if (!dbh && CTX->username != NULL)
  {
    char db[MAX_FILENAME_LENGTH];
    int lock_result;

    if (CTX->group == NULL)
      _ds_userdir_path(db, CTX->home, CTX->username, "css");
    else
      _ds_userdir_path(db, CTX->home, CTX->group, "css");

    lock_result = _hash_drv_lock_get (CTX, s, 
      (CTX->group) ? CTX->group : CTX->username);
    if (lock_result < 0) 
      goto BAIL;

    ret = _hash_drv_open(db, s->map, s->hash_rec_max, s->max_seek, 
        s->max_extents, s->extent_size, s->pctincrease, s->flags);

    if (ret) {
      _hash_drv_close(s->map);
      free(s);
      return EFAILURE;
    }
  }

  CTX->storage = s;
  s->dir_handles = nt_create (NT_INDEX);

  if (_hash_drv_get_spamtotals (CTX))
  {
    LOGDEBUG ("unable to load totals.  using zero values.");
    memset (&CTX->totals, 0, sizeof (struct _ds_spam_totals));
  }

  return 0;

BAIL:
  free(s);
  return EFAILURE;
}