DEPSOLVE.txt
author Dan Winship <danw@gnome.org>
Fri Mar 07 15:38:31 2008 -0500 (2008-03-07)
changeset 157 57e8182f59bc
child 158 9745a231f8d7
permissions -rw-r--r--
depsolving plan
danw@157
     1
We start with two razor_sets, system and upstream, and a list of
danw@157
     2
requested installations and removals.
danw@157
     3
danw@157
     4
    FIXME: what about multiple upstream repos? Having to deal with
danw@157
     5
    arbitrary numbers of razor_sets is possible, but will probably be
danw@157
     6
    messy... It might be easier to either store all upstream repo data
danw@157
     7
    in a single .repo file, or else merge all upstream .repo files
danw@157
     8
    together into a single razor_set at startup. (Or some combination
danw@157
     9
    of those.)
danw@157
    10
danw@157
    11
We create a bit array of the packages in each set, indicating which
danw@157
    12
ones are installed; the system bitarray starts out all 1s, and the
danw@157
    13
upstream bitarray all 0s. Each bit is only allowed to change state
danw@157
    14
once during the transaction; an installed package can be removed, or
danw@157
    15
an uninstalled package installed, but trying to reinstall a removed
danw@157
    16
package, or uninstall a newly-installed package is an error. This
danw@157
    17
means the packages break down into four categories:
danw@157
    18
danw@157
    19
    - installed       (1 bit in the system bit array)
danw@157
    20
    - to-be-removed   (0 bit in the system bit array)
danw@157
    21
    - to-be-installed (1 bit in the upstream bit array)
danw@157
    22
    - installable     (0 bit in the upstream bit array)
danw@157
    23
danw@157
    24
danw@157
    25
The depsolver repeats the following three steps until there are no new
danw@157
    26
requested installs or removals.
danw@157
    27
danw@157
    28
New packages phase. Walk the system and upstream package lists in
danw@157
    29
parallel, and:
danw@157
    30
danw@157
    31
    - For each package
danw@157
    32
danw@157
    33
	- If it has newly been added to the requested-installs list,
danw@157
    34
          create a razor_transaction_package for it, and set the
danw@157
    35
          appropriate bit in the upstream bitarray; if it is an
danw@157
    36
          update, clear the appropriate bit in the system bitarray
danw@157
    37
danw@157
    38
	- If it has newly been added to the requested-removals list,
danw@157
    39
          create a razor_transaction_package for it, and clear the
danw@157
    40
          appropriate bit in the system bitarray
danw@157
    41
danw@157
    42
Properties phase. Walk the system and upstream property lists in
danw@157
    43
parallel, and:
danw@157
    44
danw@157
    45
    - For each to-be-installed non-file REQUIRES:
danw@157
    46
danw@157
    47
	- See if there's an installed or to-be-installed package that
danw@157
    48
	  PROVIDES that property.
danw@157
    49
danw@157
    50
	- If not, see if there's an installable package that PROVIDES
danw@157
    51
	  that property, and add it to the requested-installs list if
danw@157
    52
	  so.
danw@157
    53
danw@157
    54
	- If not, see if there's a to-be-removed package that PROVIDES
danw@157
    55
	  that property. (If we find such a package, we have a
danw@157
    56
	  CONTRADICTION error.)
danw@157
    57
danw@157
    58
	- If none of the above, then we have an UNSATISFIABLE error
danw@157
    59
danw@157
    60
    - For each to-be-installed file REQUIRES:
danw@157
    61
danw@157
    62
	- Same as for property REQUIRES, except that since we have to
danw@157
    63
	  search the file tree, this is not O(1). (See below for more
danw@157
    64
	  discussion.)
danw@157
    65
danw@157
    66
    - For each to-be-installed PROVIDES:
danw@157
    67
danw@157
    68
	- Check if the new PROVIDES conflicts with an installed
danw@157
    69
	  CONFLICTS. If so, add the installed package to the
danw@157
    70
	  requested-installs list, so we can try to upgrade it to a
danw@157
    71
	  non-conflicting version.
danw@157
    72
danw@157
    73
	- Check if the new PROVIDES conflicts with a to-be-installed
danw@157
    74
	  CONFLICTS. If so, we have an OLD_CONFLICT error.
danw@157
    75
danw@157
    76
    - For each to-be-installed CONFLICTS:
danw@157
    77
danw@157
    78
	- Basically the reverse of the previous case: check if the new
danw@157
    79
	  CONFLICTS conflicts with an installed PROVIDES. If so, add
danw@157
    80
	  the installed package to the requested-installs list to try
danw@157
    81
	  to upgrade it.
danw@157
    82
danw@157
    83
	- Check if the new CONFLICTS conflicts with a to-be-installed
danw@157
    84
	  PROVIDES. If so, we have an NEW_CONFLICT error.
danw@157
    85
danw@157
    86
    - For each to-be-installed OBSOLETES:
danw@157
    87
danw@157
    88
	- Check if there's an installed package that PROVIDES that
danw@157
    89
	  property. If so, add that package to the requested-removals
danw@157
    90
	  list, noting it should be marked obsolete. ("Obsolete" means
danw@157
    91
	  that the to-be-removed PROVIDES step below will treat it
danw@157
    92
	  like it was upgraded, not removed.)
danw@157
    93
danw@157
    94
	- If not, check if there's a to-be-installed package that
danw@157
    95
	  PROVIDES that property. If so, we have a CONTRADICTION
danw@157
    96
	  error.
danw@157
    97
danw@157
    98
    - For each to-be-removed PROVIDES:
danw@157
    99
danw@157
   100
	- If there's also an identical to-be-installed PROVIDES, we're
danw@157
   101
	  ok and can skip this
danw@157
   102
danw@157
   103
	- Otherwise, for each installed REQUIRES of this property:
danw@157
   104
danw@157
   105
	    - Look for some other installed or to-be-installed package
danw@157
   106
	      that satisfies the REQUIRES.
danw@157
   107
danw@157
   108
	    - If there isn't one, then for each installed package in
danw@157
   109
	      this REQUIRES's package list:
danw@157
   110
danw@157
   111
		- If the PROVIDES was lost because the old package was
danw@157
   112
		  removed (not updated or obsoleted), then add the
danw@157
   113
		  requiring package to the requested-removals list.
danw@157
   114
danw@157
   115
		- Otherwise, add the requiring package to the
danw@157
   116
		  requested-installs list so it can be updated as
danw@157
   117
		  well.
danw@157
   118
danw@157
   119
	- (We don't need to look at to-be-installed REQUIRES of this
danw@157
   120
	  property, because if there are any, they will cause a
danw@157
   121
	  CONTRADICTION error when we try to re-satisfy them the next
danw@157
   122
	  time through.)
danw@157
   123
danw@157
   124
    - For each installed file REQUIRES:
danw@157
   125
danw@157
   126
	- Check that the file is still installed. If not, check if
danw@157
   127
	  a to-be-installed package also provides it.
danw@157
   128
danw@157
   129
	- If not:
danw@157
   130
danw@157
   131
	    - If the package originally providing it was removed (not
danw@157
   132
              updated or obsoleted), then add the requiring package to
danw@157
   133
              the requested-removals list.
danw@157
   134
danw@157
   135
	    - Otherwise, add the requiring package to the
danw@157
   136
              requested-installs list, in the hope that an upgrade
danw@157
   137
              will no longer require the file
danw@157
   138
danw@157
   139
(End)
danw@157
   140
danw@157
   141
danw@157
   142
Note on file dependencies
danw@157
   143
danw@157
   144
    - With this algorithm, the total time spent satisfying file
danw@157
   145
      dependencies is O(D * log F), where D is the total number of
danw@157
   146
      file dependencies being added or removed, and F is the total
danw@157
   147
      number of files.
danw@157
   148
danw@157
   149
    - If we sorted the file list differently, we could walk it in
danw@157
   150
      parallel with the property lists, resulting in an overall
danw@157
   151
      file-require-satisfying time of O(F). However, F is likely to be
danw@157
   152
      much much greater than D * log F, so this would probably end up
danw@157
   153
      actually being a pessimization.
danw@157
   154
danw@157
   155
    - A better solution (assuming that we do actually need an O(1)
danw@157
   156
      algorithm here) would be to add explicit file PROVIDES
danw@157
   157
      properties to the set as needed. That is, whenever we add a
danw@157
   158
      package containing a "REQUIRES /foo" property to a set, we also
danw@157
   159
      add a "PROVIDES /foo" property to the set, pointing to the
danw@157
   160
      correct provider packages. More than half of all file requires
danw@157
   161
      are on /bin/sh or /sbin/ldconfig, and of the 7263 file requires
danw@157
   162
      in 9306 packages currently in rawhide.repo, only 154 are not
danw@157
   163
      satisfied by my system.repo. So storing file provides in the
danw@157
   164
      property list as they are needed would eliminate the need to
danw@157
   165
      search through the file list 99% of the time.
danw@157
   166
danw@157
   167
      (We might need a separate optimization for the
danw@157
   168
      building-the-system-up-from-empty case in the installer, since
danw@157
   169
      we'd be resolving the whole transaction without having explicit
danw@157
   170
      PROVIDES listed for /bin/sh, etc.)