[Zope-dev] ReiserStorage 0.01 alpha

Petru Paler ppetru@coltronix.com
Tue, 6 Jun 2000 21:13:16 +0300 (EEST)


  This message is in MIME format.  The first part should be readable text,
  while the remaining parts are likely unreadable without MIME-aware tools.
  Send mail to mime@docserver.cac.washington.edu for more info.

---1463811836-186350100-960315196=:16066
Content-Type: TEXT/PLAIN; charset=US-ASCII

          Hello all,

   Attached you can find the code for a preliminary ZODB storage manager
which is designed to take adventage of the reiserfs filesystem
(http://devlinux.com/namesys). While it is usable on other filesystems
too, the performance will decrease as the number of objects in your
database increases.
   Comments:

1. This is as alpha as it can be. While it is usable to do some testing on
a spare Zope, you must be insane to even try to use this on a production
system.
2. A generic DirectoryStorage is comming soon, with the diference being
splitting files by directory (and, of course, being slower than the
reiserfs version).
3. As you can see in the source, I/O errors in critical points can corrupt
the storage.
4. It currently does not support versioning and undo. I'm working first on
getting it stable and fast, and then add these features.

Feedback is not only welcome, but wanted :)

-Petru

---1463811836-186350100-960315196=:16066
Content-Type: TEXT/PLAIN; charset=US-ASCII; name="ReiserStorage.py"
Content-Transfer-Encoding: BASE64
Content-ID: <Pine.LNX.4.10.10006062113160.16066@oliver.local.coltronix.com>
Content-Description: 
Content-Disposition: attachment; filename="ReiserStorage.py"

IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIA0KIyBab3Bl
IFB1YmxpYyBMaWNlbnNlIChaUEwpIFZlcnNpb24gMS4wDQojIC0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgDQojIENvcHlyaWdo
dCAoYykgRGlnaXRhbCBDcmVhdGlvbnMuICBBbGwgcmlnaHRzIHJlc2VydmVk
Lg0KIyBDb3B5cmlnaHQgKGMpIDIwMDAgUGV0cnUgUGFsZXIgKHBwZXRydUBj
b2x0cm9uaXguY29tKSBBbGwgcmlnaHRzIHJlc2VydmVkLg0KIyANCiMgVGhp
cyBsaWNlbnNlIGhhcyBiZWVuIGNlcnRpZmllZCBhcyBPcGVuIFNvdXJjZSh0
bSkuDQojIA0KIyBSZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBh
bmQgYmluYXJ5IGZvcm1zLCB3aXRoIG9yIHdpdGhvdXQNCiMgbW9kaWZpY2F0
aW9uLCBhcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2lu
ZyBjb25kaXRpb25zIGFyZQ0KIyBtZXQ6DQojIA0KIyAxLiBSZWRpc3RyaWJ1
dGlvbnMgaW4gc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNv
cHlyaWdodA0KIyAgICBub3RpY2UsIHRoaXMgbGlzdCBvZiBjb25kaXRpb25z
LCBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLg0KIyANCiMgMi4gUmVk
aXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRo
ZSBhYm92ZSBjb3B5cmlnaHQNCiMgICAgbm90aWNlLCB0aGlzIGxpc3Qgb2Yg
Y29uZGl0aW9ucywgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbg0K
IyAgICB0aGUgZG9jdW1lbnRhdGlvbiBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxz
IHByb3ZpZGVkIHdpdGggdGhlDQojICAgIGRpc3RyaWJ1dGlvbi4NCiMgDQoj
IDMuIERpZ2l0YWwgQ3JlYXRpb25zIHJlcXVlc3RzIHRoYXQgYXR0cmlidXRp
b24gYmUgZ2l2ZW4gdG8gWm9wZQ0KIyAgICBpbiBhbnkgbWFubmVyIHBvc3Np
YmxlLiBab3BlIGluY2x1ZGVzIGEgIlBvd2VyZWQgYnkgWm9wZSINCiMgICAg
YnV0dG9uIHRoYXQgaXMgaW5zdGFsbGVkIGJ5IGRlZmF1bHQuIFdoaWxlIGl0
IGlzIG5vdCBhIGxpY2Vuc2UNCiMgICAgdmlvbGF0aW9uIHRvIHJlbW92ZSB0
aGlzIGJ1dHRvbiwgaXQgaXMgcmVxdWVzdGVkIHRoYXQgdGhlDQojICAgIGF0
dHJpYnV0aW9uIHJlbWFpbi4gQSBzaWduaWZpY2FudCBpbnZlc3RtZW50IGhh
cyBiZWVuIHB1dA0KIyAgICBpbnRvIFpvcGUsIGFuZCB0aGlzIGVmZm9ydCB3
aWxsIGNvbnRpbnVlIGlmIHRoZSBab3BlIGNvbW11bml0eQ0KIyAgICBjb250
aW51ZXMgdG8gZ3Jvdy4gVGhpcyBpcyBvbmUgd2F5IHRvIGFzc3VyZSB0aGF0
IGdyb3d0aC4NCiMgDQojIDQuIEFsbCBhZHZlcnRpc2luZyBtYXRlcmlhbHMg
YW5kIGRvY3VtZW50YXRpb24gbWVudGlvbmluZw0KIyAgICBmZWF0dXJlcyBk
ZXJpdmVkIGZyb20gb3IgdXNlIG9mIHRoaXMgc29mdHdhcmUgbXVzdCBkaXNw
bGF5DQojICAgIHRoZSBmb2xsb3dpbmcgYWNrbm93bGVkZ2VtZW50Og0KIyAN
CiMgICAgICAiVGhpcyBwcm9kdWN0IGluY2x1ZGVzIHNvZnR3YXJlIGRldmVs
b3BlZCBieSBEaWdpdGFsIENyZWF0aW9ucw0KIyAgICAgIGZvciB1c2UgaW4g
dGhlIFogT2JqZWN0IFB1Ymxpc2hpbmcgRW52aXJvbm1lbnQNCiMgICAgICAo
aHR0cDovL3d3dy56b3BlLm9yZy8pLiINCiMgDQojICAgIEluIHRoZSBldmVu
dCB0aGF0IHRoZSBwcm9kdWN0IGJlaW5nIGFkdmVydGlzZWQgaW5jbHVkZXMg
YW4NCiMgICAgaW50YWN0IFpvcGUgZGlzdHJpYnV0aW9uICh3aXRoIGNvcHly
aWdodCBhbmQgbGljZW5zZSBpbmNsdWRlZCkNCiMgICAgdGhlbiB0aGlzIGNs
YXVzZSBpcyB3YWl2ZWQuDQojIA0KIyA1LiBOYW1lcyBhc3NvY2lhdGVkIHdp
dGggWm9wZSBvciBEaWdpdGFsIENyZWF0aW9ucyBtdXN0IG5vdCBiZSB1c2Vk
IHRvDQojICAgIGVuZG9yc2Ugb3IgcHJvbW90ZSBwcm9kdWN0cyBkZXJpdmVk
IGZyb20gdGhpcyBzb2Z0d2FyZSB3aXRob3V0DQojICAgIHByaW9yIHdyaXR0
ZW4gcGVybWlzc2lvbiBmcm9tIERpZ2l0YWwgQ3JlYXRpb25zLg0KIyANCiMg
Ni4gTW9kaWZpZWQgcmVkaXN0cmlidXRpb25zIG9mIGFueSBmb3JtIHdoYXRz
b2V2ZXIgbXVzdCByZXRhaW4NCiMgICAgdGhlIGZvbGxvd2luZyBhY2tub3ds
ZWRnbWVudDoNCiMgDQojICAgICAgIlRoaXMgcHJvZHVjdCBpbmNsdWRlcyBz
b2Z0d2FyZSBkZXZlbG9wZWQgYnkgRGlnaXRhbCBDcmVhdGlvbnMNCiMgICAg
ICBmb3IgdXNlIGluIHRoZSBaIE9iamVjdCBQdWJsaXNoaW5nIEVudmlyb25t
ZW50DQojICAgICAgKGh0dHA6Ly93d3cuem9wZS5vcmcvKS4iDQojIA0KIyAg
ICBJbnRhY3QgKHJlLSlkaXN0cmlidXRpb25zIG9mIGFueSBvZmZpY2lhbCBa
b3BlIHJlbGVhc2UgZG8gbm90DQojICAgIHJlcXVpcmUgYW4gZXh0ZXJuYWwg
YWNrbm93bGVkZ2VtZW50Lg0KIyANCiMgNy4gTW9kaWZpY2F0aW9ucyBhcmUg
ZW5jb3VyYWdlZCBidXQgbXVzdCBiZSBwYWNrYWdlZCBzZXBhcmF0ZWx5IGFz
DQojICAgIHBhdGNoZXMgdG8gb2ZmaWNpYWwgWm9wZSByZWxlYXNlcy4gIERp
c3RyaWJ1dGlvbnMgdGhhdCBkbyBub3QNCiMgICAgY2xlYXJseSBzZXBhcmF0
ZSB0aGUgcGF0Y2hlcyBmcm9tIHRoZSBvcmlnaW5hbCB3b3JrIG11c3QgYmUg
Y2xlYXJseQ0KIyAgICBsYWJlbGVkIGFzIHVub2ZmaWNpYWwgZGlzdHJpYnV0
aW9ucy4gIE1vZGlmaWNhdGlvbnMgd2hpY2ggZG8gbm90DQojICAgIGNhcnJ5
IHRoZSBuYW1lIFpvcGUgbWF5IGJlIHBhY2thZ2VkIGluIGFueSBmb3JtLCBh
cyBsb25nIGFzIHRoZXkNCiMgICAgY29uZm9ybSB0byBhbGwgb2YgdGhlIGNs
YXVzZXMgYWJvdmUuDQojIA0KIyANCiMgRGlzY2xhaW1lcg0KIyANCiMgICBU
SElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIERJR0lUQUwgQ1JFQVRJT05T
IGBgQVMgSVMnJyBBTkQgQU5ZDQojICAgRVhQUkVTU0VEIE9SIElNUExJRUQg
V0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRI
RQ0KIyAgIElNUExJRUQgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkg
QU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUg0KIyAgIFBVUlBPU0UgQVJF
IERJU0NMQUlNRUQuICBJTiBOTyBFVkVOVCBTSEFMTCBESUdJVEFMIENSRUFU
SU9OUyBPUiBJVFMNCiMgICBDT05UUklCVVRPUlMgQkUgTElBQkxFIEZPUiBB
TlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwNCiMgICBTUEVDSUFM
LCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFUyAoSU5DTFVE
SU5HLCBCVVQgTk9UDQojICAgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0Yg
U1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUzsgTE9TUyBPRg0KIyAgIFVT
RSwgREFUQSwgT1IgUFJPRklUUzsgT1IgQlVTSU5FU1MgSU5URVJSVVBUSU9O
KSBIT1dFVkVSIENBVVNFRCBBTkQNCiMgICBPTiBBTlkgVEhFT1JZIE9GIExJ
QUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElU
WSwNCiMgICBPUiBUT1JUIChJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhF
UldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQNCiMgICBPRiBUSEUgVVNF
IE9GIFRISVMgU09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9T
U0lCSUxJVFkgT0YNCiMgICBTVUNIIERBTUFHRS4NCiMgDQojIA0KIyBUaGlz
IHNvZnR3YXJlIGNvbnNpc3RzIG9mIGNvbnRyaWJ1dGlvbnMgbWFkZSBieSBE
aWdpdGFsIENyZWF0aW9ucyBhbmQNCiMgbWFueSBpbmRpdmlkdWFscyBvbiBi
ZWhhbGYgb2YgRGlnaXRhbCBDcmVhdGlvbnMuICBTcGVjaWZpYw0KIyBhdHRy
aWJ1dGlvbnMgYXJlIGxpc3RlZCBpbiB0aGUgYWNjb21wYW55aW5nIGNyZWRp
dHMgZmlsZS4NCiMgDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
IyMNCg0KDQojIFRvLWRvIGxpc3Q6DQojIENyaXRpY2FsOg0KIyAgICAtIE1v
c3QgSS9PIG9wZXJhdGlvbnMgYXJlIG5vdCBhdG9taWMuIFRoaXMgbWVhbnMg
dGhhdCBJL08gZXJyb3JzIChhbmQsIGZvcg0KIyAgICB0aGF0IG1hdHRlciwg
YW55IGV4Y2VwdGlvbnMgb2NjdXJlZCBpbiBfZmluaXNoKSBsZWF2ZSB0aGUg
c3RvcmFnZSBpbiBhbg0KIyAgICB1bmRlZmluZWQgc3RhdGUNCiMNCiMgTm90
IGNyaXRpY2FsOg0KIyAgICAtIFBlcmZvcm1hbmNlIHR1bmluZyAtLSBhZGQg
Y2FjaGVzIHdoZXJlIGFwcm9waWF0ZQ0KIyAgICAtIG1ha2Ugc3VyZSBsb2Nr
aW5nIGlzIG9rDQojICAgIC0gcHJvdmlkZSBkaXJlY3Rvcnkgc3BsaXR0aW5n
IHRvIGVuYWJsZSB1c2Ugb24gbm9uLXJlaXNlciBmaWxlc3lzdGVtcw0KIw0K
IyAuLi4gYW5kIHByb2JhYmx5IG1hbnkgb3RoZXJzDQoNCiIiIlJlaXNlckZT
IHN0b3JhZ2UiIiINCg0KX192ZXJzaW9uX18gPSAiMC4wMSINCg0KZnJvbSBC
YXNlU3RvcmFnZSBpbXBvcnQgQmFzZVN0b3JhZ2UNCmltcG9ydCBQT1NFeGNl
cHRpb24NCmltcG9ydCBvcywgc3RydWN0LCBzdGF0LCBvcGVyYXRvcg0KZnJv
bSBwb3NpeCBpbXBvcnQgZnN5bmMNCg0KZGVmIG9pZDJzdHIob2lkKToNCgly
ZXR1cm4gIiUwMlgiKjggJSBzdHJ1Y3QudW5wYWNrKCIhOEIiLCBvaWQpDQoN
CmNsYXNzIFJlaXNlclN0b3JhZ2UoQmFzZVN0b3JhZ2UpOg0KDQoJZGVmIF9f
aW5pdF9fKHNlbGYsIGRpcm5hbWUpOg0KCQkNCgkJaWYgZGlybmFtZVstMV0g
IT0gJy8nOg0KCQkJZGlybmFtZSA9IGRpcm5hbWUgKyAnLycNCgkJQmFzZVN0
b3JhZ2UuX19pbml0X18oc2VsZiwgZGlybmFtZSkNCgkJc2VsZi5fb2lkX2Rp
ciA9IGRpcm5hbWUgKyAnb2lkLycNCgkJc2VsZi5fdGluZGV4ID0gW10NCgkJ
c2VsZi5fb2lkID0gJ1wwXDBcMFwwXDBcMFwwXDAnDQoJCXRyeToNCgkJCWYg
PSBvcGVuKGRpcm5hbWUrJ2xhc3Rfb2lkJywgJ3J0JykNCgkJCXNlbGYuX29p
ZCA9IGYucmVhZCgpDQoJCQlmLmNsb3NlKCkNCgkJZXhjZXB0Og0KCQkJcGFz
cw0KCQlzZWxmLmxvZiA9IG9wZW4oZGlybmFtZSsnbGFzdF9vaWQnLCAnd3Qn
KQ0KDQoJZGVmIF9fbGVuX18oc2VsZik6DQoJCXByaW50ICdfX2xlbl9fJw0K
CQlyZXR1cm4gbGVuKG9zLmxpc3RkaXIoc2VsZi5fb2lkX2RpcikpDQoNCglk
ZWYgZ2V0U2l6ZShzZWxmKToNCgkJcHJpbnQgJ2dldFNpemUnDQoJCWZpbGVz
ID0gb3MubGlzdGRpcihzZWxmLl9vaWRfZGlyKQ0KCQlmaWxlcyA9IG1hcChs
YW1iZGEgeCxkPXNlbGYuX29pZF9kaXI6IGQreCwgZmlsZXMpDQoJCXNpemVz
ID0gbWFwKGxhbWJkYSB4OiBvcy5zdGF0KHgpW3N0YXQuU1RfU0laRV0sIGZp
bGVzKQ0KCQlyZXR1cm4gcmVkdWNlKG9wZXJhdG9yLmFkZCwgc2l6ZXMpDQoN
CglkZWYgbG9hZChzZWxmLCBvaWQsIHZlcnNpb24pOg0KCQlzZWxmLl9sb2Nr
X2FjcXVpcmUoKQ0KCQl0cnk6DQoJCQlmID0gb3BlbihzZWxmLl9vaWRfZGly
K29pZDJzdHIob2lkKSwgJ3JiJykNCgkJCXAgPSBmLnJlYWQoKQ0KCQkJZi5j
bG9zZSgpDQoJCQlyZXR1cm4gcFs4Ol0sIHBbOjhdDQoJCWZpbmFsbHk6DQoJ
CQlzZWxmLl9sb2NrX3JlbGVhc2UoKQ0KDQoJZGVmIHN0b3JlKHNlbGYsIG9p
ZCwgc2VyaWFsLCBkYXRhLCB2ZXJzaW9uLCB0cmFuc2FjdGlvbik6DQoJCWlm
IHRyYW5zYWN0aW9uIGlzIG5vdCBzZWxmLl90cmFuc2FjdGlvbjoNCgkJCXJh
aXNlIFBPU0V4Y2VwdGlvbi5TdG9yYWdlVHJhbnNhY3Rpb25FcnJvcihzZWxm
LCB0cmFuc2FjdGlvbikNCg0KCQlpZiB2ZXJzaW9uOg0KCQkJcmFpc2UgUE9T
RXhjZXB0aW9uLlVuc3VwcG9ydGVkLCAiVmVyc2lvbnMgYXJlbid0IHN1cHBv
cnRlZCINCg0KCQlzZWxmLl9sb2NrX2FjcXVpcmUoKQ0KCQl0cnk6DQoJCQlm
bmFtZSA9IHNlbGYuX29pZF9kaXIrb2lkMnN0cihvaWQpDQoJCQlpZiBvcy5w
YXRoLmV4aXN0cyhmbmFtZSk6DQoJCQkJdHJ5Og0KCQkJCQlmID0gb3Blbihm
bmFtZSwgJ3JiJykNCgkJCQkJaWYgc2VyaWFsICE9IGYucmVhZCg4KToNCgkJ
CQkJCXJhaXNlIFBPU0V4Y2VwdGlvbi5Db25mbGljdEVycm9yDQoJCQkJCWYu
Y2xvc2UoKQ0KCQkJCWV4Y2VwdCBJT0Vycm9yOg0KCQkJCQlyYWlzZSBQT1NF
eGNlcHRpb24uU3RvcmFnZVN5c3RlbUVycm9yLCAnSS9PIGVycm9yIHdoaWxl
IGNoZWNraW5nIGZvciBjb25mbGljdHMnDQoJCQlzZXJpYWwgPSBzZWxmLl9z
ZXJpYWwNCgkJCXNlbGYuX3RpbmRleC5hcHBlbmQoKG9pZCwgc2VyaWFsK2Rh
dGEpKQ0KCQlmaW5hbGx5Og0KCQkJc2VsZi5fbG9ja19yZWxlYXNlKCkNCg0K
CQlyZXR1cm4gc2VyaWFsDQoNCglkZWYgX2JlZ2luKHNlbGYsIHRpZCwgdSwg
ZCwgZSk6DQoJCXBhc3MNCg0KCWRlZiBfY2xlYXJfdGVtcChzZWxmKToNCgkJ
c2VsZi5fdGluZGV4ID0gW10NCg0KCWRlZiBfZmluaXNoKHNlbGYsIHRpZCwg
dXNlciwgZGVzYywgZXh0KToNCgkJdHJ5Og0KCQkJZm9yIG9pZCwgZGF0YSBp
biBzZWxmLl90aW5kZXg6DQoJCQkJZiA9IG9wZW4oc2VsZi5fb2lkX2Rpcitv
aWQyc3RyKG9pZCksICd3YicpDQoJCQkJZi53cml0ZShkYXRhKQ0KCQkJCWZz
eW5jKGYuZmlsZW5vKCkpDQoJCQkJZi5jbG9zZSgpDQoJCQlzZWxmLmxvZi5z
ZWVrKDApDQoJCQlzZWxmLmxvZi53cml0ZShzZWxmLl9vaWQpDQoJCQlmc3lu
YyhzZWxmLmxvZi5maWxlbm8oKSkNCgkJZXhjZXB0Og0KCQkJcmFpc2UgUE9T
RXhjZXB0aW9uLlRyYW5zYWN0aW9uRXJyb3IsICdJL08gZXJyb3IgY29tbWl0
aW5nIHRyYW5zYWN0aW9uIC0tIHlvdXIgc3RvcmFnZSBpcyBsaWtlbHkgY29y
cnVwdCcNCg0KCWRlZiBwYWNrKHNlbGYsIHQsIHJlZmVyZW5jZXNmKToNCgkJ
bWF4b2lkID0gb2lkMnN0cihzZWxmLl9vaWQpDQoNCgkJcm9vdGwgPSBbJ1ww
XDBcMFwwXDBcMFwwXDAnXQ0KCQlwb3AgPSByb290bC5wb3ANCgkJcGluZGV4
ID0ge30NCgkJcmVmZXJlbmNlZCA9IHBpbmRleC5oYXNfa2V5DQoJCXdoaWxl
IHJvb3RsOg0KCQkJb2lkID0gcG9wKCkNCgkJCWlmIHJlZmVyZW5jZWQob2lk
KToNCgkJCQljb250aW51ZQ0KDQoJCQkjIHNjYW4gcGlja2xlIGZvciByZWZl
cmVuY2VzDQoJCQlmID0gb3BlbihzZWxmLl9vaWRfZGlyK29pZDJzdHIob2lk
KSkNCgkJCXIgPSBmLnJlYWQoKQ0KCQkJZi5jbG9zZSgpDQoJCQlwaW5kZXhb
b2lkMnN0cihvaWQpXSA9IHINCgkJCXAgPSByWzg6XQ0KCQkJcmVmZXJlbmNl
c2YocCwgcm9vdGwpDQoNCgkJIyBub3cgZGVsZXRlIGFueSB1bnJlZmVyZW5j
ZWQgZW50cmllcw0KCQlkZWxldGVkID0gW10NCgkJZm9yIG9pZCBpbiBvcy5s
aXN0ZGlyKHNlbGYuX29pZF9kaXIpOg0KCQkJaWYgbm90IHJlZmVyZW5jZWQo
b2lkKSBhbmQgKG9pZCA8PSBtYXhvaWQpOg0KCQkJCWRlbGV0ZWQuYXBwZW5k
KG9pZCkNCg0KCQl0cnk6DQoJCQlmb3IgaSBpbiBkZWxldGVkOg0KCQkJCW9z
LnVubGluayhzZWxmLl9vaWRfZGlyK2kpDQoJCWV4Y2VwdDoNCgkJCXJhaXNl
IFBPU0V4Y2VwdGlvbi5UcmFuc2FjdGlvbkVycm9yLCAnSS9PIGVycm9yIGR1
cmluZyBwYWNrIC0tIHlvdXIgc3RvcmFnZSBpcyBwcm9iYWJseSBzY3Jld2Vk
IHVwJw0KDQo=
---1463811836-186350100-960315196=:16066--