예제 #1
0
static int
startElement_METRIC(void *data, const char *el, const char **attr)
{
   xmldata_t *xmldata = (xmldata_t *)data;
   ganglia_slope_t slope = GANGLIA_SLOPE_UNSPECIFIED;
   struct xml_tag *xt;
   struct type_tag *tt;
   datum_t *hash_datum = NULL;
   datum_t *rdatum;
   datum_t hashkey, hashval;
   const char *name = NULL;
   const char *metricval = NULL;
   const char *type = NULL;
   int do_summary;
   int i, edge, carbon_ret;
   hash_t *summary;
   Metric_t *metric;

   if (!xmldata->host_alive ) return 0;

   /* Get name for hash key, and val/type for summaries. */
   for(i = 0; attr[i]; i+=2)
      {
         xt = in_xml_list(attr[i], strlen(attr[i]));
         if (!xt) continue;

         switch (xt->tag)
            {
               case NAME_TAG:
                  name = attr[i+1];
                  hashkey.data = (void*) name;
                  hashkey.size =  strlen(name) + 1;
                  break;
               case VAL_TAG:
                  metricval = attr[i+1];
                  break;
               case TYPE_TAG:
                  type = attr[i+1];
                  break;
               case SLOPE_TAG:
                  slope = cstr_to_slope(attr[i+1]);
               default:
                  break;
            }
      }

   metric = &(xmldata->metric);
   memset((void*) metric, 0, sizeof(*metric));

   /* Summarize all numeric metrics */
   do_summary = 0;
   tt = in_type_list(type, strlen(type));
   if (!tt) return 0;

   if (tt->type==INT || tt->type==UINT || tt->type==FLOAT)
      do_summary = 1;

   /* Only keep metric details if we are the authority on this cluster. */
   if (authority_mode(xmldata))
      {
         /* Save the data to a round robin database if the data source is alive
          */
         fillmetric(attr, metric, type);
	 if (metric->dmax && metric->tn > metric->dmax)
            return 0;

         if (do_summary && !xmldata->ds->dead && !xmldata->rval)
            {
                  debug_msg("Updating host %s, metric %s", 
                                  xmldata->hostname, name);
                  if ( gmetad_config.write_rrds == 1 )
                     xmldata->rval = write_data_to_rrd(xmldata->sourcename,
                        xmldata->hostname, name, metricval, NULL,
                        xmldata->ds->step, xmldata->source.localtime, slope);
		  if (gmetad_config.carbon_server) // if the user has specified a carbon server, send the metric to carbon as well
                     carbon_ret=write_data_to_carbon(xmldata->sourcename, xmldata->hostname, name, metricval,xmldata->source.localtime);
            }
         metric->id = METRIC_NODE;
         metric->report_start = metric_report_start;
         metric->report_end = metric_report_end;


         edge = metric->stringslen;
         metric->name = addstring(metric->strings, &edge, name);
         metric->stringslen = edge;

         /* Set local idea of T0. */
         metric->t0 = xmldata->now;
         metric->t0.tv_sec -= metric->tn;

         /* Trim metric structure to the correct length. */
         hashval.size = sizeof(*metric) - GMETAD_FRAMESIZE + metric->stringslen;
         hashval.data = (void*) metric;

         /* Update full metric in cluster host table. */
         rdatum = hash_insert(&hashkey, &hashval, xmldata->host.metrics);
         if (!rdatum)
            {
               err_msg("Could not insert %s metric", name);
            }
      }

   /* Always update summary for numeric metrics. */
   if (do_summary)
      {
         summary = xmldata->source.metric_summary;
         hash_datum = hash_lookup(&hashkey, summary);
         if (!hash_datum)
            {
               if (!authority_mode(xmldata))
                  {
                     metric = &(xmldata->metric);
                     memset((void*) metric, 0, sizeof(*metric));
                     fillmetric(attr, metric, type);
                  }
               /* else we have already filled in the metric above. */
            }
         else
            {
               memcpy(&xmldata->metric, hash_datum->data, hash_datum->size);
               datum_free(hash_datum);
               metric = &(xmldata->metric);

               switch (tt->type)
                  {
                     case INT:
                     case UINT:
                     case FLOAT:
                        metric->val.d += (double)
                                strtod(metricval, (char**) NULL);
                        break;
                     default:
                        break;
                  }
            }

         metric->num++;
         metric->t0 = xmldata->now; /* tell cleanup thread we are using this */

         /* Trim metric structure to the correct length. Tricky. */
         hashval.size = sizeof(*metric) - GMETAD_FRAMESIZE + metric->stringslen;
         hashval.data = (void*) metric;

         /* Update metric in summary table. */
         rdatum = hash_insert(&hashkey, &hashval, summary);
         if (!rdatum) err_msg("Could not insert %s metric", name);
      }
   return 0;
}
예제 #2
0
/* XXX - There is an issue which will cause a failure if there are more than 16
  EXTRA_ELEMENTs.  This is a problem with the size of the data structure that
  is used to hold the metric information.
*/
static int
startElement_EXTRA_ELEMENT (void *data, const char *el, const char **attr)
{
    xmldata_t *xmldata = (xmldata_t *)data;
    int edge;
    struct xml_tag *xt;
    int i, name_off, value_off;
    Metric_t metric;
    char *name = getfield(xmldata->metric.strings, xmldata->metric.name);
    datum_t *rdatum;
    datum_t hashkey, hashval;
    datum_t *hash_datum = NULL;
    
    if (!xmldata->host_alive) 
        return 0;

    /* Only keep extra element details if we are the authority on this cluster. */
    if (!authority_mode(xmldata))
       return 0;

    hashkey.data = (void*) name;
    hashkey.size =  strlen(name) + 1;
    
    hash_datum = hash_lookup (&hashkey, xmldata->host.metrics);
    if (!hash_datum) 
        return 0;
    
    memcpy(&metric, hash_datum->data, hash_datum->size);
    datum_free(hash_datum);

    /* Check to make sure that we don't try to add more
        extra elements than the array can handle.
    */  
    if (metric.ednameslen >= MAX_EXTRA_ELEMENTS) 
    {
        debug_msg("Can not add more extra elements for [%s].  Capacity of %d reached.",
                  name, MAX_EXTRA_ELEMENTS);
        return 0;
    }

    edge = metric.stringslen;
    
    name_off = value_off = -1;
    for(i = 0; attr[i]; i+=2)
    {
        xt = in_xml_list(attr[i], strlen(attr[i]));
        if (!xt) 
            continue;
        switch (xt->tag)
        {
        case NAME_TAG:
            name_off = i;
            break;
        case VAL_TAG:
            value_off = i;
            break;
        default:
            break;
        }
    }
    
    if ((name_off >= 0) && (value_off >= 0)) 
    {
        const char *new_name = attr[name_off+1];
        const char *new_value = attr[value_off+1];

        metric.ednames[metric.ednameslen++] = addstring(metric.strings, &edge, new_name);
        metric.edvalues[metric.edvalueslen++] = addstring(metric.strings, &edge, new_value);
    
        metric.stringslen = edge;
    
        hashkey.data = (void*)name;
        hashkey.size =  strlen(name) + 1;
    
        /* Trim metric structure to the correct length. */
        hashval.size = sizeof(metric) - GMETAD_FRAMESIZE + metric.stringslen;
        hashval.data = (void*) &metric;
    
        /* Update full metric in cluster host table. */
        rdatum = hash_insert(&hashkey, &hashval, xmldata->host.metrics);
        if (!rdatum)
        {
            err_msg("Could not insert %s metric", name);
        }
        else
        {
            hash_t *summary = xmldata->source.metric_summary;
            Metric_t sum_metric;

            /* do not add every SPOOF_HOST element to the summary table.
               if the same metric is SPOOF'd on more than ~MAX_EXTRA_ELEMENTS hosts
               then its summary table is destroyed.
             */
            if ( strlen(new_name) == 10 && !strcasecmp(new_name, SPOOF_HOST) )
                return 0;

            /* only update summary if metric is in hash */
            hash_datum = hash_lookup(&hashkey, summary);

            if (hash_datum) {
                int found = FALSE;

                memcpy(&sum_metric, hash_datum->data, hash_datum->size);
                datum_free(hash_datum);

                for (i = 0; i < sum_metric.ednameslen; i++) {
                    char *chk_name = getfield(sum_metric.strings, sum_metric.ednames[i]);
                    char *chk_value = getfield(sum_metric.strings, sum_metric.edvalues[i]);

                    /* If the name and value already exists, skip adding the strings. */
                    if (!strcasecmp(chk_name, new_name) && !strcasecmp(chk_value, new_value)) {
                        found = TRUE;
                        break;
                    }
                }
                if (!found) {
                    edge = sum_metric.stringslen;
                    sum_metric.ednames[sum_metric.ednameslen++] = addstring(sum_metric.strings, &edge, new_name);
                    sum_metric.edvalues[sum_metric.edvalueslen++] = addstring(sum_metric.strings, &edge, new_value);
                    sum_metric.stringslen = edge;
                }

                /* Trim graph display sum_metric at (352, 208) now or when in startElement_EXTRA_ELEMENT
metric structure to the correct length. Tricky. */
                hashval.size = sizeof(sum_metric) - GMETAD_FRAMESIZE + sum_metric.stringslen;
                hashval.data = (void*) &sum_metric;

                /* Update metric in summary table. */
                rdatum = hash_insert(&hashkey, &hashval, summary);
                if (!rdatum)
                    err_msg("Could not insert summary %s metric", name);
            }
        }
    }
    
    return 0;
}
예제 #3
0
static int
startElement_CLUSTER(void *data, const char *el, const char **attr)
{
   xmldata_t *xmldata = (xmldata_t *)data;
   struct xml_tag *xt;
   datum_t *hash_datum = NULL;
   datum_t hashkey;
   const char *name = NULL;
   int edge;
   int i;
   Source_t *source;

   /* Get name for hash key */
   for(i = 0; attr[i]; i+=2)
      {
         xt = in_xml_list (attr[i], strlen(attr[i]));
         if (!xt) continue;

         if (xt->tag == NAME_TAG)
            name = attr[i+1];
      }

   /* Only keep cluster details if we are the authority on this cluster. */
   if (!authority_mode(xmldata))
      return 0;

   source = &(xmldata->source);
   
   xmldata->sourcename = realloc(xmldata->sourcename, strlen(name)+1);
   strcpy(xmldata->sourcename, name);
   hashkey.data = (void*) name;
   hashkey.size =  strlen(name) + 1;

   hash_datum = hash_lookup(&hashkey, xmldata->root);
   if (!hash_datum)
      {
         memset((void*) source, 0, sizeof(*source));
         
         /* Set the identity of this host. */
         source->id = CLUSTER_NODE;
         source->report_start = source_report_start;
         source->report_end = source_report_end;

         source->authority = hash_create(DEFAULT_CLUSTERSIZE);
         if (!source->authority)
            {
               err_msg("Could not create hash table for cluster %s", name);
               return 1;
            }
         if(gmetad_config.case_sensitive_hostnames == 0)
            hash_set_flags(source->authority, HASH_FLAG_IGNORE_CASE);

         source->metric_summary = hash_create(DEFAULT_METRICSIZE);
         if (!source->metric_summary)
            {
               err_msg("Could not create summary hash for cluster %s", name);
               return 1;
            }
         source->ds = xmldata->ds;
         
         /* Initialize the partial sum lock */
         source->sum_finished = (pthread_mutex_t *) 
                 malloc(sizeof(pthread_mutex_t));
         pthread_mutex_init(source->sum_finished, NULL);

         /* Grab the "partial sum" mutex until we are finished summarizing. */
         pthread_mutex_lock(source->sum_finished);
      }
   else
      {
         memcpy(source, hash_datum->data, hash_datum->size);
         datum_free(hash_datum);

         /* We need this lock before zeroing metric sums. */
         pthread_mutex_lock(source->sum_finished);

         source->hosts_up = 0;
         source->hosts_down = 0;

         hash_foreach(source->metric_summary, zero_out_summary, NULL);
      }

   /* Edge has the same invariant as in fillmetric(). */
   edge = 0;

   source->owner = -1;
   source->latlong = -1;
   source->url = -1;
   /* Fill in cluster attributes. */
   for(i = 0; attr[i]; i+=2)
      {
         xt = in_xml_list (attr[i], strlen(attr[i]));
         if (!xt)
            continue;

         switch( xt->tag )
            {
               case OWNER_TAG:
                  source->owner = addstring(source->strings, &edge, attr[i+1]);
                  break;
               case LATLONG_TAG:
                  source->latlong = addstring(source->strings, 
                                  &edge, attr[i+1]);
                  break;
               case URL_TAG:
                  source->url = addstring(source->strings, &edge, attr[i+1]);
                  break;
               case LOCALTIME_TAG:
                  source->localtime = strtoul(attr[i+1],
                                (char **) NULL, 10);
                  break;
               default:
                  break;
            }
      }
   source->stringslen = edge;
   return 0;
}
예제 #4
0
static int
startElement_HOST(void *data, const char *el, const char **attr)
{
   xmldata_t *xmldata = (xmldata_t *)data;
   datum_t *hash_datum = NULL;
   datum_t *rdatum;
   datum_t hashkey, hashval;
   struct xml_tag *xt;
   uint32_t tn=0;
   uint32_t tmax=0;
   uint32_t reported=0;
   const char *name = NULL;
   int edge;
   int i;
   Host_t *host;
   hash_t *hosts;  

   /* Check if the host is up. */
   for (i = 0; attr[i]; i+=2)
      {
         xt = in_xml_list (attr[i], strlen(attr[i]));
         if (!xt) continue;

         if (xt->tag == REPORTED_TAG)
            reported = strtoul(attr[i+1], (char **)NULL, 10);
         else if (xt->tag == TN_TAG)
            tn = atoi(attr[i+1]);
         else if (xt->tag == TMAX_TAG)
            tmax = atoi(attr[i+1]);
         else if (xt->tag == NAME_TAG)
            name = attr[i+1];
      }

   /* Is this host alive? For pre-2.5.0, we use the 60-second 
    * method, otherwise we use the host's TN and TMAX attrs.
    */
   xmldata->host_alive = (xmldata->old || !tmax) ?
      abs(xmldata->source.localtime - reported) < 60 :
      tn < tmax * 4;

   if (xmldata->host_alive)
      xmldata->source.hosts_up++;
   else
      xmldata->source.hosts_down++;

   /* Only keep host details if we are the authority on this cluster. */
   if (!authority_mode(xmldata))
      return 0;

   host = &(xmldata->host);

   /* Use node Name for hash key (Query processing
    * requires a name key).
    */
   xmldata->hostname = realloc(xmldata->hostname, strlen(name)+1);
   strcpy(xmldata->hostname, name);

   /* Convert name to lower case - host names can't be
    * case sensitive
    */
   /*for(i = 0; name[i] != 0; i++)
       xmldata->hostname[i] = tolower(name[i]);
   xmldata->hostname[i] = 0; */

   hashkey.data = (void*) name;
   hashkey.size =  strlen(name) + 1;

   hosts = xmldata->source.authority;
   hash_datum = hash_lookup (&hashkey, hosts);
   if (!hash_datum)
      {
         memset((void*) host, 0, sizeof(*host));

         host->id = HOST_NODE;
         host->report_start = host_report_start;
         host->report_end = host_report_end;

         /* Only create one hash table for the host's metrics. Not user/builtin
          * like gmond. */
         host->metrics = hash_create(DEFAULT_METRICSIZE);
         if (!host->metrics)
            {
               err_msg("Could not create metric hash for host %s", name);
               return 1;
            }
      }
   else
      {
         /* Copy the stored host data into our Host buffer in xmldata. */
         memcpy(host, hash_datum->data, hash_datum->size);
         datum_free(hash_datum);
      }

   /* Edge has the same invariant as in fillmetric(). */
   edge = 0;

   host->location = -1;
   host->tags = -1;
   host->reported = reported;
   host->tn = tn;
   host->tmax = tmax;
   /* sacerdoti: Host TN tracks what gmond sees. TN=0 when gmond received last
    * heartbeat from node. Works because clocks move at same speed, and TN is
    * a relative timespan. */
   host->t0 = xmldata->now;
   host->t0.tv_sec -= host->tn;

   /* We will store this host in the cluster's authority table. */
   for(i = 0; attr[i]; i+=2)
      {
         xt = in_xml_list (attr[i], strlen(attr[i]));
         if (!xt) continue;

         switch( xt->tag )
            {
               case IP_TAG:
                  host->ip = addstring(host->strings, &edge, attr[i+1]);
                  break;
               case DMAX_TAG:
                  host->dmax = strtoul(attr[i+1], (char **)NULL, 10);
                  break;
               case LOCATION_TAG:
                  host->location = addstring(host->strings, &edge, attr[i+1]);
                  break;
	       case TAGS_TAG:
		  host->tags = addstring(host->strings, &edge, attr[i+1]);
		  break;
               case STARTED_TAG:
                  host->started = strtoul(attr[i+1], (char **)NULL, 10);
                  break;
               default:
                  break;
            }
      }
   host->stringslen = edge;

   /* Trim structure to the correct length. */
   hashval.size = sizeof(*host) - GMETAD_FRAMESIZE + host->stringslen;
   hashval.data = host;

   /* We dont care if this is an insert or an update. */
   rdatum = hash_insert(&hashkey, &hashval, hosts);
   if (!rdatum) {
         err_msg("Could not insert host %s", name);
         return 1;
   }
   return 0;
}
예제 #5
0
static int
startElement_GRID(void *data, const char *el, const char **attr)
{
   xmldata_t *xmldata = (xmldata_t *)data;
   struct xml_tag *xt;
   datum_t *hash_datum = NULL;
   datum_t hashkey;
   const char *name = NULL;
   int edge;
   int i;
   Source_t *source;

   /* In non-scalable mode, we ignore GRIDs. */
   if (!gmetad_config.scalable_mode) 
      return 0;

   /* We do not keep info on nested grids. */
   if (authority_mode(xmldata))
      {
         /* Get name for hash key */
         for(i = 0; attr[i]; i+=2)
            {
               xt = in_xml_list (attr[i], strlen(attr[i]));
               if (!xt) continue;

               if (xt->tag == NAME_TAG)
                  {
                     name = attr[i+1];
                     xmldata->sourcename = 
                             realloc(xmldata->sourcename, strlen(name)+1);
                     strcpy(xmldata->sourcename, name);
                     hashkey.data = (void*) name;
                     hashkey.size =  strlen(name) + 1;
                  }
            }

         source = &(xmldata->source);

         /* Query the hash table for this cluster */
         hash_datum = hash_lookup(&hashkey, xmldata->root);
         if (!hash_datum)  
            {  /* New Cluster */
               memset((void*) source, 0, sizeof(*source));

               source->id = GRID_NODE;
               source->report_start = source_report_start;
               source->report_end = source_report_end;

               source->metric_summary = hash_create(DEFAULT_METRICSIZE);
               if (!source->metric_summary)
                  {
                     err_msg("Could not create summary hash for cluster %s", 
                                     name);
                     return 1;
                  }
               source->ds = xmldata->ds;

               /* Initialize the partial sum lock */
               source->sum_finished = (pthread_mutex_t *) 
                       malloc(sizeof(pthread_mutex_t));
               pthread_mutex_init(source->sum_finished, NULL);

               /* Grab the "partial sum" mutex until we are finished
                * summarizing. */
               pthread_mutex_lock(source->sum_finished);
            }
         else
            {  /* Found Cluster. Put into our Source buffer in xmldata. */
               memcpy(source, hash_datum->data, hash_datum->size);
               datum_free(hash_datum);

               /* Grab the "partial sum" mutex until we are finished
                * summarizing. Needs to be done asap.*/
               pthread_mutex_lock(source->sum_finished);

               source->hosts_up = 0;
               source->hosts_down = 0;

               hash_foreach(source->metric_summary, zero_out_summary, NULL);
            }

         /* Edge has the same invariant as in fillmetric(). */
         edge = 0;

         /* Fill in grid attributes. */
         for(i = 0; attr[i]; i+=2)
            {
               xt = in_xml_list(attr[i], strlen(attr[i]));
               if (!xt)
                  continue;

               switch( xt->tag )
                  {
                     case AUTHORITY_TAG:
                        source->authority_ptr = addstring(source->strings, 
                                        &edge, attr[i+1]);
                        break;
                     case LOCALTIME_TAG:
                        source->localtime = strtoul(attr[i+1], 
                                        (char **) NULL, 10);
                        break;
                     default:
                        break;
                  }
            }
         source->stringslen = edge;
      }

   /* Must happen after all processing of this tag. */
   xmldata->grid_depth++;
   debug_msg("Found a <GRID>, depth is now %d", xmldata->grid_depth);

   return 0;
}
예제 #6
0
static int
startElement_METRICS(void *data, const char *el, const char **attr)
{
   xmldata_t *xmldata = (xmldata_t *)data;
   struct xml_tag *xt;
   struct type_tag *tt;
   datum_t *hash_datum = NULL;
   datum_t *rdatum;
   datum_t hashkey, hashval;
   const char *name = NULL;
   const char *metricval = NULL;
   const char *metricnum = NULL;
   const char *type = NULL;
   int i;
   hash_t *summary;
   Metric_t *metric;

   /* In non-scalable mode, we do not process summary data. */
   if (!gmetad_config.scalable_mode) return 0;
   
   /* Get name for hash key, and val/type for summaries. */
   for(i = 0; attr[i]; i+=2)
      {
         xt = in_xml_list(attr[i], strlen(attr[i]));
         if (!xt) continue;

         switch (xt->tag)
            {
               case NAME_TAG:
                  name = attr[i+1];
                  hashkey.data = (void*) name;
                  hashkey.size =  strlen(name) + 1;
                  break;
               case TYPE_TAG:
                  type = attr[i+1];
                  break;
               case SUM_TAG:
                  metricval = attr[i+1];
                  break;
               case NUM_TAG:
                  metricnum = attr[i+1];
               default:
                  break;
            }
      }

   summary = xmldata->source.metric_summary;
   hash_datum = hash_lookup(&hashkey, summary);
   if (!hash_datum)
      {
         metric = &(xmldata->metric);
         memset((void*) metric, 0, sizeof(*metric));
         fillmetric(attr, metric, type);
      }
   else
      {
         memcpy(&xmldata->metric, hash_datum->data, hash_datum->size);
         datum_free(hash_datum);
         metric = &(xmldata->metric);

         tt = in_type_list(type, strlen(type));
         if (!tt) return 0;
         switch (tt->type)
               {
                  case INT:
                  case UINT:
                  case FLOAT:
                     metric->val.d += (double)
                             strtod(metricval, (char**) NULL);
                     break;
                  default:
                     break;
               }
            metric->num += atoi(metricnum);
         }

   /* Update metric in summary table. */
   hashval.size = sizeof(*metric) - GMETAD_FRAMESIZE + metric->stringslen;
   hashval.data = (void*) metric;

   summary = xmldata->source.metric_summary;
   rdatum = hash_insert(&hashkey, &hashval, summary);
   if (!rdatum) {
      err_msg("Could not insert %s metric", name);
      return 1;
   }
   return 0;
}
예제 #7
0
파일: hdbm.c 프로젝트: bwang2453/nwchem_csx
int hdbm_file_copy(const char *filefrom, const char *fileto)
/*
  Delete any original content of fileto and then copy the 
  database in filefrom into fileto.  Both files are closed
  at the end of the operation.
  */
{
    hdbm dbfrom, dbto;
    datum key, value;
    int available;
    FILE *file;

    /* Truncate the to-file to zero length or create it ... this is
       better than unlinking it since it may be a link or a special file */
    
    if (!(file = fopen(fileto, "w"))) {
	(void) fprintf(stderr,"hdbm_file_copy: failed to truncate (to) %s\n", 
		       fileto);
	return 0;
    }
    (void) fclose(file);
    
    /* Open the databases */

    if (!hdbm_open(filefrom, 1, &dbfrom)) {
	(void) fprintf(stderr,"hdbm_file_copy: failed to open (from) %s\n", 
		       filefrom);
	return 0;
    }
    if (!hdbm_open(fileto, 1, &dbto)) {
	(void) fprintf(stderr,"hdbm_file_copy: failed to open (to) %s\n", fileto);
	(void) hdbm_close(dbfrom);
	return 0;
    }
    
    /* Do the copy */
    
    for (available = hdbm_first_key(dbfrom, &key);
	 available;
	 available = hdbm_next_key(dbfrom, &key)) {
	
	int ok = hdbm_read(dbfrom, key, &value);
	if (!ok)
	    (void) fprintf(stderr, "hdbm_file_copy: failed reading from %s\n", 
			   filefrom);
	else {
	    ok = hdbm_insert(dbto, key, value);
	    datum_free(key); datum_free(value);
	    if (!ok)
		(void) fprintf(stderr, "hdbm_file_copy: failed writing to %s\n", 
			       fileto);
	}
	if (!ok) {
	    (void) hdbm_close(dbfrom);
	    (void) hdbm_close(dbto);
	    return 0;
	}
    } 
    
    return (hdbm_close(dbfrom) && hdbm_close(dbto));
}
예제 #8
0
datum_t *
hash_insert (datum_t *key, datum_t *val, hash_t *hash)
{
  size_t i;
  node_t *bucket;

  i = hashval(key, hash);

  ck_rwlock_write_lock(&hash->lock[i]);

  bucket = &hash->node[i];
  if (bucket->key == NULL)
     {
        /* This bucket hasn't been used yet */
        bucket->key  = datum_dup(key);
        if ( bucket->key == NULL )
           {
              free(bucket);
              bucket = NULL;
              ck_rwlock_write_unlock(&hash->lock[i]);
              return NULL;
           } 
        bucket->val = datum_dup(val);
        if ( bucket->val == NULL )
           {
              free(bucket);
              bucket = NULL;
              ck_rwlock_write_unlock(&hash->lock[i]);
              return NULL;
           }
        ck_rwlock_write_unlock(&hash->lock[i]);
        return bucket->val;
     }

  /* This node in the hash is already in use.  
     Collision or new data for existing key. */

  for (; bucket != NULL; bucket = bucket->next)
      {
         if(bucket->key && hash_keycmp(hash, bucket->key, key))
            {
               /* New data for an existing key */

               /* Make sure we have enough space */
               if ( bucket->val->size < val->size )
                  {
                     /* Make sure we have enough room */
                     if(! (bucket->val->data = realloc(bucket->val->data, val->size)) )
                        {
                           ck_rwlock_write_unlock(&hash->lock[i]);
                           return NULL;
                        }
                     bucket->val->size = val->size;
                  }

               memset( bucket->val->data, 0, val->size );
               memcpy( bucket->val->data, val->data, val->size );
               ck_rwlock_write_unlock(&hash->lock[i]);
               return bucket->val;
            }
      }
                    
  /* It's a Hash collision... link it in the collided bucket */
  bucket = calloc(1, sizeof(*bucket));
  if (bucket == NULL)
     {
        ck_rwlock_write_unlock(&hash->lock[i]);
        return NULL;
     }
  bucket->key = datum_dup (key);
  if ( bucket->key == NULL )
     {
        free(bucket);
        ck_rwlock_write_unlock(&hash->lock[i]);
        return NULL;
     }
  bucket->val = datum_dup (val);
  if ( bucket->val == NULL )
     {
        datum_free(bucket->key);
        free(bucket);
        ck_rwlock_write_unlock(&hash->lock[i]);
        return NULL;
     }  

  
  bucket->next = hash->node[i].next;
  hash->node[i].next = bucket;
  ck_rwlock_write_unlock(&hash->lock[i]);
  return bucket->val;
}
예제 #9
0
/* sacerdoti: This function does a tree walk while respecting the filter path.
 * Will return valid XML even if we have chosen a subtree. Since tree depth is
 * bounded, this function guarantees O(1) search time.
 */
static int
process_path (client_t *client, char *path, datum_t *myroot, datum_t *key)
{
    char *p, *q, *pathend;
    char *element;
    int rc, len;
    datum_t *found;
    datum_t findkey;
    Generic_t *node;

    node = (Generic_t*) myroot->data;

    /* Base case */
    if (!path)
    {
        /* Show the subtree. */
        applyfilter(client, node);

        if (node->children)
        {
            /* Allow this to stop early (return code = 1) */
            hash_foreach(node->children, tree_report, (void*) client);
        }
        return 0;
    }

    /* Start tag */
    if (node->report_start)
    {
        rc = node->report_start(node, key, client, NULL);
        if (rc) return 1;
    }

    /* Subtree body */
    pathend = path + strlen(path);
    p = path+1;

    if (!node->children || p >= pathend)
        rc = process_path(client, 0, myroot, NULL);
    else
    {
        /* Advance to the next element along path. */
        q = strchr(p, '/');
        if (!q) q=pathend;

        /* len is limited in size by REQUESTLEN through readline() */
        len = q-p;
        element = malloc(len + 1);
        if ( element == NULL )
            return 1;

        strncpy(element, p, len);
        element[len] = '\0';

        /* err_msg("Skipping to %s (%d)", element, len); */

        /* look for element in hash table. */
        findkey.data = element;
        findkey.size = len+1;
        found = hash_lookup(&findkey, node->children);
        if (found)
        {
            /* err_msg("Found %s", element); */

            rc = process_path(client, q, found, &findkey);

            datum_free(found);
        }
        else if (!client->http)
        {
            /* report this element */
            rc = process_path(client, 0, myroot, NULL);
        }
        else if (!strcmp(element, "*"))
        {
            /* wildcard detected -> process every child */
            struct request_context ctxt;
            ctxt.path = q;
            ctxt.client = client;
            hash_foreach(node->children, process_path_adapter, (void*) &ctxt);
        }
        else
        {
            /* element not found */
            rc = 0;
        }
        free(element);
    }
    if (rc) return 1;

    /* End tag */
    if (node->report_end)
    {
        rc = node->report_end(node, client, NULL);
    }

    return rc;
}