Archive for the 'development' Category


configuring varnish to use custom http headers

By default caches uses the field “Cache-Control” to get the TTL for objects they care about. In case of a server side cache the parameter “s-maxage” is responsible for the life time of an object. (see rfc2616). This is fine for almost all cases. The bad thing about this is a bad configured cache proxy also uses this parameter to get it’s caching informations. This causes the backend to have no control to invalidate such an object because it will remain in memory of such a bad configured cache.

So we decided to use a custom field in the http header to tell varnish how long an object should stay in cache. In the backend it was very easy to implement a few lines of code to set the custom field. I called it “Varnish-Control” . The field will contain an integer value which indicates the TTL in seconds. The main part of the work was to configure varnish to use this value instead of s-maxage form the field “Cache-Control”.

In words i did the following:

Once an item was fetched from the backend (so it was not found in the cache) I will set the TTL of the item and stuff it into the cache. Since the field “Varnish-Control” is useless for all request handling nodes on the way to the client i removed the field once the TTL was set.

The first approach was pretty simple:

sub vcl_fetch {
if (obj.http.Varnish-Control) {
set obj.ttl = 7d;
remove obj.http.Varnish-Control;
}
insert;
}

Unfortunately this solution did not care about the value I’ve set into “Varnish-Control” but uses a static value of seven days to cache items. This was not satisfying. So i tried to make it more dynamic. Since it is not possible to assign the value from obj.http.Varnish-Control to obj.ttl i had to use inline C code. This is done by using C{ … }C somewhere in the VCL file.

sub vcl_fetch {
if (obj.http.Varnish-Control) {
C{
char *ttl;
ttl = VRT_GetHdr(sp, HDR_OBJ, "\020Varnish-Control:");
VRT_l_obj_ttl(sp, atoi(ttl));
}C
remove obj.http.Varnish-Control;
}
insert;
}

Finding the right commands to access the header informations and write them into the TTL of the object was PITA. Anyway, I try to explain this two commands:

char *VRT_GetHdr(const struct sess *sp, enum gethdr_e where, const char *n)

  • The first parameter is the session pointer…nothing more to say about this.
  • The second parameter is a constant indicating from which object will be used to get the header informations. In this case it was “HDR_OBJ” which is equivalent to “obj” in plain vcl configuration scenarios. possible values are: HDR_REQ, HDR_RESP, HDR_OBJ and HDR_BEREQ.
  • The third parameter is the name of the field i like to access. NOTE: The field name has to be suffixed with a colon and it has to be prefixed with the length of the field name (including the colon). This value has to be noted octal.

void VRT_l_obj_ttl(const struct sess *, double)

  • The first parameter is again the session pointer.
  • The second parameter is the TTL as double.

Thats it!

All VRT_x commands will be available in this context. This commands can be found in varnish-cache/include/vrt.h and varnish-cache/include/vrt_obj.h

official varnish project

meinberlin.de on the run too

meinberlin
after a wonderful redesign, some hours of work (hell yeah, work), some sweat and less party, we finally done it. http://www.meinberlin.de is online. great, lovely, powerful and not seen before.The mixture: some google maps, a great team of enthusastic coders, innovative projectmanagers and a quintessence of design. So the fusion of knowlegde between Urban Media and Lovely Systems created the magazine and map news community portal meinberlin.de - erforsche deine Nachbarschaft. we proudly present it to the crowd.

For the technique guys a overview: python code within zope/zodb, jquery and native JS, mysql databases, and a huge package of ajax bases services.

Running both IE7 AND IE6 in Windows XP

Yousif Al Saif from tredosoft.com has programmed an installer allowing you to run multiple Internet Explorer versions in parallel on your Windows XP:
Download Multiple IE installer (10.3MB)

please read Yousif’s original article here and check out the comments on this article as well, you will find some useful information there as well.

Technorati Tags: , , ,

The Decathlon of Computer Science

or: “how to make zope/python at least 10 times faster”. Kudos to jukart, dobee, benji and j1m!

During the last weeks the lovely team was working hard on adding speed to some of our zope3 based applications. We were fighting problems that started with wrong bits in the EEPROM of network interfaces up to high level conceptual/architectural problems. That’s why I had the idea to write the story of our Decathlon :)
Our sites have pretty different “load profiles”. I’ll pick two of them:

Lovely Books
it’s a lovely books community site :) here are some stats: about 1.000 users, 82.000 books, 45.000 authors, 6.500 tags, 17.000 reviews,… in total a few million different objects in ZODB (and groooooowing).

  • Users are mainly accessing “the long tail”.
    The database is beeing accessed randomly.
  • Every user get’s a personalized view.
    As soon as the user is logged in, 99% of all pages can’t be cached.
  • We have a lot of pages online.
    Google has roughly 170.000 different pages in his cache, caching all the pages is pretty senseless.
  • Asynchronous Tasks might block application server threads.
    Calls to Amazons webservices,… block server threads while they are running.
  • Adding books, rating, commenting, tagging, making friends changes the relations, results, friends all the times.
    A intelligent solution for cache invalidation is needed

Videoportal
Is a local video portal with quite some traffic. A few month after the official launch we’re serving up to 60MBit/s videos and have roughly half a Terabyte Data online. The top 10 videos had been viewed more than 100.000 times.

  • Users are hammering top videos.
    The main traffic is static (video data) - and can be cached.
  • Logged in users get personalized pages.
    Sometimes it’s just the name of the logged in user on top of the page.
  • Live stats are important.
    We need to keep track of the number of videos viewed, and we need to keep track of it on a pro rata temporis basis.

continue reading the full article

Selenium tests in zope3

for an actual project I am working on I decided to try selenium tests for expanding software quality. Selenium is an open source testing environment for your browser. Selenium makes the same stuff as you as a human would do for testing an application. It clicks throw the pages and verifies if a certain text appears or not. Because the tests run inside the browser it is the perfect environment for frontend developers because you can make cross-browser tests and you can test ajax driven applications (which is not possible with server side unit oder ftests).

for simple tests, the selenium IDE - a plugin for firefox - is a great tool to get a fast overview about the opportunities of selenium. But if you want to dive a little deeper, you will get out of luck with the html-styled testing format. I want to write tests in python language and then test the stuff inside selenium. For that the zc.selenium package - a zope3 package from zope corp - makes that done for you.

here is a small example for a test method - testing the search functionality on our new community portal:

def logout(self):
s = self.selenium
s.open(self.baseURL+’/@@logout.html’)

def login(self, user=’testmember’, passw=’tEsT’):
s = self.selenium
s.type(’login’, user)
s.type(’password’, passw)
s.clickAndWait(’SUBMIT’)

def reset(self):
s = self.selenium
self.logout()
s.open(self.baseURL)

def test_04_friends_search(self):
self.reset()
s = self.selenium
s.clickAndWait(’link=Suche’)
s.select(’search.gender’, ‘label=Mann’)
s.select(’search.ageRange’, ‘label=25 - 35′)
s.type(’search.zipCode’, ‘6850′)
s.clickAndWait(’search.actions.search’)

s.verifyTextPresent(’Manfred’)

as you can see you are able to access forms, test if a specific result was found etc. The advantage to write tests in python instead of the output html format is that you are able to create methods for default workflows like login logout etc.

thanks to zope corp and the selenium team for a cool job!

additional information:

  • http://release.openqa.org/selenium-core/nightly/reference.html
  • http://www.openqa.org/
  • http://svn.zope.org/zc.selenium/

Howto use Tiny MCE in Zope3

since i’m not very experienced with Zope 3 (yet) i had some troubles to turn a text input field in my own content type into a Rich Text Editor using z3c.widget.tiny. This is how i finally got it working (thanks to dobee):

in my interfaces.py file for my content type i defined a normal Text field:

...
description = zope.schema.Text(
title = u"Description",
description = u"describe yourself",
required = False)
...

in my viewclass file (browser.py) i use formlib to handle things, therefore i had to use custom_widget to use the TinyWidget:

import zope.traversing.browser
from zope.formlib import form
from zope.app.pagetemplate import ViewPageTemplateFile
from z3c.widget.tiny.widget import TinyWidget
from training.forms import interfaces, mycontent

class myTinyWidget(TinyWidget):
mce_language = 'de'
mce_theme_advanced_disable = 'bold,italic'
mce_cleanup = 'false'
mce_entity_encoding="raw"

class AddMyContent(form.AddForm):
form_fields = form.FormFields(interfaces.IMyContent)
form_fields['description'].custom_widget = myTinyWidget

def create(self, data):
return mycontent.MyContent(**data)

def add(self, ob):
count = 0
while 'mycontent-%i' %count in self.context:
count += 1;
self.context['mycontent-%i' %count] = ob
self._finished_add = True
self._name = 'mycontent-%i' %count
return ob

def nextURL(self):
return zope.traversing.browser.absoluteURL(
self.context, self.request) + '/' + self._name

class DisplayMyContent(form.DisplayForm):
form_fields = form.FormFields(interfaces.IMyContent)

template = ViewPageTemplateFile('view.pt')

class EditMyContent(form.EditForm):

form_fields = form.FormFields(interfaces.IMyContent)
form_fields['description'].custom_widget = myTinyWidget

actions = form.EditForm.actions.copy()

@form.action("Apply and View")
def handle_edit_view_action(self, action, data):
self.actions['form.actions.apply'].success(data)
url = zope.traversing.browser.absoluteURL(
self.context, self.request)
self.request.response.redirect(url)

some notes:

form_fields['fieldxy'].custom_widget defines the widget to use for this field

we use a class derived from form.DisplayForm to handle the display of the fields using their display widgets

and now comes the part that took me days to figure out ;-) :

when coding the page template we would normally use the display widgets of the fields like this:

My name is <span tal:replace="structure view/widgets/name"/>

but for the description field which uses the Tiny MCE widget for editing text, this doesn’t work, because the normal display widget of a Text field will escape HTML entities (& becomes a & and so on) but we need the unescaped HTML code as we add formatting to the text through Tiny MCE. Therefore we need to access the description field directly in the page template and use structure to render the output as well:

<p tal:replace="structure context/description">
description
</p>

now everything works as expected :-)

Solution Found: Displaying Smileys in a Flash8 TextField

Whoever has tried to display smileys in Flash-textfields has recognized the strange and unpredictable way Flash displays inline images. It’s not possible to do this in the expected way by using <img> tags in a html textfield.

As I am currently developing a realtime chat application based on the open-source instant messaging server Jabber I had to find a work-around for this problem. Jolan’s SmileyTextField, an early solution published as Flash MX component, uses a seperate Textfield and a MovieClip displaying the smileys. The big problem of this solution is that its not possible to get the coords of a specific letter in a textfield in an easy way. SmileyTextField calculates image (or, in this case, library assets) positions using autosizing textfields and line counts, which seemed to be rather imprecise on long texts and caused severe performance issues.

Our solution, we call it the EmotionalTextField, also uses a seperate TextField and MovieClip for smiley positioning. But smiley-positions are calculated using the Flash 8 bitmap-manipulation capabilities. Basically, predefined string sets (like  :-) or :-( ) are replaced by colored dots, the textfield is loaded into a flash.display.BitmapData, and the colored dots are searched using BitmapData.getColorBoundsRect().

After some refactoring and documentation our EmotionalTextField will be released here. Also included will be a configuration-xml, where you can register the text-snippets and corresponding images you want to use in your project.

—- 05/24/07 —-

finally. it’ done! the component can be downloaded here:

Download EmotionalTextfield 0.1b

Installing Flash Media Server 2 on Ubuntu 6.10

The installation script for Flash Media Server works only on RedHat Enterprise by default. With some modifications it works fine on Ubuntu Edgy:
apt-get install libnspr4 libstdc++5 libstdc++5-3.3-dev
wget http://download.macromedia.com/pub/flashmediaserver/updates/2_0_3/linux/flashmediaserver2.tar.gz
tar xfz flashmediaserver2.tar.gz
cd FMS*
wget http://www.bluetwanger.de/~mbertheau/fms.patch
patch -p1 < fms.patch
sudo ./installFMS

Live aus der Marschrutka » Installing Flash Media Server 2 on Ubuntu 6.10 Edgy

this howto is written bei Markus Bertheau, please check the original article and his blog here.
with his great patch my installation of FMS2 on my Mac Book Pro running Ubuntu 6.10 server inside Parallels Desktop worked like a charm :-)

Technorati Tags: , ,

subversion switch

When using subversion it is sometimes neccessary to “switch” a checkout to another location.

There are different scenarios :

  1. The switch occures inside the same repository, eg. from the trunk to a branch.
    > svn switch URL [PATH]
  2. A change switches to the new location of a repositiory after the repository was moved
    > svn switch –relocate FROM TO [PATH]
  3. A switch is neccessary from a read only checkout to a writeable checkout.
    This command is often used to switch a read only svn checkout to a writeable checkout :
    > svn switch –relocate svn:// svn+ssh:// [PATH]

install Zope 2.9.3 with Python 2.4.3 on Mac OS X

install python
download python tarball of python here.

untar and change to the directory in your terminal and run config:

./configure --prefix=/opt/python-2.4.3

run make to compile the stuff:

make

and then install it:

make install

install zope

download tarball here

./configure --with-python=/opt/python-2.4.3/bin/python --prefix=/opt/zope-2.9.3
make
make install

after that you are ready to create a zope instance:

/opt/zope-2.9.3/mkzopeinstance.py