Switch from Java serialization to JSON for memcache storage.

This commit is contained in:
Moxie Marlinspike 2014-07-22 13:43:37 -07:00
parent 4cd098af1d
commit 160c0bfe14
7 changed files with 106 additions and 60 deletions

View File

@ -5,7 +5,7 @@ import org.hibernate.validator.constraints.NotEmpty;
import java.io.Serializable;
public class SignedPreKey extends PreKeyV2 implements Serializable {
public class SignedPreKey extends PreKeyV2 {
@JsonProperty
@NotEmpty

View File

@ -45,6 +45,8 @@ public class MemcacheHealthCheck extends HealthCheck {
return Result.unhealthy("Fetch failed");
}
this.client.delete("HEALTH" + random);
return Result.healthy();
}

View File

@ -26,9 +26,9 @@ import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
public class Account implements Serializable {
public class Account {
public static final int MEMCACHE_VERION = 4;
public static final int MEMCACHE_VERION = 5;
@JsonIgnore
private long id;

View File

@ -17,19 +17,27 @@
package org.whispersystems.textsecuregcm.storage;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Optional;
import net.spy.memcached.MemcachedClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.whispersystems.textsecuregcm.entities.ClientContact;
import org.whispersystems.textsecuregcm.util.Util;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
public class AccountsManager {
private final Logger logger = LoggerFactory.getLogger(AccountsManager.class);
private final Accounts accounts;
private final MemcachedClient memcachedClient;
private final DirectoryManager directory;
private final ObjectMapper mapper;
public AccountsManager(Accounts accounts,
DirectoryManager directory,
@ -38,6 +46,7 @@ public class AccountsManager {
this.accounts = accounts;
this.directory = directory;
this.memcachedClient = memcachedClient;
this.mapper = new ObjectMapper();
}
public long getCount() {
@ -54,40 +63,28 @@ public class AccountsManager {
public void create(Account account) {
accounts.create(account);
if (memcachedClient != null) {
memcachedClient.set(getKey(account.getNumber()), 0, account);
}
memcacheSet(account.getNumber(), account);
updateDirectory(account);
}
public void update(Account account) {
if (memcachedClient != null) {
memcachedClient.set(getKey(account.getNumber()), 0, account);
}
memcacheSet(account.getNumber(), account);
accounts.update(account);
updateDirectory(account);
}
public Optional<Account> get(String number) {
Account account = null;
Optional<Account> account = memcacheGet(number);
if (memcachedClient != null) {
account = (Account)memcachedClient.get(getKey(number));
}
if (!account.isPresent()) {
account = Optional.fromNullable(accounts.get(number));
if (account == null) {
account = accounts.get(number);
if (account != null && memcachedClient != null) {
memcachedClient.set(getKey(number), 0, account);
if (account.isPresent()) {
memcacheSet(number, account.get());
}
}
if (account != null) return Optional.of(account);
else return Optional.absent();
return account;
}
public boolean isRelayListed(String number) {
@ -111,4 +108,30 @@ public class AccountsManager {
return Account.class.getSimpleName() + Account.MEMCACHE_VERION + number;
}
private void memcacheSet(String number, Account account) {
if (memcachedClient != null) {
try {
String json = mapper.writeValueAsString(account);
memcachedClient.set(getKey(number), 0, json);
} catch (JsonProcessingException e) {
throw new IllegalArgumentException(e);
}
}
}
private Optional<Account> memcacheGet(String number) {
if (memcachedClient == null) return Optional.absent();
try {
String json = (String)memcachedClient.get(getKey(number));
if (json != null) return Optional.of(mapper.readValue(json, Account.class));
else return Optional.absent();
} catch (IOException e) {
logger.warn("AccountsManager", "Deserialization error", e);
return Optional.absent();
}
}
}

View File

@ -24,7 +24,7 @@ import org.whispersystems.textsecuregcm.util.Util;
import java.io.Serializable;
public class Device implements Serializable {
public class Device {
public static final long MASTER_ID = 1;

View File

@ -34,35 +34,46 @@ public class PendingAccountsManager {
}
public void store(String number, String code) {
if (memcachedClient != null) {
memcachedClient.set(MEMCACHE_PREFIX + number, 0, code);
}
memcacheSet(number, code);
pendingAccounts.insert(number, code);
}
public void remove(String number) {
if (memcachedClient != null)
memcachedClient.delete(MEMCACHE_PREFIX + number);
memcacheDelete(number);
pendingAccounts.remove(number);
}
public Optional<String> getCodeForNumber(String number) {
String code = null;
Optional<String> code = memcacheGet(number);
if (memcachedClient != null) {
code = (String)memcachedClient.get(MEMCACHE_PREFIX + number);
}
if (!code.isPresent()) {
code = Optional.fromNullable(pendingAccounts.getCodeForNumber(number));
if (code == null) {
code = pendingAccounts.getCodeForNumber(number);
if (code != null && memcachedClient != null) {
memcachedClient.set(MEMCACHE_PREFIX + number, 0, code);
if (code.isPresent()) {
memcacheSet(number, code.get());
}
}
if (code != null) return Optional.of(code);
else return Optional.absent();
return code;
}
private void memcacheSet(String number, String code) {
if (memcachedClient != null) {
memcachedClient.set(MEMCACHE_PREFIX + number, 0, code);
}
}
private Optional<String> memcacheGet(String number) {
if (memcachedClient != null) {
return Optional.fromNullable((String)memcachedClient.get(MEMCACHE_PREFIX + number));
} else {
return Optional.absent();
}
}
private void memcacheDelete(String number) {
if (memcachedClient != null) {
memcachedClient.delete(MEMCACHE_PREFIX + number);
}
}
}

View File

@ -34,37 +34,47 @@ public class PendingDevicesManager {
}
public void store(String number, String code) {
if (memcachedClient != null) {
memcachedClient.set(MEMCACHE_PREFIX + number, 0, code);
}
memcacheSet(number, code);
pendingDevices.insert(number, code);
}
public void remove(String number) {
if (memcachedClient != null) {
memcachedClient.delete(MEMCACHE_PREFIX + number);
}
memcacheDelete(number);
pendingDevices.remove(number);
}
public Optional<String> getCodeForNumber(String number) {
String code = null;
Optional<String> code = memcacheGet(number);
if (memcachedClient != null) {
code = (String)memcachedClient.get(MEMCACHE_PREFIX + number);
}
if (!code.isPresent()) {
code = Optional.fromNullable(pendingDevices.getCodeForNumber(number));
if (code == null) {
code = pendingDevices.getCodeForNumber(number);
if (code != null && memcachedClient != null) {
memcachedClient.set(MEMCACHE_PREFIX + number, 0, code);
if (code.isPresent()) {
memcacheSet(number, code.get());
}
}
if (code != null) return Optional.of(code);
else return Optional.absent();
return code;
}
private void memcacheSet(String number, String code) {
if (memcachedClient != null) {
memcachedClient.set(MEMCACHE_PREFIX + number, 0, code);
}
}
private Optional<String> memcacheGet(String number) {
if (memcachedClient != null) {
return Optional.fromNullable((String)memcachedClient.get(MEMCACHE_PREFIX + number));
} else {
return Optional.absent();
}
}
private void memcacheDelete(String number) {
if (memcachedClient != null) {
memcachedClient.delete(MEMCACHE_PREFIX + number);
}
}
}