@@ -229,6 +229,14 @@ public static function markDeletedFile($path) {
229229 'filename ' => $ filename ];
230230 }
231231
232+ private static function getUserStoragePropagator (string $ uid ): ?IPropagator {
233+ try {
234+ return Server::get (IRootFolder::class)->getUserFolder ($ uid )->getStorage ()->getPropagator ();
235+ } catch (\Exception ) {
236+ return null ;
237+ }
238+ }
239+
232240 /**
233241 * delete the version from the storage and cache
234242 *
@@ -259,10 +267,16 @@ public static function delete($path) {
259267
260268 $ versions = self ::getVersions ($ uid , $ filename );
261269 if (!empty ($ versions )) {
262- foreach ($ versions as $ v ) {
263- \OC_Hook::emit ('\OCP\Versions ' , 'preDelete ' , ['path ' => $ path . $ v ['version ' ], 'trigger ' => self ::DELETE_TRIGGER_MASTER_REMOVED ]);
264- self ::deleteVersion ($ view , $ filename . '.v ' . $ v ['version ' ]);
265- \OC_Hook::emit ('\OCP\Versions ' , 'delete ' , ['path ' => $ path . $ v ['version ' ], 'trigger ' => self ::DELETE_TRIGGER_MASTER_REMOVED ]);
270+ $ propagator = self ::getUserStoragePropagator ($ uid );
271+ $ propagator ?->beginBatch();
272+ try {
273+ foreach ($ versions as $ v ) {
274+ \OC_Hook::emit ('\OCP\Versions ' , 'preDelete ' , ['path ' => $ path . $ v ['version ' ], 'trigger ' => self ::DELETE_TRIGGER_MASTER_REMOVED ]);
275+ self ::deleteVersion ($ view , $ filename . '.v ' . $ v ['version ' ]);
276+ \OC_Hook::emit ('\OCP\Versions ' , 'delete ' , ['path ' => $ path . $ v ['version ' ], 'trigger ' => self ::DELETE_TRIGGER_MASTER_REMOVED ]);
277+ }
278+ } finally {
279+ $ propagator ?->commitBatch();
266280 }
267281 }
268282 }
@@ -614,21 +628,27 @@ public static function expireOlderThanMaxForUser($uid) {
614628 return $ version < $ threshold ;
615629 });
616630
617- foreach ($ versions as $ version ) {
618- $ internalPath = $ version ->getInternalPath ();
619- \OC_Hook::emit ('\OCP\Versions ' , 'preDelete ' , ['path ' => $ internalPath , 'trigger ' => self ::DELETE_TRIGGER_RETENTION_CONSTRAINT ]);
631+ $ propagator = self ::getUserStoragePropagator ($ uid );
632+ $ propagator ?->beginBatch();
633+ try {
634+ foreach ($ versions as $ version ) {
635+ $ internalPath = $ version ->getInternalPath ();
636+ \OC_Hook::emit ('\OCP\Versions ' , 'preDelete ' , ['path ' => $ internalPath , 'trigger ' => self ::DELETE_TRIGGER_RETENTION_CONSTRAINT ]);
620637
621- $ versionEntity = isset ($ versionEntities [$ version ->getId ()]) ? $ versionEntities [$ version ->getId ()] : null ;
622- if (!is_null ($ versionEntity )) {
623- $ versionsMapper ->delete ($ versionEntity );
624- }
638+ $ versionEntity = isset ($ versionEntities [$ version ->getId ()]) ? $ versionEntities [$ version ->getId ()] : null ;
639+ if (!is_null ($ versionEntity )) {
640+ $ versionsMapper ->delete ($ versionEntity );
641+ }
625642
626- try {
627- $ version ->delete ();
628- \OC_Hook::emit ('\OCP\Versions ' , 'delete ' , ['path ' => $ internalPath , 'trigger ' => self ::DELETE_TRIGGER_RETENTION_CONSTRAINT ]);
629- } catch (NotPermittedException $ e ) {
630- Server::get (LoggerInterface::class)->error ("Missing permissions to delete version for user {$ uid }: {$ internalPath }" , ['app ' => 'files_versions ' , 'exception ' => $ e ]);
643+ try {
644+ $ version ->delete ();
645+ \OC_Hook::emit ('\OCP\Versions ' , 'delete ' , ['path ' => $ internalPath , 'trigger ' => self ::DELETE_TRIGGER_RETENTION_CONSTRAINT ]);
646+ } catch (NotPermittedException $ e ) {
647+ Server::get (LoggerInterface::class)->error ("Missing permissions to delete version for user {$ uid }: {$ internalPath }" , ['app ' => 'files_versions ' , 'exception ' => $ e ]);
648+ }
631649 }
650+ } finally {
651+ $ propagator ?->commitBatch();
632652 }
633653 }
634654
@@ -929,47 +949,53 @@ public static function expire($filename, $uid) {
929949 $ versionsSize = $ versionsSize - $ sizeOfDeletedVersions ;
930950 }
931951
932- foreach ($ toDelete as $ key => $ path ) {
933- // Make sure to cleanup version table relations as expire does not pass deleteVersion
934- try {
935- /** @var VersionsMapper $versionsMapper */
936- $ versionsMapper = Server::get (VersionsMapper::class);
937- $ file = Server::get (IRootFolder::class)->getUserFolder ($ uid )->get ($ filename );
938- $ pathparts = pathinfo ($ path );
939- $ timestamp = (int )substr ($ pathparts ['extension ' ] ?? '' , 1 );
940- $ versionEntity = $ versionsMapper ->findVersionForFileId ($ file ->getId (), $ timestamp );
941- if ($ versionEntity ->getMetadataValue ('label ' ) !== null && $ versionEntity ->getMetadataValue ('label ' ) !== '' ) {
942- continue ;
952+ $ propagator = self ::getUserStoragePropagator ($ uid );
953+ $ propagator ?->beginBatch();
954+ try {
955+ foreach ($ toDelete as $ key => $ path ) {
956+ // Make sure to cleanup version table relations as expire does not pass deleteVersion
957+ try {
958+ /** @var VersionsMapper $versionsMapper */
959+ $ versionsMapper = Server::get (VersionsMapper::class);
960+ $ file = Server::get (IRootFolder::class)->getUserFolder ($ uid )->get ($ filename );
961+ $ pathparts = pathinfo ($ path );
962+ $ timestamp = (int )substr ($ pathparts ['extension ' ] ?? '' , 1 );
963+ $ versionEntity = $ versionsMapper ->findVersionForFileId ($ file ->getId (), $ timestamp );
964+ if ($ versionEntity ->getMetadataValue ('label ' ) !== null && $ versionEntity ->getMetadataValue ('label ' ) !== '' ) {
965+ continue ;
966+ }
967+ $ versionsMapper ->delete ($ versionEntity );
968+ } catch (DoesNotExistException $ e ) {
943969 }
944- $ versionsMapper ->delete ($ versionEntity );
945- } catch (DoesNotExistException $ e ) {
946- }
947970
948- \OC_Hook::emit ('\OCP\Versions ' , 'preDelete ' , ['path ' => $ path , 'trigger ' => self ::DELETE_TRIGGER_QUOTA_EXCEEDED ]);
949- self ::deleteVersion ($ versionsFileview , $ path );
950- \OC_Hook::emit ('\OCP\Versions ' , 'delete ' , ['path ' => $ path , 'trigger ' => self ::DELETE_TRIGGER_QUOTA_EXCEEDED ]);
951- unset($ allVersions [$ key ]); // update array with the versions we keep
952- $ logger ->info ('Expire: ' . $ path , ['app ' => 'files_versions ' ]);
953- }
971+ \OC_Hook::emit ('\OCP\Versions ' , 'preDelete ' , ['path ' => $ path , 'trigger ' => self ::DELETE_TRIGGER_QUOTA_EXCEEDED ]);
972+ self ::deleteVersion ($ versionsFileview , $ path );
973+ \OC_Hook::emit ('\OCP\Versions ' , 'delete ' , ['path ' => $ path , 'trigger ' => self ::DELETE_TRIGGER_QUOTA_EXCEEDED ]);
974+ unset($ allVersions [$ key ]); // update array with the versions we keep
975+ $ logger ->info ('Expire: ' . $ path , ['app ' => 'files_versions ' ]);
976+ }
954977
955- // Check if enough space is available after versions are rearranged.
956- // If not we delete the oldest versions until we meet the size limit for versions,
957- // but always keep the two latest versions
958- $ numOfVersions = count ($ allVersions ) - 2 ;
959- $ i = 0 ;
960- // sort oldest first and make sure that we start at the first element
961- ksort ($ allVersions );
962- reset ($ allVersions );
963- while ($ availableSpace < 0 && $ i < $ numOfVersions ) {
964- $ version = current ($ allVersions );
965- \OC_Hook::emit ('\OCP\Versions ' , 'preDelete ' , ['path ' => $ version ['path ' ] . '.v ' . $ version ['version ' ], 'trigger ' => self ::DELETE_TRIGGER_QUOTA_EXCEEDED ]);
966- self ::deleteVersion ($ versionsFileview , $ version ['path ' ] . '.v ' . $ version ['version ' ]);
967- \OC_Hook::emit ('\OCP\Versions ' , 'delete ' , ['path ' => $ version ['path ' ] . '.v ' . $ version ['version ' ], 'trigger ' => self ::DELETE_TRIGGER_QUOTA_EXCEEDED ]);
968- $ logger ->info ('running out of space! Delete oldest version: ' . $ version ['path ' ] . '.v ' . $ version ['version ' ], ['app ' => 'files_versions ' ]);
969- $ versionsSize -= $ version ['size ' ];
970- $ availableSpace += $ version ['size ' ];
971- next ($ allVersions );
972- $ i ++;
978+ // Check if enough space is available after versions are rearranged.
979+ // If not we delete the oldest versions until we meet the size limit for versions,
980+ // but always keep the two latest versions
981+ $ numOfVersions = count ($ allVersions ) - 2 ;
982+ $ i = 0 ;
983+ // sort oldest first and make sure that we start at the first element
984+ ksort ($ allVersions );
985+ reset ($ allVersions );
986+ while ($ availableSpace < 0 && $ i < $ numOfVersions ) {
987+ $ version = current ($ allVersions );
988+ \OC_Hook::emit ('\OCP\Versions ' , 'preDelete ' , ['path ' => $ version ['path ' ] . '.v ' . $ version ['version ' ], 'trigger ' => self ::DELETE_TRIGGER_QUOTA_EXCEEDED ]);
989+ self ::deleteVersion ($ versionsFileview , $ version ['path ' ] . '.v ' . $ version ['version ' ]);
990+ \OC_Hook::emit ('\OCP\Versions ' , 'delete ' , ['path ' => $ version ['path ' ] . '.v ' . $ version ['version ' ], 'trigger ' => self ::DELETE_TRIGGER_QUOTA_EXCEEDED ]);
991+ $ logger ->info ('running out of space! Delete oldest version: ' . $ version ['path ' ] . '.v ' . $ version ['version ' ], ['app ' => 'files_versions ' ]);
992+ $ versionsSize -= $ version ['size ' ];
993+ $ availableSpace += $ version ['size ' ];
994+ next ($ allVersions );
995+ $ i ++;
996+ }
997+ } finally {
998+ $ propagator ?->commitBatch();
973999 }
9741000
9751001 return $ versionsSize ; // finally return the new size of the version history
0 commit comments