The bits of the IT world that apply to me right now. Blogged in the hope that someone (even me) will find them useful.
Tuesday, August 06, 2013
Clock synchronisation approaches
Further to my earlier thoughts about Spanner.
http://krzyzanowski.org/rutgers/notes/pdf/06-clocks.pdf
Saturday, July 06, 2013
Shared directories in Ubuntu using ACLs
A nifty article on how to use ACLs in Ubuntu to share directories effectively between user accounts.
http://brunogirin.blogspot.com.au/2010/03/shared-folders-in-ubuntu-with-setgid.html
I read in another blog on the way to the above link, that Ubuntu has a fairly prescriptive user permissions model, and I just wish they'd spell out what it is... Instead, users and administrators are left to pull together blogs, like this...
http://brunogirin.blogspot.com.au/2010/03/shared-folders-in-ubuntu-with-setgid.html
I read in another blog on the way to the above link, that Ubuntu has a fairly prescriptive user permissions model, and I just wish they'd spell out what it is... Instead, users and administrators are left to pull together blogs, like this...
Tuesday, July 02, 2013
Yahoo Pipe to Google maps integration
Yahoo Maps are a bit rubbish, so I looked for a way to easily pull together a map I don't dislike using.
The map's here; the original data's here; and the Yahoo pipe between is here.
This map is a handy reference to the Victorian state government's public register of convictions for food safety offences. It's also a nice example of how cloud services can be integrated and mixed, and matched - Yahoo does provide a map interface to this data, but their maps are terrible.
View Larger Map
The map's here; the original data's here; and the Yahoo pipe between is here.
This map is a handy reference to the Victorian state government's public register of convictions for food safety offences. It's also a nice example of how cloud services can be integrated and mixed, and matched - Yahoo does provide a map interface to this data, but their maps are terrible.
View Larger Map
Thursday, June 27, 2013
Viewing D-Link DCS-932L IP camera from Ubuntu
In a word (line) ...
avconv -r 15 -f mjpeg -i http://USERNAME:PASSWORD@IP-ADDRESS/video.cgi -i http://USERNAME:PASSWORD@IP-ADDRESS/audio.cgi -vcodec mpeg4 -f mpegts file:///dev/stdout | vlc file:///dev/stdin
Now, if only the audio didn't crash avconv, we'd be cooking with gas! The silent version is here, and seems stable.
avconv -r 15 -f mjpeg -i http://USERNAME:PASSWORD@IP-ADDRESS/video.cgi -vcodec mpeg4 -f mpegts file:///dev/stdout | vlc file:///dev/stdin
avconv -r 15 -f mjpeg -i http://USERNAME:PASSWORD@IP-ADDRESS/video.cgi -i http://USERNAME:PASSWORD@IP-ADDRESS/audio.cgi -vcodec mpeg4 -f mpegts file:///dev/stdout | vlc file:///dev/stdin
Now, if only the audio didn't crash avconv, we'd be cooking with gas! The silent version is here, and seems stable.
avconv -r 15 -f mjpeg -i http://USERNAME:PASSWORD@IP-ADDRESS/video.cgi -vcodec mpeg4 -f mpegts file:///dev/stdout | vlc file:///dev/stdin
Tuesday, February 26, 2013
SOA version mangement
I was looking for a way to not write this whole report, and fortunately, Google found this report for me. Yay! I didn't really want to write this stuff, so I'm glad I don't have to, now.
The title of "Best Practices for Artifact Versioning in Service-Oriented Systems" is pretty accurate. For the TIBCO geeks, this is required knowledge for the (deprecated) TIBCO SOA Architect qualification.
http://www.sei.cmu.edu/library/abstracts/reports/11tn009.cfm
The title of "Best Practices for Artifact Versioning in Service-Oriented Systems" is pretty accurate. For the TIBCO geeks, this is required knowledge for the (deprecated) TIBCO SOA Architect qualification.
http://www.sei.cmu.edu/library/abstracts/reports/11tn009.cfm
Labels:
EAI,
ESB,
industrialisation,
industrialization,
integration,
message bus,
service discovery,
SOA,
standards,
tibco
Wednesday, February 06, 2013
File upload and copy pattern
I was asked a different question; but then ended up with this instead. Shame to waste it...
The pattern that I've used in the past has directories like this (under some root directory like /var/lib/uploads):
/partial
/ready
/working
/success
/error
This set of directories are required for all traffic to a given recipient. Essentially, a file makes its way through the directories, from top to bottom. All directories should be on a single file system. File uploaders/clients should be able to write to /partial and /ready. File receivers/servers should be able to write to everything, except /partial.
Step 1: A file is uploaded/copied into the /partial directory; with a (globally) unique file name. This step completes when there's sufficient confidence that the file has been copied (usually that just means that the expected number of bytes has been written without an error being thrown).
Step 2: The file uploader/client moves the newly uploaded file into the /ready directory. DO NOT COPY THE FILE!!!! In general, moving/renaming a file within a file system is guaranteed to be an atomic operation, but copying is not. This signifies that the file is ready (from the perspective of the client).
Step 3: When the recipient application/process is ready to process a file in /ready, it should first move the file into its /working directory.
Step 4: When the recipient application has finished processing a file (due to completion, or error) it should move the file into the /success, or /error, directory.
Things to watch
- more than one file in the working directory is likely to indicate a failure.
- Any file in the error directory is likely to indicate a failure.
- "old" files in the partial directory indicate unsuccessful copies/uploads.
- "old" files in the ready directory indicate that processing has failed/slowed.
- "old" files in the working directory indicate a failure/ABEND.
- Make sure the file system doesn't fill.
- Archiving is not covered here; that's a different pattern.
Other notes;
- If there is more than one recipient (e.g.: a multi-process server) there should be multiple working directories (working01 working02, working03, etc. - one for each process.
- this is essentially a queue implementation with single phase commit transactions.
- You can implement exactly the same pattern using file renaming, rather than separate directories. I prefer directories.
The pattern that I've used in the past has directories like this (under some root directory like /var/lib/uploads):
/partial
/ready
/working
/success
/error
This set of directories are required for all traffic to a given recipient. Essentially, a file makes its way through the directories, from top to bottom. All directories should be on a single file system. File uploaders/clients should be able to write to /partial and /ready. File receivers/servers should be able to write to everything, except /partial.
Step 1: A file is uploaded/copied into the /partial directory; with a (globally) unique file name. This step completes when there's sufficient confidence that the file has been copied (usually that just means that the expected number of bytes has been written without an error being thrown).
Step 2: The file uploader/client moves the newly uploaded file into the /ready directory. DO NOT COPY THE FILE!!!! In general, moving/renaming a file within a file system is guaranteed to be an atomic operation, but copying is not. This signifies that the file is ready (from the perspective of the client).
Step 3: When the recipient application/process is ready to process a file in /ready, it should first move the file into its /working directory.
Step 4: When the recipient application has finished processing a file (due to completion, or error) it should move the file into the /success, or /error, directory.
Things to watch
- more than one file in the working directory is likely to indicate a failure.
- Any file in the error directory is likely to indicate a failure.
- "old" files in the partial directory indicate unsuccessful copies/uploads.
- "old" files in the ready directory indicate that processing has failed/slowed.
- "old" files in the working directory indicate a failure/ABEND.
- Make sure the file system doesn't fill.
- Archiving is not covered here; that's a different pattern.
Other notes;
- If there is more than one recipient (e.g.: a multi-process server) there should be multiple working directories (working01 working02, working03, etc. - one for each process.
- this is essentially a queue implementation with single phase commit transactions.
- You can implement exactly the same pattern using file renaming, rather than separate directories. I prefer directories.
Labels:
EAI,
filesystem,
ftp,
integration,
Linux,
message bus,
script,
server
Tuesday, November 27, 2012
Google Spanner reflections
Google Spanner (warning: PDF) has made some noise recently, and I got around to giving their paper a quick read. I was happy to discover that it describes a solution to a problem I've been thinking about for awhile. I was happy to read that my musing were heading in the right direction. The key (as the Googlers are at pains to point out, and I was also considering) is how to handle distributed co-ordination of commits (in a scalable manner).
Spanner introduces the concept of tracking time by a combination of instants, intervals, and assertions about the two - on the understanding that there's uncertainty of the "current" time. As I read through the paper, I tend to think that there's no particular need for atomic and GPS clocks (although they're definitely desirable); so long as the confidence in the current time can be established. The effect of rising uncertainty in the current time would be a reduction in performance, I imagine...
It turns out that the venerable NTP protocol is able to provide measures of uncertainty; so one could re-implement Spanner without atomic clocks (at least, initially), and could then assault the various questions of electing "leaders" and manging reads and writes in a scalable manner.
Apache Zookeeper is the first thought for the leader election, but they talk about clusters of 4 machines being a large deployment, and about "within this data centre", etc. Let's reserve Zookeeper for a use case that fits better; something without Spanner's global ambitions. Spanner's architecture means that this is a key real concern. A closer reading of the paper is necessary to figure out what's involved here; and how it intimately it's related to uncertain timing.
The distributed reads and writes problem does look a bit like Ceph...
Spanner may not be so intractable, after all.
Spanner introduces the concept of tracking time by a combination of instants, intervals, and assertions about the two - on the understanding that there's uncertainty of the "current" time. As I read through the paper, I tend to think that there's no particular need for atomic and GPS clocks (although they're definitely desirable); so long as the confidence in the current time can be established. The effect of rising uncertainty in the current time would be a reduction in performance, I imagine...
It turns out that the venerable NTP protocol is able to provide measures of uncertainty; so one could re-implement Spanner without atomic clocks (at least, initially), and could then assault the various questions of electing "leaders" and manging reads and writes in a scalable manner.
Apache Zookeeper is the first thought for the leader election, but they talk about clusters of 4 machines being a large deployment, and about "within this data centre", etc. Let's reserve Zookeeper for a use case that fits better; something without Spanner's global ambitions. Spanner's architecture means that this is a key real concern. A closer reading of the paper is necessary to figure out what's involved here; and how it intimately it's related to uncertain timing.
The distributed reads and writes problem does look a bit like Ceph...
Spanner may not be so intractable, after all.
Location:
Melbourne VIC, Australia
Tuesday, May 22, 2012
VMware player 4.0.3 on Ubuntu 12.04
VMware player has some well-known issues with setting up the network for player under Ubuntu 12.04 (that is, where Ubuntu is the host OS).
With one small change, I followed the great instructions here: http://www.kartook.com/2012/05/vmware-virtual-network-device-unable-to-loadcompile-vm-player-4-0-2-in-ubuntu-12-04/
The change is that the script you download has the recognised version numbers hardcoded in the header.
Before you run the script (patch-modules_3.2.0.sh), open the file using your preferred text editor, and change the 4.0.2 to 4.0.3, so it looks like:
plreqver=4.0.3
The script (and VMware player) seems to run fine for VMware Player 4.0.3 on Ubuntu 12.04. If it should make a difference, I'm running x86_64 Ubuntu 12.04.
With one small change, I followed the great instructions here: http://www.kartook.com/2012/05/vmware-virtual-network-device-unable-to-loadcompile-vm-player-4-0-2-in-ubuntu-12-04/
The change is that the script you download has the recognised version numbers hardcoded in the header.
Before you run the script (patch-modules_3.2.0.sh), open the file using your preferred text editor, and change the 4.0.2 to 4.0.3, so it looks like:
plreqver=4.0.3
The script (and VMware player) seems to run fine for VMware Player 4.0.3 on Ubuntu 12.04. If it should make a difference, I'm running x86_64 Ubuntu 12.04.
Wednesday, March 28, 2012
Empty an Oracle schema, leave an empty schema
What it says on the tin. Sufficient code analysis will reveal that some bizarre schema dependencies may not be destroyed by this; but experience will show that's not actually a problem :-)
The code lives as a gist over on github. A snapshot is below, for simplicity:
The code lives as a gist over on github. A snapshot is below, for simplicity:
set echo off
set verify off
set serveroutput on size 100000
-- Hosted at http://lastinfinitetentacle.blogspot.com/2012/03/empty-oracle-schema-leave-empty-schema.html
-- Disable all contraints
BEGIN
FOR c IN
(SELECT c.owner, c.table_name, c.constraint_name
FROM user_constraints c, user_tables t
WHERE c.table_name = t.table_name
AND c.status = 'ENABLED'
ORDER BY c.constraint_type DESC)
LOOP
dbms_utility.exec_ddl_statement('alter table ' || c.owner || '.' || c.table_name || ' disable constraint ' || c.constraint_name);
END LOOP;
END;
/
-- remove all objects
declare
cursor dropObjectsCusor is
select 'drop ' || object_type || ' ' || object_name as sqlDropStmt
from user_objects
where object_type <> 'TABLE' and object_type <> 'INDEX'
order by object_type;
cursor dropTablesCusor is
select 'truncate table ' || object_name as sqlTruncTbl,
'drop table ' || object_name || ' cascade constraints' as sqlDropTbl
from user_objects
where object_type = 'TABLE'
order by object_type;
begin
for ob in dropTablesCusor
loop
begin
execute immediate ob.sqlTruncTbl;
exception when others then dbms_output.put_line('Could not truncate a table.');
end;
begin
execute immediate ob.sqlDropTbl;
exception when others then dbms_output.put_line('Could not drop a table.');
end;
end loop;
for ob in dropObjectsCusor
loop
begin
execute immediate ob.sqlDropStmt;
exception when others then dbms_output.put_line('Could not drop some object.');
end;
end loop;
end;
/
purge recyclebin;
Monday, October 17, 2011
CSV parser in JavaScript
I wanted a JavaScript based CSV parser. I couldn't find a good one (that would allow multi-character delimiters, and text qualifiers), so I wrote it. The textToArray function should run under any js implementation; but the demonstration of it is written for a ringojs environment.
Call textToArray with a line of delimited text, and the delimiter and text qualifier you're expecting to find; it will give back an array of the elements it finds.
Call textToArray with a line of delimited text, and the delimiter and text qualifier you're expecting to find; it will give back an array of the elements it finds.
var textToArray = function (txtLine, del, txtQual) {
"use strict";
var datArr = [], newStr = "";
while (txtLine.length > 0) {
if (txtLine.substr(0, txtQual.length) === txtQual) {
// get quoted block
newStr = txtLine.substr(0, txtQual.length + txtLine.indexOf(txtQual, txtQual.length));
datArr.push(newStr.substr(txtQual.length, newStr.length - txtQual.length * 2));
}
else {
// get data block
if (txtLine.indexOf(del) !== -1) {
newStr = txtLine.substr(0, txtLine.indexOf(del));
} else {
newStr = txtLine;
}
datArr.push(newStr);
}
txtLine = txtLine.substr(newStr.length + del.length, txtLine.length);
}
return datArr;
};
var fs = require('fs');
var con = require('console');
var del = ";;";
var txtQual = "\"\""; // a pair of quotes.
var file = fs.open('D:/ringojs-0.8/test.txt');
var line = "";
for (line in file) {
con.log(textToArray(line, del, txtQual).join("---"));
}
Subscribe to:
Posts (Atom)