package notify import "context" func (c *ClientCommon) SetBulkHandler(fn func(BulkAcceptInfo) error) { runtime := c.getBulkRuntime() if runtime == nil { return } runtime.setHandler(fn) } func (c *ClientCommon) OpenBulk(ctx context.Context, opt BulkOpenOptions) (Bulk, error) { if c == nil { return nil, errBulkClientNil } runtime := c.getBulkRuntime() if runtime == nil { return nil, errBulkRuntimeNil } req := clientBulkRequest(runtime, opt) if req.BulkID == "" { return nil, errBulkIDEmpty } if req.Dedicated { if err := clientDedicatedBulkSupportError(c); err != nil { return nil, err } } if !validBulkRange(req.Range) { return nil, errBulkRangeInvalid } if _, exists := runtime.lookup(clientFileScope(), req.BulkID); exists { return nil, errBulkAlreadyExists } resp, err := sendBulkOpenClient(ctx, c, req) if err != nil { return nil, err } if resp.DataID != 0 { req.DataID = resp.DataID } req.Dedicated = resp.Dedicated if resp.AttachToken != "" { req.AttachToken = resp.AttachToken } if req.DataID == 0 { return nil, errBulkDataIDEmpty } bulk := newBulkHandle(c.clientStopContextSnapshot(), runtime, clientFileScope(), req, c.currentClientSessionEpoch(), nil, nil, resp.TransportGeneration, clientBulkCloseSender(c), clientBulkResetSender(c), clientBulkDataSender(c, c.currentClientSessionEpoch()), clientBulkWriteSender(c, c.currentClientSessionEpoch()), clientBulkReleaseSender(c)) bulk.setClientSnapshotOwner(c) if err := runtime.register(clientFileScope(), bulk); err != nil { _, _ = sendBulkResetClient(context.Background(), c, BulkResetRequest{ BulkID: req.BulkID, DataID: req.DataID, Error: err.Error(), }) return nil, err } if bulk.Dedicated() { if err := c.attachDedicatedBulkSidecar(ctx, bulk); err != nil { runtime.remove(clientFileScope(), bulk.ID()) _, _ = sendBulkResetClient(context.Background(), c, BulkResetRequest{ BulkID: bulk.ID(), DataID: bulk.dataIDSnapshot(), Error: err.Error(), }) return nil, err } } return bulk, nil } func clientBulkRequest(runtime *bulkRuntime, opt BulkOpenOptions) BulkOpenRequest { opt = normalizeBulkOpenOptions(opt) id := opt.ID if id == "" && runtime != nil { id = runtime.nextID() } return normalizeBulkOpenRequest(BulkOpenRequest{ BulkID: id, Range: opt.Range, Metadata: cloneBulkMetadata(opt.Metadata), ReadTimeout: opt.ReadTimeout, WriteTimeout: opt.WriteTimeout, Dedicated: opt.Dedicated, ChunkSize: opt.ChunkSize, WindowBytes: opt.WindowBytes, MaxInFlight: opt.MaxInFlight, }) } func clientBulkCloseSender(c *ClientCommon) bulkCloseSender { return func(ctx context.Context, bulk *bulkHandle, full bool) error { if bulk != nil && bulk.Dedicated() { if err := bulk.waitDedicatedReady(ctx); err != nil { return err } return c.sendDedicatedBulkClose(ctx, bulk, full) } _, err := sendBulkCloseClient(ctx, c, BulkCloseRequest{ BulkID: bulk.ID(), Full: full, }) return err } } func clientBulkResetSender(c *ClientCommon) bulkResetSender { return func(ctx context.Context, bulk *bulkHandle, message string) error { if bulk != nil && bulk.Dedicated() { if err := bulk.waitDedicatedReady(ctx); err != nil { return err } return c.sendDedicatedBulkReset(ctx, bulk, message) } _, err := sendBulkResetClient(ctx, c, BulkResetRequest{ BulkID: bulk.ID(), DataID: bulk.dataIDSnapshot(), Error: message, }) return err } } func clientBulkDataSender(c *ClientCommon, epoch uint64) bulkDataSender { return func(ctx context.Context, bulk *bulkHandle, chunk []byte) error { if c == nil { return errBulkClientNil } if ctx != nil { select { case <-ctx.Done(): return ctx.Err() default: } } if bulk != nil && bulk.Dedicated() { if err := bulk.waitDedicatedReady(ctx); err != nil { return err } return c.sendDedicatedBulkData(ctx, bulk, chunk) } if epoch != 0 && !c.isClientSessionEpochCurrent(epoch) { return errTransportDetached } dataID := bulk.dataIDSnapshot() if dataID == 0 { return errBulkDataPathNotReady } return c.sendFastBulkData(ctx, dataID, bulk.nextOutboundDataSeq(), chunk) } } func clientBulkWriteSender(c *ClientCommon, epoch uint64) bulkWriteSender { return func(ctx context.Context, bulk *bulkHandle, payload []byte) (int, error) { if c == nil { return 0, errBulkClientNil } if ctx != nil { select { case <-ctx.Done(): return 0, ctx.Err() default: } } if bulk != nil && bulk.Dedicated() { if err := bulk.waitDedicatedReady(ctx); err != nil { return 0, err } return c.sendDedicatedBulkWrite(ctx, bulk, payload) } if epoch != 0 && !c.isClientSessionEpochCurrent(epoch) { return 0, errTransportDetached } return 0, nil } } func clientBulkReleaseSender(c *ClientCommon) bulkReleaseSender { return func(bulk *bulkHandle, bytes int64, chunks int) error { if c == nil || bulk == nil { return errBulkClientNil } if bytes <= 0 && chunks <= 0 { return nil } if bulk.Dedicated() { return c.sendDedicatedBulkRelease(context.Background(), bulk, bytes, chunks) } return sendBulkReleaseClient(c, BulkReleaseRequest{ BulkID: bulk.ID(), DataID: bulk.dataIDSnapshot(), Bytes: bytes, Chunks: chunks, }) } }