Skip to content

fix(windows): dehydrate and measure connected Cloud Files placeholders - #518

Merged
veryCrunchy merged 6 commits into
fix/windows-cloud-files-writeback-commitfrom
fix/windows-cloud-files-dehydrate-classification
Oct 17, 2026
Merged

veryCrunchy merged 6 commits into
fix/windows-cloud-files-writeback-commitfrom
fix/windows-cloud-files-dehydrate-classification

Conversation

@veryCrunchy

@veryCrunchy veryCrunchy commented Oct 17, 2026 •

Copy link
Copy Markdown
Member

Stacked on #517 (base fix/windows-cloud-files-writeback-commit).

Outcome

On Windows, Free up space, automatic cleanup, and the Virtual files storage summary now work on downloaded files. Before this change they reported nothing to free while the provider was connected.

While the provider is connected, every file placeholder is a reparse point with an IO_REPARSE_TAG_CLOUD* tag, and Java NIO does not report it as a regular file. JnaWindowsCloudFilesApi.allocatedBytes and dehydrate both returned 0 early when Files.isRegularFile was false. On a disposable sync root, a hydrated, in-sync 256 KiB placeholder allocated 262144 bytes, yet the API reported 0 and dehydrate did nothing.

Changes

  • allocatedBytes and dehydrate classify the path from native find data, using the same rule as the startup enumeration (windowsCloudLocalEntry).
  • dehydrate acts only on an unpinned, in-sync file placeholder (WindowsCloudDehydration.kt) and returns the bytes it actually released.
  • An online-only placeholder that allocates no bytes is skipped before any native call.
  • As the CfDehydratePlaceholder contract requires, dehydration holds an exclusive CfOpenFileWithOplock handle.
  • These all count as 0 freed and no longer abort the whole pass: the oplock cannot be taken (0x80070020) or breaks first, or Windows refuses a file that became dirty (0x80070179), pinned (0x80070188), or open in another application (0x80070187).
  • Automatic cleanup runs its plan through dehydratePlannedEvictions. It keeps a file whose known revision, pin, sync state, or allocated size changed after planning.
  • freeUpSpace and automatic cleanup add up what dehydrate returns, so a refused file is not counted as freed.
  • The out-of-process edit and open-handle test helpers move to a shared WindowsCloudExternalProcess.kt.
  • Size baselines are lowered for WindowsCloudFilesJna.kt (1030 to 1023) and WindowsCloudFilesProvider.kt (2331 to 2319, measured after merging the base).
  • docs/windows-release.md gains a dehydration and storage accounting section, and this PR adds a changelog fragment.

Validation

  • WindowsCloudFilesDehydrationTest has 3 deterministic tests and 3 native Windows tests on a disposable sync root with a synthetic backend. The deterministic tests cover classification, refusal codes, and planned evictions that changed after planning. The native tests are:
    • hydrate a file, check that allocated bytes are above 0, free them with Free up space, check that 0 bytes remain and the file still reopens;
    • the same with automatic cleanup over budget;
    • a dirty edit, a pinned file, and a file another process holds open with read-only sharing all stay local, with unchanged allocation and correct summary totals.
    • The native tests wait, for at most 15 seconds, until a hydrated file reports its full size as allocated. On timeout they report the raw allocation result and placeholder state, because one CI run sampled 0 allocated bytes right after hydration.
  • All 3 native tests fail on the previous code.
  • ./gradlew :ui:desktopTest passed on Windows 11 with JDK 21: 3995 tests, 0 failures, 69 skipped (before the review fixes). After the review fixes and the base merge, --tests '*WindowsCloud*' passed: 147 tests, 2 skipped.
  • bash tools/check-kotlin-architecture.sh passes. bash tools/check-repository.sh passes.

Limits

  • Not checked against Explorer's own Free up space command or a published MSI.
  • The test JVM runs in PHCM_DISGUISE_PLACEHOLDER mode; the packaged launcher's mode has not been measured.
  • Android is unaffected (desktopMain only).

A connected file placeholder is a cloud reparse point that Java NIO does
not report as a regular file, so allocatedBytes and dehydrate returned 0
for every hydrated placeholder. Free up space, automatic cleanup, and the
storage summary therefore found nothing to free.

Classify the path from native find data with the startup enumeration
rule and dehydrate only an unpinned, in-sync file placeholder. Windows
refusals for content that became dirty, pinned, or open elsewhere free
nothing instead of failing the whole pass, and freed totals count the
bytes each dehydration released. Dehydration opens the file for
attribute access only, so a reader that denies write sharing is reported
as in use rather than as a sharing violation.

Native tests on a disposable sync root hydrate, free, and reopen a file,
and keep dirty, pinned, and externally open files local.
…k-commit' into fix/windows-cloud-files-dehydrate-classification
@obiente-cloud
obiente-cloud Bot temporarily deployed to Obiente Preview / PR #518 / NC Native October 17, 2026 19:53 Destroyed
@obiente-cloud

obiente-cloud Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

Obiente preview

NC Native · 02638e2b30f8 · Removed

View preview status

View in Obiente

Obiente updates this comment as the preview changes.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-17T20:52:41.384595Z 02638e2 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@obiente-cloud
obiente-cloud Bot temporarily deployed to Obiente Preview / PR #518 / NC Native October 17, 2026 19:55 Destroyed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 77fe6f6c1e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread ui/src/desktopMain/kotlin/dev/obiente/nextcloudnative/app/WindowsCloudFilesJna.kt Outdated
A Windows CI runner reported no allocated bytes for a placeholder right
after its content was read, although the same sample was complete
locally. Wait within a bound until the file reports its whole size as
allocated, and report the raw allocation result and placeholder state
on timeout. Shorten the changelog summary to the fragment limit.
@obiente-cloud
obiente-cloud Bot temporarily deployed to Obiente Preview / PR #518 / NC Native October 17, 2026 20:25 Destroyed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cb747b1611

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread ui/src/desktopMain/kotlin/dev/obiente/nextcloudnative/app/WindowsCloudFilesJna.kt Outdated
CfDehydratePlaceholder requires an exclusive handle, so dehydration now
holds an exclusive CfOpenFileWithOplock handle. An oplock that cannot be
taken or breaks first keeps the content local and frees nothing.

An online-only placeholder allocates no bytes and is skipped before any
native call, so a cleanup pass does not scale with the remote tree.

Automatic cleanup executes its plan through one checker that also keeps
a file whose known revision changed after planning, besides the existing
pin, sync state, and allocated size checks.
@obiente-cloud
obiente-cloud Bot temporarily deployed to Obiente Preview / PR #518 / NC Native October 17, 2026 20:46 Destroyed
…k-commit' into fix/windows-cloud-files-dehydrate-classification

# Conflicts:
#	tools/kotlin-file-size-baseline.txt
@obiente-cloud
obiente-cloud Bot temporarily deployed to Obiente Preview / PR #518 / NC Native October 17, 2026 20:50 Destroyed
@veryCrunchy
veryCrunchy merged commit 0b529e3 into fix/windows-cloud-files-writeback-commit Oct 17, 2026
5 checks passed

This branch was successfully deployed

No deployments
Obiente Preview / PR #518 / NC Native — 02638e2b Deployed Oct 17, 2026 by obiente-cloud[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant