Пример #1
0
/* scan_irr_file_main
 * Parse file looking for objects. 
 * update_flag tell's us if we are parsing a mirror file (2)
 * or !us...!ue update file (1), in contrast to a reload on bootstrap
 * This tells us to look for mirror file format errors
 * and save's us 'check for mirror header' cycles on reloads.
 */
void *scan_irr_file_main (FILE *fp, irr_database_t *database, 
                          int update_flag, enum SCAN_T scan_scope) {
  char buffer[4096], *cp, *p = NULL;
  char first_attr[128];
  u_long save_offset, offset, position, mode, len = 0;
  irr_object_t *irr_object;
  enum IRR_OBJECTS curr_f;
  enum STATES save_state, state;
  long lineno = 0;

  /* init everything */
  if (update_flag)
    position = save_offset = offset = (u_long) ftell (fp);
  else
    position = save_offset = offset = 0;

  mode       = IRR_NOMODE;
  state      = BLANK_LINE; 
  curr_f     = NO_FIELD;
  irr_object = NULL;

  if (scan_scope == SCAN_FILE)
    database->hash_spec_tmp = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, (GDestroyNotify)Delete_hash_spec);

  /* okay, here we go scanning the file */
  while (state != DB_EOF) { /* scan to end of file */
    if ((cp = fgets (buffer, sizeof (buffer), fp)) != NULL) {
      lineno++;
      position = offset;
      len = strlen(buffer);
      offset += len;
    }

    state = get_state (cp, len, state, &save_state);
    
    /* skip comment lines and lines that exceed the buffer size */
    if (state & (OVRFLW | OVRFLW_END | COMMENT ))
      continue;

    if (update_flag      &&
	state == START_F && 
	irr_object == NULL) {
      if (!strncmp ("%END", buffer, 4))
        break; /* normal exit from successful mirror */
      else {
	state = pick_off_mirror_hdr (fp, buffer, sizeof(buffer), state, &save_state,
	                             &mode, &position, &offset, database);
	/* something wrong with update, abort scan */
	if (state == DB_EOF) {
	  p = "IRRd error: scan_irr_file_main (): Missing 'ADD' or 'DEL' "
	      "and/or malformed update!";
	  break;
	}
      }
    }

    if (state & (DB_EOF | OVRFLW | OVRFLW_END | BLANK_LINE))
      curr_f = NO_FIELD;
    else if (state != LINE_CONT)
      curr_f = get_curr_f (buffer);  

    /* we have entered into a new object -- create the initial structure */
    if (irr_object == NULL && state == START_F) {
      irr_object = New_IRR_Object (buffer, position, mode);
      /* save a copy of the first attribute for logging purposes */
      strncpy(first_attr, buffer, sizeof(first_attr));
      first_attr[sizeof(first_attr) - 1] = '\0';
    }

    /* Ignore these fields if they come at the end of the object.
     * The trick is to treat the fields like a comment at the end of the
     * object.
     * dump_object_check() will set state = DB_EOF if other error's found 
     */
    if (curr_f == SYNTAX_ERR || curr_f == WARNING) {

      /* this junk should not be in a well-formed transaction */
      if (atomic_trans) {
	p = "IRRd error: scan_irr_file_main (): 'WARNING' or 'ERROR' "
	    "attribute found in update.  Abort transaction!";
	if (irr_object != NULL)
	  Delete_IRR_Object (irr_object);
	break;
      }

      trace (ERROR, default_trace,"In (db,serial)=(%s,%lu) found 'WARNING' "
	     "or '*ERROR*' line, attempting to remove extraneous lines starting with:\n%s", database->name, database->serial_number + 1, buffer);

      /* mark end of object, read past err's and warn's */ 
      save_offset = position; 

      state = find_blank_line (fp, buffer, sizeof(buffer), state, &save_state,
                               &position, &offset);
      state = dump_object_check (irr_object, state, mode, update_flag, 
                                 database, fp);
      if (state == DB_EOF) { /* something went wrong, dump object and abort */
          trace (ERROR, default_trace,"Attempt to remove RIPE server extraneous line failed!  Abort!\n");
        Delete_IRR_Object (irr_object);
        irr_object = NULL;
        mode = IRR_NOMODE;
        continue;
      } else
        trace (NORM, default_trace, "Attempt to remove extraneous line succeeded!\n");
    }

    if (curr_f != NO_FIELD && (state & (START_F | LINE_CONT)) ) {

      /* if continuation line, attribute value starts at beginning + 1 */
      if (state == LINE_CONT)
        cp = buffer + 1; /* Ignore initial whitespace or '+' */
      else /* skip over attribute name label */
	cp = buffer + strlen(key_info[curr_f].name);

      /* NAME_F indicates object class name attribute */
      if (key_info[curr_f].f_type & NAME_F) {
        whitespace_remove(cp);
	if (*cp != '\0') { /* class name value may be on a continuation line */
          if (irr_object->name != NULL) {
 	    /* Shouldn't have more than one class name attribute */
            trace (NORM, default_trace, "Warning! Multiple class name attributes: Previous - %s %s,  New - %s %s\n", key_info[irr_object->type].name, irr_object->name, key_info[curr_f].name, cp );
	  } else {
	    irr_object->name = strdup (cp);
	    irr_object->type = curr_f;
	    irr_object->filter_val = key_info[curr_f].filter_val;
	  }
	}
      } else if (key_info[curr_f].f_type & SECONDARY_F)
        /* add secondary keys, and store things like origin, nic-hdl, etc.  */
        pick_off_secondary_fields (cp, curr_f, irr_object);

      continue;
    }

    /* Process OBJECT  (we just read a '\n' on a line by itself or eof) */
    if ( (state & (BLANK_LINE | DB_EOF)) && irr_object != NULL) {
      if (scan_scope == SCAN_OBJECT)
	return (void *) irr_object;

      if (curr_f == SYNTAX_ERR || curr_f == WARNING)
	position = save_offset;
      else if (state == DB_EOF)
	position = offset;

      if ((p = build_indexes (fp, database, irr_object, position, update_flag, first_attr)) != NULL) {
        if (!update_flag || (update_flag == 1 && atomic_trans))
	  state = DB_EOF; /* abort scan, something wrong found in input file */
	else
	  p = NULL;	/* ignore errors if mirroring or non-atomic update */
      }

      /* Need to skip over RIPE ERROR/WARNING messages in mirror file */
      if (curr_f == SYNTAX_ERR || curr_f == WARNING) {
        if (fseek (fp, offset, SEEK_SET) < 0) {
          trace (ERROR, default_trace,"Attempt to seek past RIPE server extraneous line failed!\n");
        }
      }
      Delete_IRR_Object (irr_object);
      irr_object = NULL;
      mode = IRR_NOMODE;
    }
  } /* while (state != DB_EOF) */

  /* only do on reload's and mirror updates */
  if (scan_scope == SCAN_FILE) {
    if (p == NULL) 
      commit_spec_hash (database); /* commit if no critical errors */
    g_hash_table_destroy(database->hash_spec_tmp);
  }
  return (void *) p;	/* return error string (if any) */
}
Пример #2
0
int main(int argc, char *argv[])
{
  if (argc!=5)
    {
      fprintf(stderr, "Usage: in_file search_field id_field out_basename\n");
      return 1;
    }
  
  char *in, *outbase;
  int in_len = strlen(argv[1]), out_len = strlen(argv[4]);
  
  in = malloc((in_len + 1) * sizeof(char));
  if (!in)
    {
      fprintf(stderr, "failed to alloc 'in'\n");
      return 1;
    }

  out_len += 1;
  outbase = malloc(out_len * sizeof(char));
  if (!outbase) 
    {
      fprintf(stderr, "failed to alloc 'outbase'\n");
      return 1;
    }

  strcpy(in, argv[1]);
  strcpy(outbase, argv[4]);
  
  char *search_field, *id_field;
  int sf_len = strlen(argv[2]), idf_len = strlen(argv[3]);
  search_field = (char *) malloc((sf_len + 1)  * sizeof(char));
  if (!search_field)
    {
      fprintf(stderr, "failed to alloc 'search_field'\n");
      return 1;
    }
  id_field = (char *) malloc((idf_len + 1)  * sizeof(char));
  if (!id_field)
    {
      fprintf(stderr, "failed to alloc 'id_field'\n");
      return 1;
    }

  strcpy(search_field, argv[2]);
  strcpy(id_field, argv[3]);

  fprintf(stderr, "building indexes for %s...", in);
  struct chunks *chunks = NULL;
  struct indexes *indexes = NULL;

  if (!build_indexes(in, &indexes, &chunks, -1))
    {
      fprintf(stderr, "failed to build indexes\n");
      return 1;
    }

  fprintf(stderr, "done.\n");  
  
  char **out_files = malloc(sizeof(char *) * NUMCORES);
  if (!out_files)
    {
      fprintf(stderr, "failed to alloc out files\n");
      return 1;
    }

  pthread_t *threads = malloc(sizeof(pthread_t) * NUMCORES);
  if (!threads)
    {
      fprintf(stderr, "failed to alloc threads\n");
      return 1;
    }
  int *pt_ret = malloc(sizeof(int) * NUMCORES);
  if (!pt_ret)
    {
      fprintf(stderr, "failed to alloc pt_ret\n");
      return 1;
    }

  struct find_field_args **args = malloc(sizeof(struct find_field_args *) * NUMCORES);
  if (!args)
    {
      fprintf(stderr, "failed to allocate args\n");
      return 1;
    }

  char corestr[3];
  int i, j;
  for (i=0; i<NUMCORES; i++)
    {
      sprintf(corestr, "%d", i);
      out_files[i] = malloc(sizeof(char) * (out_len + strlen(corestr) + 1));
      if (!out_files[i])
	{
	  fprintf(stderr, "failed to alloc out file");
	  return 1;
	}

      strcpy(out_files[i], outbase);
      strcat(out_files[i], corestr);

      args[i] = malloc(sizeof(struct find_field_args));
      args[i]->ioargs = malloc(sizeof(struct ioargs));
      args[i]->ioargs->in_file = in;
      args[i]->ioargs->out_file = out_files[i];
      args[i]->ioargs->chunk = &chunks[i];
      args[i]->search_field = search_field;
      args[i]->id_field = id_field;

      int mb = args[i]->ioargs->chunk->size / (1024*1024);
      fprintf(stderr, "creating new thread[%d] to process %dMB of data\n", i, mb);
      pt_ret[i] = pthread_create(&threads[i], NULL, find_field, (void *) args[i]);
    }
  
  for (i=0; i<NUMCORES; i++) 
    {
      pthread_join(threads[i], NULL);
      fprintf(stderr, "thread[%d] returned with status %d\n", i, pt_ret[i]);
      free(out_files[i]);
      free(args[i]->ioargs);
      free(args[i]);
      free_line_positions(chunks[i].lp);
    }

  if (indexes) 
    {
      free_index(indexes->index);
      free_line_positions(indexes->lp);
      free(indexes);
    }

  free(chunks);
  free(out_files);
  free(args);
  free(in);
  free(outbase);
  free(search_field);
  free(id_field);
  free(pt_ret);
  free(threads);

  return 0; 
}