Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: b22a503a280082757a14464017b4e7ce4e46ff29 (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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*******************************************************************************
 * Copyright (c) 2000, 2010 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.equinox.internal.p2.artifact.repository.simple;

import java.io.*;
import java.net.URI;
import java.util.Set;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.URIUtil;

/**
 * Blob store which maps UUIDs to blobs on disk. The UUID is mapped
 * to a file in the file-system and the blob is the file contents. For scalability,
 * the blobs are split among 255 directories with the names 00 to FF.
 */
public class BlobStore {
	protected URI store;

	protected boolean fileBased;
	/** Limits the range of directories' names. */
	protected byte mask;

	//private static short[] randomArray = {213, 231, 37, 85, 211, 29, 161, 175, 187, 3, 147, 246, 170, 30, 202, 183, 242, 47, 254, 189, 25, 248, 193, 2, 119, 133, 125, 12, 76, 213, 219, 79, 69, 133, 202, 80, 150, 190, 157, 190, 80, 190, 219, 150, 169, 117, 95, 10, 77, 214, 233, 70, 5, 188, 44, 91, 165, 149, 177, 93, 17, 112, 4, 41, 230, 148, 188, 107, 213, 31, 52, 60, 111, 246, 226, 121, 129, 197, 144, 248, 92, 133, 96, 116, 104, 67, 74, 144, 185, 141, 96, 34, 182, 90, 36, 217, 28, 205, 107, 52, 201, 14, 8, 1, 27, 216, 60, 35, 251, 194, 7, 156, 32, 5, 145, 29, 96, 61, 110, 145, 50, 56, 235, 239, 170, 138, 17, 211, 56, 98, 101, 126, 27, 57, 211, 144, 206, 207, 179, 111, 160, 50, 243, 69, 106, 118, 155, 159, 28, 57, 11, 175, 43, 173, 96, 181, 99, 169, 171, 156, 246, 243, 30, 198, 251, 81, 77, 92, 160, 235, 215, 187, 23, 71, 58, 247, 127, 56, 118, 132, 79, 188, 42, 188, 158, 121, 255, 65, 154, 118, 172, 217, 4, 47, 105, 204, 135, 27, 43, 90, 9, 31, 59, 115, 193, 28, 55, 101, 9, 117, 211, 112, 61, 55, 23, 235, 51, 104, 123, 138, 76, 148, 115, 119, 81, 54, 39, 46, 149, 191, 79, 16, 222, 69, 219, 136, 148, 181, 77, 250, 101, 223, 140, 194, 141, 44, 195, 217, 31, 223, 207, 149, 245, 115, 243, 183};
	private static byte[] randomArray = {-43, -25, 37, 85, -45, 29, -95, -81, -69, 3, -109, -10, -86, 30, -54, -73, -14, 47, -2, -67, 25, -8, -63, 2, 119, -123, 125, 12, 76, -43, -37, 79, 69, -123, -54, 80, -106, -66, -99, -66, 80, -66, -37, -106, -87, 117, 95, 10, 77, -42, -23, 70, 5, -68, 44, 91, -91, -107, -79, 93, 17, 112, 4, 41, -26, -108, -68, 107, -43, 31, 52, 60, 111, -10, -30, 121, -127, -59, -112, -8, 92, -123, 96, 116, 104, 67, 74, -112, -71, -115, 96, 34, -74, 90, 36, -39, 28, -51, 107, 52, -55, 14, 8, 1, 27, -40, 60, 35, -5, -62, 7, -100, 32, 5, -111, 29, 96, 61, 110, -111, 50, 56, -21, -17, -86, -118, 17, -45, 56, 98, 101, 126, 27, 57, -45, -112, -50, -49, -77, 111, -96, 50, -13, 69, 106, 118, -101, -97, 28, 57, 11, -81, 43, -83, 96, -75, 99, -87, -85, -100, -10, -13, 30,
			-58, -5, 81, 77, 92, -96, -21, -41, -69, 23, 71, 58, -9, 127, 56, 118, -124, 79, -68, 42, -68, -98, 121, -1, 65, -102, 118, -84, -39, 4, 47, 105, -52, -121, 27, 43, 90, 9, 31, 59, 115, -63, 28, 55, 101, 9, 117, -45, 112, 61, 55, 23, -21, 51, 104, 123, -118, 76, -108, 115, 119, 81, 54, 39, 46, -107, -65, 79, 16, -34, 69, -37, -120, -108, -75, 77, -6, 101, -33, -116, -62, -115, 44, -61, -39, 31, -33, -49, -107, -11, 115, -13, -73,};

	/**
	 * The limit is the maximum number of directories managed by this store.
	 * This number must be power of 2 and do not exceed 256. The location
	 * should be an existing valid directory.
	 */
	public BlobStore(URI store, int limit) {
		Assert.isNotNull(store);
		this.store = store;
		fileBased = "file".equalsIgnoreCase(store.getScheme()); //$NON-NLS-1$
		if (fileBased)
			Assert.isTrue(!URIUtil.toFile(store).isFile());
		Assert.isTrue(limit == 256 || limit == 128 || limit == 64 || limit == 32 || limit == 16 || limit == 8 || limit == 4 || limit == 2 || limit == 1);
		mask = (byte) (limit - 1);
	}

	public OutputStream getOutputStream(byte[] uuid) throws IOException {
		if (!fileBased)
			return null;
		new File(folderFor(uuid)).mkdir();
		return new FileOutputStream(URIUtil.toFile(fileFor(uuid)));
	}

	/*
	 * @see UniversalUniqueIdentifier#appendByteString(StringBuffer, byte)
	 */
	private void appendByteString(StringBuffer buffer, byte value) {
		String hexString;
		if (value < 0)
			hexString = Integer.toHexString(256 + value);
		else
			hexString = Integer.toHexString(value);
		if (hexString.length() == 1)
			buffer.append("0"); //$NON-NLS-1$
		buffer.append(hexString);
	}

	/*
	 * Converts an array of bytes into a String.
	 *
	 * @see UniversalUniqueIdentifier#toString()
	 */
	private String bytesToHexString(byte[] b) {
		StringBuffer buffer = new StringBuffer();
		for (byte element : b)
			appendByteString(buffer, element);
		return buffer.toString();
	}

	/**
	 * Deletes a blobFile.
	 */
	public void deleteBlob(byte[] uuid) {
		Assert.isNotNull(uuid);
		if (fileBased)
			new File(fileFor(uuid)).delete();
	}

	/**
	 * Delete all of the blobs in the given set.
	 */
	public void deleteBlobs(Set<byte[]> set) {
		for (byte[] blob : set)
			deleteBlob(blob);
	}

	public URI fileFor(byte[] uuid) {
		return URIUtil.append(folderFor(uuid), bytesToHexString(uuid));
	}

	/**
	 * Find out the name of the directory that fits better to this UUID.
	 */
	public URI folderFor(byte[] uuid) {
		byte hash = hashUUIDbytes(uuid);
		hash &= mask; // limit the range of the directory
		return URIUtil.append(store, Integer.toHexString(hash + (128 & mask)) + '/'); // +(128 & mask) makes sure 00h is the lower value
	}

	public InputStream getBlob(byte[] uuid) throws IOException {
		return URIUtil.toURL(fileFor(uuid)).openStream();
	}

	/**
	 * Converts a byte array into a byte hash representation. It is used to
	 * get a directory name.
	 */
	protected byte hashUUIDbytes(byte[] uuid) {
		byte hash = 0;
		for (byte element : uuid)
			hash ^= randomArray[element + 128]; // +128 makes sure the index is >0
		return hash;
	}
}

Back to the top