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; import java.io.Serializable;
public class SignedPreKey extends PreKeyV2 implements Serializable { public class SignedPreKey extends PreKeyV2 {
@JsonProperty @JsonProperty
@NotEmpty @NotEmpty

View File

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

View File

@ -26,9 +26,9 @@ import java.io.Serializable;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; 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 @JsonIgnore
private long id; private long id;

View File

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

View File

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