Thursday, November 21, 2013

iFail


I know iTunes on my MacBook is missing some songs I just purchased on my iPad, so I click the menus .. "Store" -> "Check for available downloads" and it tells me "All purchases have been downloaded..."
Huh!? well, next when I go to the Purchases screen (a list of my purchases) and choose to filter by "Not in My Library" it shows me my available downloads. Am I nuts?? Sure enough, I click "Check for available updates" again and again I am told. "All purchases have been downloaded ..."

They should rename this app to iLie.

Saturday, November 9, 2013

OS X Mountain Lion Server - Profile Manager / Wiki, Start Up Errors

Errors which relate to the issue (separate error on each separate line below):

ProfileManager[1318]: Retry #[n] of database migration...

devicemgrd: Terminating on unhandled exception Rake command failed with 256 at /Applications/Server.app/Contents/ServerRoot/usr/share/devicemgr/webserver/devicemgrd ...

The error occurred while reading settings for the Profile Manager service.

servermgr_wiki: No attempt was made to create Wiki file data store directory

References I used to try to fix the issue from other folks having similar issues:

https://discussions.apple.com/message/23350331#23350331
https://discussions.apple.com/message/19515803#19515803
http://forums.macrumors.com/showthread.php?t=1411450
https://discussions.apple.com/message/23190851#23190851
https://discussions.apple.com/message/20334099#20334099
https://discussions.apple.com/thread/3189397?start=30&tstart=0
http://support.apple.com/kb/ht5139 (this was too drastic in my opinion to even consider)

The real problem:

I used to have my Server Service Data on an external volume mounted at /Volumes/OSXServerData. To keep the Service Data for Profile Manage, the Wiki, and indeed all server services, on another volume other than the startup volume, one simply needs to open Server.app, select the host, click Settings then click the Edit button the same line where it says "Service Data:" and shows which volume the Service Data is currently on. Please refer to this URL for more info: http://support.apple.com/kb/HT4974 -- It is important to note in that page that is says:

"Important: Do not change the name of the service data storage volume after you designate it in Server app."

For one thing, this means that you should not edit this setting, AFTER you have already removed or renamed the volume. Apple requires that you change the Service Data volume BEFORE removing the volume. For one thing, this is so that the functionality in the server app can copy the Service Data from the original location to the new volume you designate. There us a fundamental flaw to Apple's design herein. If the volume (disk) has crapped out you have little choice, but to specify a new volume without "change[ing] the name of the [current] service data storage volume" - that is because your crapped out drive where the service data was, is no longer accessible - obviously.

No worries. I just expect that once I specify a new volume, that Server.app will recreate the default settings in the new location. After all, the new volume does correctly show in the Settings tab after it is set. And indeed it does create the /Library/Server/ folder on the new volume .... and as expected, it is filled with all the goodies one would expect to see there. It gives the perfect appearance that it has successfully configured Server to use the new volume.

Alas, that is a lie. Keep in mind that the volume that crashed was mounted at /Volumes/OSXServerData thusly, the location of the service data used to be /Volumes/OSXServerData/Library/Server/.Upon deeper inspection of the log files, I found the following types of errors:
postgres dataDir /Volumes/OSXServerData/Library/Server/PostgreSQL For Server Services/Data does not exist as directory
.. and ..
Configured wiki FileDataPath /Volumes/OSXServerData/Library/Server/Wiki/FileData does not exist as directory
This basically told me that Server.app failed to reconfigure the volume path when the new Service Data volume was specified.

So what I had to do was search /Library/Server for any files containing the old volume mount point. Invariably they would be either config files, old config files which Server.app deprecated, or log files.
I used mc (Midnight Commander) to locate those files but you can use Finder to whatever you want to. Once I obtained the list of files, I used sudo nano /Library/Server/... and the path to the particular configuration file, to edit the path information which needed to be fixed.

The files you are looking for here end with .conf, .xml or .plist and are typically located in a Config sub directory.
Some examples are:
/Library/Server/Messages/Config/jabberd/router.xml
/Library/Server/Messages/Config/jabberd/sm.xml
/Library/Server/Mail/Config/dovecot/conf.d/10-mail.conf
/Library/Server/Software\ Update/Config/swupd.conf
/Library/Server/Calendar\ and\ Contacts/Config/caldavd.plist
/Library/Server/Mail/Config/dovecot/partition_map.conf
/Library/Server/Wiki/Config/collabd.plist
/Library/Server/Software\ Update/Config/swupd.plist

I simply ignored the files which has ".bak", "unusable" or "previous" in the path because these are obviously deprecated. Then I restarted the host and everything worked again. 

Thursday, October 24, 2013

PostgreSQL grant permissions on tables and sequences

PostgreSQL grant permissions on tables and sequences in selected schema for selected user:

 DO $$  
 DECLARE  
     _tables text := (  
         SELECT  
          string_agg(  
             'GRANT SELECT, INSERT, UPDATE ON '  
                 || table_schema || '.' || table_name  
                 ||' to my_user;',  
             E'\n')  
         FROM information_schema.tables   
         WHERE table_type = 'BASE TABLE' AND table_schema = 'my_schema'  
     );  
     _sequences text := (  
         SELECT  
          string_agg(  
             'GRANT USAGE ON ' || n.nspname || '.' || c.relname ||' to my_user;',  
             E'\n')  
         FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace  
         WHERE relkind='S' AND n.nspname = 'my_schema'  
     );  
 BEGIN  
     RAISE NOTICE E'\n%\n%', _sequences, _tables;  
 END;$$  

Note: I personally (normally) don't like to allow deletes on my tables from apps - feel free to add a DELETE grant if you need it.

Wednesday, October 2, 2013

PostgreSQL : Move your stuff out of the public schema

Using the default public schema is not recommended. If you have created a bunch of tables and functions in the public schema, you can use the following scripts to move them to a different schema:

Move tables:
  DO$$   
  DECLARE   
   row record;   
  BEGIN   
   FOR row IN SELECT tablename FROM pg_tables WHERE schemaname = 'public'   
   LOOP   
    EXECUTE 'ALTER TABLE public.' || quote_ident(row.tablename) || ' SET SCHEMA [new_schema];';   
   END LOOP;   
  END;$$;  

Move functions:
  DO  
 $do$  
 DECLARE  
   sql text;  
 BEGIN  
   SELECT INTO sql  
      string_agg(format('ALTER FUNCTION public.%I(%s) SET SCHEMA new_schema;'  
           ,p.proname, pg_get_function_identity_arguments(p.oid)), E'\n')  
   FROM  pg_proc p  
   JOIN  pg_namespace n ON n.oid = p.pronamespace  
   WHERE nspname = 'public';  
    -- and other conditions, if needed  
   RAISE NOTICE '%', sql; -- for viewing the sql before executing it  
   -- EXECUTE sql; -- for executing the sql  
 END  
 $do$  

Friday, July 26, 2013

RDBMS vs NoSQL

IOHO, to the uninitiated, the problem with choosing a NoSQL solution, comes firstly, not with choosing a NoSQL technology, but with defining NoSQL in terms of ones own requirements.

http://stackoverflow.com/questions/2608103/is-there-any-nosql-that-is-acid-compliant#2608157

Wednesday, May 29, 2013

Bad code vs "bad a__" code - I love this quote

"
Writing code that is unreadable because it's full of tricks isn't "bad ass" so much as just "bad".
"
Credits: http://stackoverflow.com/questions/1789945/method-like-string-contains-in-javascript#comment-10691511

Monday, April 29, 2013

Dynamic Tables With Mustache

Problem: Generate dynamic tables from a dynamic array with Mustache given that:

  1. Total column count is unknown
  2. Only one or two column names are known and must be rendered conditionally
  3. Helper functions many not be used
  4. Data is only provided in arrays. Not model classes
Typical data-set with variable column count where ID is the only column know to always be provided:

[id*]   [Col-1]    [Col-2]    [Col-3]   ...(more)
 1      'Foo'      'Bar'      'Baz'    ...(more)
 2      'Foo'      'Bar'      'Baz'    ...(more)
 3      'Foo'      'Bar'      'Baz'    ...(more)
 ...
(more)

Solution: Mix variating key names with constant key name

In this example below, the variating keys are based on the various column names provided dynamically from the datasource which are ("id"; "name"; "legal_name"; "email"; "signon_email"; "editable") and the constant key name is "field"

array (size=6)
  0 => 
    array (size=2)
      'id' => string '10' (length=2)
      'field' => string 'id' (length=2)
  1 => 
    array (size=2)
      'value' => string 'J. Doe' (length=8)
      'field' => string 'name' (length=8)
  2 => 
    array (size=2)
      'value' => string 'Jane Doe' (length=8)
      'field' => string 'legal_name' (length=8)
  3 => 
    array (size=2)
      'value' => string 'Jane@Doe.com' (length=12)
      'field' => string 'email' (length=12)
array (size=6)
  0 => 
    array (size=2)
      'id' => string '11' (length=2)
      'field' => string 'id' (length=2)
  1 => 
    array (size=2)
      'value' => string 'Jon Doe' (length=8)
      'field' => string 'name' (length=8)
  2 => 
    array (size=2)
      'value' => string 'John Doe' (length=8)
      'field' => string 'legal_name' (length=8)
  3 => 
    array (size=2)
      'value' => string 'John@Doe.com' (length=12)
      'field' => string 'email' (length=12)

The original data source's column name is provided which can be used in Mustache to know what field is being iterated whilst "field" key provides an invariable token name which can be used in Mustache to reference the value for the field as follows:

{{#rows}}
<tr>{{#fields}}
        <td>{{#id}}<a href="foo/{{id}}">{{id}}</a>{{/id}}
            {{^id}}{{field}}: {{value} {{/id}}
        </td>
    {{/fields}}
</tr>
{{/rows}}

The following is produced:
<tr>
        <td><a href="foo/10">10</a></td>
        <td>name: J Doe</td>
        <td>legal_name: Jane Doe</td>
        <td>email: Jane@Doe.com</td>
</tr>
<tr>
        <td><a href="foo/11">11</a></td>
        <td>name: Jon Doe</td>
        <td>legal_name: John Doe</td>
        <td>email: John@Doe.com</td>
</tr>

Wednesday, January 2, 2013

How to find distances relative to points of data in the same database

If you have a scenario where you need to calculate the distance in miles, between various point given as longitude and latitude, and these points are in the same database, then simply use the Haver-sine formula to calculate the distances:
 select 
    `origin`.`id` AS `o_id`,
    `destination`.`id` AS `d_id`,
    cast((3959 * 
        acos((((cos(radians(`origin`.`latitude`))
        * cos(radians(`destination`.`latitude`)))
        * cos((radians(`destination`.`longitude`)
        - radians(`origin`.`longitude`))))
        + (sin(radians(`origin`.`latitude`))
        * sin(radians(`destination`.`latitude`))))))
   as decimal (4 , 1 )) AS `miles_apart`
from `point_of_origin` `origin` join `destinations` `destination`;

mysqldump doesn't backup views as views

mysqldump does not dump views as views, but instead, dumps them as tables. Even then, the tables columns all come out as TINYINT(4). If you're not fortunate enough to have Percona's slick backup tools then you'll need another solution.

Here is an over simplified PHP script to get the job done. Simply pipe the output to a .sql file to get it into a neat SQL script file.

<?php
// Configuration for the DB Connection
$_db_name = "test";
$_db_host = "127.0.0.1";
$_db_user = "root";
$_db_pass = "";
$_db_port = '3306';
// ---- end configuration section
$mysqli = new mysqli($_db_host, $_db_user, $_db_pass, $_db_name, $_db_port);
if(!$mysqli) die("Connection error. Aborting\n");
$result = $mysqli->query("SELECT v.TABLE_NAME, v.VIEW_DEFINITION FROM INFORMATION_SCHEMA.VIEWS `v` WHERE v.TABLE_SCHEMA='test';");
if (!$result) die("The 1st query failed to return results. Aborting.\n");
$row = $result->fetch_all();
foreach($row as $a => $b)
{
    echo "CREATE VIEW `".$b[0]."` AS ".$b[1].";\n\n";
}