
Node occasionally gives multiple files/folders the same inode - Mithaldu
https://github.com/nodejs/node/issues/12115
======
Bino
They really run into interesting problem here. Should they treat the inode as
a string (since it's not likely anyone would do mathematical operation on it),
use a two field uint32 array (for correctness) or hash into a 53 bit value
(which can't be reversed into the existing windows API). Hard one. +1 for the
uint32 array field which I think makes the most sense.

~~~
rossy
I think I prefer the string option. inodes (including Windows 64-bit file IDs)
are opaque values. All you can do is compare them with one another and pass
them to functions that accept inodes. Interpreting the integer value of the
inode is meaningless. Using a string preserves these semantics, but using an
array of numbers could be confusing/annoying because it breaks comparison with
== and ===. Also, using a string would be forwards-compatible with any future
changes to how Windows or Node identifies files, for example, Windows 8 has a
128-bit file ID type (which is needed for ReFS, I think.)

~~~
MaulingMonkey
I've done the high/lo "struct" split for pointers in Flash when porting from
32-bit to 64-bit, and it was a pain in the ass (in part because of the ==/===
behavior with arrays you point out). In retrospect I should've gone with
strings. I think we may have even eliminated the pointers before shipping
anything, and wouldn't have been a significant perf hit even if we hadn't.
(For all I know, it might've even been a perf gain...)

~~~
fastftw
Mind explaining the ==/=== issue which arises from the high/lo and array
solution?

~~~
MaulingMonkey
As parent mentions, comparison with ==/=== are "broken" for arrays or classes.
Or more accurately, they now do reference comparisons instead of value
comparisons. This means you have to replace a lot of this (using
Flash/ActionScript as the example here):

    
    
      function updateIcon(id: int, ...) {
        for (var icon in icons) {
          if (icon.id === id) {
            ...
          }
        }
      }
    

With, say, something like this:

    
    
      function updateIcon(id: Ptr, ...) {
        for (var icon in icons) {
          if (Ptr.compare(icon.id, id) === 0) {
            ...
          }
        }
      }
    

Or:

    
    
      function updateIcon(id: Array, ...) {
        for (var icon in icons) {
          if (ObjectUtil.compare(icon.id, id) === 0) {
            ...
          }
        }
      }
    

Assuming you want to preserve the exact semantics of the existing code. If you
miss a single comparison, your code will still compile. You will get no
runtime exceptions, because == and === are still legal. It'll just have a
subtle runtime flaw that will only manifest itself if two interop sites
construct the same pointer value as different Ptr or array instances without
interning (read: caching/leaking Ptr or array instances, which has it's own
problems.) You cannot override == or === to do the right thing (tm) either.

In the unlikely event you do a large refactoring or conversion completely
flawlessly, your coworker's muscle memory will, rather understandably, still
end up causing problems.

    
    
      function updateIcon(id: String, ...) {
        for (var icon in icons) {
          if (icon.id === id) {
            ...
          }
        }
      }
    

This is less refactoring, and just works(tm), because String ==/=== already
compares the value of the strings. No muscle memory to update, easier to print
in debug and trace statements, etc...

------
paulddraper
tl;dr The inode is a 64-bit integer which the high-level JS language doesn't
have.

They could (1) make a two element UInt32Array or (2) use strings or (3) use
all 64 bits of the floating point JS number type.

~~~
rossy
It's worth pointing out that (3) sounds good, but it's an imperfect solution
too. If Number.isNaN(num) is true, num === num will be false. Not just one,
but several 64-bit patterns are considered NaN when represented as a floating-
point number, so if all possible 64-bit values can be used, this could cause
the opposite problem where inodes that are actually the same are considered
not equal by JavaScript.

