I'm not sure what you mean that it's "client-based."  Sure, the logic is on
the client, as a lot of things are with memcached, but the CAS is enforced
by the server.  Doesn't seem like it's functionally any different than
adding the same function on the server side, since the client would just be
interpreting the new feature in the protocol instead, but functionally it
would work out to be identical, I believe...


On Thu, Feb 3, 2011 at 2:49 PM, Roberto Spadim <[email protected]>wrote:

> ok, but it´s client based...
> i want a server based (memcache daemon)
>
> at client side:
> memcached_lock("lock_name",1);
> memcached_lock("lock_name",0);
>
> at server side:
> lock/unlock some variable (maybe a server based flock())
> since we use ram memory we could use ram locks (not filesystem lock)
> with repcache we can replicate this lock on replicas....
>
>
> 2011/2/3 Adam Lee <[email protected]>:
> > Here's one I hacked together a while back, though, as I said before, I
> > recommend using something better suited to the job...  BTW, this thing
> uses
> > a few of our utility classes, but it should be very simple to drop in
> > replacements.
> > public class GlobalLock
> > {
> >     public GlobalLock(String lockType, String resourceId)
> >     {
> >         if (StringUtils.isBlank(lockType))
> >             throw new NullPointerException("Empty lock type");
> >         if (StringUtils.isBlank(resourceId))
> >             throw new NullPointerException("Empty resource id");
> >         _globalId = StringUtil.toHexString((lockType +
> > resourceId).getBytes()) +":GlobalLock";
> >         while(_value == 0)
> >             _value = RandomUtils.nextLong();
> >         _acquired = false;
> >     }
> >     public GlobalLock lock()
> >     {
> >         if (_acquired)
> >             return this;
> >         // Lock duration 20sec
> >         // tries to acquire lock for 21sec
> >         // obviously this is a far from perfect hack
> >         final int LOCK_DURATION_SECS = 20;
> >         final int SLEEP_TIME_MILLIS = 100;
> >         final int MAX_TRIES = 210; // max number of attempts to acquire
> lock
> >         MemcachedClient mc = FotologMemCache.getFotolog();
> >         for(int numTries = 0; numTries < MAX_TRIES; numTries++)
> >         {
> >             if (_log.isInfoEnabled()) _log.info("locking "+_globalId);
> >             try
> >             {
> >                 CASValue<Object> mcVal = mc.gets(_globalId);
> >                 if (mcVal == null)
> >                 {
> >                     _acquired = mc.add(_globalId, LOCK_DURATION_SECS,
> > _value).get();
> >                 }
> >                 else if ( ((Long)mcVal.getValue()).longValue() == 0 )
> >                 {
> >                     CASResponse casResp = mc.cas(_globalId,
> mcVal.getCas(),
> > _value);
> >                     _acquired = (casResp == CASResponse.OK);
> >                 }
> >                 else
> >                 {
> >                     if (_log.isInfoEnabled()) _log.info("waiting for
> another
> > process to finish: "+_globalId + ":" + mcVal.getValue());
> >                 }
> >             }
> >             catch (Exception e)
> >             {
> >                 _log.error(e.getMessage());
> >             }
> >             if (_acquired)
> >                 return this;
> >             try { Thread.sleep(SLEEP_TIME_MILLIS); } catch
> > (InterruptedException ie) {/**/} // don't 'busywait'
> >         }
> >         throw new GlobalLockException("Unable to lock [" + _globalId + "]
> > after " + MAX_TRIES + " attempts");
> >     }
> >
> >     /** Unlocks ALL of the resources locked with lock().
> >      * Never fails, so doesn't require additional try/catch if you are
> > calling it from some other 'finally'
> >      */
> >     public void unlock()
> >     {
> >         if (_acquired)
> >         {
> >             _acquired = false;
> >             MemcachedClient mc = FotologMemCache.getFotolog();
> >             CASValue<Object> mcVal = mc.gets(_globalId);
> >             if (mcVal == null)
> >             {
> >                 // nothing to do, val already expired
> >                 if (_log.isInfoEnabled()) _log.info("already expired: "
> +
> > _globalId + ":" + _value);
> >                 return;
> >             }
> >             else if ( ((Long)mcVal.getValue()).longValue() == _value )
> >             {
> >                 mc.cas(_globalId, mcVal.getCas(), 0l); // reset but only
> if
> > it matches our val
> >             }
> >             else
> >             {
> >                 _log.error("failed to unlock: " + _globalId + ":" +
> _value);
> >             }
> >         }
> >     }
> >
> >     private static Logger _log = Logger.getLogger(GlobalLock.class);
> >     private String _globalId;
> >     private long _value;
> >     private boolean _acquired;
> > }
> > On Tue, Feb 1, 2011 at 1:40 PM, Roberto Spadim <[email protected]>
> > wrote:
> >>
> >> LOCK should be something like this:
> >>
> >> <?php
> >> // type=0 -> unlock
> >> // type=1 -> lock
> >> // client_name must change (use sessionID + username)
> >> function
> >> memcache_flock($memcache_obj,$key,$type=0,$client_name='1',$timeout=0){
> >>
>  $ret=memcache_add($memcache_obj,$key,$client_name,false,$timeout);
> >>        if($ret==true){
> >>                if($type==0)    // delete
> >>                        memcache_del($memcache_obj,$key);
> >>                return(true);
> >>        }
> >>        $cur_cli=memcache_get($memcache_obj,$key);
> >>        if(is_string($cur_cli) && $cur_cli!=''){ // if ='' no user!
> >>                if($cur_cli !== $client_name){
> >>                        // it's not our lock
> >>                        if(check_user_online_function()) // http session
> >> function (if want
> >> http session integration), for memcached it´s like (true)
> >>                                return($cur_cli);       // return current
> >> lock client_name
> >>                }
> >>                // our lock!
> >>        }else{
> >>                // replace, autocorrect a wrong usage
> >>                memcache_replace($memcache_obj, $key, $client_name,
> false,
> >> $timeout);
> >>        }
> >>        if($type==0)    // delete?
> >>                memcache_del($memcache_obj,$key);
> >>        return(true);
> >> }
> >> ?>
> >>
> >>
> >>
> >>
> >> 2011/2/1 Adam Lee <[email protected]>:
> >> > there are some excellent solutions out there already. check out, for
> >> > example, zookeeper.
> >> >
> >> > awl
> >> >
> >> > On Jan 29, 2011 3:32 PM, "rspadim" <[email protected]> wrote:
> >> >> hi guys, there's a async replication project (repcached) that is very
> >> >> interesting, could we implement it in main source code? at compile
> >> >> time we could select from repcached or memcached
> >> >> could we make it sync and/or async?
> >> >> http://repcached.sourceforge.net/
> >> >>
> >> >>
> >> >>
> =================================================================================
> >> >> there's some non volatile solutions too that's very interesting
> >> >> (memcachedb), for low memory computers we can use disk
> >> >> could we implement it in main source code too?
> >> >> http://memcachedb.org/
> >> >>
> >> >>
> >> >>
> >> >>
> =================================================================================
> >> >> another, now !NEW! feature...
> >> >>
> >> >> i was looking for a *DISTRIBUTED LOCK MANAGER*, but i only found
> >> >> kernel linux lock manager, that's based on file system (flock)
> >> >> could we implement a lock manager at memcached?
> >> >>
> >> >> what lock manager do?
> >> >> client send: KEY NAME, lock type+client name (KEY VALUE), key
> timeout,
> >> >> wait lock timeout (infinity/seconds)
> >> >> (this can be implement in memcached protocol without many
> >> >> modifications!!!)
> >> >> server side function:
> >> >> 1)seek if client can have this lock
> >> >> 2)wait lock timeout... (this is a problem since we can have a very
> big
> >> >> wait time...)
> >> >> 3) if client disconect exit do while
> >> >> 4) yes we have the lock => change key value (give this lock to
> >> >> client), exit do
> >> >> 5) no we don't have the lock, exit do
> >> >> 6) end of do while... return key value: lock type + client name (like
> >> >> a get command)
> >> >>
> >> >> ideas:
> >> >> 1)maybe a separated memory size? we can run two separated servers,
> one
> >> >> for keys another for lock function (make command line options: just
> >> >> lock system, objects only system or both)
> >> >>
> >> >> 2)this type of key is diferent from memcached key cache objects,
> >> >> that's obvious
> >> >>
> >> >> but........ is managed with same functions... (get, list, etc)
> >> >> but........
> >> >> all write/delete functions can't be done, they MUST be done by LOCK
> >> >> (the new) function,
> >> >> DELETE/UNLOCK function is a LOCK function with lock type=0 (unlock)
> >> >> read can be done by get and will return current client lock name and
> >> >> lock type (get command)
> >> >>
> >> >>
> >> >>
> >> >> *WHY THIS FEATURE?*
> >> >> i didn't found a distributed lock manager for user space (not kernel
> >> >> space) with easy to implement protocol, and many program languages,
> >> >> and a very mature server and protocol.
> >> >> =(
> >> >>
> >> >> but with this feature...
> >> >> I DON'T NEED A SAMBA/NFS SERVER FOR NON FILESYSTEM LOCKING!!!!! \o/
> >> >> I WILL NEVER USE FLOCK() AGAIN!!! \o/ !!!
> >> >>
> >> >> I JUST NEED:
> >> >> MYSQL+MEMCACHED+ (APACHE+CGI/PHP/JAVA/PERL/PYTHON)
> >> >> for any cluster solution, no more filesystem!!!
> >> >>
> >> >> NO MORE FILESYSTEM REPLICATIONS (DRBD, NBD+RAID) FOR MY HIGH
> >> >> AVAIBILITY / CLUSTER SOLUTION!!!!!
> >> >> WE CAN USE REPCACHED (WE NEED A SYNC MODE)....
> >> >>
> >> >> THINK ABOUT IT!!!
> >> >> REPLICATION + FLOCK!!!!! IT'S A VERY VERY VERY NICE FEATURE!!!!!
> >> >>
> >> >> ====================
> >> >> type of object (1bit) default / lock manager can be putted on key
> >> >> options/flags!!!
> >> >> inside key value, we can put:
> >> >> lock type(3 bits)
> >> >> client name (a variable length, many bytes)
> >> >>
> >> >> http://en.wikipedia.org/wiki/Distributed_lock_manager
> >> >> from wikipedia, TYPE OF LOCKS:
> >> >> * Null Lock (NL). Indicates interest in the resource, but does not
> >> >> prevent other processes from locking it. It has the advantage that
> the
> >> >> resource and its lock value block are preserved, even when no
> >> >> processes are locking it.
> >> >> * Concurrent Read (CR). Indicates a desire to read (but not
> >> >> update) the resource. It allows other processes to read or update the
> >> >> resource, but prevents others from having exclusive access to it.
> This
> >> >> is usually employed on high-level resources, in order that more
> >> >> restrictive locks can be obtained on subordinate resources.
> >> >> * Concurrent Write (CW). Indicates a desire to read and update the
> >> >> resource. It also allows other processes to read or update the
> >> >> resource, but prevents others from having exclusive access to it.
> This
> >> >> is also usually employed on high-level resources, in order that more
> >> >> restrictive locks can be obtained on subordinate resources.
> >> >> * Protected Read (PR). This is the traditional share lock, which
> >> >> indicates a desire to read the resource but prevents other from
> >> >> updating it. Others can however also read the resource.
> >> >> * Protected Write (PW). This is the traditional update lock, which
> >> >> indicates a desire to read and update the resource and prevents
> others
> >> >> from updating it. Others with Concurrent Read access can however read
> >> >> the resource.
> >> >> * Exclusive (EX). This is the traditional exclusive lock which
> >> >> allows read and update access to the resource, and prevents others
> >> >> from having any access to it.
> >> >>
> >> >> NEW LOCK FUNCTION:
> >> >>
> >> >> LOCK <key><lock_type><client name><timeout><wait lock timeout>
> >> >>
> >> >> key: key name
> >> >> <lock_type+client_name>=key value
> >> >>
> >> >> lock_type:
> >> >> NL = 0
> >> >> CR = 1
> >> >> CW = 2
> >> >> PR = 3
> >> >> PW = 4
> >> >> EX = 5
> >> >>
> >> >> client name: any value
> >> >> timeout: any number, 0=infinity
> >> >> wait lock timeout: wait lock time, 0=infinity
> >> >>
> >> >> how lock works: (see that lock type is only 0 or !=0 in this
> logic...)
> >> >> i will use <sent xxxx> for user new value, and <current xxx> for the
> >> >> current server value
> >> >>
> >> >> if key don't exists, create
> >> >> do{
> >> >> if ((sent_lock_type = 0 and sent_client_name = current_client_name)
> >> >> or key_timed_out==1)
> >> >> remove key (delete)
> >> >> send null lock and sent_client_name information
> >> >> exit function
> >> >> }else if (sent lock type = (1 or 2 or 3 or 4 or 5), and current user
> >> >> = sent user)
> >> >> set
> >> >> current_client_name,current_lock_type=sent_client_name,sent_lock_type
> >> >> exit do
> >> >> }else{
> >> >> if wait lock time < time waiting lock to occur
> >> >> exit do
> >> >> }
> >> >> }while(1)
> >> >> send current_lock_type and sent_client_name
> >> >> exit function
> >> >>
> >> >>
> >> >> thanks guys!!!
> >> >
> >>
> >>
> >>
> >> --
> >> Roberto Spadim
> >> Spadim Technology / SPAEmpresarial
> >
> >
> >
> > --
> > awl
> >
>
>
>
> --
> Roberto Spadim
> Spadim Technology / SPAEmpresarial
>



-- 
awl

Reply via email to