-
Bug
-
Resolution: Unresolved
-
Low
-
None
-
6.13.10, 7.4.1, 7.5.0
-
None
-
3
-
Severity 3 - Minor
-
Issue Summary
When exporting a Space to XML, Confluence copies pages' attachments from the attachments directory <confluence-home>/attachments/ver003/ to a temporary directory such as <confluence-home>/temp/xmlexport-<date>/attachments/<pageId>/<attachmentID>.
If Confluence is unable to create any of the directories in the above structure, the export fails on a subsequent operation without a meaningful entry in the log on why the directory wasn't created.
The reason why the directory wasn't created isn't the problem for this bug, since it could be something on the OS level.
The problem is that Confluence uses a method that doesn't throw an exception if creating a directory fails.
Steps to Reproduce
The steps below is a way to reproduce a problem on which Confluence tries to create a directory but it isn't possible due to a problem on the OS level.
The problem on the OS isn't the goal for this bug. This occurs because of a limitation of ext3 file system on a maximum number of subdirectories, which will be reached during the export.
- Have a Linux server with an ext3 partition with enough space to install Confluence.
- Install a vanilla instance of Confluence making sure <confluence-home> is on the ext3 file system.
- This is validated in Confluence 6.13.10 and 7.4.1.
- Confluence still uses the same code path on 7.5.0.
- Create a sample space.
- On that space, create 35,000 pages with one attachment in each.
- The following script may be helpful to automate that task.
USRNAME=admin USRPWD=admin CONFBASEURL=http://127.0.0.1:8090/conf741 SPACE_KEY=TS2 PARENT_PAGEID=786434 PAGE_TITLE_PRE=PageNumber INIT_PAGE=1 MAX_PAGES=35000 for PAGE_NUM in $(seq ${INIT_PAGE} ${MAX_PAGES}); do NEW_PAGE_ID=$(curl --user $USRNAME:$USRPWD \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -d '{"type":"page","title":"'$PAGE_TITLE_PRE$PAGE_NUM'", "ancestors":[{"type":"page","id":'$PARENT_PAGEID'}], "space":{"key":"'$SPACE_KEY'"},"body":{"storage":{"value":"<p>This is <br/> another new page</p>","representation": "storage"}}}' \ -X POST $CONFBASEURL/rest/api/content 2>/dev/null | jq -r '.id') echo "$PAGE_TITLE_PRE$PAGE_NUM created with pageid: ${NEW_PAGE_ID}" FILENAME=testing${PAGE_NUM}.txt echo "this is a text file" > $FILENAME curl -D- -u $USRNAME:$USRPWD \ -X POST \ -H "X-Atlassian-Token: nocheck" -F "file=@${FILENAME}" -F "comment=This is my File" \ ${CONFBASEURL}/rest/api/content/${NEW_PAGE_ID}/child/attachment >/dev/null 2>&1 rm -f $FILENAME done
- The following script may be helpful to automate that task.
- Try to export the Space as XML.
Expected Results
The Space export fails because it wasn't able to create a directory to place one of the attachments.
Checking the Confluence logs we would see an exception thrown during the directory creation and a meaningful message to understand why it couldn't create the directory.
Actual Results
The Space export fails because it wasn't able to create a temporary file in the target directory because one of the directories in the expected hierarchy didn't exist.
There's no meaningful entry in the log telling which specific directory wasn't created and why.
2020-06-17 21:02:37,069 ERROR [Long running task: Export Space] [confluence.importexport.actions.ExportSpaceLongRunningTask] doInTransactionWithoutResult Error during export -- url: /spaces/doexportspace.action | referer: http://10.125.91.230:8090/spaces/exportspacexml.action?key=SO | traceId: bfffe08bb52b53d2 | userName: admin | action: doexportspace java.lang.RuntimeException: Error creating temp file in folder: /home/ubuntu/deployments/conf741/confluence-home/temp/xmlexport-20200617-201632-1/attachments/1342429/1342433 at com.atlassian.confluence.pages.persistence.dao.filesystem.FileSystemAttachmentDataUtil.createTempFile(FileSystemAttachmentDataUtil.java:66) at com.atlassian.confluence.pages.persistence.dao.filesystem.FileSystemAttachmentDataUtil.writeStreamToFile(FileSystemAttachmentDataUtil.java:37) at com.atlassian.confluence.pages.persistence.dao.FileSystemAttachmentDataDao.writeStreamToFile(FileSystemAttachmentDataDao.java:253) at com.atlassian.confluence.pages.persistence.dao.FileSystemAttachmentDataDao.saveDataForAttachment(FileSystemAttachmentDataDao.java:240) at com.atlassian.confluence.pages.persistence.dao.FileSystemAttachmentDataDao.saveDataForAttachment(FileSystemAttachmentDataDao.java:205) at com.atlassian.confluence.pages.persistence.dao.hibernate.AbstractHibernateAttachmentDao$IntraHibernateAttachmentCopier.saveAttachmentData(AbstractHibernateAttachmentDao.java:869) at com.atlassian.confluence.pages.persistence.dao.hibernate.AbstractHibernateAttachmentDao$IntraHibernateAttachmentCopier.copy(AbstractHibernateAttachmentDao.java:840) at com.atlassian.confluence.importexport.impl.FileXmlExporter.backupAttachments(FileXmlExporter.java:160) at com.atlassian.confluence.importexport.impl.FileXmlExporter.backupEverything(FileXmlExporter.java:99) at com.atlassian.confluence.importexport.impl.AbstractXmlExporter.doExport(AbstractXmlExporter.java:94) at com.atlassian.confluence.importexport.impl.FileXmlExporter.doExportInternal(FileXmlExporter.java:60) at com.atlassian.confluence.importexport.impl.FileXmlExporter.doExport(FileXmlExporter.java:54) at com.atlassian.confluence.importexport.impl.XmlExporter.doExport(XmlExporter.java:52) at com.atlassian.confluence.importexport.DefaultImportExportManager.doExport(DefaultImportExportManager.java:212) at com.atlassian.confluence.importexport.DefaultImportExportManager.exportAs(DefaultImportExportManager.java:178) (...) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) Caused by: java.io.IOException: No such file or directory at java.io.UnixFileSystem.createFileExclusively(Native Method) at java.io.File.createTempFile(File.java:2024) at com.atlassian.confluence.pages.persistence.dao.filesystem.FileSystemAttachmentDataUtil.createTempFile(FileSystemAttachmentDataUtil.java:64) ... 43 more
This occurs because this portion of the code was implemented using java.io.Files.mkdirs() method which doesn't throw any exception when it fails.
Although this method doesn't throw an exception on failure, it provide an option to check if it went successfully, which is not used within the code.
An option could be to migrate to java.nio.file.Files.createDirectories() method.
Workaround
Currently there is no known workaround for this behavior. A workaround will be added here when available