mIRC Home    About    Download    Register    News    Help

Print Thread
#258235 20/06/16 07:11 PM
Joined: Apr 2010
Posts: 969
F
Hoopy frood
OP Offline
Hoopy frood
F
Joined: Apr 2010
Posts: 969
I'd like a command to rename a hashtable. There's only two ways to mimic renaming a hashtable via scripting:

1. Looping: With my current 15,000+ items this would cause my mIRC to stutter at the least if not out-right freeze for a few seconds

2. Use the filing system: This is sub-optimal as we've all seen instances of where writing to file system can cause file corruption(no fault of mIRC's).


I purpose adding the following:

/hrename table newname

Renames table to newname
if the newname table already exists, mIRC should raise an error


Use-case: I'm pulling information from multiple web sources and do not want to alter my current table unless all the web-requests succeed. To do this, I'm adding items to temporary hashtable and here in lays the problem.


I am SReject
My Stuff
Joined: Dec 2008
Posts: 1,515
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2008
Posts: 1,515
Good suggestion +1.

- Like!


Need Online mIRC help or an mIRC Scripting Freelancer? -> https://irc.chathub.org <-
Joined: Oct 2003
Posts: 3,918
A
Hoopy frood
Offline
Hoopy frood
A
Joined: Oct 2003
Posts: 3,918
I don't disagree that /hrename would help in general, but it definitely sounds like you can avoid having to rename your hash table. Or, put another way-- I don't see why you should ever need to rename a table. Just name it what you want from the start.

From what I understand of the very short use case explanation, you're opening a bunch of sockets, writing results to a temp table, and then, when finalizing, you rename the table to something else. I don't see why you have to rename the table to something else.

You're calling the hash table "temporary", but it's not. The hash table and all of its data are "permanent". The only temporary thing about the use case you described is the name you gave it. But again, there's no reason for the name to be temporary. You can make the name permanent.

I assume you're trying to do something similar to a file swap:

1. A <- main hash table
2. create table B
3. write to B
4. delete A
5. rename B -> A

If this is true, you're using the actual table name "A" as a symbolic pointer to "the current table", which is certainly one way to do it -- let's call this "Method A". You're using the hardcoded table named A as if it were a "variable table"; a table that could have any contents. But, that's not how hash tables work, and, more importantly, there is already a way to express "variable" things in mIRC.

Quite simply, you should flip the way you're keeping track of "the current table". Instead of making sure your $hget() always go to hardcoded table A, do lookups through a table whose name is stored in a %variable. Then, all you need to do is update the variable name to point to your new table and you're done. No renames needed.

This has the added benefits of allowing you to do lookups across multiple tables (you don't need to delete the old one), and also, you can rollback fairly easily (again, don't delete old table, just keep it around). In threaded environments (not mIRC) the update is also atomic, so no critical sections needed. In those threaded environments, you can even delete the table in the background, which would create less of a stop-the-world effect. None of this is likely necessary for your use case, but what I'm getting at is that "Method A" is really never a good architecture unless you have some kind of open handle on the table that can stay open across renames-- but mIRC does not support this on hash tables, so it's not a concern.

Basically, what you should be doing is:

1. %A <- main hash table variable name
2. create table ANYTHING_YOU_WANT.tmpNNNNN
3. write to table ANYTHING_YOU_WANT.tmpNNNN
4. /set %A ANYTHING_YOU_WANT.tmpNNNN
5. [optional] delete old table (previous value for %A)

Note: NNNN can be a timestamp, so if you kept old tables around, you could even use the table name as a incrementing version to know which is the latest and even when they were created. You could do this part in other ways, of course, but all this comes for free.

But there you go, no renaming needed. I'm sure I might have some details wrong about your use case, but I'm fairly certain you can follow the spirit of this guide and make your use case work without needing to rename the table.

All this to say that while I think /hrename could be useful as a manual maintenance command, there's no reason to need it in any automated script. There are ways to deal with the constraint of immutable hash table names.


- argv[0] on EFnet #mIRC
- "Life is a pointer to an integer without a cast"
Joined: Apr 2010
Posts: 969
F
Hoopy frood
OP Offline
Hoopy frood
F
Joined: Apr 2010
Posts: 969
Originally Posted By: argv0
Basically, what you should be doing is:

1. %A <- main hash table variable name
2. create table ANYTHING_YOU_WANT.tmpNNNNN
3. write to table ANYTHING_YOU_WANT.tmpNNNN
4. /set %A ANYTHING_YOU_WANT.tmpNNNN
5. [optional] delete old table (previous value for %A)


I thought about this, but since mIRC doesn't have privatized members I find it best to keep variables to a minimal. Reduces the chance of user-action or a malfunctioning script to 'corrupt' the state of another script

Last edited by FroggieDaFrog; 23/06/16 08:33 PM.

I am SReject
My Stuff
Joined: Oct 2003
Posts: 3,918
A
Hoopy frood
Offline
Hoopy frood
A
Joined: Oct 2003
Posts: 3,918
That's not really a valid counterpoint. Hash table names are also public. Using /hfree, /hdel, or /hadd would corrupt the script in the same way.

If you have a variable that you don't want overwritten, simply namespace it appropriately (%scriptprefix.some.name) and it should not get modified unless the user really wanted to change it. In the latter case, the user could do the same with your hash table. Incidentally, /hrename makes it even easier for an outside user to do this, so this feature suggestion actually creates the same problem you're trying to avoid with variables.

The reality is that everything in mIRC is open for modification, including the very logic of your script. Even if mIRC had a "private" modifier on variables, it would be trivial to modify a script and change that if a user really wanted access. The issue I think you are raising is accidental modification, but as mentioned, with proper scoping, you can easily avoid this.

As a sidenote, if you're worried about the variables section being completely wiped (something you may want to account for), you can do something like:

Code:
; ensure %myscript.tablename is always set
alias -l find.table {
  if (%myscript.tablename) return
  var %i = $hget(0)
  while (%i > 0) {
    if (myscript.tableprefix.* iswm $hget(%i)) {
      set %myscript.tablename $hget(%i)
      return
    }
    dec %i
  }
}

alias -l table.lookup {
  find.table
  return $hget(%myscript.tablename, $1)
}


Use $table.lookup() as your primary alias and it will ensure that the table variable is always set. This does make an assumption that you (a) only have one table at any time (you're deleting the others) or (b) if you do have multiple tables, the "last created" one is the "active" table. Of course you could also write the table name to a file to ensure you could reload it if variables were erased. That might be more efficient than $hget(N). Your call there.


- argv[0] on EFnet #mIRC
- "Life is a pointer to an integer without a cast"
Joined: Jul 2006
Posts: 4,149
W
Hoopy frood
Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,149
Your example is as wrong as Froggie's answer, if this code makes sure the variable is always set, then it needs something to make sure the hash table is also always there, this has no end.

He probably didn't want to use a %variable because it's (wrongly) considered 'bad' (you know, the "don't use global variable, use an hash table instead").
I think /hrename and some /hcopy would be welcome, if I never had to rename an hash table, making a copy of it would have been useful for me in the past, I don't want to hijack this thread but copying only the matching item/data etc could be quite useful.


#mircscripting @ irc.swiftirc.net == the best mIRC help channel
Joined: Oct 2003
Posts: 3,918
A
Hoopy frood
Offline
Hoopy frood
A
Joined: Oct 2003
Posts: 3,918
/hcopy would be more useful than /hrename. But to say that using variables to solve this problem is "bad", is, well, wrong.

There is no such convention in mIRC that global variables are wrong. They are pretty much the only state of being. I've never heard "use a hash table instead" for single value strings. I think you are referring to the recommendation that large data sets should be stored in hash tables rather than tokenized in strings, which is correct, but a very different problem set than this issue. There's still nothing wrong with storing the hash table name of that large data set in a variable, and in this case, it's the right way to do it, /hrename or not.

As for your point about ensuring the hash table is loaded, that is solvable too (and already something that needs solving without this feature suggestion). You can reset the hash table and the variable name if neither exist-- that only needs a very small addition of a /init.table call (which conditionally creates/loads the table) in the /find.table of my above snippet. This is not a circular problem, they are mutually exclusive checks.

Code:
alias -l find.table {
  if (%myscript.tablename) return
  var %i = $hget(0)
  while (%i > 0) {
    if (myscript.tableprefix.* iswm $hget(%i)) {
      set %myscript.tablename $hget(%i)
      return
    }
    dec %i
  }

  ; haven't returned, so table does not exist.
  ; create or load it from disk
  hmake myscript.tableprefix.0 100 
  set %myscript.tablename myscript.tableprefix.0
}

; ...


- argv[0] on EFnet #mIRC
- "Life is a pointer to an integer without a cast"

Link Copied to Clipboard