From 231b0e94c013f955d3ab3b6c2ecab6908b2b9ca8 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Felix=20D=C3=B6rre?= Date: Thu, 4 Sep 2014 14:23:38 +0200 Subject: [PATCH] Test+implement: object cache for email and domain. --- src/org/cacert/gigi/Domain.java | 31 +++++++----- src/org/cacert/gigi/EmailAddress.java | 35 ++++++++----- src/org/cacert/gigi/IdCachable.java | 6 +++ src/org/cacert/gigi/ObjectCache.java | 21 ++++++++ src/org/cacert/gigi/User.java | 24 ++++++--- tests/org/cacert/gigi/TestObjectCache.java | 57 ++++++++++++++++++++++ 6 files changed, 143 insertions(+), 31 deletions(-) create mode 100644 src/org/cacert/gigi/IdCachable.java create mode 100644 src/org/cacert/gigi/ObjectCache.java create mode 100644 tests/org/cacert/gigi/TestObjectCache.java diff --git a/src/org/cacert/gigi/Domain.java b/src/org/cacert/gigi/Domain.java index 21fe668e..5dbbdaf0 100644 --- a/src/org/cacert/gigi/Domain.java +++ b/src/org/cacert/gigi/Domain.java @@ -3,9 +3,10 @@ package org.cacert.gigi; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; + import org.cacert.gigi.database.DatabaseConnection; -public class Domain { +public class Domain implements IdCachable { private User owner; @@ -62,6 +63,7 @@ public class Domain { ps.setString(2, suffix); ps.execute(); id = DatabaseConnection.lastInsertId(ps); + myCache.put(this); } catch (SQLException e) { throw new GigiApiException(e); } @@ -93,16 +95,6 @@ public class Domain { return suffix; } - public static Domain getById(int id) throws IllegalArgumentException { - // TODO cache - try { - Domain e = new Domain(id); - return e; - } catch (SQLException e) { - throw new IllegalArgumentException(e); - } - } - public void addPing(String type, String config) throws GigiApiException { try { PreparedStatement ps = DatabaseConnection.getInstance().prepare("INSERT INTO pingconfig SET domainid=?, type=?, info=?"); @@ -157,4 +149,21 @@ public class Domain { } } + + private static ObjectCache myCache = new ObjectCache<>(); + + public static Domain getById(int id) throws IllegalArgumentException { + Domain em = myCache.get(id); + if (em == null) { + try { + synchronized (Domain.class) { + myCache.put(em = new Domain(id)); + } + } catch (SQLException e1) { + throw new IllegalArgumentException(e1); + } + } + return em; + } + } diff --git a/src/org/cacert/gigi/EmailAddress.java b/src/org/cacert/gigi/EmailAddress.java index 5259fbcd..07ebfcc9 100644 --- a/src/org/cacert/gigi/EmailAddress.java +++ b/src/org/cacert/gigi/EmailAddress.java @@ -11,7 +11,7 @@ import org.cacert.gigi.email.MailProbe; import org.cacert.gigi.localisation.Language; import org.cacert.gigi.util.RandomToken; -public class EmailAddress { +public class EmailAddress implements IdCachable { private String address; @@ -54,8 +54,11 @@ public class EmailAddress { ps.setInt(1, owner.getId()); ps.setString(2, hash); ps.setString(3, address); - ps.execute(); - id = DatabaseConnection.lastInsertId(ps); + synchronized (EmailAddress.class) { + ps.execute(); + id = DatabaseConnection.lastInsertId(ps); + myCache.put(this); + } MailProbe.sendMailProbe(l, "email", id, hash, address); } catch (SQLException e) { e.printStackTrace(); @@ -96,17 +99,23 @@ public class EmailAddress { } } - public static EmailAddress getById(int id) throws IllegalArgumentException { - // TODO cache - try { - EmailAddress e = new EmailAddress(id); - return e; - } catch (SQLException e) { - throw new IllegalArgumentException(e); - } - } - public boolean isVerified() { return hash.isEmpty(); } + + private static ObjectCache myCache = new ObjectCache<>(); + + public static EmailAddress getById(int id) throws IllegalArgumentException { + EmailAddress em = myCache.get(id); + if (em == null) { + try { + synchronized (EmailAddress.class) { + myCache.put(em = new EmailAddress(id)); + } + } catch (SQLException e1) { + throw new IllegalArgumentException(e1); + } + } + return em; + } } diff --git a/src/org/cacert/gigi/IdCachable.java b/src/org/cacert/gigi/IdCachable.java new file mode 100644 index 00000000..0d218d5d --- /dev/null +++ b/src/org/cacert/gigi/IdCachable.java @@ -0,0 +1,6 @@ +package org.cacert.gigi; + +public interface IdCachable { + + public int getId(); +} diff --git a/src/org/cacert/gigi/ObjectCache.java b/src/org/cacert/gigi/ObjectCache.java new file mode 100644 index 00000000..9d8e9367 --- /dev/null +++ b/src/org/cacert/gigi/ObjectCache.java @@ -0,0 +1,21 @@ +package org.cacert.gigi; + +import java.lang.ref.WeakReference; +import java.util.HashMap; + +public class ObjectCache { + + HashMap> hashmap = new HashMap<>(); + + public void put(T c) { + hashmap.put(c.getId(), new WeakReference(c)); + } + + public T get(int id) { + WeakReference res = hashmap.get(id); + if (res != null) { + return res.get(); + } + return null; + } +} diff --git a/src/org/cacert/gigi/User.java b/src/org/cacert/gigi/User.java index 842f2f20..41396ae1 100644 --- a/src/org/cacert/gigi/User.java +++ b/src/org/cacert/gigi/User.java @@ -13,7 +13,7 @@ import org.cacert.gigi.util.Notary; import org.cacert.gigi.util.PasswordHash; import org.cacert.gigi.util.PasswordStrengthChecker; -public class User { +public class User implements IdCachable { private int id; @@ -129,8 +129,11 @@ public class User { query.setString(6, name.suffix); query.setDate(7, new java.sql.Date(dob.getTime())); query.setString(8, locale.toString()); - query.execute(); - id = DatabaseConnection.lastInsertId(query); + synchronized (User.class) { + query.execute(); + id = DatabaseConnection.lastInsertId(query); + myCache.put(this); + } } public void changePassword(String oldPass, String newPass) throws GigiApiException { @@ -253,10 +256,6 @@ public class User { return points; } - public static User getById(int id) { - return new User(id); - } - public EmailAddress[] getEmails() { try { PreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT id FROM emails WHERE memid=? AND deleted=0"); @@ -495,4 +494,15 @@ public class User { update.executeUpdate(); } + private static ObjectCache myCache = new ObjectCache<>(); + + public static User getById(int id) { + User u = myCache.get(id); + if (u == null) { + synchronized (User.class) { + myCache.put(u = new User(id)); + } + } + return u; + } } diff --git a/tests/org/cacert/gigi/TestObjectCache.java b/tests/org/cacert/gigi/TestObjectCache.java new file mode 100644 index 00000000..d361c16b --- /dev/null +++ b/tests/org/cacert/gigi/TestObjectCache.java @@ -0,0 +1,57 @@ +package org.cacert.gigi; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + +import java.sql.Date; +import java.sql.SQLException; +import java.util.Calendar; +import java.util.Locale; + +import org.cacert.gigi.localisation.Language; +import org.cacert.gigi.testUtils.ManagedTest; +import org.junit.Test; + +public class TestObjectCache extends ManagedTest { + + int uid = createVerifiedUser("fname", "lname", createUniqueName() + "@example.com", TEST_PASSWORD); + + @Test + public void testUserCache() throws SQLException { + assertThat(User.getById(uid), is(sameInstance(User.getById(uid)))); + + User u = new User(); + u.setFname("fname"); + u.setMname("mname"); + u.setSuffix("suffix"); + u.setLname("lname"); + u.setEmail(createUniqueName() + "@example.org"); + Calendar c = Calendar.getInstance(); + c.set(1950, 1, 1); + u.setDob(new Date(c.getTime().getTime())); + u.setPreferredLocale(Locale.ENGLISH); + u.insert(TEST_PASSWORD); + + assertThat(u, is(sameInstance(User.getById(u.getId())))); + assertThat(User.getById(u.getId()), is(sameInstance(User.getById(u.getId())))); + + } + + @Test + public void testDomainCache() throws GigiApiException { + Domain d = new Domain(User.getById(uid), "example.org"); + d.insert(); + + assertThat(d, is(sameInstance(Domain.getById(d.getId())))); + assertThat(Domain.getById(d.getId()), is(sameInstance(Domain.getById(d.getId())))); + } + + @Test + public void testEmailCache() { + EmailAddress em = new EmailAddress(createUniqueName() + "@example.org", User.getById(uid)); + em.insert(Language.getInstance(Locale.ENGLISH)); + + assertThat(em, is(sameInstance(EmailAddress.getById(em.getId())))); + assertThat(EmailAddress.getById(em.getId()), is(sameInstance(EmailAddress.getById(em.getId())))); + } +} -- 2.39.2