OSDN Git Service

ml-memcached.
authorvisor <visor@users.sourceforge.jp>
Tue, 2 Aug 2011 12:04:58 +0000 (21:04 +0900)
committervisor <visor@users.sourceforge.jp>
Tue, 2 Aug 2011 12:04:58 +0000 (21:04 +0900)
Makefile.conf
ext/ml-memcached.cc [new file with mode: 0644]
ext/ml-memcached.h [new file with mode: 0644]
lib/expr.cc
lib/expr.h
lib/motorenv.cc
lib/motorenv.h
modules/ml-formvar.cc
modules/ml-motor.cc
modules/ml-sendmail.cc

index 802481c..2c257a1 100644 (file)
@@ -2,6 +2,9 @@ UTF8JP = 1
 BSD = 1
 #Linux = 1
 
+MSRCS += ml-memcached.cc
+MLDADD += -lmemcached
+MSRCS += ml-db5.cc
 .ifdef UTF8JP
 MSRCS += ml-japanese.cc
 .endif
diff --git a/ext/ml-memcached.cc b/ext/ml-memcached.cc
new file mode 100644 (file)
index 0000000..6933ebf
--- /dev/null
@@ -0,0 +1,238 @@
+#include "ml-memcached.h"
+#include "motorconst.h"
+#include "ml.h"
+#include "mlenv.h"
+#include "motorenv.h"
+#include "ustring.h"
+#include "expr.h"
+#include <libmemcached/memcached.h>
+#include <time.h>
+#include <vector>
+#include <exception>
+
+#define MEMCACHED_LOCALHOST    "127.0.0.1"
+#define MEMCACHED_PORT         MEMCACHED_DEFAULT_PORT
+#define MEMCACHED_SOCKET       "memcached/cache.sock"
+
+/*DOC:
+==memcached module==
+
+*/
+
+/*DOC:
+===$memcached===
+ ($memcached [SUBFUNCTION...]) -> VALUE
+
+*/
+//#MFUNC       $memcached      ml_memcached    cMLMemcachedID
+MNode*  ml_memcached (MNode* cell, MlEnv* mlenv) {
+    MNode*  arg = cell->cdr ();
+    MLMemcached  obj (mlenv);
+    MNodePtr  ans;
+    memcached_return_t  rc;
+
+    if (obj.mem == NULL) {
+       throw (ustring (CharConst ("can't connect to the memcached server")));
+    }
+//    rc = memcached_server_add (obj.mem, MEMCACHED_LOCALHOST, MEMCACHED_PORT);
+    rc = memcached_server_add_unix_socket (obj.mem, mlenv->env->path_to_etc (ustring (CharConst (MEMCACHED_SOCKET))).c_str ());
+    rc = memcached_behavior_set (obj.mem, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1);
+
+    mlenv->setMStack (&obj);
+    ans = progn (arg, mlenv);
+    if (mlenv->breaksym ()
+       && (mlenv->breaksym ()->isNil () || eq (mlenv->breaksym (), cell->car ()))) {
+       mlenv->setBreaksym (NULL);
+    }
+
+    return mlenv->retval = ans ();
+}
+
+/*DOC:
+===subfunctions of $memcached===
+
+*/
+/*DOC:
+====cache-set====
+ (cache-set KEY VALUE [:expire TIMESEC]) -> NULL
+
+*/
+//#SFUNC       cache-set       ml_memcached_cache_set
+MNode*  ml_memcached_cache_set (MNode* cell, MlEnv* mlenv, MLFunc* mobj) {
+    MNode*  arg = cell->cdr ();
+    MLMemcached*  obj = MObjRef<MLMemcached> (mobj, cMLMemcachedID);
+    ustring  key;
+    ustring  val;
+    time_t  expire = 0;
+    memcached_return_t  rc;
+    std::vector<MNode*>  params;
+    std::vector<MNode*>  keywords;
+    static paramList  kwlist[] = {
+       {CharConst ("expire"), false},
+       {NULL, 0, 0}
+    };
+
+    setParams (arg, 2, &params, kwlist, &keywords, NULL);
+    key = eval_str (params[0], mlenv);
+    val = eval_str (params[1], mlenv);
+    if (keywords[0]) {
+       expire = eval_int (keywords[0], mlenv);
+    }
+
+    rc = memcached_set (obj->mem, key.data (), key.length (), val.data (), val.length (), expire, 0);
+
+    return NULL;
+}
+
+/*DOC:
+====cache-get====
+ (cache-get KEY) -> STRING
+
+*/
+//#SFUNC       cache-get       ml_memcached_cache_get
+MNode*  ml_memcached_cache_get (MNode* cell, MlEnv* mlenv, MLFunc* mobj) {
+    MNode*  arg = cell->cdr ();
+    MLMemcached*  obj = MObjRef<MLMemcached> (mobj, cMLMemcachedID);
+    ustring  key;
+    char*  val;
+    size_t  valLen = 0;
+    uint32_t  flag;
+    memcached_return_t  rc;
+    MNode*  ans = NULL;
+
+    if (!arg) 
+       throw (uErrorWrongNumber);
+    key = eval_str (arg->car (), mlenv);
+    nextNode (arg);
+    if (arg) 
+       throw (uErrorWrongNumber);
+
+    val = memcached_get (obj->mem, key.data (), key.length (), &valLen, &flag, &rc);
+    if (val) {
+       ans = newMNode_str (new ustring (val, valLen));
+    }
+
+    return ans;
+}
+
+/*DOC:
+====cache-delete====
+ (cache-delete KEY [:expire TIMESEC]) -> NULL
+
+*/
+//#SFUNC       cache-delete    ml_memcached_cache_delete
+MNode*  ml_memcached_cache_delete (MNode* cell, MlEnv* mlenv, MLFunc* mobj) {
+    MNode*  arg = cell->cdr ();
+    MLMemcached*  obj = MObjRef<MLMemcached> (mobj, cMLMemcachedID);
+    ustring  key;
+    time_t  expire = 0;
+    memcached_return_t  rc;
+    std::vector<MNode*>  params;
+    std::vector<MNode*>  keywords;
+    static paramList  kwlist[] = {
+       {CharConst ("expire"), false},
+       {NULL, 0, 0}
+    };
+
+    setParams (arg, 1, &params, kwlist, &keywords, NULL);
+    key = eval_str (params[0], mlenv);
+    if (keywords[0]) {
+       expire = eval_int (keywords[0], mlenv);
+    }
+
+    rc = memcached_delete (obj->mem, key.data (), key.length (), expire);
+
+    return NULL;
+}
+
+/*DOC:
+====cache-increment====
+ (cache-increment KEY [:offset INTEGER] [:initial INTEGER] [:expire TIME]) -> NULL
+
+*/
+//#SFUNC       cache-increment ml_memcached_cache_increment
+MNode*  ml_memcached_cache_increment (MNode* cell, MlEnv* mlenv, MLFunc* mobj) {
+    MNode*  arg = cell->cdr ();
+    MLMemcached*  obj = MObjRef<MLMemcached> (mobj, cMLMemcachedID);
+    ustring  key;
+    memcached_return_t  rc;
+    uint64_t  offset = 1;
+    uint64_t  initial = 0;
+    time_t  expire = 0;
+    uint64_t  val;
+    std::vector<MNode*>  params;
+    std::vector<MNode*>  keywords;
+    static paramList  kwlist[] = {
+       {CharConst ("offset"), false},
+       {CharConst ("initial"), false},
+       {CharConst ("expire"), false},
+       {NULL, 0, 0}
+    };
+
+    setParams (arg, 1, &params, kwlist, &keywords, NULL);
+    key = eval_str (params[0], mlenv);
+    if (keywords[0]) {         // offset
+       offset = eval_int (keywords[0], mlenv);
+    }
+    if (keywords[1]) {         // initial
+       initial = eval_int (keywords[1], mlenv); // XXX: not uint64_t
+       if (keywords[2]) {      // expire
+           expire = eval_int (keywords[2], mlenv);
+       }
+       rc = memcached_increment_with_initial (obj->mem, key.data (), key.length (), offset, initial, expire, &val);
+    } else {
+       rc = memcached_increment (obj->mem, key.data (), key.length (), offset, &val);
+    }
+    
+    if (rc == MEMCACHED_SUCCESS) {
+       return newMNode_num (val);      // XXX: no uint64_t
+    } else {
+       return NULL;
+    }
+}
+
+/*DOC:
+====cache-decrement====
+ (cache-decrement KEY [:offset INTEGER] [:initial INTEGER] [:expire TIME]) -> NULL
+
+*/
+//#SFUNC       cache-decrement ml_memcached_cache_decrement
+MNode*  ml_memcached_cache_decrement (MNode* cell, MlEnv* mlenv, MLFunc* mobj) {
+    MNode*  arg = cell->cdr ();
+    MLMemcached*  obj = MObjRef<MLMemcached> (mobj, cMLMemcachedID);
+    ustring  key;
+    memcached_return_t  rc;
+    uint64_t  offset = 1;
+    uint64_t  initial = 0;
+    time_t  expire = 0;
+    uint64_t  val;
+    std::vector<MNode*>  params;
+    std::vector<MNode*>  keywords;
+    static paramList  kwlist[] = {
+       {CharConst ("offset"), false},
+       {CharConst ("initial"), false},
+       {CharConst ("expire"), false},
+       {NULL, 0, 0}
+    };
+
+    setParams (arg, 1, &params, kwlist, &keywords, NULL);
+    key = eval_str (params[0], mlenv);
+    if (keywords[0]) {         // offset
+       offset = eval_int (keywords[0], mlenv);
+    }
+    if (keywords[1]) {         // initial
+       initial = eval_int (keywords[1], mlenv); // XXX: not uint64_t
+       if (keywords[2]) {      // expire
+           expire = eval_int (keywords[2], mlenv);
+       }
+       rc = memcached_decrement_with_initial (obj->mem, key.data (), key.length (), offset, initial, expire, &val);
+    } else {
+       rc = memcached_decrement (obj->mem, key.data (), key.length (), offset, &val);
+    }
+    
+    if (rc == MEMCACHED_SUCCESS) {
+       return newMNode_num (val);      // XXX: no uint64_t
+    } else {
+       return NULL;
+    }
+}
diff --git a/ext/ml-memcached.h b/ext/ml-memcached.h
new file mode 100644 (file)
index 0000000..c3329f3
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef ML_MEMCACHED_H
+#define ML_MEMCACHED_H
+
+#include "ml.h"
+#include "ml-id.h"
+#include "ustring.h"
+#include <libmemcached/memcached.h>
+
+class  MNode;
+class  MlEnv;
+
+class  MLMemcached: public MLFunc {
+ public:
+    memcached_st*  mem;
+
+    MLMemcached (MlEnv* _mlenv): MLFunc (cMLMemcachedID, _mlenv) {
+       mem = memcached_create (NULL);
+    };
+    virtual  ~MLMemcached () {
+       if (mem) {
+           memcached_free (mem);
+           mem = NULL;
+       }
+    };
+
+};
+
+MNode*  ml_memcached (MNode* cell, MlEnv* mlenv);
+MNode*  ml_memcached_cache_set (MNode* cell, MlEnv* mlenv, MLFunc* mobj);
+MNode*  ml_memcached_cache_get (MNode* cell, MlEnv* mlenv, MLFunc* mobj);
+MNode*  ml_memcached_cache_delete (MNode* cell, MlEnv* mlenv, MLFunc* mobj);
+MNode*  ml_memcached_cache_increment (MNode* cell, MlEnv* mlenv, MLFunc* mobj);
+MNode*  ml_memcached_cache_decrement (MNode* cell, MlEnv* mlenv, MLFunc* mobj);
+
+#endif /* ML_MEMCACHED_H */
index 90c96c5..b3f1622 100644 (file)
@@ -519,7 +519,7 @@ MNode*  execDefun (MlEnv* mlenv, MNode* lambda, MNode* values, const ustring& na
     return ans.release ();
 }
 
-void  setParams (MNode* list, int nparam, std::vector<MNode*>* params, paramList *kwlist, std::vector<MNode*>* keywords, MNode** rest) {
+void  setParams (MNode* list, int nparam, std::vector<MNode*>* params, paramList *kwlist, std::vector<MNode*>* keywords, MNode** rest, bool padding) {
     KwList*  kw = NULL;
     ustring*  u;
     MNode*  a;
@@ -586,9 +586,16 @@ void  setParams (MNode* list, int nparam, std::vector<MNode*>* params, paramList
        throw (uErrorWrongNumber);
     }
 
-    if (params) {
-       while (params->size () < nparam) {
-           params->push_back (NULL);
+    if (params->size () < nparam) {
+       if (padding) {
+           if (params) {
+               while (params->size () < nparam) {
+                   params->push_back (NULL);
+               }
+           }
+       } else {
+           delete kw;
+           throw (uErrorWrongNumber);
        }
     }
 
index af6d923..71d6db9 100644 (file)
@@ -33,6 +33,6 @@ MNode*  buildArgs (const ustring& arg1);
 bool  checkDefunArgs (MNode* lambda, MNode* values);
 MNode*  execDefun (MlEnv* mlenv, MotorVar* pool, const ustring& name, MNode* values);
 MNode*  execDefun (MlEnv* mlenv, MNode* sexp, MNode* values, const ustring& name);
-void  setParams (MNode* list, int nparam, std::vector<MNode*>* params, paramList *kwlist, std::vector<MNode*>* keywords, MNode** rest);
+void  setParams (MNode* list, int nparam, std::vector<MNode*>* params, paramList *kwlist, std::vector<MNode*>* keywords, MNode** rest, bool padding = false);
 
 #endif /* EXPR_H */
index 7e91c39..74ec6fb 100644 (file)
@@ -185,6 +185,14 @@ ustring  MotorEnv::path_to_auth (const ustring& name) {
     return ans;
 }
 
+ustring  MotorEnv::path_to_etc (const ustring& name) {
+    ustring  ans;
+
+    ans.append (CharConst (cDataTop kEtc));
+    ans.append (name);
+    return ans;
+}
+
 ustring  MotorEnv::path_to_db () {
     if (datastore.length () == 0)
        throw (uErrorMissingDatastore);
index 1280b60..cb8bed2 100644 (file)
@@ -61,6 +61,7 @@ class  MotorEnv {
 
     virtual bool  path_resource (const ustring& name, ustring& ans);
     virtual ustring  path_to_auth (const ustring& name);
+    virtual ustring  path_to_etc (const ustring& name);
     virtual ustring  path_to_db ();
     virtual ustring  path_db (const ustring& name, const char* suffix);
     virtual ustring  path_store_file (const ustring& name, const char* suffix);
index 6bd5c5b..71c9b62 100644 (file)
@@ -154,7 +154,7 @@ static void  formvar_input_readopt (MNode*& arg, MlEnv* mlenv, ustring& name, Fo
        {NULL, 0, 0}
     };
     
-    setParams (arg, 1, &params, kwlist, &keywords, NULL);
+    setParams (arg, 1, &params, kwlist, &keywords, NULL, true);
     name = eval_str (params[0], mlenv);
     opt.max = eval_int (keywords[0], mlenv);
     if (opt.max < 0)
index a1b918a..6f48616 100644 (file)
@@ -38,7 +38,7 @@ MNode*  ml_output_header (MNode* cell, MlEnv* mlenv) {
        {NULL, 0, 0}
     };
 
-    setParams (arg, 1, &params, kwlist, &keywords, NULL);
+    setParams (arg, 1, &params, kwlist, &keywords, NULL, true);
     type = eval_asciiword (params[0], mlenv);
     if (keywords[0])
        finline = eval_bool (keywords[0], mlenv);
@@ -91,7 +91,7 @@ MNode*  ml_motor_file (MNode* cell, MlEnv* mlenv) {
        {NULL, 0, 0}
     };
 
-    setParams (arg, 1, &params, kwlist, &keywords, NULL);
+    setParams (arg, 1, &params, kwlist, &keywords, NULL, true);
     file = eval_str (params[0], mlenv);
     if (keywords[0]) {
        type = eval_asciiword (keywords[0], mlenv);
index 6352d38..94694cd 100644 (file)
@@ -188,7 +188,7 @@ MNode*  ml_mail (MNode* cell, MlEnv* mlenv) {
        {NULL, 0, 0}
     };
 
-    setParams (arg, 1, &params, kwlist, &keywords, NULL);
+    setParams (arg, 1, &params, kwlist, &keywords, NULL, true);
     file = eval_str (params[0], mlenv);
     if (file.size () == 0)
        throw (uErrorFilenameEmpty);