# Copyright 1998-2012 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2

import errno
import json
import logging
import stat
import sys

try:
	import cPickle as pickle
except ImportError:
	import pickle

from portage import os
from portage import _encodings
from portage import _os_merge
from portage import _unicode_decode
from portage import _unicode_encode
from portage.exception import PermissionDenied
from portage.localization import _
from portage.util import atomic_ofstream
from portage.util import writemsg_level
from portage.versions import cpv_getkey
from portage.locks import lockfile, unlockfile

if sys.hexversion >= 0x3000000:
	basestring = str

class PreservedLibsRegistry(object):
	""" This class handles the tracking of preserved library objects """

	# JSON read support has been available since portage-2.2.0_alpha89.
	_json_write = True

	_json_write_opts = {
		"ensure_ascii": False,
		"indent": "\t",
		"sort_keys": True
	}
	if sys.hexversion < 0x30200F0:
		# indent only supports int number of spaces
		_json_write_opts["indent"] = 4

	def __init__(self, root, filename):
		""" 
			@param root: root used to check existence of paths in pruneNonExisting
		    @type root: String
			@param filename: absolute path for saving the preserved libs records
		    @type filename: String
		"""
		self._root = root
		self._filename = filename
		self._data = None
		self._lock = None

	def lock(self):
		"""Grab an exclusive lock on the preserved libs registry."""
		if self._lock is not None:
			raise AssertionError("already locked")
		self._lock = lockfile(self._filename)

	def unlock(self):
		"""Release our exclusive lock on the preserved libs registry."""
		if self._lock is None:
			raise AssertionError("not locked")
		unlockfile(self._lock)
		self._lock = None

	def load(self):
		""" Reload the registry data from file """
		self._data = None
		f = None
		content = None
		try:
			f = open(_unicode_encode(self._filename,
					encoding=_encodings['fs'], errors='strict'), 'rb')
			content = f.read()
		except EnvironmentError as e:
			if not hasattr(e, 'errno'):
				raise
			elif e.errno == errno.ENOENT:
				pass
			elif e.errno == PermissionDenied.errno:
				raise PermissionDenied(self._filename)
			else:
				raise
		finally:
			if f is not None:
				f.close()

		# content is empty if it's an empty lock file
		if content:
			try:
				self._data = json.loads(_unicode_decode(content,
					encoding=_encodings['repo.content'], errors='strict'))
			except SystemExit:
				raise
			except Exception as e:
				try:
					self._data = pickle.loads(content)
				except SystemExit:
					raise
				except Exception:
					writemsg_level(_("!!! Error loading '%s': %s\n") %
						(self._filename, e), level=logging.ERROR,
						noiselevel=-1)

		if self._data is None:
			self._data = {}
		else:
			for k, v in self._data.items():
				if isinstance(v, (list, tuple)) and len(v) == 3 and \
					isinstance(v[2], set):
					# convert set to list, for write with JSONEncoder
					self._data[k] = (v[0], v[1], list(v[2]))

		self._data_orig = self._data.copy()
		self.pruneNonExisting()

	def store(self):
		"""
		Store the registry data to the file. The existing inode will be
		replaced atomically, so if that inode is currently being used
		for a lock then that lock will be rendered useless. Therefore,
		it is important not to call this method until the current lock
		is ready to be immediately released.
		"""
		if os.environ.get("SANDBOX_ON") == "1" or \
			self._data == self._data_orig:
			return
		try:
			f = atomic_ofstream(self._filename, 'wb')
			if self._json_write:
				f.write(_unicode_encode(
					json.dumps(self._data, **self._json_write_opts),
					encoding=_encodings['repo.content'], errors='strict'))
			else:
				pickle.dump(self._data, f, protocol=2)
			f.close()
		except EnvironmentError as e:
			if e.errno != PermissionDenied.errno:
				writemsg_level("!!! %s %s\n" % (e, self._filename),
					level=logging.ERROR, noiselevel=-1)
		else:
			self._data_orig = self._data.copy()

	def _normalize_counter(self, counter):
		"""
		For simplicity, normalize as a unicode string
		and strip whitespace. This avoids the need for
		int conversion and a possible ValueError resulting
		from vardb corruption.
		"""
		if not isinstance(counter, basestring):
			counter = str(counter)
		return _unicode_decode(counter).strip()

	def register(self, cpv, slot, counter, paths):
		""" Register new objects in the registry. If there is a record with the
			same packagename (internally derived from cpv) and slot it is 
			overwritten with the new data.
			@param cpv: package instance that owns the objects
			@type cpv: CPV (as String)
			@param slot: the value of SLOT of the given package instance
			@type slot: String
			@param counter: vdb counter value for the package instance
			@type counter: String
			@param paths: absolute paths of objects that got preserved during an update
			@type paths: List
		"""
		cp = cpv_getkey(cpv)
		cps = cp+":"+slot
		counter = self._normalize_counter(counter)
		if len(paths) == 0 and cps in self._data \
				and self._data[cps][0] == cpv and \
				self._normalize_counter(self._data[cps][1]) == counter:
			del self._data[cps]
		elif len(paths) > 0:
			if isinstance(paths, set):
				# convert set to list, for write with JSONEncoder
				paths = list(paths)
			self._data[cps] = (cpv, counter, paths)

	def unregister(self, cpv, slot, counter):
		""" Remove a previous registration of preserved objects for the given package.
			@param cpv: package instance whose records should be removed
			@type cpv: CPV (as String)
			@param slot: the value of SLOT of the given package instance
			@type slot: String
		"""
		self.register(cpv, slot, counter, [])
	
	def pruneNonExisting(self):
		""" Remove all records for objects that no longer exist on the filesystem. """

		os = _os_merge

		for cps in list(self._data):
			cpv, counter, _paths = self._data[cps]

			paths = []
			hardlinks = set()
			symlinks = {}
			for f in _paths:
				f_abs = os.path.join(self._root, f.lstrip(os.sep))
				try:
					lst = os.lstat(f_abs)
				except OSError:
					continue
				if stat.S_ISLNK(lst.st_mode):
					try:
						symlinks[f] = os.readlink(f_abs)
					except OSError:
						continue
				elif stat.S_ISREG(lst.st_mode):
					hardlinks.add(f)
					paths.append(f)

			# Only count symlinks as preserved if they still point to a hardink
			# in the same directory, in order to handle cases where a tool such
			# as eselect-opengl has updated the symlink to point to a hardlink
			# in a different directory (see bug #406837). The unused hardlink
			# is automatically found by _find_unused_preserved_libs, since the
			# soname symlink no longer points to it. After the hardlink is
			# removed by _remove_preserved_libs, it calls pruneNonExisting
			# which eliminates the irrelevant symlink from the registry here.
			for f, target in symlinks.items():
				if os.path.join(os.path.dirname(f), target) in hardlinks:
					paths.append(f)

			if len(paths) > 0:
				self._data[cps] = (cpv, counter, paths)
			else:
				del self._data[cps]
	
	def hasEntries(self):
		""" Check if this registry contains any records. """
		if self._data is None:
			self.load()
		return len(self._data) > 0
	
	def getPreservedLibs(self):
		""" Return a mapping of packages->preserved objects.
			@return mapping of package instances to preserved objects
			@rtype Dict cpv->list-of-paths
		"""
		if self._data is None:
			self.load()
		rValue = {}
		for cps in self._data:
			rValue[self._data[cps][0]] = self._data[cps][2]
		return rValue
