@Override
	public MessageResponse upload(UploadRequest request) throws IOException {
		if (!loggedIn) return new RefuseResponse();

		FileServerProvider provider = serverManager.getServerProvider();
		Queue<FileServerAdapter> nr = provider.getReadQuorum();
		Queue<FileServerAdapter> nw = provider.getWriteQuorum();
		log("Nr fileservers: " + nr.toString());
		log("Nw fileservers: " + nw.toString());

		// determine highest version from Nr fileservers
		VersionRequest vRequest = new VersionRequest(request.getFilename());
		int highestVersion = 0;
		for (FileServerAdapter fs: nr) {
			Response r;
			try {
				r = fs.version(vRequest);
				if (r instanceof VersionResponse) {
					VersionResponse vr = (VersionResponse) r;
					if (vr.getVersion() > highestVersion) highestVersion = vr.getVersion();
				} else {
					log("Unexpected Response from " + fs.toString() + ": " + r.toString());
				}
			} catch (IOException e) {
				log("VersionRequest from " + fs.toString() + " failed: " + e.toString());
			} finally {
				try {
					fs.getConnection().close();
				} catch (IllegalStateException e){ }
			}
		}

		// Upload file to Nw fileservers
		UploadRequest uRequest = new UploadRequest(request.getFilename(), highestVersion + 1, request.getContent());
		long size = request.getContent().length;
		log("Uploading '" + request.getFilename() + "' with size " + size + " to Write Quorum");	
		for (FileServerAdapter fs: nw) {
			try {
				fs.upload(uRequest);
				log("Uploaded '" + uRequest.getFilename() + "' to " + fs.toString());	
			} catch (IOException e) {
				throw new IOException("Upload to " + fs.toString() + " failed.");
			} finally {
				try {
					fs.getConnection().close();
				} catch (IllegalStateException e){ }
			}
		}

		// update user's credits
		uac.increaseCredits(user, size * 2);
		log("Earned " + size * 2 + " credits");
		return new MessageResponse("File successfully uploaded.\nYou now have " + user.getCredits() + " credits.");
	}