Skip to content

Version 4.7.0

Latest

Choose a tag to compare

@RuiNelson RuiNelson released this 12 Nov 19:50

What's New

  • Block-level read cache: an SMB.Connection can keep what it reads, so reading the same bytes again doesn't go over the network. Attach a cache and nothing else in your code changes. Files you open, uploads and downloads, streams, compareFiles, and the AVFoundation and EXIFKit integrations all read through it.

    let cache = SMB.ReferenceCache(configuration: .init())
    connection.attachCache(cache)
    • fork() passes the cache on to the new connection, and disconnect() detaches it. Files that are already open keep their cache until they close. detachCache() and hasCacheAttached() complete the API.
    • The connection reports every change it makes to the cache: writes, appends, moves, deletes, truncations, date, attribute and security changes, links, copies, and opens with .create or .truncate. The cache then drops the bytes, stats and listings those changes make stale.
    • A cache never makes an operation fail. When it has nothing to offer, or runs into trouble, the connection reads from the server.
    • Attaching a cache adds one extra stat round trip per file opened for reading, and one before closing a file that was written. Without a cache, there is no extra cost.
  • SMB.ReferenceCache: a ready-to-use cache with these options:

    • Storage: bytes are kept in an SMB.CacheStorage. The default SMB.InMemoryCacheStorage has a byte budget (256 MiB by default) and an optional maximumFileSize. It evicts the least recently used files and gives memory back under memory pressure. Several caches can share one storage and its budget.
    • Trust policies: with .statOnServer (size, last-write time and change time) or .sampleBlocks(count:scan:), the cache notices changes made by other clients. These checks run through a control connection that you open, usually with try await connection.fork(), and close yourself.
    • Metadata policy: decides whether stat(at:), itemExists(at:) and listDirectory(at:) may be answered from the cache, and for how long.
    • pathMatching: controls how share paths are matched. .exact is the default; .caseInsensitive lets case variants share an entry on case-insensitive shares. Either way, a change drops every spelling that may name the same file, including spellings that differ in case or Unicode normalization.
  • Custom caches: implement SMB.BlockLevelReadCache to plug in your own cache, or SMB.CacheStorage to keep ReferenceCache's bookkeeping and store the bytes elsewhere.

See the new Block-Level Cache guide.