简称和并行文件复制
shortnames and parallel file copy
我正在处理的代码是:
枚举源目录和目标目录并生成 {src
, dst
} 对
...每对都被发送到工作线程池
... 执行工作,例如 "copy src
to dst
"
(所有这些都简化了很多)。
问题:
创建文件时,它还会获得一个短名称,该短名称可以与源目录中的另一个文件相同(名称冲突),这会导致各种影响(取决于操作顺序)。例如,复制两个文件 my file
和 MYFILE~1
可以在目标位置生成 2 个或 1 个文件(取决于您的运气),可能内容已损坏(在后一种情况下)。
问题:
如何避免此类碰撞产生的问题?最好有一个函数 creates/opens 文件忽略短名称...
备注:
不能假设短名称的生成方式。各种系统采用不同的方案(参见this)
即使您 运行 这些作业以顺序方式(一个接一个)进行——它们需要按顺序执行,这取决于短名称生成逻辑(未知) .另外,这意味着在 运行 任何作业
之前加载并 sorting/etc 整个目录在内存中
源和目标都可以很大(可能有数百万个文件),(如果可能的话)我想避免将整个目录加载到内存中或多次枚举它
无法关闭目标卷中的短名称生成并且将其作为一项要求不是一个选项(另外,关闭它不会删除现有的短名称)
应用程序仅限于 Win32 API 和 NT API
编辑: 我突然想到,在一般情况下,即使所有事情都发生在一个线程上,您也无法做到这一点——仅仅是因为无论您选择的顺序如何,都会有是一个短名称生成方案和一组保证在处理过程中产生冲突的文件名。
如果这是正确的 -- 系统实用程序如何复制文件?在复制完成后,他们会假设一些短名称或执行 "validate and fix discrepancies" 吗?
问题基本上可以归结为以下几点:dst
不应该通过 shortname
打开。
例如(在 NT API
的情况下)可以这样实现:
打开时(NtCreateFile()
,不截断)dst
使用FILE_OPEN_IF
作为CreateDisposition
成功检查 IoStatusBlock::Information
文件是否已创建 (FILE_CREATED
)
如果是 -- 什么都不用做(不可能通过短名称创建文件)
if no -- 通过NtQueryInformationFile(FileNameInformation)
检查当前文件名
- 如果名称与提供给
NtCreateFile()
的名称不同 (case-sensitivity!) -- 错误
并行进程可能会在您打开文件后立即重命名文件,但我会将其视为错误。
错误可能导致重试几次,然后是硬故障(需要人工注意)。由于 NtQueryInformationFile()
.
返回冲突文件的名称,因此手动(或什至以编程方式)修复问题应该不会太难
P.S。可以采取额外的步骤来解决 prevent/reduce 冲突。例如,如果已知短名称生成逻辑——dst
对象可以按特定顺序处理。
我正在处理的代码是:
枚举源目录和目标目录并生成 {
src
,dst
} 对...每对都被发送到工作线程池
... 执行工作,例如 "copy
src
todst
"
(所有这些都简化了很多)。
问题:
创建文件时,它还会获得一个短名称,该短名称可以与源目录中的另一个文件相同(名称冲突),这会导致各种影响(取决于操作顺序)。例如,复制两个文件 my file
和 MYFILE~1
可以在目标位置生成 2 个或 1 个文件(取决于您的运气),可能内容已损坏(在后一种情况下)。
问题:
如何避免此类碰撞产生的问题?最好有一个函数 creates/opens 文件忽略短名称...
备注:
不能假设短名称的生成方式。各种系统采用不同的方案(参见this)
即使您 运行 这些作业以顺序方式(一个接一个)进行——它们需要按顺序执行,这取决于短名称生成逻辑(未知) .另外,这意味着在 运行 任何作业
之前加载并 sorting/etc 整个目录在内存中
源和目标都可以很大(可能有数百万个文件),(如果可能的话)我想避免将整个目录加载到内存中或多次枚举它
无法关闭目标卷中的短名称生成并且将其作为一项要求不是一个选项(另外,关闭它不会删除现有的短名称)
应用程序仅限于 Win32 API 和 NT API
编辑: 我突然想到,在一般情况下,即使所有事情都发生在一个线程上,您也无法做到这一点——仅仅是因为无论您选择的顺序如何,都会有是一个短名称生成方案和一组保证在处理过程中产生冲突的文件名。
如果这是正确的 -- 系统实用程序如何复制文件?在复制完成后,他们会假设一些短名称或执行 "validate and fix discrepancies" 吗?
问题基本上可以归结为以下几点:dst
不应该通过 shortname
打开。
例如(在 NT API
的情况下)可以这样实现:
打开时(
NtCreateFile()
,不截断)dst
使用FILE_OPEN_IF
作为CreateDisposition
成功检查
IoStatusBlock::Information
文件是否已创建 (FILE_CREATED
)如果是 -- 什么都不用做(不可能通过短名称创建文件)
if no -- 通过
检查当前文件名NtQueryInformationFile(FileNameInformation)
- 如果名称与提供给
NtCreateFile()
的名称不同 (case-sensitivity!) -- 错误
- 如果名称与提供给
并行进程可能会在您打开文件后立即重命名文件,但我会将其视为错误。
错误可能导致重试几次,然后是硬故障(需要人工注意)。由于 NtQueryInformationFile()
.
P.S。可以采取额外的步骤来解决 prevent/reduce 冲突。例如,如果已知短名称生成逻辑——dst
对象可以按特定顺序处理。