Closed harisingh-highq closed 4 years ago
As the server is returning that, I would investigate why it is returning that? THere is nothing the SMBJ library can do about this return code, except return it to you to deal with it.
@hierynomus Thanks for your prompt response.
As per above logs, i think issue is in creating mkdir() method of DiskShare.
at com.hierynomus.smbj.share.DiskShare.openDirectory(DiskShare.java:130) at com.hierynomus.smbj.share.DiskShare.mkdir(DiskShare.java:240)
I looked into source code of mkdir() as per suggestion here:- https://stackoverflow.com/questions/54113855/what-does-status-object-name-collision-from-a-samba-share-really-mean-and-could
I think there should be FILE_OVERWRITE_IF in SMBcreateDisposition parameter value.
What do you suggest in this case? Can this fix would resolve the issue?
Actually before calling mkdir
you should be checking existence. Depending on the semantics of the FILE_OVERWRITE_IF
for a folder it could be bad practice. This is not a bug but desired behavior to get an exception if you try to create a directory that already exists.
I have already check for folder exist before calling mkdir as like below code:-
if (!share.folderExists(folderPath)) { String[] list =folderPath.split("\\\\"); List<String> pathList = new ArrayList<>(Arrays.asList(list)); mkDirs(share, pathList); }
But in case of concurrent simultaneous file upload case its failing to attempt folder exist and
it may try to call mkdir for same folder which is throwing STATUS_OBJECT_NAME_COLLISION error.
You need to do your own concurrency control for your code. So use a Lock
, Monitor
, Semaphore
, synchronized block
or one of the many other concurrency primitives.
You can just ignore the exception, if it is thrown you know that the directory already exists.
Alternatively you can try to create the file and only if that fails try to create the parent directories, this is the fastest method (least roundtrips)
You can just ignore the exception, if it is thrown you know that the directory already exists.
Alternatively you can try to create the file and only if that fails try to create the parent directories, this is the fastest method (least roundtrips)
Thanks @ecki for your suggestion. I appreciate your help.
Yes i think it would be good to handle this exception and try to create the file on this folder. Let me try to fix in this way.
Just a quick question is there any other possibility of throwing same error in any other case in mkdir?
You need to do your own concurrency control for your code. So use a
Lock
,Monitor
,Semaphore
,synchronized block
or one of the many other concurrency primitives.
Thanks @hierynomus for your reply
Hard to say, the name collision error code sounds pretty specific.
Btw: There is one case where one of the directories in the path are not directories but files. I don't know what error would be thrown in that case. It is always good to log that very clearly if /a/b is a file and you want to create a file in /a/b/c/d it should log that b is a file (and not that /a/b/c is no directory Or that it cannot create c. If those directories come and go nobody would know what to look for if it's not clearly logged).
@hierynomus @pepijnve Can you please help me to sort out this issue? I'm getting STATUS_OBJECT_NAME_COLLISION error although file is not already exist on below path
com.hierynomus.mssmb2.SMBApiException: STATUS_OBJECT_NAME_COLLISION (0xc0000035): Create failed for \fileserver1ind1.hqdev.india\data\HYBRID_APPLIANCE_SMBJ_REPO_Hari\\enc\griffin\HYB92\75286\ at com.hierynomus.smbj.share.Share.receive(Share.java:366) at com.hierynomus.smbj.share.Share.sendReceive(Share.java:346) at com.hierynomus.smbj.share.Share.createFile(Share.java:159) at com.hierynomus.smbj.share.DiskShare.createFileAndResolve(DiskShare.java:97) at com.hierynomus.smbj.share.DiskShare.resolveAndCreateFile(DiskShare.java:79) at com.hierynomus.smbj.share.DiskShare.open(DiskShare.java:66) at com.hierynomus.smbj.share.DiskShare.openDirectory(DiskShare.java:130) at com.hierynomus.smbj.share.DiskShare.mkdir(DiskShare.java:240) at com.hybridintegration.repository.SMBJRepo.mkDirs(SMBJRepo.java:3286)
This is create file code in share object:-
share.openFile(filePath, EnumSet.of(AccessMask.GENERIC_WRITE, AccessMask.GENERIC_READ), null, null, SMB2CreateDisposition.FILE_OVERWRITE_IF, null);