示例#1
0
/*!
 * \brief create a single forest at the point specified
 * \param pos Position on the map to start from
 * \param size Radius of the forest to paint.
 */
static void
CreateForest(UInt32 pos, UInt16 size)
{
	UInt16 x, y, i, j, s;

	x = (UInt16)(pos % getMapWidth());
	y = (UInt16)(pos / getMapWidth());
	zone_lock(lz_world);
	zone_lock(lz_flags);
	i = x - size > 0 ? x - size : 0;
	j = y - size > 0 ? y - size : 0;

	for (; i <= x + size; i++) {
		for (j = y - size; j <= y + size; j++) {
			if (i >= getMapWidth() ||
			    j >= getMapHeight())
				continue;
			if (getWorld(WORLDPOS(i, j)) != Z_DIRT)
				continue;
			s = ((y > j) ? (y - j) : (j - y)) +
			    ((x > i) ? (x - i) : (i - x));
			if (GetRandomNumber(s) < 2) {
				/*!
				 * \todo count_trees or count_real_trees
				 */
				setWorldAndFlag(WORLDPOS(i, j), Z_REALTREE, 0);
				vgame.BuildCount[bc_count_trees]++;
			}
		}
		j = y - size > 0 ? y - size : 0;
	}
	zone_unlock(lz_flags);
	zone_unlock(lz_world);
}
示例#2
0
void
DoNastyStuffTo(welem_t type, UInt16 probability, UInt8 purge)
{
	/* nasty stuff means: turn it into wasteland */
	UInt32 randomTile;
	UInt16 i, x, y;

	if (GetRandomNumber(probability) != 0)
		return;

	zone_lock(lz_world);
	zone_lock(lz_flags);
	for (i = 0; i < 50; i++) {
		randomTile = GetRandomNumber(MapMul());
		if (getWorld(randomTile) == type) {
			/* wee, let's destroy something */
			x = (UInt16)(randomTile % getMapWidth());
			y = (UInt16)(randomTile / getMapWidth());
			if (!purge)
				CreateWaste(x, y);
			else
				Build_Destroy(x, y);
			break;
		}
	}
	zone_unlock(lz_flags);
	zone_unlock(lz_world);
}
示例#3
0
Int16
BurnField(UInt16 x, UInt16 y, Int16 forceit)
{
	welem_t node;
	int rv = 0;

	zone_lock(lz_world);
	zone_lock(lz_flags);
	node = getWorld(WORLDPOS(x, y));
	if ((forceit != 0 && node != Z_BRIDGE &&
	    node != Z_REALWATER) ||
	    (node != Z_FIRE1 &&
	    node != Z_FIRE2 &&
	    node != Z_FIRE3 &&
	    node != Z_DIRT &&
	    node != Z_WASTE &&
	    node != Z_FAKEWATER &&
	    node != Z_REALWATER &&
	    node != Z_CRATER &&
	    node != Z_BRIDGE &&
	    ContainsDefence(x, y) == 0)) {
		Build_Destroy(x, y);
		setWorldAndFlag(WORLDPOS(x, y), Z_FIRE1, 1);
		orWorldFlags(WORLDPOS(x, y), SCRATCHDISASTER);
		DrawCross(x, y, 1, 1);
		vgame.BuildCount[bc_fire]++;
		rv = 1;
	}
	zone_unlock(lz_flags);
	zone_unlock(lz_world);
	return (rv);
}
示例#4
0
void
database_service_zone_unload(zone_desc_s *zone_desc, zdb_zone *zone)
{
    log_debug("database_service_zone_unload(%{dnsname}@%p=%i,%{dnsname})",
            zone_desc->origin, zone_desc, zone_desc->rc,
            (zone != NULL)?zone->origin:(const u8*)"\004NULL");

    zdb_zone *work_zone = NULL;

    if(zone != NULL)
    {
        work_zone = zone; // zone will be released by the thread
        zone_lock(zone_desc, ZONE_LOCK_UNLOAD);
        if(zone == zone_desc->loaded_zone) // UNLOAD
        {
            log_warn("database_service_zone_unload: forced unload of %p = loaded_zone", zone);
            
            log_debug7("database_service_zone_unload: %{dnsname}@%p: loaded_zone@%p (was %p)",
                    zone_desc->origin,
                    zone_desc,
                    NULL,
                    zone_desc->loaded_zone); // UNLOAD
            zdb_zone_release(zone_desc->loaded_zone);
            zone_desc->loaded_zone = NULL; // UNLOAD
        }
        // else the zone in the descriptor has changed : don't touch it
        zone_unlock(zone_desc, ZONE_LOCK_UNLOAD);
    }
    else
    {
        zone_lock(zone_desc, ZONE_LOCK_UNLOAD);
        work_zone = zone_desc->loaded_zone; // UNLOAD
        
        log_debug7("database_service_zone_unload: %{dnsname}@%p: loaded_zone@%p (was %p)",
                zone_desc->origin,
                zone_desc,
                NULL,
                zone_desc->loaded_zone); // UNLOAD
        
        if(zone_desc->loaded_zone != NULL)
        {
            // the zone we are about to unload will be released by the thread
            //zdb_zone_release(zone_desc->loaded_zone);
            zone_desc->loaded_zone = NULL; // UNLOAD
        }
        zone_unlock(zone_desc, ZONE_LOCK_UNLOAD);
    }
    
    if(work_zone != NULL)
    {
        database_service_zone_unload_parms_s *parm;
        MALLOC_OR_DIE(database_service_zone_unload_parms_s*, parm, sizeof(database_service_zone_unload_parms_s), DSZZUPRM_TAG);
        parm->zone_desc = zone_desc;
        parm->zone = work_zone;
    
        zone_acquire(zone_desc);
        database_service_zone_unload_queue_thread(database_service_zone_unload_thread, parm, NULL, "database_service_zone_unload_thread");
    }
示例#5
0
/*!
 * \todo Make the river more interesting
 */
static void
CreateFullRiver(void)
{
	UInt16 i, j, k, width;
	int axis;
	UInt16 kmax;

	width = (UInt16)(GetRandomNumber(5) + 5);
	axis = (int)GetRandomNumber(1);
	kmax = axis ? getMapWidth() : getMapHeight();

	/* This is the start position of the center of the river */
	j = (UInt16)GetRandomNumber(kmax);

	zone_lock(lz_world);
	zone_lock(lz_flags);

	for (i = 0; i < kmax; i++) {
		for (k = j; k < (width + j); k++) {
			if (k < kmax) {
				if (axis)
					setWorldAndFlag(WORLDPOS(i, k),
					    Z_REALWATER, 0);
				else
					setWorldAndFlag(WORLDPOS(k, i),
					    Z_REALWATER, 0);
			}
		}

		switch (GetRandomNumber(3)) {
		case 0:
			if (width >  5)
				width--;
			break;
		case 1:
			if (width < 15)
				width++;
			break;
		default:
			break;
		}
		switch (GetRandomNumber(4)) {
		case 0:
			if (j > 0)
				j--;
			break;
		case 1:
			if (j < kmax)
				j++;
			break;
		default:
			break;
		}
	}
	zone_unlock(lz_flags);
	zone_unlock(lz_world);
}
示例#6
0
void
DoRandomDisaster(void)
{
	UInt32 randomTile;
	Int16 i, type, random;
	UInt16 x, y;
	UInt8 disaster_level;

	disaster_level = getDisasterLevel();
	/* for those who can't handle the game (truth?) */
	if (disaster_level == 0)
		return;

	zone_lock(lz_world);
	zone_lock(lz_flags);

	for (i = 0; i < 100; i++) { /* 100 tries to hit a useful tile */
		randomTile = GetRandomNumber(MapMul());
		type = getWorld(randomTile);
		if (type != Z_DIRT &&
			type != Z_REALWATER &&
			type != Z_CRATER) {
			x = (UInt16)(randomTile % getMapWidth());
			y = (UInt16)(randomTile / getMapHeight());
			/* TODO: should depend on difficulty */
			random = (Int16)GetRandomNumber(1000 / disaster_level);
			WriteLog("Random Disaster: %d\n", (int)random);
			if (random < 10 && vgame.BuildCount[bc_fire] == 0) {
				DoSpecificDisaster(diFireOutbreak, x, y);
			} else if (random < 15 &&
			    game.objects[obj_monster].active == 0) {
				DoSpecificDisaster(diMonster, x, y);
			} else if (random < 17 &&
			    game.objects[obj_dragon].active == 0) {
				DoSpecificDisaster(diDragon, x, y);
			} else if (random < 19) {
				DoSpecificDisaster(diMeteor, x, y);
			}
			/* only one chance for disaster per turn */
			break;
		}
	}
	zone_unlock(lz_flags);
	zone_unlock(lz_world);
}
示例#7
0
Int16
UpdateDisasters(void)
{
	/* return false if no disasters are found */
	UInt16 i, j;
	welem_t type;
	int retval = 0;

	zone_lock(lz_world);
	zone_lock(lz_flags);
	clearScratch(SCRATCHDISASTER);
	for (i = 0; i < getMapHeight(); i++) {
		for (j = 0; j < getMapWidth(); j++) {
			type = getWorld(WORLDPOS(i, j));
			/* already looked at this one? */
			if (getWorldFlags(WORLDPOS(i, j)) & SCRATCHDISASTER) {
				if (type == Z_FIRE2) {
					retval = 1;
					if (GetRandomNumber(5) != 0) {
						/* are there any defences */
						if (GetDefenceValue(i, j) < 3) {
							FireSpread(i, j);
						}
						setWorldAndFlag(WORLDPOS(i, j),
						    Z_FIRE3, 0);
					} else {
						CreateWaste(i, j);
					}
				} else if (type == Z_FIRE1) {
					retval = 1;
					setWorldAndFlag(WORLDPOS(i, j),
					    Z_FIRE2, 0);
				} else if (type == Z_FIRE3) {
					retval = 1;
					CreateWaste(i, j);
				}
			}
		}
	}
	zone_unlock(lz_flags);
	zone_unlock(lz_world);
	return (retval);
}
示例#8
0
Int16
CreateDragon(UInt16 x, UInt16 y)
{
	welem_t node;
	int rv = 0;

	zone_lock(lz_world);
	zone_lock(lz_flags);
	node = getWorld(WORLDPOS(x, y));
	if (node != Z_REALWATER && node != Z_CRATER) {
		game.objects[obj_dragon].x = x;
		game.objects[obj_dragon].y = y;
		game.objects[obj_dragon].dir = (UInt16)GetRandomNumber(8);
		game.objects[obj_dragon].active = 1;
		DrawField(x, y);
		rv = 1;
	}
	zone_unlock(lz_flags);
	zone_unlock(lz_world);
	return (rv);
}
示例#9
0
/*!
 * \brief Create a waste zone for the meteor.
 * \param x horizontal position
 * \param y vertical position
 * \param size size of the meteor
 */
static void
CreateMeteor(UInt16 x, UInt16 y, Int16 size)
{
	UInt16 j;
	UInt16 i =  (Int16)(x - size) < 0 ? 0 : (UInt16)(x - size);

	zone_lock(lz_world);
	zone_lock(lz_flags);
	UILockScreen();
	for (; i <= x + size; i++) {
		j = (Int16)(y - size) < 0 ? 0 : (UInt16)(y - size);
		for (; j <= y + size; j++) {
			if (i < getMapWidth() &&
			    j < getMapHeight()) {
				if (GetRandomNumber(5) < 2) {
					if (getWorld(WORLDPOS(i, j)) !=
					    Z_REALWATER) {
						CreateWaste(i, j);
					}
				} else if (GetRandomNumber(5) < 4) {
					if (getWorld(WORLDPOS(i, j)) !=
					    Z_REALWATER &&
					    getWorld(WORLDPOS(i, j)) !=
					    Z_FAKEWATER) {
						BurnField(i, j, 1);
					}
				}
			}
		}
	}
	Build_Destroy(x, y);
	setWorldAndFlag(WORLDPOS(x, y), Z_CRATER, 0);
	zone_unlock(lz_flags);
	zone_unlock(lz_world);
	UIUnlockScreen();
	RedrawAllFields();
}
示例#10
0
/*!
 * \brief Turn the zone into wasteland
 * \param x x position to affect
 * \param y y position to affect
 */
static void
CreateWaste(UInt16 x, UInt16 y)
{
	welem_t node;

	zone_lock(lz_world);
	zone_lock(lz_flags);
	node = getWorld(WORLDPOS(x, y));
	Build_Destroy(x, y);
	if (node == Z_REALWATER || IsRoadBridge(node)) {
		zone_unlock(lz_flags);
		zone_unlock(lz_world);
		return;
	}
	setWorldAndFlag(WORLDPOS(x, y), Z_WASTE, 0);
	vgame.BuildCount[bc_waste]++;
	DrawCross(x, y, 1, 1);
	zone_unlock(lz_flags);
	zone_unlock(lz_world);
	if (node == Z_COALPLANT || node == Z_NUCLEARPLANT)  {
		UIDisasterNotify(diPlantExplosion);
		FireSpread(x, y);
	}
}
示例#11
0
void PaintTheWorld(void)
{
#if defined(LOGGING)
	UInt32 wpos;
	int val = 0;
#endif

	WriteLog("Painting the world\n");
#if defined(LOGGING)
	WriteLog("Validating that the map is clear [%ld]\n", 
	    (long)MapMul());
	zone_lock(lz_world);
	for (wpos = 0; wpos < MapMul(); wpos++) {
		val += getWorld(wpos);
	}
	assert(val == 0);
	zone_unlock(lz_world);
#endif
	CreateFullRiver();
	CreateForests();
}
示例#12
0
void
DoCommitmentNasties(void)
{
	int i;

	zone_lock(lz_world);
	for (i = 0; i < 60 - getTax(); i++) {
		UInt32 loc = GetRandomNumber(MapMul());
		welem_t world = getWorld(GetRandomNumber(MapMul()));
		int x = loc % getMapWidth();
		int y = loc % getMapHeight();

		if ((IsTransport(world)) &&
		    (GetRandomNumber(100) > getUpkeep(ue_traffic)))
			Build_Destroy(x, y);
		if ((IsWaterPipe(world) || IsPowerLine(world) ||
			    IsPowerWater(world)) &&
		    (GetRandomNumber(100) > getUpkeep(ue_power)))
			Build_Destroy(x, y);
	}
	zone_unlock(lz_world);
}
示例#13
0
static ya_result
config_section_zone_stop(struct config_section_descriptor_s *csd)
{
#if CONFIG_SETTINGS_DEBUG
    formatln("config: section: zone: stop");
#endif
    
    // NOP
    zone_desc_s *zone_desc = (zone_desc_s*)csd->base;
    ya_result return_code;
    
    // ensure the descriptor is valid
    
    if(ISOK(return_code = zone_complete_settings(zone_desc)))
    {
        zone_setdefaults(zone_desc);
        
        if(logger_is_running())
        {
            log_debug("config: %{dnsname}: zone section parsed", zone_desc->origin);
        }
        
        // load the descriptor (most likely offline)

        if(config_section_zone_filter(zone_desc, config_section_zone_filter_params) == 1)
        {
            if(logger_is_running())
            {
                log_debug("config: %{dnsname}: sending zone to service", zone_desc->origin);
            }
            database_zone_desc_load(zone_desc);
        }
        else
        {
            
            zone_desc_s *current_zone_desc = zone_acquirebydnsname(zone_desc->origin);
            if(current_zone_desc != NULL)
            {
                if(logger_is_running())
                {
                    log_debug("config: %{dnsname}: clearing original zone drop status", zone_desc->origin);
                }
                zone_lock(current_zone_desc, ZONE_LOCK_REPLACE_DESC);
                zone_clear_status(current_zone_desc, ZONE_STATUS_DROP_AFTER_RELOAD);
                zone_unlock(current_zone_desc, ZONE_LOCK_REPLACE_DESC);
                
                zone_release(current_zone_desc);
            }
            
            zone_release(zone_desc);
        }
    }
    else
    {
        zone_release(zone_desc);
    }
        
    csd->base = NULL;
    
    return return_code;
}
示例#14
0
void
MoveAllObjects(void)
{
	UInt16 i, x, y;

	for (i = 0; i < NUM_OF_OBJECTS; i++) {
		if (game.objects[i].active != 0) {
			/* hmm, is this thing destructive? */
			if (i == obj_dragon) {
				if (!BurnField(game.objects[i].x,
				    game.objects[i].y, 1)) {
					CreateWaste(game.objects[i].x,
					    game.objects[i].y);
				}
				MonsterCheckSurrounded(i);
			} else if (i == obj_monster) {
				/* whoo-hoo, bingo again */
				CreateWaste(game.objects[i].x,
				    game.objects[i].y);
				MonsterCheckSurrounded(i);
			}

			x = game.objects[i].x; /* save old position */
			y = game.objects[i].y;

			switch (GetRandomNumber(OBJ_CHANCE_OF_TURNING)) {
			case 1: /* yes, clockwise */
				game.objects[i].dir = (game.objects[i].dir+1)%8;
				break;
			case 2: /* yes, counter-clockwise */
				game.objects[i].dir = (game.objects[i].dir+7)%8;
				break;
			default:
				break;
			}
			/* now move it a nod */
			switch (game.objects[i].dir) { /* first up/down */
			case 0: /* up */
			case 1: /* up-right */
			case 7: /* up-left */
				if (game.objects[i].y > 0) {
					game.objects[i].y--;
				} else {
					game.objects[i].dir = 4;
				}
				break;
			case 3: /* down-right */
			case 4: /* down */
			case 5: /* down-left */
				if (game.objects[i].y <
				    (UInt16)(getMapHeight()-1)) {
					game.objects[i].y++;
				} else {
					game.objects[i].dir = 0;
				}
				break;
			default:
				break;
			}

			switch (game.objects[i].dir) { /* then left/right */
			case 1: /* up-right */
			case 2: /* right */
			case 3: /* down-right */
				if (game.objects[i].x <
				    (UInt16)(getMapWidth()-1)) {
					game.objects[i].x++;
				} else {
					game.objects[i].dir = 6;
				}
				break;
			case 5: /* down-left */
			case 6: /* left */
			case 7: /* up-left */
				if (game.objects[i].x > 0) {
					game.objects[i].x--;
				} else {
					game.objects[i].dir = 2;
				}
				break;
			default:
				break;
			}
			zone_lock(lz_world);
			zone_lock(lz_flags);
			DrawCross(x, y, 1, 1); /* (erase it) */
			DrawField(game.objects[i].x, game.objects[i].y);
			zone_unlock(lz_flags);
			zone_unlock(lz_world);
		}
	}
}
示例#15
0
void
database_load_zone_desc(zone_desc_s *zone_desc)
{
    yassert(zone_desc != NULL);
    
    log_debug1("database_load_zone_desc(%{dnsname}@%p=%i)", zone_desc->origin, zone_desc, zone_desc->rc);
    
    s32 err = zone_register(&database_zone_desc, zone_desc);

    if(ISOK(err))
    {
        log_info("zone: %{dnsname}: %p: config: registered", zone_desc->origin, zone_desc);
        
        zone_lock(zone_desc, ZONE_LOCK_LOAD_DESC);
        zone_set_status(zone_desc, ZONE_STATUS_REGISTERED);
        zone_clear_status(zone_desc, ZONE_STATUS_DROP_AFTER_RELOAD);
        zone_unlock(zone_desc, ZONE_LOCK_LOAD_DESC);
        
        // newly registered zone
        // used to be message->origin
        
        if(database_service_started())
        {
            database_zone_load(zone_desc->origin); // before this I should set the file name

#if HAS_MASTER_SUPPORT
            if(zone_desc->type == ZT_MASTER)
            {
                if(!host_address_empty(zone_desc->slaves))
                {
                    log_info("zone: %{dnsname}: %p: config: notifying slaves", zone_desc->origin, zone_desc);
                    host_address *slaves = host_address_copy_list(zone_desc->slaves);
                    notify_host_list(zone_desc, slaves, CLASS_CTRL);
                }
            }
            else
#endif
            {

            }
        }
    }
    else
    {
        switch(err)
        {
            case DATABASE_ZONE_MISSING_DOMAIN:
            {
                log_err("zone: ?: %p: config: no domain set (not loaded)", zone_desc);
                
                if(zone_get_status(zone_desc) & ZONE_STATUS_PROCESSING)
                {
                    log_err("zone: ?: %p: is processed by %s (releasing)", zone_desc, database_service_operation_get_name(zone_desc->last_processor));
                }
                
                zone_release(zone_desc);
                
                break;
            }
            case DATABASE_ZONE_MISSING_MASTER:
            {
                log_err("zone: %{dnsname}: %p: config: slave but no master setting (not loaded)", zone_desc->origin, zone_desc);
                
                if(zone_get_status(zone_desc) & ZONE_STATUS_PROCESSING)
                {
                    log_err("zone: ?: %p: is processed by %s (releasing)", zone_desc, database_service_operation_get_name(zone_desc->last_processor));
                }
                
                zone_release(zone_desc);
                
                break;
            }
            case DATABASE_ZONE_CONFIG_CLONE: // Exact copy
            {
                log_debug("zone: %{dnsname}: %p: config: has already been set (same settings)", zone_desc->origin, zone_desc);
                
                zone_desc_s* current = zone_acquirebydnsname(zone_desc->origin);
                
                zone_lock(current, ZONE_LOCK_REPLACE_DESC);
                zone_clear_status(current, ZONE_STATUS_DROP_AFTER_RELOAD);
                zone_unlock(current, ZONE_LOCK_REPLACE_DESC);
                zone_release(current);
                
                // whatever has been decided above, loading the zone file (if it changed) should be queued
                database_zone_load(zone_desc->origin);
                
                zone_release(zone_desc);
                
                break;
            }
            case DATABASE_ZONE_CONFIG_DUP: // Not an exact copy
            {
                log_debug("zone: %{dnsname}: %p: config: has already been set (different settings)", zone_desc->origin, zone_desc);
                
                // basically, most of the changes require a stop, restart of
                // any task linked to the zone
                // so let's make this a rule, whatever changed
                
                notify_clear(zone_desc->origin);
                
                zone_desc_s *current = zone_acquirebydnsname(zone_desc->origin);

#if HAS_DYNAMIC_PROVISIONING
                host_address *notify_slaves_then_delete = NULL;
                host_address *notify_slaves = NULL;
#endif
                if(current != zone_desc)
                {
                    zone_lock(current, ZONE_LOCK_REPLACE_DESC);
                    
                    if(zone_get_status(current) & ZONE_STATUS_PROCESSING)
                    {
                        log_err("zone: ?: %p: is processed by %s (overwriting)", zone_desc, database_service_operation_get_name(zone_desc->last_processor));
                    }
                    
                    // what happens if the change is on :
                    
                    // domain: impossible
                    
                    /// @todo 20131203 edf -- compare before replace
                    
                    // file_name : try to load the new file (will happen anyway)
                    
                    if((current->file_name != NULL) && (zone_desc->file_name != NULL))
                    {
                        if(strcmp(current->file_name, zone_desc->file_name) != 0)
                        {
                            zone_set_status(current, ZONE_STATUS_MODIFIED);
                        }
                    }
                    else if(current->file_name != zone_desc->file_name) // at least one of them is NULL
                    {
                        zone_set_status(current, ZONE_STATUS_MODIFIED);
                    }
                    
                    free(current->file_name);
                    current->file_name = zone_desc->file_name;
                    zone_desc->file_name = NULL;
                    
                    // masters :
                    
                    log_debug7("updating %p (%u) with %p (%u): masters", current, current->lock_owner, zone_desc, zone_desc->lock_owner);
                    
                    if(host_address_list_equals(current->masters, zone_desc->masters))
                    {
                        host_address_delete_list(zone_desc->masters);
                    }
                    else
                    {
                        host_address_delete_list(current->masters);
                        current->masters = zone_desc->masters;
                    }
                    zone_desc->masters = NULL;
                    
                    // notifies :
                    
                    log_debug7("updating %p (%u) with %p (%u): notifies", current, current->lock_owner, zone_desc, zone_desc->lock_owner);
                    
                    if(host_address_list_equals(current->notifies, zone_desc->notifies))
                    {
                        host_address_delete_list(zone_desc->notifies);
                    }
                    else
                    {
                        host_address_delete_list(current->notifies);
                        current->notifies = zone_desc->notifies;
                    }
                    zone_desc->notifies = NULL;
                    
#if HAS_DYNAMIC_PROVISIONING
                    
                    log_debug7("updating %p (%u) with %p (%u): slaves", current, current->lock_owner, zone_desc, zone_desc->lock_owner);
                    
                    if(host_address_list_equals(current->slaves, zone_desc->slaves))
                    {
#if HAS_MASTER_SUPPORT
                        if((current->type == ZT_MASTER) || (zone_desc->type == ZT_MASTER))
                        {
                            notify_slaves_then_delete = zone_desc->slaves;
                        }
                        else
#endif
                        {
                            host_address_delete_list(zone_desc->slaves);
                        }
                    }
                    else
                    {
#if HAS_MASTER_SUPPORT
                        if(current->type == ZT_MASTER)
                        {
                            notify_slaves_then_delete = current->slaves;
                        }
                        else
                        {
                            host_address_delete_list(current->slaves);
                        }
                        
                        if(zone_desc->type == ZT_MASTER)
                        {
                            notify_slaves = zone_desc->slaves;
                        }
#else
                        host_address_delete_list(current->slaves);
#endif
                        
                        current->slaves = zone_desc->slaves;
                    }
                    zone_desc->slaves = NULL;
                    
#endif              
                    // type : ?
                    
                    log_debug7("updating %p (%u) with %p (%u): type", current, current->lock_owner, zone_desc, zone_desc->lock_owner);
                    current->type = zone_desc->type;
                    
#if HAS_ACL_SUPPORT
                    // ac : apply the new one, update the zone access
                                        
                    log_debug7("updating %p (%u) with %p (%u): ac@%p with ac@%p",
                            current, current->lock_owner, zone_desc, zone_desc->lock_owner,
                            &current->ac, &zone_desc->ac);
                    
#ifdef DEBUG
                    log_debug7("old@%p:", current);
                    log_debug7("    notify@%p",current->ac.allow_notify.ipv4.items);
                    log_debug7("     query@%p",current->ac.allow_query.ipv4.items);
                    log_debug7("  transfer@%p",current->ac.allow_transfer.ipv4.items);
                    log_debug7("    update@%p",current->ac.allow_update.ipv4.items);
                    log_debug7("forwarding@%p",current->ac.allow_update_forwarding.ipv4.items);
                    log_debug7("   control@%p",current->ac.allow_control.ipv4.items);
                    
                    log_debug7("new@%p:", zone_desc);
                    log_debug7("    notify@%p",zone_desc->ac.allow_notify.ipv4.items);
                    log_debug7("     query@%p",zone_desc->ac.allow_query.ipv4.items);
                    log_debug7("  transfer@%p",zone_desc->ac.allow_transfer.ipv4.items);
                    log_debug7("    update@%p",zone_desc->ac.allow_update.ipv4.items);
                    log_debug7("forwarding@%p",zone_desc->ac.allow_update_forwarding.ipv4.items);
                    log_debug7("   control@%p",zone_desc->ac.allow_control.ipv4.items);
#endif
                    
                    acl_unmerge_access_control(&current->ac, &g_config->ac);
                    acl_empties_access_control(&current->ac);
                    memcpy(&current->ac, &zone_desc->ac, sizeof(access_control));
                    ZEROMEMORY(&zone_desc->ac, sizeof(access_control));
#endif
                    // notify : reset, restart
                    
                    log_debug7("updating %p (%u) with %p (%u): notify", current, current->lock_owner, zone_desc, zone_desc->lock_owner);
                    memcpy(&current->notify, &zone_desc->notify, sizeof(zone_notify_s));
#if HAS_DNSSEC_SUPPORT                    
#if HAS_RRSIG_MANAGEMENT_SUPPORT
                    // signature : reset, restart
                    
                    log_debug7("updating %p (%u) with %p (%u): signature", current, current->lock_owner, zone_desc, zone_desc->lock_owner);
                    memcpy(&current->signature, &zone_desc->signature, sizeof(zone_signature_s));
#endif                    
                    // dnssec_mode : drop everything related to the zone, load the new config
                    
                    log_debug7("updating %p (%u) with %p (%u): dnssec_mode", current, current->lock_owner, zone_desc, zone_desc->lock_owner);
                    
                    current->dnssec_mode = zone_desc->dnssec_mode;
#endif

                                        
                    // refresh : update the "alarms"
                    
                    log_debug7("updating %p (%u) with %p (%u): refresh", current, current->lock_owner, zone_desc, zone_desc->lock_owner);

                    memcpy(&current->refresh, &zone_desc->refresh, sizeof(zone_refresh_s));
                                        
                    // dynamic_provisioning : ?
                    
                    log_debug7("updating %p (%u) with %p (%u): dynamic_provisioning", current, current->lock_owner, zone_desc, zone_desc->lock_owner);
                    
                    memcpy(&current->dynamic_provisioning, &zone_desc->dynamic_provisioning, sizeof(dynamic_provisioning_s));
                    
                    // slaves : update the list
                    
                    zone_unlock(current, ZONE_LOCK_REPLACE_DESC);
                }

                // whatever has been decided above, loading the zone file should be queued
                database_zone_load(zone_desc->origin);

#if HAS_DYNAMIC_PROVISIONING
                // if asking for a load of the zone_data on a master should trigger a notify of its slaves
                
                log_debug7("handling dynamic provisioning");

                if(!host_address_empty(notify_slaves_then_delete))
                {
                    log_info("zone load desc: %{dnsname}: notifying slaves: %{hostaddrlist}", zone_desc->origin, notify_slaves_then_delete);
                    
                    notify_host_list(current, notify_slaves_then_delete, CLASS_CTRL);
                    notify_slaves_then_delete = NULL;
                }
                
                if(!host_address_empty(notify_slaves))
                {
                    log_info("zone load desc: %{dnsname}: notifying slaves: %{hostaddrlist}", zone_desc->origin, notify_slaves);
                    
                    host_address *notify_slaves_copy = host_address_copy_list(notify_slaves);
                    notify_host_list(current, notify_slaves_copy, CLASS_CTRL);
                    notify_slaves = NULL;
                }
#endif
                
#if HAS_MASTER_SUPPORT && HAS_DNSSEC_SUPPORT && HAS_RRSIG_MANAGEMENT_SUPPORT
                
                if(current->dnssec_policy != zone_desc->dnssec_policy)
                {
                    log_info("zone: %{dnsname}: %p: config: dnssec-policy modified", zone_desc->origin, zone_desc);
                    
                    if(zone_desc->dnssec_policy != NULL)
                    {
                        if(current->dnssec_policy != NULL)
                        {
                            log_warn("zone: %{dnsname}: %p: config: changing dnssec-policy at runtime (%s to %s)", zone_desc->origin, zone_desc, current->dnssec_policy->name, zone_desc->dnssec_policy->name);
                            
                            if(current->dnssec_policy->denial != zone_desc->dnssec_policy->denial)
                            {
                                log_warn("zone: %{dnsname}: %p: config: modifications of the dnssec-policy denial setting may be ignored", zone_desc->origin, zone_desc);
                            }
                        
                            dnssec_policy_release(current->dnssec_policy);
                            current->dnssec_policy = dnssec_policy_acquire_from_name(zone_desc->dnssec_policy->name);
                        }
                        else
                        {
                            log_info("zone: %{dnsname}: %p: config: dnssec-policy %s enabled", zone_desc->origin, zone_desc, zone_desc->dnssec_policy->name);
                            current->dnssec_policy = dnssec_policy_acquire_from_name(zone_desc->dnssec_policy->name);
                        }
                    }
                    else
                    {
                        log_warn("zone: %{dnsname}: %p: config: removing policy at runtime", zone_desc->origin, zone_desc);
                        dnssec_policy_release(current->dnssec_policy);
                        current->dnssec_policy = NULL;
                    }
                }
#endif
                if(current != zone_desc)
                {
                    log_debug7("destroying temporary zone descriptor @%p", zone_desc);

                    zone_release(zone_desc);
                }
                
                zone_clear_status(zone_desc, ZONE_STATUS_DROP_AFTER_RELOAD);
                
                zone_release(current);
                
                break;
            } // DUP
            default:
            {
                log_err("zone: %{dnsname}: %p: failed to register", zone_desc->origin, zone_desc);
                break;
            }
        } // switch
    }
    
    log_debug1("database_load_zone_desc(%p) done", zone_desc);
}