June 22, 2009

Interesting uses for the new 2009.1 "+X" filetype.


I gave a brief introduction to the +X file type at the bottom of the 2009.1 Release post. I hinted that there were more interesting ways of using archive triggers than just handling static file content, and here they are.

Since the archive trigger is just any ol' program, you can point it at anything you want. For instance, nothing says that you have to actually serve real file content, or even the same content twice! Granted, in most cases that kind of defeats the purpose of SCM, but if you treat it as a special case, it can be useful. Take the following set of files as an example:

p4 files //admin/...
//admin/df#2 - edit change 5 (text+X)
//admin/iostat#1 - add change 6 (text+X)
//admin/uptime#2 - edit change 7 (text+X)
//admin/topb#1 - add change 8 (text+X)

And the associated trigger definitions:

df archive //admin/dfdf
uptime archive //admin/uptime uptime
iostat archive //admin/iostat iostat
topb archive //admin/topb "top -b"

What it's saying is that any time someone reads from "//admin/df", the server runs the "df" command and sends its output back to the client, in effect making a file whose content is always the current free disk space report for the server.

p4 print -q //admin/df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/sda3 73790656 29463164 44327492 40% /
udev 10240 160 10080 2% /dev
none 4051436 66224 3985212 2% /dev/shm
/dev/sda1 194442 89675 94728 49% /boot
/dev/sdb 732443512 579285000 153158512 80% /2
/dev/sdc 488255512 432349832 55905680 89% /3

Or, the server's up-time:

p4 print -q //admin/uptime  17:35:26 up 7 days,  1:59,  2 users,  load average: 0.35, 0.48, 0.99

Note that the last trigger entry, "topb" is interesting in that the "top -b" command never exits! If you request that file from the server, it'll continually send you the output of the program. This could be great if you're expecting the behavior for continuous monitoring, etc, but if you run a "p4 sync", you'll quickly notice that it never returns...

Note that because the content is never the same for these, that a "p4 verify" will show them as being BAD.

Here's a less-practical, but more entertaining example. If you've got a video source on your server (who doesn't?), you can now stream it back to the client and watch it! In pseudocode, here's how you'd do it:

"p4 print -q //depot/video.mpeg" -> P4D -> (Trigger -> `cat /dev/video`) -> P4D ->
p4 | cvlc stream:///dev/stdin

In more detail, what happens is: when the client runs the print on the depot file, the request is sent to the server which in turn asks the trigger for its data. The trigger streams content from the video device back to the server, which then sends it to the client in chunks. Then, back on the client, p4 sends the stream to its STDOUT which is then piped to your video player!

Another way of thinking about these non-file files is as a rudimentary plugin system for the Perforce server. If you've got some arbitrary program that emits something to STDOUT, with the addition of +X on its pseudo-file, you've elevated it to the level of the rest of the P4 applications and metadata. It gives you a common, cross-platform interface for scripting and so forth.

A few ideas that come to mind are: interfaces with your OS filesystem's disk-snapshot facility, external database queries, build system results, etc. If the pseudo-file returns a discrete chunk of data, then you could use "p4 integrate" to version it! (Don't forget to edit/submit or snap the newly-integrated file to make sure it's not kept as a lazy-copy.)

In my next post, I'll give you example code to solve an actual, practical problem using +X files.