Commit 21a41b0c authored by Tigran Mkrtchyan's avatar Tigran Mkrtchyan
Browse files

nfsv41: refactor state handler to created new clients

parent 258d3c8c
......@@ -146,9 +146,13 @@ public class NFS4Client {
private final InetSocketAddress _localAddress;
private ClientCB _cl_cb = null; /* callback info */
/**
* lease expiration time in milliseconds.
*/
private final long _leaseTime;
public NFS4Client(InetSocketAddress clientAddress, InetSocketAddress localAddress,
byte[] ownerID, verifier4 verifier, String principal) {
byte[] ownerID, verifier4 verifier, String principal, long leaseTime) {
_ownerId = new Opaque(ownerID);
_verifier = verifier;
......@@ -157,7 +161,7 @@ public class NFS4Client {
_clientAddress = clientAddress;
_localAddress = localAddress;
_leaseTime = leaseTime;
_log.debug("New client id: {}", Long.toHexString(_clientId));
}
......@@ -216,10 +220,10 @@ public class NFS4Client {
* @throws ChimeraNFSException if difference between current time and last
* lease more than max_lease_time
*/
public void updateLeaseTime(long max_lease_time) throws ChimeraNFSException {
public void updateLeaseTime() throws ChimeraNFSException {
long curentTime = System.currentTimeMillis();
if ((curentTime - _cl_time) > max_lease_time * 1000) {
if ((curentTime - _cl_time) > _leaseTime) {
throw new ChimeraNFSException(nfsstat.NFSERR_EXPIRED, "lease time expired");
}
_cl_time = curentTime;
......
......@@ -17,6 +17,7 @@
package org.dcache.chimera.nfs.v4;
import java.net.InetSocketAddress;
import org.dcache.chimera.nfs.nfsstat;
import org.dcache.chimera.nfs.v4.xdr.stateid4;
import org.dcache.chimera.nfs.ChimeraNFSException;
......@@ -52,6 +53,19 @@ public class NFSv4StateHandler {
private final Map<Opaque, NFS4Client> _clientByOwner = new HashMap<Opaque, NFS4Client>();
/**
* Client's lease expiration time in milliseconds.
*/
private final long _leaseTime;
public NFSv4StateHandler() {
this(NFSv4Defaults.NFS4_LEASE_TIME*1000);
}
NFSv4StateHandler(long leaseTime) {
_leaseTime = leaseTime;
}
public synchronized void removeClient(NFS4Client client) {
for(NFSv41Session session: client.sessions() ) {
......@@ -65,7 +79,7 @@ public class NFSv4StateHandler {
}
public synchronized void addClient(NFS4Client newClient) {
private synchronized void addClient(NFS4Client newClient) {
_clients.add(newClient);
_clientsByServerId.put(newClient.getId(), newClient);
_clientsByVerifier.put(newClient.verifier(), newClient);
......@@ -110,10 +124,17 @@ public class NFSv4StateHandler {
throw new ChimeraNFSException( nfsstat.NFSERR_BAD_STATEID, "State is not confirmed" );
}
client.updateLeaseTime(NFSv4Defaults.NFS4_LEASE_TIME);
client.updateLeaseTime();
}
public synchronized List<NFS4Client> getClients() {
return new CopyOnWriteArrayList<NFS4Client>(_clients);
}
public NFS4Client createClient(InetSocketAddress clientAddress, InetSocketAddress localAddress,
byte[] ownerID, verifier4 verifier, String principal) {
NFS4Client client = new NFS4Client(clientAddress, localAddress, ownerID, verifier, principal, _leaseTime);
addClient(client);
return client;
}
}
......@@ -43,7 +43,7 @@ public class OperationCLOSE extends AbstractNFSv4Operation {
Inode inode = context.currentInode();
if (context.getMinorversion() > 0) {
context.getSession().getClient().updateLeaseTime(NFSv4Defaults.NFS4_LEASE_TIME);
context.getSession().getClient().updateLeaseTime();
/*
* for now it's just a place holder for state processing.
......
......@@ -161,9 +161,9 @@ public class OperationEXCHANGE_ID extends AbstractNFSv4Operation {
// create a new client: case 1
_log.debug("Case 1: New Owner ID");
client = new NFS4Client(remoteSocketAddress, localSocketAddress,
client = context.getStateHandler().createClient(
remoteSocketAddress, localSocketAddress,
clientOwner, _args.opexchange_id.eia_clientowner.co_verifier, principal);
context.getStateHandler().addClient(client);
} else {
......@@ -194,16 +194,16 @@ public class OperationEXCHANGE_ID extends AbstractNFSv4Operation {
_log.debug("case 5: Client Restart");
context.getStateHandler().removeClient(client);
client = new NFS4Client(remoteSocketAddress, localSocketAddress,
_args.opexchange_id.eia_clientowner.co_ownerid, _args.opexchange_id.eia_clientowner.co_verifier, principal);
context.getStateHandler().addClient(client);
client = context.getStateHandler().createClient(
remoteSocketAddress, localSocketAddress,
clientOwner, _args.opexchange_id.eia_clientowner.co_verifier, principal);
} else {
if ((!client.hasState()) || (System.currentTimeMillis() - client.leaseTime()) > (NFSv4Defaults.NFS4_LEASE_TIME * 1000)) {
_log.debug("case 3a: Client Collision is equivalent to case 1 (the new Owner ID)");
context.getStateHandler().removeClient(client);
client = new NFS4Client(remoteSocketAddress, localSocketAddress,
_args.opexchange_id.eia_clientowner.co_ownerid, _args.opexchange_id.eia_clientowner.co_verifier, principal);
context.getStateHandler().addClient(client);
client = context.getStateHandler().createClient(
remoteSocketAddress, localSocketAddress,
clientOwner, _args.opexchange_id.eia_clientowner.co_verifier, principal);
} else {
_log.debug("Case 3b: Client Collision");
throw new ChimeraNFSException(nfsstat.NFSERR_CLID_INUSE, "Principal Missmatch");
......@@ -212,16 +212,18 @@ public class OperationEXCHANGE_ID extends AbstractNFSv4Operation {
} else {
_log.debug("case 4: Replacement of Unconfirmed Record");
context.getStateHandler().removeClient(client);
client = new NFS4Client(remoteSocketAddress, localSocketAddress,
_args.opexchange_id.eia_clientowner.co_ownerid, _args.opexchange_id.eia_clientowner.co_verifier, principal);
context.getStateHandler().addClient(client);
client = context.getStateHandler().createClient(
remoteSocketAddress, localSocketAddress,
_args.opexchange_id.eia_clientowner.co_ownerid,
_args.opexchange_id.eia_clientowner.co_verifier,
principal);
}
}
}
client.updateLeaseTime(NFSv4Defaults.NFS4_LEASE_TIME);
client.updateLeaseTime();
res.eir_resok4 = new EXCHANGE_ID4resok();
res.eir_resok4.eir_clientid = new clientid4(new uint64_t(client.getId()));
......
......@@ -72,7 +72,7 @@ public class OperationOPEN extends AbstractNFSv4Operation {
throw new ChimeraNFSException(nfsstat.NFSERR_STALE_CLIENTID, "bad client id.");
}
client.updateLeaseTime(NFSv4Defaults.NFS4_LEASE_TIME);
client.updateLeaseTime();
_log.debug("open request form clientid: {}, owner: {}",
client, new String(_args.opopen.owner.value.owner));
}
......
......@@ -45,7 +45,7 @@ public class OperationRENEW extends AbstractNFSv4Operation {
throw new ChimeraNFSException(nfsstat.NFSERR_STALE_CLIENTID, "Bad client id");
}
client.updateLeaseTime(NFSv4Defaults.NFS4_LEASE_TIME);
client.updateLeaseTime();
res.status = nfsstat.NFS_OK;
}
}
......@@ -69,7 +69,7 @@ public class OperationSEQUENCE extends AbstractNFSv4Operation {
_args.opsequence.sa_sequenceid.value.value, opCount > 1));
context.setCacheThis(_args.opsequence.sa_cachethis);
session.getClient().updateLeaseTime(NFSv4Defaults.NFS4_LEASE_TIME);
client.updateLeaseTime();
context.setSession(session);
context.setSlotId(_args.opsequence.sa_slotid.value.value);
......
......@@ -58,12 +58,11 @@ public class OperationSETCLIENTID extends AbstractNFSv4Operation {
throw new ChimeraNFSException(nfsstat.NFSERR_CLID_INUSE, "Client Id In use");
}
client = new NFS4Client(context.getRpcCall().getTransport().getRemoteSocketAddress(),
client = context.getStateHandler().createClient(
context.getRpcCall().getTransport().getRemoteSocketAddress(),
context.getRpcCall().getTransport().getLocalSocketAddress(),
_args.opsetclientid.client.id, _args.opsetclientid.client.verifier, null);
context.getStateHandler().addClient(client);
res.resok4 = new SETCLIENTID4resok();
res.resok4.clientid = new clientid4();
res.resok4.clientid.value = new uint64_t(client.getId());
......
......@@ -73,7 +73,7 @@ public class OperationWRITE extends AbstractNFSv4Operation {
if (context.getMinorversion() > 0) {
context.getSession().getClient().updateLeaseTime(NFSv4Defaults.NFS4_LEASE_TIME);
context.getSession().getClient().updateLeaseTime();
} else {
context.getStateHandler().updateClientLeaseTime(_args.opwrite.stateid);
}
......
......@@ -22,19 +22,17 @@ public class NFSv4StateHandlerTest {
@Test
public void testGetByStateId() throws Exception {
NFS4Client client = createClient();
NFS4Client client = createClient(_stateHandler);
stateid4 state = client.createState().stateid();
_stateHandler.addClient(client);
_stateHandler.getClientIdByStateId(state);
}
@Test
public void testGetByVerifier() throws Exception {
NFS4Client client = createClient();
NFS4Client client = createClient(_stateHandler);
stateid4 state = client.createState().stateid();
_stateHandler.addClient(client);
assertEquals(client, _stateHandler.getClientByVerifier(client.verifier()));
}
......@@ -50,42 +48,37 @@ public class NFSv4StateHandlerTest {
@Test
public void testGetClientExists() throws Exception {
NFS4Client client = createClient();
_stateHandler.addClient(client);
NFS4Client client = createClient(_stateHandler);
assertEquals(client, _stateHandler.getClientByID(client.getId()));
}
@Test
public void testUpdateLeaseTime() throws Exception {
NFS4Client client = createClient();
NFS4Client client = createClient(_stateHandler);
NFS4State state = client.createState();
stateid4 stateid = state.stateid();
state.confirm();
_stateHandler.addClient(client);
_stateHandler.updateClientLeaseTime(stateid);
}
@Test(expected=ChimeraNFSException.class)
public void testUpdateLeaseTimeNotConfirmed() throws Exception {
NFS4Client client = createClient();
NFS4Client client = createClient(_stateHandler);
NFS4State state = client.createState();
stateid4 stateid = state.stateid();
_stateHandler.addClient(client);
_stateHandler.updateClientLeaseTime(stateid);
}
@Test(expected=ChimeraNFSException.class)
public void testUpdateLeaseTimeNotExists() throws Exception {
NFS4Client client = createClient();
NFS4Client client = createClient(_stateHandler);
stateid4 state = client.createState().stateid();
_stateHandler.updateClientLeaseTime(state);
}
static NFS4Client createClient() throws UnknownHostException {
static NFS4Client createClient(NFSv4StateHandler stateHandler) throws UnknownHostException {
InetSocketAddress address = new InetSocketAddress(InetAddress.getByName("www.google.com"), 123);
NFS4Client client = new NFS4Client(address, address, "123".getBytes(),
new verifier4("123".getBytes()), null);
return client;
return stateHandler.createClient(address, address, "123".getBytes(), new verifier4("123".getBytes()), null);
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment