def reconstruct_eclasses(self, cpv, eclass_string): """Turn a string from :obj:`serialize_eclasses` into a dict.""" if not isinstance(eclass_string, basestring): raise TypeError("eclass_string must be basestring, got %r" % eclass_string) eclass_data = eclass_string.strip().split(self.eclass_splitter) if eclass_data == [""]: # occasionally this occurs in the fs backends. they suck. return [] l = len(eclass_data) chf_funcs = self.eclass_chf_deserializers tuple_len = len(chf_funcs) + 1 if len(eclass_data) % tuple_len: raise errors.CacheCorruption( cpv, "_eclasses_ was of invalid len %i" "(must be mod %i)" % (len(eclass_data), tuple_len)) i = iter(eclass_data) # roughly; deserializer grabs the values it needs, resulting # in a sequence of key/tuple pairs for each block of chfs; # this is in turn fed into the dict kls which converts it # to the dict. # Finally, the first item, and that chain, is zipped into # a dict; in effect, if 2 chfs, this results in a stream of- # (eclass_name, ((chf1,chf1_val), (chf2, chf2_val))). try: return [(eclass, tuple(self._deserialize_eclass_chfs(i))) for eclass in i] except ValueError: raise_from( errors.CacheCorruption( cpv, 'ValueError reading %r' % (eclass_string, )))
def _delitem(self, cpv): try: os.remove(pjoin(self.location, cpv)) except FileNotFoundError: raise KeyError(cpv) except OSError as e: raise errors.CacheCorruption(cpv, e) from e
def _delitem(self, cpv): try: os.remove(pjoin(self.location, cpv)) except OSError as e: if e.errno == errno.ENOENT: raise KeyError(cpv) else: raise_from(errors.CacheCorruption(cpv, e))
def _getitem(self, cpv): path = pjoin(self.location, cpv) try: data = readlines_ascii(path, True, True, True) if data is None: raise KeyError(cpv) return self._parse_data(data, data.mtime) except (EnvironmentError, ValueError) as e: raise_from(errors.CacheCorruption(cpv, e))
def _setitem(self, cpv, values): # might seem weird, but we rely on the trailing +1; this # makes it behave properly for any cache depth (including no depth) s = cpv.rfind("/") + 1 fp = pjoin(self.location, cpv[:s], ".update.%i.%s" % (os.getpid(), cpv[s:])) try: myf = open(fp, "w", 32768) except IOError as ie: if ie.errno == errno.ENOENT: if not self._ensure_dirs(cpv): raise errors.CacheCorruption( cpv, 'error creating directory for %r' % (fp, )) try: myf = open(fp, "w", 32768) except EnvironmentError as e: raise_from(errors.CacheCorruption(cpv, e)) else: raise_from(errors.CacheCorruption(cpv, ie)) except OSError as e: raise_from(errors.CacheCorruption(cpv, e)) if self._mtime_used: if not self.mtime_in_entry: mtime = values['_mtime_'] for k, v in values.iteritems(): myf.writelines("%s=%s\n" % (k, v)) myf.close() if self._mtime_used and not self.mtime_in_entry: self._ensure_access(fp, mtime=mtime) else: self._ensure_access(fp) #update written. now we move it. new_fp = pjoin(self.location, cpv) try: os.rename(fp, new_fp) except EnvironmentError as e: os.remove(fp) raise_from(errors.CacheCorruption(cpv, e))
def _setitem(self, cpv, values): values = ProtectedDict(values) # hack. proper solution is to make this a __setitem__ override, since # template.__setitem__ serializes _eclasses_, then we reconstruct it. eclasses = values.pop('_eclasses_', None) if eclasses is not None: eclasses = self.reconstruct_eclasses(cpv, eclasses) values["INHERITED"] = ' '.join(eclasses) s = cpv.rfind('/') fp = pjoin(self.location, cpv[:s], f'.update.{os.getpid()}.{cpv[s+1:]}') try: myf = open(fp, "w") except FileNotFoundError: try: self._ensure_dirs(cpv) myf = open(fp, "w") except EnvironmentError as e: raise errors.CacheCorruption(cpv, e) from e except EnvironmentError as e: raise errors.CacheCorruption(cpv, e) from e count = 0 for idx, key in self.hardcoded_auxdbkeys_order: myf.write("%s%s" % ("\n" * (idx - count), values.get(key, ""))) count = idx myf.write("\n" * (self.magic_line_count - count)) myf.close() self._set_mtime(fp, values, eclasses) # update written, now we move it new_fp = pjoin(self.location, cpv) try: os.rename(fp, new_fp) except EnvironmentError as e: os.remove(fp) raise errors.CacheCorruption(cpv, e) from e
def _setitem(self, cpv, values): # might seem weird, but we rely on the trailing +1; this # makes it behave properly for any cache depth (including no depth) s = cpv.rfind('/') + 1 fp = pjoin(self.location, cpv[:s], f'.update.{os.getpid()}.{cpv[s:]}') try: myf = open(fp, "w", 32768) except FileNotFoundError: if not self._ensure_dirs(cpv): raise errors.CacheCorruption( cpv, f'error creating directory for {fp!r}') try: myf = open(fp, "w", 32768) except EnvironmentError as e: raise errors.CacheCorruption(cpv, e) from e except OSError as e: raise errors.CacheCorruption(cpv, e) from e if self._mtime_used: if not self.mtime_in_entry: mtime = values['_mtime_'] for k, v in sorted(values.items()): myf.writelines(f'{k}={v}\n') myf.close() if self._mtime_used and not self.mtime_in_entry: self._ensure_access(fp, mtime=mtime) else: self._ensure_access(fp) # update written, now we move it new_fp = pjoin(self.location, cpv) try: os.rename(fp, new_fp) except EnvironmentError as e: os.remove(fp) raise errors.CacheCorruption(cpv, e) from e