Java SMBJ和DFS以及;嵌套会话“;

Java SMBJ和DFS以及;嵌套会话“;,java,smb,microsoft-distributed-file-system,smbj,Java,Smb,Microsoft Distributed File System,Smbj,我有一个项目,给我一个id,然后用这个id查找文件路径并处理它们。。。这些文件位于各种安装的驱动器上,因此我使用SMBJ java库来访问它们 我遇到的问题是,一些(大多数)文件正在使用DFS装入点。。。现在,这本身并不是问题,但显然SMBJ库似乎为每个不同的DFS位置创建嵌套会话。因此,即使我在完成读取后关闭实际文件,DiskSession对象仍保留所有这些嵌套会话。。。最终,或者通过DFS配置设置,或者通过这些库,我遇到了一个问题,它突然崩溃,不再允许创建更多会话 我正在处理数十万条记录,“

我有一个项目,给我一个id,然后用这个id查找文件路径并处理它们。。。这些文件位于各种安装的驱动器上,因此我使用SMBJ java库来访问它们

我遇到的问题是,一些(大多数)文件正在使用DFS装入点。。。现在,这本身并不是问题,但显然SMBJ库似乎为每个不同的DFS位置创建嵌套会话。因此,即使我在完成读取后关闭实际文件,DiskSession对象仍保留所有这些嵌套会话。。。最终,或者通过DFS配置设置,或者通过这些库,我遇到了一个问题,它突然崩溃,不再允许创建更多会话

我正在处理数十万条记录,“崩溃”似乎发生在正在处理的大约500条记录(会话)的某个地方。我没有看到任何明显的代码来显式关闭这些嵌套会话。。事实上,我看不到从DiskShare对象外部对它们的任何外部访问

我是否缺少某种设置,可以最大限度地利用这些会话?除了我自己管理一些计数器,关闭和重新打开会话/连接之外,我不知道如何处理这个问题

有人知道我在这里遗漏了什么吗

代码如下:

public class Smb {

private static SMBClient client;
private static String[] DFSMounts = {"DFS1","dfs1"};
private static final Logger Log = LoggerFactory.getLogger(Smb.class);
private static HashMap<String,DiskShare> shares = new HashMap<>();
private static HashMap<String,Connection> connections = new HashMap<>();
private static HashMap<Connection,Session> sessions = new HashMap<>();

private synchronized static SMBClient getClient(){
    if (client == null){
        SmbConfig cfg = SmbConfig.builder().withDfsEnabled(true).build();
        client = new SMBClient(cfg);
    }
    return client;
}

private synchronized static Connection getConnection(String realDomainName) throws IOException{

    Log.info("DOMAIN NAME "+realDomainName);
    Connection connection = (connections.get(realDomainName) == null) ? client.connect(realDomainName) : connections.get(realDomainName);
    if(!connection.isConnected()) {
        connection.close();
        sessions.remove(connection);
        connection = client.connect(realDomainName);

    }
    // connection = client.connect(realDomainName);
    connections.put(realDomainName,connection);
    return connection;


}

private synchronized static Session getSession(Connection connection,SMBClient client){

    Session session = sessions.get(connection);
    if(session==null) {
        PropertiesCache props = PropertiesCache.getInstance();
        String sambaUsername = props.getProperty("smb.user");
        String sambaPass = props.getProperty("smb.password");
        String sambaDomain = props.getProperty("smb.domain");
        Log.info("CLIENT " + client);

        session = (sessions.get(connection) != null) ? sessions.get(connection) : connection.authenticate(new AuthenticationContext(sambaUsername, sambaPass.toCharArray(), sambaDomain));

        sessions.put(connection, session);
    }
    return session;
}

@SuppressWarnings("UnusedReturnValue")
public synchronized static DiskShare getShare(String domainName, String shareName) throws SmbException
{
    DiskShare share = shares.get(domainName+"/"+shareName);
    if((share!=null)&&(!share.isConnected())) share=null;
    if(share == null){
        try {


            PropertiesCache props = PropertiesCache.getInstance();
            String sambaUsername = props.getProperty("smb.user");
            String sambaPass = props.getProperty("smb.password");
            String sambaDomain = props.getProperty("smb.domain");
            String dfsIP = props.getProperty("smb.sambaIP");

            SMBClient client = getClient();

            String realDomainName = (Arrays.stream(DFSMounts).anyMatch(domainName::equals)) ? dfsIP: domainName;
            Connection connection = getConnection(realDomainName);
            Session session = getSession(connection,client);

            share = (DiskShare) session.connectShare(shareName);
            shares.put(domainName+"/"+shareName,share);
        }
        catch (Exception e){
            Log.info("EXCEPTION E "+e);
            Log.info("EX "+e.getMessage());

            throw new SmbException();
        }

    }
    return(share);

}

public static String fixFilename(String filename){
    String[] parts = filename.split("\\\\");
    ArrayList<String> partsList = new ArrayList<>(Arrays.asList(parts));
    partsList.remove(0);
    partsList.remove(0);
    partsList.remove(0);
    partsList.remove(0);
    return String.join("/",partsList);

}


public static File open(String filename) throws SmbException {
    String[] parts = filename.split("\\\\");
    String domainName = parts[2];
    String shareName = parts[3];
    DiskShare share = getShare(domainName,shareName);
    Set<SMB2ShareAccess> s = new HashSet<>();
    s.add(SMB2ShareAccess.ALL.iterator().next());
    filename = fixFilename(filename);
    return(share.openFile(filename, EnumSet.of(AccessMask.GENERIC_READ), null, s,  SMB2CreateDisposition.FILE_OPEN, null));
}
以及:


我已经为SMBJ创建了一个PR,它改变了这一点。它将为同一主机重用嵌套会话。我自己也成功地使用了它,避免了与您完全相同的问题

我错过了确切的错误信息。此外,SMBJ将执行自己的连接/会话/共享缓存,只要您保持客户机处于活动状态。没有必要维护自己的映射。没关系,我只是添加了外部缓存,因为我试图处理嵌套会话问题。最终,DFS会话在嵌套会话过多后似乎只是死掉/关闭连接。。。所有进一步请求使用连接上的会话,显然都会失败,因为连接已关闭。Hiery,不幸的是,使用DFS时,DFS解析似乎不会创建新会话,即使装载点位于其已具有连接/会话的某处。。。我可以始终如一地重现这个错误。它似乎创建了一个新的连接和会话,即使端点已解析为它已有的内容,,,请参见下面的跟踪:
String filename = documents.get(0).getUNCPath();
            try (File f = Smb.open(filename)){

               Process the file code...

                f.closeSilently();
            }
    while(i.hasNext()){
        String filename =  (String)i.next();
        Log.info("FILENAME "+filename);
        try(File f = Smb.open(filename)){

           Process the file stuff here


        }
    }