Yet Another WebIOPi+
 All Classes Namespaces Files Functions Variables Macros Pages
filememory.py
Go to the documentation of this file.
1 # Copyright 2014 Andreas Riegg - t-h-i-n-x.net
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 #
15 # Changelog
16 #
17 # 1.0 2014-08-25 Initial release.
18 # 1.1 2014-09-04 Improved file open/close handling.
19 # Reimplemented writeMemoryBytes().
20 # 1.2 2014-11-13 Updated to match v1.3 of __init__.py
21 # plus some optimizations
22 # 1.3 2014-12-08 Updated to match v1.4 of Memory implementation
23 #
24 # Config parameters
25 #
26 # - slots integer Number of memory bytes
27 # - filename string Name/path of pickle memory file
28 #
29 # Usage remarks
30 #
31 # - This class is mainly targeted to store some 100's of bytes on the
32 # server disk.
33 # It is abolutely NOT suited to save 10's of kilobytes or even more.
34 # Values are kept in server RAM, so reading is very fast but allocates
35 # server RAM memory, so be sparse on slot sizes. Every update
36 # is written immediately to disk, so writing is slower and initiates
37 # server disk activity for every write.
38 # - Multiple device instances are possible within one server. Make sure
39 # to have different filenames/pathes for each device instance via the
40 # filename parameter
41 # - Slot sizes can be changed at every instance creation time. If old size
42 # was smaller, the slots will be filled from the first slot until done.
43 # Remaining slots will be initialized with 0x00. If old size was bigger,
44 # the slots will be filled to the last available slot and the remainder
45 # of the old slot bytes will be discarded.
46 #
47 
48 import os
49 import pickle
50 from webiopi.utils.types import toint
51 from webiopi.devices.memory import Memory
52 
54 # This class uses the standard Pickle utility of Python to store the
55 # bytes.
56 
57 #---------- Constants and definitions ----------
58  BYTES = []
59 
60  FILENAME_DEFAULT = "webiopimem.pkl" # Local memory default name
61  MAXSLOT_VALUE = 10000
62 
63 #---------- Class initialisation ----------
64 
65  def __init__(self, slots=256, filename=None):
66  slots = toint(slots)
67  if not slots in range(1, self.MAXSLOT_VALUE + 1):
68  raise ValueError("slots value [%d] out of range [%d..%d]" % (slots, 1, self.MAXSLOT_VALUE))
69 
70  self._outputfile = None
71 
72  if filename != None:
73  self.filename = filename
74  else:
75  self.filename = self.FILENAME_DEFAULT
76 
77  Memory.__init__(self, slots)
78  self.BYTES = [0 for i in range(slots)]
79 
80  if os.path.exists(self.filename):
81  self.__readFile__()
82 
83 
84 #---------- Abstraction framework contracts ----------
85 
86  def __str__(self):
87  return "PICKLEFILE (%s)" % self.filename
88 
89  def close(self):
90  if self._outputfile is not None:
91  self._outputfile.close()
92 
93 #---------- Memory abstraction related methods ----------
94 
95  def __readMemoryByte__(self, address):
96  return self.BYTES[address]
97 
98  def __writeMemoryByte__(self, address, value):
99  self.BYTES[address] = value
100  self.__writeFile__()
101  return self.__readMemoryByte__(address)
102 
103 
104 #---------- Memory abstraction NON-REST re-implementation ----------
105 # Avoid file writing for every byte, do this for all bytes at the end
106 
107  def writeMemoryBytes(self, start=0, byteValues=[]):
108  self.checkByteAddress(start)
109  stop = start + len(byteValues)
110  self.checkStopByteAddress(stop)
111  i = 0
112  for byte in byteValues: # do nothing if list is empty
113  position = i + start
114  self.BYTES[position] = byte
115  i += 1
116  self.__writeFile__()
117 
118 
119 #---------- Local helpers ----------
120 
121  def __readFile__(self):
122  with open(self.filename, "rb") as f:
123  filebytes = pickle.load(f)
124 
125  byteCountFile = len(filebytes)
126  if (byteCountFile > self.byteCount()):
127  slots = self.byteCount()
128  else:
129  slots = byteCountFile
130  for i in range(slots):
131  self.BYTES[i] = filebytes[i]
132 
133  def __writeFile__(self):
134  if self._outputfile is None:
135  self._outputfile = open(self.filename, "wb")
136  pickle.dump(self.BYTES, self._outputfile)
137