update file system

This commit is contained in:
何冠峰
2024-07-05 19:29:34 +08:00
parent b151f968d7
commit a9e5e7fdd3
21 changed files with 350 additions and 513 deletions
@@ -197,6 +197,37 @@ namespace YooAsset
}
}
}
public virtual FSLoadBundleOperation LoadBundleFile(PackageBundle bundle)
{
if (RawFileBuildPipeline)
{
var operation = new DCFSLoadRawBundleOperation(this, bundle);
OperationSystem.StartOperation(PackageName, operation);
return operation;
}
else
{
var operation = new DCFSLoadAssetBundleOperation(this, bundle);
OperationSystem.StartOperation(PackageName, operation);
return operation;
}
}
public virtual void UnloadBundleFile(PackageBundle bundle, object result)
{
AssetBundle assetBundle = result as AssetBundle;
if (assetBundle == null)
return;
if (assetBundle != null)
assetBundle.Unload(true);
if (_loadedStream.TryGetValue(bundle.BundleGUID, out Stream managedStream))
{
managedStream.Close();
managedStream.Dispose();
_loadedStream.Remove(bundle.BundleGUID);
}
}
public virtual void SetParameter(string name, object value)
{
@@ -268,35 +299,26 @@ namespace YooAsset
}
public virtual bool Belong(PackageBundle bundle)
{
return Belong(bundle.BundleGUID);
}
public virtual bool Belong(string bundleGUID)
{
// 注意:缓存文件系统保底加载!
return true;
}
public virtual bool Exists(PackageBundle bundle)
{
return Exists(bundle.BundleGUID);
return _wrappers.ContainsKey(bundle.BundleGUID);
}
public virtual bool Exists(string bundleGUID)
{
return _wrappers.ContainsKey(bundleGUID);
}
public virtual bool CheckNeedDownload(PackageBundle bundle)
public virtual bool NeedDownload(PackageBundle bundle)
{
if (Belong(bundle) == false)
return false;
return Exists(bundle) == false;
}
public virtual bool CheckNeedUnpack(PackageBundle bundle)
public virtual bool NeedUnpack(PackageBundle bundle)
{
return false;
}
public virtual bool CheckNeedImport(PackageBundle bundle)
public virtual bool NeedImport(PackageBundle bundle)
{
if (Belong(bundle) == false)
return false;
@@ -304,119 +326,6 @@ namespace YooAsset
return Exists(bundle) == false;
}
public virtual bool WriteFile(PackageBundle bundle, string copyPath)
{
if (_wrappers.ContainsKey(bundle.BundleGUID))
{
throw new Exception("Should never get here !");
}
string infoFilePath = GetInfoFilePath(bundle);
string dataFilePath = GetDataFilePath(bundle);
try
{
if (File.Exists(infoFilePath))
File.Delete(infoFilePath);
if (File.Exists(dataFilePath))
File.Delete(dataFilePath);
FileUtility.CreateFileDirectory(dataFilePath);
// 拷贝数据文件
FileInfo fileInfo = new FileInfo(copyPath);
fileInfo.CopyTo(dataFilePath);
// 写入文件信息
WriteInfoFile(infoFilePath, bundle.FileCRC, bundle.FileSize);
}
catch (Exception e)
{
YooLogger.Error($"Failed to write cache file ! {e.Message}");
return false;
}
FileWrapper wrapper = new FileWrapper(infoFilePath, dataFilePath, bundle.FileCRC, bundle.FileSize);
return Record(bundle.BundleGUID, wrapper);
}
public virtual bool DeleteFile(PackageBundle bundle)
{
return DeleteFile(bundle.BundleGUID);
}
public virtual bool DeleteFile(string bundleGUID)
{
if (_wrappers.TryGetValue(bundleGUID, out FileWrapper wrapper))
{
try
{
string dataFilePath = wrapper.DataFilePath;
FileInfo fileInfo = new FileInfo(dataFilePath);
if (fileInfo.Exists)
fileInfo.Directory.Delete(true);
_wrappers.Remove(bundleGUID);
return true;
}
catch (Exception e)
{
YooLogger.Error($"Failed to delete cache file ! {e.Message}");
return false;
}
}
else
{
return false;
}
}
public virtual EFileVerifyResult VerifyFile(PackageBundle bundle)
{
if (_wrappers.TryGetValue(bundle.BundleGUID, out FileWrapper wrapper) == false)
return EFileVerifyResult.CacheNotFound;
EFileVerifyResult result = FileSystemHelper.FileVerify(wrapper.DataFilePath, wrapper.DataFileSize, wrapper.DataFileCRC, EFileVerifyLevel.High);
return result;
}
public virtual byte[] ReadFileBytes(PackageBundle bundle)
{
throw new System.NotImplementedException();
}
public virtual string ReadFileText(PackageBundle bundle)
{
throw new System.NotImplementedException();
}
public virtual FSLoadBundleOperation LoadBundleFile(PackageBundle bundle)
{
if (RawFileBuildPipeline)
{
var operation = new DCFSLoadRawBundleOperation(this, bundle);
OperationSystem.StartOperation(PackageName, operation);
return operation;
}
else
{
var operation = new DCFSLoadAssetBundleOperation(this, bundle);
OperationSystem.StartOperation(PackageName, operation);
return operation;
}
}
public virtual void UnloadBundleFile(PackageBundle bundle, object result)
{
AssetBundle assetBundle = result as AssetBundle;
if (assetBundle == null)
return;
if (assetBundle != null)
assetBundle.Unload(true);
if (_loadedStream.TryGetValue(bundle.BundleGUID, out Stream managedStream))
{
managedStream.Close();
managedStream.Dispose();
_loadedStream.Remove(bundle.BundleGUID);
}
}
#region 内部方法
private readonly BufferWriter _sharedBuffer = new BufferWriter(1024);
public void WriteInfoFile(string filePath, string dataFileCRC, long dataFileSize)
@@ -504,24 +413,21 @@ namespace YooAsset
{
return PathUtility.Combine(_manifestFileRoot, DefaultCacheFileSystemDefine.AppFootPrintFileName);
}
public void DeleteAllManifestFiles()
/// <summary>
/// 是否已经记录了文件
/// </summary>
public bool IsRecordFile(string bundleGUID)
{
if (Directory.Exists(_manifestFileRoot))
{
Directory.Delete(_manifestFileRoot, true);
}
}
public List<string> GetAllCachedBundleGUIDs()
{
return _wrappers.Keys.ToList();
return _wrappers.ContainsKey(bundleGUID);
}
/// <summary>
/// 记录缓存信息
/// 记录文件信息
/// </summary>
public bool Record(string bundleGUID, FileWrapper wrapper)
public bool RecordFile(string bundleGUID, FileWrapper wrapper)
{
if (Exists(bundleGUID))
if (_wrappers.ContainsKey(bundleGUID))
{
YooLogger.Error($"{nameof(DefaultCacheFileSystem)} has element : {bundleGUID}");
return false;
@@ -530,6 +436,104 @@ namespace YooAsset
_wrappers.Add(bundleGUID, wrapper);
return true;
}
/// <summary>
/// 验证缓存文件
/// </summary>
public EFileVerifyResult VerifyCacheFile(PackageBundle bundle)
{
if (_wrappers.TryGetValue(bundle.BundleGUID, out FileWrapper wrapper) == false)
return EFileVerifyResult.CacheNotFound;
EFileVerifyResult result = FileSystemHelper.FileVerify(wrapper.DataFilePath, wrapper.DataFileSize, wrapper.DataFileCRC, EFileVerifyLevel.High);
return result;
}
/// <summary>
/// 写入缓存文件
/// </summary>
public bool WriteCacheFile(PackageBundle bundle, string copyPath)
{
if (_wrappers.ContainsKey(bundle.BundleGUID))
{
throw new Exception("Should never get here !");
}
string infoFilePath = GetInfoFilePath(bundle);
string dataFilePath = GetDataFilePath(bundle);
try
{
if (File.Exists(infoFilePath))
File.Delete(infoFilePath);
if (File.Exists(dataFilePath))
File.Delete(dataFilePath);
FileUtility.CreateFileDirectory(dataFilePath);
// 拷贝数据文件
FileInfo fileInfo = new FileInfo(copyPath);
fileInfo.CopyTo(dataFilePath);
// 写入文件信息
WriteInfoFile(infoFilePath, bundle.FileCRC, bundle.FileSize);
}
catch (Exception e)
{
YooLogger.Error($"Failed to write cache file ! {e.Message}");
return false;
}
FileWrapper wrapper = new FileWrapper(infoFilePath, dataFilePath, bundle.FileCRC, bundle.FileSize);
return RecordFile(bundle.BundleGUID, wrapper);
}
/// <summary>
/// 删除缓存文件
/// </summary>
public bool DeleteCacheFile(string bundleGUID)
{
if (_wrappers.TryGetValue(bundleGUID, out FileWrapper wrapper))
{
try
{
string dataFilePath = wrapper.DataFilePath;
FileInfo fileInfo = new FileInfo(dataFilePath);
if (fileInfo.Exists)
fileInfo.Directory.Delete(true);
_wrappers.Remove(bundleGUID);
return true;
}
catch (Exception e)
{
YooLogger.Error($"Failed to delete cache file ! {e.Message}");
return false;
}
}
else
{
return false;
}
}
/// <summary>
/// 删除所有清单文件
/// </summary>
public void DeleteAllManifestFiles()
{
if (Directory.Exists(_manifestFileRoot))
{
Directory.Delete(_manifestFileRoot, true);
}
}
/// <summary>
/// 获取所有缓存文件GUID
/// </summary>
public List<string> GetAllCachedBundleGUIDs()
{
return _wrappers.Keys.ToList();
}
#endregion
}
}
@@ -45,7 +45,7 @@ namespace YooAsset
for (int i = _allBundleGUIDs.Count - 1; i >= 0; i--)
{
string bundleGUID = _allBundleGUIDs[i];
_fileSystem.DeleteFile(bundleGUID);
_fileSystem.DeleteCacheFile(bundleGUID);
_allBundleGUIDs.RemoveAt(i);
if (OperationSystem.IsBusy)
break;
@@ -47,7 +47,7 @@ namespace YooAsset
for (int i = _unusedBundleGUIDs.Count - 1; i >= 0; i--)
{
string bundleGUID = _unusedBundleGUIDs[i];
_fileSystem.DeleteFile(bundleGUID);
_fileSystem.DeleteCacheFile(bundleGUID);
_unusedBundleGUIDs.RemoveAt(i);
if (OperationSystem.IsBusy)
break;
@@ -8,17 +8,18 @@ namespace YooAsset
{
private readonly DefaultCacheFileSystem _fileSystem;
private VerifyTempFileOperation _verifyOperation;
private string _fileSavePath;
private string _tempFilePath;
private ESteps _steps = ESteps.None;
internal DCFSDownloadNormalFileOperation(DefaultCacheFileSystem fileSystem, PackageBundle bundle, string mainURL, string fallbackURL, int failedTryAgain, int timeout)
internal DCFSDownloadNormalFileOperation(DefaultCacheFileSystem fileSystem, PackageBundle bundle,
string mainURL, string fallbackURL, int failedTryAgain, int timeout)
: base(bundle, mainURL, fallbackURL, failedTryAgain, timeout)
{
_fileSystem = fileSystem;
}
internal override void InternalOnStart()
{
_fileSavePath = _fileSystem.GetTempFilePath(Bundle);
_tempFilePath = _fileSystem.GetTempFilePath(Bundle);
_steps = ESteps.CheckExists;
}
internal override void InternalOnUpdate()
@@ -43,26 +44,17 @@ namespace YooAsset
// 创建下载器
if (_steps == ESteps.CreateRequest)
{
FileUtility.CreateFileDirectory(_fileSavePath);
FileUtility.CreateFileDirectory(_tempFilePath);
// 删除临时文件
if (File.Exists(_tempFilePath))
File.Delete(_tempFilePath);
// 获取请求地址
_requestURL = GetRequestURL();
// 重置变量
_isAbort = false;
_latestDownloadBytes = 0;
_latestDownloadRealtime = Time.realtimeSinceStartup;
DownloadProgress = 0f;
DownloadedBytes = 0;
// 重置计时器
if (_tryAgainTimer > 0f)
YooLogger.Warning($"Try again download : {_requestURL}");
_tryAgainTimer = 0f;
// 删除临时文件
if (File.Exists(_fileSavePath))
File.Delete(_fileSavePath);
// 重置请求
ResetRequestFiled();
// 创建下载器
CreateWebRequest();
@@ -95,7 +87,7 @@ namespace YooAsset
// 验证下载文件
if (_steps == ESteps.VerifyTempFile)
{
var element = new TempFileElement(_fileSavePath, Bundle.FileCRC, Bundle.FileSize);
var element = new TempFileElement(_tempFilePath, Bundle.FileCRC, Bundle.FileSize);
_verifyOperation = new VerifyTempFileOperation(element);
OperationSystem.StartOperation(_fileSystem.PackageName, _verifyOperation);
_steps = ESteps.CheckVerifyTempFile;
@@ -111,7 +103,7 @@ namespace YooAsset
if (_verifyOperation.Status == EOperationStatus.Succeed)
{
if (_fileSystem.WriteFile(Bundle, _fileSavePath))
if (_fileSystem.WriteCacheFile(Bundle, _tempFilePath))
{
Status = EOperationStatus.Succeed;
_steps = ESteps.Done;
@@ -131,8 +123,8 @@ namespace YooAsset
}
// 注意:验证完成后直接删除文件
if (File.Exists(_fileSavePath))
File.Delete(_fileSavePath);
if (File.Exists(_tempFilePath))
File.Delete(_tempFilePath);
}
// 重新尝试下载
@@ -183,7 +175,7 @@ namespace YooAsset
private void CreateWebRequest()
{
_webRequest = DownloadSystemHelper.NewUnityWebRequestGet(_requestURL);
DownloadHandlerFile handler = new DownloadHandlerFile(_fileSavePath);
DownloadHandlerFile handler = new DownloadHandlerFile(_tempFilePath);
handler.removeFileOnAbort = true;
_webRequest.downloadHandler = handler;
_webRequest.disposeDownloadHandlerOnDispose = true;
@@ -210,7 +202,8 @@ namespace YooAsset
private ESteps _steps = ESteps.None;
internal DCFSDownloadResumeFileOperation(DefaultCacheFileSystem fileSystem, PackageBundle bundle, string mainURL, string fallbackURL, int failedTryAgain, int timeout)
internal DCFSDownloadResumeFileOperation(DefaultCacheFileSystem fileSystem, PackageBundle bundle,
string mainURL, string fallbackURL, int failedTryAgain, int timeout)
: base(bundle, mainURL, fallbackURL, failedTryAgain, timeout)
{
_fileSystem = fileSystem;
@@ -248,19 +241,10 @@ namespace YooAsset
_requestURL = GetRequestURL();
// 重置变量
_isAbort = false;
_latestDownloadBytes = 0;
_latestDownloadRealtime = Time.realtimeSinceStartup;
_fileOriginLength = 0;
DownloadProgress = 0f;
DownloadedBytes = 0;
// 重置计时器
if (_tryAgainTimer > 0f)
YooLogger.Warning($"Try again download : {_requestURL}");
_tryAgainTimer = 0f;
ResetRequestFiled();
// 获取下载起始位置
_fileOriginLength = 0;
long fileBeginLength = -1;
if (File.Exists(_fileSavePath))
{
@@ -325,7 +309,7 @@ namespace YooAsset
if (_verifyOperation.Status == EOperationStatus.Succeed)
{
if (_fileSystem.WriteFile(Bundle, _fileSavePath))
if (_fileSystem.WriteCacheFile(Bundle, _fileSavePath))
{
Status = EOperationStatus.Succeed;
_steps = ESteps.Done;
@@ -29,7 +29,7 @@ namespace YooAsset
}
internal override void InternalOnStart()
{
if (_fileSystem.CheckNeedDownload(_bundle))
if (_fileSystem.NeedDownload(_bundle))
{
_steps = ESteps.DownloadFile;
}
@@ -112,7 +112,7 @@ namespace YooAsset
{
// 注意:当缓存文件的校验等级为Low的时候,并不能保证缓存文件的完整性。
// 说明:在AssetBundle文件加载失败的情况下,我们需要重新验证文件的完整性!
EFileVerifyResult result = _fileSystem.VerifyFile(_bundle);
EFileVerifyResult result = _fileSystem.VerifyCacheFile(_bundle);
if (result == EFileVerifyResult.Succeed)
{
// 注意:在安卓移动平台,华为和三星真机上有极小概率加载资源包失败。
@@ -146,7 +146,7 @@ namespace YooAsset
else
{
_steps = ESteps.Done;
_fileSystem.DeleteFile(_bundle);
_fileSystem.DeleteCacheFile(_bundle.BundleGUID);
Status = EOperationStatus.Failed;
Error = $"Find corrupted file and delete the file : {_bundle.BundleName}";
YooLogger.Error(Error);
@@ -215,7 +215,7 @@ namespace YooAsset
}
internal override void InternalOnStart()
{
if (_fileSystem.CheckNeedDownload(_bundle))
if (_fileSystem.NeedDownload(_bundle))
{
_steps = ESteps.DownloadFile;
}
@@ -81,7 +81,7 @@ namespace YooAsset
foreach (var chidDirectory in childDirectories)
{
string bundleGUID = chidDirectory.Name;
if (_fileSystem.Exists(bundleGUID))
if (_fileSystem.IsRecordFile(bundleGUID))
continue;
// 创建验证元素类
@@ -159,7 +159,7 @@ namespace YooAsset
{
_succeedCount++;
var fileWrapper = new DefaultCacheFileSystem.FileWrapper(element.InfoFilePath, element.DataFilePath, element.DataFileCRC, element.DataFileSize);
_fileSystem.Record(element.BundleGUID, fileWrapper);
_fileSystem.RecordFile(element.BundleGUID, fileWrapper);
}
else
{