[Groonga-commit] groonga/gcs [master] Split codes for HTTP client from command-line.js to anotehr file

Back to archive index

YUKI Hiroshi null+****@clear*****
Wed Oct 17 15:42:21 JST 2012


YUKI Hiroshi	2012-10-17 15:42:21 +0900 (Wed, 17 Oct 2012)

  New Revision: 23ceba537e78434fc422a5a5ec6adef01f8a35b7
  https://github.com/groonga/gcs/commit/23ceba537e78434fc422a5a5ec6adef01f8a35b7

  Log:
    Split codes for HTTP client from command-line.js to anotehr file

  Copied files:
    lib/client.js
      (from lib/command-line.js)
  Modified files:
    bin/gcs-configure-default-search-field
    bin/gcs-create-domain
    bin/gcs-delete-domain
    bin/gcs-describe-domain
    lib/command-line.js

  Modified: bin/gcs-configure-default-search-field (+11 -8)
===================================================================
--- bin/gcs-configure-default-search-field    2012-10-16 14:35:15 +0900 (22859e4)
+++ bin/gcs-configure-default-search-field    2012-10-17 15:42:21 +0900 (7b615ab)
@@ -1,8 +1,9 @@
 #!/usr/bin/env node
 
 var CLI = require(__dirname + '/../lib/command-line').CommandLineInterface;
-var commandLine = new CLI();
+var Client = require(__dirname + '/../lib/client').Client;
 
+var commandLine = new CLI();
 commandLine
   .option('-d, --domain-name <domain name>',
           'The name of the domain that you are configuring. Required.',
@@ -13,25 +14,27 @@ commandLine
           String)
   .parse();
 
-commandLine.assertHaveDomainName();
+var client = new Client(commandLine);
+
+client.assertHaveDomainName();
 
 var domainName = commandLine.domainName;
 var fieldName = commandLine.hasOption('name') && commandLine.options.name;
-commandLine.assertDomainExistsHTTP(function() {
+client.assertDomainExists(function() {
   if (fieldName) {
-    commandLine.getIndexFieldStatus(domainName, fieldName, function(error, field) {
+    client.getIndexFieldStatus(fieldName, function(error, field) {
       if (field) {
         console.log('Setting "%s" as the default search field of "%s"...',
                     fieldName,
                     domainName);
-        commandLine.configurationAPI.UpdateDefaultSearchField(
+        client.configurationAPI.UpdateDefaultSearchField(
           {
             DomainName: domainName,
             DefaultSearchField: fieldName
           },
           function(error, result) {
             if (error)
-              commandLine.raiseFatalError(error);
+              client.raiseFatalError(error);
             console.log('Done.');
             process.exit(0);
           }
@@ -46,14 +49,14 @@ commandLine.assertDomainExistsHTTP(function() {
   } else {
     console.log('Resetting the default search field of "%s"...',
                 domainName);
-    commandLine.configurationAPI.UpdateDefaultSearchField(
+    client.configurationAPI.UpdateDefaultSearchField(
       {
         DomainName: domainName,
         DefaultSearchField: ''
       },
       function(error, result) {
         if (error)
-          commandLine.raiseFatalError(error);
+          client.raiseFatalError(error);
         console.log('Done.');
         process.exit(0);
       }

  Modified: bin/gcs-create-domain (+8 -5)
===================================================================
--- bin/gcs-create-domain    2012-10-16 14:35:15 +0900 (468e3ad)
+++ bin/gcs-create-domain    2012-10-17 15:42:21 +0900 (64b2700)
@@ -1,8 +1,9 @@
 #!/usr/bin/env node
 
 var CLI = require(__dirname + '/../lib/command-line').CommandLineInterface;
-var commandLine = new CLI();
+var Client = require(__dirname + '/../lib/client').Client;
 
+var commandLine = new CLI();
 commandLine
   .usage('--domain-name <domain name> [options]')
   .option('-d, --domain-name <domain name>',
@@ -10,20 +11,22 @@ commandLine
           String)
   .parse();
 
-commandLine.assertHaveDomainName();
+var client = new Client(commandLine);
+
+client.assertHaveDomainName();
 
 var domainName = commandLine.domainName;
-commandLine.getDomainStatus(domainName, function(error, domain) {
+client.getDomainStatus(function(error, domain) {
   if (domain) {
     console.log('The domain [' + domainName + '] already exists.');
     return process.exit(1);
   }
   console.log('Creating domain [' + domainName + ']');
-  commandLine.configurationAPI.CreateDomain(
+  client.configurationAPI.CreateDomain(
     { DomainName: domainName },
     function(error, result) {
       if (error)
-        commandLine.raiseFatalError(error);
+        client.raiseFatalError(error);
       console.log('Domain endpoints are currently being created. ' +
                   'Use gcs-describe-domain to check for endpoints.');
       process.exit(0);

  Modified: bin/gcs-delete-domain (+11 -8)
===================================================================
--- bin/gcs-delete-domain    2012-10-16 14:35:15 +0900 (3cd3bab)
+++ bin/gcs-delete-domain    2012-10-17 15:42:21 +0900 (d744ef0)
@@ -1,8 +1,9 @@
 #!/usr/bin/env node
 
 var CLI = require(__dirname + '/../lib/command-line').CommandLineInterface;
-var commandLine = new CLI();
+var Client = require(__dirname + '/../lib/client').Client;
 
+var commandLine = new CLI();
 commandLine
   .usage('--domain-name <domain name> [options]')
   .option('-d, --domain-name <domain name>',
@@ -12,23 +13,25 @@ commandLine
           'Delete the domain without prompting for confirmation.')
   .parse();
 
-commandLine.assertHaveDomainName();
-commandLine.assertDomainExistsHTTP(function() {
+var client = new Client(commandLine);
+
+client.assertHaveDomainName();
+client.assertDomainExists(function() {
   function doDelete(successMessage) {
-    commandLine.configurationAPI.DeleteDomain(
-      { DomainName: commandLine.domainName },
+    client.configurationAPI.DeleteDomain(
+      { DomainName: client.domainName },
       function(error, response) {
         if (error)
-          commandLine.raiseFatalError(error);
+          client.raiseFatalError(error);
         console.log(successMessage);
         process.exit(0);
       }
     );
   }
   if (commandLine.options.force) {
-    doDelete('Domain [' + commandLine.domainName + '] has been deleted successfully.');
+    doDelete('Domain [' + client.domainName + '] has been deleted successfully.');
   } else {
-    commandLine.confirm('Really delete? [' + commandLine.domainName + '] (y/N) ', function(ok){
+    commandLine.confirm('Really delete? [' + client.domainName + '] (y/N) ', function(ok){
       if (ok) {
         doDelete('Successfully deleted.');
       } else {

  Modified: bin/gcs-describe-domain (+14 -11)
===================================================================
--- bin/gcs-describe-domain    2012-10-16 14:35:15 +0900 (6cef8db)
+++ bin/gcs-describe-domain    2012-10-17 15:42:21 +0900 (f44075a)
@@ -1,8 +1,9 @@
 #!/usr/bin/env node
 
 var CLI = require(__dirname + '/../lib/command-line').CommandLineInterface;
-var commandLine = new CLI();
+var Client = require(__dirname + '/../lib/client').Client;
 
+var commandLine = new CLI();
 commandLine
   .option('-d, --domain-name <domain name>',
           'The name of the domain that you are creating. Required.',
@@ -13,6 +14,8 @@ commandLine
           String)
   .parse();
 
+var client = new Client(commandLine);
+
 function reportStatus(domain, indexFields, defaultSearchField) {
   console.log('=== Domain Summary ===');
   console.log('Domain Name: %s',
@@ -44,7 +47,7 @@ function reportStatus(domain, indexFields, defaultSearchField) {
   console.log('Fields:');
   console.log('=======');
   indexFields.forEach(function(indexField) {
-    console.log(commandLine.summarizeIndexFieldStatus(indexField));
+    console.log(client.summarizeIndexFieldStatus(indexField));
   });
   console.log('======================');
 }
@@ -70,16 +73,16 @@ function reportDomains(domains) {
 
   domains.forEach(function(domain) {
     var domainName = domain.DomainName;
-    commandLine.getIndexFieldStatuses(domainName, function(error, indexFields) {
+    client.getIndexFieldStatuses(domainName, function(error, indexFields) {
       if (error)
-        commandLine.raiseFatalError(error);
+        client.raiseFatalError(error);
       indexFieldStatuses[domainName] = indexFields;
       indexFieldStatusesCount++;
       tryDoReport();
     });
-    commandLine.getDefaultSearchField(domainName, function(error, defaultSearchFieldResult) {
+    client.getDefaultSearchField(domainName, function(error, defaultSearchFieldResult) {
       if (error)
-        commandLine.raiseFatalError(error);
+        client.raiseFatalError(error);
       defaultSearchFields[domainName] = defaultSearchFieldResult;
       defaultSearchFieldsCount++;
       tryDoReport();
@@ -87,17 +90,17 @@ function reportDomains(domains) {
   });
 }
 
-var domainName = commandLine.domainName;
+var domainName = client.domainName;
 if (domainName) {
-  commandLine.getDomainStatus(domainName, function(error, domain) {
+  client.getDomainStatus(function(error, domain) {
     if (error)
-      commandLine.raiseFatalError(error);
+      client.raiseFatalError(error);
     reportDomains([domain]);
   });
 } else {
-  commandLine.getDomainStatuses(function(error, domains) {
+  client.getDomainStatuses(function(error, domains) {
     if (error)
-      commandLine.raiseFatalError(error);
+      client.raiseFatalError(error);
     reportDomains(domains);
   });
 }

  Copied: lib/client.js (+43 -134) 57%
===================================================================
--- lib/command-line.js    2012-10-16 14:35:15 +0900 (9d66cbc)
+++ lib/client.js    2012-10-17 15:42:21 +0900 (5ce7194)
@@ -1,125 +1,30 @@
-var program = require('commander');
-var nroonga = require('./wrapped-nroonga');
-var Domain = require('./database/domain').Domain;
-var version = require('../package').version;
-var path = require('path');
-
 var awssum = require('awssum');
 var amazon = awssum.load('amazon/amazon');
 var CloudSearch = awssum.load('amazon/cloudsearch').CloudSearch;
 
-var defaultDatabasePath =
-      exports.defaultDatabasePath =
-      CommandLineInterface.defaultDatabasePath = process.env.GCS_DATABASE_PATH || process.env.HOME + '/.gcs/database/gcs';
-var defaultPort =
-      exports.defaultPort =
-      CommandLineInterface.defaultPort = process.env.GCS_PORT || 7575;
-var defaultBaseHost =
-      exports.defaultBaseHost =
-      CommandLineInterface.defaultBaseHost =
-        process.env.GCS_BASE_HOST || '127.0.0.1.xip.io:' + defaultPort;
-var defaultConfigurationHost =
-      exports.defaultConfigurationHost =
-      CommandLineInterface.defaultConfigurationHost =
-        process.env.GCS_CONFIGURATION_HOST || '127.0.0.1.xip.io:' + defaultPort;
-var defaultPrivilegedRanges =
-      exports.defaultPrivilegedRanges =
-      CommandLineInterface.defaultPrivilegedRanges =
-        process.env.GCS_PRIVILEGED_RANGES || '127.0.0.0/8';
-
-function CommandLineInterface() {
-  this.program = program;
-  this.reservedUsage = null;
-  this.reservedOptions = [];
+function Client(options  domainName, host) {
+  this.domainName = options.domainName;
+  this.host = options.host;
+  this.port = options.port;
 }
-CommandLineInterface.prototype = {
+Client.prototype = {
   get configurationAPI() {
     if (!this._couldSearch) {
       this._configurationAPI = new CloudSearch({
         accessKeyId: 'dummy-access-key-id',
         secretAccessKey: 'dummy-access-key',
       });
-      var CLI = this;
+      var self = this;
       this._configurationAPI.host = function() {
-        return CLI.options.baseHost.split(':')[0];
+        return self.host;
       };
       this._configurationAPI.addExtras = function(options, args) {
-        options.protocol = 'http';
-        options.port =  CLI.options.baseHost.split(':')[1] || CLI.options.port;
+        options.protocol = self.protocol || 'http';
+        options.port =  self.port;
       };
     }
     return this._configurationAPI;
   },
-  get domainName() {
-    return this.options.domainName;
-  },
-
-  get databasePath() {
-    return this.options.databasePath || defaultDatabasePath;
-  },
-  get context() {
-    return this._context ||
-           (this._context = new nroonga.Context(this.databasePath));
-  },
-  get domain() {
-    return this._domain ||
-           (this._domain = new Domain(this.options.domainName, this.context));
-  },
-  get options() {
-    return this.program;
-  },
-
-  parse: function() {
-    this.program.version(version);
-
-    if (this.reservedUsage)
-      this.program.usage.apply(this.program, this.reservedUsage);
-    else
-      this.program.usage('[options]');
-
-    this.reservedOptions.forEach(function(optionArguments) {
-      this.program.option.apply(this.program, optionArguments);
-    }, this);
-
-    this.program
-      .option('--database-path <path>',
-              'database path' +
-                '(GCS_DATABASE_PATH) ' +
-                '[' + defaultDatabasePath + ']',
-              String,
-              defaultDatabasePath)
-      .option('-p, --port <port>',
-              'specify port' +
-                '(GCS_PORT) ' +
-                '[' + defaultPort + ']',
-              Number,
-              defaultPort)
-      .option('--base-host <hostname>',
-              'The base host name assigned to the service ' +
-                '(GCS_BASE_HOST) ' +
-                '[' + defaultBaseHost + ']',
-              String,
-              defaultBaseHost);
-
-    this.program.parse(process.argv);
-
-    return this;
-  },
-  usage: function() {
-    this.reservedUsage = Array.prototype.slice.call(arguments, 0)
-    return this;
-  },
-  option: function() {
-    this.reservedOptions.push(Array.prototype.slice.call(arguments, 0));
-    return this;
-  },
-
-  prompt: function() {
-    return this.prompt.confirm.apply(this.program, arguments);
-  },
-  confirm: function() {
-    return this.program.confirm.apply(this.program, arguments);
-  },
 
   raiseFatalError: function(error) {
     if (typeof error != 'string')
@@ -135,6 +40,12 @@ CommandLineInterface.prototype = {
   },
 
   getDomainStatus: function(domainName, callback) {
+    if (typeof domainName == 'function') {
+      this.assertHaveDomainName();
+      callback = domainName;
+      domainName = this.domainName;
+    }
+
     var self = this;
     this.getDomainStatuses(
       { 'DomainNames.member.1' : domainName },
@@ -179,12 +90,22 @@ CommandLineInterface.prototype = {
     }
   },
 
-  getIndexFieldStatus: function(domainName, indexFieldName, callback) {
+  getIndexFieldStatus: function(options, callback) {
+    var domainName;
+    var fieldName;
+    if (typeof options == 'string') {
+      domainName = this.domainName;
+      fieldName = options;
+    } else {
+      domainName = options.domainName;
+      fieldName = options.fieldName;
+    }
+
     var self = this;
     this.configurationAPI.DescribeIndexFields(
       {
         DomainName: domainName,
-        'FieldNames.member.1': indexFieldName
+        'FieldNames.member.1': fieldName
       },
       function(error, response) {
         if (error)
@@ -200,17 +121,23 @@ CommandLineInterface.prototype = {
                       indexFields;
         // awssum cannot operate query options including ".", so we always get all index fields...
         indexFields = indexFields.filter(function(indexField) {
-          return indexField && indexField.Options.IndexFieldName == indexFieldName;
+          return indexField && indexField.Options.IndexFieldName == fieldName;
         });
         if (indexFields.length)
           callback(null, indexFields[0]);
         else
-          callback(indexFieldName + ' does not exist.', null);
+          callback(fieldName + ' does not exist.', null);
       }
     );
   },
 
   getIndexFieldStatuses: function(domainName, callback) {
+    if (typeof domainName == 'function') {
+      this.assertHaveDomainName();
+      callback = domainName;
+      domainName = this.domainName;
+    }
+
     var self = this;
     this.configurationAPI.DescribeIndexFields(
       { DomainName: domainName },
@@ -232,6 +159,12 @@ CommandLineInterface.prototype = {
   },
 
   getDefaultSearchField: function(domainName, callback) {
+    if (typeof domainName == 'function') {
+      this.assertHaveDomainName();
+      callback = domainName;
+      domainName = this.domainName;
+    }
+
     var self = this;
     this.configurationAPI.DescribeDefaultSearchField(
       { DomainName: domainName },
@@ -275,7 +208,7 @@ CommandLineInterface.prototype = {
              type + ' (' + summarizedOptions.join(' ') + ')';
   },
 
-  assertDomainExistsHTTP: function(callback) {
+  assertDomainExists: function(callback) {
     var domainName = this.domainName;
     var self = this;
     this.getDomainStatus(domainName, function(error, domain) {
@@ -283,30 +216,6 @@ CommandLineInterface.prototype = {
         self.raiseFatalError(domainName + ' does not exist. You must specify an existing domain name.');
       callback();
     });
-  },
-
-  assertDomainExists: function() {
-    if (!this.domain.exists())
-      this.raiseFatalError(this.domainName + ' does not exist. You must specify an existing domain name.');
-    return this;
-  },
-
-  hasOption: function(option) {
-    return this.program.rawArgs.indexOf('--' + option) > -1 ||
-           this.program.rawArgs.indexOf('-' + option) > -1;
-  },
-
-  hasTooManyExclusiveOptions: function(options) {
-    var havingOptions = options.map(function(option) {
-          return this.option[option] ? '*' : '' ;
-        }, this);
-    return havingOptions.join('').length > 1;
   }
 };
-exports.CommandLineInterface = CommandLineInterface;
-
-CommandLineInterface.resolve = function(possibleRelativePath) {
-  return path.resolve(process.cwd(), possibleRelativePath);
-};
-
-exports.Domain = CommandLineInterface.Domain = Domain;
+exports.Client = Client;

  Modified: lib/command-line.js (+7 -173)
===================================================================
--- lib/command-line.js    2012-10-16 14:35:15 +0900 (9d66cbc)
+++ lib/command-line.js    2012-10-17 15:42:21 +0900 (d92045b)
@@ -4,10 +4,6 @@ var Domain = require('./database/domain').Domain;
 var version = require('../package').version;
 var path = require('path');
 
-var awssum = require('awssum');
-var amazon = awssum.load('amazon/amazon');
-var CloudSearch = awssum.load('amazon/cloudsearch').CloudSearch;
-
 var defaultDatabasePath =
       exports.defaultDatabasePath =
       CommandLineInterface.defaultDatabasePath = process.env.GCS_DATABASE_PATH || process.env.HOME + '/.gcs/database/gcs';
@@ -33,26 +29,16 @@ function CommandLineInterface() {
   this.reservedOptions = [];
 }
 CommandLineInterface.prototype = {
-  get configurationAPI() {
-    if (!this._couldSearch) {
-      this._configurationAPI = new CloudSearch({
-        accessKeyId: 'dummy-access-key-id',
-        secretAccessKey: 'dummy-access-key',
-      });
-      var CLI = this;
-      this._configurationAPI.host = function() {
-        return CLI.options.baseHost.split(':')[0];
-      };
-      this._configurationAPI.addExtras = function(options, args) {
-        options.protocol = 'http';
-        options.port =  CLI.options.baseHost.split(':')[1] || CLI.options.port;
-      };
-    }
-    return this._configurationAPI;
-  },
+  // as option for Client
   get domainName() {
     return this.options.domainName;
   },
+  get host() {
+    return this.options.baseHost.split(':')[0];
+  },
+  get port() {
+    return this.options.baseHost.split(':')[1] || this.options.port;
+  },
 
   get databasePath() {
     return this.options.databasePath || defaultDatabasePath;
@@ -133,158 +119,6 @@ CommandLineInterface.prototype = {
       this.raiseFatalError('You must specify the domain name.');
     return this;
   },
-
-  getDomainStatus: function(domainName, callback) {
-    var self = this;
-    this.getDomainStatuses(
-      { 'DomainNames.member.1' : domainName },
-      function(error, domainStatuses) {
-        if (error)
-          self.raiseFatalError(error);
-        // awssum cannot operate query options including ".", so we always get all domains...
-        domainStatuses = domainStatuses.filter(function(domainStatus) {
-          return domainStatus && domainStatus.DomainName == domainName;
-        });
-        if (domainStatuses.length) {
-          callback(null, domainStatuses[0]);
-        } else {
-          callback(domainName + ' does not exist. You must specify an existing domain name.', null);
-        }
-      }
-    );
-  },
-
-  getDomainStatuses: function(options, callback) {
-    try {
-      var self = this;
-      if (!callback) callback = options;
-      var domainStatusesCallback = function(error, response) {
-          if (error)
-            self.raiseFatalError(error);
-          var domainStatuses = response.Body
-               .DescribeDomainsResponse
-               .DescribeDomainsResult
-               .DomainStatusList
-               .member;
-          if (!Array.isArray(domainStatuses))
-            domainStatuses = [domainStatuses];
-          callback(null, domainStatuses);
-        };
-      if (arguments.length > 1)
-        this.configurationAPI.DescribeDomains(options, domainStatusesCallback);
-      else
-        this.configurationAPI.DescribeDomains(domainStatusesCallback);
-    } catch(error) {
-      this.raiseFatalError(error);
-    }
-  },
-
-  getIndexFieldStatus: function(domainName, indexFieldName, callback) {
-    var self = this;
-    this.configurationAPI.DescribeIndexFields(
-      {
-        DomainName: domainName,
-        'FieldNames.member.1': indexFieldName
-      },
-      function(error, response) {
-        if (error)
-          self.raiseFatalError(error);
-
-        var indexFields = response.Body
-             .DescribeIndexFieldsResponse
-             .DescribeIndexFieldsResult
-             .IndexFields
-             .member;
-        indexFields = !indexFields ? [] :
-                      !Array.isArray(indexFields) ? [indexFields] :
-                      indexFields;
-        // awssum cannot operate query options including ".", so we always get all index fields...
-        indexFields = indexFields.filter(function(indexField) {
-          return indexField && indexField.Options.IndexFieldName == indexFieldName;
-        });
-        if (indexFields.length)
-          callback(null, indexFields[0]);
-        else
-          callback(indexFieldName + ' does not exist.', null);
-      }
-    );
-  },
-
-  getIndexFieldStatuses: function(domainName, callback) {
-    var self = this;
-    this.configurationAPI.DescribeIndexFields(
-      { DomainName: domainName },
-      function(error, response) {
-        if (error)
-          self.raiseFatalError(error);
-
-        var indexFields = response.Body
-             .DescribeIndexFieldsResponse
-             .DescribeIndexFieldsResult
-             .IndexFields
-             .member;
-        indexFields = !indexFields ? [] :
-                      !Array.isArray(indexFields) ? [indexFields] :
-                      indexFields;
-        callback(null, indexFields);
-      }
-    );
-  },
-
-  getDefaultSearchField: function(domainName, callback) {
-    var self = this;
-    this.configurationAPI.DescribeDefaultSearchField(
-      { DomainName: domainName },
-      function(error, response) {
-        if (error)
-          self.raiseFatalError(error);
-        try {
-          var defaultSearchField = response.Body
-                .DescribeDefaultSearchFieldResponse
-                .DescribeDefaultSearchFieldResult
-                .DefaultSearchField
-                .Options;
-          if (typeof defaultSearchField != 'string') defaultSearchField = '';
-          callback(null, defaultSearchField);
-        } catch(error) {
-          commandLine.raiseFatalError(error);
-        }
-      }
-    );
-  },
-
-  summarizeIndexFieldStatus: function(status) {
-    var type = status.Options.TextOptions ? 'text' :
-               status.Options.UIntOptions ? 'uint' :
-               status.Options.LiteralOptions ? 'literal' :
-               null;
-
-    var options = status.Options.TextOptions ||
-                  status.Options.UIntOptions ||
-                  status.Options.LiteralOptions;
-    var summarizedOptions = [];
-    if (type == 'text' || type == 'uint' || options.SearchEnabled == 'true')
-      summarizedOptions.push('Search');
-    if (type != 'uint' && options.FacetEnabled == 'true')
-      summarizedOptions.push('Facet');
-    if (type == 'uint' || options.ResultEnabled == 'true')
-      summarizedOptions.push('Result');
-
-    return status.Options.IndexFieldName + ' ' +
-             status.Status.State + ' ' +
-             type + ' (' + summarizedOptions.join(' ') + ')';
-  },
-
-  assertDomainExistsHTTP: function(callback) {
-    var domainName = this.domainName;
-    var self = this;
-    this.getDomainStatus(domainName, function(error, domain) {
-      if (error || !domain)
-        self.raiseFatalError(domainName + ' does not exist. You must specify an existing domain name.');
-      callback();
-    });
-  },
-
   assertDomainExists: function() {
     if (!this.domain.exists())
       this.raiseFatalError(this.domainName + ' does not exist. You must specify an existing domain name.');
-------------- next part --------------
HTML����������������������������...
Download 



More information about the Groonga-commit mailing list
Back to archive index