[ 
https://issues.apache.org/jira/browse/HDDS-14937?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Sreeja updated HDDS-14937:
--------------------------
    Description: 
Iceberg tables stored in Apache Ozone traditionally(table created via ofs) use 
absolute paths with the "ofs://" protocol prefix in the path. These absolute 
paths prevent the table from being accessed via S3, even when a bucket link 
exists.

This Epic introduces a native Ozone implementation of the Iceberg's 
[RewriteTablePath 
|https://github.com/apache/iceberg/blob/1.10.x/api/src/main/java/org/apache/iceberg/actions/RewriteTablePath.java]
 action to enable seamless protocol migration with zero data file copy. Iceberg 
also provides the core util methods in  
[RewriteTablePathUtil|https://github.com/apache/iceberg/blob/1.10.x/core/src/main/java/org/apache/iceberg/RewriteTablePathUtil.java]
  that can be used by Ozone for the same purpose.

This approach is particularly useful when integrating with REST-based catalogs 
such as Apache Polaris, which expect S3-compatible locations.

We will implement the Iceberg's action and use RewriteTablePathUtil to perform 
a "metadata-only" migration. 
 * *Traverse* the table’s metadata history.

 * *Rewrite* all internal absolute paths from a sourcePrefix (e.g., ofs://) to 
a targetPrefix (e.g., s3a:// or s3://).

 * *Stage* the updated metadata files in a temporary location.

 * *Perform Zero Data Copy:* The actual data files remain untouched, only the 
"pointers" in the metadata are updated.

For example:
Suppose an Iceberg table is created in an Ozone volume/bucket using an ofs:// 
warehouse path, all file references stored across the table’s metadata 
hierarchy are written as absolute ofs:// paths. This includes:
 * Table metadata files (table location, manifest-list location, previous 
metadata file locations)
 * Manifest list files (pointing to manifest files)
 * Manifest files (pointing to data files)
 * Position delete files (referencing affected data files)

{panel:title=sample metadata file before rewrite  }
{ "format-version": 2,

  "table-uuid": "9b791462-d257-45e5-92f8-435302d2c335",

  "location": "{*}ofs://ozone-om:9862/vol1/buck1/my_db/test_table{*}",

  "last-sequence-number": 2,

  "last-updated-ms": 1774448504371,

  "last-column-id": 2,

  "current-schema-id": 0,

  "schemas": [...],

  "default-spec-id": 0,

  "partition-specs": [...],

  "last-partition-id": 999,

  "default-sort-order-id": 0,

  "sort-orders": [...],

  "properties": \{...},

  "current-snapshot-id": 176890185746044789,

  "refs": { "main": {

      "snapshot-id": 176890185746044789,

      "type": "branch"} },

  "snapshots": [ { "sequence-number": 1,

      "snapshot-id": 1753351619419365870,

      "timestamp-ms": 1774448493051,

      "summary": {

        "operation": "append",

        "spark.app.id": "local-1774448389815",

        "added-data-files": "2",

        "added-records": "2",

        "added-files-size": "1224",

        "changed-partition-count": "1",

        "total-records": "2",

        "total-files-size": "1224",

        "total-data-files": "2",

        "total-delete-files": "0",

        "total-position-deletes": "0",

        "total-equality-deletes": "0",

        "engine-version": "3.5.6",

        "app-id": "local-1774448389815",

        "engine-name": "spark",

        "iceberg-version": "Apache Iceberg 1.10.0 (commit 
2114bf631e49af532d66e2ce148ee49dd1dd1f1f)"},

      "manifest-list": 
"{*}ofs://ozone-om:9862/vol1/buck1/my_db/test_table/metadata/snap-1753351619419365870-1-5ac51133-8cbf-4327-bbf8-0559b463e1f9.avro{*}",

      "schema-id": 0 },

    { "sequence-number": 2,

      "snapshot-id": 176890185746044789,

      "parent-snapshot-id": 1753351619419365870,

      "timestamp-ms": 1774448504371,

      "summary": {

        "operation": "append",

        "spark.app.id": "local-1774448389815",

        "added-data-files": "2",

        "added-records": "2",

        "added-files-size": "1224",

        "changed-partition-count": "1",

        "total-records": "4",

        "total-files-size": "2448",

        "total-data-files": "4",

        "total-delete-files": "0",

        "total-position-deletes": "0",

        "total-equality-deletes": "0",

        "engine-version": "3.5.6",

        "app-id": "local-1774448389815",

        "engine-name": "spark",

        "iceberg-version": "Apache Iceberg 1.10.0 (commit 
2114bf631e49af532d66e2ce148ee49dd1dd1f1f)"},

      "manifest-list": 
"{*}ofs://ozone-om:9862/vol1/buck1/my_db/test_table/metadata/snap-176890185746044789-1-5061c816-61b1-43e4-84e8-0ad689c2ea86.avro{*}",

      "schema-id": 0} ],

  "statistics": [],

  "partition-statistics": [],

  "snapshot-log": [...],

  "metadata-log": [ {

      "timestamp-ms": 1774448474465,

      "metadata-file": 
"{*}ofs://ozone-om:9862/vol1/buck1/my_db/test_table/metadata/00000-d480d223-a92f-4255-be8c-fef1714bb423.metadata.json{*}"},

    { "timestamp-ms": 1774448493051,

      "metadata-file": 
"{*}ofs://ozone-om:9862/vol1/buck1/my_db/test_table/metadata/00001-3d20e8d6-e151-4442-a0d7-55533f27cf09.metadata.json{*}"
 } ] }
{panel}
Since these paths are absolute ofs:// paths so they wont be resolved when we 
try to access the table with REST-based catalogs such as Apache Polaris as 
Polaris expects s3:// or s3a:// 

To make the table accessible via S3-compatible systems without copying data, we 
can use Ozone native implementation of Iceberg's RewriteTablePath to rewrite 
these absolute ofs:// paths to s3:// or s3a://


{panel:title=sample metadata file after rewrite  }
{

  "format-version": 2,

  "table-uuid": "9b791462-d257-45e5-92f8-435302d2c335",

  "location": "s3://buck1link/my_db/test_table",

  "last-sequence-number": 2,

  "last-updated-ms": 1774448504371,

  "last-column-id": 2,

  "current-schema-id": 0,

  "schemas": [...],

  "default-spec-id": 0,

  "partition-specs": [...],

  "last-partition-id": 999,

  "default-sort-order-id": 0,

  "sort-orders": [...],

  "properties": \{...},

  "current-snapshot-id": 176890185746044789,

  "refs": {

    "main": {

      "snapshot-id": 176890185746044789,

      "type": "branch"

    }

  },

  "snapshots": [

    {

      "sequence-number": 1,

      "snapshot-id": 1753351619419365870,

      "timestamp-ms": 1774448493051,

      "summary": {

        "operation": "append",

        "spark.app.id": "local-1774448389815",

        "added-data-files": "2",

        "added-records": "2",

        "added-files-size": "1224",

        "changed-partition-count": "1",

        "total-records": "2",

        "total-files-size": "1224",

        "total-data-files": "2",

        "total-delete-files": "0",

        "total-position-deletes": "0",

        "total-equality-deletes": "0",

        "engine-version": "3.5.6",

        "app-id": "local-1774448389815",

        "engine-name": "spark",

        "iceberg-version": "Apache Iceberg 1.10.0 (commit 
2114bf631e49af532d66e2ce148ee49dd1dd1f1f)"

      },

      "manifest-list": 
"s3://buck1link/my_db/test_table/metadata/snap-1753351619419365870-1-5ac51133-8cbf-4327-bbf8-0559b463e1f9.avro",

      "schema-id": 0

    },

    {

      "sequence-number": 2,

      "snapshot-id": 176890185746044789,

      "parent-snapshot-id": 1753351619419365870,

      "timestamp-ms": 1774448504371,

      "summary": {

        "operation": "append",

        "spark.app.id": "local-1774448389815",

        "added-data-files": "2",

        "added-records": "2",

        "added-files-size": "1224",

        "changed-partition-count": "1",

        "total-records": "4",

        "total-files-size": "2448",

        "total-data-files": "4",

        "total-delete-files": "0",

        "total-position-deletes": "0",

        "total-equality-deletes": "0",

        "engine-version": "3.5.6",

        "app-id": "local-1774448389815",

        "engine-name": "spark",

        "iceberg-version": "Apache Iceberg 1.10.0 (commit 
2114bf631e49af532d66e2ce148ee49dd1dd1f1f)"

      },

      "manifest-list": 
"s3://buck1link/my_db/test_table/metadata/snap-176890185746044789-1-5061c816-61b1-43e4-84e8-0ad689c2ea86.avro",

      "schema-id": 0

    }

  ],

  "statistics": [],

  "partition-statistics": [],

  "snapshot-log": [...],

  "metadata-log": [

    {

      "timestamp-ms": 1774448474465,

      "metadata-file": 
"s3://buck1link/my_db/test_table/metadata/00000-d480d223-a92f-4255-be8c-fef1714bb423.metadata.json"

    },

    {

      "timestamp-ms": 1774448493051,

      "metadata-file": 
"s3://buck1link/my_db/test_table/metadata/00001-3d20e8d6-e151-4442-a0d7-55533f27cf09.metadata.json"

    }

  ]

}
{panel}

  was:
Iceberg tables stored in Apache Ozone traditionally(table created via ofs) use 
absolute paths with the "ofs://" protocol prefix in the path. These absolute 
paths prevent the table from being accessed via S3, even when a bucket link 
exists.

This Epic introduces a native Ozone implementation of the Iceberg's 
[RewriteTablePath 
|https://github.com/apache/iceberg/blob/1.10.x/api/src/main/java/org/apache/iceberg/actions/RewriteTablePath.java]
 action to enable seamless protocol migration with zero data file copy. Iceberg 
also provides the core util methods in  
[RewriteTablePathUtil|https://github.com/apache/iceberg/blob/1.10.x/core/src/main/java/org/apache/iceberg/RewriteTablePathUtil.java]
  that can be used by Ozone for the same purpose.

This approach is particularly useful when integrating with REST-based catalogs 
such as Apache Polaris, which expect S3-compatible locations.

We will implement the Iceberg's action and use RewriteTablePathUtil to perform 
a "metadata-only" migration. 
 * *Traverse* the table’s metadata history.

 * *Rewrite* all internal absolute paths from a sourcePrefix (e.g., ofs://) to 
a targetPrefix (e.g., s3a:// or s3://).

 * *Stage* the updated metadata files in a temporary location.

 * *Perform Zero Data Copy:* The actual data files remain untouched, only the 
"pointers" in the metadata are updated.


> Ozone native implementation of Iceberg RewriteTablePath
> -------------------------------------------------------
>
>                 Key: HDDS-14937
>                 URL: https://issues.apache.org/jira/browse/HDDS-14937
>             Project: Apache Ozone
>          Issue Type: Epic
>            Reporter: Sreeja
>            Assignee: Sreeja
>            Priority: Major
>
> Iceberg tables stored in Apache Ozone traditionally(table created via ofs) 
> use absolute paths with the "ofs://" protocol prefix in the path. These 
> absolute paths prevent the table from being accessed via S3, even when a 
> bucket link exists.
> This Epic introduces a native Ozone implementation of the Iceberg's 
> [RewriteTablePath 
> |https://github.com/apache/iceberg/blob/1.10.x/api/src/main/java/org/apache/iceberg/actions/RewriteTablePath.java]
>  action to enable seamless protocol migration with zero data file copy. 
> Iceberg also provides the core util methods in  
> [RewriteTablePathUtil|https://github.com/apache/iceberg/blob/1.10.x/core/src/main/java/org/apache/iceberg/RewriteTablePathUtil.java]
>   that can be used by Ozone for the same purpose.
> This approach is particularly useful when integrating with REST-based 
> catalogs such as Apache Polaris, which expect S3-compatible locations.
> We will implement the Iceberg's action and use RewriteTablePathUtil to 
> perform a "metadata-only" migration. 
>  * *Traverse* the table’s metadata history.
>  * *Rewrite* all internal absolute paths from a sourcePrefix (e.g., ofs://) 
> to a targetPrefix (e.g., s3a:// or s3://).
>  * *Stage* the updated metadata files in a temporary location.
>  * *Perform Zero Data Copy:* The actual data files remain untouched, only the 
> "pointers" in the metadata are updated.
> For example:
> Suppose an Iceberg table is created in an Ozone volume/bucket using an ofs:// 
> warehouse path, all file references stored across the table’s metadata 
> hierarchy are written as absolute ofs:// paths. This includes:
>  * Table metadata files (table location, manifest-list location, previous 
> metadata file locations)
>  * Manifest list files (pointing to manifest files)
>  * Manifest files (pointing to data files)
>  * Position delete files (referencing affected data files)
> {panel:title=sample metadata file before rewrite  }
> { "format-version": 2,
>   "table-uuid": "9b791462-d257-45e5-92f8-435302d2c335",
>   "location": "{*}ofs://ozone-om:9862/vol1/buck1/my_db/test_table{*}",
>   "last-sequence-number": 2,
>   "last-updated-ms": 1774448504371,
>   "last-column-id": 2,
>   "current-schema-id": 0,
>   "schemas": [...],
>   "default-spec-id": 0,
>   "partition-specs": [...],
>   "last-partition-id": 999,
>   "default-sort-order-id": 0,
>   "sort-orders": [...],
>   "properties": \{...},
>   "current-snapshot-id": 176890185746044789,
>   "refs": { "main": {
>       "snapshot-id": 176890185746044789,
>       "type": "branch"} },
>   "snapshots": [ { "sequence-number": 1,
>       "snapshot-id": 1753351619419365870,
>       "timestamp-ms": 1774448493051,
>       "summary": {
>         "operation": "append",
>         "spark.app.id": "local-1774448389815",
>         "added-data-files": "2",
>         "added-records": "2",
>         "added-files-size": "1224",
>         "changed-partition-count": "1",
>         "total-records": "2",
>         "total-files-size": "1224",
>         "total-data-files": "2",
>         "total-delete-files": "0",
>         "total-position-deletes": "0",
>         "total-equality-deletes": "0",
>         "engine-version": "3.5.6",
>         "app-id": "local-1774448389815",
>         "engine-name": "spark",
>         "iceberg-version": "Apache Iceberg 1.10.0 (commit 
> 2114bf631e49af532d66e2ce148ee49dd1dd1f1f)"},
>       "manifest-list": 
> "{*}ofs://ozone-om:9862/vol1/buck1/my_db/test_table/metadata/snap-1753351619419365870-1-5ac51133-8cbf-4327-bbf8-0559b463e1f9.avro{*}",
>       "schema-id": 0 },
>     { "sequence-number": 2,
>       "snapshot-id": 176890185746044789,
>       "parent-snapshot-id": 1753351619419365870,
>       "timestamp-ms": 1774448504371,
>       "summary": {
>         "operation": "append",
>         "spark.app.id": "local-1774448389815",
>         "added-data-files": "2",
>         "added-records": "2",
>         "added-files-size": "1224",
>         "changed-partition-count": "1",
>         "total-records": "4",
>         "total-files-size": "2448",
>         "total-data-files": "4",
>         "total-delete-files": "0",
>         "total-position-deletes": "0",
>         "total-equality-deletes": "0",
>         "engine-version": "3.5.6",
>         "app-id": "local-1774448389815",
>         "engine-name": "spark",
>         "iceberg-version": "Apache Iceberg 1.10.0 (commit 
> 2114bf631e49af532d66e2ce148ee49dd1dd1f1f)"},
>       "manifest-list": 
> "{*}ofs://ozone-om:9862/vol1/buck1/my_db/test_table/metadata/snap-176890185746044789-1-5061c816-61b1-43e4-84e8-0ad689c2ea86.avro{*}",
>       "schema-id": 0} ],
>   "statistics": [],
>   "partition-statistics": [],
>   "snapshot-log": [...],
>   "metadata-log": [ {
>       "timestamp-ms": 1774448474465,
>       "metadata-file": 
> "{*}ofs://ozone-om:9862/vol1/buck1/my_db/test_table/metadata/00000-d480d223-a92f-4255-be8c-fef1714bb423.metadata.json{*}"},
>     { "timestamp-ms": 1774448493051,
>       "metadata-file": 
> "{*}ofs://ozone-om:9862/vol1/buck1/my_db/test_table/metadata/00001-3d20e8d6-e151-4442-a0d7-55533f27cf09.metadata.json{*}"
>  } ] }
> {panel}
> Since these paths are absolute ofs:// paths so they wont be resolved when we 
> try to access the table with REST-based catalogs such as Apache Polaris as 
> Polaris expects s3:// or s3a:// 
> To make the table accessible via S3-compatible systems without copying data, 
> we can use Ozone native implementation of Iceberg's RewriteTablePath to 
> rewrite these absolute ofs:// paths to s3:// or s3a://
> {panel:title=sample metadata file after rewrite  }
> {
>   "format-version": 2,
>   "table-uuid": "9b791462-d257-45e5-92f8-435302d2c335",
>   "location": "s3://buck1link/my_db/test_table",
>   "last-sequence-number": 2,
>   "last-updated-ms": 1774448504371,
>   "last-column-id": 2,
>   "current-schema-id": 0,
>   "schemas": [...],
>   "default-spec-id": 0,
>   "partition-specs": [...],
>   "last-partition-id": 999,
>   "default-sort-order-id": 0,
>   "sort-orders": [...],
>   "properties": \{...},
>   "current-snapshot-id": 176890185746044789,
>   "refs": {
>     "main": {
>       "snapshot-id": 176890185746044789,
>       "type": "branch"
>     }
>   },
>   "snapshots": [
>     {
>       "sequence-number": 1,
>       "snapshot-id": 1753351619419365870,
>       "timestamp-ms": 1774448493051,
>       "summary": {
>         "operation": "append",
>         "spark.app.id": "local-1774448389815",
>         "added-data-files": "2",
>         "added-records": "2",
>         "added-files-size": "1224",
>         "changed-partition-count": "1",
>         "total-records": "2",
>         "total-files-size": "1224",
>         "total-data-files": "2",
>         "total-delete-files": "0",
>         "total-position-deletes": "0",
>         "total-equality-deletes": "0",
>         "engine-version": "3.5.6",
>         "app-id": "local-1774448389815",
>         "engine-name": "spark",
>         "iceberg-version": "Apache Iceberg 1.10.0 (commit 
> 2114bf631e49af532d66e2ce148ee49dd1dd1f1f)"
>       },
>       "manifest-list": 
> "s3://buck1link/my_db/test_table/metadata/snap-1753351619419365870-1-5ac51133-8cbf-4327-bbf8-0559b463e1f9.avro",
>       "schema-id": 0
>     },
>     {
>       "sequence-number": 2,
>       "snapshot-id": 176890185746044789,
>       "parent-snapshot-id": 1753351619419365870,
>       "timestamp-ms": 1774448504371,
>       "summary": {
>         "operation": "append",
>         "spark.app.id": "local-1774448389815",
>         "added-data-files": "2",
>         "added-records": "2",
>         "added-files-size": "1224",
>         "changed-partition-count": "1",
>         "total-records": "4",
>         "total-files-size": "2448",
>         "total-data-files": "4",
>         "total-delete-files": "0",
>         "total-position-deletes": "0",
>         "total-equality-deletes": "0",
>         "engine-version": "3.5.6",
>         "app-id": "local-1774448389815",
>         "engine-name": "spark",
>         "iceberg-version": "Apache Iceberg 1.10.0 (commit 
> 2114bf631e49af532d66e2ce148ee49dd1dd1f1f)"
>       },
>       "manifest-list": 
> "s3://buck1link/my_db/test_table/metadata/snap-176890185746044789-1-5061c816-61b1-43e4-84e8-0ad689c2ea86.avro",
>       "schema-id": 0
>     }
>   ],
>   "statistics": [],
>   "partition-statistics": [],
>   "snapshot-log": [...],
>   "metadata-log": [
>     {
>       "timestamp-ms": 1774448474465,
>       "metadata-file": 
> "s3://buck1link/my_db/test_table/metadata/00000-d480d223-a92f-4255-be8c-fef1714bb423.metadata.json"
>     },
>     {
>       "timestamp-ms": 1774448493051,
>       "metadata-file": 
> "s3://buck1link/my_db/test_table/metadata/00001-3d20e8d6-e151-4442-a0d7-55533f27cf09.metadata.json"
>     }
>   ]
> }
> {panel}



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to