January 2005 Archives

This Week in Perl 6, Jan. 11-18, 2005

Welcome to yet another Perl Summary brought to you by music and pizza (although the pizza is late in arriving). Like many summaries before it, we start with an attempt at non sequitur and Perl 6 Language.

Perl 6 Language

Idiomatic Perl 6

Stéphane Payrard expressed a desire for more Perl 6 sample code. Luke Palmer issued the following, possibly foolish, response: "Post some 'how do I's...?' to the list, and I'll reply with code." Austin Hastings posed a couple, but there's no response yet ...

Generalized Tainting

Yuval Kogman posted an interesting musing about contagious properties (if you pull a value from someone with a contagious property, the property comes along, too). There were no responses, but it sounds interesting.

Stick/Pick

Richard H. suggested a new pair of functions, stick/pick, which would have modifiers such that push, pop, shift, unshift, and splice could all be calls to stick or pick with appropriate modifiers. Unfortunately, I think he posted it to the Google Groups interface, as it is there but not on the list. :-(

Perl 6 IDE, Again

Matisse Enzer re-raised the question of the feasibility of an IDE for Perl 6. Unfortunately, I think he re-raised it on Google Groups.

1x6 vs. 6

The dimension slice issues continue to grind with new suggestions from David Green and Craig DeForest.

Lifespan of Loop Counters

Joe Gottman wants an easy way to restrict the lifespan of his loop counter to his loop. Some folks (myself included) did not like the answer of wrapping it in a scope. Others (myself excluded) thought the answer "don't use loop, use for" was a bit of a cop-out.

Forany & Forall

Jonathan Lang wondered how to check if a condition is true for any element of an array or for all elements. The answer is to use the aptly named junction creators of any() and all().

Perl 6 Compiler

I've already reached p6c with no pizza. :-( Ah well, it was a light week.

Parrot Internals

I've already reached p6i and still no pizza :-(. Although it was close, after I wrote the =head2 my door buzzed. It was just a locked-out neighbor, but that would have been impressive timing.

Blib in 25 Seconds

Peter Christopher asked for a 25-second summary of the ./blib directory. Apparently this is harder than Hamlet in 30 seconds, which already exists.

Searching Archives

Peter Christopher wanted to know if there was a way he could search the mailing list archives. Steve Fink pointed him to groups.google.com and the ever-popular discussion topic "aardvarks."

Dynclasses with External Dependencies

Bernhard Schmalhofer wondered if there was a reasonable way to check for external dependencies for dynamic PMCs that does not involve the core Parrot configure step. Later he supplied a patch with his GDBMHash pmc, which motivated the question. Leo applied it and hinted at a mythical multi-stage configure.

s/Interpreter/INTERP/g

Bernhard Schmalhofer provided a patch, making the above cleanup all over. Leo and Sam applied different parts of it.

Black-ops Parrot

Robert Spier posted a link to the new listing for Parrot on CIA. Nicholas Clark dove for cover.

PDD Problems on the Website

Dave Brondsema noticed that PDDs 4-6 had not found their way to the website properly. Will Coleda fired off a patch.

Cleaning Old Tickets

Will Coleda, in his never-ending role as RT janitor, closed out a few obsolete tickets. Thanks, Will.

Scope and Timely Destruction

Leopold Toetsch raised the recurring issue of timely destruction. It turns out that timely destruction is hard. Various people made various suggestions. Let me state one thing clearly as if I don't, Dan doubtless will: Parrot will not use reference counting of any kind. There are a great many reasons for this some of which Luke Palmer explained.

ParrotIO* Should Have Been PMC*

Peter Christopher provided a patch fixing a pointer declaration bug. Leo applied it.

Questions for the Compiler FAQ

Some time ago, a compiler FAQ started to contain answers to questions that people posted to the list. Will Coleda posted two such questions, but there has been no response.

Languages/Perl6

Will Coleda wondered what would come of the languages/perl6 stuff as PGE now has its own SVN repository. No one answered.

Parakeet with Broken Wings

Will added an RT ticket for Parakeet, which broke in a recent shuffle.

Crashing Parrot

Will found out that he could crash Parrot by doing stuff with GCed memory. Leo admitted that he could.

Collecting Academic Garbage

Shevek asked for a good place to read about garbage collection techniques. Garrett Goebel pointed him to just such a page.

Argv[0]

Will wants to fetch the moral equivalent of argv[0].

Proposed VTABLE Changes for Method Lookup

Leo suggested a VTABLE change to facilitate MMD and method lookup. The thread had several suggestions and questions.

Food

Matt Fowles's pizza arrived. The reader then speculated that either (he writes slowly or it arrived quickly) or (he writes quickly or it arrived slowly), depending on various readers' estimates of pizza-delivery time and expected word-per-minute summarization.

Bring Hither the Fatted Parrot

Dan has returned to us. Hopefully he will be able to advance the quest for meta-objects and interoperability.

The Usual Footer

If you find these summaries useful or enjoyable, please consider contributing to the Perl Foundation to help support the development of Perl. You might also like to send feedback to ubermatt@gmail.com.

The Phalanx Project

Imagine a city protected by a small army of soldiers. The city's future growth requires a larger force; so a few determined lieutenants go to nearby towns and enlist aid from their police departments. These forces will come to the aid of the larger city when the time comes.

This is the Phalanx project, but the city is Perl, our soldiers are automated tests, and the nearby towns are the modules of CPAN.

Flashback to OSCON 2003. Larry Wall had just given his 7th annual State of the Onion where he'd announced the Ponie project. Ponie is to be Perl 5.10, but running on the new Parrot virtual machine that forms the basis of Perl 6, instead of C.

I was talking with Leon Brocard about the massive amount of testing that would be necessary to test a new implementation of Perl. Everything we know, and all our assumptions, would change. How would we know that 2+2=4 all the time? How would we know that object inheritance works? Will XS modules work the way they should? We would need a huge test suite, more than Perl has now, to make sure Ponie really is still Perl 5. The CPAN would make a great source of real-world testing.

Most CPAN modules of any popularity come with a test suite, so it would be easy to add more tests to the distributions. This would help those who worked on Ponie to make sure they had more and more tests to test against, and would help the module author by having more tests written for his code.

Which Modules?

I didn't imagine that we'd run Ponie against all of the CPAN, and wanted to follow the Pareto principle and go after the top 10%. However, with CPAN at about 4,000 modules when Phalanx started (now 6,000), it would have been too large an effort to work on 400 modules. Instead, I picked a nice round 100, or 2.5% of the distributions available.

What makes a "top 100 module"? Ideally, I'd like to know which modules had the most real-life use, but that's impossible. I decided a relative comparison of the number of downloads of modules would be a close enough approximation. (The astute reader is probably already thinking of problems with this approach, but rest assured that I've thought of them as well.)

The Phalanx Top 100 Modules are those most downloaded in 45 days from the main CPAN mirror, with some adjustments. I excluded search engine bots and anything that was apparently mirroring CPAN. I also made the executive decision that any given IP address that downloaded more then 450 modules in 45 days was a bot.

Why the Name "Phalanx"?

In ancient Greece, the phalanx was a military formation where hundreds of soldiers formed a shield wall. Each man stood shoulder to shoulder with the men next to him, their shields overlapping. As it is with the shields of the men in the phalanx, it is with the numerous and overlapping tests of the Phalanx project.

For any set of code, the more automated tests you have, the more protection you have. If you can write a test for something, you probably should. Consider these simple tests of a Project object's constructor and an accessor, tested with Perl's testing framework:

my $project = Project->new( name => "Phalanx" );
isa_ok( $project, "Project" );
is( $project->name, "Phalanx", "Name set correctly" );

Some might say, "It's only an accessor, why should we test it?" It's worth testing because when it doesn't work in production, you won't see the error at the point of the accessor. Instead, some piece of code that uses the Project::name accessor will fail, and you'll spend hours tracing the failure back to the accessor.

This sort of approach -- strength in numbers, each test building on others -- was the basis of the phalanx. So, too, will it be with Perl's tests.

Goals

The primary goal of Phalanx is to increase the quality of a given module's test suite, mostly by increasing the amount of the module's code that the tests cover. However, there are secondary goals because we're working with the code anyway.

The first sub-goal is to find hidden bugs. As we add tests to modules, we hope to uncover broken functionality. Indeed, the team working on HTML::TreeBuilder uncovered a bug in the module's code while they added tests.

In addition to adding to the testing, team members should verify the code's documentation and fill in any missing areas. Comparing code to inline documentation may uncover hidden features that only someone reading the code would know about. These should be documented and tested.

The principle here is this: Code, tests, and documentation must all agree with each other. If the code does one thing, the documentation describes it accurately, but the tests check for a different behavior, then there's a bug. It might even be the two that agree with each other that are wrong. It's possible even to find that all three might disagree with each other. Old code can be like that sometimes.

Two other sub-goals are about humans. Phalanx provides an easy way for people to wet their feet in the open source process. The very nature of Phalanx is collaborative, where each team working on a module submits patches to the module for review and approval. The module's author still maintains control, but works with the team to decide what direction testing should take.

Second, Phalanx provides a playground for people with an interest in automated testing who don't know how or where to start. Like chromatic's Perl testing kata, adding tests to existing code actually exercises each team member's skills.

Getting People to Sign Up

Once I'd created the Phalanx 100 and the guiding principles, and put up the Phalanx website, I had to find some hoplites. (Hoplites are the Greek soldiers that made up the ancient phalanxes.) I announced the project and a dozen eager hoplites volunteered. Each hoplite wrote to the author about his intent, to make sure the author was onboard with the idea. No sense in making changes and preparing patches for an author who will reject them. The author may also have input and suggestions, such as areas in the code that need more attention than others. Once the preparation was complete, the hoplite was to add tests and verify documentation.

This process turned out to be a dismal failure.

Twelve different hoplites adopted 12 distributions and produced exactly zero code in the first year. I don't mind pointing fingers, because I was one of the 12. It seems that on projects like this, working solo means motivation is hard to maintain. Each of the hoplites I talked to explained that he started with the best of intentions, but had trouble finding the time to follow through, and the motivation fell by the wayside.

This year, I tried a different approach, enlisting the support of Perl Mongers groups, starting with my home group, Chicago.pm. I then took to the conference circuit, giving lightning talks at YAPC::NA and OSCON asking for interested parties to join up with the team. Since then, SouthFlorida.pm, London.pm, and Perl Seminar New York have all joined up. We still coordinate with the module author, and also report progress centrally at our new Phalanx wiki, but now I hope that with a group, it will be easier to keep motivation high.

Phalanx Tools

Over time, as we've built up an infrastructure for Phalanx, three tools have proven themselves to be crucial to collaboration.

First were the triplets of email, web, and wiki, which allow information to be swapped on progress. The perl-qa mailing list hosted at lists.perl.org is home to many Perl folks interested in testing. The Phalanx webpage lets me post information for all hoplites to see. The Phalanx wiki allows hoplites and groups to post project progress.

Second, centralized version control is crucial since we have multiple collaborators on an individual module,. Fortunately, Robert and Ask of perl.org are graciously hosting a Subversion repository for the Phalanx teams.

Third, Paul Johnson's excellent Devel::Cover package has been invaluable in identifying shortcomings of test suites. Devel::Cover analyzes the running of the tests, and then identifies which lines of code the suite has exercised or "covered." If a line of code isn't covered by a test, it provides the hoplites a great place to start, by writing a test case to exercise the uncovered code.

Devel::Cover presents metrics on percentages of coverage, but Phalanx doesn't try necessarily to increase coverage to 100%. We've found that there's a level of diminishing returns when exercising extreme corner cases, especially cases based on platform-specific dependencies. What we've found is that the real value is finding the big areas of neglect and patching those up. Sometimes you can even find big wins, like when I found unused and un-removed code in WWW::Mechanize.

How You Can Join

If automated testing interests you, or you're looking for a way to add to the CPAN, we'd love to have you join.

  • Join the perl-qa list.

    The perl-qa list is the official mailing list of the Phalanx project. Sign up and introduce yourself.

  • Find a module that interests you.

    Find a module that could benefit from your attention. Many hoplites pick modules that they use in day-to-day life. There's also no requirement that the module you work on is from the Phalanx 100.

  • Find kindred souls.

    Phalanx seems to go better when hoplites team up to work together.

You can (and should) join our ranks and add to our numbers, as we help take Perl that much closer to Perl 6.

Other Links

This Week in Perl 6, January 03 - January 11, 2005

Welcome to another Perl 6 summary. This summary explores such thrilling issues as multi-dimensional slices of Chinese food. After all, the amount of sauce any piece of Chinese food can absorb is proportional to its surface area, which is a direct function of the number of dimensions in which you slice it (provided that we ignore degenerate cases such as fractal cuts of Peking duck).

Perl 6 Language

1x6 vs 6

Craig DeForest wondered how to disambiguate a 1x6 2D array slice from a 6 element 1D array slice. He suggested a syntax inspired by PDL. Larry admitted to not having examined this particular issue and stated that he was open to suggestions. Some suggestions arrived.

Code as Comment

Stéphane Payrard wanted to know if there is an easy way to alias arguments to a function, thus allowing a longer version for readability when calling the function and a short version inside the function. Larry suggested $s is named<subject>, which I like. The thread then devolved into punning in French.

Perl 6 Compiler

Pascal -> Pcode -> Parrot -> Profit

Sven Schubert asked about the feasibility of putting Pascal on Parrot. He noted that with the infrastructure mentioned in "Perl 6 and Parrot Essentials," the problem would not be too bad. Apparently, "Essentials" makes a few promises that we have yet to live up to, but we are working towards it. In the meantime, Stéphane Payrard suggested a way for him to kill two birds with one stone: Pcode.

Grammar Improvements

Luke Blanshard submitted some rules for Perl6::Grammar. Luke Palmer committed a slight variation of his work, and the hacking commences...

Parrot

pop_pad

Peter Christopher wondered why pop_pad had not been implemented last week. This week, Leo implemented it and asked for tests.

Resizable Arrays

Simon Glover asked why ResizablePMCArray was so different from all of its Resizable*Array bretheren. The answer is that Leo improved it. This brings up an obvious task for someone looking for a reasonably friendly chunk of Parrot to work on. Rationalizing the implementation of the various Resizable*Arrays would probably be a good task for a novice looking to dig into something. Perhaps one who is on winter break...

Parrot 0.1.1 NCI Troubles

Ian Joyce noticed that Parrot 0.1.1 had some trouble with nci.t. Leo admitted that this was the case but that the CVS version works.

Test or Benchmark

Nicholas Clark wondered if resizablestringarray.t was actually a benchmark, because it had a big number which was really hurting his poor machine. Simon Glover admitted to the copy/paste error.

x86 Solaris 2.5.1 and 2.7

Andy Bach and Nicholas Clark worked towards making Parrot happier on the aforementioned architecture. This thread seemed to peter out when Nicholas asked, "How do we run a callback unconditionally after gccversion is known, independent of its value?"

VTABLE_call_method

Leo and Sam had a disagreement about whether a call_method vtable entry makes sense. I think that we are waiting for higher intervention...

Updated perlhist.txt

Will Coleda applied Bernhard's patch updating perlhist.txt and streams.t.

Warnock Warnocked

Will Coleda applied the long Warnocked update to Warnock's contact information with only a trace of irony.

gcov of perlarray.pmc reaches 100%

Simon Glover produced full test coverage for perlarray.pmc. Nifty. Some brave soul (possibly fitting an earlier description) should try this with the Fixed*Arrays...

Parrot Under Solaris 9

Nicholas Clark, Andy Doughery, and Christian Aperghis-Tramoni all tried to convince Parrot to work on Solaris. They are brave souls.

parrot-config Updates

Peter Christopher asked questions about parrot-config.imc. He also provided an initial solution.

Key Question

Simon Glover noticed some bad behavior with respect to Key PMCs. Leo and Sam both admitted that it was bad and that they need some work.

Parrot PDL

Bernhard Schmalhofer posted a pointer to PDL. Luke Palmer pondered Piddles as Parrot PMCs. Craig DeForest proposed a path passing through PDL's PP and pausing at Parrot. (Perhaps the preponderance of Ps in Perl, Parrot, and Python should push me to alliterate with another available letter.)

Parrot Syntax Engine

Henrik Gulbrandsen introduced the powerful Parrot Syntax Engine. Leo asked a few questions to which Henrik provided answers. All in all, it looks really cool and makes me a little jealous that I did not develop the Tomita algorithm first.

s/libnci.so/libnci_test.so/g

Bernhard Schmalhofer moved libnci.so to libnci_test.so, as it really is for testing. Leo applied the patch.

Segfaulting readline

Matt Diephouse managed to segfault Parrot using readline. Leo fixed it. Matt pointed out a new bug that it introduced.

Substrings of Invalid Ranges

Matt Diephouse noticed that taking a substring of an invalid range had odd results. Simor Glover provided a bunch of tests for it. Leo applied the patch but mentioned that these corner cases need an authoritative hammering.

The Usual Footer

If you find these summaries useful or enjoyable, please consider contributing to the Perl Foundation to help support the development of Perl. You might also like to send feedback to

An Introduction to Quality Assurance

On Being Wrong

When I decided to study computer science, I installed Linux on my computer and bought a copy of "The C Programming Language" by Kernighan and Ritchie. I have been trying to solve software problems ever since. After much heartache, I decided that if I was to continue programming I would have to come to terms with being wrong, because I quickly discovered that being wrong is a big part of the development cycle: you code, compile, view the errors, and then code some more. I found it helpful to actually say "I am wrong" when the compiler complained, to remind myself where the fault lay. It made finding problems a lot easier when I accepted responsibility for the errors.

Enjoy the Ride

To deal with the frustration of constantly being wrong, I began to view programming more as a game that I enjoyed than as an epic battle, and I started looking at things from the compiler's perspective. This view has improved my overall approach to software immensely. I was also fortunate to discover Perl Debugged by Peter Scott and Ed Wright. The authors provide a wealth of information about debugging and testing Perl scripts, but they also emphasize that the right mental attitude is often the key to a programmer's success. Basically, they say that you should enjoy what you do.

Bugs come in many flavors, from syntax errors to errors of logic. Perl's interpreter will catch most typos, especially if you use warnings, but some can be tricky--and errors of logic are often even harder to tease out.

Here is a common syntax error:

if ($two_plus_two = 5) {
   print "two plus two is five"; 
} else {
   # I never seem to get here...
}

Here is common logical error:

  1. I know of software companies that let their customers find their bugs for them.
  2. These companies are worth millions of dollars.
  3. If I let my customers find my bugs for me, I will be worth millions of dollars.

This particular error can lead to embarrassing code such as the following:

sub handle_error() {

print <<END;

   Dear Friend,
      We realize this may be a difficult time 
      for you, but there has been an SQL error. 
      Please email us for further assistance, 
      or try entering your obituary again. 
      Thank you. 

END
}

Now, anyone who wants to sleep easy at night will want to avoid shameful code like this, because slowly but surely, users are becoming less tolerant of buggy code. If you haven't done so already, you will want to read through Michael G. Schwern's Test::Tutorial and get started. Test-based development, combined with quality assurance, can enable a company to offer its customers a rare and valuable commodity: reliable software. In the future, the world of software may very well be divided between the companies that incorporate testing into their development cycle and those that used to be in business.

Parts of a Test

When the compiler stops complaining, many developers are happy to declare victory and move on to the next project, but for the tester (often just the developer with his hat on backwards), things are just becoming interesting. Testers begin by breaking the program into sections, as Lydia Ash does in The Web Testing Companion. She notes the following five basic software functions:

  1. Accepting input
  2. Giving output
  3. Saving data
  4. Manipulating data
  5. Removing data

To begin testing, start at the top of the list and work down, one section at a time. At this point in the process, you really understand why everyone always tells you to write modular code. It is much easier to work through the list if you've broken your program into the functions get_input(), display_members(), add_member(), update_info(), and delete_member().

Where to Look

When asked where to look for bugs, software testers sometimes speak of the "joints" between program components, "equivalence classes," and "edge values." These are the primary points of weakness in an application.

An example of a joint is the place where your software interacts with a third-party module. It's important to make sure that all of the components send and receive what you think they should.

An equivalence class is a class of data that follows the same data path through the program. Consider a program that divides the number 50 by whatever number the user enters and either returns a positive integer or tells them why the answer is not a positive integer. You might have the following classes: negative numbers; the number zero; the numbers 1, 2, 5, 10, 25, and 50; numbers greater than 50; and non-numbers. Consider the following incomplete but well-intentioned code:

sub factor_of_50 {
    my $divisor = shift;
    my $result  = 50 / $divisor;

    return $result if $result == int( $result );
    return "$divisor is negative" if $result < 0;
    return "$result is not an integer";
}

In this case, good tests should start with -1, 0, 1, 49, and 51, the edge values for this program, to test the different paths through the code. Edge values define the limits of the program, values near and past the stated minimum and maximum that the program should handle. In the example above, you'd also want to enter a string of letters and punctuation to see how the program handles it. Then, compare the test results to the program's specification, which tells you which inputs should work and what outputs the users should see.

Specifications

Any non-trivial program needs to have a specified list of what it should do. This list of requirements lays a foundation on which to build the software and against which testers can test. There must be a specification of quality from the beginning, or else there is no way to tell if the program has passed or failed a given test. Functional specifications tell you about the program's logic, while non-functional specifications include things like the speed of the application, usability issues for a user interface, and security.

Writing Tests

Once you have a specification, you can make a test inventory--a list of all the tests you need to write in order to prove that the software meets the specifications. Of course, you need to eliminate all the bugs that crash the program and as many more as you can find, but when do you say enough is enough?

In Software Testing Fundamentals, Marnie Hutcheson describes her Most Important Tests method. This process tries to determine which tests will be most valuable to run. Essentially, it is a way to present management with the opportunity to weigh the tradeoffs between further testing and pushing the product to market sooner.

Reporting

Reporting is, of course, crucial to testing. You test, trying to get the software to fail, so that you can report the bugs you find back to the development team, so they can fix things before the software's release. A clear, informative bug report is the only one worth writing. Here is a template for a web application's bug report from The Web Testing Companion.

SERVER CONFIG
Operating System: <Operating system and hardware, if applicable.>
Software Build: <Build-number of your software.>
Topology: <If you have multiple topologies where you test your server in-house.>

CLIENT
OS: <Operating system, service packs, and other dependent DLL versions, if applicable>
Browser: <Browser and version>

DESCRIPTION
<Brief description of the problem>

Repro (short for reproduction)

  1. <Very descriptive steps showing how to recreate the problem>
  2.  
  3.  

Result:
<Description of exactly what happens after the last repro step>

Expected Results:
<Description of what should have happened after the last repro step>

Notes:
<Add any information about when this was last verified or what this might be related to here>

Final Thoughts

When all the tests have finshed, the tester turns the repro reports in to the development team and starts looking forward to the next project. If there are any bugs found, the developer is back to square one: debugging. The process has come full circle. Hopefully, after a few more iterations, everyone can go out and have a paintball war.

Software development and software testing require two different mindsets. Sometimes it is hard for one person to switch back and forth between them, but testing is essential to the success of any non-trivial software project in the same way that editing is essential for any non-trivial writing project. Without it, progress is ponderous, at best.

In conclusion, I'd like to list the nine debugging rules from David J. Agans' excellent book, Debugging. His book clarifies these essential debugging concepts and is mandatory reading for anyone who fixes things:

  1. Understand the system
  2. Make it fail
  3. Quit thinking and look
  4. Divide and conquer
  5. Change one thing at a time
  6. Keep an audit trail
  7. Check the plug
  8. Get a fresh view
  9. If you didn't fix it, it isn't fixed

Bibliography

Agans, David J. Debugging, American Management Association, 2002

Ash, Lydia. The Web Testing Companion, Wiley, 2003

Hutcheson, Marnie L. Software Testing Fundamentals, Wiley, 2003

Scott, Peter J.; Wright, Ed. Perl Debugged, Addison-Wesley Pub Co, 2001

This Fortnight in Perl 6, December 21 - 31 2004

All~

Welcome to a New Year of Perl 6 Summaries. I have been doing biweekly summaries over the holiday season, but I plan on returning to weekly ones now. Hopefully "World of Warcraft" won't prevent me, we shall see. But if anyone starts a Perl guild, drop me a line. ;-)

Perl 6 Language

Perl IDE

Matisse wondered if an IDE for Perl would be possible given its dynamic nature. The consensus arrived at last time was that an IDE that worked for "nice" code would be possible, but a fully general one would be extremely difficult and quite possibly impossible.

Premature Optimization

Jona... has a rant about low-level data types and premature optimizations. So Google tells me, but I can't find it in my Gmail account... Perhaps he posted directly to Google continuation enhanced arcs. I wish people would not do that....

Strictness of fully qualified globals

Alexey Trofimenko wanted to know if Perl 6 would have a way to catch mistakes like $OtherPackage::NmaeWithTypo when using strict. The thread seemed to wander off without answering his question, although it did note that perhaps OtherPackage::$NmaeWithTypo would make more sense.

Perl 6 Compiler

Using ASCII 0 as a terminating character

Nicholas Clark pointed out that Perl 5 allows the use of \0 as a quoting character for q{}. He felt that this was useful and should remain in Perl 6. Patrick agreed.

Parrot

P5 was the new P2

Last time, I reported that Sam and Leo wanted to pass P5 in P2 as well. Sam reported later that he was no longer confident in this idea. I guess I should de-nudge Dan....

Warning in pybuiltin.pmc

Simon Glover submitted a patch to fix it, but Warnock applies.

POD cleanup

Chromatic applied his previously threatened patch with a polite thanks to himself.

Reading past EOF in PIR

Matt Diephouse noted that the error from reading past the EOF in PIR was not really informative. Patches welcome.

Missing examples in PDD16

Simon Glover noticed a section in PDD16 that just stops mid-sentence. He suggested that it be either finished or removed. No answer...

MMD and VTABLE_find

Leo and Sam continued their discussion of how to implement MMD. The conversations stopped, but I am not sure that it progressed. Perhaps some guidance would be helpful...

PyCon discussions

A.M. Kuchling noted that PyCon will take place on March 23-25 in Washington, D.C. Many folk will be there including the authors of IronPython and Jython. The deadline for submissions was Dec. 31, 2004, but that does not mean that people cannot attend, learn a whole bunch, and take over the world.

Dynclasses broke the build

Will noted that dynclasses/*py* broke the build. Sam fixed it with alacrity.

Mod_parrot

Adrian Lambeck provided a patch to make mod_parrot work with parrot-0.1.1. Nicholas Clark applied it.

Missing make test dependencies

Will Coleda noted some problems with running make test with first running make. Sam fixed them, but could not close the RT tickets.

Split on RegExp

Will Colleda gave Patrick a friend nudge about split. Patrick noted the nudge.

--no-lines and --help for ops2*.pl

Bernhard Schmalhofer added support for the above mentioned flags to ops2c.pl and ops2pm.pl. Leo applied it.

StringArray--

Prompted by a question from Simon Glover, Leo deprecated StringArray.

Ponie on x86 Solaris

Andy Bach noticed some problems with Ponie on x86 Solaris. Leo and Nicholas Clark helped him push the failing Ponie slightly farther before failing.

Win32 dynclass issues

Jonathan Worthington bravely set out to fix dynclass pains in Win32. With the help of Leo and Nicholas Clark, he is making progress.

Undef != Undef

Simon Glover noted that this oddity caused unexpected results. This led to some scrutiny of the Fixed vs Resizable arrays. The consensus is that the core PMCs need their exact semantics specified and then implemented, as oposed to the current approach of letting the implementation be the specification.

Deleting keys from an OrderedHash

Simon Glover noticed that it hurt when he did this. Leo told him not to do that.

Native structures for Parrot

Graciliano M. P. explained that he wanted native datatypes in Parrot so he could make optimizations where appropriate. Leo, Luke, and Bernhard all explained that it could be done. Bernhard Schmalhofer even went on to ponder Piddles in Parrot.

Parrot bench's working directory

Matt Diephouse wondered if he should make Parrot bench run from the root directory instead of its subdirectory. Joshua Gatcomb indicated that he should.

VTABLE_call_method

Sam Ruby solicited input on adding a new VTABLE_call_method slot.

Pop_pad

Peter Christopher wondered why pop_pad had no implementation yet.

The Usual Footer

If you find these summaries useful or enjoyable, please consider contributing to the Perl Foundation to help support the development of Perl. You might also like to send feedback to

Bricolage Configuration Directives


In my previous article, I provided a guided tour of the Bricolage installation process. If you followed along, you should now have a nice, functioning installation of Bricolage 1.8 all ready to go. But as Mr. Popeil used to say, "But wait, there's more!"

Like many other applications, Bricolage comes with a runtime configuration file. This file, named bricolage.conf, lives in the conf subdirectory of your Bricolage root. It contains a list of settings that tell Bricolage how to find things, how to connect to the database, which optional features to include, and other good stuff. This article provides a guided tour of all of the configuration settings in bricolage.conf to enable you to configure things exactly the way you need them, so that you can manage your sites more effectively with Bricolage.

Configuration Format

The format of bricolage.conf, derived from the Perl Cookbook, is quite simple. A directive appears on a single line, followed by a space, an equal sign, and then the value. Anything after a pound sign (#) is a comment. Typical entries look like this:

APACHE_BIN   = /usr/local/apache/bin/httpd
APACHE_CONF  = /usr/local/bricolage/conf/httpd.conf
LISTEN_PORT  = 80
SSL_PORT     = 443
SSL_ENABLE   = No

Most bricolage.conf configuration options are one of two types: Boolean values or strings. A Boolean configuration directive can be either enabled or disabled, but you have several ways in which to do so. To enable a Boolean directive, simply set its value to Yes, On, or 1 (the number one). To disable it, set it to No, Off, or 0 (zero). String values follow the equal sign. They can be as long as necessary, but cannot break across lines.

Apache Configuration

The first section of bricolage.conf configures Bricolage to use the Apache web server. Because Bricolage runs on top of Apache but uses its own startup scripts, it needs to know where to find Apache resources so that it can configure and start Apache properly. Bricolage's default method of dynamically configuring Apache therefore relies on these directives. The installation sets many of them for you, but not all, so it's worth it to have a look to see if you need to tweak any of them:

APACHE_BIN

This directive tells Bricolage where to find your Apache httpd executable, which it uses to start itself up.

APACHE_CON

This directive points to the httpd.conf file. This, of course, is the famous Apache configuration file. It, too, needs configuration to run Bricolage (the Bricolage installer configures the default httpd.conf in the conf subdirectory of your Bricolage root directory), and Bricolage, in turn, uses this directive to tell httpd where to find the configuration file when it starts up.

LISTEN_PORT

This is the TCP/IP port on which Bricolage will listen for requests. It uses the HTTP standard port 80 by default, but you can change Bricolage to use another port if you already have another server listening on port 80.

SSL_PORT

This is the TCP/IP port on which Bricolage will listen for secure sockets layer (SSL) requests. It defaults to the standard HTTP SSL port 443, but again, you can change it to another port if something else is already using port 443. SSL is disabled by default, however, so read on for details on how to turn it on.

SSL_ENABLE

This directive turns on SSL support. You must have either mod_ssl or Apache-SSL installed and properly configured in your Apache server. Not quite a Boolean configuration directive, the possible values for SSL_ENABEL are No (or Off or 0 [zero]), mod_ssl, or apache-ssl. SSL is a useful feature for keeping communications encrypted between the server and users' browsers.

ALWAYS_USE_SSL

By default, an SSL-enabled Bricolage installation uses SSL only for logging in to Bricolage and in the user profile (where users can change their passwords). Users can elect to encrypt all communications by checking the Always use SSL checkbox when logging in, but some security policies may require the encryption of all communications. In such cases, enable this Boolean directive to force the encryption of all communications between the Bricolage server and users' browsers.

SSL_CERTIFICATE_KEY_FILE
SSL_CERTIFICATE_FILE

These directives specify the location of your SSL keys. If you've configured mod_ssl or Apache-SSL, you should already be familiar with these files. They help to encrypt and decrypt requests between the server and the browser. If you use make certificate to generate your SSL certificate during the Apache build process, by default your server key file will be server.key in the conf/ssl.key subdirectory of your Apache root directory, while the server public key file will be server.crt and in the conf/ssl.crt subdirectory. Bricolage uses these directives to set the Apache SSLCertificateKeyFile and SSLCertificateFile directives, respectively, in its dynamic configuration of Apache.

NAME_VHOST

This directive roughly corresponds to the Apache httpd.conf NameVirtualHost directive. Set it to the IP address on which the Bricolage Apache server will listen for requests. If you have only one IP address on your server, the simplest thing to do is to leave this directive set to *, which applies to all IP addresses. Again, Bricolage uses this directive in its dynamic configuration of Apache.

VHOST_SERVER_NAME

This is the virtual host name under which to run Bricolage. Bricolage requires a full host or virtual host to run and will use this directive to configure the virtual host dynamically. Leave it set to _default_ to use the default host name set in your httpd.conf file.

MANUAL_APACHE

Bricolage uses Apache::ReadConfig to configure the httpd daemon. There is no httpd.conf include file. If you want to take control of your Bricolage Apache server by manually configuring it, enable this Boolean directive. It will generate a file, bric_httpd.conf, in the bricolage subdirectory of your temporary directory (see the TEMP_DIR directive for the location of the temporary directory). This file will contain all of the Apache configuration directives that Bricolage uses to configure Apache dynamically. Restarting Bricolage will rewrite this file, but if you want to use it and edit it manually, copy it to the conf subdirectory of your Bricolage root directory, disable the MANUAL_APACHE directive, and then change the section of the httpd.conf file that configures Bricolage from:

PerlPassEnv BRICOLAGE_ROOT
PerlModule Bric::App::ApacheConfig

To:

Include /usr/local/bricolage/conf/bric_httpd.conf
PerlPassEnv BRICOLAGE_ROOT
PerlModule Bric::App::ApacheStartup

Here /usr/local/bricolage/conf/bric_httpd.conf is the full path name to the newly generated bric_httpd.conf file. You can now tweak this file to your heart's content. Just be sure to generate a new one after each upgrade of Bricolage, as certain directives may change between releases.

SYS_USER
SYS_GROUP

These directives configure the system user and group used by Bricolage. They should contain the same value as the User and Group httpd.conf directives, usually nobody or www. Any files written to the file system by Bricolage will be owned by this user and group.

Database Configuration

The next major section of the Bricolage configuration file configures the database. Bricolage uses PostgreSQL 7.3 or later for its data store. Connecting to that database requires several attributes, not least of which are the username and password. These are all set during installation, but it's worth being familiar with them in case things change down the line.

DB_NAME

The name of the database that stores Bricolage's data. The installer will set this for you. The default value, bric, works well in most situations, but it might be set to a different name if you entered one during installation, perhaps because you already had another database named bric; Why would you want to do that? Perhaps you have multiple Bricolage installations on the same host. Another reason it might be different is that your ISP provides you with a single database that they name according to their own naming conventions. At any rate, you're unlikely to need to change the value of this directive.

DB_USER

The username that Bricolage will use when connecting to the database. Again, you are unlikely to need to change this directive, especially because, when Bricolage creates the database, it specifically assigns permissions for this user to access the appropriate tables, sequences, and such. Note that, for security reasons, you should never use the PostgreSQL superuser for this directive.

DB_PASS

The password for the DB_USER to use to connect to the PostgreSQL database. You'll need to change this directive if the password ever changes in the database. Depending on your PostgreSQL server's security model, it might not matter what the password is. For example, if the PostgreSQL is on the same host as your Bricolage server and trusts local users (the default configuration), it will ignore the password. Consult your PostgreSQL authentication settings (in the server's pg_hba.conf file) or check with your PostgreSQL DBA if you have questions.

DB_HOST

This is the host name of your PostgreSQL server. If it's on the same host as your Bricolage server, it will likely be commented out, thereby letting Bricolage default to localhost. Otherwise, it will be a different host name or IP address. Change this setting if ever your PostgreSQL server moves to a different host or has its host name or IP address changed.

DB_PORT

The TCP/IP port on which your PostgreSQL server listens for connections. This directive will be commented out if you've installed PostgreSQL locally and you're using Unix sockets instead of TCP/IP for its connectivity (a good idea for security-conscious environments). It will also be commented out if Bricolage should use the default PostgreSQL port of 5432. Otherwise, if Bricolage must connect to the PostgreSQL server via TCP/IP on a port other than 5432, set this directive to the appropriate port number.

Directory Settings

Bricolage stores a lot of files on your server's file system, generally in well-named directories below your Bricolage root directory. Sometimes you may want them installed elsewhere, perhaps for the purposes of conserving disk space or distributing I/O between different partitions. If you want to move any of these directories to a location other than that set by the installer, copy over any existing files to ensure that Bricolage continues to operate correctly.

TEMP_DIR

Bricolage creates several temporary files as it runs, for its cache, user sessions, and the like. If you selected the multi option when installing Bricolage, this directive will point to a directory named tmp under your Bricolage root. Otherwise, it will point to your system's global tmp directory.

MASON_COMP_ROOT

The Bricolage UI uses HTML::Mason. All of the components to power the UI live in this directory, generally a subdirectory of your Bricolage root named comp. However, media files uploaded to Bricolage also go in this directory, which means that it can become quite large if you manage a lot of media documents. It might be useful, therefore, to move this directory to a separate partition.

MASON_DATA_ROOT

Mason compiles the Bricolage UI components into object files and stores them in this directory. For the most part you don't need to worry about where these files live (the default is the data directory under the Bricolage root directory), although Bricolage will read from it quite a lot as it loads the object files into memory, so disk I/O is important. It's unlikely to grow too except...

BURN_ROOT

This directive tells Bricolage where to store formatting templates, object files, and burned files that are ready for distribution. As such, it can also grow quite large, especially if you've published or previewed a lot of documents. Bricolage never deletes these files so that you always have a canonical directory of the distribution files output by Bricolage. However, the default location for the BURN_ROOT is under the directory specified by the MASON_DATA_ROOT directive. If you encounter disk space problems, you might want to move this directory to another partition.

XML::Writer Configuration

The Bricolage Mason burner is responsible for pushing documents through Mason formatting templates. If you're writing templates that output XML (and I'll demonstrate writing templates in a later article, so hang in there!), you might want to simplify things by using an XML::Writer object to generate the XML. Bricolage simplifies things by providing these directives to create a globally available XML::Writer object for use in all Mason templates.

INCLUDE_XML_WRITER

Enable this Boolean directive to tell Bricolage to create an XML::Writer object that's globally available as $writer to all Mason templates. Bricolage is smart enough to configure the XML::Writer object to output XML to Mason's buffer, so that you can even mix standard Mason output in your templates with XML::Writer output.

XML_WRITER_ARGS

Use this directive to specify a list of options to pass to the XML::Writer constructor when INCLUDE_XML_WRITER is enabled. This directive is a string containing a Perl expression to pass to XML::Writer. The XML::Writer documentation has the full list of possible parameters. Common parameters include NEWLINES to trigger the output of new lines between XML elements, and DATA_INDENT to indent nested XML elements by a certain number of characters.

Authentication Configuration

Several configuration directives affect the behavior and security of the Bricolage authentication system. Bricolage handles its own authentication, storing passwords in the database as MD5-encrypted hashes and recording authentication in a browser cookie. In a security-conscious environment, it pays to be familiar with these directives and even to review their settings periodically.

AUTH_TTL

This directive specifies the time-to-live, in seconds, for an authentication session. Each time an authenticated user sends a request to the server, the elapsed time resets to zero. You could therefore set AUTH_TTL to 3600 seconds for a one-hour time-to-live, and a user would be able to use Bricolage all day, as long as each request was less than an hour apart (but she might have to re-authenticate after lunch). This directive is especially useful in environments where users access Bricolage from public workstations and forget to log out. The default value of 28800 (eight hours) is probably too long in a production environment.

AUTH_SECRET

Bricolage stores the user authentication session locally and keys it off of an MD5 string stored in a browser cookie. The MD5 string comes from the browser's IP subnet, the expiration time, the user name, and the last access time. Because such a string is potentially replicable by someone trying to crack the system, Bricolage also uses a random string of characters to salt the MD5 string. AUTH_SECRET is the string used for this purpose. The installer generates it for you, but you might want to change it now and then, in order to keep it random and meet the specifications of your security policy. All users will need to re-authenticate after you change AUTH_SECRET and restart Bricolage.

LOGIN_LENGTH

This directive specifies a minimum user name length. Each user must have a user name of at least this number of characters. The default, 5, is generally adequate, and allows the default admin user name to work properly.

PASSWD_LENGTH

This directive corresponds to the LOGIN_LENGTH directive, but applies to passwords. The password length in Bricolage is unlimited, but it's generally a good idea to ensure that they all contain a minimum number of characters. The default is 5.

Distribution Configuration

When Bricolage previews or publishes documents, it pushes them through formatting templates (written in Mason, Template Toolkit, or HTML::Template) and writes the resulting files to disk. It then distributes those files to the appropriate servers specified in the destination manager in the user interface. (A later article will explain more of the Bricolage administrative interface.) Many run-time configuration directives affect the behavior of the Bricolage distribution server.

ENABLE_DIST

This Boolean directive enables Bricolage distribution. The only reason to disable distribution is if you set up a separate distribution server. To my knowledge, no one has actually done this, even though Bricolage supports it. The QUEUE_PUBLISH_JOBS directive is more popular to reduce Bricolage server overhead.

DIST_ATTEMPTS

Bricolage distributes files via file system copy, FTP, SFTP, or WebDAV—depending on your destination configuration. We all know that failures can occasionally occur. Bricolage will attempt to distribute a file after a failed distribution and will do it multiple times. Set the DIST_ATTEMPTS directive to the number of times it should attempt to distribute a file before giving up.

PREVIEW_LOCAL

This Boolean directive enables Bricolage's internal preview server. This is just a URI in the Bricolage UI that knows to serve previewed content rather than the UI. This is handy for evaluating Bricolage, but be sure to disable it in a production environment, especially if your front-end server needs to serve something other than static HTML. The recommended approach is to set up a separate preview server that is identical to your production server and configure a destination to distribute and redirect previews to that server.

PREVIEW_MASON

With the PREVIEW_LOCAL directive enabled, if the content you're generating includes Mason calls, you can enable this boolean directive to make Bricolage's internal preview server evaluate the Mason code before serving documents.

DEF_MEDIA_TYPE

This string directive identifies the default media type (also called a MIME type) of files for which Bricolage cannot determine the media type. The default value, text/html, covers a lot of typical files in a Web content management environment, such as .php or .jsp files. To add new types for Bricolage to recognize, use the media type manager in the UI.

ENABLE_SFTP_MOVER

By default, Bricolage does not support distribution via secure FTP (SFTP). If you need it, install the required Net::SFTP module, enable this directive, and restart Bricolage.

SFTP_HOME

If you've enabled SFTP distribution, use this directive specify a home directory for SFTP to use, especially if you want to use public and private SSH keys. Consult the Net::SFTP documentation for details.

ENABLE_SFTP_V2

Enable this directive to prefer SSH2 support for SFTP distribution. You'll also need to install more Perl modules from CPAN. Consult the Net::SFTP documentation for details.

SFTP_MOVER_CIPHER

Net::SFTP uses the Net::SSH::Perl module to handle the SSH side of things. This module supports multiple encryption ciphers. If you prefer one, specify it via this directive.

ENABLE_WEBDAV_MOVER

Bricolage also supports distribution via WebDAV, a standard for distributing documents via the HTTP protocol. DAV, as it is also known, has support in multiple web servers including Microsoft's IIS and Apache 2. If you'd like to distribute document files to your production server or servers via DAV, install the HTTP::DAV module, enable this Boolean directive and restart Bricolage.

QUEUE_PUBLISH_JOBS

By default, when a user schedules a document to publish immediately, the Bricolage server will immediately execute the distribution. If users publish a lot of documents or you're bulk publishing large sections of your site at once, this can really slow down the Bricolage UI for other users. This is even true even if you've scheduled a bulk of documents to publish at a future date and time, because the way the default bric_dist_mon script works is to tickle the Bricolage server to distribute documents.

The way around this problem is to enable the QUEUE_PUBLISH_JOBS boolean directive and then use the bric_queued program instead of bric_dist_mon. With QUEUE_PUBLISH_JOBS enabled, the Bricolage server will never burn and distribute documents, even if a user schedules them to publish yesterday. Instead, bric_queued handles all of the burning and distribution itself, without having the Bricolage server expend resources on the task. With this approach, be sure to run bric_queued from a fairly aggressive cron job.

FTP_UNLINK_BEFORE_MOVE

When Bricolage distributes files via FTP, it uploads them with a temporary file name, and then, when the transfer is complete, it renames the file to the final name. However, if an earlier version of the file is already present, the rename might fail. (This depends on your FTP server, but Microsoft's IIS is the server that led us to add this feature.) In such a case, enable this directive and Bricolage will delete any existing instance of the file before renaming the temporary file.

Alert Configuration

Bricolage has an interface for sending alert emails when it logs events that meet certain criteria against objects. Bricolage needs to know a few things before it can send the alerts.

SMTP_SERVER

Bricolage uses an SMTP server to send alert email messages. The default value for this directive, localhost, is fine if you use a Unix system with sendmail (or some other SMTP server) running locally. If your organization has a dedicated SMTP server or if your Bricolage host has none of its own, change the value of this directive.

ALERT_FROM

Set this directive to an email address that you want to appear in the From header of alert emails. I typically set it to something like Bricolage Admin <www@example.com>, but use whatever is appropriate for your organization. If your users are inclined to reply to alert emails, you may want to set up a special ALERT_FROM email address that has an auto-responder to let the user know that the reply will go unread.

ALERT_TO_METH

This string directive indicates which header to use for specifying alert recipients in email alerts. The possible values are To and Bcc.

User Interface Configuration

Some configuration directives enable you to affect how the Bricolage user interface works in subtle ways. If you haven't used the Bricolage browser-based interface much yet, some of these won't make much sense just now. Feel free to come back and look again when you're you've had some experience with the Bricolage interface and want to make it behave more according to your own notions of correctness.

FULL_SEARCH

By default, when you search for objects in the Bricolage admin interfaces, or for stories, media, or templates in the asset library, the Bricolage UI appends a wildcard character to the end of your search string. Thus if you search for foo, the search will return results for all records that start with foo. If, however, you set the FULL_SEARCH Boolean directive to a true value, all searches in the Bricolage UI will become substring searches. So a search for foo will return all records where foo appears anywhere in a record.

The downside to this approach is that it prevents PostgreSQL from using its database indexes. In principal, this is only a problem if you have a large number of objects in Bricolage. If, say, you had 100,000 stories in Bricolage, you would notice that story searches would be noticeably slower with FULL_SEARCH enabled than with it disabled. Leave it disabled if you expect to manage a lot of documents. Your users can always manually prepend the wildcard character (%) to the front of search queries if they want a substring search.

ALLOW_WORKFLOW_TRANSFER

Bricolage workflows are made up of a series of desks. In general, workflows have their own desks, but desks can appear in more than one workflow. In such a case, documents moved to such a shared desk in one workflow will be visible on the same desk in another workflow. This is great for managing common tasks across workflows, such as translation or legal review. The upshot is that, by default, a document placed on a desk in one workflow cannot be transferred from that desk to another desk in a different workflow. Users can only move it to other desks in the workflow in which it originated. Set the ALLOW_WORKFLOW_TRANSFER Boolean directive to a true value to remove this constraint, so that a document placed on a desk in one workflow can be moved from that desk to other desks in other workflows that the desk is in.

ALLOW_ALL_SITES_CX

When managing multiple sites in Bricolage, the user interface will display a site context select list. Only the workflows for the selected site will be displayed. If you want to allow users to see all of the workflows for all of the sites that they have permission to access, set this Boolean directive to a true value to add an All Sites option to the Site context select list. But beware! If you have access to a lot of sites, you'll have access to a bewildering number of workflows when you select this option!

YEAR_SPAN_BEFORE
YEAR_SPAN_AFTER

For the input of dates in Bricolage, the user interface offers select lists for the day, month, and year. By default, the years available in the Year select list have a limit of the ten years before and after the value for the year or the current year. If you need more years in your select list, set these directives to the number of years before and after the current value or current year. For example, if you manage a site of historical photographs with Bricolage, you might need to select years that range back over 100 years. In such a case, set YEAR_SPAN_BEFORE to 100. A science fiction book review site, on the other hand, might need years much farther in the future. For such a case, set YEAR_SPAN_AFTER to the appropriately high number.

DEFAULT_FILENAME
DEFAULT_FILE_EXT

The file names generated for story documents are set on a per-output channel basis. The user interface offers default values for these settings in the output channel profile. The default file name is index, and the default file name suffix is html. If, say, you were outputing content to an IIS server, you might want to set the DEFAULT_FILENAME directive to default and the DEFAULT_FILE_EXT directive to htm, instead. It's not a big deal either way, though, because you can actually set the values you need for each output in the user interface. These are just the displayed defaults, settable as directives for the ultimate in laziness.

ENABLE_OC_ASSET_ASSOCIATION

Document models are associated with output channels in Bricolage. When you create a new document based on a model, it will automatically have the output channel associations defined by the model. If you'd like users to be able to change the associations—say, to assign output channels defined by the model to be optionally associated with documents based on that model—set this directive to a true value. If, however, the added complexity of output channel associations will only confuse your users, set this directive to a false value to remove the user interface for changing document output channel associations.

ENABLE_CATEGORY_BROWSER

When editing a story document in Bricolage, you'll see a select list of all categories that you have READ permission to access to allow you to optionally add the story to a new category. Most of the time, however, you'll only add a story to one or two categories, and then never change these settings. Therefore, if you have a lot of categories in your Bricolage installation (and there are systems in production with over 2000 categories), it's wasteful to load them all every time you edit a story document when you'll never change them again.

In such a case, set the Boolean ENABLE_CATEGORY_BROWSER directive to a true value and restart Bricolage. This will change the story profile to offer a link to a category browser, which enables you to search for the category or categories to associate with a story. Now, not only will you no longer load all categories every time you access the story profile (and the story profile is, for content producers, the most commonly accessed page in the Bricolage UI), but you'll only load those you search for in the category browser. I highly recommend that every Bricolage admin to set this directive to a true value.

Document Management Configuration

These directives relate to how Bricolage manages documents.

PUBLISH_RELATED_ASSETS

Bricolage allows you to create relationships between documents. These can point to related stories or add images to a document, among other things. By default, when you publish a document, Bricolage will also try to publish any related documents. This will help to prevent 404s or broken image problems. In some cases, you might not want this behavior, so set the PUBLISH_RELATED_ASSETS Boolean directive to a false value.

STORY_URI_WITH_FILENAME

Story documents in Bricolage must have unique URIs. URIs consist of a story's category and optionally other parts of the story, such as its cover date and its slug (a one-word description of a story). They do not, however, consist of the file name. This is in keeping with W3C suggestions. The idea is that the story has a directory URI, and there may be several forms of the story with different file names in that directory, such as index.html for HTML, rdf.xml for RDF, and index.pdf for PDFs.

However, some organizations have Website policies that demand the inclusion of file names in the URI. This is so that different documents can be in the same directory. A common example might be a About Us directory with separate /about/index.html, /about/contact.html, and /about/copyright.html documents. Such URIs are not possible by default in Bricolage, which requires that all stories have unique URIs, because each of these stories would have the same URI, namely /about. To get around this issue, set the STORY_URI_WITH_FILENAME Boolean directive to a true value. From then on, all stories will include their file names in their URIs. Be careful, though! Existing stories will not have their URIs changed. Decide how you want to set this directive when you start using Bricolage, and never change it.

ALLOW_SLUGLESS_NONFIXED

The URIs for story documents are determined by patterns specified on a per-output channel basis. There are two different URI formats in each output channel, one for fixed documents and one for non-fixed documents. Non-fixed documents typically use parts of the cover date in their URIs, while fixed URIs do not. Each document model has a flag set to indicate whether documents based on the model will use the fixed for non-fixed URI patterns. The result is that, for non-fixed stories, you might have URIs like /reviews/books/2004/12/23/princess_bride. Here the URI format includes the slug, a one-word summary of the contents of a story (the princess_bride part of this example). However, slugs are optional in stories, even non-fixed stories. If you want to force all non-fixed stories to include the slug in order to guarantee the creation of more meaningful URIs, set this Boolean directive to a true value.

AUTOGENERATE_SLUG

This Boolean directive complements the ALLOW_SLUGLESS_NONFIXED directive. If you want to keep the slug optional but generate one when a user neglects to type one in, set AUTOGENERATE_SLUG to a true value. This will cause Bricolage to generate a simple slug based on the title of the story. For example, a story with the title Essential Perl 6 would have the slug essential_perl_6 generated for it.

Apache::SizeLimit Configuration

Bricolage is a large application that includes many CPAN modules as well as its own 120,000+ lines of code. When you start it up, its processes can take up 30MB of memory or more. In general this isn't a problem, because Apache shares that memory between child processes. As each process handles requests, however, its size can swell independent of other processes. If you're performing resource intensive activities, such as publishing a lot of documents at once, the process that handles the request can become quite large. Because Perl (and, by extension, mod_perl) does not return memory to the system, this can give the appearance that you have a memory leak.

The solution to this problem is to use the Apache::SizeLimit module distributed with mod_perl to check your mod_perl processes periodically and kill them when they exceed a certain size. Bricolage has integrated support for Apache::SizeLimit that these directives can quickly enable and configure.

CHECK_PROCESS_SIZE

This Boolean directive turns on the Apache::SizeLimit support. After you set it to a true value and restart Bricolage, it will use the settings in the following directives to decide how often to check your processes and to kill them when they get to be too big.

MAX_PROCESS_SIZE

This is the maximum size, in bytes, that processes can reach before Apache::SizeLimit will kill them.

CHECK_FREQUENCY

This directive determines how often Apache::SizeLimit will check the size of your mod_perl processes. If you set it to 5, it will check a process after every fifth request handled by that process. The default is 1.

MIN_SHARE_SIZE

This directive indicates the minimum amount of shared memory the process must employ to avoid being considered a candidate for termination. Consult the Apache::SizeLimit documentation for more information. The default is 0, meaning that all Apache mod_perl processes will have their sizes checked.

MAX_UNSHARED_SIZE

This directive sets a limit on the amount of unshared memory a process may consume to not be a candidate for termination. You can use this directive to tweak your settings if you find that Apache::SizeLimit terminates processes while they are still mainly using shared memory. The default is 0.

Virtual FTP Server Configuration

Bricolage pushes story documents through formatting templates to generate output when you preview or publish them. Formatting templates can use Mason, Template Toolkit, or HTML::Template. If you have a lot of different types of story documents, or just elements of story documents, you'll likely end up with a lot of templates to manage. Editing templates in the browser interface's textarea fields can be a pain. A better approach is to use the Bricolage virtual FTP server, which provides access to all Bricolage templates via FTP. If the security of your password isn't a serious consideration (because FTP sends passwords in the clear, and maybe you work behind a firewall or over a virtual private network), enable the virtual FTP server and edit Bricolage templates from within your favorite FTP-enabled editor (Emacs, Vim, HomeSite, etc.). Here's how.

ENABLE_FTP_SERVER

This boolean directive enables the virtual FTP server. Set it to a true value, tune the other FTP directives, reboot Bricolage, fire up the bric_ftpd application, and get to work! Just connect to your Bricolage FTP server on the port specified by the FTP_PORT directive, login with your Bricolage username and password, and you can browse templates by site, output channel, and category.

FTP_PORT

This directive specifies a TCP/IP port on which the Bricolage virtual FTP server will listen for connections. The default is 2121.

FTP_ADDRESS

If your host has more than one IP address, specify one of them here to have the virtual FTP server to listen for connections on that IP address only. By default, the FTP server will listen on all of your host's IP addresses.

FTP_LOG

The location of the virtual FTP server log. By default, it will be in the log subdirectory of your Bricolage root directory.

FTP_PID_FILE

Specify the location of the PID file for the Bricolage FTP server. bric_ftpd will use this file to record the PID of the server when you start it and to stop the server when you execute bric_ftpd -k. The default is to store the PID file in the log subdirectory of your Bricolage root directory.

FTP_DEPLOY_ON_UPLOAD

As of Bricolage 1.8 and later, the Bricolage FTP server will save templates to your private sandbox when you upload them. This means that they will be checked out to you, appear in your personal workspace in the UI, and execute when you (and only you) preview stories that use them. To check in and deploy a template to use in production when other users preview and publish documents, simply append the string .deploy to the end of the file name when you upload it and Bricolage will do the rest.

Prior to version 1.8.0, the Bricolage virtual FTP server checked out, updated, checked in, and deployed templates on every upload. If for some reason you prefer this approach (and to be honest, I can't imagine why anyone would!), set the FTP_DEPLOY_ON_UPLOAD directive to a true value and restart bric_ftpd.

FTP_DEBUG

If for some reason the virtual FTP server isn't behaving the way you expect, set this Boolean directive to a true value and restart bric_ftpd. Then tail the FTP log (specified by the FTP_LOG directive) to diagnose the problem.

Preloading Configuration

Because Bricolage runs on Apache 1.3, the parent process loads all of its code at startup time, before it forks off any children. This is memory efficient, because most modern operating systems use a copy-on-write forking design. This means that the children all share memory with the parent until they write to that memory, at which time the kernel copies that memory to the child process.

When loading a lot of code, children never overwrite much of it. It's highly advantageous to load as much code as you think you'll need into the parent process at startup time, to prevent each of the children from loading it themselves and taking up that much more memory. These directives help you to do just that.

PERL_LOADER

This string directive can be any Perl code you like, as long as it's all on one line in the bricolage.conf file. Bricolage will execute this code at startup time, in the namespace used by the Mason burner. This is very useful for loading Perl modules that your templates use, so that you're not loading them in each child process. The default value loads Apache::Util, which has many useful HTML output utility functions, and Bric::Util::Burner, which exports several constants that you can use in templates to tell what type of burn is being executed (preview or publish). Other common modules you might want to load here include CGI.pm or XML::RSS to assist with HTML and RSS output, respectively. You can load anything here, really.

LOAD_LANGUAGES

Bricolage has localizations for multiple languages, including German, Portuguese, Italian, Cantonese, Mandarin, and Russian. The localization libraries are Perl modules loaded at server startup time. For the most efficient use of memory, load the languages you expect to use most often by specifying the appropriate language codes (such as en for English, pt_pt for Portuguese, de_de for German, etc.) in a space-delimited list via the LOAD_LANGUAGES directive.

LOAD_CHAR_SETS

This directive functions just like the LOAD_LANGUAGES directive, except that it loads the libraries that convert to and from UTF-8. Bricolage allows individual users to use different character sets when accessing the Bricolage UI, including ISO-8859-1, ISO-8859-2, Big5, ShiftJIS, GB-2312, and others. To save memory overhead, specify each character set that you expect your users will need to use day-to-day in Bricolage in a space-delimited list in the LOAD_CHAR_SETS directive.

Thumbnail Configuration

As of Bricolage 1.8.0, Bricolage can generate thumbnail versions of image files uploaded for media documents. All you need to do is install the Imager module from CPAN (along with the necessary libraries for the image formats you use—see the Imager README file for details) and configure thumbnail support via these directives.

USE_THUMBNAILS

Set this Boolean directive to a true value and restart Bricolage to have thumbnails generated for all image files in Bricolage. You must have Imager installed, of course. You might also want to consider installing media type icons specific to particular types of non-image files. See the README file and script in contrib/copy_gnome_icons in the Bricolage sources for information on which icon files to use and how to install them using the copy_gnome_icons script.

THUMBNAIL_SIZE

Set this directive to the maximum dimension of thumbnail images, in pixels. Bricolage will use this number to constrain the size of the thumbnail so that its greatest dimension does not exceed this number. For example, if THUMBNAIL_SIZE has its default value, 75, and you upload a 150 x 100 pixel image file, Bricolage will generate a 75 x 50 pixel thumbnail.

htmlArea Configuration

Bricolage 1.8.0 added support for WYSIWYG (what you see is what you get) editing via the htmlArea JavaScript editor, though it has this feature disabled by default. To enable it, download and install htmlArea 3.0 (in beta release as of this writing) in the comp/media/htmlarea directory under your Bricolage root. Then configure it via these directives and restart Bricolage. You will then be able to specify a WYSIWYG field type in document element definitions, and content editors can take advantage of htmlArea's WYSIWYG features when editing content in those fields.

ENABLE_HTMLAREA

Set this Boolean directive to a true value to enable Bricolage's htmlArea support. You must have htmlArea installed in the comp/media/htmlarea directory under your Bricolage root.

HTMLAREA_TOOLBAR

The htmlArea editor offers a lot of WYSIWYG features as controls (buttons) in its interface. The controls handle tasks such as copy, paste, italicize, boldface, link, etc. By default, Bricolage enables only a subset of these controls. The subset excludes layout type features such as font selection and color, line justification, and the like. The idea is to provide only the tools needed for users to easily add semantically meaningful markup rather than layout markup, so as to keep content independent of presentation. If you really need to allow your users to use six different type faces in twelve colors, you can enable the htmlArea controls for these features via the HTMLAREA_TOOLBAR directive. The value of the directive is a comma-separated list of single-quoted strings with brackets at either end. See the htmlArea documentation for a complete list of supported controls.

Up Next

Now you have all the information you need to configure how Bricolage operates to your heart's content. My next article will explore the nitty-gritty of defining document models in Bricolage.

Visit the home of the Perl programming language: Perl.org

Sponsored by

Monthly Archives

Powered by Movable Type 5.13-en