|
YAACC - UPNP Client and Server
|
In-memory registry of the active shares served by the temporary media proxy. More...

Classes | |
| class | Entry |
| One share. | |
| enum | Kind |
| What the target of an entry is. More... | |
Public Member Functions | |
| ShareRegistry (LongSupplier nowMillis, Consumer< byte[]> randomBytes, int maxActive) | |
| ShareRegistry (LongSupplier nowMillis, Consumer< byte[]> randomBytes) | |
Same with DEFAULT_MAX_ACTIVE. | |
| String | register (Entry entry) |
| Registers an entry. | |
| String | registerOrEvict (Entry entry) |
The one way the glue puts an entry into the registry: if the registry is full, the entry that was released the longest ago (a leftover of an ended playback) is evicted (evictOldestReleased()) and the registration is tried ONCE more. | |
| Entry | lookup (String key) |
| boolean | markActive (String key) |
| Cancels a pending release (a player started again, a renderer is still fetching). | |
| void | release (String key) |
| Starts the grace period (the player ended). | |
| boolean | remove (String key) |
| Removes the entry now and closes its target (once). | |
| boolean | evictOldestReleased () |
| Makes room for a new share: removes and closes the entry that was released the longest ago and is still in its grace period (a leftover of an ended playback). | |
| boolean | hasRoom () |
A cheap look before a file is opened: whether registerOrEvict would find a slot (a free one, an expired one or a released one that can be evicted). | |
| int | expire () |
| Removes and closes every entry that has expired. | |
| void | removeAll () |
| Removes and closes every entry (service stop). | |
| int | size () |
Static Public Member Functions | |
| static ShareRegistry | createDefault () |
A registry on the monotonic system clock and a SecureRandom. | |
| static boolean | isWellFormedKey (String key) |
Format check for the key from a request path, used by the proxy handler BEFORE the lookup (no registry state needed): exactly {@value KEY_TEXT_LENGTH} characters, each one of A-Z a-z 0-9 - _ (the unpadded base64url form of KEY_BYTES bytes). | |
Static Public Attributes | |
| static final int | DEFAULT_MAX_ACTIVE = 8 |
| How many active entries the default registry holds. | |
| static final int | KEY_BYTES = 16 |
| Number of random bytes behind a key (128 bit). | |
| static final int | KEY_TEXT_LENGTH = 22 |
Length of a key in characters: KEY_BYTES bytes as unpadded base64url. | |
In-memory registry of the active shares served by the temporary media proxy.
Plain Java with an injectable clock and random source so it can be unit tested on the JVM.
Every entry gets a random key: 16 bytes from the random source, encoded as unpadded base64url (22 characters). The key depends on nothing but the random bytes (not on the target), is never handed out twice while the registry lives (retired keys are remembered for a bounded window of recent keys, which is plenty for a 128-bit random source and keeps the memory bounded), and is the only way to reach the entry. Nothing is persisted.
Lifetime of an entry: it expires absoluteMaxMillis after registration, or, once release(String) was called, idleGraceMillis after the first release, whichever comes first (markActive(String) cancels a pending release). An expired entry is never returned; it is removed and its target closed when it is noticed (by lookup, register, size or expire()). A target that implements AutoCloseable is closed exactly once, whichever way the entry goes (remove, expiry, removeAll()); an exception from close() is swallowed. At most maxActive entries are held; register returns null when none is free.
All methods are thread safe. No method throws for a null, empty or garbage key.
| de.yaacc.share.ShareRegistry.ShareRegistry | ( | LongSupplier | nowMillis, |
| Consumer< byte[]> | randomBytes, | ||
| int | maxActive ) |
| nowMillis | monotonic clock in milliseconds, not null |
| randomBytes | fills the given array with random bytes (e.g. ), not null; must be thread safe or is only called under the registry's lock |
| maxActive | > 0 |
| IllegalArgumentException | for a null argument or a non-positive maximum |
Referenced by de.yaacc.share.ShareRegistry.createDefault().

| boolean de.yaacc.share.ShareRegistry.evictOldestReleased | ( | ) |
Makes room for a new share: removes and closes the entry that was released the longest ago and is still in its grace period (a leftover of an ended playback).
Entries that were never released are not touched, so a running playback is never cut. Expired entries are swept as well.
register); false if there is no released entry Referenced by de.yaacc.share.ShareRegistry.registerOrEvict().

| int de.yaacc.share.ShareRegistry.expire | ( | ) |
Removes and closes every entry that has expired.
| boolean de.yaacc.share.ShareRegistry.hasRoom | ( | ) |
A cheap look before a file is opened: whether registerOrEvict would find a slot (a free one, an expired one or a released one that can be evicted).
Nothing is changed.
|
static |
Format check for the key from a request path, used by the proxy handler BEFORE the lookup (no registry state needed): exactly {@value KEY_TEXT_LENGTH} characters, each one of A-Z a-z 0-9 - _ (the unpadded base64url form of KEY_BYTES bytes).
ASCII only: no padding =, no + / . %, no whitespace, no unicode letters or digits. Nothing is trimmed or decoded.
Referenced by de.yaacc.share.ShareKeyTracker< P >.keyOfProxyPath(), de.yaacc.share.ShareRegistry.lookup(), de.yaacc.share.ShareRegistry.markActive(), de.yaacc.share.ShareKeyTracker< P >.refresh(), de.yaacc.share.ShareRegistry.release(), de.yaacc.share.ShareRegistry.remove(), de.yaacc.share.ShareConcurrencyLimiter.tryAcquire(), and de.yaacc.upnp.server.http.YaaccUpnpServerContentHttpHandler.updateRendererPosition().

| Entry de.yaacc.share.ShareRegistry.lookup | ( | String | key | ) |

| boolean de.yaacc.share.ShareRegistry.markActive | ( | String | key | ) |
Cancels a pending release (a player started again, a renderer is still fetching).
Does not extend the absolute maximum.

| String de.yaacc.share.ShareRegistry.register | ( | Entry | entry | ) |
Registers an entry.
If no slot is free, expired entries are swept first, so they never block a free slot. Entries that were released but are still in their grace period keep their slot; a caller that wants such an entry to make room calls evictOldestReleased() and retries.
maxActive entries are active or no unused key could be drawn (a broken random source repeating itself); in both cases nothing is stored and the caller keeps ownership of the target (the registry does not close it) | IllegalArgumentException | if the entry is null |
Referenced by de.yaacc.share.ShareRegistry.registerOrEvict().

| String de.yaacc.share.ShareRegistry.registerOrEvict | ( | Entry | entry | ) |
The one way the glue puts an entry into the registry: if the registry is full, the entry that was released the longest ago (a leftover of an ended playback) is evicted (evictOldestReleased()) and the registration is tried ONCE more.
The registry does not close the target of an entry it refused: when this returns null the caller still owns the target and must close it.

| void de.yaacc.share.ShareRegistry.release | ( | String | key | ) |
Starts the grace period (the player ended).
The first release counts; repeated releases do not restart the grace period. Unknown keys are ignored.

| boolean de.yaacc.share.ShareRegistry.remove | ( | String | key | ) |
Removes the entry now and closes its target (once).
Referenced by de.yaacc.upnp.UpnpClient.createPlayableItem(), and de.yaacc.upnp.UpnpClient.discardShareOf().


| int de.yaacc.share.ShareRegistry.size | ( | ) |
Referenced by de.yaacc.share.ShareRegistry.size().

