Jeffrey, thanks. But if I would have only 16KB blocks buffer configured and with a mix of databases 8KB (mostly system or CACHETEMP/IRISTEMP) and some of my application data stored in 16KB blocks. 8KB databases in any way will get buffered in 16KB Buffer, and they will be stored one to one, 8KB data in 16KB buffer. That's correct?

So, If I would need to separate global buffers for streams, I'll just need the separate from any other data block size and a significantly small amount of global buffer for this size of the block and it will be enough for more efficient usage of global buffer? At least for non-stream data, with a higher priority?

I've mentioned above a system with a significant amount of streams stored in the database. And just checked how global buffers used there. And streams are just around 6%. The system is very active, including files. Tons of objects created every minute, attached files, changes in files (yeah, our users can change MS Word files online on the fly, and we keep all the versions).

So, I still see no reasons to change it. And still, see tons of benefits, of keeping it as is.

Fragmentations issues, with SSD disks not an issue anymore. 

But in any way, I agree with storing files in the database. I have a system in production, where we have about 100TB of data, while more than half is just for files, stored in the database. Some of our .dat files by mapping used exclusively for streams, and we take care of them, periodically by cutting them at some point, to continue with an empty database. Mirroring, helps us do not to worry too much about backups. But If would have to store such amount of files as files on the filesystem, we would lose our mind, caring about backups and integrity.

LuhnMCheckSum(input) public {
  Set input = $Piece(input, "#", 1)
  Set codePoints = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/:"
  Set n = $Length(codePoints)

  Set sum = 0
  Set factor = 2
  Set len = $Length(input)  
  For i = len:-1:1 {
    Set codePoint = $Find(codePoints, $Extract(input, i)) - 2
    Set addend = factor * codePoint
    Set factor = $Case(factor, 2: 1, : 2)
    Set addend = (addend \ n) + (addend # n)
    Set sum = sum + addend
  }
  Set remainder = sum # n
  Set checkCodePoint = (n - remainder) # n
  Return $Extract(codePoints, checkCodePoint + 1)
}
LuhnMValidate(input) public {
  Set checksum = $Piece(input, "#", 2)
  Set input = $Piece(input, "#")
  Return $$LuhnMCheckSum(input) = checksum
}

Yeah, sure, it's quite simple to do. JWT tokens contain three parts separated by a pointer sign. 

  • Header, with the algorithm of the signature and the type of token
  • Payload, any data in JSON format
  • Signature needs to verify the token 

All of those parts are encoded with Base64

  Set token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" 

  #; Extract parts of the token
  Set $ListBuild(header, payload, sign) = $ListFromString(token, ".")

  #; Decode and parse Header
  Set header = $System.Encryption.Base64Decode(header)
  Set header = {}.%FromJSON(header)
  Write !,"header"
  Write !,"alg = ",header.alg
  Write !,"typ = ",header.typ

  #; Decode and parse Payload
  Set payload = $System.Encryption.Base64Decode(payload)
  Set payload = {}.%FromJSON(payload)
  Write !!,"data"
  Write !,"name = ", payload.name 
  Write !,"iat = ", payload.iat