**FREE //===================================================================== // // Project......: MEDDFN // // Member.......: MEDDFNBLD // // Description..: Media Definition Buffer Builder // // Builds IBM API request buffers. // // IBM Release..: IBM i V7R5 // //===================================================================== //--------------------------------------------------------------- // IMPORTANT: // // All offsets in the TAPE0200 create buffer are ABSOLUTE offsets // from the beginning of the API input buffer. // // This includes: // // OffsetToFirstDeviceDefinition // OffsetToNextDeviceDefinition // OffsetToFirstMediaFileDefinition // OffsetToNextMediaFileDefinition // OffsetToVolumeIdentifierArray // // Verified against IBM QSRCRTMD on IBM i 7.5. // //--------------------------------------------------------------- ctl-opt option(*srcstmt:*nodebugio) nomain ; /COPY './meddfn_h.rpgle' /COPY './meddfnap_h.rpgle' // /COPY GOSCH1/MEDDFN,MEDDFN_H // /COPY GOSCH1/MEDDFN,MEDDFNAP_H //===================================================================== // Internal Prototypes //===================================================================== dcl-pr MD_InitializeBuilder; BuilderContext likeds(MD_BuilderContext_T); end-pr; dcl-pr MD_AppendStructure; BuilderContext likeds(MD_BuilderContext_T); Data char(32767) const options(*varsize); DataLength int(10) const; end-pr; dcl-pr MD_AppendBytes; BuilderContext likeds(MD_BuilderContext_T); Data char(32767) const options(*varsize); DataLength int(10) const; end-pr; dcl-pr MD_BuildTape0200Device; BuilderContext likeds(MD_BuilderContext_T); MediaDevice likeds(MD_MediaDevice_T) const; IsLastDevice ind const; end-pr; //===================================================================== // Volume Builder //===================================================================== dcl-pr MD_BuildTape0200VolumeArray; BuilderContext likeds(MD_BuilderContext_T); MediaFile likeds(MD_MediaFile_T) const; end-pr; //===================================================================== // Media Builder //===================================================================== dcl-pr MD_BuildTape0200Media; BuilderContext likeds(MD_BuilderContext_T); MediaDevice likeds(MD_MediaDevice_T) const; MediaIndex int(10) const; end-pr; //===================================================================== // Header Builder //===================================================================== dcl-pr MD_BuildTape0200Header; BuilderContext likeds(MD_BuilderContext_T); MediaDefinition likeds(MD_MediaDefinition_T) const; end-pr; //===================================================================== // Exported Procedures //===================================================================== //===================================================================== // // MD_BuildCreateBuffer // // Description: // Builds a complete TAPE0200 create buffer. // //===================================================================== dcl-proc MD_BuildCreateBuffer export; dcl-pi *n; BuilderContext likeds(MD_BuilderContext_T); MediaDefinition likeds(MD_MediaDefinition_T) const; end-pi; dcl-s DeviceIndex int(10); MD_InitializeBuilder(BuilderContext); MD_BuildTape0200Header( BuilderContext : MediaDefinition); for DeviceIndex = 1 to MediaDefinition.NumberOfDevices; MD_BuildTape0200Device( BuilderContext : MediaDefinition.Device(DeviceIndex) : DeviceIndex = MediaDefinition.NumberOfDevices); endfor; end-proc; //===================================================================== // Internal Procedures //===================================================================== //===================================================================== // // MD_InitializeBuilder // //===================================================================== dcl-proc MD_InitializeBuilder; dcl-pi *n; BuilderContext likeds(MD_BuilderContext_T); end-pi; clear BuilderContext; BuilderContext.BufferLength = 0; end-proc; //===================================================================== // // MD_AppendStructure // //===================================================================== dcl-proc MD_AppendStructure; dcl-pi *n; BuilderContext likeds(MD_BuilderContext_T); Data char(32767) const options(*varsize); DataLength int(10) const; end-pi; %subst( BuilderContext.Buffer : BuilderContext.BufferLength + 1 : DataLength) = %subst(Data : 1 : DataLength); BuilderContext.BufferLength += DataLength; end-proc; //===================================================================== // // MD_AppendBytes // //===================================================================== dcl-proc MD_AppendBytes; dcl-pi *n; BuilderContext likeds(MD_BuilderContext_T); Data char(32767) const options(*varsize); DataLength int(10) const; end-pi; %subst( BuilderContext.Buffer : BuilderContext.BufferLength + 1 : DataLength) = %subst(Data : 1 : DataLength); BuilderContext.BufferLength += DataLength; end-proc; //===================================================================== // // MD_BuildTape0200Header // // Builds the TAPE0200 header. // //===================================================================== dcl-proc MD_BuildTape0200Header; dcl-pi *n; BuilderContext likeds(MD_BuilderContext_T); MediaDefinition likeds(MD_MediaDefinition_T) const; end-pi; dcl-ds Header0200 likeds(MD_Tape0200Header_T) inz; Header0200.Reserved1 = 0; Header0200.Reserved2 = 0; Header0200.MaximumParallelDeviceResources = MediaDefinition.MaximumParallelResources; Header0200.MinimumParallelDeviceResources = MediaDefinition.MinimumParallelResources; Header0200.OffsetToFirstDeviceDefinition = %size(MD_Tape0200Header_T); Header0200.NumberOfDeviceDefinitions = MediaDefinition.NumberOfDevices; Header0200.LengthOfHeader = %size(MD_Tape0200Header_T); Header0200.DeviceAllocation = MediaDefinition.DeviceAllocation; Header0200.SaveFormat = MediaDefinition.SaveFormat; MD_AppendStructure( BuilderContext : Header0200 : %size(Header0200)); end-proc; //===================================================================== // // MD_BuildTape0200Device // // Description: // Builds one TAPE0200 Device Definition and appends it to the // builder buffer. // //===================================================================== dcl-proc MD_BuildTape0200Device; dcl-pi *n; BuilderContext likeds(MD_BuilderContext_T); MediaDevice likeds(MD_MediaDevice_T) const; IsLastDevice ind const; end-pi; dcl-ds Device0200 likeds(MD_Tape0200DeviceDefinition_T) inz; dcl-s MediaIndex int(10); dcl-s NextDeviceOffset int(10); //--------------------------------------------------------------- // Calculate offset to next device definition //--------------------------------------------------------------- if IsLastDevice; NextDeviceOffset = 0; else; NextDeviceOffset = %size(MD_Tape0200DeviceDefinition_T); for MediaIndex = 1 to MediaDevice.NumberOfMediaFiles; NextDeviceOffset += %size(MD_Tape0200MediaFileDefinition_T); NextDeviceOffset += MD_AlignLength( MediaDevice.MediaFile(MediaIndex) .NumberOfVolumeIdentifiers * MD_VOLUME_ID_LENGTH); endfor; endif; //--------------------------------------------------------------- // Device structure //--------------------------------------------------------------- // Device0200.OffsetToNextDeviceDefinition = // NextDeviceOffset; Device0200.OffsetToNextDeviceDefinition = BuilderContext.BufferLength + NextDeviceOffset; Device0200.DeviceName = MediaDevice.DeviceName; Device0200.Reserved = x'0000'; Device0200.OffsetToFirstMediaFileDefinition = BuilderContext.BufferLength + %size(MD_Tape0200DeviceDefinition_T); Device0200.NumberOfMediaFileDefinitions = MediaDevice.NumberOfMediaFiles; Device0200.LengthOfDeviceDefinition = %size(MD_Tape0200DeviceDefinition_T); //--------------------------------------------------------------- // Append device structure //--------------------------------------------------------------- MD_AppendStructure( BuilderContext : Device0200 : %size(Device0200)); //--------------------------------------------------------------- // Append all media definitions //--------------------------------------------------------------- for MediaIndex = 1 to MediaDevice.NumberOfMediaFiles; MD_BuildTape0200Media( BuilderContext : MediaDevice : MediaIndex); MD_BuildTape0200VolumeArray( BuilderContext : MediaDevice.MediaFile(MediaIndex)); endfor; end-proc; //===================================================================== // // MD_BuildTape0200Media // // Description: // Builds one TAPE0200 Media Definition and appends it to the // builder buffer. // //===================================================================== dcl-proc MD_BuildTape0200Media; dcl-pi *n; BuilderContext likeds(MD_BuilderContext_T); MediaDevice likeds(MD_MediaDevice_T) const; MediaIndex int(10) const; end-pi; dcl-ds Media0200 likeds(MD_Tape0200MediaFileDefinition_T) inz; dcl-ds MediaFile likeds(MD_MediaFile_T) inz; MediaFile = MediaDevice.MediaFile(MediaIndex); //--------------------------------------------------------------- // Sequence Number //--------------------------------------------------------------- Media0200.SequenceNumber = MediaFile.SequenceNumber; //--------------------------------------------------------------- // Starting Position in File //--------------------------------------------------------------- Media0200.StartingPositionInFile = *ALL'0'; // TODO: // StartingPositionInFile is currently initialized to *ALL'0'. // The business object does not yet expose all valid API options. //--------------------------------------------------------------- // Volume Information //--------------------------------------------------------------- Media0200.NumberOfVolumeIdentifiers = MediaFile.NumberOfVolumeIdentifiers; if MediaFile.NumberOfVolumeIdentifiers > 0; Media0200.OffsetToVolumeIdentifierArray = BuilderContext.BufferLength + %size(MD_Tape0200MediaFileDefinition_T); Media0200.LengthOfVolumeIdentifier = MD_VOLUME_ID_LENGTH; Media0200.StartingVolumeArrayElement = 1; else; Media0200.OffsetToVolumeIdentifierArray = 0; Media0200.LengthOfVolumeIdentifier = 0; Media0200.StartingVolumeArrayElement = 0; endif; //--------------------------------------------------------------- // Structure Length //--------------------------------------------------------------- Media0200.LengthOfMediaFileDefinition = %size(MD_Tape0200MediaFileDefinition_T); if MediaIndex < MediaDevice.NumberOfMediaFiles; Media0200.OffsetToNextMediaFileDefinition = BuilderContext.BufferLength + %size(MD_Tape0200MediaFileDefinition_T) + (MD_AlignLength( MediaFile.NumberOfVolumeIdentifiers * MD_VOLUME_ID_LENGTH)); else; Media0200.OffsetToNextMediaFileDefinition = 0; endif; //--------------------------------------------------------------- // Append structure to builder buffer //--------------------------------------------------------------- MD_AppendStructure( BuilderContext : Media0200 : %size(Media0200)); end-proc; //===================================================================== // // MD_BuildTape0200VolumeArray // // Description: // Appends all Volume Identifiers to the builder buffer. // //===================================================================== dcl-proc MD_BuildTape0200VolumeArray; dcl-pi *n; BuilderContext likeds(MD_BuilderContext_T); MediaFile likeds(MD_MediaFile_T) const; end-pi; dcl-s VolumeIndex int(10); dcl-s Padding int(10) inz(0); dcl-s Pad char(4) inz(x'00000000'); dcl-s VolumeBytes int(10) inz(0); for VolumeIndex = 1 to MediaFile.NumberOfVolumeIdentifiers; MD_AppendBytes( BuilderContext : MediaFile.VolumeIdentifier( VolumeIndex).VolumeIdentifier : MD_VOLUME_ID_LENGTH ); endfor; VolumeBytes = MediaFile.NumberOfVolumeIdentifiers * MD_VOLUME_ID_LENGTH; Padding = MD_AlignLength(VolumeBytes) - VolumeBytes; if Padding > 0; MD_AppendBytes( BuilderContext : Pad : Padding); endif; end-proc; dcl-proc MD_AlignLength; dcl-pi *n int(10); Length int(10) const; end-pi; dcl-s Result int(10); Result = Length; if %rem(Result : 4) <> 0; Result += 4 - %rem(Result : 4); endif; return Result; end-proc;