From 9b565b6bc427673437c28518d1f61c13b58be42e Mon Sep 17 00:00:00 2001
From: Perttu Ahola <celeron55@gmail.com>
Date: Sun, 5 Jun 2011 18:57:36 +0300
Subject: [PATCH] tried to reduce unnecessary map saving disk i/o a bit

---
 src/environment.cpp | 116 +++++++++++++++++++++++++-------------------
 src/environment.h   |  22 ++++++++-
 src/main.cpp        |  12 ++++-
 src/map.cpp         |  10 ++--
 src/mapblock.h      |   4 ++
 5 files changed, 106 insertions(+), 58 deletions(-)

diff --git a/src/environment.cpp b/src/environment.cpp
index f5f20d0e5..798228802 100644
--- a/src/environment.cpp
+++ b/src/environment.cpp
@@ -694,7 +694,7 @@ void ServerEnvironment::step(float dtime)
 			if(block==NULL)
 				continue;
 			
-			// Set current time as timestamp
+			// Set current time as timestamp (and let it set ChangedFlag)
 			block->setTimestamp(m_game_time);
 		}
 
@@ -721,7 +721,7 @@ void ServerEnvironment::step(float dtime)
 			if(m_game_time > stamp && stamp != BLOCK_TIMESTAMP_UNDEFINED)
 				dtime_s = m_game_time - block->getTimestamp();
 
-			// Set current time as timestamp
+			// Set current time as timestamp (and let it set ChangedFlag)
 			block->setTimestamp(m_game_time);
 
 			//dstream<<"Block is "<<dtime_s<<" seconds old."<<std::endl;
@@ -737,6 +737,8 @@ void ServerEnvironment::step(float dtime)
 				event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
 				event.p = p;
 				m_map->dispatchEvent(&event);
+
+				block->setChangedFlag();
 			}
 
 			// TODO: Do something
@@ -790,7 +792,7 @@ void ServerEnvironment::step(float dtime)
 				continue;
 			
 			// Set current time as timestamp
-			block->setTimestamp(m_game_time);
+			block->setTimestampNoChangedFlag(m_game_time);
 
 			// Run node metadata
 			bool changed = block->m_node_metadata.step(dtime);
@@ -800,6 +802,8 @@ void ServerEnvironment::step(float dtime)
 				event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
 				event.p = p;
 				m_map->dispatchEvent(&event);
+
+				block->setChangedFlag();
 			}
 		}
 	}
@@ -821,7 +825,7 @@ void ServerEnvironment::step(float dtime)
 				continue;
 			
 			// Set current time as timestamp
-			block->setTimestamp(m_game_time);
+			block->setTimestampNoChangedFlag(m_game_time);
 
 			/*
 				Do stuff!
@@ -996,49 +1000,8 @@ u16 getFreeServerActiveObjectId(
 u16 ServerEnvironment::addActiveObject(ServerActiveObject *object)
 {
 	assert(object);
-	if(object->getId() == 0)
-	{
-		u16 new_id = getFreeServerActiveObjectId(m_active_objects);
-		if(new_id == 0)
-		{
-			dstream<<"WARNING: ServerEnvironment::addActiveObject(): "
-					<<"no free ids available"<<std::endl;
-			delete object;
-			return 0;
-		}
-		object->setId(new_id);
-	}
-	if(isFreeServerActiveObjectId(object->getId(), m_active_objects) == false)
-	{
-		dstream<<"WARNING: ServerEnvironment::addActiveObject(): "
-				<<"id is not free ("<<object->getId()<<")"<<std::endl;
-		delete object;
-		return 0;
-	}
-	/*dstream<<"INGO: ServerEnvironment::addActiveObject(): "
-			<<"added (id="<<object->getId()<<")"<<std::endl;*/
-			
-	m_active_objects.insert(object->getId(), object);
-
-	// Add static object to active static list of the block
-	v3f objectpos = object->getBasePosition();
-	std::string staticdata = object->getStaticData();
-	StaticObject s_obj(object->getType(), objectpos, staticdata);
-	// Add to the block where the object is located in
-	v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS));
-	MapBlock *block = m_map->getBlockNoCreateNoEx(blockpos);
-	if(block)
-	{
-		block->m_static_objects.m_active.insert(object->getId(), s_obj);
-		object->m_static_exists = true;
-		object->m_static_block = blockpos;
-	}
-	else{
-		dstream<<"WARNING: Server: Could not find a block for "
-				<<"storing newly added static active object"<<std::endl;
-	}
-
-	return object->getId();
+	u16 id = addActiveObjectRaw(object, true);
+	return id;
 }
 
 /*
@@ -1141,6 +1104,58 @@ ActiveObjectMessage ServerEnvironment::getActiveObjectMessage()
 	************ Private methods *************
 */
 
+u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
+		bool set_changed)
+{
+	assert(object);
+	if(object->getId() == 0)
+	{
+		u16 new_id = getFreeServerActiveObjectId(m_active_objects);
+		if(new_id == 0)
+		{
+			dstream<<"WARNING: ServerEnvironment::addActiveObjectRaw(): "
+					<<"no free ids available"<<std::endl;
+			delete object;
+			return 0;
+		}
+		object->setId(new_id);
+	}
+	if(isFreeServerActiveObjectId(object->getId(), m_active_objects) == false)
+	{
+		dstream<<"WARNING: ServerEnvironment::addActiveObjectRaw(): "
+				<<"id is not free ("<<object->getId()<<")"<<std::endl;
+		delete object;
+		return 0;
+	}
+	/*dstream<<"INGO: ServerEnvironment::addActiveObjectRaw(): "
+			<<"added (id="<<object->getId()<<")"<<std::endl;*/
+			
+	m_active_objects.insert(object->getId(), object);
+
+	// Add static object to active static list of the block
+	v3f objectpos = object->getBasePosition();
+	std::string staticdata = object->getStaticData();
+	StaticObject s_obj(object->getType(), objectpos, staticdata);
+	// Add to the block where the object is located in
+	v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS));
+	MapBlock *block = m_map->getBlockNoCreateNoEx(blockpos);
+	if(block)
+	{
+		block->m_static_objects.m_active.insert(object->getId(), s_obj);
+		object->m_static_exists = true;
+		object->m_static_block = blockpos;
+
+		if(set_changed)
+			block->setChangedFlag();
+	}
+	else{
+		dstream<<"WARNING: Server: Could not find a block for "
+				<<"storing newly added static active object"<<std::endl;
+	}
+
+	return object->getId();
+}
+
 /*
 	Remove objects that satisfy (m_removed && m_known_by_count==0)
 */
@@ -1231,8 +1246,8 @@ void ServerEnvironment::activateObjects(MapBlock *block)
 			continue;
 		}
 		// This will also add the object to the active static list
-		addActiveObject(obj);
-		//u16 id = addActiveObject(obj);
+		addActiveObjectRaw(obj, false);
+		//u16 id = addActiveObjectRaw(obj, false);
 	}
 	// Clear stored list
 	block->m_static_objects.m_stored.clear();
@@ -1245,7 +1260,8 @@ void ServerEnvironment::activateObjects(MapBlock *block)
 		block->m_static_objects.m_stored.push_back(s_obj);
 	}
 	// Block has been modified
-	block->setChangedFlag();
+	// NOTE: No it has not really. Save I/O here.
+	//block->setChangedFlag();
 }
 
 /*
diff --git a/src/environment.h b/src/environment.h
index b4f2a64ca..bb9fb0136 100644
--- a/src/environment.h
+++ b/src/environment.h
@@ -159,7 +159,7 @@ class ServerEnvironment : public Environment
 	void loadMeta(const std::string &savedir);
 
 	/*
-		ActiveObjects
+		External ActiveObject interface
 		-------------------------------------------
 	*/
 
@@ -198,13 +198,31 @@ class ServerEnvironment : public Environment
 	ActiveObjectMessage getActiveObjectMessage();
 
 	/*
-		ActiveBlockModifiers
+		ActiveBlockModifiers (TODO)
 		-------------------------------------------
 	*/
 
 	void addActiveBlockModifier(ActiveBlockModifier *abm);
 
 private:
+
+	/*
+		Internal ActiveObject interface
+		-------------------------------------------
+	*/
+
+	/*
+		Add an active object to the environment.
+
+		Called by addActiveObject.
+
+		Object may be deleted by environment immediately.
+		If id of object is 0, assigns a free id to it.
+		Returns the id of the object.
+		Returns 0 if not added and thus deleted.
+	*/
+	u16 addActiveObjectRaw(ServerActiveObject *object, bool set_changed);
+	
 	/*
 		Remove all objects that satisfy (m_removed && m_known_by_count==0)
 	*/
diff --git a/src/main.cpp b/src/main.cpp
index 2c85c2595..802dc539b 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -297,7 +297,7 @@ SUGG: Erosion simulation at map generation time
 SUGG: Try out the notch way of generating maps, that is, make bunches
       of low-res 3d noise and interpolate linearly.
 
-Mapgen v2:
+Mapgen v2 (the current one):
 * Possibly add some kind of erosion and other stuff
 * Better water generation (spread it to underwater caverns but don't
   fill dungeons that don't touch big water masses)
@@ -306,6 +306,16 @@ Mapgen v2:
   the other chunk making nasty straight walls when the other chunk
   is generated. Fix it. Maybe just a special case if the ground is
   flat?
+* Consider not updating this one and make a good mainly block-based
+  generator
+
+SUGG: Make two "modified states", one that forces the block to be saved at
+	the next save event, and one that makes the block to be saved at exit
+	time.
+
+TODO: Add a not_fully_generated flag to MapBlock, which would be set for
+	blocks that contain eg. trees from neighboring generations but haven't
+	been generated itself. This is required for the future generator.
 
 Misc. stuff:
 ------------
diff --git a/src/map.cpp b/src/map.cpp
index 579f30e9a..ba361b393 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -4987,9 +4987,7 @@ void ServerMap::save(bool only_changed)
 	
 	u32 sector_meta_count = 0;
 	u32 block_count = 0;
-	
-	{ //sectorlock
-	//JMutexAutoLock lock(m_sector_mutex); // Bulk comment-out
+	u32 block_count_all = 0; // Number of blocks in memory
 	
 	core::map<v2s16, MapSector*>::Iterator i = m_sectors.getIterator();
 	for(; i.atEnd() == false; i++)
@@ -5008,6 +5006,9 @@ void ServerMap::save(bool only_changed)
 		for(j=blocks.begin(); j!=blocks.end(); j++)
 		{
 			MapBlock *block = *j;
+			
+			block_count_all++;
+
 			if(block->getChangedFlag() || only_changed == false)
 			{
 				saveBlock(block);
@@ -5022,8 +5023,6 @@ void ServerMap::save(bool only_changed)
 		}
 	}
 
-	}//sectorlock
-	
 	/*
 		Only print if something happened or saved whole map
 	*/
@@ -5033,6 +5032,7 @@ void ServerMap::save(bool only_changed)
 		dstream<<DTIME<<"ServerMap: Written: "
 				<<sector_meta_count<<" sector metadata files, "
 				<<block_count<<" block files"
+				<<", "<<block_count_all<<" blocks in memory."
 				<<std::endl;
 	}
 }
diff --git a/src/mapblock.h b/src/mapblock.h
index 1eb97353c..74666eb48 100644
--- a/src/mapblock.h
+++ b/src/mapblock.h
@@ -628,6 +628,10 @@ class MapBlock : public NodeContainer
 		m_timestamp = time;
 		setChangedFlag();
 	}
+	void setTimestampNoChangedFlag(u32 time)
+	{
+		m_timestamp = time;
+	}
 	u32 getTimestamp()
 	{
 		return m_timestamp;
-- 
GitLab