Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,20 @@
</dependency>
</dependencies>

<build>
<plugins>
<!-- we want JDK 1.6 source and binary compatiblility -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>

<repositories>
<repository>
<id>com.springsource.repository.bundles.release</id>
Expand All @@ -315,4 +329,6 @@
<url>http://maven.springframework.org/release</url>
</repository>
</repositories>


</project>
10 changes: 10 additions & 0 deletions src/main/java/com/percero/agents/sync/access/AccessManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -870,6 +870,16 @@ public List<String> getObjectAccessJournals(String className, String classId) th
return result;
}

@Override
public Set<String> getClassAccessJournalIDs(String className) {
return null;
}

@Override
public long getNumClientsInterestedInWholeClass(String className) {
return 0;
}

@SuppressWarnings("unchecked")
public Map<String, Collection<String>> getClientAccessess(Collection<ClassIDPair> classIdPairs) throws Exception {
Map<String, Collection<String>> result = new HashMap<String, Collection<String>>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ public Set<String> findClientByUserIdDeviceId(String deviceId, String userId)
* @throws Exception
*/
public List<String> getObjectAccessJournals(String className, String classId) throws Exception;
Set<String> getClassAccessJournalIDs(String className);
long getNumClientsInterestedInWholeClass(String className);

public void removeAccessJournalsByObject(ClassIDPair classIdPair);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -566,8 +566,7 @@ public void destroyClient(String clientId) {
* This function checks to see if a User has no more UserDevices. If they do not have
* any, then it removes all the User's entries in ALL AccessJournal sets.
*
* @param userId
* @param clientId
* @param clientId
*/
@SuppressWarnings("unchecked")
@Transactional
Expand All @@ -578,6 +577,18 @@ private void deleteClientAccessJournals(String clientId) {

// Now remove the Client's AccessJournal key.
redisDataStore.deleteKey(clientAccessJournalsKey);

// Check to see if each Object's access journal set is empty and if so remove it
// from the class access journal set
for(String caj : clientAccessJournals){
if(redisDataStore.getSetIsEmpty(RedisKeyUtils.ACCESS_JOURNAL_PREFIX+caj)){
String[] parts = caj.split(":");
String className = parts[0];
String ID = parts[1];
String classAccessJournalKey = RedisKeyUtils.classAccessJournal(className);
redisDataStore.removeSetValue(classAccessJournalKey, ID);
}
}
}

@SuppressWarnings("unchecked")
Expand Down Expand Up @@ -830,7 +841,14 @@ private Long upsertRedisAccessJournal(String userId, String clientId, String cla
// Need to add the ObjectID to the Client's AccessJournals set.
String clientAccessJournalKey = RedisKeyUtils.clientAccessJournal(clientId);
redisDataStore.addSetValue(clientAccessJournalKey, RedisKeyUtils.objectId(className, classId));


// Add to the class's AccessJournals set
if(classId != null && !classId.isEmpty() && !classId.equals("0")) {
log.info("Adding to class AccessJournals: "+classId);
String classAccessJournalKey = RedisKeyUtils.classAccessJournal(className);
redisDataStore.addSetValue(classAccessJournalKey, classId);
}

// Need to add the ClientID to the Object's AccessJournal set.
return redisDataStore.addSetValue(key, clientId);
} catch(Exception e) {
Expand Down Expand Up @@ -881,6 +899,14 @@ public List<String> getObjectAccessJournals(String className, String classId) th
return result;
}

public Set<String> getClassAccessJournalIDs(String className){
return (Set<String>) redisDataStore.getSetValue(RedisKeyUtils.classAccessJournal(className));
}

public long getNumClientsInterestedInWholeClass(String className){
return redisDataStore.getSetSize(RedisKeyUtils.accessJournal(className,"0"));
}

public List<String> checkUserListAccessRights(Collection<Object> clientIdList, String className, String classId) throws Exception {
List<String> result = new ArrayList<String>();

Expand Down Expand Up @@ -984,6 +1010,9 @@ public void removeAccessJournalsByObject(ClassIDPair classIdPair) {
// }
// }

String classAccessJournalKey = RedisKeyUtils.classAccessJournal(classIdPair.getClassName());
redisDataStore.removeSetValue(classAccessJournalKey, classIdPair.getID());

// Now delete the AccessJournal record.
redisDataStore.deleteKey(accessJournalKey);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ public static String accessJournalPrefix() {
public static String clientAccessJournal(String clientId) {
return (new StringBuilder(INT_64).append("c:").append(ACCESS_JOURNAL_PREFIX).append(clientId)).toString();
}

public static String classAccessJournal(String className) {
return (new StringBuilder(INT_64).append("class:").append(ACCESS_JOURNAL_PREFIX).append(className)).toString();
}

public static String historicalObject(String className, String classId) {
return (new StringBuilder(INT_128).append("ho:").append(className).append(":").append(classId)).toString();
Expand Down
137 changes: 137 additions & 0 deletions src/main/java/com/percero/agents/sync/cache/CacheManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package com.percero.agents.sync.cache;

import com.percero.agents.sync.access.RedisKeyUtils;
import com.percero.agents.sync.datastore.RedisDataStore;
import com.percero.agents.sync.metadata.IMappedClassManager;
import com.percero.agents.sync.metadata.MappedClass;
import com.percero.agents.sync.metadata.MappedClassManagerFactory;
import com.percero.agents.sync.metadata.MappedField;
import com.percero.agents.sync.vo.BaseDataObject;
import com.percero.agents.sync.vo.ClassIDPair;
import com.percero.framework.vo.IPerceroObject;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import sun.misc.Cache;

import java.lang.reflect.InvocationTargetException;
import java.util.*;

/**
* Created by jonnysamps on 9/5/15.
*/
@Component
public class CacheManager {

private static Logger logger = Logger.getLogger(CacheManager.class);

@Autowired
RedisDataStore redisDataStore;

@Autowired
Long cacheTimeout = Long.valueOf(60 * 60 * 24 * 14); // Two weeks

public void updateCachedObject(IPerceroObject perceroObject, Map<ClassIDPair, Collection<MappedField>> changedFields){
// TODO: Field-level updates could be REALLY useful here. Would avoid A TON of UNNECESSARY work...
try {
if (cacheTimeout > 0) {
// TODO: Also need to update the caches of anything object that is related to this object.
String key = RedisKeyUtils.classIdPair(perceroObject.getClass().getCanonicalName(), perceroObject.getID());
if (redisDataStore.hasKey(key)) {
redisDataStore.setValue(key, ((BaseDataObject) perceroObject).toJson());
}

// Iterate through each changed object and reset the cache for that object.
if (changedFields != null) {
// Iterator<Map.Entry<ClassIDPair, Collection<MappedField>>> itrChangedFieldEntrySet = changedFields.entrySet().iterator();
// Set<String> keysToDelete = new HashSet<String>();
// while (itrChangedFieldEntrySet.hasNext()) {
// Map.Entry<ClassIDPair, Collection<MappedField>> nextEntry = itrChangedFieldEntrySet.next();
// ClassIDPair thePair = nextEntry.getKey();
// if (!thePair.comparePerceroObject(perceroObject)) {
// String nextKey = RedisKeyUtils.classIdPair(thePair.getClassName(), thePair.getID());
// keysToDelete.add(nextKey);
// }
// }
Iterator<ClassIDPair> itrChangedFieldKeyset = changedFields.keySet().iterator();
Set<String> keysToDelete = new HashSet<String>();
while (itrChangedFieldKeyset.hasNext()) {
ClassIDPair thePair = itrChangedFieldKeyset.next();
if (!thePair.comparePerceroObject(perceroObject)) {
String nextKey = RedisKeyUtils.classIdPair(thePair.getClassName(), thePair.getID());
keysToDelete.add(nextKey);
}
}

if (!keysToDelete.isEmpty()) {
redisDataStore.deleteKeys(keysToDelete);
// TODO: Do we simply delete the key? Or do we refetch the object here and update the key?
//redisDataStore.setValue(nextKey, ((BaseDataObject)perceroObject).toJson());
}
} else {
// No changedFields? We should never get here?
IMappedClassManager mcm = MappedClassManagerFactory.getMappedClassManager();
MappedClass mappedClass = mcm.getMappedClassByClassName(perceroObject.getClass().getName());
Iterator<MappedField> itrToManyFields = mappedClass.toManyFields.iterator();
while (itrToManyFields.hasNext()) {
MappedField nextMappedField = itrToManyFields.next();
Object fieldObject = nextMappedField.getGetter().invoke(perceroObject);
if (fieldObject != null) {
if (fieldObject instanceof IPerceroObject) {
String nextKey = RedisKeyUtils.classIdPair(fieldObject.getClass().getCanonicalName(), ((IPerceroObject) fieldObject).getID());
if (redisDataStore.hasKey(nextKey)) {
redisDataStore.deleteKey(nextKey);
// TODO: Do we simply delete the key? Or do we refetch the object here and update the key?
//redisDataStore.setValue(nextKey, ((BaseDataObject)perceroObject).toJson());
}
} else if (fieldObject instanceof Collection) {
Iterator<Object> itrFieldObject = ((Collection) fieldObject).iterator();
while (itrFieldObject.hasNext()) {
Object nextListObject = itrFieldObject.next();
if (nextListObject instanceof IPerceroObject) {
String nextKey = RedisKeyUtils.classIdPair(nextListObject.getClass().getCanonicalName(), ((IPerceroObject) nextListObject).getID());
if (redisDataStore.hasKey(nextKey)) {
redisDataStore.deleteKey(nextKey);
// TODO: Do we simply delete the key? Or do we refetch the object here and update the key?
//redisDataStore.setValue(nextKey, ((BaseDataObject)perceroObject).toJson());
}
}
}
}
}
}
Iterator<MappedField> itrToOneFields = mappedClass.toOneFields.iterator();
while (itrToOneFields.hasNext()) {
MappedField nextMappedField = itrToOneFields.next();
Object fieldObject = nextMappedField.getGetter().invoke(perceroObject);
if (fieldObject != null) {
if (fieldObject instanceof IPerceroObject) {
String nextKey = RedisKeyUtils.classIdPair(fieldObject.getClass().getCanonicalName(), ((IPerceroObject) fieldObject).getID());
if (redisDataStore.hasKey(nextKey)) {
redisDataStore.deleteKey(nextKey);
// TODO: Do we simply delete the key? Or do we refetch the object here and update the key?
//redisDataStore.setValue(nextKey, ((BaseDataObject)perceroObject).toJson());
}
} else if (fieldObject instanceof Collection) {
Iterator<Object> itrFieldObject = ((Collection) fieldObject).iterator();
while (itrFieldObject.hasNext()) {
Object nextListObject = itrFieldObject.next();
if (nextListObject instanceof IPerceroObject) {
String nextKey = RedisKeyUtils.classIdPair(nextListObject.getClass().getCanonicalName(), ((IPerceroObject) nextListObject).getID());
if (redisDataStore.hasKey(nextKey)) {
redisDataStore.deleteKey(nextKey);
// TODO: Do we simply delete the key? Or do we refetch the object here and update the key?
//redisDataStore.setValue(nextKey, ((BaseDataObject)perceroObject).toJson());
}
}
}
}
}
}
}
}
} catch (Exception e){
logger.warn(e.getMessage(), e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,11 @@ public Map<Object, Object> getHashEntries( final String key ) {
public Long getHashSize( final String key ) {
return template.opsForHash().size(key);
}

@Transactional
public Long getSetSize( final String key ) {
return template.opsForSet().size(key);
}

@Transactional
public void deleteHashKey( final String key, final Object hashKey ) {
Expand Down
34 changes: 17 additions & 17 deletions src/main/java/com/percero/agents/sync/helpers/PostDeleteHelper.java
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
package com.percero.agents.sync.helpers;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.apache.log4j.Logger;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.percero.agents.sync.access.IAccessManager;
import com.percero.agents.sync.services.IPushSyncHelper;
import com.percero.agents.sync.services.ISyncAgentService;
import com.percero.agents.sync.vo.ClassIDPair;
import com.percero.agents.sync.vo.PushDeleteResponse;
import com.percero.agents.sync.vo.RemovedClassIDPair;
import com.percero.framework.vo.IPerceroObject;
import org.apache.log4j.Logger;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

@Component
public class PostDeleteHelper {
Expand Down Expand Up @@ -63,25 +62,27 @@ public void postDeleteObject(IPerceroObject theObject, String pusherUserId, Stri
log.debug("PostDeleteHelper for " + theObject.toString() + " from clientId " + (pusherClientId == null ? "NULL" : pusherClientId));

ClassIDPair pair = new ClassIDPair(theObject.getID(), theObject.getClass().getCanonicalName());

postDeleteObject(pair, pusherUserId, pusherClientId, pushToUser);
}

public void postDeleteObject(ClassIDPair pair, String pusherUserId, String pusherClientId, boolean pushToUser) throws Exception {
// Remove all UpdateJournals for the objects.
accessManager.removeUpdateJournalsByObject(pair);

// Notify interested users that this object has been deleted.
RemovedClassIDPair removedPair = new RemovedClassIDPair();
removedPair.setClassName(theObject.getClass().getName());
removedPair.setID(theObject.getID());
removedPair.setClassName(pair.getClassName());
removedPair.setID(pair.getID());

List<String> clientIds = accessManager.getObjectAccessJournals(pair.getClassName(), pair.getID());

List<String> clientIds = accessManager.getObjectAccessJournals(theObject
.getClass().getName(), theObject.getID());

// Now remove the AccessJournals for this Object.
accessManager.removeAccessJournalsByObject(pair);
// Now remove the ObjectModJournals for this Object.
accessManager.removeObjectModJournalsByObject(pair);
// Now remove the HistoricalObjects for this Object.
accessManager.removeHistoricalObjectsByObject(pair);

// Now run past the ChangeWatcher.
accessManager.checkChangeWatchers(pair, null, null);
// Remove ChangeWatchers associated with this object.
Expand All @@ -105,7 +106,6 @@ protected void pushObjectDeleteJournals(Collection<String> clientIds, String cla
pushDeleteResponse = new PushDeleteResponse();
pushDeleteResponse.setObjectList(new ArrayList<RemovedClassIDPair>());

// pushDeleteResponse.setClientId(nextClientId);
pushDeleteResponse.getObjectList().add(removedPair);

pushDeleteResponse.setObjectJson(objectJson);
Expand Down
Loading