Level: cleaned up chunk loading error handling, close #2056

This now removes logging from the level providers (for the most part) and replaces it with exception throws and catches. The implementation using the providers should catch these exceptions if they are thrown.
This commit is contained in:
Dylan K. Taylor
2018-03-01 12:28:11 +00:00
parent ae2e1fdd5a
commit 9d018e8d9e
8 changed files with 306 additions and 289 deletions

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\level\format\io\region;
use pocketmine\level\format\ChunkException;
use pocketmine\level\format\io\exception\CorruptedChunkException;
use pocketmine\utils\Binary;
use pocketmine\utils\MainLogger;
@ -95,10 +96,18 @@ class RegionLoader{
return !($this->locationTable[$index][0] === 0 or $this->locationTable[$index][1] === 0);
}
/**
* @param int $x
* @param int $z
*
* @return null|string
* @throws \InvalidArgumentException if invalid coordinates are given
* @throws CorruptedChunkException if chunk corruption is detected
*/
public function readChunk(int $x, int $z) : ?string{
$index = self::getChunkOffset($x, $z);
if($index < 0 or $index >= 4096){
return null;
throw new \InvalidArgumentException("Invalid chunk position in region, expected x/z in range 0-31, got x=$x, z=$z");
}
$this->lastUsed = time();
@ -115,27 +124,26 @@ class RegionLoader{
if($length >= self::MAX_SECTOR_LENGTH){
$this->locationTable[$index][0] = ++$this->lastSector;
$this->locationTable[$index][1] = 1;
MainLogger::getLogger()->error("Corrupted chunk header detected");
throw new CorruptedChunkException("Corrupted chunk header detected (sector count larger than max)");
}
return null;
}
if($length > ($this->locationTable[$index][1] << 12)){ //Invalid chunk, bigger than defined number of sectors
MainLogger::getLogger()->error("Corrupted bigger chunk detected");
MainLogger::getLogger()->error("Corrupted bigger chunk detected (bigger than number of sectors given in header)");
$this->locationTable[$index][1] = $length >> 12;
$this->writeLocationIndex($index);
}elseif($compression !== self::COMPRESSION_ZLIB and $compression !== self::COMPRESSION_GZIP){
MainLogger::getLogger()->error("Invalid compression type");
return null;
throw new CorruptedChunkException("Invalid compression type (got $compression, expected " . self::COMPRESSION_ZLIB . " or " . self::COMPRESSION_GZIP . ")");
}
$chunkData = fread($this->filePointer, $length - 1);
if($chunkData !== false){
return $chunkData;
}else{
MainLogger::getLogger()->error("Corrupted chunk detected");
return null;
if($chunkData === false){
throw new CorruptedChunkException("Corrupted chunk detected (failed to read chunk data from disk)");
}
return $chunkData;
}
public function chunkExists(int $x, int $z) : bool{