Locking semantics

You don't delete an inode; you unlink directory entries from it (this is the operation that is performed when you "delete" a file... you sever the linkage between a particular *name* and the inode that it references).

Each "unlink()" decreases the reference count as the reference is removed. When the last reference is unlink()-ed, you now have no way to reference the inode so it is *then* deleted.

A consequence of this is that you can only "link" (i.e., add another

*name* that references a particular inode) names residing on the same volume together. E.g., if: /some/particular/pathname /some/long/name each reside on the same volume, then: /some/particular/pathname/file1 /some/particular/pathname/file2 /some/particular/pathname/file3 /some/long/name/fileA /some/long/name/fileB can all reference the same "physical" file. (These are called "hard links" -- see below)

If, however: /another/point/in/the/filesystem is on a *different* volume, then you can't link to the file referenced above -- because the other volume has no ties to the first one. For that reason, there are "soft links" (symbolic links) that can be located anywhere and, effectively, encode the referenced pathname *in* the symlink. So, the inode for: /another/point/in/the/filesystem/othername would actually "contain" the equivalent of: "/some/particular/pathname/file1" When /another/point/in/the/filesystem/othername is referenced, it is seen to be such a structure and it's contents are used to find the actual file.

Note that a symlink can reference another symlink, etc. So, this resolution process can be extended arbitrarily.

A consequence of this symlinks implementation is that the

*pathname* which the symlink references can be *deleted* and the symlink is never notified. E.g., if: /some/particular/pathname/file1 is unlinked ("deleted"), then any later attempt to access /another/point/in/the/filesystem/othername will result in "file not found". This is because the *name* "/another/point/in/the/filesystem/othername" persists but the name that it *references*, "/some/particular/pathname/file1", doesn't -- even though the *file* that it was intended to reference is still present as: /some/particular/pathname/file2 /some/particular/pathname/file3 /some/long/name/fileA /some/long/name/fileB I.e., there's no way of knowing how many symlinks reference a particular name when that name is "unlinked"! Nor of sorting out where they reside in the file system(s) -- some of which may not even be *mounted* at the present time!

Links (hard and soft) have value in many ways. E.g., I can put a "name" in a particular place in the filesystem hierarchy (remember, filesystem is just a big, unified namespace!). Then, place links to the actual file in different places for convenience or access control.

E.g., links in every user's home directory that point to "important message" allows everyone to read their apparently *local* "copy" of that "important message" while, in fact, only referencing that one copy. When you've read it, you can freely delete your "copy" of it (unlink the *name* that resides in your home directory) yet still have the actual file persist for the other users who may not, yet, have read it.

inodes are used for multiple purposes in the filesystem. For a regular file, they contain most of the metadata associated with the actual file (its size, owner, access permissions, timestamps, etc -- and, pointers to the actual disk blocks that contain the file's data, for small files... inodes are cascaded to multiple levels of indirection to support bigger files; e.g., the first inode contains pointers to "indirect" inodes which then reference other inodes -- or, the actual data blocks themselves)

A directory is actually a special file whose contents are (name,inode) pairs.

[Disk blocks can contain multiple inodes, so the INITIAL size of a directory varies with the underlying format of the filesystem; bigger blocks create bigger directories before the directory starts to need to reference other disk blocks... just like regular files grow!]
Reply to
Don Y
Loading thread data ...

Grrr... the inode is never "deleted". Rather, it is marked as "free" and reused for some other filesystem use.

Reply to
Don Y

(sigh) Yet another source of confusion...

Directories are (name, inode REFERENCE) pairs -- much the same as my namespaces contain (name, object handle) pairs.

When a filesystem is built, some number of disk blocks are set aside to contain inodes. The system uses these to build the infrastructure for the file system.

E.g., each directory entry "points to" an inode. That inode contains metadata for the file in question (OR, a symlink to a name that does!). In addition to the metadata, it contains pointers to the first N disk blocks that contain the file's data (I think N=12?). So, for "short" files (< 12 blocks), a single inode can encode the position of the entire file's content.

If the file is longer than this, then another pointer in the inode points to a second level of decoding -- another inode that references additional blocks. Etc.

As different directory entries can point to this first inode, it is possible to have different "names" for the same "physical" file. And, because the metadata for the file is stored *in* that inode (and NOT in the directory!), every name that references a particular "physical file" will show the exact same metadata (size, owner, access time, etc.) regardless of how the file is accessed.

A directory is just like a regular file but is composed entirely of (name, inode #) pairs. So, when the first disk block is allocated for the directory, some number of entries can be referenced in it (which depends on how large that block is -- as dictated by the format of the filesystem). As the directory grows, additional blocks are logically appended to it -- just like a regular file growing.

inodes are a fixed size. So, as the underlying filesystem format increases the size of the disk blocks, the number of inodes in any given block increases. (when you build a file system, you decide how large the blocks should be; larger blocks more efficiently handle larger files -- and larger volumes!)

Reply to
Don Y

No. It means only that names must be guaranteed unique within their scope. The easiest way to enforce that is to guarantee that they are unique in any scope.

I wouldn't call that "cooperation" ... it's a condition that needs to be met to be part of the system.

What rules? So far you have been arguing against rules.

You can't have it both ways - you'll end up like Fred and Barney trying to name the boat.

That's why Wilson - it takes into account the number of "good" samples vs total number of sample attempts.

There are problems with every approach I can think of. Every measure is subject to relative displacements on different axes canceling each other. Weighting the components doesn't help.

These are just out of the press. I used to test cooked with my dog Calvin ... he wouldn't eat a noodle unless it was done.

George

Reply to
George Neuner

But objects can have multiple names and in multiple contexts. E.g., "stdin" means different things to different processes.

How do you design so that you can "connect" to vendorA's globally unique named object *or* vendorB's *equivalent* yet differently named object?

Competing processes manage to share *memory* -- they don't each *expect* to be using memory address "27". The system provides mechanisms so their individual needs are met without them realizing there is a conflict.

The rule is: you place a reservation (on a resource: memory, cpu cycles, names, etc.) and, if that reservation can't be met (just like malloc returning NULL), you address it -- or aren't allowed to run/install.

So, developers who are lazy and assume their needs will be met end up producing products that tend to be seen as "problems" instead of those products produced by folks who play be those rules.

But how do you decide what is truly "good"?

That's why its called "Engineering": "choosing the LEAST BAD solution"!

I don't make "thin" pasta (well, sometimes capellini). I much prefer homemade cavatelli -- a heartier pasta. But, far too much effort considering how much/fast I eat it! :-/

Sunday lunch. Finestkind. (C annoyed that I slept late :> )

Reply to
Don Y

Just add one or more top level name services. You're already walking paths by handing them off to different objects ... what's wrong with a vendorA object?

: stdin = open( "/vendorA/stdin" ) :

Why does the string "stdin" have to be unique in the entire system?

If there may be more than one, then make it so a process can query for all the "stdin" that exist. Or turn it around and have the console connect to the process and tell it the meaning of "stdin".

Memory is not the "end all" of sharing examples: in a virtual address system, every process may indeed have an address "27". And they all might be multiplexed on the real address "27".

Leaving aside virtual addressing, how many memory blocks have an

*offset* "27"? There always is some kind of name/reference conflict if you ridiculously include disjoint scopes.

The compiler doesn't use your name "foo" - it maps "foo" to something unique in the scope(s) where "foo" is used. It may complain that "foo" conflicts, but really it is not the name that conflicts but the mapping of the name in the intended scope.

That distinction is important.

"good" = "exists".

Users don't have to answer survey questions: out of W surveys taken, there may be X responses to Q1, Y responses to Q2, no responses to Q3, Z responses to Q4 ...

The potential for null responses invalidates the simple mean - you need to take into account the number of responses vs the number of times the question has been asked. That's the mean with confidence.

8-)

I'm looking for a way to compare sets/tuples of values for degree of similarity. I need to be able to "score" them in a simple way to be able to say, e.g., S1 is 92% wrt S2. The computation of the score needs to be not *too* difficult to explain to a layman.

It's important that every element/component contribute noticeably to the score - which rules out simple sums and products because displacements of different components may cancel. Ditto simple things like minimum or average of components. And "scores" have to be directly comparable, which rules out hashing because hashes are inherently unordered.

AFAICS, that leaves some kind of geometric comparison. There are a number of possibilities there, but all have some sticking points: either the computations are complex, or they lose data (as with sum and product), [or both], or direct comparisons are difficult, or impossible in N space, or are spatially "location" dependent. Etc. ad nauseam.

Hyperplanes would be at different "angles" and so there is no good notion of "distance between them. The end points of differing vectors form an unordered cloud which makes directly comparing end points meaningless. The lengths of the vectors (or of the component paths) suffer from displacement cancellation, as does volume wrt origin.

What seems like it has potential is comparing N-balls whose origins are the end point of the minimum component vector, and whose radii are the distances to the end points of other, non-minimum vectors.

AFAICS, every unique path should result in a different end point, so this incorporates all component information, it is not terribly difficult to compute, and it has the attraction that 2D and 3D notions of it can be illustrated easily.

???

George

Reply to
George Neuner

First, who picks those names? See my comment re: "Hugh's Pizza" opting to choose "HP" as the name of it's namespace. :> I.e., how would Hugh know that someone else hadn't already expected /tmp/HP to be of exclusive use to *it*?

Also, it doesn't address the problem. That (presumably) makes everything under "/vendorA" *private*. I.e., vendorA's app can now create stdin, foo, baz, etc. and know that they are unique -- because the namespace below /vendorA hasn't been "shared" with anyone.

The goal is to be able to share a name with another process. I.e., so "/vendorA" is, in fact, shared and accessible by more than one process. Once that happens, what's to stop one of those other processes from binding "stdin" (your example) to a device that is incompatible with vendorA's application's intended use of that name?

/vendorA's app needs to be able to say: "'stdin' is a name I have chosen to be 'significant'; don't let anyone else use this name in this SHARED namespace! And, in the case where someone has already reserved this name (or, it is already in use), let me know so I can pick a new name that I will be ASSURED will be unique when I eventually execute"

I can do this by adding a reserve() method that can be applied to any "directory object" and forcing the installer to invoke it based on parameters specified in the IDL for a particular module/group of modules.

So, when invokes a method that effectively adds a name to that (shared (portion of)) namespace, the directory server sees the registered reservation and blocks the operation ("E_NAME_CONFLICT") unless the request is being issued by the reserving entity.

It *isn't*. "stdin" may be something like a traditional file to processA, a pipe name to processB, etc.

But, it might deliberately appear in some portion of a namespace. If other actors can create names in that (shared portion of) namespace, then any of them could create stdin and bind it to anything they choose. When processX eventually runs, it discovers that stdin is already in use in the namespace that it was designed to use. (it would have to create a private portion of the namespace like "./HP" and create stdin there)

The goal is to allow multiple objects to be named "stdin" (or ) in much the same way that every (UNIX) process has a "stdin" object. So, each process wants to *know* that it can have a stdin (or a "fizzle") regardless of which other processes have access to *its* namespace.

A VM system grants you the ability to have these (apparent) conflicts because it ensures each *is* disjoint. No other process can access "your" 27, by design. You have to explicitly share it.

Once it is shared, those that have access to it can opt to use it for whatever OTHER reason's they choose.

It doesn't matter to the actor using the name.

As a UN*X-ish example, imagine trying to code a "string" in your application for the name of a file in /tmp through which you will exchange data with another process that has access to /tmp's contents. You'd have to create the name at install time (so it is available for you when you want/need it), then set the group permissions on the "file" so that only members of a particular group could access it, then ensure you and that other process are the only members of that group.

If you postpone these actions to run-time, you may discover that some other process has created a file (under /tmp) with exactly that name and locked *you* out of it. Or, worse, NOT locked you out but is using it to store entirely different data -- your use of that data would be erroneous (it's not what you think it is!); or, your alteration of it would crash a preexisting, functioning application.

I think that may be wishful thinking. OTOH, I'm not sure you can do much better than that as the participants self-select.

Unless you structure the presentation so they see each question individually Note that I complained about that form of presentation: it hides the next questions from the respondent (which I personally dislike) and makes the interaction more tedious (unless you preload the entire survey and just client-script its presentation!)

Regardless, that would just ensure |Q1| >= |Q2| >= |Q3| >= ... which doesn't significantly improve your situation (unless you push the more important questions to the head of the survey)

That;s what makes it *fun*! Digging a ditch is simple: these are the desired dimensions; if you encounter stone, buried human remains, etc. that doesn't change the end result!

So, you're using it as an automated alternative to my "equivalence tables" suggestion?

And, as you say below, they tend to have the "whoosh" effect (sound of something flying over the heads of those to whom you are trying to explain).

I think you'll end up with people *thinking* "well, that makes sense"... but, still, not really relating (grok-ing) to the concept. OTOH, if it is enough to get them past the "why is S1Q4 treated the same as S83Q7 when they appear to be different" then that will be enough.

How'd the noodles end up?

Chores...

Reply to
Don Y

Not exactly. The namespace can be shared immutably or can exist with various protections against unwanted modification.

But it doesn't require any kind of reservation system. Think of it in terms of objects and accessors - if there is no set() for a binding, then it can't be modified.

Or you can make namespaces extensible with the rule that existing binding can't be shadowed by new ones. If some process wants to change a binding, it has to make a copy of the namespace.

With suitable structure and "functional" copying, that doesn't have to be very expensive.

That's why functions like tmpfile() and tmpnam() exist. The whole point is that names should be system generated - guaranteed non-conflicting - and only aliases for them should be permitted to be "friendly".

Right.

No. Regardless of any notions of equivalence, there has to be a doorknob *simple* way for a layman to compare result sets. A tuple of values is too complicated - it requires understanding what the values represent.

[Don't start about "needing to understand" ... Americans vote all the time without understanding anything of the premises, the people, the politics, the problems, the proposals or the potential consequences of their votes.]

My idea is predicated on each variable's value falling within a known range. Seen as a vector tuple, a set of variables/values is a path to a point in N-space. The components of the path can be all minimized, all maximized, or somewhere in between.

The hard part is that the points associated with all possible paths form a cloud confined within a ball in N-space. In 3-space you can think of it as a sphere with the minimum and maximum paths designating the poles, and all other combinations ending at some interior point. Same principle - more dimensions. With discrete values for the variables you can think of it as a rectangular solid inscribed within a sphere.

The object then is to describe the "distance" of a point from the poles. In 3-space it's obvious and mostly intuitive ... in N-space not so much. A "ball" isn't spherical - or any approximation thereof

- it's "shape" is the union of hypersolids that result from all subset combinations of its basis ranges.

IOW: you know that 2 different points represent different paths, but it isn't necessarily obvious how the components of the paths relate to one another.

That's what I would like to remedy - to take the "cloud" of points and squeeze it into a line. Not possible I know.

My grandmother made noodles ... I make bad noodle jokes. I shouldn't even think about noodles.

George

Reply to
George Neuner

Relatively little in the system is "persistent". Objects come (and go) as applications demand services to come on-line, etc. So, *new* objects are the primary occupants of namespaces.

A new process gets little more than a namespace handle provided *to* it. From this, the process must locate everything that it needs to provide its function and/or service.

"Live" objects don't need to exploit a namespace -- for anything other than an initial communication channel. ProcessA can create an object (of type) and directly pass a handle to that object to some other process -- that it locates via the namespace with which it was created. These "anonymous" objects never need to be named unless they need to be located through some *other* process's namespace.

Given that a process may draw on resources and services provided by many other processes, there is need for (portions of) *shared* namespaces. So, processX can create a resource that processA will need (giving it a particular name) while processY creates some other resource that processA will also need (giving it another name), etc. As potentially many actors can create and consume names in that namespace, there is no *guarantee* that a name will be available for a particular use (e.g., another actor comes along and *thinks* some particular name is appropriate for *its* use -- without realizing that some other actor had already planned on using that name... whenever it got around to doing so!)

The directory object (or equivalend) is the object that is being acted upon. If multiple actors have rights to create() names in that object, then any of them can create the name that processZ was expecting to use!

A reservation effectively says: "You can invoke the create() method on this object -- but, in addition to the names that are already in use, representing current objects in that namespace, you can not use any of THESE reserved names: .... Doing so will result in a FAIL."

An analogy with a system heap would be: "You can request memory from the heap -- but, can never request more than a particular quota reserved for your use... even if there are gobs of memory available!"

A process can always augment *it's* namespace and deny others access to it. But, the process must be "live". And, the name that it uses to bind the "augmentation" into the namespace must be "available".

E.g., if that namespace is shared, then some other process could opt to create an object called "augment" (or "subdir" or "private", etc.) and the namespace's owner would effectively be prohibited from making this binding.

Temporary files are seldom "shared" -- except directly to child processes, etc. E.g., if two users did:

$ cd /tmp $ cc ~/myfile.c

At least one of them would be unpleasantly surprised! And, there is no way to ensure a particular one "wins" that race!

I just think letting a *person* make that decision will lead to better data (summaries). Even if they have to hire someone to create and maintain these "equivalence relations". E.g., someone who is happy that they could *return* a product is different from someone who is happy with a product's *purchase*.

Understood.

I think you're setting yourself up for some "conclusions" that end up appearing incompatible -- yet mathematically "correct".

Ah. Now you've got me thinking about them and how yummy some cavatelli would be... Of course, I'll probably be cursing you when/if I actually make them ("Cripes! I forgot how long this takes!!")

I need more automation: a bigger pasta machine; a bigger ice cream churn; a hydraulic lift in the garage floor; etc. You know... "life's little essentials!" ;-)

Reply to
Don Y

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.