Search in sources :

Example 1 with OpLockInterface

use of org.alfresco.jlan.server.locking.OpLockInterface in project alfresco-repository by Alfresco.

the class ContentDiskDriver method closeFile.

/**
 * Close the file.
 *
 * @param sess Server session
 * @param tree Tree connection.
 * @param file Network file context.
 * @exception java.io.IOException If an error occurs.
 */
public void closeFile(SrvSession sess, TreeConnection tree, final NetworkFile file) throws IOException {
    if (logger.isDebugEnabled()) {
        logger.debug("Close file: file" + file);
    }
    // Get the associated file state
    final ContentContext ctx = (ContentContext) tree.getContext();
    FileState toUpdate = null;
    if (file instanceof ContentNetworkFile) {
        if (ctx.hasStateCache()) {
            FileState fstate = ctx.getStateCache().findFileState(file.getFullName());
            if (fstate != null) {
                if (file.getGrantedAccess() > NetworkFile.ATTRIBUTESONLY && fstate.decrementOpenCount() == 0)
                    fstate.setSharedAccess(SharingMode.READWRITE + SharingMode.DELETE);
                if (file.hasOpLock()) {
                    // Release the oplock
                    OpLockInterface flIface = (OpLockInterface) this;
                    OpLockManager oplockMgr = flIface.getOpLockManager(sess, tree);
                    oplockMgr.releaseOpLock(file.getOpLock().getPath());
                    if (logger.isDebugEnabled())
                        logger.debug("Released oplock for closed file, file=" + file.getFullName());
                }
                if (file.hasDeleteOnClose() == false && fstate.hasModifyDateTime() && fstate.hasFilesystemObject() && fstate.isDirectory() == false) {
                    // Update the modification date on the file/folder node
                    toUpdate = fstate;
                }
            }
        }
        // Decrement the file open count
        ContentNetworkFile contentFile = (ContentNetworkFile) file;
        if (contentFile.decrementOpenCount() > 0) {
            if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE))
                logger.debug("Deferred file close, path=" + file.getFullName() + ", openCount=" + contentFile.getOpenCount());
            return;
        } else if (logger.isDebugEnabled())
            logger.debug("Last reference to file, closing, path=" + file.getFullName() + ", access=" + file.getGrantedAccessAsString() + ", fid=" + file.getProtocolId() + ", modified=" + contentFile.isModified());
    }
    // Check if there is a quota manager enabled
    long fileSize = 0L;
    if (ctx.hasQuotaManager() && file.hasDeleteOnClose()) {
        if (file instanceof ContentNetworkFile) {
            ContentNetworkFile contentFile = (ContentNetworkFile) file;
            if (contentFile.hasContent() == false)
                contentFile.openContent(false, false);
            // Save the current file size
            fileSize = contentFile.getFileSize();
        }
    }
    // Depending on whether the node has the NO_CONTENT aspect, we may have to wipe it out on error
    final CallableIO<Void> errorHandler = new CallableIO<Void>() {

        public Void call() throws IOException {
            if (file instanceof NodeRefNetworkFile) {
                NodeRef nodeRef = ((NodeRefNetworkFile) file).getNodeRef();
                if (nodeService.exists(nodeRef) && nodeService.hasAspect(nodeRef, ContentModel.ASPECT_NO_CONTENT)) {
                    logger.debug("No content - delete");
                    fileFolderService.delete(nodeRef);
                }
            }
            return null;
        }
    };
    try {
        // Perform repository updates in a retryable write transaction
        final FileState finalFileState = toUpdate;
        Pair<NodeRef, Boolean> result = doInWriteTransaction(sess, new CallableIO<Pair<NodeRef, Boolean>>() {

            public Pair<NodeRef, Boolean> call() throws IOException {
                if (file instanceof OpenOfficeContentNetworkFile) {
                    OpenOfficeContentNetworkFile ooFile = (OpenOfficeContentNetworkFile) file;
                    if (ooFile.truncatedToZeroLength()) {
                        // Inhibit versioning for this transaction
                        getPolicyFilter().disableBehaviour(ContentModel.ASPECT_VERSIONABLE);
                        if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE))
                            logger.debug("OpenOffice file truncation update only, inhibit versioning, " + file.getFullName());
                    }
                }
                // Update the modification date on the file/folder node
                if (finalFileState != null && file instanceof ContentNetworkFile) {
                    NodeRef nodeRef = (NodeRef) finalFileState.getFilesystemObject();
                    // Check if the file data has been updated, if not then inhibit versioning for this txn
                    // so the timestamp update does not generate a new file version
                    ContentNetworkFile contentFile = (ContentNetworkFile) file;
                    if (contentFile.isModified() == false && nodeService.hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE)) {
                        // Stop a new file version being generated
                        getPolicyFilter().disableBehaviour(ContentModel.ASPECT_VERSIONABLE);
                        if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE))
                            logger.debug("Timestamp update only, inhibit versioning, " + file.getFullName());
                    }
                    // Update the modification timestamp
                    getPolicyFilter().disableBehaviour(nodeRef, ContentModel.ASPECT_AUDITABLE);
                    if (permissionService.hasPermission((NodeRef) finalFileState.getFilesystemObject(), PermissionService.WRITE_PROPERTIES) == AccessStatus.ALLOWED) {
                        nodeService.setProperty(nodeRef, ContentModel.PROP_MODIFIER, authService.getCurrentUserName());
                        Date modifyDate = new Date(finalFileState.getModifyDateTime());
                        nodeService.setProperty(nodeRef, ContentModel.PROP_MODIFIED, modifyDate);
                        if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE))
                            logger.debug("Updated modification timestamp, " + file.getFullName() + ", modTime=" + modifyDate);
                    }
                }
                // Defer to the network file to close the stream and remove the content
                file.close();
                if (file.hasDeleteOnClose()) {
                    logger.debug("File has delete on close");
                    if (file instanceof NodeRefNetworkFile) {
                        NodeRefNetworkFile nodeNetFile = (NodeRefNetworkFile) file;
                        final NodeRef nodeRef = nodeNetFile.getNodeRef();
                        if (fileFolderService.exists(nodeRef)) {
                            try {
                                boolean isVersionable = nodeService.hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE);
                                try {
                                    // Delete the file
                                    FileState fileState = ctx.getStateCache().findFileState(file.getFullName());
                                    if (fileState != null && fileState.findAttribute(CanDeleteWithoutPerms) != null) {
                                        // Has CanDeleteWithoutPerms attribute, so delete from system user
                                        AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Object>() {

                                            @Override
                                            public Object doWork() throws Exception {
                                                logger.debug("delete as system" + nodeRef);
                                                fileFolderService.delete(nodeRef);
                                                return null;
                                            }
                                        }, AuthenticationUtil.getSystemUserName());
                                    } else {
                                        logger.debug("delete nodeRef:" + nodeRef);
                                        fileFolderService.delete(nodeRef);
                                    }
                                } catch (Exception ex) {
                                    logger.debug("on delete on close", ex);
                                    // Propagate retryable errors. Log the rest.
                                    if (RetryingTransactionHelper.extractRetryCause(ex) != null) {
                                        if (ex instanceof RuntimeException) {
                                            throw (RuntimeException) ex;
                                        } else {
                                            throw new AlfrescoRuntimeException("Error during delete on close, " + file.getFullName(), ex);
                                        }
                                    }
                                    if (logger.isWarnEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE))
                                        logger.warn("Error during delete on close, " + file.getFullName(), ex);
                                }
                                // Return a node ref to update in the state table
                                return new Pair<NodeRef, Boolean>(nodeRef, isVersionable);
                            } catch (org.alfresco.repo.security.permissions.AccessDeniedException ex) {
                                if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE))
                                    logger.debug("Delete on close - access denied, " + file.getFullName());
                                throw new AccessDeniedException("Delete on close " + file.getFullName());
                            }
                        }
                    }
                }
                return null;
            }
        });
        if (result != null) {
            if (ctx.hasQuotaManager())
                ctx.getQuotaManager().releaseSpace(sess, tree, file.getFileId(), file.getFullName(), fileSize);
            if (ctx.hasStateCache()) {
                if (result.getSecond()) {
                    // Get, or create, the file state
                    FileState fState = ctx.getStateCache().findFileState(file.getFullName(), true);
                    // Indicate that the file was deleted via a delete on close request
                    fState.setFileStatus(DeleteOnClose);
                    // Make sure the file state is cached for a short while, save the noderef details
                    fState.setExpiryTime(System.currentTimeMillis() + FileState.RenameTimeout);
                    fState.setFilesystemObject(result.getFirst());
                } else {
                    // Remove the file state
                    ctx.getStateCache().removeFileState(file.getFullName());
                }
            }
        }
        if (logger.isDebugEnabled() && (ctx.hasDebug(AlfrescoContext.DBG_FILE) || ctx.hasDebug(AlfrescoContext.DBG_RENAME))) {
            logger.debug("Closed file: network file=" + file + " delete on close=" + file.hasDeleteOnClose());
            if (file.hasDeleteOnClose() == false && file instanceof ContentNetworkFile) {
                ContentNetworkFile cFile = (ContentNetworkFile) file;
                logger.debug("  File " + file.getFullName() + ", version=" + nodeService.getProperty(cFile.getNodeRef(), ContentModel.PROP_VERSION_LABEL));
            }
        }
    }// Make sure we clean up before propagating exceptions
     catch (IOException e) {
        try {
            doInWriteTransaction(sess, errorHandler);
        } catch (Throwable t) {
            logger.error(t.getMessage(), t);
        }
        throw e;
    } catch (RuntimeException e) {
        try {
            doInWriteTransaction(sess, errorHandler);
        } catch (Throwable t) {
            logger.error(t.getMessage(), t);
        }
        throw e;
    } catch (Error e) {
        try {
            doInWriteTransaction(sess, errorHandler);
        } catch (Throwable t) {
            logger.error(t.getMessage(), t);
        }
        throw e;
    }
}
Also used : FileState(org.alfresco.jlan.server.filesys.cache.FileState) AccessDeniedException(org.alfresco.jlan.server.filesys.AccessDeniedException) NodeRef(org.alfresco.service.cmr.repository.NodeRef) AlfrescoRuntimeException(org.alfresco.error.AlfrescoRuntimeException) Pair(org.alfresco.util.Pair) ContentIOException(org.alfresco.service.cmr.repository.ContentIOException) IOException(java.io.IOException) Date(java.util.Date) DiskFullException(org.alfresco.jlan.server.filesys.DiskFullException) FileSharingException(org.alfresco.jlan.server.filesys.FileSharingException) DeviceContextException(org.alfresco.jlan.server.core.DeviceContextException) FileExistsException(org.alfresco.jlan.server.filesys.FileExistsException) FileNotFoundException(java.io.FileNotFoundException) QuotaManagerException(org.alfresco.jlan.server.filesys.quota.QuotaManagerException) InvalidNodeRefException(org.alfresco.service.cmr.repository.InvalidNodeRefException) NodeLockedException(org.alfresco.service.cmr.lock.NodeLockedException) AccessDeniedException(org.alfresco.jlan.server.filesys.AccessDeniedException) ContentIOException(org.alfresco.service.cmr.repository.ContentIOException) IOException(java.io.IOException) AlfrescoRuntimeException(org.alfresco.error.AlfrescoRuntimeException) DirectoryNotEmptyException(org.alfresco.jlan.server.filesys.DirectoryNotEmptyException) OpLockInterface(org.alfresco.jlan.server.locking.OpLockInterface) AlfrescoRuntimeException(org.alfresco.error.AlfrescoRuntimeException) OpLockManager(org.alfresco.jlan.server.locking.OpLockManager)

Aggregations

FileNotFoundException (java.io.FileNotFoundException)1 IOException (java.io.IOException)1 Date (java.util.Date)1 AlfrescoRuntimeException (org.alfresco.error.AlfrescoRuntimeException)1 DeviceContextException (org.alfresco.jlan.server.core.DeviceContextException)1 AccessDeniedException (org.alfresco.jlan.server.filesys.AccessDeniedException)1 DirectoryNotEmptyException (org.alfresco.jlan.server.filesys.DirectoryNotEmptyException)1 DiskFullException (org.alfresco.jlan.server.filesys.DiskFullException)1 FileExistsException (org.alfresco.jlan.server.filesys.FileExistsException)1 FileSharingException (org.alfresco.jlan.server.filesys.FileSharingException)1 FileState (org.alfresco.jlan.server.filesys.cache.FileState)1 QuotaManagerException (org.alfresco.jlan.server.filesys.quota.QuotaManagerException)1 OpLockInterface (org.alfresco.jlan.server.locking.OpLockInterface)1 OpLockManager (org.alfresco.jlan.server.locking.OpLockManager)1 NodeLockedException (org.alfresco.service.cmr.lock.NodeLockedException)1 ContentIOException (org.alfresco.service.cmr.repository.ContentIOException)1 InvalidNodeRefException (org.alfresco.service.cmr.repository.InvalidNodeRefException)1 NodeRef (org.alfresco.service.cmr.repository.NodeRef)1 Pair (org.alfresco.util.Pair)1