@@ -16,6 +16,7 @@ import (
1616 "time"
1717 "unsafe"
1818
19+ infinity "github.com/Code-Hex/go-infinity-channel"
1920 "github.com/Code-Hex/vz/v3/internal/objc"
2021)
2122
@@ -210,12 +211,6 @@ func NewVirtioBlockDeviceConfiguration(attachment StorageDeviceAttachment) (*Vir
210211 return config , nil
211212}
212213
213- func newVirtioBlockDeviceConfiguration (ptr unsafe.Pointer ) * VirtioBlockDeviceConfiguration {
214- return & VirtioBlockDeviceConfiguration {
215- pointer : objc .NewPointer (ptr ),
216- }
217- }
218-
219214// BlockDeviceIdentifier returns the device identifier is a string identifying the Virtio block device.
220215// Empty string by default.
221216//
@@ -425,17 +420,8 @@ type NetworkBlockDeviceStorageDeviceAttachment struct {
425420
426421 * baseStorageDeviceAttachment
427422
428- attachmentStatusCh chan networkBlockDeviceStorageDeviceAttachmentStatusData
429- }
430-
431- type NetworkBlockDeviceStorageDeviceAttachmentStatus interface {
432- IsConnected () bool
433- Error () error
434- }
435-
436- type networkBlockDeviceStorageDeviceAttachmentStatusData struct {
437- connected bool
438- err error
423+ didEncounterError * infinity.Channel [error ]
424+ connected * infinity.Channel [struct {}]
439425}
440426
441427var _ StorageDeviceAttachment = (* NetworkBlockDeviceStorageDeviceAttachment )(nil )
@@ -459,14 +445,15 @@ func NewNetworkBlockDeviceStorageDeviceAttachment(url string, timeout time.Durat
459445 return nil , err
460446 }
461447
462- ch := make (chan networkBlockDeviceStorageDeviceAttachmentStatusData )
448+ didEncounterError := infinity .NewChannel [error ]()
449+ connected := infinity .NewChannel [struct {}]()
463450
464451 handle := cgo .NewHandle (func (err error ) {
465- connected := true
466452 if err != nil {
467- connected = false
453+ didEncounterError .In () <- err
454+ return
468455 }
469- ch <- networkBlockDeviceStorageDeviceAttachmentStatusData { connected , err }
456+ connected . In () <- struct {}{ }
470457 })
471458
472459 nserrPtr := newNSErrorAsNil ()
@@ -484,7 +471,8 @@ func NewNetworkBlockDeviceStorageDeviceAttachment(url string, timeout time.Durat
484471 C .uintptr_t (handle ),
485472 ),
486473 ),
487- attachmentStatusCh : ch ,
474+ didEncounterError : didEncounterError ,
475+ connected : connected ,
488476 }
489477 if err := newNSError (nserrPtr ); err != nil {
490478 return nil , err
@@ -495,41 +483,48 @@ func NewNetworkBlockDeviceStorageDeviceAttachment(url string, timeout time.Durat
495483 return attachment , nil
496484}
497485
498- // Returns the connected value. It is true if the NBD client successfully connected to the server. False if there was an error that prevented the connection
499- func ( n * networkBlockDeviceStorageDeviceAttachmentStatusData ) IsConnected () bool {
500- return n . connected
501- }
502-
503- // Returns the error associated to the failed connection of the NBD client to the server
504- func (n * networkBlockDeviceStorageDeviceAttachmentStatusData ) Error () error {
505- return n .err
486+ // Connected receive the signal via channel when the NBD client successfully connects or reconnects with the server.
487+ //
488+ // The NBD connection with the server takes place when the VM is first started, and reconnection attempts take place when the connection
489+ // times out or when the NBD client has encountered a recoverable error, such as an I/O error from the server.
490+ //
491+ // Note that the Virtualization framework may call this method multiple times during a VM’s life cycle. Reconnections are transparent to the guest.
492+ func (n * NetworkBlockDeviceStorageDeviceAttachment ) Connected () <- chan struct {} {
493+ return n .connected . Out ()
506494}
507495
508- // It allows the caller to subscribe to the attachmentStatus channel to listen to changes of the network block device attachment
509- // This way it can be informed if the NBD client successfully connects/reconnects to the server or it encounter an error
510- func (n * NetworkBlockDeviceStorageDeviceAttachment ) Listen (statusCh chan NetworkBlockDeviceStorageDeviceAttachmentStatus ) {
511- go func () {
512- for {
513- status := <- n .attachmentStatusCh
514- statusCh <- & status
515- }
516- }()
496+ // The DidEncounterError is triggered via the channel when the NBD client encounters an error that cannot be resolved on the client side.
497+ // In this state, the client will continue attempting to reconnect, but recovery depends entirely on the server's availability.
498+ // If the server resumes operation, the connection will recover automatically; however, until the server is restored, the client will continue to experience errors.
499+ func (n * NetworkBlockDeviceStorageDeviceAttachment ) DidEncounterError () <- chan error {
500+ return n .didEncounterError .Out ()
517501}
518502
519- //export attachmentHandler
520- func attachmentHandler (cgoHandleUintptr C.uintptr_t , errorPtr unsafe.Pointer ) {
503+ // attachmentDidEncounterErrorHandler function is called when the NBD client encounters a nonrecoverable error.
504+ // After the attachment object calls this method, the NBD client is in a nonfunctional state.
505+ //
506+ //export attachmentDidEncounterErrorHandler
507+ func attachmentDidEncounterErrorHandler (cgoHandleUintptr C.uintptr_t , errorPtr unsafe.Pointer ) {
521508 cgoHandle := cgo .Handle (cgoHandleUintptr )
522509 handler := cgoHandle .Value ().(func (error ))
523510
524511 err := newNSError (errorPtr )
525512
526- go handler (err )
513+ handler (err )
527514}
528515
516+ // attachmentWasConnectedHandler function is called when a connection to the server is first established as the VM starts,
517+ // and during any reconnection attempts triggered by connection timeouts or recoverable errors encountered by the NBD client,
518+ // such as server-side I/O errors.
519+ //
520+ // Note that the Virtualization framework may invoke this method multiple times throughout the VM’s lifecycle,
521+ // ensuring reconnection processes remain seamless and transparent to the guest.
522+ // For more details, see: https://developer.apple.com/documentation/virtualization/vznetworkblockdevicestoragedeviceattachmentdelegate/4168511-attachmentwasconnected?language=objc
523+ //
529524//export attachmentWasConnectedHandler
530525func attachmentWasConnectedHandler (cgoHandleUintptr C.uintptr_t ) {
531526 cgoHandle := cgo .Handle (cgoHandleUintptr )
532527 handler := cgoHandle .Value ().(func (error ))
533528
534- go handler (nil )
529+ handler (nil )
535530}
0 commit comments