Basic Examples of how to use SH_COMMAND_ADDCOMPONENTS



Example 1:    Add a child named "Joe" to the root node.  Joe will run on "somecomputer.beos.com", which should have a SockHopServer that accepts connections on port 2958, and accepts the password "".

    // Setup a root node to use in all succeeding examples.  Pass in an invalid BMessenger, since for 
    // this example we don't care about getting any reply BMessages back from the root node...
    BLooper * root = SHCreateRootNode(BMessenger());
    root->Run();

[...]

    BMessage msg(SH_COMMAND_ADDCOMPONENTS);
    msg.AddString(SH_NAME_TO, "/");
    msg.AddFlat(SH_NAME_CHILDREN, &SHNodeSpec("Joe", "somecomputer.beos.com", 2958));
    root->PostMessage(&msg);



Example 2:    Same as the above example, except this time supply the password "topsecret" to the SockHop server.  If the SockHop server you wish to connect to has been configured to accept a password, you will need to do this in order to successfully connect to it.

    BMessage msg(SH_COMMAND_ADDCOMPONENTS);
    msg.AddString(SH_NAME_TO, "/");
    BMessage password;
    password.AddString("password", "topsecret");
    msg.AddFlat(SH_NAME_CHILDREN, &SHNodeSpec("Joe", "somecomputer.beos.com", 2958, &password));
    root->PostMessage(&msg);



Example 3:    Add a TestWorker object to node "/Joe":

    TestWorker test;    // TestWorker is a hypothetical user-defined subclass of SHWorker
    BMessage testArchive;
    test.Archive(&testArchive);

    BMessage msg(SH_COMMAND_ADDCOMPONENTS);
    msg.AddString(SH_NAME_TO, "/Joe");
    msg.AddMessage(SH_NAME_COMPONENTS, &testArchive);
    root->PostMessage(&msg);



Example 4:    Add a CustomSorter object to node "/Joe":

    CustomSorter sort;    // CustomSorter is a hypothetical user-defined subclass of SHSorter
    BMessage sortArchive;
    sort.Archive(&sortAchive);

    BMessage msg(SH_COMMAND_ADDCOMPONENTS);
    msg.AddString(SH_NAME_TO, "/Joe");
    msg.AddMessage(SH_NAME_COMPONENTS, &sortArchive);
    root->PostMessage(&msg);



Example 5:    Make sure the file "mydata.bin" is cached locally to node "/Joe".  If the file is not already on "/Joe"'s local filesystem, it will be downloaded to him.

    BMessage msg(SH_COMMAND_ADDCOMPONENTS);
    msg.AddString(SH_NAME_TO, "/Joe");
    SHFileSpec spec;
    if (spec.addFlavor(SHFlavor("mydata.bin")) == B_NO_ERROR)
    {
       msg.AddFlat(SH_NAME_FILES, &spec);
       root->PostMessage(&msg);
    }
    else printf("Error adding flavor--file missing?\n");



Example 6:    Add a symbolic link from "/Joe" to "/Bob".   The symlink will appear as a child of "Joe", that is named "Bob", but all BMessages sent to it will actually go to "/Bob".

    BMessage msg(SH_COMMAND_ADDCOMPONENTS);
    msg.AddString(SH_NAME_TO, "/Joe");
    msg.AddString(SH_NAME_SYMLINKS, "/Bob");
    root->PostMessage(&msg);


Fancy Examples of how to use SH_COMMAND_ADDCOMPONENTS



Example 7:    Add many items of various types to "/Joe" with a single BMessage.  This example gives Joe three new child nodes, three TestWorker objects, and cached three more local files onto Joe's disk.

    BMessage msg(SH_COMMAND_ADDCOMPONENTS);
    msg.AddString(SH_NAME_TO, "/Joe");

    // Give Joe three children, on three other computers...
    msg.AddFlat(SH_NAME_CHILDREN, &SHNodeSpec("JoesChild1", "anothercomputer1.beos.com"));
    msg.AddFlat(SH_NAME_CHILDREN, &SHNodeSpec("JoesChild2", "anothercomputer2.beos.com"));
    msg.AddFlat(SH_NAME_CHILDREN, &SHNodeSpec("JoesChild3", "anothercomputer3.beos.com"));

    // And give him a few more TestWorkers...
    TestWorker testWorker;
    BMessage testMsg;
    testWorker.Archive(&testMsg);
 
    msg.AddMessage(SH_NAME_COMPONENTS, &testMsg);    // Joe gets
    msg.AddMessage(SH_NAME_COMPONENTS, &testMsg);    // three instances of
    msg.AddMessage(SH_NAME_COMPONENTS, &testMsg);    // the TestWorker!

    // And give Joe some additional files, as well.
    SHFileSpec spec;
    spec.AddFlavor(SHFlavor("moredata1.bin"));
    spec.AddFlavor(SHFlavor("moredata2.bin"));
    spec.AddFlavor(SHFlavor("moredata3.bin"));
    msg.AddFlat(SH_NAME_FILES, &spec);

    // Send it all off
    root->PostMessage(&msg);



Example 8:  Automagically download different files to different nodes, based on their hardware architecture.  This example will cache the file "ImportantFile.powerpc" on all PowerPC BeOS systems in the node tree, and cache the file "ImportantFile.intel" on all Intel BeOS systems in the tree.

    BMessage msg(SH_COMMAND_ADDCOMPONENTS);
    // Note that I DON'T specify SH_NAME_TO for this one.  Not specifying SH_NAME_TO creates
    // a "broadcast" message that will be received by EVERY node in the tree!

    // Specify files based on system type, via SHFileSpec::AddFlavor().
    SHFileSpec spec;
    if (spec.AddFlavor(SHFlavor("ImportantFile.powerpc", SH_ARCH_BEOS_PPC)) != B_NO_ERROR)
        printf("Warning:  ImportantFile.powerpc doesn't exist on the root node!  It won't be cached...\n");
    if (spec.AddFlavor(SHFlavor("ImportantFile.intel", SH_ARCH_BEOS_X86)) != B_NO_ERROR)
        printf("Warning:  ImportantFile.intel doesn't exist on the root node!  It won't be cached...\n");

    msg.AddFlat(SH_NAME_FILES, &spec);

    // Send it off
    root->PostMessage(&msg);



Example 9:    Make a "fully connected" network of 5 nodes, so that any node can send a BMessage to any other node in just one "hop".   (Note:  This example can crash the net_server; apparently there are apparently race conditions in the net_server that cause problems when many connections are accepted near-simultaneously)

    // First, we create a node tree with nodes "A", "B", "C", "D", "E" under the root node:
    BMessage msg(SH_COMMAND_ADDCOMPONENTS);
    msg.AddString(SH_NAME_TO, "/");
    msg.AddFlat(SH_NAME_CHILDREN, &SHNodeSpec("A"));   // For this example,
    msg.AddFlat(SH_NAME_CHILDREN, &SHNodeSpec("B"));   // all the nodes are being created as threads
    msg.AddFlat(SH_NAME_CHILDREN, &SHNodeSpec("C"));   // in the root node's process space.
    msg.AddFlat(SH_NAME_CHILDREN, &SHNodeSpec("D"));   // In real code, they might be on different computers.
    msg.AddFlat(SH_NAME_CHILDREN, &SHNodeSpec("E"));
    root->PostMessage(&msg);

    // Now, tell each of the 5 nodes to create symlinks to all the other nodes:
    BMessage createSymLinks(SH_COMMAND_ADDCOMPONENTS);
    createSymLinks.AddString(SH_NAME_TO, "/*");        // BMessage will go to all 5 child nodes
    createSymLinks.AddFlat(SH_NAME_SYMLINKS,  "/*");   // and each of them will create symlinks to all 5.

    root->PostMessage(&createSymLinks);

    // After this point, each of the 5 children has 5 "children" of its own, except that these
    // "grandchildren" are actually symlinks to the other children.  So, when a component on one
    // of the 5 nodes sends a message to one of its node's "children", the message will actually
    // go to one of the node's siblings (or back to the node itself)!