Help
RSS
API
Feed
Maltego
Contact
Domain > sukhanov.net
×
More information on this domain is in
AlienVault OTX
Is this malicious?
Yes
No
DNS Resolutions
Date
IP Address
2024-03-19
18.155.129.100
(
ClassC
)
2025-11-03
3.169.173.79
(
ClassC
)
Port 80
HTTP/1.1 301 Moved PermanentlyServer: CloudFrontDate: Mon, 03 Nov 2025 01:04:33 GMTContent-Type: text/htmlContent-Length: 167Connection: keep-aliveLocation: https://sukhanov.net/X-Cache: Redirect from cloudfrontVia: 1.1 5ec2b95241693f962e2ff4afc726b38e.cloudfront.net (CloudFront)X-Amz-Cf-Pop: HIO52-P4X-Amz-Cf-Id: Vcyt8wN07MeOeO8AixR_MflBfVWNPsdZ6LEoaeRXE05BIe7dR-HBMg html>head>title>301 Moved Permanently/title>/head>body>center>h1>301 Moved Permanently/h1>/center>hr>center>CloudFront/center>/body>/html>
Port 443
HTTP/1.1 200 OKContent-Type: text/htmlContent-Length: 93048Connection: keep-aliveLast-Modified: Sun, 13 Jun 2021 17:42:22 GMTx-amz-server-side-encryption: AES256Accept-Ranges: bytesServer: AmazonS3Date: Mon, 03 Nov 2025 00:42:24 GMTETag: 7682c41020dae9de5877f62f93d589afX-Cache: Hit from cloudfrontVia: 1.1 5f7d374d92b73172fce43b7879076d1c.cloudfront.net (CloudFront)X-Amz-Cf-Pop: HIO52-P4X-Amz-Cf-Id: YtEC6pv_0UKBxd5y8l9auf6z0dL_sMiDnBBG7qO0pdwqgkY-W4dkCgAge: 1329 !DOCTYPE html PUBLIC -//W3C//DTD XHTML 1.0 Transitional//EN http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd>html xmlnshttp://www.w3.org/1999/xhtml langen xml:langen> head> meta http-equivContent-Type contenttext/html; charsetutf-8 /> title>sukhanov.net/title> style typetext/css mediaall>@import url(./theme/style.css);/style> style typetext/css mediaall>@import url(./theme/fruity.css);/style> link hrefhttp://sukhanov.net/feeds/all.atom.xml typeapplication/atom+xml relalternate titlesukhanov.net Full Atom Feed /> /head> body> div idmaincontainer> div idtopsection> div classinnertube> h1>/h1> /div> /div> div idcontentwrapper> div idcontentcolumn> div classinnertube> div classcontent> span classsubject>a href./practical-event-sourcing-with-sql-postgres.html relbookmark titlePermalink to Practical Event Sourcing with SQL (Postgres)>Practical Event Sourcing with SQL (Postgres)/a>/span> br/> p>Event sourcing is an excellent software design pattern. Instead of persisting current state of an asset and mutating itin place. An asset is represented by the events through its life cycle. When the current state of an asset is neededits re-computed from the events./p>p>Despite being a great way to solve many problems its somewhat scarcely applied. There are undoubtedly many reason forthis, but personally I suspect part of the problem is lack of good examples of how to use it. Ive seen plenty ofsoftware engineers understand the theory and utility of Event Sourcing but struggle with implementation there of. Itdoesnt need to be this way. Event Sourcing can be implemented in common relational databases such as postgres andmysql. The database schemas of Event Sourcing implementations dont vary all that much and as a result by masteringcouple of building blocks, Event Sourcing becomes approachable./p>h2>Quick primer to event sourcing theory/h2>p>A quick example of event sourcing. Consider a data schema to represent a book tracking system at a library:/p>table>thead>tr>th alignleft>Book/th>th alignleft>Status/th>th alignleft>Date/th>th alignleft>Member/th>/tr>/thead>tbody>tr>td alignleft>Humiliated and Insulted/td>td alignleft>Checked Out/td>td alignleft>2021-02-12/td>td alignleft>Alice/td>/tr>tr>td alignleft>Crime and Punishment/td>td alignleft>Checked Out/td>td alignleft>2021-01-11/td>td alignleft>Bob/td>/tr>tr>td alignleft>The Idiot/td>td alignleft>Checked In/td>td alignleft>2002-12-02/td>td alignleft>Mallory/td>/tr>/tbody>/table>p>We can mutate assets in place. And so if Eve was to check out The Idiot the stored data in the database would now looklike:/p>table>thead>tr>th alignleft>Book/th>th alignleft>Status/th>th alignleft>Date/th>th alignleft>Member/th>/tr>/thead>tbody>tr>td alignleft>Humiliated and Insulted/td>td alignleft>Checked Out/td>td alignleft>2021-02-12/td>td alignleft>Alice/td>/tr>tr>td alignleft>Crime and Punishment/td>td alignleft>Checked Out/td>td alignleft>2021-01-11/td>td alignleft>Bob/td>/tr>tr>td alignleft>The Idiot/td>td alignleft>strong>Checked Out/strong>/td>td alignleft>strong>2021-02-22/strong>/td>td alignleft>strong>Eve/strong>/td>/tr>/tbody>/table>p>By storing data in such a way, it possible to deduce answers to following questions:/p>ul>li>What is the state of a particular book, is it checked out?/li>li>Who checked out the book last/li>li>When was the last time the book was checked out/li>/ul>p>To convert this library system example to an Event Source model. The schema barely needs to change, simply drop theUnique constraint on Book column. The difference lies in how the table used. Specifically how data is added and readout is with how add and read data. Well deal with how read is different later, for now Storage. Storage is different inthat records are not modified but a new one is appended instead./p>p>Post Eves transaction the data will look as follows, note that the Idiot is now duplicated:/p>table>thead>tr>th alignleft>Book/th>th alignleft>Status/th>th alignleft>Date/th>th alignleft>Member/th>/tr>/thead>tbody>tr>td alignleft>strong>The Idiot/strong>/td>td alignleft>strong>Checked Out/strong>/td>td alignleft>strong>2021-02-22/strong>/td>td alignleft>strong>Eve/strong>/td>/tr>tr>td alignleft>Humiliated and Insulted/td>td alignleft>Checked Out/td>td alignleft>2021-02-12/td>td alignleft>Alice/td>/tr>tr>td alignleft>Crime and Punishment/td>td alignleft>Checked Out/td>td alignleft>2021-01-11/td>td alignleft>Bob/td>/tr>tr>td alignleft>The Idiot/td>td alignleft>Checked In/td>td alignleft>2002-12-02/td>td alignleft>Mallory/td>/tr>/tbody>/table>p>By using event sourcing we can not only answer all the same questions as above but also now have enough data todetermine:/p>ul>li>What is the most/least common checked out book/li>li>How frequently is a book checked out/li>li>Who has checked out a book in the past/li>li>Who has checked out the most books in any time range/li>li>What is the average checkout time for a book/li>li>We can even replay history of whole book or library and use that to test our library system./li>/ul>p>There are many other facts we can extract about books and library members. And we can do all of that without anyancillary tables./p>p>Hopefully by now you can see some scenarios where event sourcing may be useful, and well go over some other things toconsider when weighing event sourcing vs more classical data storage methodoligies. But for now lets return to the openquestion of how do you effectively query data stored in such a fashion./p>h2>Practical Event Sourcing with SQL/h2>p>To explore some queries well start with a data set repesenting the travels of ships.This data is organized as follows:/p>table>thead>tr>th alignleft>Ship/th>th alignleft>Action/th>th alignleft>Port/th>th alignleft>Time/th>/tr>/thead>tbody>tr>td alignleft>Edh/td>td alignleft>depart/td>td alignleft>Los Angeles/td>td alignleft>2020-07-02 15:54:24.467018/td>/tr>tr>td alignleft>Yough/td>td alignleft>depart/td>td alignleft>Singapore/td>td alignleft>2020-10-17 08:52:57.891636/td>/tr>tr>td alignleft>Ash/td>td alignleft>arrive/td>td alignleft>Port Klang/td>td alignleft>2020-09-28 11:13:48.191754/td>/tr>tr>td alignleft>Thorn/td>td alignleft>depart/td>td alignleft>Dubai/td>td alignleft>2020-05-12 16:23:40.381128/td>/tr>tr>td alignleft>.../td>td alignleft>.../td>td alignleft>.../td>td alignleft>.../td>/tr>/tbody>/table>blockquote>p>Follow along by througha hrefhttps://www.db-fiddle.com/f/7vYydHWN4LuJtytzLQW1di/0>db-fiddle/a> or downloada href./static/ship_ledger.sql>ship_ledger.sql/a>, a sql script thatcreates a temporary table. This data can be loaded by excuting code>\iship_ledger.sql/code> from a hrefhttps://www.postgresql.org/docs/current/app-psql.html>psql/a> or a hrefhttps://www.pgcli.com/>pgcli/a> clients. /p>/blockquote>h3>Read current state of single asset/h3>p>Say we want to find what port the ship Ash was last at. All we need to do is to ORDER the results and pick the firstelement with ship name ASH/p>table classhighlighttable>tr>td classlinenos>div classlinenodiv>pre>1234/pre>/div>/td>td classcode>div classhighlight>pre>span>/span>code>span classk>SELECT/span> span classo>*/span> span classk>FROM/span> span classn>ship_ledger/span>span classk>WHERE/span> span classn>ship/span> span classo>/span> span classs1>'Ash'/span>span classk>ORDER/span> span classk>BY/span> span classk>time/span> span classk>DESC/span>span classk>LIMIT/span> span classmi>1/span>span classp>;/span>/code>/pre>/div>/td>/tr>/table>h3>Read current state of all assets/h3>p>What if we want to extend the previous question to get current all states for all ships. We want to get outcome similarto:/p>table>thead>tr>th alignleft>Ship/th>th alignleft>Action/th>th alignleft>Port/th>th alignleft>Time/th>/tr>/thead>tbody>tr>td alignleft>Ash/td>td alignleft>arrive/td>td alignleft>Rotterdam/td>td alignleft>2021-01-15 03:35:29.845197/td>/tr>tr>td alignleft>Edh/td>td alignleft>arrive/td>td alignleft>Los Angeles/td>td alignleft>2021-01-09 09:37:30.387559/td>/tr>tr>td alignleft>Ethel/td>td alignleft>arrive/td>td alignleft>Laem Chabang/td>td alignleft>2021-01-25 05:40:35.469808/td>/tr>tr>td alignleft>Thorn/td>td alignleft>arrive/td>td alignleft>Antwerp/td>td alignleft>2021-01-05 10:50:07.723586/td>/tr>tr>td alignleft>Wyn/td>td alignleft>arrive/td>td alignleft>Los Angeles/td>td alignleft>2021-01-16 11:56:50.433422/td>/tr>tr>td alignleft>Yough/td>td alignleft>arrive/td>td alignleft>Hamburg/td>td alignleft>2021-01-03 10:57:43.320602/td>/tr>/tbody>/table>p>There are several ways in doing this lets explore applying DISTINCT ON as well as WINDOW functions as both of theseapproaches are a good foundation block to other queries./p>h4>Current State of all assets using DISTINCT ON/h4>p>Utilizing DISTINCT ON we can instruct our database to retrieve only one record for each ship after having ordered it bytime./p>table classhighlighttable>tr>td classlinenos>div classlinenodiv>pre>123/pre>/div>/td>td classcode>div classhighlight>pre>span>/span>code>span classk>SELECT/span> span classk>DISTINCT/span> span classk>ON/span> span classp>(/span>span classn>ship/span>span classp>)/span> span classo>*/span>span classk>FROM/span> span classn>ship_ledger/span>span classk>ORDER/span> span classk>BY/span> span classn>ship/span>span classp>,/span> span classk>time/span> span classk>DESC/span>span classp>;/span>/code>/pre>/div>/td>/tr>/table>p>Unlike the single ship example here we need order not just by time but also by ship. This nuance is side effect ofinternal implementation of the database through the database which picks the first result after having arranged the databy ship. It requires you to explicitly order the data on the DISTINCT key and if you forget to do so itll remind withan error message code>SELECT DISTINCT ON expressions must match initial ORDER BY expressions/code>. See a hrefhttps://www.postgresql.org/docs/current/sql-select.html#SQL-DISTINCT>documentation ondistinct/a> for additional information./p>h4>Current state of all assets using Window Functions/h4>p>The same result of the previous query can be accomplished by using data a hrefhttps://www.postgresql.org/docs/current/tutorial-window.html>WindowFunctions/a>. This method is a bit more manual and requiresto first arrange the data by ship and time (for similar reasons as in previous query):/p>table classhighlighttable>tr>td classlinenos>div classlinenodiv>pre>123/pre>/div>/td>td classcode>div classhighlight>pre>span>/span>code>span classk>SELECT/span> span classo>*/span>span classp>,/span> span classn>RANK/span>span classp>()/span> span classn>OVER/span>span classp>(/span>span classn>PARTITION/span> span classk>BY/span> span classn>ship/span> span classk>ORDER/span> span classk>BY/span> span classn>ship/span>span classp>,/span> span classk>TIME/span> span classk>DESC/span>span classp>)/span> span classk>AS/span> span classn>rank/span>span classk>FROM/span> span classn>ship_ledger/span>/code>/pre>/div>/td>/tr>/table>p>This will return all events, they will be arranged by code>ship/code> and each event associated to a specific ship will besequentially numbered (ranked)./p>table>thead>tr>th alignleft>ship/th>th alignleft>action/th>th alignleft>port/th>th alignleft>time/th>th alignleft>rank/th>/tr>/thead>tbody>tr>td alignleft>Ash/td>td alignleft>arrive/td>td alignleft>Rotterdam/td>td alignleft>2021-01-15 03:35:29.845197/td>td alignleft>1/td>/tr>tr>td alignleft>Ash/td>td alignleft>depart/td>td alignleft>Shanghai/td>td alignleft>2020-12-27 07:12:25.163836/td>td alignleft>2/td>/tr>tr>td alignleft>.../td>td alignleft>.../td>td alignleft>.../td>td alignleft>.../td>td alignleft>3/td>/tr>tr>td alignleft>Edh/td>td alignleft>arrive/td>td alignleft>Los Angeles/td>td alignleft>2021-01-09 09:37:30.387559/td>td alignleft>1/td>/tr>tr>td alignleft>Edh/td>td alignleft>depart/td>td alignleft>Dubai/td>td alignleft>2020-12-12 07:29:13.325785/td>td alignleft>2/td>/tr>tr>td alignleft>.../td>td alignleft>.../td>td alignleft>.../td>td alignleft>.../td>td alignleft>3/td>/tr>tr>td alignleft>Ethel/td>td alignleft>arrive/td>td alignleft>Laem Chabang/td>td alignleft>2021-01-25 05:40:35.469808/td>td alignleft>1/td>/tr>tr>td alignleft>Ethel/td>td alignleft>depart/td>td alignleft>Los Angeles/td>td alignleft>2020-12-28 08:22:25.237478/td>td alignleft>2/td>/tr>tr>td alignleft>.../td>td alignleft>.../td>td alignleft>.../td>td alignleft>.../td>td alignleft>3/td>/tr>/tbody>/table>p>To narrow down the results to one last event per ship, all we need to do is filter results to those where rank is 1:/p>table classhighlighttable>tr>td classlinenos>div classlinenodiv>pre>123456/pre>/div>/td>td classcode>div classhighlight>pre>span>/span>code>span classk>SELECT/span> span classo>*/span>span classk>FROM/span> span classp>(/span>span classk>SELECT/span> span classo>*/span>span classp>,/span> span classn>RANK/span>span classp>()/span> span classn>OVER/span>span classp>(/span>span classn>PARTITION/span> span classk>BY/span> span classn>ship/span> span classk>ORDER/span> span classk>BY/span> span classn>ship/span>span classp>,/span> span classk>TIME/span> span classk>DESC/span>span classp>)/span> span classk>AS/span> span classn>rank/span> span classk>FROM/span> span classn>ship_ledger/span>span classp>)/span> span classk>AS/span> span classn>ranked_ledger/span>span classk>WHERE/span> span classn>rank/span>span classo>/span>span classmi>1/span>/code>/pre>/div>/td>/tr>/table>p>and finally we get same result as before:/p>table>thead>tr>th alignleft>ship/th>th alignleft>action/th>th alignleft>port/th>th alignleft>time/th>th alignleft>rank/th>/tr>/thead>tbody>tr>td alignleft>Ash/td>td alignleft>arrive/td>td alignleft>Rotterdam/td>td alignleft>2021-01-15 03:35:29.845197/td>td alignleft>1/td>/tr>tr>td alignleft>Edh/td>td alignleft>arrive/td>td alignleft>Los Angeles/td>td alignleft>2021-01-09 09:37:30.387559/td>td alignleft>1/td>/tr>tr>td alignleft>Ethel/td>td alignleft>arrive/td>td alignleft>Laem Chabang/td>td alignleft>2021-01-25 05:40:35.469808/td>td alignleft>1/td>/tr>tr>td alignleft>Thorn/td>td alignleft>arrive/td>td alignleft>Antwerp/td>td alignleft>2021-01-05 10:50:07.723586/td>td alignleft>1/td>/tr>tr>td alignleft>Wyn/td>td alignleft>arrive/td>td alignleft>Los Angeles/td>td alignleft>2021-01-16 11:56:50.433422/td>td alignleft>1/td>/tr>tr>td alignleft>Yough/td>td alignleft>arrive/td>td alignleft>Hamburg/td>td alignleft>2021-01-03 10:57:43.320602/td>td alignleft>1/td>/tr>/tbody>/table>h4>Last N states of an asset/h4>p>It may already have become apparent that filtering by rank already gives an options to get last few port result.This was not an option available with DISTINCT ON. Lets say that want last 3 port arrivals for each ship:/p>table classhighlighttable>tr>td classlinenos>div classlinenodiv>pre>1234567/pre>/div>/td>td classcode>div classhighlight>pre>span>/span>code>span classk>SELECT/span> span classo>*/span>span classk>FROM/span> span classp>(/span>span classk>SELECT/span> span classo>*/span>span classp>,/span> span classn>RANK/span>span classp>()/span> span classn>OVER/span>span classp>(/span>span classn>PARTITION/span> span classk>BY/span> span classn>ship/span> span classk>ORDER/span> span classk>BY/span> span classn>ship/span>span classp>,/span> span classk>TIME/span> span classk>DESC/span>span classp>)/span> span classk>AS/span> span classn>rank/span> span classk>FROM/span> span classn>ship_ledger/span> span classk>WHERE/span> span classn>action/span> span classo>/span> span classs1>'arrive'/span>span classp>)/span> span classk>AS/span> span classn>ranked_ledger/span>span classk>WHERE/span> span classn>rank/span>span classo></span>span classmi>3/span>/code>/pre>/div>/td>/tr>/table>p>Result of this is:/p>table>thead>tr>th alignleft>ship/th>th alignleft>action/th>th alignleft>port/th>th alignleft>time/th>th alignleft>rank/th>/tr>/thead>tbody>tr>td alignleft>Ash/td>td alignleft>arrive/td>td alignleft>Rotterdam/td>td alignleft>2021-01-15 03:35:29.845197/td>td alignleft>1/td>/tr>tr>td alignleft>Ash/td>td alignleft>arrive/td>td alignleft>Shanghai/td>td alignleft>2020-12-20 22:51:46.163836/td>td alignleft>2/td>/tr>tr>td alignleft>Ash/td>td alignleft>arrive/td>td alignleft>Busan/td>td alignleft>2020-12-18 12:44:35.557756/td>td alignleft>3/td>/tr>tr>td alignleft>Edh/td>td alignleft>arrive/td>td alignleft>Los Angeles/td>td alignleft>2021-01-09 09:37:30.387559/td>td alignleft>1/td>/tr>tr>td alignleft>Edh/td>td alignleft>arrive/td>td alignleft>Dubai/td>td alignleft>2020-12-10 10:41:57.325785/td>td alignleft>2/td>/tr>tr>td alignleft>Edh/td>td alignleft>arrive/td>td alignleft>Kaohsiung/td>td alignleft>2020-11-22 19:14:36.678225/td>td alignleft>3/td>/tr>tr>td alignleft>Ethel/td>td alignleft>arrive/td>td alignleft>Laem Chabang/td>td alignleft>2021-01-25 05:40:35.469808/td>td alignleft>1/td>/tr>tr>td alignleft>Ethel/td>td alignleft>arrive/td>td alignleft>Los Angeles/td>td alignleft>2020-12-21 12:25:15.237478/td>td alignleft>2/td>/tr>tr>td alignleft>Ethel/td>td alignleft>arrive/td>td alignleft>Port Klang/td>td alignleft>2020-11-18 21:27:19.832519/td>td alignleft>3/td>/tr>tr>td alignleft>Thorn/td>td alignleft>arrive/td>td alignleft>Antwerp/td>td alignleft>2021-01-05 10:50:07.723586/td>td alignleft>1/td>/tr>tr>td alignleft>Thorn/td>td alignleft>arrive/td>td alignleft>Port Klang/td>td alignleft>2020-12-12 10:17:27.015774/td>td alignleft>2/td>/tr>tr>td alignleft>Thorn/td>td alignleft>arrive/td>td alignleft>Kaohsiung/td>td alignleft>2020-12-01 22:04:29.384756/td>td alignleft>3/td>/tr>tr>td alignleft>Wyn/td>td alignleft>arrive/td>td alignleft>Los Angeles/td>td alignleft>2021-01-16 11:56:50.433422/td>td alignleft>1/td>/tr>tr>td alignleft>Wyn/td>td alignleft>arrive/td>td alignleft>Antwerp/td>td alignleft>2020-12-25 14:47:07.326144/td>td alignleft>2/td>/tr>tr>td alignleft>Wyn/td>td alignleft>arrive/td>td alignleft>Rotterdam/td>td alignleft>2020-12-19 20:20:47.150076/td>td alignleft>3/td>/tr>tr>td alignleft>Yough/td>td alignleft>arrive/td>td alignleft>Hamburg/td>td alignleft>2021-01-03 10:57:43.320602/td>td alignleft>1/td>/tr>tr>td alignleft>Yough/td>td alignleft>arrive/td>td alignleft>Shanghai/td>td alignleft>2020-12-13 02:15:03.588928/td>td alignleft>2/td>/tr>tr>td alignleft>Yough/td>td alignleft>arrive/td>td alignleft>Antwerp/td>td alignleft>2020-11-20 10:00:10.311773/td>td alignleft>3/td>/tr>/tbody>/table>h3>Aggregating multiple events of an asset into single record/h3>p>In the previous example gave us last 3 ports for each ship. But data for any single ship was represented in 3 rows, thiscan be somewhat cumbersome It would a lot easier to deal with if all information for each ship was available on the samerow. This can be realized using lead() a hrefhttps://www.postgresql.org/docs/current/functions-window.htm>window-function/a>/p>p>Lets first do it with last two ports/p>table classhighlighttable>tr>td classlinenos>div classlinenodiv>pre>12345678/pre>/div>/td>td classcode>div classhighlight>pre>span>/span>code>span classk>SELECT/span> span classo>*/span>span classk>FROM/span> span classp>(/span>span classk>SELECT/span> span classo>*/span>span classp>,/span> span classn>RANK/span>span classp>()/span> span classn>OVER/span>span classp>(/span>span classn>PARTITION/span> span classk>BY/span> span classn>ship/span> span classk>ORDER/span> span classk>BY/span> span classn>ship/span>span classp>,/span> span classk>TIME/span> span classk>DESC/span>span classp>)/span> span classk>AS/span> span classn>rank/span>span classp>,/span> span classn>lead/span>span classp>(/span>span classn>port/span>span classp>,/span> span classmi>1/span>span classp>)/span> span classn>OVER/span>span classp>(/span>span classn>PARTITION/span> span classk>BY/span> span classn>ship/span> span classk>ORDER/span> span classk>BY/span> span classn>ship/span>span classp>,/span> span classk>TIME/span> span classk>DESC/span>span classp>)/span> span classk>AS/span> span classn>previous_port/span> span classk>FROM/span> span classn>ship_ledger/span> span classk>WHERE/span> span classn>action/span> span classo>/span> span classs1>'arrive'/span>span classp>)/span> span classk>AS/span> span classn>ranked_ledger/span>span classk>WHERE/span> span classn>rank/span>span classo>/span>span classmi>1/span>span classp>;/span>/code>/pre>/div>/td>/tr>/table>p>Result:/p>table>thead>tr>th alignleft>ship/th>th alignleft>action/th>th alignleft>port/th>th alignleft>time/th>th alignleft>rank/th>th alignleft>previous_port/th>/tr>/thead>tbody>tr>td alignleft>Ash/td>td alignleft>arrive/td>td alignleft>Rotterdam/td>td alignleft>2021-01-15 03:35:29.845197/td>td alignleft>1/td>td alignleft>Shanghai/td>/tr>tr>td alignleft>Edh/td>td alignleft>arrive/td>td alignleft>Los Angeles/td>td alignleft>2021-01-09 09:37:30.387559/td>td alignleft>1/td>td alignleft>Dubai/td>/tr>tr>td alignleft>Ethel/td>td alignleft>arrive/td>td alignleft>Laem Chabang/td>td alignleft>2021-01-25 05:40:35.469808/td>td alignleft>1/td>td alignleft>Los Angeles/td>/tr>tr>td alignleft>Thorn/td>td alignleft>arrive/td>td alignleft>Antwerp/td>td alignleft>2021-01-05 10:50:07.723586/td>td alignleft>1/td>td alignleft>Port Klang/td>/tr>tr>td alignleft>Wyn/td>td alignleft>arrive/td>td alignleft>Los Angeles/td>td alignleft>2021-01-16 11:56:50.433422/td>td alignleft>1/td>td alignleft>Antwerp/td>/tr>tr>td alignleft>Yough/td>td alignleft>arrive/td>td alignleft>Hamburg/td>td alignleft>2021-01-03 10:57:43.320602/td>td alignleft>1/td>td alignleft>Shanghai/td>/tr>/tbody>/table>p>The same pattern can be extended to 3 ports by supplying to code>lead(port, 2)/code> with the same PARTITION statement. Howeverthe repetition is off putting, and to deal with that we can define the partition window independently and refer it towindow function via an alias./p>table classhighlighttable>tr>td classlinenos>div classlinenodiv>pre> 1 2 3 4 5 6 7 8 91011/pre>/div>/td>td classcode>div classhighlight>pre>span>/span>code>span classk>SELECT/span> span classo>*/span>span classk>FROM/span> span classp>(/span>span classk>SELECT/span> span classo>*/span>span classp>,/span> span classn>RANK/span>span classp>()/span> span classn>OVER/span>span classp>(/span>span classn>ship_ledger_group/span>span classp>)/span> span classk>AS/span> span classn>rank/span>span classp>,/span> span classn>lead/span>span classp>(/span>span classn>port/span>span classp>,/span> span classmi>1/span>span classp>)/span> span classn>OVER/span>span classp>(/span>span classn>ship_ledger_group/span>span classp>)/span> span classk>AS/span> span classn>previous_port/span>span classp>,/span> span classn>lead/span>span classp>(/span>span classn>port/span>span classp>,/span> span classmi>2/span>span classp>)/span> span classn>OVER/span>span classp>(/span>span classn>ship_ledger_group/span>span classp>)/span> span classk>AS/span> span classn>two_ports_ago/span> span classk>FROM/span> span classn>ship_ledger/span> span classk>WHERE/span> span classn>action/span> span classo>/span> span classs1>'arrive'/span> span classn>WINDOW/span> span classn>ship_ledger_group/span> span classk>AS/span> span classp>(/span>span classn>PARTITION/span> span classk>BY/span> span classn>ship/span> span classk>ORDER/span> span classk>BY/span> span classn>ship/span>span classp>,/span> span classk>TIME/span> span classk>DESC/span>span classp>)/span> span classp>)/span> span classk>AS/span> span classn>ranked_ledger/span>span classk>WHERE/span> span classn>rank/span>span classo>/span>span classmi>1/span>span classp>;/span>/code>/pre>/div>/td>/tr>/table>p>Result:/p>table>thead>tr>th alignleft>ship/th>th alignleft>action/th>th alignleft>port/th>th alignleft>time/th>th alignleft>rank/th>th alignleft>previous_port/th>th alignleft>two_ports_ago/th>/tr>/thead>tbody>tr>td alignleft>Ash/td>td alignleft>arrive/td>td alignleft>Rotterdam/td>td alignleft>2021-01-15 03:35:29.845197/td>td alignleft>1/td>td alignleft>Shanghai/td>td alignleft>Busan/td>/tr>tr>td alignleft>Edh/td>td alignleft>arrive/td>td alignleft>Los Angeles/td>td alignleft>2021-01-09 09:37:30.387559/td>td alignleft>1/td>td alignleft>Dubai/td>td alignleft>Kaohsiung/td>/tr>tr>td alignleft>Ethel/td>td alignleft>arrive/td>td alignleft>Laem Chabang/td>td alignleft>2021-01-25 05:40:35.469808/td>td alignleft>1/td>td alignleft>Los Angeles/td>td alignleft>Port Klang/td>/tr>tr>td alignleft>Thorn/td>td alignleft>arrive/td>td alignleft>Antwerp/td>td alignleft>2021-01-05 10:50:07.723586/td>td alignleft>1/td>td alignleft>Port Klang/td>td alignleft>Kaohsiung/td>/tr>tr>td alignleft>Wyn/td>td alignleft>arrive/td>td alignleft>Los Angeles/td>td alignleft>2021-01-16 11:56:50.433422/td>td alignleft>1/td>td alignleft>Antwerp/td>td alignleft>Rotterdam/td>/tr>tr>td alignleft>Yough/td>td alignleft>arrive/td>td alignleft>Hamburg/td>td alignleft>2021-01-03 10:57:43.320602/td>td alignleft>1/td>td alignleft>Shanghai/td>td alignleft>Antwerp/td>/tr>/tbody>/table>p>We dont have the timestamp displayed for the previous ports but it can be added utilizing same approach. Based ofcode>lead(port, 1) OVER(ship_ledger_group) AS previous_port,/code> a new select statement can be added rigth after as code>lead(time,1) OVER(ship_ledger_group) AS previous_port_time,/code>/p>h3>Extract new data from past events of an asset with Window Functions/h3>p>How about finding the average travel time of the most popular ports? /p>table classhighlighttable>tr>td classlinenos>div classlinenodiv>pre> 1 2 3 4 5 6 7 8 910111213141516/pre>/div>/td>td classcode>div classhighlight>pre>span>/span>code>span classk>SELECT/span> span classo>*/span>span classk>FROM/span> span classp>(/span>span classk>SELECT/span> span classn>port/span>span classp>,/span> span classn>last_port_event/span>span classp>,/span> span classk>avg/span>span classp>(/span>span classk>time/span>span classo>-/span>span classn>last_event_time/span>span classp>),/span> span classk>count/span>span classp>(/span>span classo>*/span>span classp>)/span> span classk>FROM/span> span classp>(/span>span classk>SELECT/span> span classo>*/span>span classp>,/span> span classn>lag/span>span classp>(/span>span classn>port/span>span classp>,/span> span classmi>1/span>span classp>)/span> span classn>OVER/span>span classp>(/span>span classn>ship_ledger_group/span>span classp>)/span> span classk>AS/span> span classn>last_port_event/span>span classp>,/span> span classn>lag/span>span classp>(/span>span classk>time/span>span classp>,/span> span classmi>1/span>span classp>)/span> span classn>OVER/span>span classp>(/span>span classn>ship_ledger_group/span>span classp>)/span> span classk>AS/span> span classn>last_event_time/span> span classk>FROM/span> span classn>ship_ledger/span> span classn>WINDOW/span> span classn>ship_ledger_group/span> span classk>AS/span> span classp>(/span>span classn>PARTITION/span> span classk>BY/span> span classn>ship/span> span classk>ORDER/span> span classk>BY/span> span classn>ship/span>span classp>,/span> span classk>time/span> span classk>ASC/span>span classp>)/span> span classp>)/span> span classn>ss/span> span classk>GROUP/span> span classk>BY/span> span classp>(/span>span classn>port/span>span classp>,/span> span classn>last_port_event/span>span classp>)/span> span classp>)/span> span classk>as/span> span classn>sss/span>span classk>ORDER/span> span classk>BY/span> span classk>count/span> span classk>DESC/span>span classk>LIMIT/span> span classmi>3/span>span classp>;/span>/code>/pre>/div>/td>/tr>/table>p>Result:/p>table>thead>tr>th alignleft>port/th>th alignleft>last_port_event/th>th alignleft>avg/th>th alignleft>count/th>/tr>/thead>tbody>tr>td alignleft>Busan/td>td alignleft>Busan/td>td alignleft>3 days, 8:44:19.400000/td>td alignleft>15/td>/tr>tr>td alignleft>Rotterdam/td>td alignleft>Rotterdam/td>td alignleft>3 days, 14:06:46.538462/td>td alignleft>13/td>/tr>tr>td alignleft>Singapore/td>td alignleft>Singapore/td>td alignleft>4 days, 1:40:51.846154/td>td alignleft>13/td>/tr>/tbody>/table>h3>Extract new data from past events of an asset with Pivot Table (crosstab)/h3>blockquote>p>The following section of tutorial requires the tablefunc extension to be enabled. To enabled as a privileged userexecute:/p>table classhighlighttable>tr>td classlinenos>div classlinenodiv>pre>1/pre>/div>/td>td classcode>div classhighlight>pre>span>/span>code>span classk>CREATE/span> span classn>EXTENSION/span> span classk>IF/span> span classk>NOT/span> span classk>EXISTS/span> span classn>tablefunc/span>span classp>;/span>/code>/pre>/div>/td>/tr>/table>p>If crosstab is called without enabling tablefunc extension Postgres will error out with:/p>table classhighlighttable>tr>td classlinenos>div classlinenodiv>pre>12345/pre>/div>/td>td classcode>div classhighlight>pre>span>/span>code>span classk>function/span> span classn>crosstab/span>span classp>(/span>span classk>unknown/span>span classp>,/span> span classk>unknown/span>span classp>)/span> span classn>does/span> span classk>not/span> span classn>exist/span>span classn>LINE/span> span classmi>3/span>span classp>:/span> span classk>FROM/span> span classn>crosstab/span> span classo>^/span> span classn>HINT/span>span classp>:/span> span classk>No/span> span classk>function/span> span classn>matches/span> span classn>the/span> span classn>given/span> span classn>name/span> span classk>and/span> span classn>argument/span> span classn>types/span>span classp>./span> span classn>You/span> span classn>might/span> span classn>need/span> span classk>to/span> span classk>add/span> span classn>explicit/span> span classk>type/span> span classn>casts/span>span classp>./span>/code>/pre>/div>/td>/tr>/table>/blockquote>p>A common pattern with Event Sourcing is storing a state with a corresponding event. Say we have a user session trackingsystem where record the state action that occured. /p>table>thead>tr>th alignleft>session/th>th alignleft>user/th>th alignleft>event/th>th alignleft>time/th>/tr>/thead>tbody>tr>td alignleft>B/td>td alignleft>Alice/td>td alignleft>login/td>td alignleft>2020-07-02 12:00:12/td>/tr>tr>td alignleft>A/td>td alignleft>Bob/td>td alignleft>logout/td>td alignleft>2020-07-02 12:01:11/td>/tr>tr>td alignleft>B/td>td alignleft>Eve/td>td alignleft>publish/td>td alignleft>2020-07-02 12:02:22/td>/tr>tr>td alignleft>B/td>td alignleft>Alice/td>td alignleft>publish/td>td alignleft>2020-07-02 12:11:00/td>/tr>tr>td alignleft>C/td>td alignleft>Mallory/td>td alignleft>login/td>td alignleft>2020-07-02 12:12:20/td>/tr>tr>td alignleft>A/td>td alignleft>Bob/td>td alignleft>publish/td>td alignleft>2020-07-02 12:12:21/td>/tr>tr>td alignleft>B/td>td alignleft>Alice/td>td alignleft>publish/td>td alignleft>2020-07-02 12:20:12/td>/tr>tr>td alignleft>B/td>td alignleft>Alice/td>td alignleft>logout/td>td alignleft>2020-07-02 12:22:20/td>/tr>/tbody>/table>blockquote>p>Follow along by downloading the a href./static/session_tracking.sql>session_tracking.sql/a> a sql script that creates a temporary table.This data can be loaded by excuting code>\i session_tracking.sql/code> froma hrefhttps://www.postgresql.org/docs/current/app-psql.html>psql/a> or a hrefhttps://www.pgcli.com/>pgcli/a> clients. /p>/blockquote>p>With this data we may be interested in finding duration of a session. The time between login and logout states for allsessions./p>table classhighlighttable>tr>td classlinenos>div classlinenodiv>pre> 1 2 3 4 5 6 7 8 910/pre>/div>/td>td classcode>div classhighlight>pre>span>/span>code>span classk>SELECT/span> span classo>*/span>span classp>,/span> span classn>logout/span>span classo>-/span>span classn>login/span> span classk>as/span> span classn>duration/span>span classk>FROM/span> span classn>crosstab/span> span classp>(/span>span classerr>$$/span> span classk>SELECT/span> span classk>DISTINCT/span> span classk>ON/span> span classp>(/span>span classk>session/span>span classp>,/span> span classn>event/span>span classp>)/span> span classss>"user"/span>span classp>,/span> span classn>event/span>span classp>,/span> span classk>time/span> span classk>FROM/span> span classn>user_sessions/span> span classk>WHERE/span> span classn>event/span> span classk>in/span> span classp>(/span>span classs1>'login'/span>span classp>,/span> span classs1>'logout'/span>span classp>)/span> span classk>ORDER/span> span classk>BY/span> span classk>session/span>span classp>,/span> span classn>event/span>span classp>,/span> span classk>time/span> span classk>DESC/span> span classerr>$$/span>span classp>,/span> span classerr>$$/span> span classk>VALUES/span>span classp>(/span>span classs1>'login'/span>span classp>),/span> span classp>(/span>span classs1>'logout'/span>span classp>)/span> span classerr>$$/span>span classp>)/span> span classk>AS/span> span classn>ct/span> span classp>(/span>span classss>"user"/span> span classnb>text/span>span classp>,/span> span classn>login/span> span classk>timestamp/span>span classp>,/span> span classn>logout/span> span classk>timestamp/span>span classp>);/span>/code>/pre>/div>/td>/tr>/table>p>What happens in this query is a whats often called a pivot. The inner query prepares the result by extracting lastevent associate with login out logout./p>table>thead>tr>th alignleft>user/th>th alignleft>event/th>th alignleft>time/th>/tr>/thead>tbody>tr>td alignleft>Bob/td>td alignleft>logout/td>td alignleft>2020-07-02 12:01:11/td>/tr>tr>td alignleft>Alice/td>td alignleft>login/td>td alignleft>2020-07-02 12:00:12/td>/tr>tr>td alignleft>Alice/td>td alignleft>logout/td>td alignleft>2020-07-02 12:22:20/td>/tr>tr>td alignleft>Mallory/td>td alignleft>login/td>td alignleft>2020-07-02 12:12:20/td>/tr>/tbody>/table>p>The crosstab then performs the pivot, turning events into columns and populating them with corresponding time valuesyielding the following data:/p>table>thead>tr>th alignleft>user/th>th alignleft>login/th>th alignleft>logout/th>th alignleft>duration/th>/tr>/thead>tbody>tr>td alignleft>Bob/td>td alignleft>null>/td>td alignleft>2020-07-02 12:01:11/td>td alignleft>null>/td>/tr>tr>td alignleft>Alice/td>td alignleft>2020-07-02 12:00:12/td>td alignleft>2020-07-02 12:22:20/td>td alignleft>0:22:08/td>/tr>tr>td alignleft>Mallory/td>td alignleft>2020-07-02 12:12:20/td>td alignleft>null>/td>td alignleft>null>/td>/tr>/tbody>/table>blockquote>p>This query above is extra careful to:/p>ul>li>retrieve only logout an login events (WHERE event IN (login, logout))/li>li>explicitly declare to crosstab what values to expect as events (VALUES(login), (logout))/li>li>specify the types of resulting data AS (ct (user text, login timestamp, logout timestamp))./li>/ul>p>This safety is not incidental, it is possible to create a more generic version of return all event types there are fewgotchas associated with it that are beyond the scope of this exercise./p>/blockquote>p>Lets try some other applying crosstab to some other examples. Lets say we want to know when each ship has been tothe 3 most popular ports. First what are the most popular ports:/p>table classhighlighttable>tr>td classlinenos>div classlinenodiv>pre>123456/pre>/div>/td>td classcode>div classhighlight>pre>span>/span>code>span classk>SELECT/span> span classn>port/span>span classp>,/span> span classk>count/span>span classp>(/span>span classo>*/span>span classp>)/span>span classk>FROM/span> span classn>ship_ledger/span>span classk>GROUP/span> span classk>BY/span> span classn>port/span>span classk>ORDER/span> span classk>BY/span> span classk>count/span>span classp>(/span>span classo>*/span>span classp>)/span> span classk>DESC/span>span classk>LIMIT/span> span classmi>3/span>/code>/pre>/div>/td>/tr>/table>p>Singapore, Rotterdam, Busan. Great! crosstab can now be applied to find the when each ship was there last:/p>table classhighlighttable>tr>td classlinenos>div classlinenodiv>pre> 1 2 3 4 5 6 7 8 91011/pre>/div>/td>td classcode>div classhighlight>pre>span>/span>code>span classk>SELECT/span> span classo>*/span>span classk>FROM/span> span classn>crosstab/span> span classp>(/span>span classerr>$$/span> span classk>SELECT/span> span classk>DISTINCT/span> span classk>ON/span> span classp>(/span>span classn>ship/span>span classp>,/span> span classn>port/span>span classp>)/span> span classn>ship/span>span classp>,/span> span classn>port/span>span classp>,/span> span classk>TIME/span> span classk>FROM/span> span classn>ship_ledger/span> span classk>WHERE/span> span classn>action/span>span classo>/span>span classs1>'arrive'/span> span classk>AND/span> span classn>port/span> span classk>IN/span> span classp>(/span>span classs1>'Singapore'/span>span classp>,/span> span classs1>'Rotterdam'/span>span classp>,/span> span classs1>'Busan'/span>span classp>)/span> span classk>ORDER/span> span classk>BY/span> span classn>ship/span>span classp>,/span> span classn>port/span>span classp>,/span> span classk>TIME/span> span classk>DESC/span> span classerr>$$/span>span classp>,/span> span classerr>$$/span> span classk>VALUES/span>span classp>(/span>span classs1>'Singapore'/span>span classp>),/span> span classp>(/span>span classs1>'Rotterdam'/span>span classp>),/span> span classp>(/span>span classs1>'Busan'/span>span classp>)/span> span classerr>$$/span>span classp>)/span> span classk>AS/span> span classn>ct/span>span classp>(/span>span classn>ship/span> span classnb>text/span>span classp>,/span> span classn>singapore/span> span classk>TIMESTAMP/span>span classp>,/span> span classn>rotterdam/span> span classk>TIMESTAMP/span>span classp>,/span> span classn>Busan/span> span classk>TIMESTAMP/span>span classp>);/span>/code>/pre>/div>/td>/tr>/table>h2>Summary and Applicability/h2>p>Hopefully these examples give you bit of an insight into how you can utilize Event Sourcing in your project. Just likeany pattern it is not panacea, here are use cases which for which event sourcing is great for and there is also theopposite./p>p>Great use cases:/p>ul>li>User session tracking. Just like in the example above if you want to record what users are doing in your application for future analysis event sourcing is great fit. /li>li>Transactional systems such as order systems or banking. Instead of storing an account balance all transaction against an account can be store ensuring that balance is always accurate even in concurrent executions./li>li>By utilizing event sourcing its possible to build distributed worker systems without having to rely on a queue. How much simpler can your system be by using your relational database that you have anyway and not have to start add rabbitmq / sqs / zeromq to your architecture./li>li>Any time where point in time injection of data may be necessary. What if you get yesterdays transactions today, after todays transactions have already been executed. Without event sourcing, if transactions are not commutative you may need to build complex logic to rollback state and reply while in event sourcing you just create a new back-dated event the state will be recomputed on use./li>li>Similar to point in time injection, you want to know what the state of something was in the past. Analysing state of events up to that point and ignoring the rest give you that ability./li>/ul>p>When is event sourcing counter productive? Well its particularly useless if you are dealing with data that does not havea time dimension. In terms of performance event sourcing is not necessarily much more expensive but details there dependon the nature of the problem, its unlikely to be a order of magnitude difference. Perhaps the biggest downside of eventsourcing is slightly more complex queries but that difference may be immaterial esp as the benefits can be liberating./p>p>Its also worth noting that while examples above are written with Postgres in mind, similar functionality exists in otherdatabase engines./p> span classcategory> /span> span classdate>a href./practical-event-sourcing-with-sql-postgres.html relbookmark titlePermalink to Practical Event Sourcing with SQL (Postgres)>2021-03-14T16:14:01-04:00/a>/span> /div> div classcontent> span classsubject>a href./goodbye-gitn.html relbookmark titlePermalink to Goodbye GITN>Goodbye GITN/a>/span> br/> p>What the hell is GITN? You might ask. GITN stands for glitchinthe.net, andfor the past ten years it has hosted my blaagh, dns, email, IRC and more. Ithas served us well, went through a couple of hard drives but the rest of thehardware has stayed the same. Its pretty remarkable, actually, that it is has notkeeled over many years ago. I guess when you have a machine in a niceenvironment it lives for a long time./p>p>Why the change? Well there are several reasons. Gitn is no longer hosting as many services as it used to. Over past few years spam has grown insophistication compared to deterrents. That or Ive grown less interested inwasting my time on maintaing the deterrents. At any rate, late last year Ioutsourced my email and DNS to a hrefhttp://fastmail.com>fastmail/a>. IRC(irc.glitchinthe.net) was also shut down a while back as the IRC network itwas part of effectivly disbanded. With fewer services to host, migration hasbecome a easier. But I still kept putting it off. Untill, last week. When my colocprovider had network problems which resulted in twelve hours of downtime, itreminded me that its time to move whats still on gitn somewhere else./p>p>So here we go! Its all going to AWS. Ive been using it quite extensivlyat work and it has been, just a pleasure to work with. Rather inexpensive, andcomes with some great services. It just made sense to move what ever remainedof gitn there./p>p>While migrating Im also simplifying infrastructure, so its not completelytrivial and might take a couple of weeks to finish. By the time you read thisit will all be in a new place./p> span classcategory> a href./tag/lilug.html>LILUG/a> a href./tag/server.html>Server/a> /span> span classdate>a href./goodbye-gitn.html relbookmark titlePermalink to Goodbye GITN>2014-04-25T23:26:52-04:00/a>/span> /div> div classcontent> span classsubject>a href./debian-gnu-linux-on-samsung-ativ-book-9-plus.html relbookmark titlePermalink to Debian GNU / Linux on Samsung ATIV Book 9 Plus>Debian GNU / Linux on Samsung ATIV Book 9 Plus/a>/span> br/> p>Samsung just recently released a new piece of kit, ATIV Book 9 plus. Its theirtop of the line Ultrabook. Being in on the market for a new laptop, when Iheard of the specs, I was hooked. Sure it doesnt have the best CPU in alaptop or even amazing amount of ram, in that regard its kind of run of themill. But that was enough for me. The really amazing thing is the screen, with3200x1800 resolution and 275DPI. If you were to get a stand alone monitor withsimilar resolution youd be forking over anywhere from 50-200% the value ofthe ATIV Book 9 Plus. Anyway this is not a marketing pitch. As a GNU / Linuxuser, buying bleeding edge hardware can be a bit intimidating. The problem isthat its not clear if the hardware will work without too much fuss. Icouldnt find any reports or folks running GNU / Linux on it, but decided toorder one anyway./p>p>My distro of choice is a hrefhttp://www.debian.org/>Debian GNU / Linux/a>. So whenthe machine arrived the first thing I did was, try a hrefhttp://live.debian.net/>DebianLive/a>. It did get some tinkering of BIOS (press f2 onboot to enter config) to get it to boot. Mostly because the BIOS UI ishorrendus. In the end disabling a hrefhttp://en.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface#Secure_boot>secure boot/a> was pretty much all it took.Out of the box, most things worked, exception being Wi-Fi and brightnesscontrol. At this point I was more or less convinced that getting GNU / Linuxrunning on it would not be too hard./p>p>I proceeded to installing Debian from a hrefhttp://www.debian.org/CD/http-ftp/>stable net-bootcd/a>. At first witha hrefhttp://en.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface>UEFI/a>enabled but secure boot disabled, installation went over fine but when it cametime to boot the machine, it would simply not work. Looked like boot loaderwasnt starting properly. I didnt care too much about UEFI so I disabled itcompletely and re-installed Debian. This time things worked and Debian Stablebooted up. I tweaked /etc/apt/sources.list switching froma hrefhttp://www.debian.org/releases/stable/>Stable/a> toa hrefhttp://www.debian.org/releases/testing/>Testing/a>. Rebooted the machine andnoticed that on boot the screen went black. It was rather obvious that theproblem was with KMS. Likely the root of the problem was the new kernel(a hrefhttp://packages.debian.org/jessie/linux-image-3.10-3-amd64>linux-image-3.10-3-amd64/a>) which got pulled in during upgrade to testing. The shortterm work around is simple, disable KMS (a hrefhttps://wiki.debian.org/KernelModesetting#Disabling_KMS>add nomodeset to kernel boot line ingrub/a>)./p>p>So now I had a booting base system but there was still the problem of Wi-Fiand KMS. I installed latest a hrefhttp://packages.debian.org/jessie/firmware-iwlwifi>firmware-iwlwifi/a> which had therequired firmware for a hrefhttp://wireless.kernel.org/en/users/Drivers/iwlwifi>Intel Corporation Wireless7260/a>. However Wi-Fistill did not work, fortunately I came across this a hrefhttps://bbs.archlinux.org/viewtopic.php?id167305>post on arch linuxwiki/a> which states that theWi-Fi card is only supported in a hrefhttp://www.spinics.net/lists/linux-wireless/msg109955.html>Linux Kernel>3.11/a>./p>p>After an hour or so of tinkering with kernel configs I got the latest kernel(a hrefhttps://www.kernel.org/pub/linux/kernel/v3.x/linux-3.11.4.tar.xz>3.11.3/a>)to boot with working KMS and Wi-Fi. Long story short, until Debian moves tokernel >3.11 youll need to compile your own or install my a hrefhttp://dotcommie.net/ativ/>custom compiledpackage/a>. With the latest kernel pretty mucheverything works this machine. Including the things that are often tricky,like; suspend, backlight control, touchscreen, and obviously Wi-Fi. The onlything remaining thing to figure out, are the volume and keyboard backlightcontrol keys. But for now Im making due with a software sound mixer. Andkeyboard backlight can be adjusted with (values: 0-4):/p>div classhighlight>pre>span>/span>code>span classerr>echo "4" > /sys/class/leds/samsung::kbd_backlight/brightness/span>/code>/pre>/div>p>So if you are looking to get Samsung ATIV Book 9 and wondering if itll playnice with GNU / Linux. The answer is yes./p> span classcategory> a href./tag/debian.html>Debian/a> a href./tag/hardware.html>Hardware/a> a href./tag/lilug.html>LILUG/a> a href./tag/software.html>Software/a> a href./tag/linux.html>linux/a> /span> span classdate>a href./debian-gnu-linux-on-samsung-ativ-book-9-plus.html relbookmark titlePermalink to Debian GNU / Linux on Samsung ATIV Book 9 Plus>2013-10-05T16:11:05-04:00/a>/span> /div> div classcontent> span classsubject>a href./hypnotoad-svg.html relbookmark titlePermalink to Hypnotoad SVG>Hypnotoad SVG/a>/span> br/> p>Hypnotoad is all over the internet. By in large depicted in tiny animated gifswith horrible compression artifacts and other flaws. Behold hypnotoad in itsfull glory, a lossless a hrefhttp://www.w3.org/TR/SVG/animate.html>animated/a>a hrefhttp://www.w3.org/Graphics/SVG/>svg/a> format. You can now scale hypnotoad tounimaginable dimentions without doing it injust - ALL GLORY TO THE HYPNOTOAD/p>p>img altALL GLORY TO THE HYPNOTOAD src./images/hypnotoad.svg>/p> span classcategory> a href./tag/lilug.html>LILUG/a> a href./tag/art.html>art/a> a href./tag/experiment.html>experiment/a> a href./tag/svg.html>svg/a> /span> span classdate>a href./hypnotoad-svg.html relbookmark titlePermalink to Hypnotoad SVG>2012-09-25T22:47:40-04:00/a>/span> /div> div classcontent> span classsubject>a href./cross-compile-with-make-kpkg.html relbookmark titlePermalink to Cross Compile with make-kpkg>Cross Compile with make-kpkg/a>/span> br/> p>I got myself one of the fancy shmancy netbooks. Due to a habit and somehardware issues I needed to compile a kernel. The problem here though is thatit takes for ever to build a kernel on one of these things. No sweat Ill justbuild it on my desktop, itll only take 5-10 minutes. But of course there is acatch. My desktop is 64bit and this new machine is an Atom CPU which only does32bit./p>p>The process for compiling a 32bit kernel on a 64bit machine is probably a loteasier if you dont compile it the Debian way. But this is not something Iwant to do, I like installing the kernels through the package manager anddoing this type of cross compile using make-kpkg is not trivial. There areplenty of forum and email threads about people recommending to use chroot orvirtual machines for this task, but that is such a chore to set up. So here ismy recipe for cross compiling 32bit kernel on 64bit host without chroot / vm,the-debian-way./p>ol>li>Install 32bit tools (ia32-libs, lib32gcc1, lib32ncurses5, libc6-i386, util-linux, maybe some other ones)/li>li>Download & unpack your a hrefhttp://kernel.org/>kernel sources/a>/li>li>run code>linux32 make menuconfig/code> and configure your kernel for your new machine/li>li>clean your build dirs code>make-kpkg clean --cross-compile - --archi386/code> (only needed on consecutive compiles)/li>li>compile your kernel code>nice -n 100 fakeroot linux32 make-kpkg --cross-compile - --archi386 --revision05test kernel_image/code> for faster compilation on multi-CPU machines run code>export CONCURRENCY_LEVEL$((/code>cat /proc/cpuinfo |grep ^processor|wc -lcode>*2))/code> first/li>li>At this point you have a 32bit kernel inside a package labeled for 64bit arch. We need to fix this, run code>fakeroot deb-reversion -k bash ../linux-image-2.6.35.3_05test_amd64.deb/code>. Open the file code>DEBIAN/control/code> with code>vim/emacs/code> and change code>Architecture: amd64/code> to code>Architecture: i386/code> exit the bash process with ctrl+d /li>li>Thats it, now just transfer the re-generated deb to destination machine and install it./li>/ol>p>Many if not all ideas for this process come from reading a hrefhttp://old.nabble.com/Compiling-kernel-%28i386%29-using-make-kpkg-td26186606.html>emailthreads/a> the comments made by a hrefhttp://old.nabble.com/Compiling-kernel-%28i386%29-using-make-kpkg-td26186606.html>Goswin VonBrederlow/a> were particularly helpful, thanks./p> span classcategory> a href./tag/debian.html>Debian/a> a href./tag/lilug.html>LILUG/a> a href./tag/linux.html>linux/a> a href./tag/software.html>software/a> /span> span classdate>a href./cross-compile-with-make-kpkg.html relbookmark titlePermalink to Cross Compile with make-kpkg>2010-08-25T22:09:15-04:00/a>/span> /div> div classcontent> span classsubject>a href./versionless-distro.html relbookmark titlePermalink to Versionless Distro>Versionless Distro/a>/span> br/> p>Every six months the internet lights up with stories that Canonical & Co hasdone the unthinkable they have increased the number following the word Ubuntu.In other words they have release a new version. This is a well understoodconcept to differentiate releases of software. As the version increases it isexpected that new features are introduced and old bugs are removed (hopefullymore are removed than added)./p>p>Versioning distributions and releasing the versions separately is a commonpractice, employed by most if not all distributions out there. Ubuntu hasadopted the policy of releasing regularly and quite often. But there is adifferent approach it revolves around a concept I call Versionless where youdo not have a hard release but instead let the changes trickle down. In theapplication world these releases are often called nightly builds. Withdistributions it is a little bit different./p>p>First of all its worth noting that distributions are not like applications.Distributions are collection made up by applications and a kernel, theapplications that are included are usually stable releases and so the biggestunpredictability comes from the combination and configuration there of. As aresult one of the important roles for distro developers is to ensure that thecombination of the many applications does not lead to adverse side effects.This is done in several ways, the general method is to mix all theapplications in a pot, the so called pre-release and then test thecombination. The testing is done by whole community, as users often installthese pre-releases to see if they see any quirks through their regular use.When the pre-release becomes stable enough it is pushed out the door as apublic release./p>p>In an ideal world after this whole process all the major bugs and issues wouldhave been resolved and users go on to re-install/update their distributioninstallations to the new release -- without any issues. The problem is thateven if the tests passed with flying colors does not mean that on the userwill not experience problems. The more complicated a configuration that a userhas the more chances they will notice bugs as part of upgrade. This isparticularly evident where there are multiple interacting systems. Doing afull upgrade of a distribution it is not always obvious what change in theupdate has caused this problem./p>p>Versionless distributions are nothing new, they has been a staple of Debianfor a while. In fact it is the process for testing package compatibilitybetween release, but it is also a lot more. There are two Debian releases thatfollow this paradigm, a hrefhttp://wiki.debian.org/DebianTesting>Debian Testing/a>and a hrefhttp://wiki.debian.org/DebianUnstable>Debian Unstable/a>. As applicationsare packaged they are added to Debian Unstable and after they fulfill certaincriteria, IE they have spent some time in Unstable and have not had anycritical bugs filed against them, they are then passed along to DebianTesting. Users are able to balance their needs between new features andstability by selecting the corresponding repository. As soon as the packagesare added to the repositories the become immediately available to user forinstall/upgrade./p>p>What it really comes down to is testing outside your environment is useful butit cannot be relied solely upon. And when upgrades are performed it isimportant to know what has changed and how to undo it. Keeping track ofchanges for 1000s of updates is nearly impossible. So update small and updateoften, use Debian. Good packages managers are your best friend, but onlysecond to great package developers!/p> span classcategory> a href./tag/debian.html>Debian/a> a href./tag/lilug.html>LILUG/a> a href./tag/linux.html>linux/a> a href./tag/software.html>software/a> /span> span classdate>a href./versionless-distro.html relbookmark titlePermalink to Versionless Distro>2010-05-14T19:03:54-04:00/a>/span> /div> div classcontent> span classsubject>a href./monitor-hot-plugging-linux-kde.html relbookmark titlePermalink to Monitor hot plugging. Linux & KDE>Monitor hot plugging. Linux & KDE/a>/span> br/> p>Apparently Linux does not have any monitor hotplugging support which is quitea pain. Every time you want to attach a monitor to laptop you have toreconfigure the display layout. This is a tad frustrating if you have to dothis several times a day. And it doesnt help that KDE subsystems are a bitflaky when it comes to changing display configuration. Ive had plasma crash aon me 1/3 times while performing this operation./p>p>Long story short I got fed up with all of this and wrote the following 3 linescript to automate the process and partially alleviate this head ache/p>div classhighlight>pre>span>/span>code>span classerr> #!/bin/bash/span>span classerr> xrandr --output LVDS1 --auto --output VGA1 --auto/span>span classerr> sleep 1/span>span classerr> kquitapp plasma-desktop &> /dev/null/span>span classerr> sleep 1/span>span classerr> kwin --replace & &> /dev/null/span>span classerr> sleep 1/span>span classerr> kstart plasma-desktop &> /dev/null/span>/code>/pre>/div>p>You probably need to adjust the xrandr line to make it behave like you wantbut auto everything works quite well for me. Check man page for xrandr fordetails./p>p>For further reading on monitor hot plugging I encourage you read a hrefhttps://bugs.launchpad.net/ubuntu/+source/xorg-server/+bug/306735>launchpadbug #306735/a>. Fortunately there are solutions for this problem, howeverthey are on the a hrefhttp://msdn.microsoft.com/en-us/library/ff568431%28VS.85%29.aspx>other side of the pond/a>./p>p>em>Update:/em> Added the kwin replace line to fix sporadic malfunction of kwin(disappearance of window decorations) during this whole operation./p> span classcategory> a href./tag/lilug.html>LILUG/a> a href./tag/code.html>code/a> a href./tag/debian.html>debian/a> a href./tag/kde.html>kde/a> a href./tag/linux.html>linux/a> a href./tag/software.html>software/a> /span> span classdate>a href./monitor-hot-plugging-linux-kde.html relbookmark titlePermalink to Monitor hot plugging. Linux & KDE>2010-04-10T16:58:58-04:00/a>/span> /div> div classcontent> span classsubject>a href./flash-still-crawling.html relbookmark titlePermalink to Flash -- still crawling,>Flash -- still crawling,/a>/span> br/> p>Flash is an absolute resource drain youve probably noticed how it completelyhogs resources when you watch a video. Ever wonder how much more power isconsumed watching flash over a regular video file? Is it a significant number?For those too lazy to read the rest, the simple answer is yes. And now to thedetails./p>p>Recently I was watching a hulu video on a 1080P monitor and I noticed it was alittle choppy. I decided to conduct an experiment and actually measure thedifference in resource, power utilization between flash and h.264 (inmplayer). Not having the desire to make a video and encode it for flash andh.264 I randomly chose a trailer which was sufficiently long and was widelyavailable in multiple formats. Tron Legacy, conveniently available througha hrefhttp://www.youtube.com/watch?vL9szn1QQfas>youtube/a> and a hrefhttp://thepiratebay.org/torrent/5471227/Tron_Legacy_Official_Trailer_HD_1080p_-----_MAAZ>The Pirate Bay/a> in 1080P, excellent./p>p>In a more or less idle state my laptop draws around 1500mA of current(according to ACPI), CPU utilization is around 3% and clock averaged bothcores is somewhere around 1.5Ghz (1Ghz min 2Ghz max .25Ghz step size utilizingthe on-demand CPU frequency governor). Firing up the video through youtube inwindowed mode (which scales the video to around 800pixels) The CPU utilizationjumps up to around 85% and current draw to around 44000mA clock is continuallykept at 2Ghz on both cores. Setting the movie to full screen (1080 pixelswide) decreases CPU usage to 70% and current draw to 3500mA, this might soundcounter intuitive but it makes perfect sense as at 1920 wide the video is innative resolution and does not need to be scaled (This actually demonstratesthat Flash does not make good use of the hardware scaling AKAa hrefhttp://en.wikipedia.org/wiki/X_video_extension>Xv/a>). Viewing the same 1080ptrailer in a hrefhttp://www.mplayerhq.hu>mplayer/a>, does reduce CPU load andcurrent draw. Size of the video window does not matter much scaling it toabout 800pixels or viewing in native 1920 pixels wide results in same numbers,thanks to mplayers Xv support. CPU utilization is around 40% and CPU doesquite frequently clock down to reduce power consumption, current draw isaround 3000mA./p>p>So what does all of this mean. Assuming the voltage at the built in ACPIammeter is equal to battery voltage (11.1V) that means the difference in powerconsumption between playing a video in flash vs Mplayer h.264 is aboutequivalent to medium strength CFL light bulb (1.5A*11.1V15watts). Now thisexperiment is completely unscientific and has many flaws, primarily perhapsthat I use Linux 64 bit flash player (10,0,42,34) the vast majority of flashusers are obviously on windows and its possible that it runs better on windowsplatforms but I wouldnt bet money on that./p>p>It makes me wonder if google is supposedly so concerned about beinga hrefhttp://www.google.com/corporate/green/>green/a> maybe they should think aboutswitching the default video format for youtube. We can do some interestingestimations. Lets assume that the average user of youtube watches 10 minutesworth of content in the default flash format, that means they consume about (10hours * 15watts / 60 minutes in an hour * 52 weeks in a year / 1000 watthours in megawatt hours) .13 kilowatt hours per year more than using otherformats. This does not sound like all that much but, assuming that 5% of theworld population fits into this category it equals to about 40 000 000kilowatts of power that could be saved. What does this number really mean? Iinvite you to go to the a hrefhttp://www.epa.gov/RDEE/energy-resources/calculator.html>EPA Greenhouse calculator/a> and plug it in. Youll see its equivalentto annual emission of 5500 cars. Again the numbers are completely unscientificbut even if they are off by a factor of 3, it is still a significant number.It would be nice for someone to conduct a more thorough investigation./p>p>While conducting this experiment I noticed something interesting. Playing the1080p video in youtube would work fine for the first 1.5 min but then it wouldget choppy. The full trailer was fully downloaded so it didnt make muchsense. Firing up KDE System monitor I was able to quite quickly to figure outthe problem. As the video got choppy the CPU clock would drop while usageremained high, clearly the problem must be with cooling. System monitor wasreporting CPU temperature of about 100C and power consumption of almost6000mA. It had been a while since I cleaned the inside of my laptop, so Istripped it apart and took out a nice chunk of dust that was between theradiator and the fan. After this CPU temperature never went above 85C andcurrent draw was at a much more reasonable 4400 while playing the flash video.Hopefully this will resolve my choppy hulu problem./p>p>The graphs of this experiment are available. The a href./images/flashsux_flash.png>flashgraph/a>, at first the scaletrailer was played following by full screen. For the a href./images/flashsux_mplayer.png>mplayergraph/a> the inverse was done,first full screen then scaled .. but it doesnt matter much for mplayer./p> span classcategory> a href./tag/lilug.html>LILUG/a> a href./tag/wwts.html>WWTS/a> a href./tag/software.html>software/a> /span> span classdate>a href./flash-still-crawling.html relbookmark titlePermalink to Flash -- still crawling,>2010-04-07T22:42:19-04:00/a>/span> /div> div classcontent> span classsubject>a href./en-guarde-la-ou-est-le-salut.html relbookmark titlePermalink to En guarde? La ou est le salut?>En guarde? La ou est le salut?/a>/span> br/> p>In reply to a hrefhttp://www.josefsipek.net/>Josef Jeff Sipeks/a>a hrefhttp://www.josefsipek.net/blahg/?p365>reply/a> to my post entitle a hrefhttp://dotcommie.net/feed/index.php?id153>SMTP --time to chuck it/a> from a couple ofyears ago./p>blockquote>p>This is a (long overdue) reply to a hrefhttp://dotcommie.net/feed/>Ilya/a>s post:a hrefhttp://dotcommie.net//feed/index.php?id153>SMPT -- Time to chuck it/a>./p>p>.../p>blockquote>p>There are two apparent problems at the root of the SMTP protocol whichallow for easy manipulation: lack of authentication and sender validation, andlack of user interaction. It would not be difficult to design a more flexibleprotocol which would allow for us to enjoy the functionality that we arefamiliar with all the while address some, if not all of the problems withinSMTP./p>p>To allow for greater flexibility in the protocol, it would first be brokenfrom a server-server model into a client-server model./p>/blockquote>p>This is first point I 100% disagree with.../p>blockquote>p>That is, traditionally when one would send mail, it would be sent to alocal SMTP server which would then relay the message onto the next serveruntil the email reached its destination. This approach allowed for emailcaching and delayed-send (when a (receiving) mail server was off-line forhours (or even days) on end, messages could still trickle through as thesending server would try to periodically resend the messages.) Todays mailservers have very high up times and many are redundant so caching email fordelayed delivery is not very important./p>/blockquote>p>Delayed delivery is not very important?! What? What happened to the wholebetter late than never idiom?/p>p>It is not just about uptime of the server. There are other variables onemust consider when thinking about the whole system of delivering email. Heresa short list; Im sure Im forgetting something:/p>ul>li>server uptime/li>li>server reliability/li>li>network connection (all the routers between the server and the source)uptime/li>li>network connection reliability/li>/ul>p>It does little to no good if the network connection is flakey. Ilya isarguing that thats rarely the case, and while I must agree that it isnt asbad as it used to be back in the 80s, I also know from experience thatnetworks are very fragile and it doesnt take much to break them./p>p>A couple of times over the past few years, I noticed that my ISPs routingtables got screwed up. Within two hours of such a screwup, things returned tonormal, but thats 2 hours of downtime./p>p>Another instance of a network going haywire: one day, at a hrefhttp://www.stonybrook.edu>Stony BrookUniversity/a>, the internet connection stoppedworking. Apparently, a compromised machine on the university campus caused acampus edge device to become overwhelmed. This eventually lead to a completefailure of the device. It took almost a day until the compromised machine gotdisconnected, the failed device reset, and the backlog of all the traffic onboth sides of the router settled down./p>p>Failures happen. Network failures happen frequently. More frequently that Iwould like them to, more frequently than the network admins would like themto. Failures happen near the user, far away from the user. One can hope thatdynamic routing tables keep the internet as a whole functioning, but eventhose can fail. Want an example? Sure. Not that long ago, the well know videorepository a hrefhttp://www.youtube.com>YouTube/a> disappeared off the face of theEarth...well, to some degree. As this a hrefhttp://www.ripe.net/news/study-youtube-hijacking.html>RIPE NCC RIS casestudy/a> shows, onFebruary 24, 2008, Pakistan Telecom decided to announce BGP routes forYouTubes IP range. The result was, that if you tried to access any ofYouTubes servers on the 208.65.152.0/22 subnet, your packets were directed toPakistan. For about an hour and twenty minutes that was the case. Then YouTubestarted announcing more granular subnets, diverting some of the traffic backto itself. Eleven minutes later, YouTube announced even more granular subnets,diverting large bulk of the traffic back to itself. Few dozen minutes later,PCCW Global (Pakistan Telecoms provider responsible for forwarding theoffending BGP announcements to the rest of the world) stopped forwarding theincorrect routing information./p>p>So, networks are fragile, which is why having an email transfer protocolthat allows for retransmission a good idea./p>/blockquote>p>em>Pas touche!/em> I have not conducted extensive surveys of mail serverconfigurations, but, from personal experience; most mail server give up onsending email a lot sooner than recommended. a hrefhttp://www.ietf.org/rfc/rfc2821.txt>RFC2821/a> calls for a 4-5 day period. This isa reflection of the times, email is expected to deliver messages almostinstantaneously (Just ask Ted Stevens!)./p>p>As you are well aware I am not implying that networks are anywhere nearperfect, it just does not matter. If you send a message and it does not getdelivered immediately your mail client would be able to tell you so. Thisallows you to reacts, had the message been urgent you can use other forms ofcommunication to try to get it through (phone /gasp>). The client can alsoqueue the message (assuming no CAPTCHA system, more on that later) and try todeliver it later. Granted machines which run clients have significantlyshorter uptimes than servers but is it really that big of a deal, especiallynow that servers give up on delivery just a few hours after first attempt?/p>p>I, for one, am looking forward to the day when I no longer have to ask mypotential recipient whether or not they have received my message./p>blockquote>blockquote>p>Instead, having direct communication between the sender-client and thereceiver-server has many advantages: opens up the possibility for CAPTCHAsystems, makes the send-portion of the protocol easier to upgrade, and allowsfor new functionality in the protocol./p>/blockquote>p>Wow. So much to disagree with!/p>ol>li>CAPTCHA doesnt work/li>li>What about mailing lists? How does the mailing list server answer theCAPTCHAs?/li>li>How does eliminating server-to-server communication make the protocoleasier to upgrade?/li>li>New functionality is a nice thing in theory, but what do you want fromyour mail transfer protocol? I, em>personally/em>, want it to transfer my emailbetween where I send it from and where it is supposed to be delivered to./li>li>If anything eliminating the server-to-server communication would causethe MUAs to be in charge of the protocols. This means that at first therewould be many competing protocols, until one takes over - not necessarily thebetter one (Betamax vs. VHS comes to mind)./li>li>What happens in the case of overzealous firewall admins? What if Ireally want to send email to bob@example.com, but the firewall (for whateverreason) is blocking all traffic to example.com?/li>li>em>Touche!/em> I have to admit CAPTCHAs are a bit ridiculous in this application./li>li>See above/li>li>By creating more work for admins. It allows users to more directly complain to the admins that the new protocol feature does not work. Yes I know admins want less work and fewer complaining users, but there are benefits. It really comes down to the fact that with more interactivity it is easier to react to changes, servers do not have brains but the people behind their clients do./li>li>Hopefully that will still happen./li>li>Well the worse protocol is already winning SMTP, dMTP (dot Mail Transfer Protocol) is so much better even if it is quite vague. MUAs will not be in charge, if they don not play ball then mail will not be delivered./li>li>Now you are just getting ahead of yourself. Stop making up problems. The solution to overzealous admins, is their removal..../li>/ol>blockquote>p>And so this brings us to the next point, authentication, how do you knowthat the email actually did, originate from the sender. This is one of thelargest problems with SMTP as it is so easy to fake ones outgoing emailaddress. The white list has to rely on a verifiable and consistent flag in theemail. A sample implementation of such a control could work similar to thecurrent hack to the email system, SPF, in which a special entry is made in theDNS entry which says where the mail can originate from. While this approach isquite effective in a sever-server architecture it would not work in a client-server architecture. Part of the protocol could require the sending client tosend a cryptographic-hash of the email to his own receiving mail server, sothat the receiving partys mail server could verify the authenticity of thesource of the email. In essence this creates a 3 way handshake between thesenders client, the senders (receiving) mail server and the receivers mailserver./p>/blockquote>p>I tend to stay away from making custom authentication protocols./p>p>In this scheme, what guarantees you that the client and his home serverarent both trying to convince the receiving server that the email is reallyfrom whom they say it is? In kerberos, you have a key for each system, and apassword for each user. The kerberos server knows it all, and this centralauthority is why things work. With SSL certificates, you rely on the strengthof the crypto used, as well as blind faith in the certificate authority./p>/blockquote>p>They might, the point is not so much to authenticate the user but to link himto a server. If the server he is linked to is dirty, well you can blacklistit. Much of the spam today is sent from bot-nets, in this schema all theindividual botnet senders would have to link themselves to a server.Obviously, a clever spammer would run a server on each of the zombie machinesto auth for itself. The catch is that he would have to ensure that theFirewalls/NATs are open and that there is a (sub-) domain pointing back at theserver. This is all costly for the spammer and for the good guy itll be easyto trace down the dirty domains./p>blockquote>blockquote>p>At first it might seem that this process uses up more bandwidth andincreases the delay of sending mail but one has to remember that in usualconfiguration of sending email using IMAP or POP for mail storage oneundergoes a similar process,/p>/blockquote>p>Umm...while possible, I believe that very very large majority of email issent via SMTP (and Im not even counting all the spam)./p>/blockquote>p>Carton jaune, I addressed that issue in my original posting which is just 2sentences below this one. Excessive lobotomy is not appreciated./p>blockquote>blockquote>p>first email is sent for storage (over IMAP or POP) to the senders mailserver and then it is sent over SMTP to the senders email for redirection tothe receivers mail server. It is even feasible to implement hooks in the IMAPand POP stacks to talk to the mail sending daemon directly eliminating anadditional socket connection by the client./p>/blockquote>p>Why would you want to stick with IMAP and POP? They do share certain ideaswith SMTP./p>/blockquote>p>Carton rouge, I said nothing about sticking to IMAP/POP. The point is that thesystem can be streamlined somewhat./p>blockquote>blockquote>p>For legitimate mass mail this process would not encumber the sendingprocedure as for this case the sending server would be located on the samemachine as the senders receiving mail server (which would store the hash forauthentication), and they could even be streamlined into one monolithicprocess./p>/blockquote>p>Not necessarily. There are entire businesses that specialize in mailing listmaintenance. You pay them, and they give you an account with software thatmaintains your mailing list. Actually, its amusing how similar it is to whatspammers do. The major difference is that in the legitimate case, the customersupplies their own list of email address to mail. Anyway, my point is, inthese cases (and they are more common than you think) the mailing sender is ona different computer than the from domains MX record./p>/blockquote>p>I do not think that increasing the burden on mass mailers even good ones issuch a bad thing./p>blockquote>p>.../p>p>I really cant help but read that as If we use this magical protocol thatwill make things better, things will get better! Sorry, but unless I see someprotocol which would be a good candidate, I will remain sceptical./p>/blockquote>p>And I can not help but read this as We should not think about improvingprotocols because it impossible to do better. In any case I appreciate yourmal-pare. The discussion is important as letting protocols rot is not a goodidea./p>blockquote>p>.../p>/blockquote> span classcategory> a href./tag/lilug.html>LILUG/a> a href./tag/wwts.html>WWTS/a> a href./tag/news.html>news/a> a href./tag/software.html>software/a> /span> span classdate>a href./en-guarde-la-ou-est-le-salut.html relbookmark titlePermalink to En guarde? La ou est le salut?>2009-04-22T10:47:24-04:00/a>/span> /div> div classcontent> span classsubject>a href./eric-s-raymond-speaks-heresy.html relbookmark titlePermalink to Eric S. Raymond speaks heresy.>Eric S. Raymond speaks heresy./a>/span> br/> p>Recently my local LUG (a hrefhttp://lilug.org>LILUG/a>) invited a hrefhttp://www.catb.org/~esr/>Eric S.Raymond/a> (ESR) to come and speak. For those of youwho are not familiar with ESR, he is one of the three largest icons of theOpen Source/Free Software movement. Needless to say, it was an honor so seehim speak. For the most part, his talk was quite tame but one of the points heraised seemed quite controversial. According to him the GPL and other virallicenses are no longer needed as they do more harm than good to the community.I dont want to put words into his mouth so Ive transcribed what he saidduring the talk. You can view the a hrefhttp://www.archive.org/details/LILUG_20090310_ESR>ESR Q/Atalk/a> in its entirety, thisspecific excerpt is about 45 minutes into the video./p>blockquote>p>What is the point of being famous and respected if you cant speak heresyabout your own movement. What is the point?/p>p>One of my heretical opinions is that we worry way too much about licensing.And in particular; I dont think we really need reciprocal licensing. I dontthink we need licenses like the GPL, that punish people for taking codeclosed-source. Let me explain what I think. And then Ill explain why thefact we dont actually need those licenses matters./p>p>I dont think we need them because. There has been a fair amount of economicanalysis done in the last 10 years, significant amount of it has been done by,well, me. Which seems to demonstrate that open source is what the economistcall a more efficient mode of production use, superior mode of production. Youget better investment, better return out of the resources you invested bydoing open source development than closed source development. In particular,there have been a number of occasions on which people have taken open sourceproducts that were reasonable successful, and just taken them closed.Effectively putting them under proprietary control, proprietary licensing andthen tried to make a business model out of that. They generally fail. And thereason they fail is pretty simple. That is because when you take a productclosed, you are now limited to what ever small number of developers that yourcorporation can afford to hire. The open source community that you just turnedyour back on does not, they have more people than you. They can put outreleases more frequently, getting more user feedback. So the suggestion is,simply because of the numerical dynamics of the process: taking open softwareclosed is something that the market is going to punish. You are going to lose.The inefficiencies inherent in closed source development are eventually goingto ambush you, going to inaudible you, and your are not going to have abusiness model or product anymore. Weve seen this happened number of times./p>p>But now, lets look at the implications of taking this seriously. Thequestion I found myself asking is: if the market punished people for takingopen source closed, then why do our licenses need to punish people for takingopen source closed? That is why I dont think you really need GPL or areciprocal licenses anymore. It is attempting to prevent the behavior that themarket punishes anyway. That attempt has a downside, the downside is thatpeople, especially lawyers, especially corporate bosses look at the GPL andexperience fear. Fear that all of their corporate secrets, business knowledge,and special sauce will suddenly be everted to the outside world by someinadvertent slip by some internal code. I think that fear is now costing usmore than the threat of inaudible. And that is why I dont we need the GPLanymore./p>p>-- Eric S. Raymond/p>/blockquote>p>Eric then went on to say that the BSD license is a good alternative to theGPL. This has sparked a heated discussion on the a hrefhttp://freesoftwareroundtable.org/>Free Software RoundTable/a>(a hrefhttp://freesoftwareroundtable.org/>FSRT/a>) radio shows mailing list. Whileone can admire of the simplicity and clarity of the license it seems farfetched to say that it should be replacing the GPL. While yes there areeconomical incentive for corporations to keep code Open Source but therelative cost of closing the source depends largely on the size of company.Yes some small companies will not be able to afford to keep a code base alivewith internal/contracted developers for larger companies the costs are a loteasier to digest./p>p>Prime example of such a large company is a hrefhttp://apple.com>Apple/a>. In 2001Apple came out with a completely new version of its operating system, MAC OSX. Although a successor to MAC OS 9, it was very different. OS X borrowed avery large code base from the BSDs, and some (pretty much everything butDarwin) of the code was effectively closed. This has not prevented Apple or OSX from thriving./p>p>From the other end of the spectrum, are the companies such as MySQL AB whichproduce Free Software but also sell closed source licenses of the same codefor a living. There is a market for this, it exists because of those scaredlawyers and corporate bosses. Killing the GPL would effectively kill thismarket, as a result development on some of these projects would slow downsignificantly./p>p>The Open Source/Free Software movement is thriving, it does not mean its agood time to kill the GPL. In fact I dont think there will ever be a timewhen killing the GPL will do more good than harm./p> span classcategory> a href./tag/lilug.html>lilug/a> a href./tag/news.html>news/a> a href./tag/software.html>software/a> /span> span classdate>a href./eric-s-raymond-speaks-heresy.html relbookmark titlePermalink to Eric S. Raymond speaks heresy.>2009-03-23T11:30:14-04:00/a>/span> /div>p classpaginator> Page 1 / 4 a href./index2.html>»/a>/p> /div> /div> /div> div idmenu> div classinnertube> a href/feeds/atom.xml titlefeed>img src./images/rss.png>/a>/li> a href/ titleBlog>img src./images/blog.png>/a>/li> a hrefhttps://github.com/IlyaSukhanov titleProjects>img src./images/gear.png>/a>/li> a href/pages/contact.html titleContact>img src./images/letter.png>/a>/li> a href/gallery/index.html titleGallery>img src./images/landscape.png>/a>/li> p classpaginator> a href./index2.html titlenext>img src./theme/rarr.png altnext/>/a> /p> /div> /div> /div> /body>/html>
View on OTX
|
View on ThreatMiner
Please enable JavaScript to view the
comments powered by Disqus.
Data with thanks to
AlienVault OTX
,
VirusTotal
,
Malwr
and
others
. [
Sitemap
]