How can I create an OID from time - c

In pymongo you can do something like this to create an OID from time:
dummy_id = ObjectId.from_datetime(time)
Is there something like that in mongoc?
I saw that there's a "bson_oid_get_time_t()" function, but is there a reverse function of this, and if not, How can it be implemented in C?

I don't believe there is a reverse function, but it should be easy for you to generate your own using the default constructor and "fixing" the time.
Here is an example where I create an object ID.
Then I create a timestamp for December 25, 2014 and modify the OID to that date.
#include <time.h>
#include <bson.h>
int
main (int argc,
char *argv[])
{
time_t oid_thinks_time; //what time does the OID think it is
bson_oid_t oid;
bson_oid_t *oid_pointer = &oid;
bson_oid_init (&oid, NULL); // get a standard ObjectId
oid_thinks_time = bson_oid_get_time_t (&oid); //It was just made
printf ("The OID was generated at %u\n", (unsigned) oid_thinks_time); //prove it
time_t ts = time(NULL); //make a new time
struct tm * timeinfo = localtime(&ts);
timeinfo->tm_year = 2014-1900; //-1900 because time.h
timeinfo->tm_mon = 12 - 1; // time.h off by one (starts at 0)
timeinfo->tm_mday = 25;
ts = mktime(timeinfo); // create the time
u_int32_t ts_uint = (uint32_t)ts;
ts_uint = BSON_UINT32_TO_BE (ts_uint); //BSON wants big endian time
memcpy (&oid_pointer->bytes[0], &ts_uint, sizeof (ts_uint)); //overwrite the first 4 bytes with user selected time
oid_thinks_time = bson_oid_get_time_t (&oid);
printf ("The OID was fixed to time %u\n", (unsigned) oid_thinks_time);//prove it
}
The output of this code is:
The OID was generated at 1491238015
The OID was fixed to time 1419526015

Related

How to send messages in PM server Minix

So I'm trying to create a new system call on PM server. My question is, how can I send some kind of message to function.
in IPC server all I had to do is add my system call to the list, because all functions there were defined as (*func)(message *)
(...)/servers/ipc/main.c
static struct {
int type;
int (*func)(message *);
int reply; /* whether the reply action is passed through */
} ipc_calls[] = {
(...)
{ IPC_MYNEWSIGNAL, do_something, 1 },
};
but in PM in table.c functions are defined as
(...)/servers/pm/table.c
int (* const call_vec[NR_PM_CALLS])(void) = {
(...)
CALL(PM_GETSYSINFO) = do_getsysinfo
}
and if I try to pass function with signature
int do_something(message *m)
I will get error:
Incompatible pointer types: initializing int (*const)(void) with int (message *)
What is the correct way to create signal on PM server if I need to receive some kind of information?
As far as I understood from the question, you want to receive arguments inside the syscall handler. Let's take as an example the library function clock_settime from libc.
int clock_settime(clockid_t clock_id, const struct timespec *ts)
{
message m;
memset(&m, 0, sizeof(m));
m.m_lc_pm_time.clk_id = clock_id;
m.m_lc_pm_time.now = 1; /* set time immediately. don't use adjtime() method. */
m.m_lc_pm_time.sec = ts->tv_sec;
m.m_lc_pm_time.nsec = ts->tv_nsec;
if (_syscall(PM_PROC_NR, PM_CLOCK_SETTIME, &m) < 0)
return -1;
return 0;
}
As you can see it writes the args inside message struct and passes to _syscall. OK, now have a look at syscall handler for PM_CLOCK_SETTIME which is mounted in table.c.
int do_gettime()
{
clock_t ticks, realtime, clock;
time_t boottime;
int s;
if ( (s=getuptime(&ticks, &realtime, &boottime)) != OK)
panic("do_time couldn't get uptime: %d", s);
switch (m_in.m_lc_pm_time.clk_id) {
case CLOCK_REALTIME:
clock = realtime;
break;
case CLOCK_MONOTONIC:
clock = ticks;
break;
default:
return EINVAL; /* invalid/unsupported clock_id */
}
mp->mp_reply.m_pm_lc_time.sec = boottime + (clock / system_hz);
mp->mp_reply.m_pm_lc_time.nsec =
(uint32_t) ((clock % system_hz) * 1000000000ULL / system_hz);
return(OK);
}
It becomes clear that the argument is a global variable named m_in. A little bit more search shows that it comes from glo.h
/* The parameters of the call are kept here. */
EXTERN message m_in; /* the incoming message itself is kept here. */
I suppose that MINIX will handle setting and accessing the global variable, so you don't need to explicitly write to it.
Have a look at point 7 Passing a parameter to a system call here. To understand how to compile the kernel correctly refer to this post.

What function in C can I use to get the date alone separate from time?

I am building a C program and I need to use time separately and also the date separately. I want to do this without using the structure struct tm since I have to send the time and the date to different columns in my database table called Logs:
int main(){
duration = clock() - duration;
double Duration = ((double)duration)/CLOCKS_PER_SEC;
char* IPaddr = inet_ntoa(newAddr.sin_addr);
int PortNo = ntohs(newAddr.sin_port);
printf("\n%s %s %d %f\n", task, IPaddr, PortNo, Duration);
printf("now: %d-%d-%d %d:%d:%d\n",tm.tm_mday,tm.tm_mon+1,tm.tm_year+1900,tm.tm_hour,tm.tm_min,tm.tm_sec);
if (mysql_query(con, "INSERT INTO Logs(ClientIP, ClientPort, Job_type, SubmissionTime, SubmissionDate, Duration)
VALUES(%s, %d, %s, %, %, %f)")) {
finish_with_error(con);
}
return 0;
}
You might want to declare two character arrays, one for the date string and one for the time string, and call strftime twice to construct them.
Something like this:
char SubmissionDate[20], SubmissionTime[20];
strftime(SubmissionDate, sizeof(SubmissionDate), "%Y-%m-%d", &tm);
strftime(SubmissionTime, sizeof(SubmissionTime), "%H:%M:%S", &tm);

Access violation when trying to populate an array of struct

Original code comment specifying the core question:
The error I am getting is while iterating through the while loop,
memory out of range or something... resizing to 300 ... Access
violation writing location that's the exact Fraze...
I'm trying to implement a faster .Net List<T> equivalent in C.
I'm using blittable data types in C#.
In the code below I've moved a function body to the main function just for testing after I have failed to understand where am I wrong.
The problem seems to be that inside the while loop UntArr does not increment.
What am I doing wrong?
typedef struct {
int Id;
char *StrVal;
}Unit; // a data unit as element of an array
unsigned int startTimer(unsigned int start);
unsigned int stopTimer(unsigned int start);
int main(){
Unit *UntArr= {NULL};
//Unit test[30000];
//decelerations comes first..
char *dummyStringDataObject;
int adummyNum,requestedMasterArrLength,requestedStringSize,MasterDataArrObjectMemorySize,elmsz;
int TestsTotalRounds, TestRoundsCounter,ccountr;
unsigned int start, stop, mar;
//Data Settings (manually for now)
requestedMasterArrLength=300;
requestedStringSize = 15;
//timings
start=0;stop=0;
//data sizes varies (x86/x64) compilation according to fastest results
MasterDataArrObjectMemorySize = sizeof(UntArr);
elmsz= sizeof(UntArr[0]);
TestRoundsCounter=-1;
start = startTimer(start);
while(++TestRoundsCounter<requestedMasterArrLength){
int count;
count=-1;
//allocate memory for the "Master Arr"
UntArr = (Unit *)malloc(sizeof(Unit)*requestedMasterArrLength);
dummyStringDataObject = (char*)malloc(sizeof(char)*requestedStringSize);
dummyStringDataObject = "abcdefgHijkLmNo";
while (++count<requestedMasterArrLength)
{
dummyStringDataObject[requestedStringSize-1]=count+'0';
puts(dummyStringDataObject);
ccountr=-1;
// tried
UntArr[count].Id = count;
UntArr[count].StrVal = (char*)malloc(sizeof(char)*requestedStringSize);
UntArr[count].StrVal = dummyStringDataObject;// as a whole
//while(++ccountr<15)// one by one cause a whole won't work ?
//UntArr[count].StrVal[ccountr] = dummyStringDataObject[ccountr];
}
free(UntArr);free(dummyStringDataObject);
}
stop = startTimer(start);
mar = stop - start;
MasterDataArrObjectMemorySize = sizeof(UntArr)/1024;
printf("Time taken in millisecond: %d ( %d sec)\r\n size: %d kb\r\n", mar,(mar/1000),MasterDataArrObjectMemorySize);
printf("UntArr.StrVal: %s",UntArr[7].StrVal);
getchar();
return 0;
}
unsigned int startTimer(unsigned int start){
start = clock();
return start;
}
unsigned int stopTimer(unsigned int start){
start = clock()-start;
return start;
}
testing the code one by one instead of within a while loop work as expected
//allocate memory for the "Master Arr"
UntArr = (Unit *)malloc(sizeof(Unit)*requestedMasterArrLength);
UntArr[0].Id = 0;
dummyStringDataObject = (char*)malloc(sizeof(char)*requestedStringSize);
dummyStringDataObject = "abcdefgHijkLmNo";
////allocate memory for the string object
UntArr[0].StrVal = (char*)malloc(sizeof(char)*requestedStringSize);
////test string manipulation
adummyNum=5;
UntArr[0].StrVal= dummyStringDataObject;
//
UntArr[0].StrVal[14] = adummyNum+'0';
////test is fine
as it happens and as i am new to pointers i have not realize that when debugging
i will not see the elements of given pointer to an array as i am used to
with normal Array[] but looping through result which i did not even try as when i was hovering above the Array* within the while loop expecting to see the elements as in a normal array:
Data[] DataArr = new Data[1000] <- i have expected to actually see the body of the array while looping and populating the Data* and did not realize it is not an actual array but a pointer to one so you can not see the elements/body.
the solution is via a function now as planed originally :
void dodata(int requestedMasterArrLength,int requestedStringSize){
int ccountr,count;
count=0;
UntArr=NULL;
UntArr = (Unit *)malloc(sizeof(Unit)*requestedMasterArrLength);
while(count!=requestedMasterArrLength)
{
char dummyStringDataObject[]= "abcdefgHi";
UntArr[count].StrVal=NULL;
dummyStringDataObject[requestedStringSize-1] = count+'0';
UntArr[count].Id= count;
ccountr=0;
UntArr[count].StrVal= (char*)malloc(sizeof(char)*requestedStringSize);
while(ccountr!=requestedStringSize){
UntArr[count].StrVal[ccountr] = dummyStringDataObject[ccountr];
++ccountr;
}
++count;
}
}
generaly speaking, x86 compilation would get better performance for this current task , populating an array of a struct.
so i have compiled it also in c++ and c#.
executing similar code in C# and C++
minimum time measured in c# ~ 3,100 ms.
minimum time measured in this code - C ~ 1700 ms.
minimum time measured in C++ ~ 900 ms.
i was surprised to see this last result c++ is the winner but why.
i thought c is closer to the system level, CPU, Memory...

ASN1_TIME_print functionality without BIO?

As described in this question: Openssl C++ get expiry date, there is the possibility to write an ASN1 time into a BIO buffer and then read it back into a custom buffer buf:
BIO *bio;
int write = 0;
bio = BIO_new(BIO_s_mem());
if (bio) {
if (ASN1_TIME_print(bio, tm))
write = BIO_read(bio, buf, len-1);
BIO_free(bio);
}
buf[write]='\0';
return write;
How could this be achieved without using BIO at all? The ASN1_TIME_print function is only present when OPENSSL_NO_BIO is not defined. Is there a way to write the time directly into a given buffer?
You can try the sample code below. It doesn't use BIO, but should give you the same output as the OP's example. If you don't trust the ASN1_TIME string, you'll want to add some error checking for:
notBefore->data is > 10 chars
each char value is between '0' and '9'
values for year, month, day, hour, minute, second
type
You should test for the type (i.e. UTC), if you expect multiple types.
You should also test whether or not the date/time is GMT and add that to the string if you want the output to match exactly as if using BIOs. see:
openssl/crypto/asn1/t_x509.c - ASN1_UTCTIME_print or ASN1_GENERALIZEDTIME_print
ASN1_TIME* notBefore = NULL;
int len = 32;
char buf[len];
struct tm tm_time;
notBefore = X509_get_notBefore(x509_cert);
// Format ASN1_TIME with type UTC into a tm struct
if(notBefore->type == V_ASN1_UTCTIME){
strptime((const char*)notBefore->data, "%y%m%d%H%M%SZ" , &tm_time);
strftime(buf, sizeof(char) * len, "%h %d %H:%M:%S %Y", &tm_time);
}
// Format ASN1_TIME with type "Generalized" into a tm struct
if(notBefore->type == V_ASN1_GENERALIZEDTIME){
// I didn't look this format up, but it shouldn't be too difficult
}
I think this should be possible, at least in terms of writing the time directly into a given buffer -- but you'll still need to use BIOs.
Ideally, BIO_new_mem_buf would suit, given that it creates an in-memory BIO using a given buffer as the source. Unfortunately, that function treats the given buffer as read-only, which is not what we want. However, we can create our own function (let's call it BIO_new_mem_buf2), based on the BIO_new_mem_buf source code:
BIO *BIO_new_mem_buf2(void *buf, int len)
{
BIO *ret;
BUF_MEM *b;
size_t sz;
if (!buf) {
BIOerr(BIO_F_BIO_NEW_MEM_BUF, BIO_R_NULL_PARAMETER);
return NULL;
}
sz = (size_t)len;
if (!(ret = BIO_new(BIO_s_mem())))
return NULL;
b = (BUF_MEM *)ret->ptr;
b->data = buf;
b->length = sz;
b->max = sz;
return ret;
}
This is just like BIO_new_mem_buf, except that a) the len argument must indicate the size of the given buffer, and b) the BIO is not marked "readonly".
With the above, you should now be able to call:
ASN1_TIME_print(bio, tm)
and have the time appear in your given buffer.
Note that I have not tested the above code, so YMMV. Hope this helps!

can't get C method icalrecur_expand_recurrence to work

This is a bit frustrating. I've been working on this for a while now, and I can't seem to get this method to work like it says it does.
#include "icalrecur.h"
#include <time.h> /* for time() */
#include <stdio.h>
int get_occurrences(char* rrule, time_t start, int count)
{
//char* rule; /* rule string */
// *rule = PG_GETARG_CHAR(0);
time_t *result[count]; /* output array */
icalrecur_expand_recurrence(rrule, start, count, *result);
return (time_t) *result;
}
//time_t *output[5*8];
void main() {
time_t right_now = time(0);
char *_rrule = "FREQ=WEEKLY;INTERVAL=2;COUNT=8;WKST=SU;BYDAY=TU,TH";
get_occurrences(_rrule, right_now, 5);
}
I save this test file as ical_recur.h. Then I type in bash:
gcc -I/usr/local/libical/include/libical -L/usr/local/libical/lib/ -lical -o hello ical_recur.c
To include the libical.a libraries. The include/libical directory has icalrecur.h in it, so I really don't even need to be including the whole ical library.
~: ./hello
Segmentation fault
Anytime I change around any pointers, it starts complaining about something during compilation. Can anyone get this to work?? Source files are from Marketcircle on github.
Looking at the documentation it seems that you have an unwanted extra level of indirection - you need to change:
time_t *result[count]; /* output array */
icalrecur_expand_recurrence(rrule, start, count, *result);
to:
time_t result[count]; /* output array */
icalrecur_expand_recurrence(rrule, start, count, result);
Also you're passing a read-only string literal to a function which expects a char * - this should at least give you a compiler warning (hint: always use gcc -Wall ..., read the warnings carefully, understand them and fix them). main() should look more like this:
int main() {
time_t right_now = time(0);
char _rrule[] = "FREQ=WEEKLY;INTERVAL=2;COUNT=8;WKST=SU;BYDAY=TU,TH";
get_occurrences(_rrule, right_now, 5);
return 0;
}
Some more problems:
this line doesn't do anything useful, but it's not clear what you're trying to achieve:
char _size = (char)(((int)'0') + sizeof(result));
all those casts are a "code smell" and this should tell you that you're doing something very wrong here
your function is defined as returning an int, but you're trying to cast your array to a time_t and return that, which also makes no sense - again, turn on compiler warnings - let the compiler help you find and fix your mistakes.
Now you can use this extension for postgresql.
Example usage:
SELECT * FROM
unnest(
rrule_get_occurrences('FREQ=WEEKLY;INTERVAL=1;WKST=MO;UNTIL=20200101T045102Z;BYDAY=SA;BYHOUR=10;BYMINUTE=51;BYSECOND=2'::rrule,
'2019-12-07 10:51:02+00'::timestamp with time zone)
);
unnest
------------------------
2019-12-07 10:51:02+00
2019-12-14 10:51:02+00
2019-12-21 10:51:02+00
2019-12-28 10:51:02+00
(4 rows)

Resources