# Copyright 1998-2014 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:
	# pylint: disable=W0622
	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
