aboutsummaryrefslogtreecommitdiffstats
path: root/Zotlabs/Lib/Hashpath.php
blob: f3b25d2b63e879d900d625d383afdb57ee0956cd (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<?php
namespace Zotlabs\Lib;

/*
 * Zotlabs\Lib\Hashpath
 *
 * Creates hashed directory structures for fast access and resistance to overloading any single directory with files.
 *
 * Takes a $hash which could be any string
 * a $prefix which is where to place the hash directory in the filesystem, default is current directory
 * use an empty string for $prefix to place hash directories directly off the root directory
 * an optional $depth and $slice (default is 2) to indicate the hash level
 * $depth = 1, 256 directories, suitable for < 384K records/files
 * $depth = 2, 65536 directories, suitable for < 98M records/files
 * $depth = 3, 16777216 directories, suitable for < 2.5B records/files
 * ...
 * The total number of records anticipated divided by the number of hash directories should generally be kept to
 * less than 1500 entries for optimum performance though this varies by operating system and filesystem type.
 * ext4 uses 32 bit inode numbers (~4B record limit) so use caution or alternative filesystem types with $depth above 3. 
 * an optional $mkdir (boolean) to recursively create the directory (ignoring errors) before returning
 *
 * examples: for a $hash of 'abcdefg' and prefix of 'path' the following paths are returned for $depth = 1 and $depth = 3
 *    path/7d/7d1a54127b222502f5b79b5fb0803061152a44f92b37e23c6527baf665d4da9a
 *    path/7d/1a/54/7d1a54127b222502f5b79b5fb0803061152a44f92b37e23c6527baf665d4da9a
 *
 * see also: boot.php:os_mkdir() - here we provide the equivalent of mkdir -p with permissions of 770. 
 *
 */
 
class Hashpath {

	static function path($hash, $prefix = '.', $depth = 1, $slice = 2, $mkdir = true, $alg = false) {

		if ($alg)
			$hash = hash($alg, $hash);

		$start = 0;
		if ($depth < 1)
			$depth = 1;
		$sluglen = $depth * $slice;

		do {
			$slug	  = substr($hash, $start, $slice);
			$prefix  .= '/' . $slug;
			$start	 += $slice;
			$sluglen -= $slice;
		}
		while ($sluglen);

		if ($mkdir)
			os_mkdir($prefix, STORAGE_DEFAULT_PERMISSIONS, true);
		
		return $prefix . '/' . $hash;
	}
}