0.00%
Search · Index

Weblog Page

Filtered by date 2008-02-17, 91 - 100 of 111 Postings (all, summary)

Distributing upgrades of your package

Created by Gustaf Neumann, last modified by Gustaf Neumann 17 Feb 2008, at 07:08 AM

by Jade Rubick

OpenACS docs are written by the named authors, and may be edited by OpenACS documentation staff.

The OpenACS Package Repository builds a list of packages that can be installed on OpenACS installations, and can be used by administrators to update their packages. If you are a package developer, there are a couple of steps you need to take in order to release a new version of your package.

For the sake of this example, let's assume you are the package owner of the notes package. It is currently at version 1.5, and you are planning on releasing version 1.6. It is also located in OpenACS's CVS.

To release your package:

cd /path/to/notes
cvs commit -m "Update package to version 1.6."
cvs tag notes-1-6-final
cvs tag -F openacs-5-1-compat

Of course, make sure you write upgrade scripts (the section called “Writing upgrade scripts”)

Programming with AOLserver

Created by Gustaf Neumann, last modified by Gustaf Neumann 17 Feb 2008, at 07:08 AM

By Michael Yoon, Jon Salz and Lars Pind.

OpenACS docs are written by the named authors, and may be edited by OpenACS documentation staff.

When using AOLserver, remember that there are effectively two types of global namespace, not one:

  1. Server-global: As you'd expect, there is only one server-global namespace per server, and variables set within it can be accessed by any Tcl code running subsequently, in any of the server's threads. To set/get server-global variables, use AOLserver 3's nsv API (which supersedes ns_share from the pre-3.0 API).

  2. Script-global: Each Tcl script (ADP, Tcl page, registered proc, filter, etc.) executing within an AOLserver thread has its own global namespace. Any variable set in the top level of a script is, by definition, script-global, meaning that it is accessible only by subsequent code in the same script and only for the duration of the current script execution.

The Tcl built-in command global accesses script-global, not server-global, variables from within a procedure. This distinction is important to understand in order to use global correctly when programming AOLserver.

Also, AOLserver purges all script-global variables in a thread (i.e., Tcl interpreter) between HTTP requests. If it didn't, that would affect (and complicate) our use of script-global variables dramatically, which would then be better described as thread-global variables. Given AOLserver's behaviour, however, "script-global" is a more appropriate term.

ns_schedule_proc and ad_schedule_proc each take a -thread flag to cause a scheduled procedure to run asychronously, in its own thread. It almost always seems like a good idea to specify this switch, but there's a problem.

It turns out that whenever a task scheduled with ns_schedule_proc -thread or ad_schedule_proc -thread t is run, AOLserver creates a brand new thread and a brand new interpreter, and reinitializes the procedure table (essentially, loads all procedures that were created during server initialization into the new interpreter). This happens every time the task is executed - and it is a very expensive process that should not be taken lightly!

The moral: if you have a lightweight scheduled procedure which runs frequently, don't use the -thread switch.

Note also that thread is initialized with a copy of what was installed during server startup, so if the procedure table have changed since startup (e.g. using the APM watch facility), that will not be reflected in the scheduled thread.

The return command in Tcl returns control to the caller procedure. This definition allows nested procedures to work properly. However, this definition also means that nested procedures cannot use return to end an entire thread. This situation is most common in exception conditions that can be triggered from inside a procedure e.g., a permission denied exception. At this point, the procedure that detects invalid permission wants to write an error message to the user, and completely abort execution of the caller thread. return doesn't work, because the procedure may be nested several levels deep. We therefore use ad_script_abort to abort the remainder of the thread. Note that using return instead of ad_script_abort may raise some security issues: an attacker could call a page that performed some DML statement, pass in some arguments, and get a permission denied error -- but the DML statement would still be executed because the thread was not stopped. Note that return -code return can be used in circumstances where the procedure will only be called from two levels deep.

Many functions have a single return value. For instance, empty_string_p returns a number: 1 or 0. Other functions need to return a composite value. For instance, consider a function that looks up a user's name and email address, given an ID. One way to implement this is to return a three-element list and document that the first element contains the name, and the second contains the email address. The problem with this technique is that, because Tcl does not support constants, calling procedures that returns lists in this way necessitates the use of magic numbers, e.g.:

set user_info [ad_get_user_info $user_id]
set first_name [lindex $user_info 0]
set email [lindex $user_info 1]

AOLserver/Tcl generally has three mechanisms that we like, for returning more than one value from a function. When to use which depends on the circumstances.

Using Arrays and Pass-By-Value

The one we generally prefer is returning an array get-formatted list. It has all the nice properties of pass-by-value, and it uses Tcl arrays, which have good native support.

ad_proc ad_get_user_info { user_id } {
    db_1row user_info { select first_names, last_name, email from users where user_id = :user_id }
    return [list  name "$first_names $last_name"  email $email  namelink "<a href=\"/shared/community-member?user_id=[ns_urlencode $user_id]\">$first_names $last_name</a>"  emaillink "<a href=\"mailto:$email\">$email</a>"]
}

array set user_info [ad_get_user_info $user_id]

doc_body_append "$user_info(namelink) ($user_info(emaillink))"

You could also have done this by using an array internally and using array get:

ad_proc ad_get_user_info { user_id } {
    db_1row user_info { select first_names, last_name, email from users where user_id = :user_id }
    set user_info(name) "$first_names $last_name"
    set user_info(email) $email
    set user_info(namelink) "<a href=\"/shared/community-member?user_id=[ns_urlencode $user_id]\">$first_names $last_name</a>"
    set user_info(emaillink) "<a href=\"mailto:$email\">$email</a>"
    return [array get user_info]
}

Using Arrays and Pass-By-Reference

Sometimes pass-by-value incurs too much overhead, and you'd rather pass-by-reference. Specifically, if you're writing a proc that uses arrays internally to build up some value, there are many entries in the array, and you're planning on iterating over the proc many times. In this case, pass-by-value is expensive, and you'd use pass-by-reference.

The transformation of the array into a list and back to an array takes, in our test environment, approximately 10 microseconds per entry of 100 character's length. Thus you can process about 100 entries per milisecond. The time depends almost completely on the number of entries, and almost not at all on the size of the entries.

You implement pass-by-reference in Tcl by taking the name of an array as an argument and upvar it.

ad_proc ad_get_user_info {
    -array:required
    user_id
} {
    upvar $array user_info
    db_1row user_info { select first_names, last_name, email from users where user_id = :user_id }
    set user_info(name) "$first_names $last_name"
    set user_info(email) $email
    set user_info(namelink) "<a href=\"/shared/community-member?user_id=[ns_urlencode $user_id]\">$first_names $last_name</a>"
    set user_info(emaillink) "<a href=\"mailto:$email\">$email</a>"
}

ad_get_user_info -array user_info $user_id

doc_body_append "$user_info(namelink) ($user_info(emaillink))"

We prefer pass-by-value over pass-by-reference. Pass-by-reference makes the code harder to read and debug, because changing a value in one place has side effects in other places. Especially if have a chain of upvars through several layers of the call stack, you'll have a hard time debugging.

Multisets: Using ns_sets and Pass-By-Reference

An array is a type of set, which means you can't have multiple entries with the same key. Data structures that can have multiple entries for the same key are known as a multiset or bag.

If your data can have multiple entries with the same key, you should use the AOLserver built-in ns_set. You can also do a case-insensitive lookup on an ns_set, something you can't easily do on an array. This is especially useful for things like HTTP headers, which happen to have these exact properties.

You always use pass-by-reference with ns_sets, since they don't have any built-in way of generating and reconstructing themselves from a string representation. Instead, you pass the handle to the set.

ad_proc ad_get_user_info {
    -set:required
    user_id
} {
    db_1row user_info { select first_names, last_name, email from users where user_id = :user_id }
    ns_set put $set name "$first_names $last_name"
    ns_set put $set email $email
    ns_set put $set namelink "<a href=\"/shared/community-member?user_id=[ns_urlencode $user_id]\">$first_names $last_name</a>"
    ns_set put $set emaillink "<a href=\"mailto:$email\">$email</a>"
}

set user_info [ns_set create]
ad_get_user_info -set $user_info $user_id

doc_body_append "[ns_set get $user_info namelink] ([ns_set get $user_info emaillink])"

We don't recommend ns_set as a general mechanism for passing sets (as opposed to multisets) of data. Not only do they inherently use pass-by-reference, which we dis-like, they're also somewhat clumsy to use, since Tcl doesn't have built-in syntactic support for them.

Consider for example a loop over the entries in a ns_set as compared to an array:

# ns_set variant
set size [ns_set size $myset]
for { set i 0 } { $i < $size } { incr i } {
    puts "[ns_set key $myset $i] = [ns_set value $myset $i]"
}

# array variant
foreach name [array names myarray] {
    puts "$myarray($name) = $myarray($name)"
}

And this example of constructing a value:

# ns_set variant
set myset [ns_set create]
ns_set put $myset foo $foo
ns_set put $myset baz $baz
return $myset

# array variant
return [list
    foo $foo
    baz $baz
]

ns_sets are designed to be lightweight, so memory consumption should not be a problem. However, when using ns_set get to perform lookup by name, they perform a linear lookup, whereas arrays use a hash table, so ns_sets are slower than arrays when the number of entries is large.

Using CVS for backup-recovery

Created by Gustaf Neumann, last modified by Gustaf Neumann 17 Feb 2008, at 07:08 AM

CVS-only backup is often appropriate for development sites. If you are already using CVS and your data is not important, you probably don't need to do anything to back up your files. Just make sure that your current work is checked into the system. You can then roll back based on date - note the current system time, down to the minute. For maximum safety, you can apply a tag to your current files. You will still need to back up your database.

Note that, if you did the CVS options in this document, the /var/lib/aolserver/$OPENACS_SERVICE_NAME/etc directory is not included in cvs and you may want to add it.

[root root]# su - $OPENACS_SERVICE_NAME
[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$ cd /var/lib/aolserver/$OPENACS_SERVICE_NAME

[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$ cvs commit -m "last-minute commits before upgrade to 4.6"
cvs commit: Examining .
cvs commit: Examining bin
(many lines omitted)
[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$ cvs tag before_upgrade_to_4_6
cvs server: Tagging bin
T bin/acs-4-0-publish.sh
T bin/ad-context-server.pl
(many lines omitted)
[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$ exit
[root root]#
su - $OPENACS_SERVICE_NAME
cd /var/lib/aolserver/$OPENACS_SERVICE_NAME
cvs commit -m "last-minute commits before upgrade to 4.6"
cvs tag before_upgrade_to_4_6
exit

To restore files from a cvs tag such as the one used above:

[root root]# su - $OPENACS_SERVICE_NAME
[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$ cd /var/lib/aolserver/$OPENACS_SERVICE_NAME

[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$ cvs up -r current
[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$ exitsu - $OPENACS_SERVICE_NAME
cd /var/lib/aolserver/$OPENACS_SERVICE_NAME
cvs up -r current

Basic Caching

Created by Gustaf Neumann, last modified by Gustaf Neumann 17 Feb 2008, at 07:08 AM

Based on a post by Dave Bauer.

OpenACS docs are written by the named authors, and may be edited by OpenACS documentation staff.
  1. Implement your proc as my_proc_not_cached

  2. Create a version of your proc called my_proc which wraps the non-cached version in the caching mechanism. In this example, my_proc_not_cached takes one argument, -foo, so the wrapper passes that on. The wrapper also uses the list command, to ensure that the arguments get passed correctly and to prevent commands passed in as arguments from being executed.

    ad_proc my_proc {-foo} {
            Get a cached version of my_proc.
    } {
        return [util_memoize [list my_proc_not_cached -foo $foo]]
    }
  3. In your code, always call my_proc. There will be a seperate cache item for each unique call to my_proc_not_cached so that calls with different arguments are cached seperately. You can flush the cache for each cache key by calling util_memoize_flush my_proc_not_cached args.

  4. The cached material will of course become obsolete over time. There are two ways to handle this.

    • Timed Expiration: pass in max_age to util_memoize. If the content is older than max_age, it will be re-generated.

    • Direct Flushing. In any proc which invalidates the cached content, call util_memoize_flush my_proc_not_cached args.

  5. If you are correctly flushing the cached value, then it will need to be reloaded. You may wish to pre-load it, so that the loading delay does not impact users. If you have a sequence of pages, you could call the cached proc in advance, to increase the chances that it's loaded and current when the user reaches it. Or, you can call (and discard) it immediately after flushing it.

Where did this document come from?

Created by Gustaf Neumann, last modified by Gustaf Neumann 17 Feb 2008, at 07:08 AM

This document was created by Vinod Kurup, but it's really just plagiarism from a number of documents that came before it. If I've used something that you've written without proper credit, let me know and I'll fix it right away.

Versions 4.6.2 to present were edited by Joel Aufrecht.

These are a few of my sources:

Please also see the Credits section for more acknowledgements.

System/Application Requirements Template

Created by Gustaf Neumann, last modified by Gustaf Neumann 17 Feb 2008, at 07:08 AM

By You

OpenACS docs are written by the named authors, and may be edited by OpenACS documentation staff.

Briefly explain to the reader what this document is for, whether it records the requirements for a new system, a client application, a toolkit subsystem, etc. Remember your audience: fellow programmers, AND interested non-technical parties such as potential clients, who may all want to see how rigorous our engineering process is. Here and everywhere, write clearly and precisely; for requirements documentation, write at a level that any intelligent layperson can understand.

Very broadly, describe how the system meets a need of a business, group, the OpenACS as a whole, etc. Make sure that technical and non-technical readers alike would understand what the system would do and why it's useful. Whenever applicable, you should explicitly state what the business value of the system is.

Discuss the high-level breakdown of the components that make up the system. You can go by functional areas, by the main transactions the system allows, etc.

You should also state the context and dependencies of the system here, e.g. if it's an application-level package for OpenACS 4, briefly describe how it uses kernel services, like permissions or subsites.

Determine the types or classes of users who would use the system, and what their experience would be like at a high-level. Sketch what their experience would be like and what actions they would take, and how the system would support them.

Describe other systems or services that are comparable to what you're building. If applicable, say why your implementation will be superior, where it will match the competition, and where/why it will lack existing best-of-breed capabilities. This section is also in the Design doc, so write about it where you deem most appropriate.

Include all pertinent links to supporting and related material, such as:

  • System/Package "coversheet" - where all documentation for this software is linked off of

  • Design document

  • Developer's guide

  • User's guide

  • Other-cool-system-related-to-this-one document

  • Test plan

  • Competitive system(s)

The main course of the document, requirements. Break up the requirements sections (A, B, C, etc.) as needed. Within each section, create a list denominated with unique identifiers that reflect any functional hierarchy present, e.g. 20.5.13. - for the first number, leave generous gaps on the first writing of requirements (e.g. 1, 10, 20, 30, 40, etc.) because you'll want to leave room for any missing key requirements that may arise.

  • 10.0 A Common Solution

    Programmers and designers should only have to learn a single system that serves as a UI substrate for all the functionally specific modules in the toolkit.

    10.0.1

    The system should not make any assumptions about how pages should look or function.

    10.0.5

    Publishers should be able to change the default presentation of any module using a single methodology with minimal exposure to code.

For guidelines writing requirements, take a look at the quality standards, along with a good example, such as Package Manager Requirements.

Besides writing requirements in natural language, consider using the following techniques as needed:

  • Pseudocode - a quasi programming language, combining the informality of natural language with the strict syntax and control structures of a programming language.

  • Finite State Machines - a hypothetical machine that can be in only one of a given number of states at any specific time. Useful to model situations that are rigidly deterministic, that is, any set of inputs mathematically determines the system outputs.

  • Decision Trees and Decision Tables - similar to FSMs, but better suited to handle combinations of inputs.

  • Flowcharts - easy to draw and understand, suited for event and decision driven systems. UML is the industry standard here.

  • Entity-Relationship diagrams - a necessary part of Design documents, sometimes a high-level ER diagram is useful for requirements as well.

Although in theory coding comes after design, which comes after requirements, we do not, and perhaps should not, always follow such a rigid process (a.k.a. the waterfall lifecyle). Often, there is a pre-existing system or prototype first, and thus you may want to write some thoughts on implementation, for aiding and guiding yourself or other programmers.

Document Revision # Action Taken, Notes When? By Whom?
0.3 Edited further, incorporated feedback from Michael Yoon 9/05/2000 Kai Wu
0.2 Edited 8/22/2000 Kai Wu
0.1 Created 8/21/2000 Josh Finkler, Audrey McLoghlin

Staged Deployment for Production Networks

Created by Gustaf Neumann, last modified by Gustaf Neumann 17 Feb 2008, at 07:08 AM

By Joel Aufrecht

OpenACS docs are written by the named authors, and may be edited by OpenACS documentation staff.

This section describes two minimal-risk methods for deploying changes on a production network. The important characteristics of a safe change deployment include: (THIS SECTION IN DEVELOPMENT)

  • Control: You know for sure that the change you are making is the change that you intend to make and is the change that you tested.

  • Rollback: If anything goes wrong, you can return to the previous working configuration safely and quickly.

With this method, we control the files on a site via CVS. This example uses one developmental server (service0-dev) and one production server (service0). Depending on your needs, you can also have a staging server for extensive testing before you go live. The only way files should move between the server instances is via cvs.

To set up a developmental installation, first set up either your developmental installation or your production installation, and follow the instructions for committing your files to CVS. We'll assume in this example that you set up the production server (service0). To set up the developmental instance, you then follow the intall guide again, this time creating a new user (service0-dev) that you'll use for the new installation. To get the files for service0-dev, you check them out from cvs (check out service0).

su - service0-dev
co -d /cvsroot service0
mv service0 /var/lib/aolserver/service0-dev
ln -s /home/service0-dev/web /var/lib/aolserver/service0-dev
emacs web/etc/config.tcl
emacs web/etc/daemontools/run

In the config.tcl file, you'll probably want to pay attention the rollout support section. That will ensure that email on your developmental server will not be sent out to the general world.

Also, instead of going through the OpenACS online installer, you'll actually load live data into your production server.

You can even automate the process of getting live data from your production server. Copy something like this to /home/service0-dev/bin and put it in service0-dev's crontab to run once a night. You'll need to make sure the database backups are set up in service0's crontab, and that if the servers are on different physical machines, that the database backup is copied to the developmental machine once per night.

/usr/local/bin/svc -d /service/service0-dev
/bin/sleep 60
# this deletes the dev database!
/usr/local/pgsql/bin/dropdb service0-dev
/usr/local/pgsql/bin/createdb -E UNICODE service0-dev
# this is not necessary from Postgres 7.4 on
/usr/local/pgsql/bin/psql -f /var/lib/aolserver/service0-dev/packages/acs-kernel/sql/postgresql/postgresql.sql service0
mv /var/lib/aolserver/service0/database-backup/service0-nightly-backup.dmp.gz /var/lib/aolserver/service0-dev/database-backup/service0-nightly-backup-old.dmp.gz
/bin/gunzip /var/lib/aolserver/service0-dev/database-backup/service0-nightly-backup.dmp.gz
/usr/bin/perl -pi -e "s/^\\connect service0$/\\connect service0-dev/" /var/lib/aolserver/service0-dev/database-backup/service0-nightly-backup.dmp
/usr/local/pgsql/bin/psql service0-dev < /var/lib/aolserver/service0-dev/database-backup/service0-nightly-backup.dmp
/usr/local/bin/svc -u /service/service0-dev
/bin/gzip /var/lib/aolserver/service0-dev/database-backup/service0-nightly-backup-old.dmp

Your developmental server will always have data about a day old.

To make changes on service0-dev:

1) change the file on service0-dev as desired
2) test the new file
3) commit the file:
if the file is /var/lib/aolserver/service0-dev/www/index.adp, do:

cd /var/lib/aolserver/service0-dev/www
cvs diff index.adp (this is optional; it's just a
reality check)
the lines starting > will be added and the lines
starting < will be removed, when you commit
if that looks okay, commit with:
cvs -m "changing text on front page for February conference" index.adp
the stuff in -m "service0" is a comment visible only from within cvs commands

To make these changes take place on service0:

4) update the file on production:
cd /var/lib/aolserver/service0/www
cvs up -Pd index.adp

If you make changes that require changes to the database, test them out first on service0-dev, using either -create.sql or upgrade scripts. Once you've tested them, you then update and run the upgrade scripts from the package manager.

The production site can run "HEAD" from cvs.

The drawback to using HEAD as the live code is that you cannot commit new work on the development server without erasing the definition of 'working production code.' So a better method is to use a tag. This guarantees that, at any time in the future, you can retrieve exactly the same set of code. This is useful for both of the characteristics of safe change deployment. For control, you can use tags to define a body of code, test that code, and then know that what you are deploying is exactly that code. For rollback, you can use return to the last working tag if the new tag (or new, untagged changes) cause problems. .... example of using tags to follow ...

The approach taken in this section is to always create a new service with the desired changes, running in parallel with the existing site. This guarantees control, at least at the final step of the process: you know what changes you are about to make because you can see them directly. It does not, by itself, guarantee the entire control chain. You need additional measures to make sure that the change you are making is exactly and completely the change you intended to make and tested previously, and nothing more. Those additional measures typically take the form of source control tags and system version numbers. The parallel-server approach also guarantees rollback because the original working service is not touched; it is merely set aside.

This approach can has limitations. If the database or file system regularly receiving new data, you must interrupt this function or risk losing data in the shuffle. It also requires extra steps if the database will be affected.

Figure6.2.Simple A/B Deployment - Step 1

Simple A/B Deployment - Step 1

Figure6.3.Simple A/B Deployment - Step 2

Simple A/B Deployment - Step 2

Figure6.4.Simple A/B Deployment - Step 3

Simple A/B Deployment - Step 3

Figure6.5.Complex A/B Deployment - Step 1

Complex A/B Deployment - Step 1

Figure6.6.Complex A/B Deployment - Step 2

Complex A/B Deployment - Step 2

Figure6.7.Complex A/B Deployment - Step 3

Complex A/B Deployment - Step 3

Install nsopenssl

Created by Gustaf Neumann, last modified by Gustaf Neumann 17 Feb 2008, at 07:08 AM

By Joel Aufrecht and Malte Sussdorff

OpenACS docs are written by the named authors, and may be edited by OpenACS documentation staff.

This AOLserver module is required if you want people to connect to your site via https. These commands compile nsopenssl and install it, along with a tcl helper script to handle https connections. You will also need ssl certificates. Because those should be different for each server service, you won't need those instructions until later.

You will need the unpacked Aolserver tarball in /usr/local/src/aolserver and the nsopenssl tarball in /tmp.

Red Hat 9 note: see this thread for details on compiling nsopenssl.)

[root bin]# cd /usr/local/src/aolserver
[root aolserver]# wget --passive http://www.scottg.net/download/nsopenssl-2.1.tar.gz
[root aolserver]# tar xzf nsopenssl-2.1.tar.gz 
[root aolserver]# cd nsopenssl-2.1
[root nsopenssl-2.1]# make OPENSSL=/usr/local/ssl
gcc -I/usr/local/ssl/include -I../aolserver/include -D_REENTRANT=1 -DNDEBUG=1 -g -fPIC -Wall -Wno-unused -mcpu=i686 -DHAVE_CMMSG=1 -DUSE_FIONREAD=1 -DHAVE_COND_EINTR=1   -c -o nsopenssl.o nsopenssl.c
(many lines omitted)
gcc -shared -nostartfiles -o nsopenssl.so nsopenssl.o config.o init.o ssl.o thread.o tclcmds.o -L/usr/local/ssl/lib -lssl -lcrypto
[root nsopenssl-2.1]# cp nsopenssl.so /usr/local/aolserver/bin
[root nsopenssl-2.1]# cp https.tcl /usr/local/aolserver/modules/tcl/
[root nsopenssl-2.1]#
cd /usr/local/src/aolserver
wget --passive http://www.scottg.net/download/nsopenssl-2.1.tar.gz
tar xzf nsopenssl-2.1.tar.gz
cd nsopenssl-2.1
make OPENSSL=/usr/local/ssl
cp nsopenssl.so /usr/local/aolserver/bin
cp https.tcl /usr/local/aolserver/modules/tcl/

For Debian (more information):

apt-get install libssl-dev
cd /usr/local/src/aolserver
tar xzf /tmp/nsopenssl-2.1.tar.gz
cd nsopenssl-2.1
make OPENSSL=/usr/lib/ssl
cp nsopenssl.so /usr/local/aolserver/bin
cp https.tcl /usr/local/aolserver/modules/tcl/

You will need the AOLserver4 source in /usr/local/src/aolserver/aolserver and OpenSSL installed in /usr/local/ssl (or at least symlinked there). The use of INST=/point/to/aolserver is being replaced with AOLSERVER=/point/to/aolserver. We are including both here, because while this module still requires INST, if one just uses AOLSERVER, the default value would be used and could intefere with another existing installation.

FreeBSD note: build nsopenssl with gmake install OPENSSL=/usr/local/openssl AOLSERVER=/usr/local/aolserver4r10

[root bin]# cd /usr/local/src/aolserver
[root aolserver]# cvs -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/aolserver login
[root aolserver]# cvs -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/aolserver co nsopenssl
[root aolserver]# cd nsopenssl
[root nsopenssl]# make OPENSSL=/usr/local/ssl
gcc -I/usr/local/ssl/include (many items omitted)  -c -o sslcontext.o sslcontext.c
(many lines omitted)
[root nsopenssl-2.1]# make install OPENSSL=/usr/local/ssl AOLSERVER=/usr/local/aolserver4r10 INST=/usr/local/aolserver4r10
[root nsopenssl-2.1]#
cd /usr/local/src/aolserver
cvs -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/aolserver login
cvs -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/aolserver co nsopenssl
cd nsopenssl
make OPENSSL=/usr/local/ssl
make install OPENSSL=/usr/local/ssl AOLSERVER=/usr/local/aolserver AOLSERVER=/usr/local/aolserver4r10

If you have problems starting your server with nsopenssl.so due to missing libssl.so.0.9.7 (or lower), you have to create symlinks

[root nsopenssl]# cd /usr/local/aolserver/lib
[root lib]# ln -s /usr/local/ssl/lib/libssl.so.0.9.7 libssl.so.0.9.7
[root lib]# ln -s /usr/local/ssl/lib/libcrypto.so.0.9.7 libcrypto.so.0.9.7
[root lib]#
cd /usr/local/aolserver/lib
ln -s /usr/local/ssl/lib/libssl.so.0.9.7 libssl.so.0.9.7
ln -s /usr/local/ssl/lib/libcrypto.so.0.9.7 libcrypto.so.0.9.7

SSL support must be enabled seperately in each OpenACS server (Generate ssl certificates.

If your ports for SSL are privileged (below 1024), you will have to start AOLserver with prebinds for both your HTTP and your HTTPS port (usually by adding -b your_ip:your_http_port,your_ip:your_https_port to the nsd call. If you are using daemontools, this can be changed in your etc/daemontools/run file).

To enable SSL support in your server, make sure your etc/config.tcl file has a section on "OpenSSL 3 with AOLserver4". If that section is not present, try looking at the README file in /usr/local/src/aolserver/nsopenssl.

Writing upgrade scripts

Created by Gustaf Neumann, last modified by Gustaf Neumann 17 Feb 2008, at 07:08 AM

by Jade Rubick

OpenACS docs are written by the named authors, and may be edited by OpenACS documentation staff.

If your package changes its data model, you have to write an upgrade script. This is very easy in OpenACS.

First, you want to make sure you change the original .sql file so that new installation will have the new data model.

Next, check what version your package is currently at. For example, it may be at version 1.0b1. Create a file in sql/postgres/upgrade called packagename-1.0b1-1.0b2.sql and put the SQL code that will update the data model. For example, if you add in a column, you would have an alter table add column statement in this file. Test this out very well, because data model changes are more serious and fundamental changes than the program .tcl files.

Now use the APM to create a new package version 1.0b2. Commit all your changes, tag the release (the section called “Distributing upgrades of your package”), and both new installations and upgrades will be taken care of.

Using PSGML mode in Emacs

Created by Gustaf Neumann, last modified by Gustaf Neumann 17 Feb 2008, at 07:08 AM

By David Lutterkort

OpenACS docs are written by the named authors, and may be edited by OpenACS documentation staff.

Note: nxml mode replaces and/or complements psgml mode. More information.

PSGML Mode is a mode for editing, umm, SGML and XML documents in emacs. It can parse a DTD and help you insert the right tags in the right place, knows about tags' attributes and can tell you in which contexts a tag can be used. If you give it the right DTD, that is. But even without a DTD, it can save you some typing since pressing C-c/ will close an open tag automatically.

Most newer emacsen come with PSGML mode preinstalled. You can find out whether your emacs has it with the locate-library command. In Emacs, type M-x locate-library and enter psgml. Emacs will tell you if it found it or not.

If you don't have PSGML preinstalled in your Emacs, there are two things you can do:

  1. On Linux: Get the psgml rpm from RedHat's docbook-tools and install it as usual.

  2. On other systems: Get the tarball from the PSGML Website. Unpack it and follow the install instructions.

The easiest way to teach PSGML mode about a DTD is by adding it to your own CATALOG. Here is an example of how you can set that up for the Docbook XML DTD.

  1. Get the Docbook XML DTD zip archive from docbook.org

  2. Go somewhere in your working directory and do

          mkdir -p dtd/docbook-xml
          cd dtd/docbook-xml
          unzip -a <docbook XML DTD zip archive>
    
    
  3. Create a file with the name CATALOG in the dtd directory and put the line

          CATALOG "docbook-xml/docbook.cat"
    

    in it. By maintaining your own CATALOG, it is easy to add more DTD's without changing your emacs settings. (How about that HTML 4.01 DTD you always wanted to get from W3C ? The DTD is in the zip archives and tarballs available on the site.)

That's it. Now you are ready to tell emacs all about PSGML mode and that funky CATALOG

If you installed PSGML mode in a non-standard location, e.g., somewhere in your home directory, you need to add this to the load-path by adding this line to your .emacs file:

      (add-to-list 'load-path "/some/dir/that/contains/psgml.elc")

To let PSGML mode find your CATALOG and to enable PSGML mode for all your editing, add these lines to your .emacs:

      (require 'psgml)

      (add-to-list 'auto-mode-alist '("\\.html" . sgml-mode))
      (add-to-list 'auto-mode-alist '("\\.adp" . xml-mode))
      (add-to-list 'auto-mode-alist '("\\.xml" . xml-mode))
      (add-to-list 'auto-mode-alist '("\\.xsl" . xml-mode))

      (add-to-list 'sgml-catalog-files "/path/to/your/dtd/CATALOG")

If you want font-locking and indentation, you can also add these lines into the .emacs file:

      (setq sgml-markup-faces '((start-tag . font-lock-function-name-face)
                                (end-tag . font-lock-function-name-face)
                (comment . font-lock-comment-face)
                (pi . bold)
                (sgml . bold)
                (doctype . bold)
                (entity . font-lock-type-face)
                (shortref . font-lock-function-name-face)))
      (setq sgml-set-face t)
      (setq-default sgml-indent-data t)
      ;; Some convenient key definitions:
      (define-key sgml-mode-map "\C-c\C-x\C-e" 'sgml-describe-element-type)
      (define-key sgml-mode-map "\C-c\C-x\C-i" 'sgml-general-dtd-info)
      (define-key sgml-mode-map "\C-c\C-x\C-t" 'sgml-describe-entity)

All SGML and XML documents that should conform to a DTD have to declare a doctype. For the docbook XML, all your .xml files whould start with the line

      <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "docbookx.dtd">

If your document is only part of a larger XML document, you can tell PSGML mode about it by appending the following lines to your file. In this case, do not include a DOCTYPE declaration in your file.

      <!--
       Local Variables:
       sgml-parent-document: ("top.xml" "book" "sect1")
       End:
      -->

Which says that the parent of this document can be found in the file top.xml, that the element in the parent that will enclose the current document is a book and that the current file's topmost element is a sect1.

Of course, you should read the emacs texinfo pages that come with PSGML mode from start to finish. Barring that, here are some handy commands:

Key Command
C-c C-e Insert an element. Uses completion and only lets you insert elements that are valid
C-c C-a Edit attributes of enclosing element.
C-c C-x C-i Show information about the document's DTD.
C-c C-x C-e Describe element. Shows for one element which elements can be parents, what its contents can be and lists its attributes.

Next Page