mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-18 15:05:56 +00:00
Fixed a series of mistakes that prevented converting from regionized leveldb to a different format
This commit is contained in:
parent
8027c271fa
commit
fdae689f87
@ -104,20 +104,19 @@ final class RegionizedLevelDB extends BaseLevelDB{
|
||||
return Binary::writeLong(morton2d_encode($chunkX, $chunkZ));
|
||||
}
|
||||
|
||||
protected function getDBPathForCoords(int $chunkX, int $chunkZ) : string{
|
||||
protected function getDBPathForRegionCoords(int $regionX, int $regionZ) : string{
|
||||
return Path::join(self::dbRegionPath($this->path, $this->regionLength), sprintf(
|
||||
"db.%d.%d",
|
||||
(int) floor($chunkX / $this->regionLength),
|
||||
(int) floor($chunkZ / $this->regionLength)
|
||||
$regionX,
|
||||
$regionZ
|
||||
));
|
||||
}
|
||||
|
||||
protected function getDBIndexForCoords(int $chunkX, int $chunkZ) : int{
|
||||
return morton2d_encode((int) floor($chunkX / $this->regionLength), (int) floor($chunkZ / $this->regionLength));
|
||||
}
|
||||
|
||||
protected function fetchDBForCoords(int $chunkX, int $chunkZ, bool $createIfMissing) : ?\LevelDB{
|
||||
$index = $this->getDBIndexForCoords($chunkX, $chunkZ);
|
||||
/**
|
||||
* @throws CorruptedChunkException
|
||||
*/
|
||||
protected function fetchDBForRegionCoords(int $regionX, int $regionZ, bool $createIfMissing) : ?\LevelDB{
|
||||
$index = morton2d_encode($regionX, $regionZ);
|
||||
$db = $this->databases[$index] ?? null;
|
||||
|
||||
if(
|
||||
@ -126,13 +125,13 @@ final class RegionizedLevelDB extends BaseLevelDB{
|
||||
){
|
||||
$options = self::DB_DEFAULT_OPTIONS;
|
||||
$options["create_if_missing"] = $createIfMissing;
|
||||
$dbPath = $this->getDBPathForCoords($chunkX, $chunkZ);
|
||||
$dbPath = $this->getDBPathForRegionCoords($regionX, $regionZ);
|
||||
try{
|
||||
$this->databases[$index] = new \LevelDB($dbPath, $options);
|
||||
}catch(\LevelDBException $e){
|
||||
//no other way to detect error type :(
|
||||
if(!str_contains($e->getMessage(), "(create_if_missing is false)")){
|
||||
throw new CorruptedChunkException("Couldn't open LevelDB region $dbPath for $chunkX.$chunkZ: " . $e->getMessage(), 0, $e);
|
||||
throw new CorruptedChunkException("Couldn't open LevelDB region $dbPath: " . $e->getMessage(), 0, $e);
|
||||
}
|
||||
|
||||
//remember that this DB doesn't exist, so we don't have to hit the disk hundreds of times looking for it
|
||||
@ -142,15 +141,24 @@ final class RegionizedLevelDB extends BaseLevelDB{
|
||||
|
||||
$this->databasesLastUsed[$index] = time();
|
||||
return $this->databases[$index];
|
||||
|
||||
}
|
||||
|
||||
protected function fetchDBForChunkCoords(int $chunkX, int $chunkZ, bool $createIfMissing) : ?\LevelDB{
|
||||
return $this->fetchDBForRegionCoords(
|
||||
(int) floor($chunkX / $this->regionLength),
|
||||
(int) floor($chunkZ / $this->regionLength),
|
||||
$createIfMissing
|
||||
);
|
||||
}
|
||||
|
||||
public function loadChunk(int $chunkX, int $chunkZ) : ?LoadedChunkData{
|
||||
$db = $this->fetchDBForCoords($chunkX, $chunkZ, createIfMissing: false);
|
||||
$db = $this->fetchDBForChunkCoords($chunkX, $chunkZ, createIfMissing: false);
|
||||
return $db !== null ? $this->loadChunkFromDB($db, $chunkX, $chunkZ) : null;
|
||||
}
|
||||
|
||||
public function saveChunk(int $chunkX, int $chunkZ, ChunkData $chunkData, int $dirtyFlags) : void{
|
||||
$db = $this->fetchDBForCoords($chunkX, $chunkZ, createIfMissing: true) ??
|
||||
$db = $this->fetchDBForChunkCoords($chunkX, $chunkZ, createIfMissing: true) ??
|
||||
throw new AssumptionFailedError("We asked fetch to create a DB, it shouldn't return null");
|
||||
|
||||
$this->saveChunkToDB($db, $chunkX, $chunkZ, $chunkData, $dirtyFlags);
|
||||
@ -181,7 +189,7 @@ final class RegionizedLevelDB extends BaseLevelDB{
|
||||
self::dbRegionPath($this->path, $this->regionLength),
|
||||
\FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::UNIX_PATHS
|
||||
),
|
||||
'/\/db\.(-?\d+)\.(-?\d+)\$/',
|
||||
'/\/db\.(-?\d+)\.(-?\d+)$/',
|
||||
\RegexIterator::GET_MATCH
|
||||
);
|
||||
}
|
||||
@ -192,15 +200,20 @@ final class RegionizedLevelDB extends BaseLevelDB{
|
||||
/** @var string[] $region */
|
||||
foreach($iterator as $region){
|
||||
try{
|
||||
$db = new \LevelDB($region[0], self::DB_DEFAULT_OPTIONS);
|
||||
$regionX = (int) $region[1];
|
||||
$regionZ = (int) $region[2];
|
||||
$db = $this->fetchDBForRegionCoords($regionX, $regionZ, createIfMissing: false);
|
||||
if($db === null){
|
||||
throw new AssumptionFailedError("DB at $region[0] should definitely exist");
|
||||
}
|
||||
|
||||
//TODO: we don't need the DB name coords for now, but we might in the future if the key format is
|
||||
//changed to be relative
|
||||
yield from $this->getAllChunksFromDB($db, $skipCorrupted, $logger);
|
||||
}catch(\LevelDBException $e){
|
||||
}catch(CorruptedChunkException $e){
|
||||
//TODO: detect permission errors - although I'm not sure what we could do differently
|
||||
if(!$skipCorrupted){
|
||||
throw new CorruptedChunkException($e->getMessage(), 0, $e);
|
||||
throw $e;
|
||||
}
|
||||
if($logger !== null){
|
||||
$logger->error($e->getMessage());
|
||||
@ -216,7 +229,12 @@ final class RegionizedLevelDB extends BaseLevelDB{
|
||||
/** @var string[] $region */
|
||||
foreach($iterator as $region){
|
||||
//TODO: calculateChunkCount has no accounting for corruption errors
|
||||
$db = new \LevelDB($region[0], self::DB_DEFAULT_OPTIONS);
|
||||
$regionX = (int) $region[1];
|
||||
$regionZ = (int) $region[2];
|
||||
$db = $this->fetchDBForRegionCoords($regionX, $regionZ, createIfMissing: false);
|
||||
if($db === null){
|
||||
throw new AssumptionFailedError("DB at $region[0] should definitely exist");
|
||||
}
|
||||
|
||||
//TODO: we'd need a specialized calculate impl if we change the key length
|
||||
$total += $this->calculateChunkCountInDB($db);
|
||||
|
Loading…
x
Reference in New Issue
Block a user