]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blobdiff - src/allmydata/mutable/common.py
Remove ResponseCache in favor of MDMFSlotReadProxy's cache. closes #1240.
[tahoe-lafs/tahoe-lafs.git] / src / allmydata / mutable / common.py
index 4e745433e9e4ddfe94ddc8bfa9cdec0f5591f1aa..16f39b302f0d8356f461d02f3d3d72cf314865d0 100644 (file)
 
-from allmydata.util import idlib
-
 MODE_CHECK = "MODE_CHECK" # query all peers
 MODE_ANYTHING = "MODE_ANYTHING" # one recoverable version
 MODE_WRITE = "MODE_WRITE" # replace all shares, probably.. not for initial
                           # creation
 MODE_READ = "MODE_READ"
+MODE_REPAIR = "MODE_REPAIR" # query all peers, get the privkey
 
-class NotMutableError(Exception):
+class NotWriteableError(Exception):
     pass
 
-class NeedMoreDataError(Exception):
+class BadShareError(Exception):
+    """This represents an error discovered in a particular share, during
+    retrieve, from which we can recover by using some other share. This does
+    *not* include local coding errors.
+    """
+
+class NeedMoreDataError(BadShareError):
     def __init__(self, needed_bytes, encprivkey_offset, encprivkey_length):
         Exception.__init__(self)
         self.needed_bytes = needed_bytes # up through EOF
         self.encprivkey_offset = encprivkey_offset
         self.encprivkey_length = encprivkey_length
-    def __str__(self):
+    def __repr__(self):
         return "<NeedMoreDataError (%d bytes)>" % self.needed_bytes
 
 class UncoordinatedWriteError(Exception):
     def __repr__(self):
-        return "<%s -- You, oh user, tried to change a file or directory at the same time as another process was trying to change it.  To avoid data loss, don't do this.  Please see docs/write_coordination.html for details.>" % (self.__class__.__name__,)
+        return ("<%s -- You, oh user, tried to change a file or directory "
+                "at the same time as another process was trying to change it. "
+                " To avoid data loss, don't do this.  Please see "
+                "docs/write_coordination.rst for details.>" %
+                (self.__class__.__name__,))
 
 class UnrecoverableFileError(Exception):
     pass
 
-class CorruptShareError(Exception):
-    def __init__(self, peerid, shnum, reason):
-        self.args = (peerid, shnum, reason)
-        self.peerid = peerid
+class NotEnoughServersError(Exception):
+    """There were not enough functioning servers available to place shares
+    upon. This might result from all servers being full or having an error, a
+    local bug which causes all server requests to fail in the same way, or
+    from there being zero servers. The first error received (if any) is
+    stored in my .first_error attribute."""
+    def __init__(self, why, first_error=None):
+        Exception.__init__(self, why, first_error)
+        self.first_error = first_error
+
+class CorruptShareError(BadShareError):
+    def __init__(self, server, shnum, reason):
+        self.args = (server, shnum, reason)
+        self.server = server
         self.shnum = shnum
         self.reason = reason
     def __str__(self):
-        short_peerid = idlib.nodeid_b2a(self.peerid)[:8]
-        return "<CorruptShareError peerid=%s shnum[%d]: %s" % (short_peerid,
-                                                               self.shnum,
-                                                               self.reason)
-
-
-
-
-
-class DictOfSets(dict):
-    def add(self, key, value):
-        if key in self:
-            self[key].add(value)
-        else:
-            self[key] = set([value])
-
-    def discard(self, key, value):
-        if not key in self:
-            return
-        self[key].discard(value)
-        if not self[key]:
-            del self[key]
-
-class ResponseCache:
-    """I cache share data, to reduce the number of round trips used during
-    mutable file operations. All of the data in my cache is for a single
-    storage index, but I will keep information on multiple shares (and
-    multiple versions) for that storage index.
-
-    My cache is indexed by a (verinfo, shnum) tuple.
-
-    My cache entries contain a set of non-overlapping byteranges: (start,
-    data, timestamp) tuples.
-    """
-
-    def __init__(self):
-        self.cache = DictOfSets()
-
-    def _does_overlap(self, x_start, x_length, y_start, y_length):
-        if x_start < y_start:
-            x_start, y_start = y_start, x_start
-            x_length, y_length = y_length, x_length
-        x_end = x_start + x_length
-        y_end = y_start + y_length
-        # this just returns a boolean. Eventually we'll want a form that
-        # returns a range.
-        if not x_length:
-            return False
-        if not y_length:
-            return False
-        if x_start >= y_end:
-            return False
-        if y_start >= x_end:
-            return False
-        return True
-
-
-    def _inside(self, x_start, x_length, y_start, y_length):
-        x_end = x_start + x_length
-        y_end = y_start + y_length
-        if x_start < y_start:
-            return False
-        if x_start >= y_end:
-            return False
-        if x_end < y_start:
-            return False
-        if x_end > y_end:
-            return False
-        return True
-
-    def add(self, verinfo, shnum, offset, data, timestamp):
-        index = (verinfo, shnum)
-        self.cache.add(index, (offset, data, timestamp) )
-
-    def read(self, verinfo, shnum, offset, length):
-        """Try to satisfy a read request from cache.
-        Returns (data, timestamp), or (None, None) if the cache did not hold
-        the requested data.
-        """
-
-        # TODO: join multiple fragments, instead of only returning a hit if
-        # we have a fragment that contains the whole request
-
-        index = (verinfo, shnum)
-        end = offset+length
-        for entry in self.cache.get(index, set()):
-            (e_start, e_data, e_timestamp) = entry
-            if self._inside(offset, length, e_start, len(e_data)):
-                want_start = offset - e_start
-                want_end = offset+length - e_start
-                return (e_data[want_start:want_end], e_timestamp)
-        return None, None
-
+        return "<CorruptShareError server=%s shnum[%d]: %s" % \
+               (self.server.get_name(), self.shnum, self.reason)
 
+class UnknownVersionError(BadShareError):
+    """The share we received was of a version we don't recognize."""