Browse Source

clean repo

Maxim Sokhatsky 11 years ago
parent
commit
8b621d62ec

+ 12 - 15
LICENSE

@@ -1,18 +1,15 @@
-Copyright (c) 2013 Maxim Sokhatsky, Synrc Research Center
+Copyright (c) 2014 Maxim Sokhatsky <maxim@synrc.com>
 
 
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and following permission notice appear in all copies:
 
 
-Software should be used for the great good and the true happiness of all sentient beings.
+Software may only be used for the great good and the true happiness of all sentient beings.
 
 
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

+ 0 - 198
README.md

@@ -1,198 +0,0 @@
-KVS: Data Framework for KV Stores
-=================================
-
-Online Presentation: http://slid.es/maximsokhatsky/kvs
-
-Features
---------
-
-* Polymorphic Tuples
-* Managing Linked-Lists
-* Various Backends Support: KAI, Mnesia, Riak, CouchDB
-* Sequential Consistency via Feed Server
-* Basic Schema for Social Sites and Accounting
-* Extendable Schema
-* Supports Secondary Indexes for KAI, Mnesia and Riak
-* Change Backends on-the-fly
-* Supports Multiple backends at the same time
-* Xen Ready
-
-Overview
---------
-
-This is database handling application that hides database access
-and provides high-level rich API to stored and extend following data:
-
-* Acl
-* Users
-* Groups
-* Subscriptions
-* Feeds
-* Comments
-* Meetings
-* Accounts
-* Payments
-* Products
-* Purchases
-
-This Framework provides also a Plugin for Feed Server for sequential consistency.
-All write requests with given object keys will be handled by single processes
-in Feed Server so you may not worry about concurrent changes of user feeds.
-
-All write operations that are made to data with secondary indexes,
-i.e. not like linked lists could be potentially handled without feed_server.
-But some KV storages are not supporting secondary indexes add those backends carefully.
-
-Store Backends
---------------
-
-Currently kvs includes following store backends:
-
-* Mnesia
-* Riak
-* KAI
-
-Configuring
------------
-
-First of all you need to tune your backend in the kvs application:
-
-    {kvs, {dba,store_kai}},
-
-Try to check it:
-
-    1> kvs:config(dba).
-    store_kai
-    2> kvs:version().
-    {version,"KVS KAI PURE XEN"}
-
-Create database for single node:
-
-    3> kvs:join().
-
-Create database joining to existing cluster:
-
-    3> kvs:join('kvs@synrc.com').
-
-Check table packages included into the schema:
-
-    4> kvs:dir().
-    [kvs_user,kvs_product,kvs_membership,kvs_payment,kvs_feed,
-     kvs_acl,kvs_account,kvs_group]
-
-Operations
-----------
-
-Try to add some data:
-
-    1> rr(kvs).
-    2> kvs:put(#user{id="maxim@synrc.com"}).
-    ok
-    3> kvs:get(user,"maxim@synrc.com").
-    #user{id = "maxim@synrc.com",container = feed,...}
-    4> kvs:put(#user{id="doxtop@synrc.com"}).
-    5> length(kvs:all(user)).
-    2
-
-Polymorphic Records
--------------------
-
-The data in KVS represented as plain Erlang records. The first element of the tuple
-as usual indicates the name of bucket. And the second element usually corresponds
-to the index key field. Additional secondary indexes could be applied for stores
-that supports 2i, e.g. kai, mnesia, riak.
-
-    1 record_name -- user, groups, acl, etc... table name -- element(1, Rec).
-    2 id          -- index key -- element(2, Rec).
-
-Iterators
----------
-
-All record could be chained into the double-linked lists in the database.
-So you can inherit from the ITERATOR record just like that:
-
-    -record(acl_entry, {?ITERATOR(acl),
-        entry_id,
-        acl_id,
-        accessor,
-        action}).
-
-The layout of iterators are following:
-
-    1 record_name -- table name, like
-    2 id          -- index key
-    3 container   -- container name
-    4 feed_id     -- feed id
-    5 prev        -- poniter to previous object in list
-    6 next        -- next
-    7 feeds       -- subfeeds
-    8 guard,      -- aux field
-    9 ...
-
-This means your table will support add/remove operations to lists.
-
-    1> kvs:add(#user{id="mes@ua.fm"}).
-    2> kvs:add(#user{id="dox@ua.fm"}).
-    
-Read the chain (undefined means all)
-    
-    3> kvs:entries(kvs:get(feed, users), user, undefined).
-    [#user{id="mes@ua.fm"},#user{id="dox@ua.fm"}]
-    
-Read flat values by all keys from table:
-
-    4> kvs:all(user).
-    [#user{id="mes@ua.fm"},#user{id="dox@ua.fm"}]
-
-Containers
-----------
-
-If you are using iterators records this automatically means you are using containers.
-Containers are just boxes for storing top/heads of the linked lists. Here is layout
-of containers:
-
-    1 record_name   -- container name
-    2 id            -- unique id
-    3 top           -- pointer to the list's head
-    4 entries_count -- number of elements in list
-
-Extending Schema
-----------------
-
-Usually you need only specify custom mnesia indexes and tables tuning.
-Riak and KAI backends don't need it. Group you table into table packages
-represented as modules with handle_notice API.
-
-    -module(kvs_box).
-    -inclue_lib("kvs/include/kvs.hrl").
-    -record(box,{id,user,email}).
-    -record(box_subscription,{who,whom}).
-    init(Backend=store_mnesia) ->
-        ?CREATE_TAB(box),
-        ?CREATE_TAB(box_subscription),
-        Backend:add_table_index(box, user),
-        Backend:add_table_index(box, email),
-        Backend:add_table_index(box_subscription, who),
-        Backend:add_table_index(box_subscription, whom);
-    init(_) -> ok.
-
-And plug it into schema config:
-
-    {kvs, {schema,[kvs_user,kvs_acl,kvs_account,...,kvs_box]}},
-
-And on database init
-
-    1> kvs:join().
-
-It will create your custom schema.
-
-Credits
--------
-
-* Maxim Sokhatsky
-* Andrii Zadorozhnii
-* Vladimir Kirillov
-* Alex Kalenuk
-* Sergey Polkovnikov
-
-OM A HUM

+ 0 - 27
include/accounts.hrl

@@ -1,27 +0,0 @@
--include("kvs.hrl").
-
--type currency()         :: internal | quota | game_points | money | bonus.
--type account_id()       :: {string(), currency()}. %% {username, currency}.
--type transaction_id()   :: string().
-
--record(account, {
-        id :: account_id(),
-        debet = 0 :: integer(),
-        credit = 0 :: integer(),
-        last_change = 0 :: integer() }).
-
--record(tx_payment,{ id :: integer() }).
--record(tx_admin_change,{ reason :: binary() }).
--record(tx_default_assignment,{ }).
-
--type transaction_info() :: #tx_payment{} | #tx_admin_change{} | #tx_default_assignment{}.
-
--record(user_transaction, {?CONTAINER, user}).
-
--record(transaction, {?ITERATOR(user_transaction), %:: transaction_id(),
-        commit_time :: erlang:now(),
-        amount :: integer(),    %% amount to move between accounts
-        remitter :: account_id(), %% accout that gives money/points
-        acceptor :: account_id(), %% account receive money/points
-        currency :: currency(),   %% some of the points or money
-        info :: transaction_info()}).

+ 0 - 10
include/acls.hrl

@@ -1,10 +0,0 @@
--include("kvs.hrl").
--record(acl, {?CONTAINER}).
-
--record(acl_entry, {?ITERATOR(acl),
-        entry_id,
-        acl_id,
-        accessor,
-        action}).
-
--record(feature, {name, id, aclver}).

+ 0 - 4
include/config.hrl

@@ -1,4 +0,0 @@
--record(config, {key, value}).
-
--define(DBA, store_mnesia).
-%-define(DBA, kvs:config(dba)).

+ 0 - 6
include/feed_state.hrl

@@ -1,6 +0,0 @@
--record(state, {
-        owner = "feed_owner",
-        type :: user | group | system | product,
-        feeds = [],
-        callback,
-        cached_feeds=[]}).

+ 0 - 79
include/feeds.hrl

@@ -1,79 +0,0 @@
--include("kvs.hrl").
--record(feed, {?CONTAINER, aclver}).
-
--record(entry, {?ITERATOR(feed), % {entry_id, feed_id}
-        entry_id,
-        from,
-        to,
-        title,
-        description,
-        created,
-        hidden,
-        access,
-        shared,
-        starred,
-        deleted,
-%        likes,
-%        likes_count,
-        media = [],
-        etc,       %% field to link additional info
-        type = {user, normal}}).
-
--record(media, {
-        id,
-        title :: iolist(),
-        width,
-        height,
-        html :: iolist(),
-        url :: iolist(),
-        version,
-        thumbnail_url :: iolist(),
-        type :: {atom(), atom() | string()},
-        thumbnail_height}).
-
--record(comment, {?ITERATOR(feed), % {comment_id, entry_id, feed_id}
-        comment_id,
-        entry_id,
-        content,
-        from,
-        created,
-        media = [],
-        parent}).
-
--record(entry_views, {?CONTAINER}).
--record(user_view,   {?ITERATOR(entry_views), user, created}).
--record(like, {?ITERATOR(feed), user_id, entry_id, created}).
-
--record(entry_likes, {
-        entry_id,       % this is a general entry_id. Every same entry in different feeds has the same id
-        one_like_head,  % this is a head for linked list of {user, time} tupples
-        total_count     % it's easier to keep it than count
-        }).
-
--record(user_likes, {
-        user_id,
-        one_like_head,
-        total_count
-        }).
-
-
--record(one_like, {
-        id,              % just a number
-        user_id,        % who likes
-        entry_id,       % what
-        feed_id,        % where
-        created_time,   % when
-        next
-        }).
-
--record(hidden_feed, {id}).
-
-% Statistics. We have to keep count of user entries and comments. 
-% Gathering it the old way will work very ineffective with more users to come.
-% And comments from user record are somehow always undefined. Either it fails, or it is used somewhere else
-
--record(user_etries_count, {
-        user_id,    % user id
-        entries = 0,    % number of entries
-        comments = 0   % number of comments
-        }).

+ 0 - 22
include/groups.hrl

@@ -1,22 +0,0 @@
--include("types.hrl").
--include("kvs.hrl").
-
--record(group,{?ITERATOR(feed, true),
-        name,
-        description,
-        scope :: public | private,
-        creator,
-        created,
-        owner,
-        users_count = 0 :: integer(),   % we have to store this, counting would be very expensive and this number is sufficient for sorting and stuff
-        entries_count = 0}).
-
--record(group_subscription, {
-        key,
-        who,
-        where,
-        type,
-        posts_count = 0 :: integer() % we need this for sorting and counting is expensive
-        }).
-
--define(GROUP_EXCHANGE(GroupId), list_to_binary("group_exchange."++GroupId++".fanout")).

+ 0 - 25
include/invites.hrl

@@ -1,25 +0,0 @@
--include("types.hrl").
-
--record(invite_code, {
-        code,
-        create_date,
-        issuer :: username_type() | '_', %% Dialyzer and record MatchSpec warnings http://j.mp/vZ8670
-        recipient,
-        next,
-        prev,
-        created_user :: username_type() | '_'}).
-
--record(invite_by_issuer, {
-        user,
-        top}).
-
--record(invitation_tree, {
-        user,                 % user id
-        parent,               % parent user id
-        next_sibling = none,  % user id of next child of the same parent
-        first_child  = none,  % link to the children list
-        invite_code,          % invite code, for this user
-        children = empty      % can be filled in traversal
-        }).
-
--define(INVITATION_TREE_ROOT, {root}).

+ 0 - 29
include/kvs.hrl

@@ -1,29 +0,0 @@
--ifndef(KVS_HRL).
--define(KVS_HRL, true).
-
--define(USR_FEED, users).
--define(PRD_FEED, products).
--define(GRP_FEED, groups).
--define(ENT_FEED, entries).
--define(CMT_FEED, comments).
--define(FEED(Type), case Type of user -> ?USR_FEED; product -> ?PRD_FEED; group -> ?GRP_FEED; entry-> ?ENT_FEED; comment-> ?CMT_FEED;_-> undefined end).
-
--record(id_seq, {thing, id}).
-
--define(CONTAINER, id, top, entries_count=0).
--define(ITERATOR(Container, Guard), id, container=Container, feed_id, prev, next, feeds=[], guard=Guard).
--define(ITERATOR(Container), ?ITERATOR(Container, false)).
--define(CONTAINERS, [
-    {feed,              record_info(fields, feed)},
-    {acl,               record_info(fields, acl)},
-    {entry_views,       record_info(fields, entry_views)},
-    {user_transaction,  record_info(fields, user_transaction)},
-    {user_payment,      record_info(fields, user_payment)} ]).
-
--record(container, {?CONTAINER}).
--record(iterator,  {?ITERATOR(undefined)}).
-
--define(CREATE_TAB(T), store_mnesia:create_table(T, record_info(fields, T), [{storage, permanent}]) ).
-
-
--endif.

+ 0 - 38
include/meetings.hrl

@@ -1,38 +0,0 @@
--record(team, {
-        name, % { team name for now will bu just first player username }
-        id,
-        play_record, % { linked list history of played users under that ticket }
-        type }).
-
--record(meeting, {
-        name, % { tournament name }
-        id,
-        game_type,
-        description,
-        creator,
-        created, % time
-        start_date,
-        start_time,
-        end_date,
-        status, % { activated, ongoing, finished, canceled }
-        quota,
-        tours,
-        awards, 
-        winners :: list(), % [{UserId, Position, GiftId}]
-        waiting_queue, % { play_record, added here when user wants to join tournament }
-        avatar,
-        owner,
-        players_count,
-        speed,
-        type,
-        game_mode }). % { eliminatin, pointing, etc }
-
--record(play_record, { % { tournament_player, game_record, tournament_info, choose your name :) }
-        who, % { user }
-        tournament, % { tournament in which user played }
-        team, % { team under which user player tournament }
-        game_id, % { game id that user played under that team }
-        realname,
-        points, % [{money,Point},{bonus,Points}]
-        quota }).
-

+ 0 - 9
include/membership.hrl

@@ -1,9 +0,0 @@
--record(membership, {
-        id                         :: any(),      % package id
-        no                         :: integer(),  % package number (need to display in pricelist)
-        amount                     :: integer(),  % price
-        currency                   :: integer(),  % currency charge
-        fee                        :: integer(),  % net membership fee
-        available_for_sale = false :: boolean(),  % not used yet
-        quota::integer() }).
-

+ 0 - 33
include/payments.hrl

@@ -1,33 +0,0 @@
--include("kvs.hrl").
-
--type payment_state() :: added | done | cancelled | pending | untracked | failed | unknown | confirmed | discarded.
--type payment_type():: credit_card | mobile | paypal | wire_transfer | facebook.
-
--record(state_change, {
-        time     :: erlang:now(),
-        state    :: any(),
-        info     :: any()}).
-
--record(user_payment,    {?CONTAINER, user}).
-
--record(payment, {?ITERATOR(user_payment),
-        external_id     :: any(),     % id of the purchase in external payment system if any
-        user_id         :: any(),
-        product_id      :: any(),
-        payment_type    :: payment_type(),
-        state           :: payment_state(),
-        membership,
-        product,
-        start_time      :: erlang:now(),
-        end_time        :: erlang:now(),
-        state_log = []  :: [#state_change{}],
-        info            :: any() }).
-
--record(pi_credit_card, {
-        cardholder_name,
-        cardholder_surname,
-        cardnumber_masked,
-        retref_num,
-        prov_date,
-        auth_code
-        }).

+ 0 - 41
include/products.hrl

@@ -1,41 +0,0 @@
--include("kvs.hrl").
-
--record(ext_product_info, {
-        vendor_id,
-        id,
-        active,
-        title,
-        brief,
-        category,
-        category_name,
-        in_stock,
-        retailer_price,
-        user_price }).
-
--record(product, {?ITERATOR(feed, true),
-        ext_id                 :: term(),    % ext
-        vendor_id              :: integer(), % auto
-        categories             :: list(integer()), % admin
-        creator,
-        owner,
-        title,
-        brief,
-        cover,
-        publish_start_date     :: calendar:date_time(), % admin
-        publish_end_date       :: calendar:date_time(), % admin
-        price = 0              :: integer(),
-        currency               :: integer(),  % currency charge
-        retailer_price         :: integer(), % ext
-        our_price              :: integer(), % auto
-        fee                    :: integer(),  % net membership fee
-        enabled                :: boolean(), % admin
-        for_sale               :: boolean(),
-        created                :: calendar:date_time(), % auto
-        modify_date            :: calendar:date_time() }).
-
--record(product_category, {
-        id             :: integer(),
-        name           :: binary(),
-        description    :: binary(),
-        parent         :: undefined | integer() }).
-

+ 0 - 5
include/purchases.hrl

@@ -1,5 +0,0 @@
--record(user_product, {
-        username,
-        timestamp,
-        product_id }).
-

+ 0 - 21
include/translations.hrl

@@ -1,21 +0,0 @@
--record(translation, {english, lang, word}).
-
--define(URL_DICTIONARY, [
-                         {"account", "es", "cuenta"},
-                         {"admin", "es", "administracion"},
-                         {"dashboard", "es", "panel-principal"},
-                         {"friends", "es", "amigos"},
-                         {"gifts", "es", "regalos"},
-                         {"groups", "es", "grupos"},
-                         {"invite", "es", "invitar"},
-                         {"login", "es", "ingresar"},
-                         {"main", "es", "principal"},
-                         {"privacy", "es", "privacidad"},
-                         {"social", "es", "social"},
-                         {"terms", "es", "terminos"},
-                         {"view", "es", "ver"},
-                         {"group", "es", "grupo"},
-                         {"contact", "es", "contacto"},
-                         {"success", "es", "exito"},
-                         {"fail", "es", "suspender"}
-                         ]).

+ 0 - 9
include/types.hrl

@@ -1,9 +0,0 @@
--ifndef(TYPES_HRL).
--define(TYPES_HRL, true).
-
--type username_type() :: string().
--type id_type() :: integer().
--type user_state() :: ok | not_verified | banned.
--type proplist() :: [proplists:property()].
-
--endif.

+ 0 - 106
include/users.hrl

@@ -1,106 +0,0 @@
--include("types.hrl").
--include("kvs.hrl").
-
--record(user, {?ITERATOR(feed, true),
-        email,
-        username :: username_type() | '_', %% Dialyzer and record MatchSpec warnings http://j.mp/vZ8670
-        display_name,
-        password,
-        facebook_id,
-        twitter_id,
-        googleplus_id,
-        github_id,
-        auth,
-        avatar,
-        name = undefined,
-        surname = undefined,
-        age,
-        sex,
-        location,
-        education,
-        register_date,
-        status = not_verified :: user_state() | '_',
-        verification_code :: string() | '_',
-        zone,
-        type,
-        comments,
-        discussions,
-        transactions,
-        team,
-        aclver}).
-
--record(user_status,{
-        email,
-        last_login,
-        show_splash = true :: boolean()
-        }).
-
--record(user_info,{
-        email,
-        name,
-        surname,
-        age,
-        avatar_url,
-        sex,
-        skill = 0 :: integer(),
-        score = 0 :: integer()}).
-
--record(user_address, {
-        email,
-        address = "",
-        city = "",
-        district = "",
-        postal_code = "",
-        phone = "",
-        personal_id = "" }).
-
--record(user_type,{
-        id,
-        aclver}).
-
--record(subscription,{
-        key,
-        who,
-        whom}).
-
--record(forget_password, {
-        token :: string(),
-        uid   :: string(),
-        create :: {integer(), integer(), integer()}}).
-
--record(prohibited,{
-        ip        :: {string(), atom()},
-        activity  :: any(),
-        time      :: {integer(),integer(),integer()},
-        uid = undefined :: 'undefined' | string()}).
-
--record(avatar,{
-        big :: string(),
-        small :: string(),
-        tiny :: string()}).
-
--record(user_game_status,{
-        user,
-        status  %% strings: online|offline|busy|free_for_game|invisible
-        }).
-
--record(user_ignores, {who, whom}).
--record(user_ignores_rev, {whom, who}).
-
--record(twitter_oauth, {user_id, token, secret}).
--record(facebook_oauth, {user_id, access_token}).
--record(googleplus_oauth, {user_id, access_token}).
--record(github_oauth, {user_id, access_token}).
-
--define(ACTIVE_USERS_TOP_N, 12).
-
--record(active_users_top, {
-        no,
-        user_id,
-        entries_count,
-        last_one_timestamp
-        }).
-
--define(USER_EXCHANGE(UserId), list_to_binary("user_exchange."++UserId++".fanout")).
-
--record(uploads, {key, counter}).

+ 0 - 6
rebar.config

@@ -1,6 +0,0 @@
-{deps_dir, ["deps"]}.
-{deps,[
-%    {riak_kv,    ".*",    {git, "git://github.com/spawnproc/riak_kv.git", {tag,"1.3.2-voxoz"}}},
-    {kai,         ".*",   {git, "git://github.com/synrc/kai.git", "master"}},
-    {mqs,        ".*",    {git, "git://github.com/synrc/mqs.git", "master"}}
-]}.

+ 0 - 7
src/feed_server_api.erl

@@ -1,7 +0,0 @@
--module(feed_server_api).
--export([handle/3]).
-
-handle([Module|Parameters],Message,State) ->
-%    error_logger:info_msg("[feed_server_api]handle_notice Route: ~p Message ~p",[[Module|Parameters],Message]),
-    M = if is_atom(Module)->Module; true-> list_to_atom(binary_to_list(term_to_binary(Module))) end,
-    M:handle_notice([M|Parameters],Message,State).

+ 0 - 9
src/kvs.app.src

@@ -1,9 +0,0 @@
-{application, kvs, 
- [
-  {description, "SRC KVS Distributed Persistance"},
-  {vsn, "1"},
-  {registered, []},
-  {applications, [kernel,stdlib,mnesia,mqs]},
-  {mod, { kvs_app, []}},
-  {env, []}
- ]}.

+ 0 - 315
src/kvs.erl

@@ -1,315 +0,0 @@
--module(kvs).
--author('Maxim Sokhatsky <maxim@synrc.com>').
--include_lib("kvs/include/users.hrl").
--include_lib("kvs/include/translations.hrl").
--include_lib("kvs/include/groups.hrl").
--include_lib("kvs/include/feeds.hrl").
--include_lib("kvs/include/acls.hrl").
--include_lib("kvs/include/meetings.hrl").
--include_lib("kvs/include/invites.hrl").
--include_lib("kvs/include/config.hrl").
--include_lib("kvs/include/accounts.hrl").
--include_lib("kvs/include/membership.hrl").
--include_lib("kvs/include/payments.hrl").
--include_lib("kvs/include/products.hrl").
--include_lib("stdlib/include/qlc.hrl").
--include_lib("kvs/include/feed_state.hrl").
--compile(export_all).
-
-start() -> DBA = ?DBA, DBA:start().
-dir() -> DBA = ?DBA, DBA:dir().
-stop() -> DBA = ?DBA, DBA:stop().
-initialize() -> DBA = ?DBA, DBA:initialize().
-delete() -> DBA = ?DBA, DBA:delete().
-wait_for_tables() -> DBA=?DBA, DBA:wait_for_tables().
-join() -> DBA = ?DBA, DBA:join().
-join(Node) -> DBA = ?DBA, DBA:join(Node).
-
-add(Record) when is_tuple(Record) ->
-    Id = element(#iterator.id, Record),
-    case kvs:get(element(1,Record), Id) of {ok, _} -> error_logger:info_msg("Entry exist: ~p", [Id]),{error, exist};
-    {error, not_found} ->
-        Type = element(1, Record),
-        CName = element(#iterator.container, Record),
-        Cid = case element(#iterator.feed_id, Record) of undefined -> ?FEED(Type); Fid -> Fid end,
-        Container = case kvs:get(CName, Cid) of {ok,C} -> C;
-        {error, not_found} when Cid /= undefined ->
-            NC =  setelement(#container.id, erlang:list_to_tuple([CName|proplists:get_value(CName, ?CONTAINERS)]), Cid),
-            NC1 = setelement(#container.entries_count, NC, 0),
-            kvs:put(NC1),NC1;
-        _ -> error end,
-
-        if Container == error -> {error, no_container}; true ->
-            Next = undefined,
-            Prev = case element(#container.top, Container) of undefined -> undefined;
-              Tid -> case kvs:get(Type, Tid) of {error, not_found} -> undefined;
-                {ok, Top} -> NewTop = setelement(#iterator.next, Top, Id), kvs:put(NewTop), element(#iterator.id, NewTop) end end,
-
-            C1 = setelement(#container.top, Container, Id),
-            C2 = setelement(#container.entries_count, C1, element(#container.entries_count, Container)+1),
-            kvs:put(C2),
-
-            R  = setelement(#iterator.feeds, Record, [ case F1 of {FN, Fd} -> {FN, Fd} ; _-> {F1, kvs_feed:create()} end || F1 <- element(#iterator.feeds, Record)]),
-            R1 = setelement(#iterator.next,  R,  Next),
-            R2 = setelement(#iterator.prev,  R1, Prev),
-            R3 = setelement(#iterator.feed_id, R2, element(#container.id, Container)),
-            kvs:put(R3),
-            error_logger:info_msg("[kvs] PUT: ~p", [element(#container.id,R3)]),
-            {ok, R3} end;
-    E ->  error_logger:info_msg("Entry exist: ~p", [E]),{error, exist} end.
-
-remove(RecordName, RecordId) ->
-    case kvs:get(RecordName, RecordId) of {error, not_found} -> error_logger:info_msg("not found");
-    {ok, E} ->
-        Id = element(#iterator.id, E),
-        CName = element(#iterator.container, E),
-        Cid = element(#iterator.feed_id, E),
-
-        {ok, Container} = kvs:get(CName, Cid),
-        Top = element(#container.top, Container),
-
-        Next = element(#iterator.next, E),
-        Prev = element(#iterator.prev, E),
-        case kvs:get(RecordName, Next) of {ok, NE} -> NewNext = setelement(#iterator.prev, NE, Prev), kvs:put(NewNext); _ -> ok end,
-        case kvs:get(RecordName, Prev) of {ok, PE} -> NewPrev = setelement(#iterator.next, PE, Next), kvs:put(NewPrev); _ -> ok end,
-
-        C1 = case Top of Id -> setelement(#container.top, Container, Prev); _ -> Container end,
-        C2 = setelement(#container.entries_count, C1, element(#container.entries_count, Container)-1),
-        kvs:put(C2),
-        error_logger:info_msg("[kvs] DELETE: ~p id: ~p", [RecordName, Id]),
-        kvs:delete(RecordName, Id) end.
-
-remove(E) when is_tuple(E) ->
-    Id = element(#iterator.id, E),
-    CName = element(#iterator.container, E),
-    Cid = element(#iterator.feed_id, E),
-    {ok, Container} = kvs:get(CName, Cid),
-    Top = element(#container.top, Container),
-
-    Next = element(#iterator.next, E),
-    Prev = element(#iterator.prev, E),
-
-    case kvs:get(element(1,E), Next) of {ok, NE} -> NewNext = setelement(#iterator.prev, NE, Prev), kvs:put(NewNext); _ -> ok end,
-    case kvs:get(element(1,E), Prev) of {ok, PE} -> NewPrev = setelement(#iterator.next, PE, Next), kvs:put(NewPrev); _ -> ok end,
-
-    C1 = case Top of Id -> setelement(#container.top, Container, Prev); _ -> Container end,
-    C2 = setelement(#container.entries_count, C1, element(#container.entries_count, Container)-1),
-    kvs:put(C2),
-
-    error_logger:info_msg("[kvs] DELETE: ~p", [Id]),
-    kvs:delete(E).
-
-traversal( _,undefined,_,_) -> [];
-traversal(_,_,0,_) -> [];
-traversal(RecordType, Start, Count, Direction)->
-    case kvs:get(RecordType, Start) of {error,_} -> [];
-    {ok, R} ->  Prev = element(Direction, R),
-                Count1 = case Count of C when is_integer(C) -> C - 1; _-> Count end,
-                [R | traversal(RecordType, Prev, Count1, Direction)] end.
-
-entries({ok, Container}, RecordType, Count) -> entries(Container, RecordType, Count);
-entries(Container, RecordType, Count) when is_tuple(Container) -> traversal(RecordType, element(#container.top, Container), Count, #iterator.prev);
-entries(_,_,_) -> error_logger:info_msg("=> ENTRIES ARGS NOT MATCH!"), [].
-
-entries(RecordType, Start, Count, Direction) ->
-    E = traversal(RecordType, Start, Count, Direction),
-    case Direction of #iterator.next -> lists:reverse(E); #iterator.prev -> E end.
-
-init_db() ->
-    case kvs:get(user,"joe") of
-        {error,_} ->
-            add_seq_ids(),
-            kvs_account:create_account(system),
-            add_translations();
-        {ok,_} -> ignore end.
-
-add_seq_ids() ->
-    Init = fun(Key) ->
-           case kvs:get(id_seq, Key) of
-                {error, _} -> ok = kvs:put(#id_seq{thing = Key, id = 0});
-                {ok, _} -> ignore
-           end
-    end,
-    Init("meeting"),
-    Init("user_transaction"),
-    Init("user_product"),
-    Init("user_payment"),
-    Init("user_status"),
-    Init("transaction"),
-    Init("membership"),
-    Init("payment"),
-    Init("acl"),
-    Init("acl_entry"),
-    Init("feed"),
-    Init("entry"),
-    Init("like_entry"),
-    Init("likes"),
-    Init("one_like"),
-    Init("comment").
-
-add_translations() ->
-    lists:foreach(fun({English, Lang, Word}) ->
-        kvs:put(#translation{english = English, lang = "en",  word = English}),
-        kvs:put(#translation{english = English, lang = Lang,  word = Word}) end, ?URL_DICTIONARY).
-
-add_sample_users() ->
-  Groups = [],
-  UserList = [],
-
-  kvs:put(Groups),
-
-  {ok, Quota} = kvs:get(config,"accounts/default_quota", 300),
-
-  [ begin
-        [ kvs_group:join(Me#user.username,G#group.id) || G <- Groups ],
-          kvs_account:create_account(Me#user.username),
-          kvs_account:transaction(Me#user.username, quota, Quota, #tx_default_assignment{}),
-          kvs:put(Me#user{password = kvs:sha(Me#user.password)})
-    end || Me <- UserList ],
-
-  [ kvs_user:subscribe(Me#user.username, Her#user.username) || Her <- UserList, Me <- UserList, Her /= Me ],
-  [ kvs_user:init_mq(U) || U <- UserList ],
-
-  ok.
-
-version() -> DBA=?DBA, DBA:version().
-
-add_configs() ->
-    %% smtp
-    kvs:put(#config{key="smtp/user",     value="noreply@synrc.com"}),
-    kvs:put(#config{key="smtp/password", value="maxim@synrc.com"}),
-    kvs:put(#config{key="smtp/host",     value="mail.synrc.com"}),
-    kvs:put(#config{key="smtp/port",     value=465}),
-    kvs:put(#config{key="smtp/with_ssl", value=true}),
-    kvs:put(#config{key="accounts/default_quota", value=2000}),
-    kvs:put(#config{key="accounts/quota_limit/soft",  value=-30}),
-    kvs:put(#config{key="accounts/quota_limit/hard",  value=-100}),
-    kvs:put(#config{key="purchase/notifications/email",  value=["maxim@synrc.com"]}),
-    kvs:put(#config{key="delivery/notifications/email",  value=["maxim@synrc.com"]}).
-
-put(Record) ->
-    DBA=?DBA,
-    DBA:put(Record).
-
-put_if_none_match(Record) ->
-    DBA=?DBA,
-    DBA:put_if_none_match(Record).
-
-update(Record, Meta) ->
-    DBA=?DBA,
-    DBA:update(Record, Meta).
-
-get(RecordName, Key) ->
-    DBA=?DBA,
-    DBA:get(RecordName, Key).
-
-get_for_update(RecordName, Key) ->
-    DBA=?DBA,
-    DBA:get_for_update(RecordName, Key).
-
-get(RecordName, Key, Default) ->
-    DBA=?DBA,
-    case DBA:get(RecordName, Key) of
-        {ok,{RecordName,Key,Value}} ->
-            error_logger:info_msg("db:get config value ~p,", [{RecordName, Key, Value}]),
-            {ok,Value};
-        {error, _B} ->
-            error_logger:info_msg("db:get new config value ~p,", [{RecordName, Key, Default}]),
-            DBA:put({RecordName,Key,Default}),
-            {ok,Default} end.
-
-delete(Keys) -> DBA=?DBA, DBA:delete(Keys).
-delete(Tab, Key) -> error_logger:info_msg("db:delete ~p:~p",[Tab, Key]), DBA=?DBA,DBA:delete(Tab, Key).
-delete_by_index(Tab, IndexId, IndexVal) -> DBA=?DBA,DBA:delete_by_index(Tab, IndexId, IndexVal).
-multi_select(RecordName, Keys) -> DBA=?DBA,DBA:multi_select(RecordName, Keys).
-select(From, PredicateFunction) -> error_logger:info_msg("db:select ~p, ~p",[From,PredicateFunction]), DBA=?DBA, DBA:select(From, PredicateFunction).
-count(RecordName) -> DBA=?DBA,DBA:count(RecordName).
-all(RecordName) -> DBA=?DBA,DBA:all(RecordName).
-all_by_index(RecordName, Index, IndexValue) -> DBA=?DBA,DBA:all_by_index(RecordName, Index, IndexValue).
-next_id(RecordName) -> DBA=?DBA,DBA:next_id(RecordName).
-next_id(RecordName, Incr) -> DBA=?DBA,DBA:next_id(RecordName, Incr).
-next_id(RecordName, Default, Incr) -> DBA=?DBA,DBA:next_id(RecordName, Default, Incr).
-
-author_comments(Who) -> DBA=?DBA,DBA:author_comments(Who).
-
-make_admin(User) ->
-    {ok,U} = kvs:get(user, User),
-    kvs_acl:define_access({user, U#user.id}, {feature, admin}, allow),
-    ok.
-
-make_rich(User) -> 
-    Q = kvs:get_config("accounts/default_quota",  300),
-    kvs_account:transaction(User, quota, Q * 100, #tx_default_assignment{}),
-    kvs_account:transaction(User, internal, Q, #tx_default_assignment{}),
-    kvs_account:transaction(User, currency, Q * 2, #tx_default_assignment{}).
-
-list_to_term(String) ->
-    {ok, T, _} = erl_scan:string(String++"."),
-    case erl_parse:parse_term(T) of
-        {ok, Term} ->
-            Term;
-        {error, Error} ->
-            Error
-    end.
-
-save_db(Path) ->
-    Data = lists:append([all(B) || B <- [list_to_term(B) || B <- store_riak:dir()] ]),
-    kvs:save(Path, Data).
-
-load_db(Path) ->
-    add_seq_ids(),
-    AllEntries = kvs:load(Path),
-    [{_,_,{_,Handler}}] = ets:lookup(config, "riak_client"),
-    [case is_tuple(E) of
-        false -> skip;
-        true ->  put(E) 
-    end || E <- AllEntries].
-
-make_paid_fake(UId) ->
-    put(#payment{user_id=UId,info= "fake_purchase"}).
-
-save(Dir, Value) ->
-    filelib:ensure_dir(Dir),
-    file:write_file(Dir, term_to_binary(Value)).
-
-load(Key) ->
-    {ok, Bin} = file:read_file(Key),
-    binary_to_term(Bin).
-
-coalesce(undefined, B) -> B;
-coalesce(A, _) -> A.
-
-
-uuid() ->
-  R1 = random:uniform(round(math:pow(2, 48))) - 1,
-  R2 = random:uniform(round(math:pow(2, 12))) - 1,
-  R3 = random:uniform(round(math:pow(2, 32))) - 1,
-  R4 = random:uniform(round(math:pow(2, 30))) - 1,
-  R5 = erlang:phash({node(), now()}, round(math:pow(2, 32))),
-
-  UUIDBin = <<R1:48, 4:4, R2:12, 2:2, R3:32, R4: 30>>,
-  <<TL:32, TM:16, THV:16, CSR:8, CSL:8, N:48>> = UUIDBin,
-
-  lists:flatten(io_lib:format("~8.16.0b-~4.16.0b-~4.16.0b-~2.16.0b~2.16.0b-~12.16.0b-~8.16.0b",
-                              [TL, TM, THV, CSR, CSL, N, R5])).
-uuname() ->
-  lists:flatten(io_lib:format("~8.16.0b",[erlang:phash2({node(), now()}, round(math:pow(2, 32)))])).
-
-sha(Raw) ->
-    lists:flatten([io_lib:format("~2.16.0b", [N]) || <<N>> <= crypto:sha(Raw)]).
-
-sha_upper(Raw) ->
-    SHA = sha(Raw),
-    string:to_upper(SHA).
-
-config(Key) -> config(kvs, Key, "").
-config(App,Key) -> config(App,Key, "").
-config(App, Key, Default) -> case application:get_env(App,Key) of
-                              undefined -> Default;
-                              {ok,V} -> V end.
-
-modules() -> Modules = case kvs:config(schema) of
-        [] -> [ kvs_user, kvs_product, kvs_membership,
-                kvs_payment, kvs_feed, kvs_acl,
-                kvs_account, kvs_group ];
-        E  -> E end.

+ 0 - 141
src/kvs_account.erl

@@ -1,141 +0,0 @@
--module(kvs_account).
--include_lib("kvs/include/kvs.hrl").
--include_lib("kvs/include/accounts.hrl").
--include_lib("kvs/include/membership.hrl").
--include_lib("kvs/include/payments.hrl").
--include_lib("kvs/include/feed_state.hrl").
--compile(export_all).
-
-init(Backend) ->
-    ?CREATE_TAB(id_seq),
-    ?CREATE_TAB(account),
-    ?CREATE_TAB(transaction),
-    ok.
-
-transaction(Account, Currency, 0, TransactionInfo) -> ok;
-transaction(Account, Currency, Amount, TransactionInfo) when Amount /= 0 ->
-    {Remitter, Acceptor} = if Amount > 0 -> {system, Account}; true -> {Account, system} end,
-    transaction(Remitter, Acceptor, Currency, abs(Amount), TransactionInfo).
-transaction(Remitter, Acceptor, Currency, Amount, TransactionInfo) ->
-    TX = #transaction{id = generate_id(), acceptor = Acceptor, remitter = Remitter,
-                      amount = Amount, commit_time = now(), currency = Currency, info = TransactionInfo},
-    commit_transaction(TX).
-
-debet(Account, Currency) ->
-    case kvs:get(account,{Account, Currency}) of
-         {ok,#account{debet = Debet}} -> {ok, Debet};
-         Error -> Error end.
-
-credit(AccountId, Currency) ->
-    case kvs:get(account,{AccountId, Currency}) of
-         {ok,#account{credit = Credit}} -> {ok, Credit};
-         Error -> Error end.
-
-balance(AccountId, Currency) ->
-    case kvs:get(account,{AccountId, Currency}) of
-         {ok, #account{debet = Debet, credit = Credit}} -> {ok, Debet - Credit};
-         Error -> Error end.
-
-create_account(AccountId) -> [ kvs:put(#account{id={AccountId, Currency}}) || Currency <- get_currencies() ].
-
-check_quota(User) -> check_quota(User, 0).
-check_quota(User, Amount) ->
-    SoftLimit = kvs:get_config("accounts/quota_limit/soft",  -20),
-    {ok, Balance} = balance(User, quota),
-    BalanceAfterChange = Balance - Amount,
-    if  BalanceAfterChange > SoftLimit -> ok;
-        true ->
-            HardLimit = kvs:get(config, "accounts/quota_limit/hard",  -100),
-            if  BalanceAfterChange =< HardLimit -> {error, hard_limit};
-                true -> {error, soft_limit} end end.
-
-commit_transaction(#transaction{remitter = R, acceptor = A,  currency = Currency, amount = Amount} = TX) ->
-    case change_accounts(R, A, Currency, Amount) of
-         ok -> %mqs:notify([kvs_account, user, R, transaction], TX),
-               %mqs:notify([kvs_account, user, A, transaction], TX);
-                xen;
-         Error -> skip end.
-
-check_remitter_balance(RA, Amount) -> ok.
-
-change_accounts(Remitter, Acceptor, Currency, Amount) ->
-    case {kvs:get(account,{Remitter, Currency}), kvs:get(account,{Acceptor, Currency})} of
-        {{ok, RA = #account{}}, {ok, AA = #account{}}}  ->
-            %% check balance for remitter according to currency and amount
-            case check_remitter_balance(RA, Amount) of
-                ok ->   RA1 = RA#account{credit = RA#account.credit + Amount, last_change = -Amount },
-                        AA1 = AA#account{debet = AA#account.debet + Amount, last_change = Amount},
-                        kvs:put([AA1, RA1]);
-                {error, Reason} -> {error, {remitter_balance, Reason}} end;
-        {{error, Reason}, #account{}} -> {error, {remitter_account_unavailable, Reason}};
-        {#account{}, {error, Reason}} -> {error, {acceptor_account_unavailable, Reason}};
-        {RE, AE} -> {error, both_accounts_unavailable} end.
-
-get_currencies() -> [internal, currency, money, quota, points].
-generate_id() -> {now(),make_ref()}.
-transactions(UserId) -> tx_list(UserId, undefined, 10000).
-
-tx_list(UserId, undefined, PageAmount) ->
-    case kvs:get(user_transaction, UserId) of
-        {ok, O} when O#user_transaction.top =/= undefined -> tx_list(UserId, O#user_transaction.top, PageAmount);
-        {error, _} -> [] end;
-tx_list(UserId, StartFrom, Limit) ->
-    case kvs:get(transaction,StartFrom) of
-        {ok, #transaction{next = N}=P} -> [ P | kvs:traversal(transaction, #transaction.next, N, Limit)];
-        X -> [] end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-handle_notice(["kvs_account", "user", User, "transaction"] = Route,
-    Message, #state{owner = Owner, type =Type} = State) ->
-    error_logger:info_msg("queue_action(~p): add_transaction: Owner=~p, Route=~p, Message=~p", [self(), {Type, Owner}, Route, Message]),    
-    MP = Message,
-    add_transaction_to_user(User,MP),
-    {noreply, State};
-
-handle_notice(Route, Message, State) -> error_logger:info_msg("Unknown ACCOUNTS notice").
-
-%%%%%%%%%%%%%%%%%%%%%%%%%
-
-add_transaction_to_user(UserId,Purchase) ->
-    {ok,Top} = case kvs:get(user_transaction, UserId) of
-                     {ok,T} -> {ok,T};
-                     _ -> error_logger:info_msg("user_transaction not found"),
-                          Head = #user_transaction{ user = UserId, top = undefined},
-                          {kvs:put(Head),Head}
-                end,
-
-    EntryId = Purchase#transaction.id, %kvs:next_id("membership_purchase",1),
-    Prev = undefined,
-    case Top#user_transaction.top of
-        undefined -> Next = undefined;
-        X -> case kvs:get(transaction, X) of
-                 {ok, TopEntry} ->
-                     Next = TopEntry#transaction.id,
-                     EditedEntry = #transaction {
-                           commit_time = TopEntry#transaction.commit_time,
-                           amount = TopEntry#transaction.amount,
-                           remitter = TopEntry#transaction.remitter,
-                           acceptor = TopEntry#transaction.acceptor,
-                           currency = TopEntry#transaction.currency,
-                           info = TopEntry#transaction.info,
-                           id = TopEntry#transaction.id,
-                           next = TopEntry#transaction.next,
-                           prev = EntryId },
-                    kvs:put(EditedEntry); % update prev entry
-                 {error, _} -> Next = undefined
-             end
-    end,
-
-    Entry  = #transaction{id = EntryId,
-                           commit_time = Purchase#transaction.commit_time,
-                           amount = Purchase#transaction.amount,
-                           remitter = Purchase#transaction.remitter,
-                           acceptor = Purchase#transaction.acceptor,
-                           currency = Purchase#transaction.currency,
-                           info = Purchase#transaction.info,
-                           next = Next,
-                           prev = Prev},
-
-    case kvs:put(Entry) of ok -> kvs:put(#user_transaction{ user = UserId, top = EntryId}), {ok, EntryId};
-                              Error -> error_logger:info_msg("Cant write transaction"), {failure,Error} end.

+ 0 - 70
src/kvs_acl.erl

@@ -1,70 +0,0 @@
--module(kvs_acl).
--copyright('Synrc Research Center s.r.o.').
--compile(export_all).
--include_lib("kvs/include/kvs.hrl").
--include_lib("kvs/include/acls.hrl").
--include_lib("kvs/include/users.hrl").
--include_lib("kvs/include/groups.hrl").
--include_lib("kvs/include/feeds.hrl").
-
-init(Backend) ->
-    ?CREATE_TAB(acl),
-    ?CREATE_TAB(acl_entry),
-    ok.
-
-define_access(Accessor, Resource, Action) -> 
-    Entry = #acl_entry{ id = {Accessor, Resource},
-                        accessor= Accessor,
-                        action  = Action,
-                        feed_id = Resource},
-    case kvs:add(Entry) of {error, exist} -> kvs:put(Entry#acl_entry{action=Action}); {ok, E} -> E end.
-
-check(Keys) ->
-    Acls = [Acl || {ok, Acl = #acl_entry{}} <- [kvs:get(acl_entry, Key) || Key <- Keys]],
-    case Acls of [] -> none;
-        [#acl_entry{action = Action} | _] -> Action end.
-
-check_access(#user{id = UId, type = UType}, #feed{id = FId}) ->
-    Feed = {feed, FId},
-    Query = [ {{user, UId}, Feed}, {{user_type, UType}, Feed}, {default, Feed}],
-    check(Query);
-
-check_access(#user{id = UId, type = UType}, #group{id = GId}) ->
-    Group = {group, GId},
-    Query = [ {{user, UId}, Group}, {{user_type, UType}, Group}, {default, Group}],
-    check(Query);
-
-
-check_access(#user{id = AId, type = AType}, #user{id = RId}) ->
-    User = {user, RId},
-    Query = [ {{user, AId}, User}, {{user_type, AType}, User}, {default, User} ],
-    check(Query);
-
-check_access({user_type, Type}, #user{id = RId}) ->
-    User = {user, RId},
-    Query = [ {{user_type, Type}, User}, {default, User} ],
-    check(Query);
-
-check_access({user_type, Type}, #feed{id = FId}) ->
-    Feed = {feed, FId},
-    Query = [ {{user_type, Type}, Feed}, {default, Feed} ],
-    check(Query);
-
-check_access({user_type, Type}, #group{id = GId}) ->
-    Group = {group, GId},
-    Query = [{{user_type, Type}, Group}, {default, Group}],
-    check(Query);
-
-check_access({ip, _Ip} = Accessor, {feature, _Feature} = Resource) ->
-    Query = [{Accessor, Resource}, {default, Resource}],
-    check(Query);
-
-check_access(#user{id = AId, type = AType}, {feature, _Feature} = R) ->
-    Query = [ {{user, AId}, R}, {{user_type, AType}, R}, {default, R} ],
-    check(Query);
-
-check_access(UId, {feature, _Feature} = Resource) ->
-    case kvs:get(user, UId) of
-        {ok, User} -> check_access(User, Resource);
-        E -> E
-    end.

+ 0 - 24
src/kvs_app.erl

@@ -1,24 +0,0 @@
--module(kvs_app).
--behaviour(application).
--export([start/2, stop/1, wait_vnodes/0]).
-
-wait_riak() ->
-    case kvs:put({test,ok}) of
-         ok -> stop;
-         _ -> wait_riak()
-    end.
-
-wait_vnodes() ->
-    case riak:client_connect(node()) of
-    {ok,C} ->
-    case C:get(<<"test">>,<<"ok">>,[]) of
-         {error,{insufficient_vnodes,_,_,_}} -> wait_vnodes();
-         _ -> stop
-    end;
-    _ -> error end.
-
-start(_StartType, _StartArgs) ->
-    kvs_sup:start_link().
-
-stop(_State) ->
-    ok.

+ 0 - 219
src/kvs_feed.erl

@@ -1,219 +0,0 @@
--module(kvs_feed).
--author('Maxim Sokhatsky').
--author('Andrii Zadorozhnii').
--copyright('Synrc Research Center, s.r.o.').
--compile(export_all).
--include_lib("kvs/include/kvs.hrl").
--include_lib("kvs/include/feeds.hrl").
--include_lib("kvs/include/users.hrl").
--include_lib("kvs/include/groups.hrl").
--include_lib("kvs/include/feed_state.hrl").
--define(CACHED_ENTRIES, 20).
-
-init(Backend) ->
-    ?CREATE_TAB(feed),
-    ?CREATE_TAB(entry),
-    ?CREATE_TAB(comment),
-    Backend:add_table_index(entry, feed_id),
-    Backend:add_table_index(entry, entry_id),
-    Backend:add_table_index(entry, from),
-    Backend:add_table_index(comment, entry_id),
-    Backend:add_table_index(comment, author_id),
-    ok.
-
-create() ->
-    FId = kvs:next_id("feed", 1),
-    ok = kvs:put(#feed{id = FId} ),
-    FId.
-
-comments_count(user,  Uid) -> case kvs:get(user_etries_count, Uid) of {error,_} -> 0; {ok, UEC} -> UEC#user_etries_count.comments end;
-comments_count(entry, Eid) -> case kvs:get(entry, Eid) of {error,_} -> 0; {ok, E} -> comments_count([E],0) end;
-comments_count(product, Pid)->case kvs:get(product, Pid) of {error,_}->0; {ok, P} -> comments_count([P], 0) end;
-comments_count([], Acc) -> Acc;
-comments_count([E|T], Acc) ->
-    C = case lists:keyfind(comments, 1, element(#iterator.feeds, E)) of false -> 0;
-    {_, Fid} -> case kvs:get(feed, Fid) of {error,_} -> 0;
-        {ok, Feed } -> Feed#feed.entries_count 
-            + comments_count(kvs:entries(Feed, comment, undefined), 0) end end,
-    comments_count(T,  C + Acc).
-
-add_like(Fid, Eid, Uid) ->
-    Write_one_like = fun(Next) ->
-        Self_id = kvs:next_id("one_like", 1),   
-        kvs:put(#one_like{    % add one like
-            id = Self_id,
-            user_id = Uid,
-            entry_id = Eid,
-            feed_id = Fid,
-            created_time = now(),
-            next = Next
-        }),
-        Self_id
-    end,
-    % add entry - like
-    case kvs:get(entry_likes, Eid) of
-        {ok, ELikes} -> 
-            kvs:put(ELikes#entry_likes{
-                one_like_head = Write_one_like(ELikes#entry_likes.one_like_head), 
-                total_count = ELikes#entry_likes.total_count + 1
-            });
-        {error, _} ->
-            kvs:put(#entry_likes{
-                entry_id = Eid,                
-                one_like_head = Write_one_like(undefined),
-                total_count = 1
-            })
-    end,
-    % add user - like
-    case kvs:get(user_likes, Uid) of
-        {ok, ULikes} -> 
-            kvs:put(ULikes#user_likes{
-                one_like_head = Write_one_like(ULikes#user_likes.one_like_head),
-                total_count = ULikes#user_likes.total_count + 1
-            });
-        {error, _} ->
-            kvs:put(#user_likes{
-                user_id = Uid,                
-                one_like_head = Write_one_like(undefined),
-                total_count = 1
-            })
-    end.
-
-entries_count(Uid) ->
-    case kvs:get(user_etries_count, Uid) of
-        {ok, UEC} -> UEC#user_etries_count.entries;
-        {error, _} -> 0 end.
-
-edit_entry(FeedId, EId, NewDescription) ->
-    case kvs:get(entry,{EId, FeedId}) of
-        {ok, OldEntry} ->
-            NewEntryRaw =  OldEntry#entry{description = NewDescription},
-            NewEntry = feedformat:format(NewEntryRaw),
-            kvs:put(NewEntry);
-        {error, Reason}-> {error, Reason} end.
-
-like_list(undefined) -> [];
-like_list(Id) -> {ok, OneLike} = kvs:get(one_like, Id), [OneLike] ++ like_list(OneLike#one_like.next).
-like_list(undefined, _) -> [];
-like_list(_, 0) -> [];
-like_list(Id, N) -> {ok, OneLike} = kvs:get(one_like, Id), [OneLike] ++ like_list(OneLike#one_like.next, N-1).
-
-entry_likes(Entry_id) ->
-    case kvs:get(entry_likes, Entry_id) of
-        {ok, Likes} -> like_list(Likes#entry_likes.one_like_head);
-        {error, _} -> [] end.
-
-entry_likes_count(Entry_id) ->
-    case kvs:get(entry_likes, Entry_id) of
-        {ok, Likes} -> Likes#entry_likes.total_count;
-        {error, _} -> 0 end.
-
-user_likes_count(UserId) ->
-    case kvs:get(user_likes, UserId) of
-        {ok, Likes} -> Likes#user_likes.total_count;
-        {error, _} -> 0 end.
-
-user_likes(UserId) ->
-    case kvs:get(user_likes, UserId) of
-        {ok, Likes} -> like_list(Likes#user_likes.one_like_head);
-        {error, _} -> [] end.
-
-user_likes(UserId, {Page, PageAmount}) ->
-    case kvs:get(user_likes, UserId) of
-        {ok, Likes} -> lists:nthtail((Page-1)*PageAmount, like_list(Likes#user_likes.one_like_head, PageAmount*Page));
-        {error, _} -> [] end.
-
-%% MQ API
-
-handle_notice([kvs_feed, _, Owner, entry, Eid, add],
-              [#entry{feed_id=Fid}=Entry],
-              #state{owner=Owner} = S) ->
-    case lists:keyfind(Fid,2, S#state.feeds) of false -> skip;
-    {_,_} -> add_entry(Eid,Fid,Entry) end,
-
-    {noreply, S};
-
-handle_notice([kvs_feed,_, Owner, entry, {Eid, FeedName}, edit],
-              [#entry{}=Entry],
-              #state{owner=Owner, feeds=Feeds}=S) ->
-    case lists:keyfind(FeedName,1,Feeds) of false -> skip; {_,Fid}-> update_entry(Eid,Fid,Entry) end,
-
-    {noreply, S};
-
-handle_notice([kvs_feed,_, Owner, entry, Eid, edit],
-              [#entry{feed_id=Fid}=Entry],
-              #state{owner=Owner, feeds=Feeds}=S) ->
-    case lists:keyfind(Fid, 2, Feeds) of false -> skip;
-    {_,_} -> update_entry(Eid,Fid,Entry) end,
-
-    {noreply, S};
-
-handle_notice([kvs_feed, Owner, entry, delete],
-              [#entry{id=Id,feed_id=Fid}=E],
-              #state{owner=Owner, feeds=Feeds}=State) ->
-    error_logger:info_msg("DELETE"),
-    case lists:keyfind(Fid,2,Feeds) of false -> ok;
-    _ ->
-        error_logger:info_msg("[kvs_feed] => Remove entry ~p from feed ~p", [Id, Fid]),
-        Removed = case kvs:remove(entry, Id) of {error,Er}->{error, Er}; ok -> E end,
-        msg:notify([kvs_feed, entry, Id, deleted], [Removed]) end,
-
-    {noreply,State};
-
-handle_notice([kvs_feed, Owner, delete],
-              [#entry{entry_id=Eid}=E],
-              #state{owner=Owner}=State) ->
-    error_logger:info_msg("[kvs_feed] Delete all entries ~p ~p", [E#entry.entry_id, Owner]),
-
-    [msg:notify([kvs_feed, To, entry, delete],[Ed])
-        || #entry{to={_, To}}=Ed <- kvs:all_by_index(entry, entry_id, Eid)],
-
-    Fid = ?FEED(entry),
-    Removed = case kvs:remove(entry,{Eid, Fid}) of {error,X} -> {error,X}; ok -> E#entry{id={Eid,Fid},feed_id=Fid} end,
-    msg:notify([kvs_feed, entry, {Eid, Fid}, deleted], [Removed]),
-
-    {noreply, State};
-
-handle_notice([kvs_feed,_,Owner, comment, Cid, add],
-              [#comment{id={Cid, {_, EFid}, _}}=C],
-              #state{owner=Owner, feeds=Feeds} = S) ->
-    case lists:keyfind(EFid,2,Feeds) of false -> skip;
-    {_,_}-> add_comment(C) end,
-
-    {noreply, S};
-
-handle_notice(["kvs_feed","likes", _, _, "add_like"] = Route,  % _, _ is here beacause of the same message used for comet update
-    Message, #state{owner = Owner, type =Type} = State) ->
-    error_logger:info_msg("queue_action(~p): add_like: Owner=~p, Route=~p, Message=~p", [self(), {Type, Owner}, Route, Message]),
-    {UId, E} = Message,
-    {EId, FId} = E#entry.id,
-    kvs_feed:add_like(FId, EId, UId),
-    {noreply, State};
-
-handle_notice(_Route, _Message, State) ->
-  %error_logger:error_msg("~p ===> Unknown FEED notice ~p", [State#state.owner, Route]), 
-  {noreply, State}.
-
-add_comment(C) ->
-    error_logger:info_msg("[kvs_feed] Add comment ~p ~p", [C#comment.id, C#comment.feed_id]),
-    Added = case kvs:add(C#comment{feeds=[comments]}) of {error, E} -> {error, E}; {ok, Cm} -> Cm end,
-    msg:notify([kvs_feed, comment, C#comment.id, added], [Added]).
-
-add_entry(Eid,Fid,Entry) ->
-    error_logger:info_msg("[kvs_feed] => Add entry ~p to feed ~p.", [Eid, Fid]),
-    E = Entry#entry{id = {Eid, Fid}, entry_id = Eid, feeds=[comments]},
-    Added = case kvs:add(E) of {error, Err}-> {error,Err}; {ok, En} -> En end,
-    msg:notify([kvs_feed, entry, {Eid, Fid}, added], [Added]).
-
-update_entry(Eid,Fid,Entry) ->
-    case kvs:get(entry, {Eid,Fid}) of false -> skip;
-    {ok, E} ->
-        error_logger:info_msg("[kvs_feed] => Update entry ~p in ~p", [Eid, Fid]),
-        Upd = E#entry{description=Entry#entry.description,
-                      title = Entry#entry.title,
-                      media = Entry#entry.media,
-                      etc   = Entry#entry.etc,
-                      type  = Entry#entry.type},
-        kvs:put(Upd),
-        msg:notify([kvs_feed, entry, {Eid, Fid}, updated], [Upd]) end.
-

+ 0 - 217
src/kvs_group.erl

@@ -1,217 +0,0 @@
--module(kvs_group).
--compile(export_all).
--include_lib("kvs/include/kvs.hrl").
--include_lib("kvs/include/users.hrl").
--include_lib("kvs/include/groups.hrl").
--include_lib("kvs/include/feeds.hrl").
--include_lib("kvs/include/accounts.hrl").
--include_lib("kvs/include/feed_state.hrl").
--include_lib("kvs/include/config.hrl").
--include_lib("mqs/include/mqs.hrl").
-
-init(Backend) ->
-    ?CREATE_TAB(group_subscription),
-    ?CREATE_TAB(group),
-    Backend:add_table_index(group_subscription, who),
-    Backend:add_table_index(group_subscription, where),
-    ok.
-
-retrieve_groups(User) ->
-    case participate(User) of
-         [] -> [];
-         Gs -> UC_GId = lists:reverse(lists:sort([{members_count(GId), GId} || GId <- Gs])),
-               Result = [begin case kvs:get(group,GId) of
-                                   {ok, Group} -> {Group#group.name,GId,UC};
-                                   _ -> undefined end end || {UC, GId} <- UC_GId],
-               [X||X<-Result,X/=undefined] end.
-
-delete(GroupName) ->
-    case kvs:get(group,GroupName) of 
-        {error,_} -> ok;
-        {ok, Group} ->
-%            mqs:notify([feed, delete, GroupName], empty),
-            kvs:delete_by_index(group_subscription, <<"where_bin">>, GroupName),
-            [kvs:delete(Feed, Fid) || {Feed, Fid} <- Group#group.feeds],
-            kvs:delete(group, GroupName),
-            case mqs:open([]) of
-                {ok, Channel} ->
-                    Routes = kvs_users:rk_group_feed(GroupName),
-                    kvs_users:unbind_group_exchange(Channel, GroupName, Routes),
-                    mqs_channel:close(Channel);
-                {error,Reason} -> error_logger:info_msg("delete group failed: ~p",[Reason]) end end.
-
-participate(UserName) -> DBA=?DBA,DBA:participate(UserName).
-members(GroupName) -> DBA=?DBA,DBA:members(GroupName).
-
-owner(UserName, GroupName) ->
-    case kvs:get(group, GroupName) of
-        {ok,Group} -> case Group#group.owner of UserName -> true;  _ -> false end;
-        _ -> false end.
-
-member(UserName, GroupName) ->
-    case kvs:get(group_subscription, {UserName, GroupName}) of
-        {error, _} -> false;
-        {ok,_} -> true end.
-
-member_type(UserName, GroupName) ->
-    case kvs:get(group_subs, {UserName, GroupName}) of
-        {error, _} -> not_in_group;
-        {ok, #group_subscription{type=Type}} -> Type end.
-
-add(UserName, GroupName, Type) ->
-    kvs:put(#group_subscription{key={UserName,GroupName},who=UserName, where=GroupName, type=Type}),
-    {ok, Group} = kvs:get(group, GroupName),
-    Users = Group#group.users_count,
-    kvs:put(Group#group{users_count = Users + 1}).
-
-join(UserName,GroupName) ->
-    case kvs:get(group,GroupName) of
-        {ok, #group{id = GroupName, scope = public}} ->
-            add(UserName, GroupName, member),
-            {ok, joined};
-        {ok, #group{id = GroupName}} ->
-            case member_type(UserName, GroupName) of
-                member -> {ok, joined};
-                req -> {error, already_sent};
-                req_rejected -> {error, request_rejected};
-                not_in_group -> add(UserName, GroupName, req), {ok, requested};
-                _ -> {error, unknown_type} end;
-        Error -> Error end.
-
-leave(UserName,GroupName) ->
-    kvs:delete(group_subscription, {UserName, GroupName}),
-    case kvs:get(group, GroupName) of
-        {error,_} -> error_logger:info_msg("Remove ~p from group failed reading group ~p", [UserName, GroupName]);
-        {ok,Group} -> kvs:put(Group#group{users_count = Group#group.users_count - 1}) end.
-
-approve_request(UserName, GroupName) -> add(UserName, GroupName, member).
-reject_request(UserName, GroupName) -> add(UserName, GroupName, req_rejected).
-member_type(UserName, GroupName, Type) -> msg:notify(["subscription", "user", GroupName, "add_to_group"], {GroupName, UserName, Type}).
-
-exists(GroupName) -> case kvs:get(group,GroupName) of {ok,_} -> true; _ -> false end.
-
-coalesce(undefined, B) -> B;
-coalesce(A, _) -> A.
-
-publicity(GroupName) ->
-    case kvs:get(group,GroupName) of
-        {error,_} -> no_such_group;
-        {ok,Group} -> Group#group.scope end.
-
-members_count(GroupName) ->
-    case kvs:get(group,GroupName) of
-        {error,_} -> no_such_group;
-        {ok,Group} -> Group#group.users_count end.
-
-user_has_access(UserName, GroupName) ->
-    Type = member_type(UserName, GroupName),
-    case kvs:get(group, GroupName) of
-        {error,_} -> false;
-        {ok,Group} ->
-            Publicity = Group#group.scope,
-            case {Publicity, Type} of
-                {public, _} -> true;
-                {private, member} -> true;
-                _ -> false end end.
-
-handle_notice([kvs_group, Owner, add],
-              [#group{}=Group],
-              #state{owner=Owner}=State) ->
-    error_logger:info_msg("[kvs_group] Create group ~p", [Owner]),
-    Created = case kvs:add(Group) of {error, E} -> {error, E};
-    {ok, #group{id=Id} = G} ->
-        Params = [{id, Id}, {type, group}, {feeds, element(#iterator.feeds, G)}],
-        case workers_sup:start_child(Params) of {error, E} -> {error, E}; _ -> G end end,
-
-    msg:notify([kvs_group, group, Group#group.id, added], [Created]),
-    {noreply, State};
-
-
-handle_notice(["kvs_group", "update", GroupName] = Route, 
-    Message, #state{owner=ThisGroupOwner, type=Type} = State) ->
-    error_logger:info_msg("queue_action(~p): update_group: Owner=~p, Route=~p, Message=~p", [self(), {Type, ThisGroupOwner}, Route, Message]),    
-    {_UId, _GroupUsername, Name, Description, Owner, Publicity} = Message,
-    case kvs:get(group, GroupName) of
-        {ok, Group} ->
-            NewGroup = Group#group{name = coalesce(Name,Group#group.name),
-                description = coalesce(Description,Group#group.description),
-                scope = coalesce(Publicity,Group#group.scope),
-                owner = coalesce(Owner,Group#group.owner)},
-            kvs:put(NewGroup);
-        {error,Reason} -> error_logger:info_msg("Cannot update group ~p",[Reason]) end,
-    {noreply, State};
-
-handle_notice([kvs_group, Owner, delete],
-              [#group{}=P],
-              #state{owner=Owner, feeds=Feeds}=State) ->
-    error_logger:info_msg("[kvs_group] Delete group ~p ~p", [P#group.id, Owner]),
-    Removed = case kvs:remove(P) of {error,E} -> {error,E};
-    ok ->
-        % todo: handle group feeds?
-
-        supervisor:terminate_child(workers_sup, {group, P#group.id}),
-        supervisor:delete_child(workers_sup, {group, P#group.id}),
-        P
-    end,
-    msg:notify([kvs_product, group, P#group.id, deleted], [Removed]),
-    {noreply, State};
-
-handle_notice([kvs_group, join, Owner],
-              [{FeedName, Who}, Entry],
-              #state{owner = Owner, feeds=Feeds} = State) ->
-    error_logger:info_msg("[kvs_group] ~p Join group:  ~p", [Who, Owner]),
-    join(Who, Owner),
-    case lists:keyfind(FeedName, 1, Feeds) of false -> skip;
-    {_,Fid} -> msg:notify([kvs_feed, group, Owner, entry, Who, add],
-                          [Entry#entry{id={Who, Fid},feed_id=Fid,to={group, Owner}}]) end,
-
-%    subscription_mq(group, add, UserName, GroupName),
-    {noreply, State};
-
-handle_notice([kvs_group, leave, Owner],
-              [{FeedName, Who}],
-              #state{owner = Owner, feeds=Feeds} = State) ->
-    error_logger:info_msg("[kvs_group] ~p leave group ~p", [Who, Owner]),
-    leave(Who, Owner),
-    case lists:keyfind(FeedName, 1, Feeds) of false -> skip;
-    {_,Fid} -> msg:notify([kvs_feed, group, Owner, entry, delete], [#entry{id={Who,Fid}, feed_id=Fid}]) end,
-
-%    subscription_mq(group, remove, UserName, GroupName),
-    {noreply, State};
-
-handle_notice(_Route, _Message, State) ->
-%  error_logger:info_msg("Unknown GROUP notice"),
-  {noreply, State}.
-
-build_group_relations(Group) -> [
-    mqs:key( [kvs_group, create] ),
-    mqs:key( [kvs_group, update, Group] ),
-    mqs:key( [kvs_group, remove, Group] ),
-    mqs:key( [kvs_group, join, Group] ),
-    mqs:key( [kvs_group, leave, Group] ),
-    mqs:key( [kvs_group, like, Group]),   % for comet mostly
-    mqs:key( [kvs_feed, delete, Group] ),
-    mqs:key( [kvs_feed, group, Group, '*', '*', '*'] )
-    ].
-
-init_mq(Group=#group{}) ->
-    GroupExchange = ?GROUP_EXCHANGE(Group#group.id),
-    ExchangeOptions = [{type, <<"fanout">>}, durable, {auto_delete, false}],
-    case mqs:open([]) of
-        {ok, Channel} ->
-            mqs_channel:create_exchange(Channel, GroupExchange, ExchangeOptions),
-            Relations = build_group_relations(Group),
-            [mqs_channel:bind_exchange(Channel, ?GROUP_EXCHANGE(Group#group.id), ?NOTIFICATIONS_EX, Route) || Route <- Relations],
-            mqs_channel:close(Channel);
-        {error, Reason} -> error_logger:info_msg("init_mq error: ~p",[Reason]) end.
-
-rk_group_feed(Group) -> mqs_lib:list_to_key([kvs_feed, group, Group, '*', '*', '*']).
-
-subscription_mq(Type, Action, Who, Where) ->
-    case mqs:open([]) of
-        {ok,Channel} ->
-            case {Type,Action} of 
-                {group,add}     -> mqs_channel:bind_exchange(Channel, ?GROUP_EXCHANGE(Who), ?NOTIFICATIONS_EX, rk_group_feed(Where));
-                {groupr,remove}  -> mqs_channel:unbind_exchange(Channel, ?GROUP_EXCHANGE(Who), ?NOTIFICATIONS_EX, rk_group_feed(Where)) end,
-            mqs_channel:close(Channel);
-        {error,Reason} -> error_logger:info_msg("subscription_mq error: ~p",[Reason]) end.

+ 0 - 114
src/kvs_meeting.erl

@@ -1,114 +0,0 @@
--module(kvs_meeting).
--include_lib("kvs/include/kvs.hrl").
--include_lib("kvs/include/users.hrl").
--include_lib("kvs/include/meetings.hrl").
--include_lib("kvs/include/feed_state.hrl").
--include_lib("kvs/include/config.hrl").
--compile(export_all).
-
-init(Backend) ->
-    ?CREATE_TAB(team),
-    ok.
-
-create_team(Name) ->
-    TID = kvs:next_id("team",1),
-    ok = kvs:put(Team = #team{id=TID,name=Name}),
-    TID.
-
-create(UID, Name) -> create(UID, Name, "", date(), time(), 100, 100, undefined, pointing, game_okey, standard, 8, slow).
-create(UID, Name, Desc, Date, Time, Players, Quota, Awards, Type, Game, Mode, Tours, Speed) ->
-    NodeAtom = nsx_opt:get_env(store,game_srv_node,'game@doxtop.cc'),
-    TID = rpc:call(NodeAtom, game_manager, gen_game_id, []),
-    CTime = erlang:now(),
-    kvs:put(#meeting{name = Name, id = TID, description = Desc, quota = Quota,
-        players_count = Players, start_date = Date, awards = Awards,
-        creator = UID, created = CTime, game_type = Game, game_mode = Mode,
-        type = Type, tours = Tours, speed = Speed, start_time = Time, status = created, owner = UID}),
-    TID.
-
-get(TID) ->
-    case kvs:get(meeting, TID) of
-        {ok, Tournament} -> Tournament;
-        {error, _} -> #meeting{} end.
-
-start(_TID) -> ok.
-join(UID, TID) -> join_tournament(UID, TID).
-leave(UID, TID) -> leave_tournament(UID, TID).
-user_joined(TID, UID) -> 
-    AllJoined = [UId || #play_record{who = UId} <- tournament_users(TID)],
-    lists:member(UID, AllJoined).
-all() -> kvs:all(tournament).
-user_is_team_creator(_UID, _TID) -> true.
-destroy(TID) -> kvs:delete_by_index(play_record, <<"play_record_tournament_bin">>, TID),
-                          kvs:delete(tournament,TID).
-clear() -> [destroy(T#meeting.id) || T <- kvs:all(meeting)].
-lost() -> lists:usort([erlang:element(3, I) || I <- kvs:all(play_record)]).
-
-handle_notice(["kvs_meeting", "user", UId, "create"] = Route,
-    Message, #state{owner = Owner, type =Type} = State) ->
-    error_logger:info_msg("queue_action(~p): create: Owner=~p, Route=~p, Message=~p", [self(), {Type, Owner}, Route, Message]),
-    {TourName, TourDesc, {Y,M,D}, Time, MaxPlayers, Quota, Award, TourType, GameType} = Message,
-    case kvs_meeting:create(UId, TourName, TourDesc, {Y,M,D}, Time, MaxPlayers, Quota, Award, TourType, GameType) of
-        {error,X} -> 
-            error_logger:info_msg("Error creating tournament: ~p", X);
-        TId -> skip end,
-    {noreply, State};
-
-handle_notice(["kvs_meeting", "user", UId, "create_and_join"] = Route,
-    Message, #state{owner = Owner, type =Type} = State) ->
-    error_logger:info_msg("queue_action(~p): create_and_join: Owner=~p, Route=~p, Message=~p", [self(), {Type, Owner}, Route, Message]),
-    {TourName, TourDesc, {Y,M,D}, Time, MaxPlayers, Quota, Award, TourType, GameType} = Message,
-    case kvs_meeting:create(UId, TourName, TourDesc, {Y,M,D}, Time, MaxPlayers, Quota, Award, TourType, GameType) of
-        {error,X} -> 
-            error_logger:info_msg("Error creating tournament: ~p", X);
-        TId -> kvs_meeting:join(UId, TId) end,
-    {noreply, State};
-
-handle_notice(["kvs_meeting", "user", UId, "join"] = Route,
-    Message, #state{owner = Owner, type =Type} = State) ->
-    error_logger:info_msg("queue_action(~p): tournament_join: Owner=~p, Route=~p, Message=~p", [self(), {Type, Owner}, Route, Message]),
-    {UId, TId} = Message,
-    kvs_meeting:join(UId, TId),
-    {noreply, State};
-
-handle_notice(["kvs_meeting", "user", UId, "leave"] = Route,
-    Message, #state{owner = Owner, type =Type} = State) ->
-    error_logger:info_msg("queue_action(~p): tournament_remove: Owner=~p, Route=~p, Message=~p", [self(), {Type, Owner}, Route, Message]),
-    {UId, TId} = Message,
-    kvs_meeting:leave(UId, TId),
-    {noreply, State};
-
-handle_notice(Route, Message, State) -> error_logger:info_msg("Unknown MEETINGS notice").
-
-join_tournament(UserId, TournamentId) ->
-    case kvs:get(user, UserId) of
-        {ok, User} ->
-            GP = case kvs_account:balance(UserId, points) of
-                     {ok, AS1} -> AS1;
-                     {error, _} -> 0 end,
-            Q = case kvs_account:balance(UserId,  quota) of
-                     {ok, AS4} -> AS4;
-                     {error, _} -> 0 end,
-            RN = kvs_users:user_realname(UserId),
-            kvs:put(#play_record{
-                 who = UserId,
-                 tournament = TournamentId,
-                 team = User#user.team,
-                 game_id = undefined, 
-                 realname = RN,
-                 points = GP,
-                 quota = Q});
-        _ ->
-            error_logger:info_msg(" User ~p not found for joining tournament ~p", [UserId, TournamentId])
-    end.
-
-leave_tournament(UserId, TournamentId) ->
-    case kvs:get(play_record, {UserId, TournamentId}) of
-        {ok, _} -> 
-            kvs:delete(play_record, {UserId, TournamentId}),
-            leave_tournament(UserId, TournamentId); % due to WTF error with old records
-        _ -> ok
-    end.
-
-user_tournaments(UId) -> DBA=?DBA,DBA:user_tournaments(UId).
-tournament_users(TId) -> DBA=?DBA,DBA:tournament_users(TId).

+ 0 - 89
src/kvs_membership.erl

@@ -1,89 +0,0 @@
--module(kvs_membership).
--author('Vladimir Baranov <baranoff.vladimir@gmail.com>').
--include_lib("kvs/include/kvs.hrl").
--include_lib("kvs/include/membership.hrl").
--include_lib("kvs/include/payments.hrl").
--include_lib("kvs/include/products.hrl").
--include_lib("kvs/include/accounts.hrl").
--include_lib("kvs/include/feed_state.hrl").
--compile(export_all).
-
-init(Backend) ->
-    ?CREATE_TAB(membership),
-    ok.
-
-add_package(#membership{}=Package)->
-    Id = generate_id(),
-    save_package(Package#membership{id = Id}).
-
-list_packages(Options) ->
-    Predicate = fun(MP = #membership{}) -> check_conditions(Options, MP, true) end,
-    select(membership, Predicate).
-
-list_packages()-> kvs:all(membership).
-
-available_for_sale(PackageId, State) ->
-    case kvs:get(membership,PackageId) of
-        {ok, Package} -> case save_package(Package#membership{available_for_sale = State}) of
-            {ok, _} -> ok;
-            Error -> Error end;
-        {error, Reason}-> {error, Reason} end.
-
-generate_id()->
-    Id = kvs:next_id("membership"),
-    integer_to_list(Id).
-
-add_sample_data()->
-    SamplePackages = [
-    #membership{no = 1, amount = 7,   currency = 0,  quota = 7,   fee = 7},
-    #membership{no = 2, amount = 12,  currency = 5,  quota = 15,  fee = 7},
-    #membership{no = 3, amount = 12,  currency = 0,  quota = 15,  fee = 12},
-    #membership{no = 4, amount = 25,  currency = 10, quota = 30,  fee = 15},
-    #membership{no = 5, amount = 30,  currency = 0,  quota = 60,  fee = 30},
-    #membership{no = 6, amount = 50,  currency = 20, quota = 60,  fee = 30},
-    #membership{no = 7, amount = 50,  currency = 0,  quota = 90,  fee = 50},
-    #membership{no = 8, amount = 100, currency = 40, quota = 120, fee = 60}],
-    WithPaymentTypes = [
-        Package#membership{id = Package#membership.no} ||
-            Payment <- [facebook, credit_card, wire_transfer, paypal, mobile],
-            Package <- SamplePackages],
-    Enabled = [P#membership{available_for_sale = true} || P <- WithPaymentTypes],
-    kvs:put(Enabled).
-
-select(RecordType, Predicate) ->
-    All = kvs:all(RecordType),
-    lists:filter(Predicate, All).
-
-save_package(Package) ->
-    case kvs:put([Package]) of
-        ok -> {ok, Package#membership.id};
-        {error, Reason}-> {error, Reason} end.
-
-timestamp()->
-    {Y, Mn, D} = erlang:date(),
-    {H, M, S} = erlang:time(),
-    lists:flatten(io_lib:format("~b~2..0b~2..0b_~2..0b~2..0b~2..0b", [Y, Mn, D, H, M, S])).
-
-check_conditions(_, _, false) -> false;
-check_conditions([{available_for_sale, AS}|T], MP = #membership{available_for_sale = AS1}, _) -> check_conditions(T, MP, AS == AS1);
-check_conditions([{payment_type, PT}|T], MP = #membership{}, _) -> check_conditions(T, MP, true);
-check_conditions([], _, true) -> true.
-
-delete_package(PackageId) -> kvs:delete(membership, PackageId).
-
-%% MQ API
-
-handle_notice(["kvs_membership","system", "add_package"] = Route,
-    Message, #state{owner = Owner, type =Type} = State) ->
-    error_logger:info_msg("queue_action(~p): add_package: Owner=~p, Route=~p, Message=~p", [self(), {Type, Owner}, Route, Message]),
-    {MP} = Message,
-    case add_package(MP) of
-        {ok, _} -> ok;
-        {error, Reason} -> error_logger:info_msg("Unable to add membership package: ~p, Reason ~p", [MP, Reason])
-    end,
-    {noreply, State};
-
-handle_notice(Route, Message, State) -> error_logger:info_msg("Unknown MEMBERSHIP notice").
-
-coalesce(undefined, B) -> B;
-coalesce(A, _) -> A.

+ 0 - 139
src/kvs_payment.erl

@@ -1,139 +0,0 @@
--module(kvs_payment).
--include_lib("kvs/include/kvs.hrl").
--include_lib("kvs/include/membership.hrl").
--include_lib("kvs/include/payments.hrl").
--include_lib("kvs/include/accounts.hrl").
--include_lib("kvs/include/feed_state.hrl").
--compile(export_all).
-
-init(Backend) ->
-    ?CREATE_TAB(payment),
-    ?CREATE_TAB(user_payment),
-    Backend:add_table_index(payment, product_id),
-    ok.
-
-payments(UserId) -> payments(UserId, undefined).
-payments(UserId, PageAmount) ->
-    case kvs:get(user_payment, UserId) of
-        {ok, O} -> kvs:entries(O, payment, PageAmount);
-        {error, _} -> [] end.
-payments(UserId, StartFrom, Limit) ->
-    case kvs:get(payment, StartFrom) of {error,_}-> [];
-        {ok, P} ->  kvs:traversal(payment, P, Limit) end.
-
-user_paid(UId) ->
-    case kvs:get(user_payment, UId) of
-        {error,_} -> false;
-        {ok,#user_payment{top = undefined}} -> false;
-        _ -> true end.
-
-default_if_undefined(Value, Undefined, Default) ->
-    case Value of
-        Undefined -> Default;
-        _ -> Value end.
-
-charge_user_account(_MP) -> ok.
-%    OrderId = MP#payment.id,
-%    Package = MP#payment.membership,
-%    UserId  = MP#payment.user_id,
-%
-%    Currency = Package#membership.currency,
-%    Quota    = Package#membership.quota,
-%
-%    PaymentTransactionInfo = #tx_payment{id=MP#payment.id},
-%
-%    try
-%        kvs_account:transaction(UserId, currency, Currency, PaymentTransactionInfo),
-%        kvs_account:transaction(UserId, quota,    Quota,    PaymentTransactionInfo)
-%    catch
-%        _:E ->
-%            error_logger:info_msg("unable to charge user account. User=~p, OrderId=~p. Error: ~p",
-%                   [UserId, OrderId, E])
-%    end.
-
-add_payment(#payment{} = MP) -> add_payment(#payment{} = MP, undefined, undefined).
-add_payment(#payment{} = MP, State0, Info) ->
-    error_logger:info_msg("ADD PAYMENT"),
-    Start = now(),
-    State = default_if_undefined(State0, undefined, 'added'),
-    StateLog = case Info of
-        undefined -> [#state_change{time = Start, state = State, info = system_change}];
-        _ -> [#state_change{time = Start, state = State, info = Info}] end,
-
-    Id = default_if_undefined(MP#payment.id, undefined, payment_id()),
-    kvs:add(MP#payment{id = Id, state = State, start_time = Start, state_log = StateLog, feed_id=MP#payment.user_id}).
-
-set_payment_state(MPId, NewState, Info) ->
-    case kvs:get(payment, MPId) of
-    {ok, MP} ->
-        Time = now(),
-        StateLog = MP#payment.state_log,
-        NewStateLog = [#state_change{time = Time, state = NewState, info = Info}|StateLog],
-        EndTime = case NewState of
-                  'done' -> now();
-                  'cancelled' -> now();
-                  'failed' -> now();
-                  _ -> MP#payment.end_time end,
-
-        NewMP=MP#payment{state = NewState, end_time = EndTime, state_log = NewStateLog},
-
-        Result = kvs:put(NewMP),
-        msg:notify([kvs_payment, payment, NewMP#payment.id, updated], [Result]);
-    Error ->
-        error_logger:info_msg("[kvs_payment]Can't set purchase state, not yet in db"),
-        Error end.
-
-set_payment_info(MPId, Info) ->
-    {ok, MP} = kvs:get(payment, MPId),
-    kvs:put(MP#payment{info = Info}).
-
-set_payment_external_id(MPId, ExternalId) ->
-    {ok, MP} = kvs:get(payment, MPId),
-    case MP#payment.external_id of
-        ExternalId -> ok;
-        _ -> kvs:put(MP#payment{external_id = ExternalId}) end.
-
-list_payments() -> kvs:all(payment).
-
-list_payments(SelectOptions) ->
-    Predicate = fun(MP = #payment{}) -> kvs_membership:check_conditions(SelectOptions, MP, true) end,
-    kvs_membership:select(payment, Predicate).
-
-payment_id() ->
-    NextId = kvs:next_id("payment"),
-    lists:concat([timestamp(), "_", NextId]).
-
-handle_notice([kvs_payment, Type, Owner, set_state],
-              {MPId, NewState, Info},
-              #state{owner = Owner, type =Type} = State) ->
-    error_logger:info_msg("[kvs_payment] set_state: Owner: ~p Id: ~p State: ~p", [Owner, MPId, NewState]),
-    set_payment_state(MPId, NewState, Info),
-    {noreply, State};
-
-handle_notice([kvs_payment, Type, Owner, add],
-              {MP},
-              #state{owner = Owner, type =Type} = State) ->
-    error_logger:info_msg("[kvs_payment] add_purchase ~p ~p", [Owner, MP#payment.id]),
-    add_payment(MP),
-    {noreply, State};
-
-handle_notice([kvs_payment, Type, Owner, set_external_id],
-              {PurchaseId, TxnId},
-              #state{owner = Owner, type =Type} = State) ->
-    error_logger:info_msg("[kvs_payment] set_external_id: Owner: ~p, Id: ~p, Tx: ~p", [Owner, PurchaseId, TxnId]),
-    set_payment_external_id(PurchaseId, TxnId),
-    {noreply, State};
-
-handle_notice([kvs_payment, Type, Owner, set_info],
-              {OrderId, Info},
-              #state{owner = Owner, type =Type} = State) ->
-    error_logger:info_msg("[kvs_payment] set_info: Owner:~p Info: ~p", [Owner, Info]),
-    set_payment_info(OrderId, Info),
-    {noreply, State};
-
-handle_notice(_,_,State) -> {noreply, State}.
-
-timestamp()->
-  {Y, Mn, D} = erlang:date(),
-  {H, M, S} = erlang:time(),
-  lists:flatten(io_lib:format("~b~2..0b~2..0b_~2..0b~2..0b~2..0b", [Y, Mn, D, H, M, S])).

+ 0 - 186
src/kvs_product.erl

@@ -1,186 +0,0 @@
--module(kvs_product).
--copyright('Synrc Research Center s.r.o.').
--include_lib("kvs/include/kvs.hrl").
--include_lib("kvs/include/products.hrl").
--include_lib("kvs/include/purchases.hrl").
--include_lib("kvs/include/users.hrl").
--include_lib("kvs/include/groups.hrl").
--include_lib("kvs/include/feeds.hrl").
--include_lib("kvs/include/accounts.hrl").
--include_lib("kvs/include/config.hrl").
--include_lib("kvs/include/feed_state.hrl").
--include_lib("mqs/include/mqs.hrl").
--compile(export_all).
-
-init(Backend) ->
-    ?CREATE_TAB(product),
-    ?CREATE_TAB(user_product),
-    ?CREATE_TAB(product_category),
-    ok.
-
-delete(Name) ->
-  case kvs:get(product, Name) of
-    {ok, Product} ->
-      [kvs_group:leave(Name, Gid) || Gid <- kvs_group:participate(Name)],
-      kvs:remove(product, Name),
-      {ok, Product};
-    E -> E end.
-
-subscription_mq(Type, Action, Who, Whom) ->
-    case mqs:open([]) of
-    {ok,Channel} ->
-        case {Type,Action} of
-        {user,add}->
-            mqs_channel:bind_exchange(Channel, ?USER_EXCHANGE(Who), ?NOTIFICATIONS_EX, rk_product_feed(Whom));
-        {user,remove} ->
-            mqs_channel:unbind_exchange(Channel, ?USER_EXCHANGE(Who), ?NOTIFICATIONS_EX, rk_product_feed(Whom)) end,
-        mqs_channel:close(Channel);
-    {error,Reason} -> error_logger:info_msg("subscription_mq error: ~p",[Reason]) end.
-
-init_mq(Product=#product{}) ->
-    Groups = kvs_group:participate(Product),
-    ProductExchange = ?USER_EXCHANGE(Product#product.id),
-    ExchangeOptions = [{type, <<"fanout">>}, durable, {auto_delete, false}],
-    case mqs:open([]) of
-    {ok, Channel} ->
-        error_logger:info_msg("Cration Exchange: ~p,",[{Channel,ProductExchange,ExchangeOptions}]),
-        mqs_channel:create_exchange(Channel, ProductExchange, ExchangeOptions),
-        Relations = build_product_relations(Product, Groups),
-        [ mqs_channel:bind_exchange(Channel, ?USER_EXCHANGE(Product#product.id), ?NOTIFICATIONS_EX, Route)
-            || Route <- Relations],
-        mqs_channel:close(Channel);
-    {error,Reason} -> error_logger:info_msg("init_mq error: ~p",[Reason]) end.
-
-build_product_relations(Product, Groups) -> [
-    mqs:key( [kvs_product, '*', Product]),
-    mqs:key( [kvs_feed, product, Product, '*', '*', '*']),
-    mqs:key( [kvs_feed, product, Product, '*'] ),
-    mqs:key( [kvs_payment, product, Product, '*']),
-    mqs:key( [kvs_account, product, Product, '*']),
-    mqs:key( [kvs_meeting, product, Product, '*']),
-    mqs:key( [kvs_purchase, product, Product, '*']) |
-  [ mqs:key( [kvs_feed, group, G, '*', '*', '*']) || G <- Groups ]
-    ].
-
-rk_product_feed(Product) -> mqs:key([kvs_feed, product, Product, '*', '*', '*']).
-
-retrieve_connections(Id,Type) ->
-    Friends = case Type of 
-        user -> kvs_product:list_subscr_usernames(Id);
-        _ -> kvs_group:list_group_members(Id) end,
-    case Friends of
-        [] -> [];
-        Full -> Sub = lists:sublist(Full, 10),
-            case Sub of
-                [] -> [];
-                _ ->
-                    Data = [begin
-                        case kvs:get(user,Who) of
-                            {ok,Product} -> RealName = kvs_product:user_realname_user(Product),
-                            Paid = kvs_payment:user_paid(Who),
-                            {Who,Paid,RealName};
-                        _ -> undefined end end || Who <- Sub],
-                    [ X || X <- Data, X/=undefined ] end end.
-
-handle_notice(["kvs_product", "subscribe", Who],
-    Message, #state{owner = _Owner, type =_Type} = State) ->
-    {Whom} = Message,
-    kvs_product:subscribe(Who, Whom),
-    subscription_mq(user, add, Who, Whom),
-    {noreply, State};
-
-handle_notice(["kvs_product", "unsubscribe", Who],
-    Message, #state{owner = _Owner, type =_Type} = State) ->
-    {Whom} = Message,
-    kvs_product:unsubscribe(Who, Whom),
-    subscription_mq(user, remove, Who, Whom),
-    {noreply, State};
-
-handle_notice([kvs_product, Owner, add],
-              [#product{}=Product, Recipients],
-              #state{owner=Owner, feeds=Feeds}=State) ->
-    error_logger:info_msg("[kvs_product] Create product ~p", [Owner]),
-    Created = case kvs:add(Product) of {error, E} -> {error, E};
-    {ok, #product{id=Id} = P} ->
-        Params = [{id, Id}, {type, product}, {feeds, element(#iterator.feeds, P)}],
-        case workers_sup:start_child(Params) of {error, E} -> {error, E};
-        _ -> Entry = to_entry(P),
-
-            [msg:notify([kvs_group, join, Gid], [{products, Id}, Entry]) || {Type, Gid} <- Recipients, Type==group],
-
-            case lists:keyfind(products, 1, Feeds) of false -> skip;
-            {_,Fid} -> msg:notify([kvs_feed, user, Owner, entry, Id, add], [Entry#entry{feed_id=Fid, to={user, Owner}}]) end,
-            P
-        end end,
-
-    msg:notify([kvs_product, product, Product#product.id, added], [Created]),
-    {noreply, State};
-
-handle_notice([kvs_product, Owner, update],
-              [#product{}=Product, Recipients], #state{owner=Owner} = State) ->
-    error_logger:info_msg("[kvs_product] Update product ~p", [Owner]),
-    case kvs:get(product, Owner) of {error,E}->
-        msg:notify([kvs_product, product, Owner, updated], [{error,E}]);
-    {ok, #product{}=P} ->
-        Id = P#product.id,
-        UpdProduct = P#product{
-            title = Product#product.title,
-            brief = Product#product.brief,
-            cover = Product#product.cover,
-            price = Product#product.price,
-            currency = Product#product.currency},
-        kvs:put(UpdProduct),
-
-        Entry = to_entry(UpdProduct),
-
-        Groups = ordsets:from_list([Gid || {Type,Gid} <- Recipients, Type==group]),
-        Participate = ordsets:from_list([Gid || #group_subscription{where=Gid} <- kvs_group:participate(Id)]),
-        Intersection = ordsets:intersection(Groups, Participate),
-        Leave = ordsets:subtract(Participate, Intersection),
-        Join = ordsets:subtract(Groups, Intersection),
-
-        [msg:notify([kvs_group, leave, Gid], [{products, Id}]) || Gid <- Leave],
-        [msg:notify([kvs_group, join, Gid], [{products, Id}, Entry]) || Gid <- Join],
-
-        [msg:notify([kvs_feed, RouteType, To, entry, {Id, products}, edit], [Entry])
-            || {RouteType, To} <- [{user, P#product.owner} | [{group, G} || G <- Intersection]]],
-        msg:notify([kvs_product, product, Owner, updated], [UpdProduct])
-    end,
-    {noreply, State};
-
-handle_notice([kvs_product, Owner, delete],
-              [#product{}=P],
-              #state{owner=Owner, feeds=Feeds}=State) ->
-    error_logger:info_msg("[kvs_product] Delete product ~p ~p", [P#product.id, Owner]),
-    Removed = case kvs:remove(P) of {error,E} -> {error,E};
-    ok ->
-        [msg:notify([kvs_group, leave, Gid], [{products, P#product.id}])
-            || #group_subscription{where=Gid} <- kvs_group:participate(P#product.id)],
-
-        case lists:keyfind(products, 1, Feeds) of false -> skip;
-        {_,Fid} -> case kvs:get(entry, {P#product.id, Fid}) of {error,_} -> ok;
-            {ok, E} -> msg:notify([kvs_feed, Owner, delete], [E]) end end,
-
-        supervisor:terminate_child(workers_sup, {product, P#product.id}),
-        supervisor:delete_child(workers_sup, {product, P#product.id}),
-        P
-    end,
-    msg:notify([kvs_product, product, P#product.id, deleted], [Removed]),
-    {noreply, State};
-
-handle_notice(_Route, _Message, State) -> {noreply, State}.
-
-to_entry(#product{}=P) ->
-    Media = case P#product.cover of undefined -> #media{};
-        File ->
-            Thumbnail = filename:join([ filename:dirname(File), "thumbnail", filename:basename(File)]),
-            [#media{url=File, thumbnail_url = Thumbnail}] end,
-
-    #entry{ entry_id = P#product.id,
-            created = P#product.created,
-            from = P#product.owner,
-            type = product,
-            media = Media,
-            title = P#product.title,
-            description = P#product.brief,
-            shared = ""}.

+ 0 - 39
src/kvs_purchase.erl

@@ -1,39 +0,0 @@
--module(kvs_purchase).
--copyright('Synrc Research Center s.r.o.').
--include_lib("kvs/include/products.hrl").
--include_lib("kvs/include/purchases.hrl").
--include_lib("kvs/include/config.hrl").
--include_lib("kvs/include/accounts.hrl").
--include_lib("kvs/include/feed_state.hrl").
--compile(export_all).
-
-solvent(UId, ProductId) ->
-    {ok, Credit} = kvs_accounts:balance(UId, currency),
-    {ok, #product{price = Price}} = kvs:get(product, ProductId),
-    Credit >= Price.
-
-buy(UId, ProductId) ->
-    {ok, #product{price = Price}} = kvs:get(product, ProductId),
-    kvs_accounts:transaction(UId, currency, -Price, "Buy " ++ ProductId ++ " for "++ integer_to_list(Price)),
-    kvs:put(#user_product{username=UId, timestamp=now(), product_id = ProductId}).
-
-give(UId, ProductId) ->
-    kvs:put(#user_product{username=UId, timestamp=now(), product_id = ProductId}).
-
-products(UId) -> DBA=?DBA, DBA:products(UId).
-
-handle_notice(["kvs_purchase", "user", UId, "buy"] = Route,
-    Message, #state{owner = Owner, type =Type} = State) ->
-    error_logger:info_msg(" queue_action(~p): buy_gift: Owner=~p, Route=~p, Message=~p", [self(), {Type, Owner}, Route, Message]),
-    {GId} = Message,
-    buy(UId, GId),
-    {noreply, State};
-
-handle_notice(["kvs_purchase", "user", UId, "give"] = Route,
-    Message, #state{owner = Owner, type =Type} = State) ->
-    error_logger:info_msg(" queue_action(~p): give_gift: Owner=~p, Route=~p, Message=~p", [self(), {Type, Owner}, Route, Message]),
-    {GId} = Message,
-    give(UId, GId),
-    {noreply, State};
-
-handle_notice(R,_,S) -> error_logger:info_msg("Unhandled PURCHASE notice ~p", [R]), {noreply, S}.

+ 0 - 24
src/kvs_sup.erl

@@ -1,24 +0,0 @@
--module(kvs_sup).
--behaviour(supervisor).
--export([start_link/0]).
--export([init/1]).
--define(CHILD(I, Type), {I, {I, start_link, []}, permanent, 5000, Type, [I]}).
-
-start_link() ->
-    supervisor:start_link({local, ?MODULE}, ?MODULE, []).
-
-init([]) ->
-    RestartStrategy = one_for_one,
-    MaxRestarts = 1000,
-    MaxSecondsBetweenRestarts = 3600,
-
-    SupFlags = {RestartStrategy, MaxRestarts, MaxSecondsBetweenRestarts},
-
-    Restart = permanent,
-    Shutdown = 2000,
-    Type = worker,
-
-    kvs:start(),
-
-    {ok, { {one_for_one, 5, 10}, []} }.
-

+ 0 - 176
src/kvs_user.erl

@@ -1,176 +0,0 @@
--module(kvs_user).
--copyright('Synrc Research Center s.r.o.').
--include_lib("kvs/include/users.hrl").
--include_lib("kvs/include/purchases.hrl").
--include_lib("kvs/include/payments.hrl").
--include_lib("kvs/include/groups.hrl").
--include_lib("kvs/include/accounts.hrl").
--include_lib("kvs/include/products.hrl").
--include_lib("kvs/include/config.hrl").
--include_lib("kvs/include/feeds.hrl").
--include_lib("kvs/include/feed_state.hrl").
--include_lib("mqs/include/mqs.hrl").
--include_lib("kvs/include/kvs.hrl").
--compile(export_all).
-
-init(Backend) ->
-    ?CREATE_TAB(user),
-    ?CREATE_TAB(user_status),
-    ?CREATE_TAB(subscription),
-    Backend:add_table_index(user, facebook_id),
-    Backend:add_table_index(user, googleplus_id),
-    Backend:add_table_index(user, twitter_id),
-    Backend:add_table_index(user, github_id),
-    Backend:add_table_index(subscription, who),
-    Backend:add_table_index(subscription, whom),
-    ok.
-
-delete(UserName) ->
-    case kvs_user:get(UserName) of
-        {ok, User} ->
-            GIds = kvs_group:participate(UserName),
-            [ mqs:notify(["subscription", "user", UserName, "remove_from_group"], {GId}) || GId <- GIds ],
-            F2U = [ {MeId, FrId} || #subscription{who = MeId, whom = FrId} <- subscriptions(User) ],
-            [ unsubscribe(MeId, FrId) || {MeId, FrId} <- F2U ],
-            [ unsubscribe(FrId, MeId) || {MeId, FrId} <- F2U ],
-            kvs:delete(user_status, UserName),
-            kvs:delete(user, UserName),
-            {ok, User};
-        E -> E end.
-
-get({facebook, FBId}) -> user_by_facebook_id(FBId);
-get({googleplus, GId}) -> user_by_googleplus_id(GId).
-
-subscribe(Who, Whom) ->
-    Record = #subscription{key={Who,Whom}, who = Who, whom = Whom},
-    kvs:put(Record).
-
-unsubscribe(Who, Whom) ->
-    case subscribed(Who, Whom) of
-        true  -> kvs:delete(subscription, {Who, Whom});
-        false -> skip end.
-
-subscriptions(undefined)-> [];
-subscriptions(#user{username = UId}) -> subscriptions(UId);
-
-subscriptions(UId) -> DBA=?DBA, DBA:subscriptions(UId).
-subscribed(Who) -> DBA=?DBA, DBA:subscribed(Who).
-
-subscribed(Who, Whom) ->
-    case kvs:get(subscription, {Who, Whom}) of
-        {ok, _} -> true;
-        _ -> false end.
-
-subscription_mq(Type, Action, Who, Whom) ->
-    case mqs:open([]) of
-        {ok,Channel} ->
-            case {Type,Action} of 
-                {user,add}     -> mqs_channel:bind_exchange(Channel, ?USER_EXCHANGE(Who), ?NOTIFICATIONS_EX, rk_user_feed(Whom));
-                {user,remove}  -> mqs_channel:unbind_exchange(Channel, ?USER_EXCHANGE(Who), ?NOTIFICATIONS_EX, rk_user_feed(Whom)) end,
-            mqs_channel:close(Channel);
-        {error,Reason} -> error_logger:info_msg("subscription_mq error: ~p",[Reason]) end.
-
-init_mq(User=#user{}) ->
-    Groups = kvs_group:participate(User),
-    UserExchange = ?USER_EXCHANGE(User#user.username),
-    ExchangeOptions = [{type, <<"fanout">>}, durable, {auto_delete, false}],
-    case mqs:open([]) of
-        {ok, Channel} ->
-            error_logger:info_msg("Cration Exchange: ~p,",[{Channel,UserExchange,ExchangeOptions}]),
-            mqs_channel:create_exchange(Channel, UserExchange, ExchangeOptions),
-            Relations = build_user_relations(User, Groups),
-            [ mqs_channel:bind_exchange(Channel, ?USER_EXCHANGE(User#user.username), ?NOTIFICATIONS_EX, Route) || Route <- Relations],
-            mqs_channel:close(Channel);
-        {error,Reason} -> error_logger:info_msg("init_mq error: ~p",[Reason]) end.
-
-build_user_relations(User, Groups) -> [
-    mqs:key( [kvs_user, '*', User]),
-    mqs:key( [kvs_feed, user, User, '*', '*', '*']),
-    mqs:key( [kvs_feed, user, User, '*'] ),
-    mqs:key( [kvs_payment, user, User, '*']),
-    mqs:key( [kvs_account, user, User, '*']),
-    mqs:key( [kvs_meeting, user, User, '*']),
-    mqs:key( [kvs_purchase, user, User, '*']) |
-  [ mqs:key( [kvs_feed, group, G, '*', '*', '*']) || G <- Groups ]
-    ].
-
-rk_user_feed(User) -> mqs:key([kvs_feed, user, User, '*', '*', '*']).
-
-retrieve_connections(Id,Type) ->
-    Friends = case Type of 
-        user -> kvs_user:list_subscr_usernames(Id);
-        _ -> kvs_group:list_group_members(Id) end,
-    case Friends of
-        [] -> [];
-        Full -> Sub = lists:sublist(Full, 10),
-            case Sub of
-                [] -> [];
-                _ ->
-                    Data = [begin
-                        case kvs:get(user,Who) of
-                            {ok,User} -> RealName = kvs_user:user_realname_user(User),
-                            Paid = kvs_payment:user_paid(Who),
-                            {Who,Paid,RealName};
-                        _ -> undefined end end || Who <- Sub],
-                    [ X || X <- Data, X/=undefined ] end end.
-
-user_by_facebook_id(FBId) ->
-    case kvs:get(facebook,FBId) of
-        {ok,{_,User,_}} -> kvs:get(user,User);
-        Else -> Else end.
-
-user_by_googleplus_id(GId) ->
-    case kvs:get(googleplus,GId) of
-        {ok,{_,User,_}} -> kvs:get(user,User);
-        Else -> Else end.
-
-handle_notice([kvs_user, user, registered], {_,_,#user{id=Who}=U}, #state{owner=Who}=State)->
-    error_logger:info_msg("Notification about registered me ~p", [U]),
-    kvs_account:create_account(Who),
-    {ok, DefaultQuota} = kvs:get(config, "accounts/default_quota",  300),
-    kvs_account:transaction(Who, quota, DefaultQuota, #tx_default_assignment{}),
-    {noreply, State};
-
-handle_notice([kvs_user, user, Owner, delete],
-              [#user{}=U],
-              #state{owner=Owner}=State) ->
-    error_logger:info_msg("[kvs_user]Delete user ~p", [U]),
-    {noreply, State};
-
-handle_notice([kvs_user, login, user, Who, update_status],
-              {Status},
-              #state{owner=Who} = State) ->
-    error_logger:info_msg("[kvs_user] Update ~p status ~p", [Who, Status]),
-    case kvs:get(user, Who) of {error,_}-> ok;
-    {ok, U}-> kvs:put(U#user{status=Status}) end,
-
-    Update = case kvs:get(user_status, Who) of
-    {error, not_found} -> #user_status{email = Who, last_login = erlang:now()};
-    {ok, UserStatus} -> UserStatus#user_status{last_login = erlang:now()} end,
-    kvs:put(Update),
-
-    {noreply, State};
-
-handle_notice(["kvs_user", "subscribe", Who] = Route,
-    Message, #state{owner = Owner, type =Type} = State) ->
-    {Whom} = Message,
-    kvs_user:subscribe(Who, Whom),
-    subscription_mq(user, add, Who, Whom),
-    {noreply, State};
-
-handle_notice(["kvs_user", "unsubscribe", Who] = Route,
-    Message, #state{owner = Owner, type =Type} = State) ->
-    {Whom} = Message,
-    kvs_user:unsubscribe(Who, Whom),
-    subscription_mq(user, remove, Who, Whom),
-    {noreply, State};
-
-handle_notice(["kvs_user", "update", Who] = Route,
-    Message, #state{owner = Owner, type =Type} = State) ->
-    {NewUser} = Message,
-    kvs:put(NewUser),
-    {noreply, State};
-
-handle_notice(Route, Message, State) -> 
-  %error_logger:info_msg("Unknown USERS notice"), 
-  {noreply, State}.

+ 0 - 96
src/store_kai.erl

@@ -1,96 +0,0 @@
--module(store_kai).
--author('Maxim Sokhatsky <maxim@synrc.com>').
--copyright('Synrc Research Center s.r.o.').
--include_lib("kai/include/kai.hrl").
--include_lib("kvs/include/config.hrl").
--include_lib("kvs/include/users.hrl").
--include_lib("kvs/include/groups.hrl").
--include_lib("kvs/include/feeds.hrl").
--include_lib("kvs/include/acls.hrl").
--include_lib("kvs/include/invites.hrl").
--include_lib("kvs/include/meetings.hrl").
--include_lib("kvs/include/membership.hrl").
--include_lib("kvs/include/payments.hrl").
--include_lib("kvs/include/purchases.hrl").
--include_lib("kvs/include/accounts.hrl").
--include_lib("stdlib/include/qlc.hrl").
--compile(export_all).
-
-start() -> kai:start(), ok.
-stop() -> kai_store:stop(), ok.
-version() -> {version,"KVS KAI PURE XEN"}.
-join() -> initialize(), ok.
-join(Node) -> initialize(), ok.
-initialize() -> ok.
-dir() -> kvs:modules().
-
-put(Records) when is_list(Records) -> lists:foreach(fun kai_put/1, Records);
-put(Record) -> kai_put(Record).
-
-kai_put(Record) ->
-    Data = #data{key = element(2,Record), bucket = table_to_num(element(1,Record)),
-        last_modified = now(), checksum = erlang:md5(term_to_binary(Record)),
-        vector_clocks = vclock:fresh(), value = Record },
-    kai_store:put(Data).
-
-update(Record, Object) -> ok.
-
-get(Tab, Key) ->
-    Data = #data{key=Key,bucket=table_to_num(Tab)},
-    kai_get(Data).
-
-kai_get(Data) ->
-    case kai_store:get(Data) of
-         #data{value=Value} -> Value;
-         undefined -> {error,not_found};
-         E -> {error,E} end.
-
-delete(Tab, Key) ->
-    ok.
-
-key_to_bin(Key) ->
-    if is_integer(Key) -> erlang:list_to_binary(integer_to_list(Key));
-       is_list(Key) -> erlang:list_to_binary(Key);
-       is_atom(Key) -> erlang:list_to_binary(erlang:atom_to_list(Key));
-       is_binary(Key) -> Key;
-       true ->  [ListKey] = io_lib:format("~p", [Key]), erlang:list_to_binary(ListKey) end.
-
-all(RecordName) ->
-    {list_of_data,List} = kai_store:list(table_to_num(RecordName)),
-    [ kai_get(Data) || Data <- List ].
-
-all_by_index(Tab, IndexId, IndexVal) -> [].
-
-% index funs
-
-products(UId) -> all_by_index(user_product, <<"user_bin">>, list_to_binary(UId)).
-subscriptions(UId) -> all_by_index(subsciption, <<"subs_who_bin">>, list_to_binary(UId)).
-subscribed(Who) -> all_by_index(subscription, <<"subs_whom_bin">>, list_to_binary(Who)).
-participate(UserName) -> all_by_index(group_subscription, <<"who_bin">>, UserName).
-members(GroupName) -> all_by_index(group_subscription, <<"where_bin">>, GroupName).
-user_tournaments(UId) -> all_by_index(play_record, <<"play_record_who_bin">>, list_to_binary(UId)).
-tournament_users(TId) -> all_by_index(play_record, <<"play_record_tournament_bin">>, list_to_binary(integer_to_list(TId))).
-author_comments(Who) ->
-    EIDs = [E || #comment{entry_id=E} <- all_by_index(comment,<<"author_bin">>, Who) ],
-    lists:flatten([ all_by_index(entry,<<"entry_bin">>,EID) || EID <- EIDs]).
-
-table_to_num(user) -> 10;
-table_to_num(user_status) -> 20;
-table_to_num(subscription) -> 30;
-table_to_num(group) -> 40;
-table_to_num(group_subscription) -> 50;
-table_to_num(payment) -> 60;
-table_to_num(user_payment) -> 70;
-table_to_num(account) -> 80;
-table_to_num(transaction) -> 90;
-table_to_num(id_seq) -> 100;
-table_to_num(team) -> 110;
-table_to_num(membership) -> 120;
-table_to_num(product) -> 130;
-table_to_num(product_category) -> 140;
-table_to_num(user_product) -> 150;
-table_to_num(acl) -> 160;
-table_to_num(acl_entry) -> 170;
-table_to_num(feed) -> 180;
-table_to_num(entry) -> 190;
-table_to_num(comment) -> 200.

+ 0 - 139
src/store_mnesia.erl

@@ -1,139 +0,0 @@
--module(store_mnesia).
--author('Maxim Sokhatsky').
--copyright('Synrc Research Center s.r.o.').
--include_lib("kvs/include/config.hrl").
--include_lib("kvs/include/users.hrl").
--include_lib("kvs/include/groups.hrl").
--include_lib("kvs/include/feeds.hrl").
--include_lib("kvs/include/acls.hrl").
--include_lib("kvs/include/invites.hrl").
--include_lib("kvs/include/meetings.hrl").
--include_lib("kvs/include/membership.hrl").
--include_lib("kvs/include/payments.hrl").
--include_lib("kvs/include/purchases.hrl").
--include_lib("kvs/include/products.hrl").
--include_lib("kvs/include/accounts.hrl").
--include_lib("kvs/include/translations.hrl").
--include_lib("stdlib/include/qlc.hrl").
--compile(export_all).
-
-start() -> mnesia:start().
-stop() -> mnesia:stop().
-join() -> mnesia:change_table_copy_type(schema, node(), disc_copies), initialize().
-join(Node) ->
-    mnesia:change_config(extra_db_nodes, [Node]),
-    mnesia:change_table_copy_type(schema, node(), disc_copies),
-    [{Tb, mnesia:add_table_copy(Tb, node(), Type)}
-     || {Tb, [{Node, Type}]} <- [{T, mnesia:table_info(T, where_to_commit)}
-                               || T <- mnesia:system_info(tables)]].
-delete() -> mnesia:delete_schema([node()]).
-version() -> {version,"KVS MNESIA Embedded"}.
-
-initialize() ->
-    error_logger:info_msg("Mnesia Init"),
-    mnesia:create_schema([node()]),
-    [ Module:init(store_mnesia) || Module <- kvs:modules() ],
-    wait_for_tables(),
-    ok.
-
-wait_for_tables() ->
-    mnesia:wait_for_tables([user,product,group,entry,comment,subscription,group_subscription],5000).
-
-dir() ->
-    Tables = mnesia:system_info(local_tables),
-    [{table,atom_to_list(T)}||T<-Tables].
-get(RecordName, Key) -> just_one(fun() -> mnesia:read(RecordName, Key) end).
-put(Records) when is_list(Records) -> void(fun() -> lists:foreach(fun mnesia:write/1, Records) end);
-put(Record) -> put([Record]).
-
-delete(Keys) when is_list(Keys) -> void(fun() -> lists:foreach(fun mnesia:delete_object/1, Keys) end);
-delete(Keys) -> delete([Keys]).
-delete(Tab, Key) -> mnesia:transaction(fun()-> mnesia:delete({Tab, Key}) end), ok.
-
-multi_select(RecordName, Keys) when is_list(Keys) -> flatten(fun() -> [mnesia:read({RecordName, Key}) || Key <- Keys] end).
-
-select(From, PredicateFunction) when is_function(PredicateFunction) -> exec(qlc:q([Record || Record <- mnesia:table(From), apply(PredicateFunction, [Record])]));
-select(From, [{where, Fn}, {order, {Idx, Order}}]) -> exec(qlc:q([R || R <- qlc:keysort(Idx, mnesia:table(From), [{order, Order}]), apply(Fn, [R])]));
-select(From, [{where, Fn}, {order, {Idx, Order}}, {limit, {1, Length}}]) ->
-    {atomic, Recs} = mnesia:transaction(fun()->
-        QC = qlc:cursor(qlc:q(
-            [R || R <- qlc:keysort(Idx, mnesia:table(From), [{order, Order}]), apply(Fn, [R])])),
-        Ret = qlc:eval(qlc:next_answers(QC, Length)),
-        qlc:delete_cursor(QC),
-        Ret
-    end),
-    Recs;
-
-select(From, [{where, Fn}, {order, {Idx, Order}}, {limit, {Offset, Length}}]) ->
-    {atomic, Recs} = mnesia:transaction(fun()->
-        QC = qlc:cursor(qlc:q(
-            [R || R <- qlc:keysort(Idx, mnesia:table(From), [{order, Order}]), apply(Fn, [R])])),
-        qlc:next_answers(QC, Offset - 1),
-        Ret = qlc:eval(qlc:next_answers(QC, Length)),
-        qlc:delete_cursor(QC),
-        Ret
-    end),
-    Recs;
-
-select(RecordName, Key) -> many(fun() -> mnesia:read({RecordName, Key}) end).
-count(RecordName) -> mnesia:table_info(RecordName, size).
-all(RecordName) -> flatten(fun() -> Lists = mnesia:all_keys(RecordName), [ mnesia:read({RecordName, G}) || G <- Lists ] end).
-all_by_index(RecordName,Key,Value) -> flatten(fun() -> mnesia:index_read(RecordName,Value,Key) end).
-
-next_id(RecordName) -> next_id(RecordName, 1).
-next_id(RecordName, Incr) -> mnesia:dirty_update_counter({id_seq, RecordName}, Incr).
-
-just_one(Fun) ->
-    case mnesia:transaction(Fun) of
-        {atomic, []} -> {error, not_found};
-        {atomic, [R]} -> {ok, R};
-        {atomic, [_|_]} -> {error, duplicated};
-        _ -> {error, not_found} end.
-
-flatten(Fun) -> case mnesia:transaction(Fun) of {atomic, R} -> lists:flatten(R); _ -> [] end.
-many(Fun) -> case mnesia:transaction(Fun) of {atomic, R} -> R; _ -> [] end.
-void(Fun) -> case mnesia:transaction(Fun) of {atomic, ok} -> ok; {aborted, Error} -> {error, Error} end.
-
-create_table(Record, RecordInfo,  Opts0) ->
-    Attr = [{attributes, RecordInfo}],
-    Opts = transform_opts(Opts0),
-    AllOpts = lists:concat([Opts, Attr]),
-    case mnesia:create_table(Record, lists:flatten(AllOpts)) of
-        {atomic, ok}                         -> ok;
-        {aborted, {already_exists, Record}}  -> ok;
-        {aborted, Err}                       -> {error, Err} end.
-
-add_table_index(Record, Field) ->
-    catch case mnesia:add_table_index(Record, Field) of
-        {atomic, ok} -> ok;
-        {aborted,Reason} -> {aborted,Reason};
-        Err -> Err end.
-
-transform_opts(Opts) -> transform_opts(Opts, []).
-transform_opts([], Acc) -> lists:reverse(Acc);
-transform_opts([{storage, Value} | Rest], Acc0) ->
-    NewOpts = storage_to_mnesia_type(Value),
-    Acc = [NewOpts | Acc0],
-    transform_opts(Rest, Acc);
-transform_opts([Other | Rest], Acc0) ->
-    Acc = [Other | Acc0],
-    transform_opts(Rest, Acc).
-
-storage_to_mnesia_type(permanent) -> {disc_copies, [node()]};
-storage_to_mnesia_type(temporary) -> {ram_copies, [node()]};
-storage_to_mnesia_type(ondisk) -> {disc_only_copies, [node()]}.
-
-exec(Q) -> F = fun() -> qlc:e(Q) end, {atomic, Val} = mnesia:transaction(F), Val.
-
-% index funs
-
-products(UId) -> all_by_index(user_product, #user_product.username, UId).
-subscriptions(UId) -> all_by_index(subscription, #subscription.who, UId).
-subscribed(Who) -> all_by_index(subscription, #subscription.whom, Who).
-participate(UserName) -> all_by_index(group_subscription, #group_subscription.who, UserName).
-members(GroupName) -> all_by_index(group_subscription, #group_subscription.where, GroupName).
-user_tournaments(UId) -> all_by_index(play_record, #play_record.who, UId).
-tournament_users(TId) -> all_by_index(play_record, #play_record.tournament, TId).
-author_comments(Who) ->
-    EIDs = [E || #comment{entry_id=E} <- all_by_index(comment,#comment.from, Who) ],
-    lists:flatten([ all_by_index(entry, #entry.id,EID) || EID <- EIDs]).

+ 0 - 232
src/store_riak.erl

@@ -1,232 +0,0 @@
--module(store_riak).
--author('Maxim Sokhatsky <maxim@synrc.com>').
--copyright('Synrc Research Center s.r.o.').
--include_lib("kvs/include/config.hrl").
--include_lib("kvs/include/users.hrl").
--include_lib("kvs/include/groups.hrl").
--include_lib("kvs/include/feeds.hrl").
--include_lib("kvs/include/acls.hrl").
--include_lib("kvs/include/invites.hrl").
--include_lib("kvs/include/meetings.hrl").
--include_lib("kvs/include/membership.hrl").
--include_lib("kvs/include/payments.hrl").
--include_lib("kvs/include/purchases.hrl").
--include_lib("kvs/include/accounts.hrl").
--include_lib("stdlib/include/qlc.hrl").
--compile(export_all).
-
-start() -> ok.
-stop() -> ok.
-version() -> {version,"KVS RIAK 1.3.2-voxoz"}.
-join() -> initialize(), ok.
-join(Node) -> initialize(), ok.
-
-initialize() ->
-    C = riak:client_connect(node()),
-    ets:new(config, [named_table,{keypos,#config.key}]),
-    ets:insert(config, #config{ key = "riak_client", value = C}),
-    ok.
-
-dir() ->
-    C = riak_client(),
-    {ok,Buckets} = C:list_buckets(),
-    [{table,binary_to_list(X)}||X<-Buckets].
-
-riak_clean(Table) when is_list(Table)->
-    C = riak_client(),
-    {ok,Keys}=C:list_keys(erlang:list_to_binary(Table)),
-    [ C:delete(erlang:list_to_binary(Table),Key) || Key <- Keys];
-riak_clean(Table) ->
-    C = riak_client(),
-    [TableStr] = io_lib:format("~p",[Table]),
-    {ok,Keys}=C:list_keys(erlang:list_to_binary(TableStr)),
-    [ kvs:delete(Table,key_to_bin(Key)) || Key <- Keys].
-
-make_object(T) ->
-    Bucket = element(1,T),
-    Key = element(2,T),
-    Obj1 = riak_object:new(key_to_bin(Bucket), key_to_bin(Key), T),
-    Indices = make_indices(T),
-    Meta = dict:store(<<"index">>, Indices, dict:new()),
-    Obj2 = riak_object:update_metadata(Obj1, Meta),
-    error_logger:info_msg("RIAK PUT IDX ~p",[Indices]),
-    Obj2.
-
-make_indices(#subscription{who=Who, whom=Whom}) -> [
-    {<<"who_bin">>, key_to_bin(Who)},
-    {<<"whom_bin">>, key_to_bin(Whom)}];
-
-make_indices(#group_subscription{who=UId, where=GId}) -> [
-    {<<"who_bin">>, key_to_bin(UId)},
-    {<<"where_bin">>, key_to_bin(GId)}];
-
-make_indices(#user{username=UId,zone=Zone}) -> [
-    {<<"user_bin">>, key_to_bin(UId)},
-    {<<"zone_bin">>, key_to_bin(Zone)}];
-
-make_indices(#user_product{username=UId,product_id=PId}) -> [
-    {<<"user_bin">>, key_to_bin(UId)},
-    {<<"product_bin">>, key_to_bin(PId)}];
-
-make_indices(#payment{id=Id,user_id=UId}) -> [
-    {<<"payment_bin">>, key_to_bin(Id)},
-    {<<"user_bin">>, key_to_bin(UId)}];
-
-make_indices(#comment{id={CID,EID},from=Who}) -> [
-    {<<"comment_bin">>, key_to_bin({CID,EID})},
-    {<<"author_bin">>, key_to_bin(Who)}];
-
-make_indices(#entry{id={EID,FID},entry_id=EntryId,feed_id=Feed,from=From,to=To}) -> [
-    {<<"entry_feed_bin">>, key_to_bin({EID,FID})},
-    {<<"entry_bin">>, key_to_bin(EntryId)},
-    {<<"from_bin">>, key_to_bin(From)},
-    {<<"to_bin">>, key_to_bin(To)},
-    {<<"feed_bin">>, key_to_bin(Feed)}];
-
-make_indices(Record) -> [
-    {key_to_bin(atom_to_list(element(1,Record))++"_bin"),key_to_bin(element(2,Record))}].
-
-riak_client() -> [{_,_,{_,C}}] = ets:lookup(config, "riak_client"), C.
-
-put(Records) when is_list(Records) -> lists:foreach(fun riak_put/1, Records);
-put(Record) -> riak_put(Record).
-
-riak_put(Record) ->
-    Object = make_object(Record),
-    Riak = riak_client(),
-    Result = Riak:put(Object),
-    post_write_hooks(Record, Riak),
-    Result.
-
-put_if_none_match(Record) ->
-    Object = make_object(Record),
-    Riak = riak_client(),
-    case Riak:put(Object, [if_none_match]) of
-        ok -> post_write_hooks(Record, Riak), ok;
-        Error -> Error end.
-
-update(Record, Object) ->
-    NewObject = make_object(Record),
-    NewKey = riak_object:key(NewObject),
-    case riak_object:key(Object) of
-        NewKey ->
-            MetaInfo = riak_object:get_update_metatdata(NewObject),
-            UpdObject2 = riak_object:update_value(Object, Record),
-            UpdObject3 = riak_object:update_metadata(UpdObject2, MetaInfo),
-            Riak = riak_client(),
-            case Riak:put(UpdObject3, [if_not_modified]) of
-                ok -> post_write_hooks(Record, Riak), ok;
-                Error -> Error
-            end;
-        _ -> {error, keys_not_equal}
-    end.
-
-post_write_hooks(R,C) ->
-    case element(1,R) of
-        user -> case R#user.email of
-                    undefined -> nothing;
-                    _ -> C:put(make_object({email, R#user.username, R#user.email})) end,
-                case R#user.facebook_id of
-                  undefined -> nothing;
-                  _ -> C:put(make_object({facebook, R#user.username, R#user.facebook_id})) end,
-                case R#user.googleplus_id of
-                  undefined -> nothing;
-                  _ -> C:put(make_object({googleplus, R#user.username, R#user.googleplus_id})) end,
-                case R#user.twitter_id of
-                  undefined -> nothing;
-                  _ -> C:put(make_object({twitter, R#user.username, R#user.twitter_id})) end,
-                case R#user.github_id of
-                  undefined -> nothing;
-                  _ -> C:put(make_object({github, R#user.username, R#user.github_id})) end;
-        _ -> continue end.
-
-get(Tab, Key) ->
-    Bucket = key_to_bin(Tab),
-    IntKey = key_to_bin(Key),
-    riak_get(Bucket, IntKey).
-
-riak_get(Bucket,Key) ->
-    C = riak_client(),
-    RiakAnswer = C:get(Bucket,Key),
-    case RiakAnswer of
-        {ok, O} -> {ok, riak_object:get_value(O)};
-        X -> X end.
-
-get_for_update(Tab, Key) ->
-    C = riak_client(),
-    case C:get(key_to_bin(Tab), key_to_bin(Key)) of
-        {ok, O} -> {ok, riak_object:get_value(O), O};
-        Error -> Error end.
-
-delete(Tab, Key) ->
-    C = riak_client(),
-    Bucket = key_to_bin(Tab),
-    IntKey = key_to_bin(Key),
-    C:delete(Bucket, IntKey).
-
-delete_by_index(Tab, IndexId, IndexVal) ->
-    Riak = riak_client(),
-    Bucket = key_to_bin(Tab),
-    {ok, Keys} = Riak:get_index(Bucket, {eq, IndexId, key_to_bin(IndexVal)}),
-    [Riak:delete(Bucket, Key) || Key <- Keys].
-
-key_to_bin(Key) ->
-    if is_integer(Key) -> erlang:list_to_binary(integer_to_list(Key));
-       is_list(Key) -> erlang:list_to_binary(Key);
-       is_atom(Key) -> erlang:list_to_binary(erlang:atom_to_list(Key));
-       is_binary(Key) -> Key;
-       true ->  [ListKey] = io_lib:format("~p", [Key]), erlang:list_to_binary(ListKey) end.
-
-all(RecordName) ->
-    Riak = riak_client(),
-    RecordBin = key_to_bin(RecordName),
-    {ok,Keys} = Riak:list_keys(RecordBin),
-    Results = [ riak_get_raw({RecordBin, Key, Riak}) || Key <- Keys ],
-    [ Object || Object <- Results, Object =/= failure ].
-
-all_by_index(Tab, IndexId, IndexVal) ->
-    Riak = riak_client(),
-    Bucket = key_to_bin(Tab),
-    {ok, Keys} = Riak:get_index(Bucket, {eq, IndexId, key_to_bin(IndexVal)}),
-    lists:foldl(fun(Key, Acc) ->
-        case Riak:get(Bucket, Key, []) of
-            {ok, O} -> [riak_object:get_value(O) | Acc];
-            {error, notfound} -> Acc end end, [], Keys).
-
-riak_get_raw({RecordBin, Key, Riak}) ->
-    case Riak:get(RecordBin, Key) of
-        {ok,O} -> riak_object:get_value(O);
-        X -> failure end.
-
-next_id(CounterId) -> next_id(CounterId, 1).
-next_id(CounterId, Incr) -> next_id(CounterId, 0, Incr).
-next_id(CounterId, Default, Incr) ->
-    Riak = riak_client(),
-    CounterBin = key_to_bin(CounterId),
-    {Object, Value, Options} =
-        case Riak:get(key_to_bin(id_seq), CounterBin, []) of
-            {ok, CurObj} ->
-                R = #id_seq{id = CurVal} = riak_object:get_value(CurObj),
-                NewVal = CurVal + Incr,
-                Obj = riak_object:update_value(CurObj, R#id_seq{id = NewVal}),
-                {Obj, NewVal, [if_not_modified]};
-            {error, notfound} ->
-                NewVal = Default + Incr,
-                Obj = riak_object:new(key_to_bin(id_seq), CounterBin, #id_seq{thing = CounterId, id = NewVal}),
-                {Obj, NewVal, [if_none_match]} end,
-    case Riak:put(Object, Options) of
-        ok -> Value;
-        {error, _} -> next_id(CounterId, Incr) end.
-
-% index funs
-
-products(UId) -> all_by_index(user_product, <<"user_bin">>, list_to_binary(UId)).
-subscriptions(UId) -> all_by_index(subsciption, <<"subs_who_bin">>, list_to_binary(UId)).
-subscribed(Who) -> all_by_index(subscription, <<"subs_whom_bin">>, list_to_binary(Who)).
-participate(UserName) -> all_by_index(group_subscription, <<"who_bin">>, UserName).
-members(GroupName) -> all_by_index(group_subscription, <<"where_bin">>, GroupName).
-user_tournaments(UId) -> all_by_index(play_record, <<"play_record_who_bin">>, list_to_binary(UId)).
-tournament_users(TId) -> all_by_index(play_record, <<"play_record_tournament_bin">>, list_to_binary(integer_to_list(TId))).
-author_comments(Who) ->
-    EIDs = [E || #comment{entry_id=E} <- all_by_index(comment,<<"author_bin">>, Who) ],
-    lists:flatten([ all_by_index(entry,<<"entry_bin">>,EID) || EID <- EIDs]).