Skip to content

Commit

Permalink
Merge branch 'dev' of github.com:ParadropLabs/Paradrop into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
damouse committed Jul 7, 2015
2 parents 8c8fd77 + 4c49742 commit af568ba
Show file tree
Hide file tree
Showing 7 changed files with 611 additions and 1 deletion.
123 changes: 123 additions & 0 deletions paradrop/paradrop/backend/fc/chutestorage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
###################################################################
# Copyright 2013-2014 All Rights Reserved
# Authors: The Paradrop Team
###################################################################

import sys, json, copy, base64

from paradrop.lib.utils.output import out, logPrefix
from paradrop.lib.utils.pdutils import timeint, str2json
from paradrop.lib.utils import pdos
from paradrop.lib import settings

from paradrop.lib.utils.storage import PDStorage

from paradrop.lib.chute import Chute

class ChuteStorage(PDStorage):
"""
ChuteStorage class.
This class holds onto the list of Chutes on this AP.
It implements the PDStorage class which allows us to save the chuteList to disk transparently
"""
# Class variable of chute list so all instances see the same thing
chuteList = dict()

def __init__(self, filename=None, reactor=None):
if(not filename):
filename = settings.FC_CHUTESTORAGE_SAVE_PATH
PDStorage.__init__(self, filename, "chuteList", reactor, settings.FC_CHUTESTORAGE_SAVE_TIMER)

# Has it been loaded?
if(len(ChuteStorage.chuteList) == 0):
out.verbose(' %s Loading chutes from disk: %s\n' % (logPrefix(), filename))
self.loadFromDisk()

def getChuteList(self):
"""Return a list of the GUIDs of the chutes we know of."""
return list(ChuteStorage.chuteList.values())

def getChute(self, name):
"""Returns a reference to a chute we have in our cache, or None."""
return ChuteStorage.chuteList.get(name, None)

def deleteChute(self, ch):
"""Deletes a chute from the chute storage. Can be sent the chute object, or the chute name."""
if (isinstance(ch, Chute)):
del ChuteStorage.chuteList[ch.name]
else:
del ChuteStorage.chuteList[ch]
self.saveToDisk()

def saveChute(self, ch):
"""
Saves the chute provided in our internal chuteList.
Also since we just received a new chute to hold onto we should save our ChuteList to disk.
"""
# check if there is a version of the chute already
oldch = ChuteStorage.chuteList.get(ch.name, None)
if(oldch):
newch = copy.deepcopy(oldch)
# we should merge these chutes so we don't lose any data
# First set the regular data
for k,v in ch.getAPIDataFormat().iteritems():
setattr(newch, k, v)
# Now deal with cache separately
for k,v in ch._cache.iteritems():
newch._cache[k] = v
# this allows us to keep what WAS there, replace any duplicates with new stuff without loosing anything too
ChuteStorage.chuteList[ch.name] = newch
else:
ChuteStorage.chuteList[ch.name] = ch
self.saveToDisk()

def clearChuteStorage(self):
ChuteStorage.chuteList = {}
pdos.remove(settings.FC_CHUTESTORAGE_SAVE_PATH)

#
# Functions we override to implement PDStorage Properly
#
def attrSaveable(self):
"""Returns True if we should save the ChuteList, otherwise False."""
return (type(ChuteStorage.chuteList) == dict)

def importAttr(self, pyld):
"""Takes an array of dicts that represent Chutes and converts them into a list of Chute objects.
Raises Exception if name missing from Chute.
Returns dict[name] = Chute
"""
pyld = json.loads(base64.b64decode(pyld), object_hook=convertUnicode)
d = {}
for p in pyld:
c = Chute(p)
if(c.name == ""):
raise Exception('importChuteList', 'Missing name from Chute object')
d[c.name] = c

#print("importChuteList\n%s" % d)
return d

def exportAttr(self, cl):
"""Takes a chutelist (dict of Chute objects) and returns a string representing an array of chutes in API Data format."""
return base64.b64encode(json.dumps([c.fullDump() for c in ChuteStorage.chuteList.values()]))

if(__name__ == '__main__'):
def usage():
print('Usage: $0 -ls : print chute storage details')
exit(0)

try:
if(sys.argv[1] != '-ls'):
usage()
except Exception as e:
print(e)
usage()

cs = ChuteStorage()

chutes = cs.getChuteList()
for ch in chutes:
print(ch)
2 changes: 2 additions & 0 deletions paradrop/paradrop/backend/fc/updateObject.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
'''

from paradrop.backend import exc
from paradrop.backend.fc import chutestorage
from paradrop.lib import settings

class UpdateObject(object):
Expand Down Expand Up @@ -35,6 +36,7 @@ def __init__(self, obj):
self.failure = None
# Use a temporary planmap for each chute
self.plans = exc.plangraph.PlanMap(self.name)
self.chuteStor = chutestorage.ChuteStorage()

def __str__(self):
return "<Update({}) :: {} - {} @ {}>".format(self.updateClass, self.name, self.updateType, self.tok)
Expand Down
77 changes: 77 additions & 0 deletions paradrop/paradrop/lib/chute.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
###################################################################
# Copyright 2013-2015 All Rights Reserved
# Authors: The Paradrop Team
###################################################################

from paradrop.lib.utils.output import out, logPrefix

STATE_INVALID = "invalid"
STATE_DISABLED = "disabled"
STATE_RUNNING = "running"
STATE_FROZEN = "frozen"
STATE_STOPPED = "stopped"

class Chute(object):
"""
Wrapper class for Chute objects.
"""
def __init__(self, descriptor):
# Set these first so we don't have to worry about it later
self.name = None
self.state = None

self._cache = {}
self.__dict__.update(obj)

def __repr__(self):
return "<Chute %s - %s>" % (self.name, self.state)

def __str__(self):
s = "Chute:%s\n" % (self.name)
return s

def fullDump(self):
"""Return a dump of EVERYTHING in this chute including all API data and all internal cache data."""
d = self.__dict__
d['cache'] = d.pop('_cache')
return d

def isValid(self):
"""Return True only if the Chute object we have has all the proper things defined to be in a valid state."""
if(not self.name or len(self.name) == 0):
return False
return True

def delCache(self, key):
"""Delete the key:val from the _cache dict object."""
if(key in self._cache.keys()):
del(self._cache[key])

def setCache(self, key, val):
"""Set the key:val into the _cache dict object to carry around."""
self._cache[key] = val

def getCache(self, key):
"""Get the val out of the _cache dict object, or None if it doesn't exist."""
return self._cache.get(key, None)

def dumpCache(self):
"""
Return a string of the contents of this chute's cache.
In case of catastrophic failure dump all cache content so we can debug.
"""
return "\n".join(["%s:%s" % (k,v) for k,v in self._cache.iteritems()])

def appendCache(self, key, val):
"""
Finds the key they requested and appends the val into it, this function assumes the cache object
is of list type, if the key hasn't been defined yet then it will set it to an empty list.
"""
r = self.getCache(key)
if(not r):
r = []
elif(not isinstance(r, list)):
out.warn('** %s Unable to append to cache, not list type\n' % logPrefix())
return
r.append(val)
self.setCache(key, r)
3 changes: 2 additions & 1 deletion paradrop/paradrop/lib/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@
#
FC_BOUNCE_UPDATE = None


FC_CHUTESTORAGE_SAVE_PATH = "./tmp"
FC_CHUTESTORAGE_SAVE_TIMER = 60



Expand Down

0 comments on commit af568ba

Please sign in to comment.