diff --git a/src/main/java/org/olat/course/statistic/AsyncExportManager.java b/src/main/java/org/olat/course/statistic/AsyncExportManager.java index 24e9a39194bcbc152e5470e5ebe12d955be606ea..9e910db52ea4c0c279d69b8658cc9226b05f3472 100644 --- a/src/main/java/org/olat/course/statistic/AsyncExportManager.java +++ b/src/main/java/org/olat/course/statistic/AsyncExportManager.java @@ -51,7 +51,7 @@ public class AsyncExportManager extends BasicManager { private static AsyncExportManager INSTANCE; /** set via spring **/ - private int concurrentExportsPerNode_ = 2; + private int concurrentExportsPerNode_ = 1; private TaskExecutorManager taskExecutorManager; @@ -105,24 +105,55 @@ public class AsyncExportManager extends BasicManager { log_.info("asyncArchiveCourseLogFiles: user "+identity.getName()+" wants to archive a course log. Already pending jobs: "+waitingCnt_); } - taskExecutorManager.execute(new Runnable() { + CourseLogRunnable run = new CourseLogRunnable(identity, callback, oresID, exportDir, begin, end, adminLog, userLog, statisticLog, charset, locale, email); + taskExecutorManager.execute(run); + } + + public static class CourseLogRunnable implements Runnable { + + private final Identity identity; + private final Runnable callback; + private final Long oresID; + private final String exportDir; + private final Date begin; + private final Date end; + private final boolean adminLog; + private final boolean userLog; + private final boolean statisticLog; + private final String charset; + private final Locale locale; + private final String email; + + public CourseLogRunnable(Identity identity, Runnable callback, Long oresID, String exportDir, Date begin, Date end, + boolean adminLog, boolean userLog, boolean statisticLog, String charset, Locale locale, String email) { + this.identity = identity; + this.callback = callback; + this.oresID = oresID; + this.exportDir = exportDir; + this.begin = begin; + this.end = end; + this.adminLog = adminLog; + this.userLog = userLog; + this.statisticLog = statisticLog; + this.charset = charset; + this.locale = locale; + this.email = email; + } - @Override - public void run() { - try{ - log_.info("asyncArchiveCourseLogFiles: user "+identity.getName()+" aquires lock for archiving course log"); - waitForSlot(identity); - log_.info("asyncArchiveCourseLogFiles: user "+identity.getName()+" starts archiving..."); - ExportManager.getInstance().archiveCourseLogFiles(oresID, exportDir, begin, end, adminLog, userLog, statisticLog, charset, locale, email); - log_.info("asyncArchiveCourseLogFiles: user "+identity.getName()+" finished archiving..."); - } finally { - returnSlot(identity); - log_.info("asyncArchiveCourseLogFiles: user "+identity.getName()+" releases lock for archiving course log"); - callback.run(); - } + @Override + public void run() { + try{ + log_.info("asyncArchiveCourseLogFiles: user "+identity.getName()+" aquires lock for archiving course log"); + AsyncExportManager.getInstance().waitForSlot(identity); + log_.info("asyncArchiveCourseLogFiles: user "+identity.getName()+" starts archiving..."); + ExportManager.getInstance().archiveCourseLogFiles(oresID, exportDir, begin, end, adminLog, userLog, statisticLog, charset, locale, email); + log_.info("asyncArchiveCourseLogFiles: user "+identity.getName()+" finished archiving..."); + } finally { + AsyncExportManager.getInstance().returnSlot(identity); + log_.info("asyncArchiveCourseLogFiles: user "+identity.getName()+" releases lock for archiving course log"); + callback.run(); } - - }); + } } public synchronized boolean asyncArchiveCourseLogOngoingFor(Identity identity) { diff --git a/src/main/java/org/olat/course/statistic/ExportManager.java b/src/main/java/org/olat/course/statistic/ExportManager.java index 8c6f5a5ef8457942d356fc3fa044d775bc07724a..7e66a14a86be04dda2243e5e9d33adc3c1248273 100644 --- a/src/main/java/org/olat/course/statistic/ExportManager.java +++ b/src/main/java/org/olat/course/statistic/ExportManager.java @@ -127,13 +127,13 @@ public class ExportManager extends BasicManager { */ public void archiveCourseLogFiles(Long oresID, String exportDir, Date begin, Date end, boolean adminLog, boolean userLog, boolean statisticLog, String charset, Locale locale, String email){ - String zipName = ExportUtil.createFileNameWithTimeStamp(ExportManager.COURSE_LOG_FILES, "zip"); - Date date = new Date(); - String tmpDirName = oresID + "-" + date.getTime(); - final VFSContainer tmpDirVFSContainer = new LocalFolderImpl(new File(WebappHelper.getTmpDir(), tmpDirName)); + String zipName = ExportUtil.createFileNameWithTimeStamp(ExportManager.COURSE_LOG_FILES, "zip"); + Date date = new Date(); + String tmpDirName = oresID + "-" + date.getTime(); + final VFSContainer tmpDirVFSContainer = new LocalFolderImpl(new File(WebappHelper.getTmpDir(), tmpDirName)); final File tmpDir = new File(WebappHelper.getTmpDir(), tmpDirName); - List<VFSItem> logFiles = new ArrayList<VFSItem>(); + List<VFSItem> logFiles = new ArrayList<VFSItem>(); if (adminLog) { logFiles.add(createLogFile(oresID, begin, end, charset, tmpDirVFSContainer, tmpDir, FILENAME_ADMIN_LOG, true, false)); } diff --git a/src/main/java/org/olat/course/statistic/_spring/statisticContext.xml b/src/main/java/org/olat/course/statistic/_spring/statisticContext.xml index 71c3afa3c210d63baba405aee90c653cc03dabe2..c88e1f3fe8c78a2c271d1c17bc3415df486175ed 100644 --- a/src/main/java/org/olat/course/statistic/_spring/statisticContext.xml +++ b/src/main/java/org/olat/course/statistic/_spring/statisticContext.xml @@ -96,13 +96,9 @@ ........................................................................ --> - <bean id="courseLogExporter" - class="org.olat.course.statistic.export.SimpleLogExporter"> - - <property name="logLineConverter"> - <ref bean="logLineConverter"/> - </property> - + <bean id="courseLogExporter" class="org.olat.course.statistic.export.SimpleLogExporter"> + <property name="dbInstance" ref="database"/> + <property name="logLineConverter" ref="logLineConverter"/> </bean> <bean id="logLineConverter" diff --git a/src/main/java/org/olat/course/statistic/export/SimpleLogExporter.java b/src/main/java/org/olat/course/statistic/export/SimpleLogExporter.java index 40ffd9af33dcb1b78145ae28b6fe6a8197c026a5..3a4eae6b8f10fa2c665f838a67de8cb0397eda65 100644 --- a/src/main/java/org/olat/course/statistic/export/SimpleLogExporter.java +++ b/src/main/java/org/olat/course/statistic/export/SimpleLogExporter.java @@ -27,14 +27,22 @@ package org.olat.course.statistic.export; import java.io.File; +import java.io.Writer; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.StandardOpenOption; import java.util.Calendar; import java.util.Date; import java.util.List; -import org.olat.core.commons.persistence.DBFactory; -import org.olat.core.commons.persistence.DBQuery; +import javax.persistence.EntityManager; +import javax.persistence.TemporalType; +import javax.persistence.TypedQuery; + +import org.olat.core.commons.persistence.DB; +import org.olat.core.logging.OLog; +import org.olat.core.logging.Tracing; import org.olat.core.logging.activity.LoggingObject; -import org.olat.core.util.FileUtils; /** * @@ -51,8 +59,10 @@ import org.olat.core.util.FileUtils; */ public class SimpleLogExporter implements ICourseLogExporter { + private static final OLog log = Tracing.createLoggerFor(SimpleLogExporter.class); private static final String LINE_SEPARATOR = System.getProperty("line.separator"); + private DB dbInstance; private LogLineConverter logLineConverter_; private SimpleLogExporter() { @@ -63,9 +73,14 @@ public class SimpleLogExporter implements ICourseLogExporter { public void setLogLineConverter(LogLineConverter logLineConverter) { logLineConverter_ = logLineConverter; } + + public void setDbInstance(DB dbInstance) { + this.dbInstance = dbInstance; + } + @Override public void exportCourseLog(File outFile, String charset, Long resourceableId, Date begin, Date end, boolean resourceAdminAction, boolean anonymize) { - StringBuffer result = new StringBuffer(); + String query = "select v from org.olat.core.logging.activity.LoggingObject v " + "where v.resourceAdminAction = :resAdminAction " + "AND ( " @@ -81,31 +96,44 @@ public class SimpleLogExporter implements ICourseLogExporter { if (end != null) { query = query.concat(" AND (v.creationDate <= :createdBefore)"); } + + EntityManager em = dbInstance.getCurrentEntityManager(); + em.clear(); - DBQuery dbQuery = DBFactory.getInstance().createQuery(query); - dbQuery.setBoolean("resAdminAction", resourceAdminAction); - dbQuery.setString("resId", Long.toString(resourceableId)); + TypedQuery<LoggingObject> dbQuery = em.createQuery(query, LoggingObject.class) + .setParameter("resAdminAction", resourceAdminAction) + .setParameter("resId", Long.toString(resourceableId)); if (begin != null) { - dbQuery.setDate("createdAfter", begin); + dbQuery.setParameter("createdAfter", begin, TemporalType.DATE); } if (end != null) { Calendar cal = Calendar.getInstance(); cal.setTime(end); cal.add(Calendar.DAY_OF_MONTH, 1); end = cal.getTime(); - dbQuery.setDate("createdBefore", end); + dbQuery.setParameter("createdBefore", end, TemporalType.DATE); } - - List queryResult = dbQuery.list(); - result.append(logLineConverter_.getCSVHeader()); - result.append(LINE_SEPARATOR); - for (Object loggingObject : queryResult) { - result.append(logLineConverter_.getCSVRow((LoggingObject)loggingObject, anonymize, resourceableId )); - result.append(LINE_SEPARATOR); + try(Writer out = Files.newBufferedWriter(outFile.toPath(), Charset.forName("UTF-8"), StandardOpenOption.CREATE_NEW)) { + out.append(logLineConverter_.getCSVHeader()); + out.append(LINE_SEPARATOR); + + int count = 0; + List<LoggingObject> queryResult = dbQuery.getResultList(); + for (LoggingObject loggingObject : queryResult) { + out.append(logLineConverter_.getCSVRow(loggingObject, anonymize, resourceableId)); + out.append(LINE_SEPARATOR); + if(count % 1000 == 0) { + out.flush(); + em.clear(); + } + } + + } catch(Exception e) { + log.error("", e); + } finally { + em.clear(); + dbInstance.commitAndCloseSession(); } - - FileUtils.save(outFile, result.toString(), charset); } - } diff --git a/src/main/java/org/olat/modules/wiki/Wiki.java b/src/main/java/org/olat/modules/wiki/Wiki.java index 8bd597aa7d85acbeb353972d848eb2b450bcb697..56f8128f4ee037727054c162c2ceddac26a262b6 100644 --- a/src/main/java/org/olat/modules/wiki/Wiki.java +++ b/src/main/java/org/olat/modules/wiki/Wiki.java @@ -49,6 +49,7 @@ import org.olat.core.util.Formatter; import org.olat.core.util.vfs.VFSContainer; import org.olat.core.util.vfs.VFSItem; import org.olat.core.util.vfs.VFSLeaf; +import org.olat.core.util.vfs.VFSManager; import org.olat.core.util.vfs.filters.VFSLeafFilter; import org.olat.modules.wiki.gui.components.wikiToHtml.FilterUtil; import org.olat.modules.wiki.versioning.ChangeInfo; @@ -82,9 +83,9 @@ public class Wiki implements WikiContainer, Serializable { if(wikiRootContainer == null) throw new AssertException("null values are not allowed for the wiki constructor!"); wikiPages = Collections.synchronizedMap(new HashMap<String, WikiPage>()); this.diffService = WikiManager.getInstance().getDiffService(); - versionsContainer = (VFSContainer) wikiRootContainer.resolve(WikiManager.VERSION_FOLDER_NAME); - pageContainer = (VFSContainer) wikiRootContainer.resolve(WikiManager.WIKI_RESOURCE_FOLDER_NAME); - mediaContainer = (VFSContainer) wikiRootContainer.resolve(WikiContainer.MEDIA_FOLDER_NAME); + versionsContainer = VFSManager.getOrCreateContainer(wikiRootContainer, WikiManager.VERSION_FOLDER_NAME); + pageContainer = VFSManager.getOrCreateContainer(wikiRootContainer, WikiManager.WIKI_RESOURCE_FOLDER_NAME); + mediaContainer = VFSManager.getOrCreateContainer(wikiRootContainer, WikiContainer.MEDIA_FOLDER_NAME); } /** diff --git a/src/main/java/org/olat/modules/wiki/WikiManager.java b/src/main/java/org/olat/modules/wiki/WikiManager.java index 25528ab195df0265c2858d63100337160ad624b9..51daa64fd4ca4f1fa74bd3f13ff9a7354aa280ae 100644 --- a/src/main/java/org/olat/modules/wiki/WikiManager.java +++ b/src/main/java/org/olat/modules/wiki/WikiManager.java @@ -208,6 +208,8 @@ public class WikiManager { Files.createDirectories(wikiDir); mediaDir = destDir.resolve(WikiContainer.MEDIA_FOLDER_NAME); Files.createDirectories(mediaDir); + Path versionDir = destDir.resolve(VERSION_FOLDER_NAME); + Files.createDirectories(versionDir); } @Override