Wednesday, March 30, 2011

How to start a .dmg from the command line

> hdiutil mount ./Pacifist-2.6.4.dmg
> open /Volumes/Pacifist-2.6.4/Pacifist.app

Primary TRANS killed, backup TRANS recovers, but QRY reports lost responses at the end

E.g.:

STATISTICS FOR RATE VARIATION 01:
----------------
      Dialog Statistics:
      ----------
      Dialog initiation Rate.......... = 10 (dialogs/sec)
      Initiated dialogs............... = 300
      Successfully ended dialogs...... = 300
      Failed dialogs.................. = 0
      ...
      Message Statistics:
      ---------
      Total requests sent............. = 19382
      Total responses received........ = 19382
      Total valid responses received.. = 19382
      Total mis-sequenced responses... = 147
      Total lost responses............ = 102
      ...

Lost responses are detected by QRY when seq_num > prev_seq_num + 1. Mis-sequenced responses are detected when seq_num < prev_seq_num. So, the latter occurs because SCOS allows the backup TRANS to handle old dialogs previously initiated by the primary TRANS. And, the former may occur when backup TRANS continue its dialogs afterwards.

As a rule, do not pay too much attention to sequence numbers when SCOS recovers data because this is a rotating U8.

SCOS Object Stores

Format:
<CeName>.<AppLogicalName>.<ProtocolName>.<NodeName>.<ProtocolKey>.<SHM>

For TCAP, Protocol Key=Application ID

E.g.:

${OMNI_HOME}/tif/shm/tif.C71ICPTRCLTD01.TCAP.C71.32.698
${OMNI_HOME}/tif/shm/bu.tondu.C71ICPTRCLTD02.TCAP.C71.286.698
${OMNI_HOME}/tondu/shm/tondu.C71ICPTRCLTD02.TCAP.C71.286.698
${OMNI_HOME}/tondu/shm/bu.tif.C71ICPTRCLTD01.TCAP.C71.32.698

Check what ScosRead() does

  • In chtbl.c, add:
int
JG_DEBUG_chtbl_remove(ObjectStoreHeader_t * pObjectStoreHeader,
StateItem_t * pDataItemToRemove)
{
int bucket;
S32 elementIndexRemoved;
List_t *pList;
ListElmt_t *prev;
ListElmt_t *pElement;
ListElmt_t *pElementItemRemoved;
HashIndex_t *pHashIndex = get_hash_index_ptr(pObjectStoreHeader);
HashTableHeader_t *pHashTableHeader = get_hash_table_header_ptr(pObjectStoreHeader);

/* Hash the key */
bucket = wrapperHashFn(pObjectStoreHeader->protocol, &pDataItemToRemove->key, pHashIndex->hdr.numberOfItems) % pHashIndex->hdr.numberOfItems;
if (TRUE == DebugIndicator)
{
printf("chtbl_remove: bucket=%d\n", bucket);
}

/* point to the first list */
pList = pHashIndex->bucket;

/* move to the hashed list */
pList += bucket; /* ptr arith */

/* Search for the data in the bucket */
prev = NULL;

JG_DEBUG("chtbl_remove: pDataItemToRemove->key.ukey.tcapKey{.dialog_id=%d, .type=%d}", pDataItemToRemove->key.ukey.tcapKey.dialog_id, pDataItemToRemove->key.ukey.tcapKey.type);
for (pElement = get_ptr_from_element_index(pObjectStoreHeader, LIST_HEAD(pList)); NULL != pElement; pElement = get_next_hash_table_item(pElement))
{
JG_DEBUG("chtbl_remove: pElement->data.item.key.ukey.tcapKey.{.dialog_id=%d, .type=%d}", pElement->data.item.key.ukey.tcapKey.dialog_id, pElement->data.item.key.ukey.tcapKey.type);
if (matchFn(&(pDataItemToRemove->key), &(pElement->data.item.key)))
{
if (TRUE == DebugIndicator)
{
printf("chtbl_remove: found\n");
}

*pDataItemToRemove = pElement->data.item; /* structure copy */
if (TRUE == DebugIndicator)
{
printf("item=%d\n", pElement->thisIndex);
dump_scos_state_item(pObjectStoreHeader->protocol, pDataItemToRemove);
}

/* Remove the item from the bucket */
if (list_rem_next(pObjectStoreHeader, pList, prev, &elementIndexRemoved, &pElementItemRemoved) 0)
{
pHashTableHeader->itemsUsed--;
list_ins_next(pObjectStoreHeader, &pHashTableHeader->freeList, NULL, elementIndexRemoved, pElementItemRemoved);
return RETURNok;
}

else
{
if (TRUE DebugIndicator)
{
printf(“chtbl_remove: list_rem_next failure\n”);
}
return RETURNerror;
}
}
prev = pElement;
}

/ Return that the data was not found /
if (TRUE == DebugIndicator)
{
printf(“chtbl_remove: not found\n”);
}
return RETURNerror;
}


  1. In scoschtbl.h, add:
int
JG_DEBUG_chtbl_remove(ObjectStoreHeader_t * pObjectStoreHeader, StateItem_t *pDataItemToRemove);


  1. In scoslib.c / Scos Read, replace
iRet = _primary_object_store_delete_object(pObjectStoreDescriptor, pStateItem);

with

iRet = JG_DEBUG_chtbl_remove(pObjectStoreDescriptor->pObjectStoreHeader, pStateItem);
JG_DEBUG("ScosRead: _primary_object_store_delete_object returned %d", iRet);

Also add the name of the Object Store we’re reading from:

JG_DEBUG("ScosRead: pObjectStoreDescriptor->name=%s",pObjectStoreDescriptor->name);

Using ScosTerminate() + ScosDesignateBackup(NULL)

Do NOT use ScosDesignateBackup(NULL) to un-designate the backup application right after or right before ScosTerminate().
Indeed, first function will cause a SCOS_UNDESIGNATE_BACKUP to be sent to primaryworker, and second function will cause a TERMINATE to be enqueued in the ringbuffer. First message will be read by the main thread of the primaryworker.
TERMINATE will be read by the consumer thread of the primaryworker. As both threads then call send_destroy_bkup_obj_store_and_die_msg() and FtTerminate(), there will be a race condition that may lead to no SCOS_TERMINATE_RESP being sent back by the primaryworker.

How is the TCAP router aware that the primary app has died?

  • TCMG notifies the TCAP router on reception of a TAP_UNBIND. Then, the routing tables of the router are reworked.
  • If the app is started manually + Ft Attach, POP needs 10 seconds by default to notice that the application is dead. This is immediate if the app is started by POP. Then POP sends a SIGCPT to TAP, which sends a TAP_UNBIND to TCMG.
  • The 10 seconds delay can be changed via the -HCtimer option of POP.

How is the primary worker aware of the backup worker death?

If the SCOS backup worker on CE 2 dies, then the matching SCOS primary worker on CE 1 will see it by detecting a hang up of its SCTP communications with the dead backup worker. The CE 1 SCOS primary worker will then re-connect to the SCOS process manager on CE 2 (sctp_connect), which in turn will start a new CE 2 SCOS backup worker that will be able to exchange data again with the CE 1 SCOS primary worker.

Run simplest qry/trans scenario

configureNodes -z -nk C7 C7
DFconvert rc.C7.698

where rc.C7.698 is:

CREATE-OSPC:PC=2020,NI=NAT0;
CREATE-GT:TT=0,NP=ISDN-TEL,NA=NSN,DIG="34",PC=2020,SSN=7,RI=GT;
CREATE-GT:TT=1,NP=ISDN-MOB,NA=NSN,DIG="8765",PC=2020,SSN=7,RI=GT;
CREATE-GT:TT=100,NP=MARI-MOB,NA=SUB,DIG="1234",PC=2020,SSN=7,RI=GT;
CREATE-GT:TT=254,NP=TELEX,NA=NSN,DIG="34456",PC=2020,SSN=7,RI=GT;
CREATE-GT:TT=10,NP=DATA,NA=INT,DIG="12345678",PC=2020,SSN=7,RI=GT;
CREATE-GT:TT=10,NP=PRIV-NET,NA=INT,DIG="12345678",PC=2020,SSN=7,RI=GT;
CREATE-GT:TT=0,NP=ISDN-TEL,NA=NSN,DIG="123456abcdef1234567890",PC=2020,SSN=7,RI=GT;
$OMNI_HOME/bin/test/c7icptrans -node C7 -no800 -lssn 7 -opc 2020 -rec 2 -oosna SCOS -tdbgmk 1 -data -name C7ICPTRCLTD01 -stdaln
$OMNI_HOME/bin/test/c7icpqry -stdaln -node C7 -data -opc 2020 -dpc 2020 -rssn 7

How do I copy a directory structure from one machine to another?

 $ tar cf - some_directory | ssh kramer "( cd /path/to/destination; tar xf - )"

tar cf – some_directory creates a tar file of some_directory but the dash tells tar to write to STDOUT instead of writing to an actual file on disk. The STDOUT from the first tar command is piped to STDIN of the next command. The right hand side of the pipe says to log into the host kramer using ssh and run the commands cd and tar xf -. The trick is with the commands “( cd /path/to/destination; tar xf – )”. The parens create a subshell, in which the current directory is changed to /path/to/destination, and tar xf – reads from STDIN and extracts the tar file. This STDIN is the same STDIN that was sent to us over the pipe from STDOUT of the first tar command. Thus the directory structure on jerry gets tar’d up, transfered to kramer, then extracted all in one fell swoop.

Bash sample init file

# This file controls the behaviour of line input editing for
# programs that use the GNU Readline library.  Existing
# programs include FTP, Bash, and GDB.
#
# You can re-read the inputrc file with C-x C-r.
# Lines beginning with '#' are comments.
#
# First, include any systemwide bindings and variable
# assignments from /etc/Inputrc
$include /etc/Inputrc

#
# Set various bindings for emacs mode.

set editing-mode emacs

$if mode=emacs

Meta-Control-h:    backward-kill-word    Text after the function name is ignored

#
# Arrow keys in keypad mode
#
#"\M-OD":        backward-char
#"\M-OC":        forward-char
#"\M-OA":        previous-history
#"\M-OB":        next-history
#
# Arrow keys in ANSI mode
#
"\M-[D":        backward-char
"\M-[C":        forward-char
"\M-[A":        previous-history
"\M-[B":        next-history
#
# Arrow keys in 8 bit keypad mode
#
#"\M-\C-OD":       backward-char
#"\M-\C-OC":       forward-char
#"\M-\C-OA":       previous-history
#"\M-\C-OB":       next-history
#
# Arrow keys in 8 bit ANSI mode
#
#"\M-\C-[D":       backward-char
#"\M-\C-[C":       forward-char
#"\M-\C-[A":       previous-history
#"\M-\C-[B":       next-history

C-q: quoted-insert

$endif

# An old-style binding.  This happens to be the default.
TAB: complete

# Macros that are convenient for shell interaction
$if Bash
# edit the path
"\C-xp": "PATH=${PATH}\e\C-e\C-a\ef\C-f" 
# prepare to type a quoted word --
# insert open and close double quotes
# and move to just after the open quote
"\C-x\"": "\"\"\C-b" 
# insert a backslash (testing backslash escapes
# in sequences and macros)
"\C-x\\": "\\" 
# Quote the current or previous word
"\C-xq": "\eb\"\ef\"" 
# Add a binding to refresh the line, which is unbound
"\C-xr": redraw-current-line
# Edit variable on current line.
"\M-\C-v": "\C-a\C-k$\C-y\M-\C-e\C-a\C-y=" 
$endif

# use a visible bell if one is available
set bell-style visible

# don't strip characters to 7 bits when reading
set input-meta on

# allow iso-latin1 characters to be inserted rather
# than converted to prefix-meta sequences
set convert-meta off

# display characters with the eighth bit set directly
# rather than as meta-prefixed characters
set output-meta on

# if there are more than 150 possible completions for
# a word, ask the user if he wants to see all of them
set completion-query-items 150

# For FTP
$if Ftp
"\C-xg": "get \M-?" 
"\C-xt": "put \M-?" 
"\M-.": yank-last-arg
$endif

How do I change every occurance of a string in multiple files?

Why, use perl pie!

perl -p -i -e 's/jerry/george/g' *.txt

How can I run long pipe lines of commands on a remote host via SSH without escaping all the meta characters?

$ ssh kramer <<EOF
ps -ef | grep http | awk '{print \$NF}'
EOF

The only tricks here are the use of a bash here document, and the fact that the command line is typed directly into ssh’s STDIN so there’s no need to escape things like pipes and semi-colons, etc. However, notice that you do still need to escape dollar signs because they’ll still be interpreted as shell variables.

How can I run a shell script on a remote host without copying the script out?

One way would be:

$ cat myscript.sh | ssh kramer /bin/sh

This one is pretty simple how it works, but it is often overlooked as an option for getting things done. The shell script is written to STDOUT. /bin/sh is executed on the remote server, and it reads myscript.sh on STDIN, thus executing the local copy of the script. This is way convenient for some things. The only problem I see with this one is that you can’t pass command line arguments to the script.

How do I diff two files on different machines (using bash)?

$ diff <(ssh -n george cat /etc/passwd) <(ssh -n kramer cat /etc/passwd)

This is just the Bash Process Substitution trick.

Tuesday, March 29, 2011

From within a bash executing script, how do I find the directory where the script lives?

A simple pwd doesn’t work because it gives the Present Working Directory, and we want to know the directory where the script actually resides on disk. I can’t remember the previous solution I came up with, but here’s another solution that should work:


#!/bin/bash
dir=$(echo $0 | sed -e "s,\([/]\),$(pwd)/\1,")
echo I live in $dir

Here is how it works (hopefully). $0 is the name of the script as it was executed, so this may be foo.sh, ./foo.sh, /tmp/foo.sh, etc.. This gets sent to sed, which then uses a basic regular expression that says “If the first character of $0 was NOT a forward slash, then prepend $0 with my present working directory ($(pwd)) followed by whatever that first character was (\1), then assign this new value to dir”. If the first character in $0 is a forward slash, then we were invoked via an absolute path and so we don’t want to change anything.

Modified files during last 10 days

find . -name '*' -mtime -10 -print

Print file date

perl -MTime::Local -e 'print scalar localtime((stat "core")[9]), "\n"'
 

Install new osx86 kernel

sudo -s
cp ~/Desktop/new_kernel /
chown 0:0 /new_kernel
chmod 755 /new_kernel
then @boot:
<TAB>
/new_kernel <RET>

If OK, replace /mach_kernel with /new_kernel