Пример #1
0
int Scene_Gang_Manager::matched_handle(int64_t gang_id1, int64_t gang_id2) {
	Time_Value now = Time_Value::gettimeofday();
	Date_Time dt(now);
//	dt.hour(20);
//	dt.minute(30);
	dt.second(0);
	dt.microsec(0);

	int8_t index = make_index() - 1;
	int64_t scene_index = SCENE_GANG_GLOBAL_MANAGER->make_scene_index();
	Gang_War_Matched_Gangs_Pair matched_gangs;
	matched_gangs.matched_pair.first = gang_id1;
	matched_gangs.matched_pair.second = gang_id2;
	matched_gangs.match_time.sec(dt.time_sec());
	matched_gangs.matched_index = index;
	matched_gangs.scene_index = scene_index;
	gang_vec_.push_back(matched_gangs);
	scene_index_gang_map_.insert(std::make_pair(scene_index, matched_gangs));

	Gang_War_Matched_Gang_Info info;
	info.matched_index = index;
	info.scene_index = scene_index;
	info.match_time = matched_gangs.match_time;
	info.camp = CAMP_RED;
	if (gang_id1 > 0) {
		info.force = 0;
		Gang_DB_View* gdv = gang_view_by_id(gang_id1);
		if (gdv) {
			info.force = gdv->force_total;
		}
		info.gang_name = gang_name(gang_id1);
		info.zone.clear();
		std::string *zone = find_zone(gang_id1);
		if (zone) {
			info.zone = *zone;
		}
		gang_index_map_.insert(std::make_pair(gang_id1, info));
	}
	info.camp = CAMP_BLUE;
	if (gang_id2 > 0) {
		info.force = 0;
		Gang_DB_View* gdv = gang_view_by_id(gang_id2);
		if (gdv) {
			info.force = gdv->force_total;
		}
		info.gang_name = gang_name(gang_id2);
		info.zone.clear();
		std::string *zone = find_zone(gang_id2);
		if (zone) {
			info.zone = *zone;
		}
		gang_index_map_.insert(std::make_pair(gang_id2, info));
	}
	return 0;
}
Пример #2
0
/** Set parent of frame. */
void frame_set_parent(pfn_t pfn, void *data, size_t hint)
{
	irq_spinlock_lock(&zones.lock, true);
	
	size_t znum = find_zone(pfn, 1, hint);
	
	ASSERT(znum != (size_t) -1);
	
	zone_get_frame(&zones.info[znum],
	    pfn - zones.info[znum].base)->parent = data;
	
	irq_spinlock_unlock(&zones.lock, true);
}
Пример #3
0
void *frame_get_parent(pfn_t pfn, size_t hint)
{
	irq_spinlock_lock(&zones.lock, true);
	
	size_t znum = find_zone(pfn, 1, hint);
	
	ASSERT(znum != (size_t) -1);
	
	void *res = zone_get_frame(&zones.info[znum],
	    pfn - zones.info[znum].base)->parent;
	
	irq_spinlock_unlock(&zones.lock, true);
	
	return res;
}
Пример #4
0
/** Add reference to frame.
 *
 * Find respective frame structure for supplied PFN and
 * increment frame reference count.
 *
 * @param pfn Frame number of the frame to be freed.
 *
 */
NO_TRACE void frame_reference_add(pfn_t pfn)
{
	irq_spinlock_lock(&zones.lock, true);
	
	/*
	 * First, find host frame zone for addr.
	 */
	size_t znum = find_zone(pfn, 1, 0);
	
	ASSERT(znum != (size_t) -1);
	
	zones.info[znum].frames[pfn - zones.info[znum].base].refcount++;
	
	irq_spinlock_unlock(&zones.lock, true);
}
Пример #5
0
/** Mark given range unavailable in frame zones.
 *
 */
NO_TRACE void frame_mark_unavailable(pfn_t start, size_t count)
{
	irq_spinlock_lock(&zones.lock, true);
	
	for (size_t i = 0; i < count; i++) {
		size_t znum = find_zone(start + i, 1, 0);
		
		if (znum == (size_t) -1)  /* PFN not found */
			continue;
		
		zone_mark_unavailable(&zones.info[znum],
		    start + i - zones.info[znum].base);
	}
	
	irq_spinlock_unlock(&zones.lock, true);
}
Пример #6
0
/** Free frames of physical memory.
 *
 * Find respective frame structures for supplied physical frames.
 * Decrement each frame reference count. If it drops to zero, mark
 * the frames as available.
 *
 * @param start Physical Address of the first frame to be freed.
 * @param count Number of frames to free.
 * @param flags Flags to control memory reservation.
 *
 */
void frame_free_generic(uintptr_t start, size_t count, frame_flags_t flags)
{
	size_t freed = 0;
	
	irq_spinlock_lock(&zones.lock, true);
	
	for (size_t i = 0; i < count; i++) {
		/*
		 * First, find host frame zone for addr.
		 */
		pfn_t pfn = ADDR2PFN(start) + i;
		size_t znum = find_zone(pfn, 1, 0);
		
		ASSERT(znum != (size_t) -1);
		
		freed += zone_frame_free(&zones.info[znum],
		    pfn - zones.info[znum].base);
	}
	
	irq_spinlock_unlock(&zones.lock, true);
	
	/*
	 * Signal that some memory has been freed.
	 * Since the mem_avail_mtx is an active mutex,
	 * we need to disable interruptsto prevent deadlock
	 * with TLB shootdown.
	 */
	
	ipl_t ipl = interrupts_disable();
	mutex_lock(&mem_avail_mtx);
	
	if (mem_avail_req > 0)
		mem_avail_req -= min(mem_avail_req, freed);
	
	if (mem_avail_req == 0) {
		mem_avail_gen++;
		condvar_broadcast(&mem_avail_cv);
	}
	
	mutex_unlock(&mem_avail_mtx);
	interrupts_restore(ipl);
	
	if (!(flags & FRAME_NO_RESERVE))
		reserve_free(freed);
}
Пример #7
0
/**********************************************************************
 * C Code Documentation ************************************************
 **********************************************************************
   NAME time_ceiling

   DESCRIPTION  Find new times corresponding to the input times, such that
   in the input times' time zone, the time of day is midnight and the 
   output times are no earlier than the input times.
   To be called from R as 
   \\
   {\tt 
   .Call("time_ceiling", time.vec, zone.list)
   }
   where TIMECLASS is replaced by the name of the time class.

   ARGUMENTS
      IARG  time_vec  The R time vector object
      IARG  zone_list The list of R time zone objects

   RETURN Returns a time vector object of the same length as the input time
   vector, containing the above described output times.

   ALGORITHM  For each input time, this function calculates the desired
   ceiling time using the date_ceil function, in conjunction with the 
   time zone information found from find_zone.

   EXCEPTIONS 

   NOTE See also: time_floor

**********************************************************************/
SEXP time_ceiling( SEXP time_vec, SEXP zone_list )
{

  SEXP ret;
  Sint *in_days, *in_ms, *jul_data, *ms_data;
  char *zone;
  Sint i, lng;
  TZONE_STRUCT *tzone;
  
  /* get the desired parts of the time object */

  if( !time_get_pieces( time_vec, NULL, &in_days, &in_ms, &lng, NULL, 
			&zone, NULL ))
    error( "Invalid argument in C function time_ceiling" );

  tzone = find_zone( zone, zone_list );
  if( !tzone )
    error( "Unknown or unreadable time zone in C function time_ceiling" );

  /* create output time object and find pointers for data*/

  PROTECT(ret = time_create_new( lng, &jul_data, &ms_data ));
  if( !ret || !jul_data || !ms_data ){
    UNPROTECT(3);
    error( "Could not create new time object in c function time_ceiling" );
  }

  /* for each time, calculate floor */

  for( i = 0; i < lng; i++ )
  {
    if(  in_days[i] ==NA_INTEGER ||
	 in_ms[i] ==NA_INTEGER ||
	!date_ceil( in_days[i], in_ms[i], tzone, &(jul_data[i]), 
		     &(ms_data[i] )))
    {
      /* error occurred -- put NA into return value */
      jul_data[i] = NA_INTEGER;
      ms_data[i] = NA_INTEGER;
    }
  }

  UNPROTECT(3); //1+2 from time_get_pieces
  return( ret );
}
Пример #8
0
void Scene_Gang_Manager::matched_handle(Gang_War_Spot &spot) {
	Time_Value now = Time_Value::gettimeofday();
	Date_Time dt(now);
//	dt.hour(20);
//	dt.minute(30);
	dt.second(0);
	dt.microsec(0);

	int8_t index = spot.index;
	int64_t scene_index = SCENE_GANG_GLOBAL_MANAGER->make_scene_index();
	Gang_War_Matched_Gangs_Pair matched_gangs;
	for (std::vector<Gang_Basic_Detail>::iterator it = spot.gang_vec.begin(); it != spot.gang_vec.end(); ++it) {
		if (it->gang_id > 0) {
			if (it->index == 0) {
				matched_gangs.matched_pair.first = it->gang_id;
			} else if (it->index == 1) {
				matched_gangs.matched_pair.second = it->gang_id;
			}
		}
	}
	matched_gangs.match_time.sec(dt.time_sec());
	matched_gangs.matched_index = spot.index;
	matched_gangs.scene_index = scene_index;
	gang_vec_.push_back(matched_gangs);
	scene_index_gang_map_.insert(std::make_pair(scene_index, matched_gangs));

	Gang_War_Matched_Gang_Info info;
	info.matched_index = index;
	info.scene_index = scene_index;
	info.match_time = matched_gangs.match_time;
	info.camp = CAMP_RED;
	if (matched_gangs.matched_pair.first > 0) {
		info.force = 0;
		Gang_DB_View* gdv = gang_view_by_id(matched_gangs.matched_pair.first);
		if (gdv) {
			info.force = gdv->force_total;
		}
		info.gang_name = gang_name(matched_gangs.matched_pair.first);
		info.zone.clear();
		std::string *zone = find_zone(matched_gangs.matched_pair.first);
		if (zone) {
			info.zone = *zone;
		}
		gang_index_map_.insert(std::make_pair(matched_gangs.matched_pair.first, info));
	}
	info.camp = CAMP_BLUE;
	if (matched_gangs.matched_pair.second > 0) {
		info.force = 0;
		Gang_DB_View* gdv = gang_view_by_id(matched_gangs.matched_pair.second);
		if (gdv) {
			info.force = gdv->force_total;
		}
		info.gang_name = gang_name(matched_gangs.matched_pair.second);
		info.zone.clear();
		std::string *zone = find_zone(matched_gangs.matched_pair.second);
		if (zone) {
			info.zone = *zone;
		}
		gang_index_map_.insert(std::make_pair(matched_gangs.matched_pair.second, info));
	}
}
Пример #9
0
/**********************************************************************
 * C Code Documentation ************************************************
 **********************************************************************
   NAME time_rel_add

   DESCRIPTION  Add a relative time object to a time object. 
   To be called from R as 
   \\
   {\tt 
   .Call("time_rel_add", time.vec, [email protected], sort( rel.obj@holidays),
          zone.list)
   }
   where TIMECLASS is replaced by the name of the time class.

   ARGUMENTS
      IARG  time_vec    The R time vector object
      IARG  rel_strs    The character strings from the relative time object
      IARG  hol_vec     SORTED vector of holiday dates
      IARG  zone_list   The list of R time zone objects


   RETURN Returns a time vector that is the result of adding the
   relative times to the input time vector, taking into account the
   given holidays.  The relative time addition is done in the 
   object's local time zone.

   ALGORITHM  First, a list of the holidays' julian dates is 
   created, taking into account the holidays' time zone.
   (Time values are converted to local zones by first converting
   to a TIME_DATE_STRUCT using the jms_to_struct function, and then
   to their local time zones by calling GMT_to_zone function
   in conjunction with find_zone.  If needed, they can then be
   converted back to julian dates by calling julian_from_mdy.)
   Then the times are combined with the
   relative times using the rtime_add_with_zones function.
   No special time zones or formats are put on the returned object.
   If time_vec or rel_strs has a length that is a multiple of the other,
   the shorter one is repeated. If the sequence becomes monotonic
   or is not moving from start towards end, an error is generated.

   EXCEPTIONS 

   NOTE See also: time_rel_seq, time_time_add, time_num_op

**********************************************************************/
SEXP time_rel_add( SEXP time_vec, SEXP rel_strs, 
		   SEXP hol_vec, SEXP zone_list )
{

  SEXP ret;
  Sint *in_days, *in_ms, *out_days, *out_ms;
  Sint *hol_days, *hol_ms;
  Sint i, lng1, lng2, lng_hol, lng, ind1, ind2, all_na;
  TIME_DATE_STRUCT td, td_hol;
  TZONE_STRUCT *tzone, *tzone_hol;
  Sint *hol_dates;

  /* get the desired parts of the time objects */

  if( !time_get_pieces( time_vec, NULL, &in_days, &in_ms, &lng1, NULL, 
			&td.zone, NULL ) ||
      !td.zone || ( lng1 && ( !in_days || !in_ms )))
    error( "Invalid time argument in C function time_rel_add" );

  tzone = find_zone( td.zone, zone_list );
  if( !tzone )
    error( "Unknown or unreadable time zone in C function time_rel_add" );

  if( !time_get_pieces( hol_vec, NULL, &hol_days, &hol_ms, &lng_hol, NULL, 
			&td_hol.zone, NULL ) ||
      (( lng_hol && (!hol_days || !hol_ms )) || !td_hol.zone ))
    error( "Invalid holiday argument in C function time_rel_add" );

  tzone_hol = find_zone( td_hol.zone, zone_list );
  if( !tzone_hol )
    error( "Unknown or unreadable time zone for holidays in C function time_rel_add" );

  /* extract the rel time strings */
  if(!isString(rel_strs) || (lng2 = length(rel_strs)) < 1L)
    error( "Problem extracting relative time strings in C function time_rel_add" );

  if(lng1 && lng2 && ( lng1 % lng2 ) && ( lng2 % lng1 ))
    error( "Length of longer operand is not a multiple of length of shorter in C function time_rel_add" );

  /* create output time object */
  if( !lng1 || !lng2 )
    lng = 0;
  else if( lng2 > lng1 )
    lng = lng2;
  else
    lng = lng1;


  PROTECT(ret = time_create_new( lng, &out_days, &out_ms ));

  if( !out_days || !out_ms || !ret )
    error( "Could not create return object in C function time_rel_add" );

  /* get list of holiday dates */
  hol_dates = NULL;
  all_na = 0;
  if( lng_hol>0 )
  {
    hol_dates = (Sint *) R_alloc( lng_hol, sizeof(Sint) );

    for( i = 0; i < lng_hol; i++ )
    {
      if(  hol_days[i] == NA_INTEGER || 
	   hol_ms[i] == NA_INTEGER ||
	  !jms_to_struct( hol_days[i], hol_ms[i], &td_hol ) ||
	  !GMT_to_zone( &td_hol, tzone_hol ) ||
	  !julian_from_mdy( td_hol, &(hol_dates[i])))
	{
	  all_na = 1;
	  break;
	}
    }
  }

  /* go through input and perform operation */
  for( i = 0; i < lng; i++ )
  {
    ind1 = i % lng1;
    ind2 = i % lng2;

    /* check for NA, convert to local zone, add, and convert back */
    if(	all_na ||
	 in_days[ind1] == NA_INTEGER || 
	 in_ms[ind1] == NA_INTEGER ||
	!jms_to_struct( in_days[ind1], in_ms[ind1], &td ) ||
	!rtime_add_with_zones( &td, (char *) CHAR(STRING_ELT(rel_strs, ind2)), 
			       hol_dates, lng_hol, tzone ) ||
	!julian_from_mdy( td, &(out_days[i] )) ||
	!ms_from_hms( td, &(out_ms[i] )))
    {
      out_days[i] = NA_INTEGER;
      out_ms[i] = NA_INTEGER;
    }
  }

  UNPROTECT(5); //4+1 from time_get_pieces
  return ret;

}
Пример #10
0
SEXP time_rel_seq( SEXP start_time, SEXP end_time,
		   SEXP len_vec, SEXP has_len,
		   SEXP rel_strs, SEXP hol_vec,
		   SEXP zone_list)
{
  SEXP ret, tmp_days, tmp_ms;
  Sint *start_days, *start_ms, *end_days, *end_ms,
    *out_days, *out_ms, *use_len, *seq_len;
  Sint *hol_days, *hol_ms, num_alloc;
  Sint i, lng_hol, lng, direction=0;
  TIME_DATE_STRUCT td, td_hol;
  TZONE_STRUCT *tzone, *tzone_hol;
  char *in_strs;
  Sint *hol_dates;
  Sint pre_start_day, pre_start_ms, used_old_alg ;
  Sint num_protect=0;

  /* figure out if we have end time or length */
  PROTECT(has_len = AS_LOGICAL(has_len));
  num_protect++;
  if( length(has_len) < 1L){
    UNPROTECT(num_protect);
    error( "Problem extracting data from second argument in C function time_rel_seq" );
  }
  use_len = (Sint *) LOGICAL(has_len);

  /* get the desired parts of the time objects */
  if( !time_get_pieces( start_time, NULL, &start_days, &start_ms, &lng, NULL, 
			&td.zone, NULL ) ||
      !td.zone || !lng || !start_days || !start_ms ){
    UNPROTECT(num_protect);
    error( "Invalid time argument in C function time_rel_seq" );
  }
  num_protect += 2; //from time_get_pieces
  if( lng > 1 )
    warning( "Start time has multiple elements; only the first will be used" );

  tzone = find_zone( td.zone, zone_list );
  if( !tzone ){
    UNPROTECT(num_protect);
    error( "Unknown or unreadable time zone in C function time_rel_seq" );
  }

  if( !(*use_len))
  {
    if( !time_get_pieces( end_time, NULL, &end_days, &end_ms, 
			  &lng, NULL, NULL, NULL ) ||
	!lng || !end_days || !end_ms ){
      error( "Invalid time argument in C function time_rel_seq" );
      UNPROTECT(num_protect);
    }
    num_protect +=2;
    if( lng > 1 )
      warning( "End time has multiple elements; only the first will be used" );
  }

  if( !time_get_pieces( hol_vec, NULL, &hol_days, &hol_ms, &lng_hol, NULL, 
			&td_hol.zone, NULL ) ||
      (( lng_hol && (!hol_days || !hol_ms )) || !td_hol.zone )){
    UNPROTECT(num_protect);
    error( "Invalid holiday argument in C function time_rel_seq" );
  }
  num_protect +=2;

  tzone_hol = find_zone( td_hol.zone, zone_list );
  if( !tzone_hol ){
    UNPROTECT(num_protect);
    error( "Unknown or unreadable time zone for holidays in C function time_rel_seq" );
  }

  /* extract the rel time string */
  if(!isString(rel_strs) || (lng = length(rel_strs)) < 1L){
    UNPROTECT(num_protect);
    error( "Problem extracting relative time strings in C function time_rel_seq" );    
  }
  if( lng > 1 )
    warning( "Relative time has multiple elements; only the first will be used" );
  in_strs = (char *) CHAR(STRING_ELT(rel_strs, 0));
  /* extract the length */

  if( *use_len )
  {
    if( !IS_INTEGER(len_vec) || (lng = length(len_vec)) < 1L){
      UNPROTECT(num_protect);
      error( "Problem extracting data from third argument in C function time_rel_seq" );
    }
    seq_len = INTEGER(len_vec);

    if( *seq_len < 0 )
      error( "Length cannot be less than zero" );

    if( lng > 1 )
      warning( "Length has multiple elements; only the first will be used" );
  }

  /* get list of holiday dates */
  hol_dates = NULL;
  if( lng_hol )
  {
    hol_dates = (Sint *) R_alloc( lng_hol, sizeof(Sint) );

    for( i = 0; i < lng_hol; i++ )
    {
      if(  hol_days[i] ==NA_INTEGER || 
	   hol_ms[i] ==NA_INTEGER ||
	  !jms_to_struct( hol_days[i], hol_ms[i], &td_hol ) ||
	  !GMT_to_zone( &td_hol, tzone_hol ) ||
	  !julian_from_mdy( td_hol, &(hol_dates[i])))
	  error( "Bad holiday data in C function time_rel_seq" );
    }
  }

  /* create output time object or temporary storage */

  if( *use_len )
  {
    if(  *seq_len ==NA_INTEGER){
      UNPROTECT(num_protect);
      error( "NA not allowed in sequence" );
    }

    PROTECT(ret = time_create_new( *seq_len, &out_days, &out_ms ));
    num_protect++;

    if( !out_days || !out_ms || !ret ){
      UNPROTECT(num_protect);
      error( "Could not create return object in C function time_rel_seq" );
    }
    if(*seq_len == 0){
      UNPROTECT(num_protect);
      return ret;
    }
  } else
  {
    /* figure out the direction */

    if(  *end_days ==NA_INTEGER ||  *end_ms ==NA_INTEGER){
      UNPROTECT(num_protect);
      error( "NA not allowed in sequence" );
    }

    if(( *start_days > *end_days ) || 
       (( *start_days == *end_days ) && ( *start_ms > *end_ms )))
      direction = -1;
    else if(( *end_days > *start_days ) ||
       (( *start_days == *end_days ) && ( *end_ms > *start_ms )))
      direction = 1;
    else
      direction = 0; /* this will be a flag to end after copying in start */

    /* we don't know the length we'll need.  Allocate at least 100,
       and assume daily to figure out approx length if longer */

    num_alloc = 100;
    if( *start_days - *end_days > 100 )
      num_alloc =  *start_days - *end_days + 20;
    if( *end_days - *start_days > 100 )
      num_alloc =  *end_days - *start_days + 20;

    PROTECT(tmp_days = NEW_INTEGER(num_alloc));
    PROTECT(tmp_ms = NEW_INTEGER(num_alloc));
    num_protect += 2;

    out_days = INTEGER(tmp_days);
    out_ms = INTEGER(tmp_ms);
  }

  /* start with the start time */

  if(  *start_days ==NA_INTEGER ||  *start_ms ==NA_INTEGER){
    UNPROTECT(num_protect);
    error( "NA not allowed in sequence" );
  }
  /* fprintf(stderr, " time_rel_seq: start=%ld,%ld, in_strs[0]=%s\n", *start_days, *start_ms, in_strs[0]); */
  if (avoid_bad_start_day) {
     /* the following is gross.  -wwd */
     char tmp_strs[100] ;
     strncpy(tmp_strs, in_strs, 99);
     if (tmp_strs[0] == '-')
       tmp_strs[0] = '+';
     else if (tmp_strs[0] == '+')
       tmp_strs[0] = '-';
     if (tmp_strs[1] == 'a') {
       /* fprintf(stderr, " time_rel_seq: alignment might have caused problems -- using old algorithm\n");  */
       out_days[0] = *start_days;
       out_ms[0] = *start_ms;
       used_old_alg = 1 ;
       i = 1 ;
     } else {
       /* convert to local zone, add, and convert back */
       if( !jms_to_struct( *start_days, *start_ms, &td ) ||
	   !rtime_add_with_zones( &td, tmp_strs, hol_dates, lng_hol, tzone ) ||
	   !julian_from_mdy( td, &pre_start_day) ||
	   !ms_from_hms( td, &pre_start_ms)){
	 UNPROTECT(num_protect);
         error( "Could not subtract relative time in C function time_rel_seq" );
       }
        /* fprintf(stderr, "pre_start=%ld,%ld\n", pre_start_day, pre_start_ms); */
        i = 0; /* was i=1 */
        used_old_alg = 0 ;
     }
  } else {
      /* original algorithm */
      out_days[0] = *start_days;
      out_ms[0] = *start_ms;
      i = 1 ;
      used_old_alg = 1 ;
  }

  /* go through input and perform operation */
#define PREV_DAY ( (i>0) ? out_days[i-1] : pre_start_day )
#define PREV_MS  ( (i>0) ? out_ms[i-1] : pre_start_ms )

  /*LINTED: Const meant to be in cond context here */
  while( 1 )
  {
    /* see if we are done */
    if( *use_len && ( i >= *seq_len )){
      UNPROTECT(num_protect);
      return ret;
    }
    
    if( !*use_len )
    {
      if( !direction )
	break;
      if(( direction * ( PREV_DAY - *end_days ) > 0 ) ||
	 (( PREV_DAY == *end_days ) && 
	  ( direction * ( PREV_MS - *end_ms ) > 0 )))
      {
	if (i>0) /* is i==0 possible? I think it means an error */
          i--;
	break;
      }

      /* also check on our allocation */
      if( i >= num_alloc - 1 )
      {
	num_alloc += 200;
	SETLENGTH( tmp_days, num_alloc );
        out_days = INTEGER(tmp_days) ;
	SETLENGTH( tmp_ms, num_alloc );
        out_ms = INTEGER(tmp_ms) ;
      }
    }

    /* convert to local zone, add, and convert back */
    if(	!jms_to_struct( PREV_DAY, PREV_MS, &td ) ||
	!rtime_add_with_zones( &td, in_strs, hol_dates, lng_hol, tzone ) ||
	!julian_from_mdy( td, &(out_days[i] )) ||
	!ms_from_hms( td, &(out_ms[i] ))){
      UNPROTECT(num_protect);
      error( "Could not add relative time in C function time_rel_seq" );
    }

    /* make sure we went in the right direction */

    if(( out_days[i] == PREV_DAY ) &&
       ( out_ms[i] == PREV_MS )){
      UNPROTECT(num_protect);
      error( "Relative date addition resulted in stationary time" );
    }

    if( !direction )
    {
      if(( out_days[i] > PREV_DAY ) ||
	 (( out_days[i] == PREV_DAY ) &&
	  ( out_ms[i] > PREV_MS )))
	direction = 1;
      else
	direction = -1;
    } else
    {
      if(( direction * ( out_days[i] - PREV_DAY ) < 0 ) ||
	 (( out_days[i] == PREV_DAY ) && 
	  ( direction * ( out_ms[i] - PREV_MS) < 0 ))){
	UNPROTECT(num_protect);
	error( "Relative date addition resulted in non-monotonic sequence" );
      }
    }

    i++;
  }


  /* if we got here, it means we have to make a time object and
     copy in the numbers now */

  num_alloc = i;
  PROTECT(ret = time_create_new( num_alloc, &end_days, &end_ms ));
  num_protect++;
  if( !end_days || !end_ms || !ret ){
    UNPROTECT(num_protect);
    error( "Could not create return object in C function time_rel_seq" );
  }

  for( i = 0; i < num_alloc; i++ )
  {
    end_days[i] = out_days[i];
    end_ms[i] = out_ms[i];
  }

  UNPROTECT(num_protect);
  return ret;
}
Пример #11
0
/* return value 0: syntaxerror,badIXFR, 1:OK, 2:done_and_skip_it */
static int
apply_ixfr(namedb_type* db, FILE *in, const off_t* startpos,
	const char* zone, uint32_t serialno, nsd_options_t* opt,
	uint16_t id, uint32_t seq_nr, uint32_t seq_total,
	int* is_axfr, int* delete_mode, int* rr_count,
	size_t child_count)
{
	uint32_t filelen, msglen, pkttype, timestamp[2];
	int qcount, ancount, counter;
	buffer_type* packet;
	region_type* region;
	int i;
	uint16_t rrlen;
	const dname_type *dname_zone, *dname;
	zone_type* zone_db;
	domain_type* last_in_list;
	char file_zone_name[3072];
	uint32_t file_serial, file_seq_nr;
	uint16_t file_id;
	off_t mempos;

	memmove(&mempos, startpos, sizeof(off_t));
	if(fseeko(in, mempos, SEEK_SET) == -1) {
		log_msg(LOG_INFO, "could not fseeko: %s.", strerror(errno));
		return 0;
	}
	/* read ixfr packet RRs and apply to in memory db */

	if(!diff_read_32(in, &pkttype) || pkttype != DIFF_PART_IXFR) {
		log_msg(LOG_ERR, "could not read type or wrong type");
		return 0;
	}
	if(!diff_read_32(in, &timestamp[0]) ||
	   !diff_read_32(in, &timestamp[1])) {
		log_msg(LOG_ERR, "could not read timestamp");
		return 0;
	}

	if(!diff_read_32(in, &filelen)) {
		log_msg(LOG_ERR, "could not read len");
		return 0;
	}

	/* read header */
	if(filelen < QHEADERSZ + sizeof(uint32_t)*3 + sizeof(uint16_t)) {
		log_msg(LOG_ERR, "msg too short");
		return 0;
	}

	region = region_create(xalloc, free);
	if(!region) {
		log_msg(LOG_ERR, "out of memory");
		return 0;
	}

	if(!diff_read_str(in, file_zone_name, sizeof(file_zone_name)) ||
		!diff_read_32(in, &file_serial) ||
		!diff_read_16(in, &file_id) ||
		!diff_read_32(in, &file_seq_nr))
	{
		log_msg(LOG_ERR, "could not part data");
		region_destroy(region);
		return 0;
	}

	if(strcmp(file_zone_name, zone) != 0 || serialno != file_serial ||
		id != file_id || seq_nr != file_seq_nr) {
		log_msg(LOG_ERR, "internal error: reading part with changed id");
		region_destroy(region);
		return 0;
	}
	msglen = filelen - sizeof(uint32_t)*3 - sizeof(uint16_t)
		- strlen(file_zone_name);
	packet = buffer_create(region, QIOBUFSZ);
	dname_zone = dname_parse(region, zone);
	zone_db = find_zone(db, dname_zone, opt, child_count);
	if(!zone_db) {
		log_msg(LOG_ERR, "no zone exists");
		region_destroy(region);
		/* break out and stop the IXFR, ignore it */
		return 2;
	}

	if(msglen > QIOBUFSZ) {
		log_msg(LOG_ERR, "msg too long");
		region_destroy(region);
		return 0;
	}
	buffer_clear(packet);
	if(fread(buffer_begin(packet), msglen, 1, in) != 1) {
		log_msg(LOG_ERR, "short fread: %s", strerror(errno));
		region_destroy(region);
		return 0;
	}
	buffer_set_limit(packet, msglen);

	/* only answer section is really used, question, additional and
	   authority section RRs are skipped */
	qcount = QDCOUNT(packet);
	ancount = ANCOUNT(packet);
	buffer_skip(packet, QHEADERSZ);

	/* skip queries */
	for(i=0; i<qcount; ++i)
		if(!packet_skip_rr(packet, 1)) {
			log_msg(LOG_ERR, "bad RR in question section");
			region_destroy(region);
			return 0;
		}

	DEBUG(DEBUG_XFRD,2, (LOG_INFO, "diff: started packet for zone %s",
			dname_to_string(dname_zone, 0)));
	/* first RR: check if SOA and correct zone & serialno */
	if(*rr_count == 0) {
		DEBUG(DEBUG_XFRD,2, (LOG_INFO, "diff: %s parse first RR",
			dname_to_string(dname_zone, 0)));
		dname = dname_make_from_packet(region, packet, 1, 1);
		if(!dname) {
			log_msg(LOG_ERR, "could not parse dname");
			region_destroy(region);
			return 0;
		}
		if(dname_compare(dname_zone, dname) != 0) {
			log_msg(LOG_ERR, "SOA dname %s not equal to zone",
				dname_to_string(dname,0));
			log_msg(LOG_ERR, "zone dname is %s",
				dname_to_string(dname_zone,0));
			region_destroy(region);
			return 0;
		}
		if(!buffer_available(packet, 10)) {
			log_msg(LOG_ERR, "bad SOA RR");
			region_destroy(region);
			return 0;
		}
		if(buffer_read_u16(packet) != TYPE_SOA ||
			buffer_read_u16(packet) != CLASS_IN) {
			log_msg(LOG_ERR, "first RR not SOA IN");
			region_destroy(region);
			return 0;
		}
		buffer_skip(packet, sizeof(uint32_t)); /* ttl */
		if(!buffer_available(packet, buffer_read_u16(packet)) ||
			!packet_skip_dname(packet) /* skip prim_ns */ ||
			!packet_skip_dname(packet) /* skip email */) {
			log_msg(LOG_ERR, "bad SOA RR");
			region_destroy(region);
			return 0;
		}
		if(buffer_read_u32(packet) != serialno) {
			buffer_skip(packet, -4);
			log_msg(LOG_ERR, "SOA serial %d different from commit %d",
				buffer_read_u32(packet), serialno);
			region_destroy(region);
			return 0;
		}
		buffer_skip(packet, sizeof(uint32_t)*4);
		counter = 1;
		*rr_count = 1;
		*is_axfr = 0;
		*delete_mode = 0;

		DEBUG(DEBUG_XFRD,2, (LOG_INFO, "diff: %s start count %d, ax %d, delmode %d",
			dname_to_string(dname_zone, 0), *rr_count, *is_axfr, *delete_mode));
	}
	else  counter = 0;

	last_in_list = zone_db->apex;
	for(; counter < ancount; ++counter,++(*rr_count))
	{
		uint16_t type, klass;
		uint32_t ttl;

		if(!(dname=dname_make_from_packet(region, packet, 1,1))) {
			log_msg(LOG_ERR, "bad xfr RR dname %d", *rr_count);
			region_destroy(region);
			return 0;
		}
		if(!buffer_available(packet, 10)) {
			log_msg(LOG_ERR, "bad xfr RR format %d", *rr_count);
			region_destroy(region);
			return 0;
		}
		type = buffer_read_u16(packet);
		klass = buffer_read_u16(packet);
		ttl = buffer_read_u32(packet);
		rrlen = buffer_read_u16(packet);
		if(!buffer_available(packet, rrlen)) {
			log_msg(LOG_ERR, "bad xfr RR rdata %d, len %d have %d",
				*rr_count, rrlen, (int)buffer_remaining(packet));
			region_destroy(region);
			return 0;
		}
		DEBUG(DEBUG_XFRD,2, (LOG_INFO, "diff: %s parsed count %d, ax %d, delmode %d",
			dname_to_string(dname_zone, 0), *rr_count, *is_axfr, *delete_mode));

		if(*rr_count == 1 && type != TYPE_SOA) {
			/* second RR: if not SOA: this is an AXFR; delete all zone contents */
			delete_zone_rrs(db, zone_db);
			/* add everything else (incl end SOA) */
			*delete_mode = 0;
			*is_axfr = 1;
			DEBUG(DEBUG_XFRD,2, (LOG_INFO, "diff: %s sawAXFR count %d, ax %d, delmode %d",
				dname_to_string(dname_zone, 0), *rr_count, *is_axfr, *delete_mode));
		}
		if(*rr_count == 1 && type == TYPE_SOA) {
			/* if the serial no of the SOA equals the serialno, then AXFR */
			size_t bufpos = buffer_position(packet);
			uint32_t thisserial;
			if(!packet_skip_dname(packet) ||
				!packet_skip_dname(packet) ||
				buffer_remaining(packet) < sizeof(uint32_t)*5)
			{
				log_msg(LOG_ERR, "bad xfr SOA RR formerr.");
				region_destroy(region);
				return 0;
			}
			thisserial = buffer_read_u32(packet);
			if(thisserial == serialno) {
				/* AXFR */
				delete_zone_rrs(db, zone_db);
				*delete_mode = 0;
				*is_axfr = 1;
			}
			/* must have stuff in memory for a successful IXFR,
			 * the serial number of the SOA has been checked
			 * previously (by check_for_bad_serial) if it exists */
			if(!*is_axfr && !domain_find_rrset(zone_db->apex,
				zone_db, TYPE_SOA)) {
				log_msg(LOG_ERR, "%s SOA serial %d is not "
					"in memory, skip IXFR", zone, serialno);
				region_destroy(region);
				/* break out and stop the IXFR, ignore it */
				return 2;
			}
			buffer_set_position(packet, bufpos);
		}
		if(type == TYPE_SOA && !*is_axfr) {
			/* switch from delete-part to add-part and back again,
			   just before soa - so it gets deleted and added too */
			/* this means we switch to delete mode for the final SOA */
			*delete_mode = !*delete_mode;
			DEBUG(DEBUG_XFRD,2, (LOG_INFO, "diff: %s IXFRswapdel count %d, ax %d, delmode %d",
				dname_to_string(dname_zone, 0), *rr_count, *is_axfr, *delete_mode));
		}
		if(type == TYPE_TSIG || type == TYPE_OPT) {
			/* ignore pseudo RRs */
			buffer_skip(packet, rrlen);
			continue;
		}

		DEBUG(DEBUG_XFRD,2, (LOG_INFO, "xfr %s RR dname is %s type %s",
			*delete_mode?"del":"add",
			dname_to_string(dname,0), rrtype_to_string(type)));
		if(*delete_mode) {
			/* delete this rr */
			if(!*is_axfr && type == TYPE_SOA && counter==ancount-1
				&& seq_nr == seq_total-1) {
				continue; /* do not delete final SOA RR for IXFR */
			}
			if(!delete_RR(db, dname, type, klass, last_in_list, packet,
				rrlen, zone_db, region, *is_axfr)) {
				region_destroy(region);
				return 0;
			}
			if (!*is_axfr && last_in_list->nextdiff) {
				last_in_list = last_in_list->nextdiff;
			}
		}
		else
		{
			/* add this rr */
			if(!add_RR(db, dname, type, klass, ttl, packet,
				rrlen, zone_db, *is_axfr)) {
				region_destroy(region);
				return 0;
			}
		}
	}
	fix_empty_terminals(zone_db);
	region_destroy(region);
	return 1;
}
Пример #12
0
static int
read_sure_part(namedb_type* db, FILE *in, nsd_options_t* opt,
	struct diff_read_data* data, struct diff_log** log,
	size_t child_count)
{
	char zone_buf[3072];
	char log_buf[5120];
	uint32_t old_serial, new_serial, num_parts;
	uint16_t id;
	uint8_t committed;
	struct diff_zone *zp;
	uint32_t i;
	int have_all_parts = 1;
	struct diff_log* thislog = 0;
	off_t commitpos;

	/* read zone name and serial */
	if(!diff_read_str(in, zone_buf, sizeof(zone_buf)) ||
		!diff_read_32(in, &old_serial) ||
		!diff_read_32(in, &new_serial) ||
		!diff_read_16(in, &id) ||
		!diff_read_32(in, &num_parts)) {
		log_msg(LOG_ERR, "diff file bad commit part");
		return 0;
	}
	commitpos = ftello(in); /* position of commit byte */
	if(commitpos == -1) {
		log_msg(LOG_INFO, "could not ftello: %s.", strerror(errno));
		return 0;
	}
	if(!diff_read_8(in, &committed) ||
		!diff_read_str(in, log_buf, sizeof(log_buf)) )
	{
		log_msg(LOG_ERR, "diff file bad commit part");
		return 0;
	}

	if(log) {
		thislog = (struct diff_log*)region_alloc(db->region, sizeof(struct diff_log));
		if(!thislog) {
			log_msg(LOG_ERR, "out of memory, %s:%d", __FILE__, __LINE__);
			exit(1);
		}
		thislog->zone_name = region_strdup(db->region, zone_buf);
		thislog->comment = region_strdup(db->region, log_buf);
		thislog->error = 0;
		thislog->next = *log;
		*log = thislog;
	}

	/* has been read in completely */
	zp = diff_read_find_zone(data, zone_buf);
	if(!zp) {
		log_msg(LOG_ERR, "diff file commit without IXFR");
		if(thislog)
			thislog->error = "error no IXFR parts";
		return 1;
	}
	if(committed && check_for_bad_serial(db, zone_buf, old_serial)) {
		DEBUG(DEBUG_XFRD,1, (LOG_ERR,
			"skipping diff file commit with bad serial"));
		zp->parts->root = RBTREE_NULL;
		zp->parts->count = 0;
		if(thislog)
			thislog->error = "error bad serial";
		return 1;
	}
	for(i=0; i<num_parts; i++) {
		struct diff_xfrpart *xp = diff_read_find_part(zp, i);
		if(!xp || xp->id != id || xp->new_serial != new_serial) {
			have_all_parts = 0;
		}
	}
	if(!have_all_parts) {
		DEBUG(DEBUG_XFRD,1, (LOG_ERR,
			"skipping diff file commit without all parts"));
		if(thislog)
			thislog->error = "error missing parts";
	}

	if(committed && have_all_parts)
	{
		int is_axfr=0, delete_mode=0, rr_count=0;
		off_t resume_pos;

#ifdef NSEC3
#ifndef FULL_PREHASH
		struct region *region;
		dname_type const *zone_dname;
		struct zone *zone;

		region = region_create(xalloc, free);
		if (region == NULL) {
			log_msg(LOG_ERR, "out of memory");
			return 0;
		}
		zone_dname = dname_parse(region, zone_buf);
		if (zone_dname == NULL) {
			log_msg(LOG_ERR, "out of memory");
		        region_destroy(region);
			return 0;
		}
		zone = find_zone(db, zone_dname, opt, child_count);
		region_destroy(region);
		if (zone == NULL) {
			log_msg(LOG_ERR, "no zone exists");
			/* just stop trying applying ixfr */
			return 1;
		}
		if (0 != namedb_nsec3_mod_domains_create(db)) {
			log_msg(LOG_ERR,
				"unable to allocate space "
				"for modified NSEC3 domains");
			return 0;
		}
#endif /* !FULL_PREHASH */
#endif /* NSEC3 */

		DEBUG(DEBUG_XFRD,1, (LOG_INFO, "processing xfr: %s", log_buf));

		resume_pos = ftello(in);
		if(resume_pos == -1) {
			log_msg(LOG_INFO, "could not ftello: %s.", strerror(errno));
			return 0;
		}
		for(i=0; i<num_parts; i++) {
			struct diff_xfrpart *xp = diff_read_find_part(zp, i);
			int ret;
			DEBUG(DEBUG_XFRD,2, (LOG_INFO, "processing xfr: apply part %d", (int)i));
			ret = apply_ixfr(db, in, &xp->file_pos, zone_buf, new_serial, opt,
				id, xp->seq_nr, num_parts, &is_axfr, &delete_mode,
				&rr_count, child_count);
			if(ret == 0) {
				log_msg(LOG_ERR, "bad ixfr packet part %d in %s", (int)i,
					opt->difffile);
				mark_and_exit(opt, in, commitpos, log_buf);
			} else if(ret == 2) {
				break;
			}
		}
#ifdef NSEC3
#ifndef FULL_PREHASH
		if (is_axfr != 0)
			prehash_zone(db, zone);
		else
			prehash_zone_incremental(db, zone);
#endif /* !FULL_PREHASH */
#endif /* NSEC3 */

		if(fseeko(in, resume_pos, SEEK_SET) == -1) {
			log_msg(LOG_INFO, "could not fseeko: %s.", strerror(errno));
			return 0;
		}
	}
	else {
	 	DEBUG(DEBUG_XFRD,1, (LOG_INFO, "skipping xfr: %s", log_buf));
	}

	/* clean out the parts for the zone after the commit/rollback */
	zp->parts->root = RBTREE_NULL;
	zp->parts->count = 0;
	return 1;
}