diff --git a/bbb-common-web/src/main/java/org/bigbluebutton/presentation/imp/Office2PdfPageConverter.java b/bbb-common-web/src/main/java/org/bigbluebutton/presentation/imp/Office2PdfPageConverter.java index f78002e686aaa7ee050ce8b066c4b6e29e8181a7..c8ca293cfa9ed207921528622a2eac70e14f42aa 100755 --- a/bbb-common-web/src/main/java/org/bigbluebutton/presentation/imp/Office2PdfPageConverter.java +++ b/bbb-common-web/src/main/java/org/bigbluebutton/presentation/imp/Office2PdfPageConverter.java @@ -39,7 +39,7 @@ public abstract class Office2PdfPageConverter { private static Logger log = LoggerFactory.getLogger(Office2PdfPageConverter.class); public static boolean convert(File presentationFile, File output, int page, UploadedPresentation pres, - String presOfficeConversionExec){ + String presOfficeConversionExec, int conversionTimeout) { try { Map<String, Object> logData = new HashMap<>(); @@ -61,11 +61,12 @@ public abstract class Office2PdfPageConverter { NuProcessBuilder officeConverterExec = new NuProcessBuilder(Arrays.asList(presOfficeConversionExec, presentationFile.getAbsolutePath(), output.getAbsolutePath())); Office2PdfConverterHandler office2PdfConverterHandler = new Office2PdfConverterHandler(); + officeConverterExec.setProcessListener(office2PdfConverterHandler); NuProcess process = officeConverterExec.start(); try { - process.waitFor(0, TimeUnit.SECONDS); + process.waitFor(conversionTimeout, TimeUnit.SECONDS); } catch (InterruptedException e) { log.error("InterruptedException while counting PDF pages {}", presentationFile.getName(), e); } @@ -104,4 +105,6 @@ public abstract class Office2PdfPageConverter { } } + + } diff --git a/bbb-common-web/src/main/java/org/bigbluebutton/presentation/imp/OfficeToPdfConversionService.java b/bbb-common-web/src/main/java/org/bigbluebutton/presentation/imp/OfficeToPdfConversionService.java index 23de66c929fe5326a671260230b11a62ef672ab5..e80202dee7d49e2d2e60911de028be286ab7242c 100644 --- a/bbb-common-web/src/main/java/org/bigbluebutton/presentation/imp/OfficeToPdfConversionService.java +++ b/bbb-common-web/src/main/java/org/bigbluebutton/presentation/imp/OfficeToPdfConversionService.java @@ -28,12 +28,16 @@ import org.slf4j.LoggerFactory; import java.io.File; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.Semaphore; public class OfficeToPdfConversionService { private static Logger log = LoggerFactory.getLogger(OfficeToPdfConversionService.class); private OfficeDocumentValidator2 officeDocumentValidator; private boolean skipOfficePrecheck = false; private String presOfficeConversionExec = null; + private Semaphore presOfficeConversionSemaphore = new Semaphore(4); + private int presOfficeConversionTimeout = 60; + /* * Convert the Office document to PDF. If successful, update * UploadPresentation.uploadedFile with the new PDF out and @@ -93,12 +97,26 @@ public class OfficeToPdfConversionService { presentationFile.getAbsolutePath().lastIndexOf('.')); return new File(filenameWithoutExt + ".pdf"); } - private boolean convertOfficeDocToPdf(UploadedPresentation pres, - File pdfOutput) { + private boolean convertOfficeDocToPdf(UploadedPresentation pres, File pdfOutput) { boolean success = false; int attempts = 0; while(!success) { - success = Office2PdfPageConverter.convert(pres.getUploadedFile(), pdfOutput, 0, pres, presOfficeConversionExec); + + try { + if(presOfficeConversionSemaphore.availablePermits() == 0) { + log.info("Waiting for previous conversions finish before start (meetingId: {}, presId: {}, filename: {}), current queue: {}.", + pres.getMeetingId(), pres.getId(), pres.getName(), presOfficeConversionSemaphore.getQueueLength()); + } + presOfficeConversionSemaphore.acquire(); + + success = Office2PdfPageConverter.convert(pres.getUploadedFile(), pdfOutput, 0, pres, + presOfficeConversionExec, presOfficeConversionTimeout); + + } catch (Exception e) { + } finally { + presOfficeConversionSemaphore.release(); + } + if(!success) { if(++attempts != 3) { @@ -129,5 +147,13 @@ public class OfficeToPdfConversionService { this.presOfficeConversionExec = presOfficeConversionExec; } + public void setPresOfficeConversionTimeout(int presOfficeConversionTimeout) { + this.presOfficeConversionTimeout = presOfficeConversionTimeout; + } + + public void setPresOfficeConversionMaxConcurrents(int presOfficeConversionMaxConcurrents) { + presOfficeConversionSemaphore = new Semaphore(presOfficeConversionMaxConcurrents); + } + } diff --git a/bbb-libreoffice/docker-bbb-libreoffice/Dockerfile b/bbb-libreoffice/docker-bbb-libreoffice/Dockerfile deleted file mode 100644 index eb5669bec1fd6c7f36e36caa7cab778d6b36dd93..0000000000000000000000000000000000000000 --- a/bbb-libreoffice/docker-bbb-libreoffice/Dockerfile +++ /dev/null @@ -1,16 +0,0 @@ -FROM openjdk:8-jre - -ENV DEBIAN_FRONTEND noninteractive - -RUN apt update - -RUN apt -y install locales-all fontconfig libxt6 libxrender1 -RUN apt -y install --no-install-recommends libreoffice fonts-crosextra-carlito fonts-crosextra-caladea fonts-noto fonts-noto-cjk - - -RUN dpkg-reconfigure fontconfig && fc-cache -f -s -v - -VOLUME ["/usr/share/fonts/"] -ADD ./bbb-libreoffice-entrypoint.sh /usr/local/bin/ - -ENTRYPOINT ["/usr/local/bin/bbb-libreoffice-entrypoint.sh" ] diff --git a/bbb-libreoffice/docker-bbb-libreoffice/bbb-libreoffice-entrypoint.sh b/bbb-libreoffice/docker-bbb-libreoffice/bbb-libreoffice-entrypoint.sh deleted file mode 100644 index e94594109498762c1c0c4786007d065d1495d1a8..0000000000000000000000000000000000000000 --- a/bbb-libreoffice/docker-bbb-libreoffice/bbb-libreoffice-entrypoint.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -## Initialize environment -/usr/lib/libreoffice/program/soffice.bin -env:UserInstallation="file:///tmp/" - -## Run daemon -/usr/lib/libreoffice/program/soffice.bin --accept="socket,host=0.0.0.0,port=8000,tcpNoDelay=1;urp;StarOffice.ServiceManager" --headless --invisible --nocrashreport --nodefault --nofirststartwizard --nolockcheck --nologo --norestore -env:UserInstallation="file:///tmp/" diff --git a/bbb-libreoffice/install.sh b/bbb-libreoffice/install-local.sh similarity index 79% rename from bbb-libreoffice/install.sh rename to bbb-libreoffice/install-local.sh index e3641a05df403958069640728143e92e539f68d1..d7daa9970b3d423bb0a469895c62f99e8e556c48 100755 --- a/bbb-libreoffice/install.sh +++ b/bbb-libreoffice/install-local.sh @@ -4,6 +4,8 @@ if [ "$EUID" -ne 0 ]; then exit 1; fi; +cd "$(dirname "$0")" + DOCKER_CHECK=`docker --version &> /dev/null && echo 1 || echo 0` if [ "$DOCKER_CHECK" = "0" ]; then @@ -21,9 +23,6 @@ else echo "Docker already installed"; fi -#Uninstall old version of docker and service if exists (keep temporarily) -./uninstall-bbb-libreoffice.sh - IMAGE_CHECK=`docker image inspect bbb-soffice &> /dev/null && echo 1 || echo 0` if [ "$IMAGE_CHECK" = "0" ]; then echo "Docker image doesn't exists, building" @@ -36,11 +35,7 @@ FOLDER_CHECK=`[ -d /usr/share/bbb-libreoffice-conversion/ ] && echo 1 || echo 0` if [ "$FOLDER_CHECK" = "0" ]; then echo "Install folder doesn't exists, installing" mkdir -m 755 /usr/share/bbb-libreoffice-conversion/ - cp assets/convert-local.sh /usr/share/bbb-libreoffice-conversion/ - cp assets/convert-remote.sh /usr/share/bbb-libreoffice-conversion/ - ln -sfn /usr/share/bbb-libreoffice-conversion/convert-local.sh /usr/share/bbb-libreoffice-conversion/convert.sh - chmod 755 /usr/share/bbb-libreoffice-conversion/convert-local.sh - chmod 755 /usr/share/bbb-libreoffice-conversion/convert-remote.sh + cp assets/convert-local.sh /usr/share/bbb-libreoffice-conversion/convert.sh chmod 755 /usr/share/bbb-libreoffice-conversion/convert.sh chown -R root /usr/share/bbb-libreoffice-conversion/ else diff --git a/bbb-libreoffice/install-remote.sh b/bbb-libreoffice/install-remote.sh new file mode 100755 index 0000000000000000000000000000000000000000..68a7814207f88fc248fd17ea4b6148d1ac1f550d --- /dev/null +++ b/bbb-libreoffice/install-remote.sh @@ -0,0 +1,19 @@ +#!/bin/bash +if [ "$EUID" -ne 0 ]; then + echo "Please run this script as root ( or with sudo )" ; + exit 1; +fi; + +cd "$(dirname "$0")" + +FOLDER_CHECK=`[ -d /usr/share/bbb-libreoffice-conversion/ ] && echo 1 || echo 0` +if [ "$FOLDER_CHECK" = "0" ]; then + echo "Install folder doesn't exists, installing" + mkdir -m 755 /usr/share/bbb-libreoffice-conversion/ + cp assets/convert-remote.sh /usr/share/bbb-libreoffice-conversion/convert.sh + chmod 755 /usr/share/bbb-libreoffice-conversion/convert.sh + chown -R root /usr/share/bbb-libreoffice-conversion/ +else + echo "Install folder already exists" +fi; + diff --git a/bbb-libreoffice/uninstall-bbb-libreoffice.sh b/bbb-libreoffice/uninstall-bbb-libreoffice.sh deleted file mode 100755 index 991f4e36c81ffdee7f44ae17b6baf264bef6b76a..0000000000000000000000000000000000000000 --- a/bbb-libreoffice/uninstall-bbb-libreoffice.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash -set -e - -if [ "$EUID" -ne 0 ]; then - echo "Please run this script as root ( or with sudo )" ; - exit 1; -fi; - -IMAGE_CHECK=`docker image inspect bbb-libreoffice 2>&1 > /dev/null && echo 1 || echo 0` -if [ "$IMAGE_CHECK" = "1" ]; then - echo "Stopping services" - systemctl --no-pager --no-legend --value --state=running | grep bbb-libreoffice | awk -F '.service' '{print $1}' | xargs --no-run-if-empty -n 1 systemctl stop - - echo "Removing image" - docker image rm bbb-libreoffice -fi - -FOLDER_CHECK=`[ -d /usr/share/bbb-libreoffice/ ] && echo 1 || echo 0` -if [ "$FOLDER_CHECK" = "1" ]; then - echo "Stopping services" - systemctl --no-pager --no-legend --value --state=running | grep bbb-libreoffice | awk -F '.service' '{print $1}' | xargs --no-run-if-empty -n 1 systemctl stop - - echo "Removing install folder" - rm -rf /usr/share/bbb-libreoffice/ - - echo "Removing service definitions" - rm /lib/systemd/system/bbb-libreoffice@.service - find /etc/systemd/ | grep bbb-libreoffice | xargs --no-run-if-empty -n 1 -I __ rm __ - systemctl daemon-reload -fi; - -NETWORK_CHECK=`docker network inspect bbb-libreoffice &> /dev/null && echo 1 || echo 0` -if [ "$NETWORK_CHECK" = "1" ]; then - echo "Removing docker network" - docker network remove bbb-libreoffice -fi - diff --git a/bbb-libreoffice/uninstall.sh b/bbb-libreoffice/uninstall-local.sh similarity index 68% rename from bbb-libreoffice/uninstall.sh rename to bbb-libreoffice/uninstall-local.sh index c8143ccfa6b9d08ce605123864bdb50f7e70cf24..6a97af3c3d19063285ac1c0d28b6b7d9d4565d35 100755 --- a/bbb-libreoffice/uninstall.sh +++ b/bbb-libreoffice/uninstall-local.sh @@ -7,10 +7,6 @@ if [ "$EUID" -ne 0 ]; then fi; -#Uninstall old version of docker and service if exists (keep temporarily) -./uninstall-bbb-libreoffice.sh - - IMAGE_CHECK=`docker image inspect bbb-soffice 2>&1 > /dev/null && echo 1 || echo 0` if [ "$IMAGE_CHECK" = "1" ]; then echo "Removing image" @@ -28,11 +24,3 @@ if [ "$FILE_SUDOERS_CHECK" = "1" ]; then echo "Removing Sudoers file" rm /etc/sudoers.d/zzz-bbb-docker-libreoffice fi; - - -NETWORK_CHECK=`docker network inspect bbb-libreoffice &> /dev/null && echo 1 || echo 0` -if [ "$NETWORK_CHECK" = "1" ]; then - echo "Removing docker network" - docker network remove bbb-libreoffice -fi - diff --git a/bbb-libreoffice/uninstall-remote.sh b/bbb-libreoffice/uninstall-remote.sh new file mode 100755 index 0000000000000000000000000000000000000000..9ed8f50b4ce68291ef1366b48dfd96c40944ea1b --- /dev/null +++ b/bbb-libreoffice/uninstall-remote.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -e + +if [ "$EUID" -ne 0 ]; then + echo "Please run this script as root ( or with sudo )" ; + exit 1; +fi; + + +FOLDER_CHECK=`[ -d /usr/share/bbb-libreoffice-conversion/ ] && echo 1 || echo 0` +if [ "$FOLDER_CHECK" = "1" ]; then + echo "Removing install folder" + rm -rf /usr/share/bbb-libreoffice-conversion/ +fi; diff --git a/bigbluebutton-web/grails-app/conf/bigbluebutton.properties b/bigbluebutton-web/grails-app/conf/bigbluebutton.properties index 30bbcf15ef702a7f6e05eb73a28d1608c219fbc5..c618b764ca5798d6cc080cf19675610bf5215939 100755 --- a/bigbluebutton-web/grails-app/conf/bigbluebutton.properties +++ b/bigbluebutton-web/grails-app/conf/bigbluebutton.properties @@ -98,6 +98,16 @@ numConversionThreads=5 #------------------------------------ numFileProcessorThreads=2 +#------------------------------------ +# Timeout(secs) to wait for conversion script execution +#------------------------------------ +officeToPdfConversionTimeout=60 + +#------------------------------------ +# Max concurrent of conversion script execution +#------------------------------------ +officeToPdfMaxConcurrentConversions=4 + #---------------------------------------------------- # Conversion of the presentation slides to SWF to be # used in the Flash client diff --git a/bigbluebutton-web/grails-app/conf/spring/doc-conversion.xml b/bigbluebutton-web/grails-app/conf/spring/doc-conversion.xml index 6c08a782cde840c0517fd1392719a38b15c2bcd4..c5ab9192081adac7a47c4828f264c6f94a9f9f72 100755 --- a/bigbluebutton-web/grails-app/conf/spring/doc-conversion.xml +++ b/bigbluebutton-web/grails-app/conf/spring/doc-conversion.xml @@ -38,6 +38,8 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. <property name="officeDocumentValidator" ref="officeDocumentValidator"/> <property name="skipOfficePrecheck" value="${skipOfficePrecheck}"/> <property name="presOfficeConversionExec" value="${presOfficeConversionExec:/usr/share/bbb-libreoffice-conversion/convert.sh}"/> + <property name="presOfficeConversionTimeout" value="${officeToPdfConversionTimeout}"/> + <property name="presOfficeConversionMaxConcurrents" value="${officeToPdfMaxConcurrentConversions}"/> </bean> <bean id="pageExtractor" class="org.bigbluebutton.presentation.imp.PageExtractorImp"/>