package at.ac.ait.archistar.engine; import java.util.Map; import java.util.Set; import static org.fest.assertions.api.Assertions.*; import at.ac.ait.archistar.backendserver.fragments.Fragment; import at.ac.ait.archistar.engine.crypto.ArchistarSMCIntegrator; import at.ac.ait.archistar.engine.dataobjects.CustomSerializer; import at.ac.ait.archistar.engine.dataobjects.FSObject; import at.ac.ait.archistar.engine.dataobjects.SimpleFileInterface; import at.ac.ait.archistar.engine.distributor.Distributor; import at.ac.ait.archistar.engine.distributor.ServerConfiguration; import at.ac.ait.archistar.engine.metadata.MetadataService; import at.archistar.crypto.CryptoEngine; import at.archistar.crypto.secretsharing.ReconstructionException; /** * As most Archistar instances look kinda the same this class tries to capture * most of the similarities. This should prevent Archistar clients from * reimplementing the same functionality over and over again. * * @author andy */ public class Engine implements SimpleFileInterface { /** * our server configuration */ protected final ServerConfiguration servers; /** * the distributor which will transfer requests over the BFT network to the * replicasS */ protected final Distributor distributor; /** * our naming service */ private final MetadataService metadataService; /** * cryptographic directives */ private final CryptoEngine crypto; /** * the serializer used to tranform objects into byte arrays */ private final CustomSerializer serializer; /** * Create a new Archistar engine containing the following components * * @param servers which (remote) servers should be used * @param naming which metadata serverice to use for naming * @param distributor distribution options to use for storage * @param crypto which cryptographic directives to use for security */ public Engine(ServerConfiguration servers, MetadataService naming, Distributor distributor, CryptoEngine crypto) { this.servers = servers; this.distributor = distributor; this.metadataService = naming; this.crypto = crypto; this.serializer = new CustomSerializer(); } @Override public int connect() { int serverCount = this.distributor.connectServers(); this.metadataService.connect(); return serverCount; } @Override public int disconnect() { this.metadataService.disconnect(); this.distributor.disconnectServers(); return 0; } @Override public synchronized FSObject getObject(String path) throws ReconstructionException { Set<Fragment> fragments = this.metadataService.getDistributionFor(path); assertThat(fragments).hasSize(servers.getOnlineStorageServerCount()); boolean result = this.distributor.getFragmentSet(fragments); // TODO: just assert that nothing went wrong.. assertThat(result).isEqualTo(true); byte[] decrypted = ArchistarSMCIntegrator.decrypt(this.crypto, fragments); return this.serializer.deserialize(decrypted); } @Override public synchronized boolean putObject(FSObject obj) { assertThat(obj).isNotNull(); assertThat(metadataService).isNotNull(); Set<Fragment> fragments = this.metadataService.getDistributionFor(obj.getPath()); byte[] serialized = this.serializer.serialize(obj); // encrypt the fragments Set<Fragment> encryptedData = ArchistarSMCIntegrator.encrypt(this.crypto, serialized, fragments); return this.distributor.putFragmentSet(encryptedData); } @Override public synchronized Map<String, String> statObject(String path) { return metadataService.stat(path); } @Override public synchronized int deleteObject(FSObject obj) { return metadataService.delete(obj); } @Override public synchronized Set<String> listObjects(String path) { return this.metadataService.list(path); } }