Kannel: Open Source WAP and SMS gateway  $Revision: 5037 $
load.c
Go to the documentation of this file.
1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2016 Kannel Group
5  * Copyright (c) 1998-2001 WapIT Ltd.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Kannel Group (http://www.kannel.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Kannel" and "Kannel Group" must not be used to
28  * endorse or promote products derived from this software without
29  * prior written permission. For written permission, please
30  * contact org@kannel.org.
31  *
32  * 5. Products derived from this software may not be called "Kannel",
33  * nor may "Kannel" appear in their name, without prior written
34  * permission of the Kannel Group.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
40  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
41  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
42  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
46  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Kannel Group. For more information on
51  * the Kannel Group, please see <http://www.kannel.org/>.
52  *
53  * Portions of this software are based upon software originally written at
54  * WapIT Ltd., Helsinki, Finland for the Kannel project.
55  */
56 
63 #include "gwlib/gwlib.h"
64 #include "load.h"
65 
66 
67 struct load_entry {
68  float prev;
69  float curr;
70  double last;
71  int interval;
72  int dirty;
73 };
74 
75 
76 struct load {
77  struct load_entry **entries;
78  int len;
79  int heuristic;
81 };
82 
83 static double microtime(double *p) {
84  struct timeval tv;
85  double result;
86 
87  gettimeofday(&tv, NULL);
88  result = tv.tv_sec + (1e-6 * tv.tv_usec);
89 
90  if(p != NULL) {
91  *p = result;
92  }
93 
94  return result;
95 }
96 
97 Load* load_create_real(int heuristic)
98 {
99  struct load *load;
100 
101  load = gw_malloc(sizeof(*load));
102  load->len = 0;
103  load->entries = NULL;
104  load->heuristic = heuristic;
105  load->lock = gw_rwlock_create();
106 
107  return load;
108 }
109 
110 
112 {
113  int i;
114  struct load_entry *entry;
115 
116  if (load == NULL)
117  return -1;
118 
119  gw_rwlock_wrlock(load->lock);
120 
121  /* first look if we have equal interval added already */
122  for (i = 0; i < load->len; i++) {
123  if (load->entries[i]->interval == interval) {
124  gw_rwlock_unlock(load->lock);
125  return -1;
126  }
127  }
128  /* so no equal interval there, add new one */
129  entry = gw_malloc(sizeof(struct load_entry));
130  entry->prev = entry->curr = 0.0;
131  entry->interval = interval;
132  entry->dirty = 1;
133  microtime(&entry->last);
134 
135  load->entries = gw_realloc(load->entries, sizeof(struct load*) * (load->len + 1));
136  load->entries[load->len] = entry;
137  load->len++;
138 
139  gw_rwlock_unlock(load->lock);
140 
141  return 0;
142 }
143 
144 
146 {
147  int i;
148 
149  if (load == NULL)
150  return;
151 
152  for (i = 0; i < load->len; i++) {
153  gw_free(load->entries[i]);
154  }
155  gw_free(load->entries);
156  gw_rwlock_destroy(load->lock);
157  gw_free(load);
158 }
159 
160 
161 void load_increase_with(Load *load, unsigned long value)
162 {
163  double now;
164  int i;
165 
166  if (load == NULL)
167  return;
168 
169  gw_rwlock_wrlock(load->lock);
170  microtime(&now);
171  for (i = 0; i < load->len; i++) {
172  struct load_entry *entry = load->entries[i];
173  /* check for special case, load over whole live time */
174  if((entry->interval != -1 && now >= entry->last + entry->interval)) {
175  /* rotate */
176  entry->curr /= entry->interval;
177  if (entry->prev > 0)
178  entry->prev = (2*entry->curr + entry->prev)/3;
179  else
180  entry->prev = entry->curr;
181  entry->last = now;
182  entry->curr = 0.0;
183  entry->dirty = 0;
184  }
185  entry->curr += value;
186  }
187  gw_rwlock_unlock(load->lock);
188 }
189 
190 
191 double load_get(Load *load, int pos)
192 {
193  double ret;
194  double now;
195  struct load_entry *entry;
196 
197  if (load == NULL || pos >= load->len) {
198  return -1.0;
199  }
200 
201  /* first maybe rotate load */
202  load_increase_with(load, 0);
203 
204  microtime(&now);
205  gw_rwlock_rdlock(load->lock);
206  entry = load->entries[pos];
207  if (load->heuristic && !entry->dirty) {
208  ret = entry->prev;
209  } else {
210  double diff = (now - entry->last);
211  if (diff == 0) diff = 1;
212  ret = entry->curr/diff;
213  ret = (ret > entry->curr ? entry->curr : ret);
214  }
215  gw_rwlock_unlock(load->lock);
216 
217  return ret;
218 }
219 
220 
222 {
223  int ret;
224  if (load == NULL)
225  return 0;
226  gw_rwlock_rdlock(load->lock);
227  ret = load->len;
228  gw_rwlock_unlock(load->lock);
229  return ret;
230 }
float curr
Definition: load.c:69
float prev
Definition: load.c:68
void gw_rwlock_destroy(RWLock *lock)
Definition: gw-rwlock.c:112
int gw_rwlock_wrlock(RWLock *lock)
Definition: gw-rwlock.c:177
int load_add_interval(Load *load, int interval)
Definition: load.c:111
Load * load_create_real(int heuristic)
Definition: load.c:97
RWLock * gw_rwlock_create(void)
Definition: gw-rwlock.c:77
int gw_rwlock_rdlock(RWLock *lock)
Definition: gw-rwlock.c:134
struct load_entry ** entries
Definition: load.c:77
double load_get(Load *load, int pos)
Definition: load.c:191
RWLock * lock
Definition: load.c:80
int load_len(Load *load)
Definition: load.c:221
int len
Definition: load.c:78
int interval
Definition: load.c:71
double last
Definition: load.c:70
int gw_rwlock_unlock(RWLock *lock)
Definition: gw-rwlock.c:155
double interval
Definition: fakewap.c:234
Definition: load.c:67
void load_destroy(Load *load)
Definition: load.c:145
Definition: load.c:76
int heuristic
Definition: load.c:79
static double microtime(double *p)
Definition: load.c:83
void load_increase_with(Load *load, unsigned long value)
Definition: load.c:161
int dirty
Definition: load.c:72
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.