Exemplo n.º 1
0
/**
 * 好友发送个性签名.
 */
void UdpData::SomeoneSendSign()
{
        PalInfo *pal;
        char *sign;

        if (!(pal = cthrd.GetPalFromList(ipv4)))
                return;

        /* 若好友不兼容iptux协议,则需转码 */
        if (!FLAG_ISSET(pal->flags, 0))
                ConvertEncode(pal->encode);
        /* 对编码作适当调整 */
        if (strcasecmp(pal->encode, encode ? encode : "utf-8") != 0) {
                g_free(pal->encode);
                pal->encode = g_strdup(encode ? encode : "utf-8");
        }
        /* 更新 */
        if ( (sign = ipmsg_get_attach(buf, ':', 5))) {
                g_free(pal->sign);
                pal->sign = sign;
                gdk_threads_enter();
                pthread_mutex_lock(cthrd.GetMutex());
                cthrd.UpdatePalToList(ipv4);
                pthread_mutex_unlock(cthrd.GetMutex());
                mwin.UpdateItemToPaltree(ipv4);
                gdk_threads_leave();
        }
}
Exemplo n.º 2
0
/**
 * 更新好友信息数据.
 * @param pal 好友数据
 */
void UdpData::UpdatePalInfo(PalInfo *pal)
{
        g_free(pal->segdes);
        pal->segdes = progdt.FindNetSegDescription(ipv4);
        g_free(pal->version);
        if (!(pal->version = iptux_get_section_string(buf, ':', 0)))
                pal->version = g_strdup("?");
        g_free(pal->user);
        if (!(pal->user = iptux_get_section_string(buf, ':', 2)))
                pal->user = g_strdup("???");
        g_free(pal->host);
        if (!(pal->host = iptux_get_section_string(buf, ':', 3)))
                pal->host = g_strdup("???");
        if (!FLAG_ISSET(pal->flags, 2)) {
                g_free(pal->name);
                if (!(pal->name = ipmsg_get_attach(buf, ':', 5)))
                        pal->name = g_strdup(_("mysterious"));
                g_free(pal->group);
                pal->group = GetPalGroup();
                g_free(pal->iconfile);
                if (!(pal->iconfile = GetPalIcon()))
                        pal->iconfile = g_strdup(progdt.palicon);
                FLAG_CLR(pal->flags, 0);
                g_free(pal->encode);
                if ( (pal->encode = GetPalEncode()))
                        FLAG_SET(pal->flags, 0);
                else
                        pal->encode = g_strdup(encode ? encode : "utf-8");
        }
        FLAG_SET(pal->flags, 1);
        pal->packetn = 0;
        pal->rpacketn = 0;
}
Exemplo n.º 3
0
/**
 * 好友上线.
 */
void UdpData::SomeoneEntry()
{
        Command cmd;
        pthread_t pid;
        PalInfo *pal;

        /* 转换缓冲区数据编码 */
        ConvertEncode(progdt.encode);

        /* 加入或更新好友列表 */
        gdk_threads_enter();
        pthread_mutex_lock(cthrd.GetMutex());
        if ( (pal = cthrd.GetPalFromList(ipv4))) {
                UpdatePalInfo(pal);
                cthrd.UpdatePalToList(ipv4);
        } else {
                pal = CreatePalInfo();
                cthrd.AttachPalToList(pal);
        }
        pthread_mutex_unlock(cthrd.GetMutex());
        if (mwin.PaltreeContainItem(ipv4))
                mwin.UpdateItemToPaltree(ipv4);
        else
                mwin.AttachItemToPaltree(ipv4);
        gdk_threads_leave();

        /* 通知好友本大爷在线 */
        cmd.SendAnsentry(cthrd.UdpSockQuote(), pal);
        if (FLAG_ISSET(pal->flags, 0)) {
                pthread_create(&pid, NULL, ThreadFunc(CoreThread::SendFeatureData), pal);
                pthread_detach(pid);
        }
}
Exemplo n.º 4
0
		extern int attrlayer_flush(int flags)
		{
			static t_elist *curr = &loadedlist;
			static t_elist *next = NULL;
			t_attrgroup *attrgroup;
			unsigned int fcount;
			unsigned int tcount;

			fcount = tcount = 0;
			if (curr == &loadedlist || FLAG_ISSET(flags, FS_ALL)) {
				curr = elist_next(&loadedlist);
				next = elist_next(curr);
			}

			/* elist_for_each_safe splitted into separate startup for userstep function */
			for (; curr != &loadedlist; curr = next, next = elist_next(curr)) {
				if (!FLAG_ISSET(flags, FS_ALL) && tcount >= prefs_get_user_step()) break;

				attrgroup = elist_entry(curr, t_attrgroup, loadedlist);
				switch (attrgroup_flush(attrgroup, flags)) {
				case 0:
					/* stop on the first account not flushed (ie accessed too early) */
					goto loopout;
				case 1:
					fcount++;
					break;
				case -1:
					eventlog(eventlog_level_error, __FUNCTION__, "could not flush account");
					break;
				default:
					break;
				}
				tcount++;
			}

		loopout:
			if (fcount > 0)
				eventlog(eventlog_level_debug, __FUNCTION__, "flushed %u user accounts", fcount);

			if (!FLAG_ISSET(flags, FS_ALL) && curr != &loadedlist) return 1;

			return 0;
		}
Exemplo n.º 5
0
/*
 * Get NVMeD (NVMeDirect wide) features
 */
int nvmed_feature_get(NVMED* nvmed, int feature) {
	switch(feature) {
		case NVMED_CACHE_LAZY_INIT:
			return FLAG_ISSET(nvmed, NVMED_CACHE_LAZY_INIT);
			break;
		case NVMED_CACHE_SIZE:
			return nvmed->num_cache_size;
	};

	return 0;
}
Exemplo n.º 6
0
/**
 * 将好友信息数据写入指定的缓冲区.
 * @param buffer text-buffer
 * @param pal class PalInfo
 */
void DialogPeer::FillPalInfoToBuffer(GtkTextBuffer *buffer, PalInfo *pal)
{
        char buf[MAX_BUFLEN], ipstr[INET_ADDRSTRLEN];
        GdkPixbuf *pixbuf;
        GtkTextIter iter;

        gtk_text_buffer_get_end_iter(buffer, &iter);

        snprintf(buf, MAX_BUFLEN, _("Version: %s\n"), pal->version);
        gtk_text_buffer_insert(buffer, &iter, buf, -1);

        if (pal->group && *pal->group != '\0')
                snprintf(buf, MAX_BUFLEN, _("Nickname: %s@%s\n"), pal->name, pal->group);
        else
                snprintf(buf, MAX_BUFLEN, _("Nickname: %s\n"), pal->name);
        gtk_text_buffer_insert(buffer, &iter, buf, -1);

        snprintf(buf, MAX_BUFLEN, _("User: %s\n"), pal->user);
        gtk_text_buffer_insert(buffer, &iter, buf, -1);

        snprintf(buf, MAX_BUFLEN, _("Host: %s\n"), pal->host);
        gtk_text_buffer_insert(buffer, &iter, buf, -1);

        inet_ntop(AF_INET, &pal->ipv4, ipstr, INET_ADDRSTRLEN);
        if (pal->segdes && *pal->segdes != '\0')
                snprintf(buf, MAX_BUFLEN, _("Address: %s(%s)\n"), pal->segdes, ipstr);
        else
                snprintf(buf, MAX_BUFLEN, _("Address: %s\n"), ipstr);
        gtk_text_buffer_insert(buffer, &iter, buf, -1);

        if (!FLAG_ISSET(pal->flags, 0))
                snprintf(buf, MAX_BUFLEN, _("Compatibility: Microsoft\n"));
        else
                snprintf(buf, MAX_BUFLEN, _("Compatibility: GNU/Linux\n"));
        gtk_text_buffer_insert(buffer, &iter, buf, -1);

        snprintf(buf, MAX_BUFLEN, _("System coding: %s\n"), pal->encode);
        gtk_text_buffer_insert(buffer, &iter, buf, -1);

        if (pal->sign && *pal->sign != '\0') {
                gtk_text_buffer_insert(buffer, &iter, _("Signature:\n"), -1);
                gtk_text_buffer_insert_with_tags_by_name(buffer, &iter,
                                 pal->sign, -1, "sign-words", NULL);
        }

        if (pal->photo && *pal->photo != '\0'
                 && (pixbuf = gdk_pixbuf_new_from_file(pal->photo, NULL))) {
                gtk_text_buffer_insert(buffer, &iter, _("\nPhoto:\n"), -1);
                //TODO 缩放多少才合适
                pixbuf_shrink_scale_1(&pixbuf, 200, -1);
                gtk_text_buffer_insert_pixbuf(buffer, &iter, pixbuf);
                g_object_unref(pixbuf);
        }
}
Exemplo n.º 7
0
/**
 * 某好友请求本计算机的共享文件.
 * @param pal class PalInfo
 */
void UdpData::ThreadAskSharedFile(PalInfo *pal)
{
        SendFile sfile;
        bool permit;

        if (FLAG_ISSET(progdt.flags, 0)) {
                gdk_threads_enter();
                permit = pop_request_shared_file(pal);
                gdk_threads_leave();
                if (permit)
                        sfile.SendSharedInfoEntry(pal);
        } else
                sfile.SendSharedInfoEntry(pal);
}
Exemplo n.º 8
0
int
syscmd_file_can_read(char *filename)
{
    struct stat stat_buf;

#define FLAG_ISSET(V,F)        (((V) & (F)) == (F))

    if (!stat(filename, &stat_buf))
    {
        if (FLAG_ISSET(stat_buf.st_mode, S_IRUSR))
        {
            return 1;
        }
    }
    return 0;
}
Exemplo n.º 9
0
/**
 * 分派UDP数据到相应的函数去进行处理.
 */
void UdpData::DispatchUdpData()
{
        uint32_t commandno;

        /* 如果开启了黑名单处理功能,且此地址正好被列入了黑名单 */
        /* 嘿嘿,那就不要怪偶心狠手辣了 */
        if (FLAG_ISSET(progdt.flags, 1) && cthrd.BlacklistContainItem(ipv4))
                return;

        /* 决定消息去向 */
        commandno = iptux_get_dec_number(buf, ':', 4);
        switch (GET_MODE(commandno)) {
        case IPMSG_BR_ENTRY:
                SomeoneEntry();
                break;
        case IPMSG_BR_EXIT:
                SomeoneExit();
                break;
        case IPMSG_ANSENTRY:
                SomeoneAnsentry();
                break;
        case IPMSG_BR_ABSENCE:
                SomeoneAbsence();
                break;
        case IPMSG_SENDMSG:
                SomeoneSendmsg();
                break;
        case IPMSG_RECVMSG:
                SomeoneRecvmsg();
                break;
        case IPTUX_ASKSHARED:
                SomeoneAskShared();
                break;
        case IPTUX_SENDICON:
                SomeoneSendIcon();
                break;
        case IPTUX_SENDSIGN:
                SomeoneSendSign();
                break;
        case IPTUX_SENDMSG:
                SomeoneBcstmsg();
                break;
        default:
                break;
        }
}
Exemplo n.º 10
0
/**
 * 播放音频文件.
 * @param file 音频文件
 * @note 如果时间间隔过短,系统将会忽略后一个请求.
 */
void SoundSystem::Playing(const char *file)
{
        GstElement *pipeline, *filesrc;
        struct timeval time;

        gettimeofday(&time, NULL);
        if (!FLAG_ISSET(progdt.sndfgs, 0) || (difftimeval(time, timestamp) < 0.1))
                return;

        if (persist)
                EosMessageOccur(this);
        persist = true;
        filesrc = GST_ELEMENT(g_datalist_get_data(&eltset, "filesrc-element"));
        g_object_set(filesrc, "location", file, NULL);
        pipeline = GST_ELEMENT(g_datalist_get_data(&eltset, "pipeline-element"));
        gst_element_set_state(pipeline, GST_STATE_PLAYING);
        timestamp = time;
}
Exemplo n.º 11
0
/**
 * Pack filehandles
 *  @param buf Buffer
 *  @return If buf is NULL return needed size
 */
size_t _fs_pack_filehandles(pack_t buf) {
  struct filelist_item *file;
  struct fslist_item *fs;
  size_t i;

  if (buf==NULL) {
    // Prepare filesystems
    size_t size = sizeof(size_t)+llist_size(fslist)*sizeof(int)*2; // id, pid
    for (i=0;(fs = llist_get(fslist,i));i++) size += strlen(fs->mountpoint_str)+1; // mountpoint

    // Prepare files
    size += sizeof(size_t)+llist_size(filelist)*sizeof(int)*8; // fh, fs_fh, stfl, fdfl, shmid, type, mode
    for (i=0;(file = llist_get(filelist,i));i++) size += strlen(file->path)+1; // path

    return size;
  }
  else {
    // Pack filesystems
    packi(buf,llist_size(fslist));
    for (i=0;(fs = llist_get(fslist,i));i++) {
      packi(buf,fs->id);
      packi(buf,fs->pid);
      packstr(buf,fs->mountpoint_str);
    }

    // Pack files
    packi(buf,llist_size(filelist));
    for (i=0;(file = llist_get(filelist,i));i++) {
      if (file->type!=FL_DIR && !FLAG_ISSET(file->fdfl,FD_CLOEXEC)) {
        packi(buf,file->fh);
        packi(buf,file->fs_fh);
        packi(buf,file->shmid);
        packi(buf,file->type);
        packi(buf,file->mode);
        packi(buf,file->stfl);
        packi(buf,file->fdfl);
        packi(buf,file->fs->id);
        packstr(buf,file->path);
      }
    }

    return 0;
  }
}
Exemplo n.º 12
0
/**
 * 好友发送头像数据.
 */
void UdpData::SomeoneSendIcon()
{
        PalInfo *pal;
        char *iconfile;

        if (!(pal = cthrd.GetPalFromList(ipv4)) || FLAG_ISSET(pal->flags, 2))
                return;

        /* 接收并更新数据 */
        if ( (iconfile = RecvPalIcon())) {
                g_free(pal->iconfile);
                pal->iconfile = iconfile;
                gdk_threads_enter();
                pthread_mutex_lock(cthrd.GetMutex());
                cthrd.UpdatePalToList(ipv4);
                pthread_mutex_unlock(cthrd.GetMutex());
                mwin.UpdateItemToPaltree(ipv4);
                gdk_threads_leave();
        }
}
Exemplo n.º 13
0
/*
 * Destroy MQ Handle
 */
int nvmed_handle_destroy_mq(NVMED_HANDLE* nvmed_handle) {
	int i;

	if(nvmed_handle == NULL) return -NVMED_NOENTRY;
	if(!FLAG_ISSET(nvmed_handle, HANDLE_MQ)) {
		nvmed_printf("%s: failed to destroy MQ - not MQ\n",
				HtoD(nvmed_handle)->ns_path);

		return -NVMED_FAULT;
	}
	for(i=1; i<nvmed_handle->num_mq; i++) {
		pthread_spin_lock(&nvmed_handle->queue_mq[i]->mngt_lock);
		nvmed_handle->queue_mq[i]->numHandle--;
		pthread_spin_unlock(&nvmed_handle->queue_mq[i]->mngt_lock);
	}

	free(nvmed_handle->queue_mq);

	return nvmed_handle_destroy(nvmed_handle);
}
Exemplo n.º 14
0
/**
 * 确保好友一定在线.
 * @return 好友数据
 */
PalInfo *UdpData::AssertPalOnline()
{
        PalInfo *pal;

        if ( (pal = cthrd.GetPalFromList(ipv4))) {
                /* 既然好友不在线,那么他自然不在列表中 */
                if (!FLAG_ISSET(pal->flags, 1)) {
                        FLAG_SET(pal->flags, 1);
                        gdk_threads_enter();
                        pthread_mutex_lock(cthrd.GetMutex());
                        cthrd.UpdatePalToList(ipv4);
                        pthread_mutex_unlock(cthrd.GetMutex());
                        mwin.AttachItemToPaltree(ipv4);
                        gdk_threads_leave();
                }
        } else {
                SomeoneLost();
                pal = cthrd.GetPalFromList(ipv4);
        }

        return pal;
}
Exemplo n.º 15
0
/**
 * 好友在线.
 */
void UdpData::SomeoneAnsentry()
{
        Command cmd;
        pthread_t pid;
        PalInfo *pal;
        const char *ptr;

        /* 若好友不兼容iptux协议,则需转码 */
        ptr = iptux_skip_string(buf, size, 3);
        if (!ptr || *ptr == '\0')
                ConvertEncode(progdt.encode);

        /* 加入或更新好友列表 */
        gdk_threads_enter();
        pthread_mutex_lock(cthrd.GetMutex());
        if ( (pal = cthrd.GetPalFromList(ipv4))) {
                UpdatePalInfo(pal);
                cthrd.UpdatePalToList(ipv4);
        } else {
                pal = CreatePalInfo();
                cthrd.AttachPalToList(pal);
        }
        pthread_mutex_unlock(cthrd.GetMutex());
        if (mwin.PaltreeContainItem(ipv4))
                mwin.UpdateItemToPaltree(ipv4);
        else
                mwin.AttachItemToPaltree(ipv4);
        gdk_threads_leave();

        /* 更新本大爷的数据信息 */
        if (FLAG_ISSET(pal->flags, 0)) {
                pthread_create(&pid, NULL, ThreadFunc(CoreThread::SendFeatureData), pal);
                pthread_detach(pid);
        } else if (strcasecmp(progdt.encode, pal->encode) != 0)
                cmd.SendAnsentry(cthrd.UdpSockQuote(), pal);
}
Exemplo n.º 16
0
/**
 * 好友广播消息.
 */
void UdpData::SomeoneBcstmsg()
{
        GroupInfo *grpinf;
        PalInfo *pal;
        uint32_t commandno, packetno;
        char *text;

        /* 如果对方兼容iptux协议,则无须再转换编码 */
        pal = cthrd.GetPalFromList(ipv4);
        if (!pal || !FLAG_ISSET(pal->flags, 0))
                ConvertEncode(pal ? pal->encode : progdt.encode);
        /* 确保好友在线,并对编码作出适当调整 */
        pal = AssertPalOnline();
        if (strcasecmp(pal->encode, encode ? encode : "utf-8") != 0) {
                g_free(pal->encode);
                pal->encode = g_strdup(encode ? encode : "utf-8");
        }

        /* 检查此消息是否过时 */
        packetno = iptux_get_dec_number(buf, ':', 1);
        if (packetno <= pal->packetn)
                return;
        pal->packetn = packetno;

        /* 插入消息&在消息队列中注册 */
        text = ipmsg_get_attach(buf, ':', 5);
        if (text && *text != '\0') {
                commandno = iptux_get_dec_number(buf, ':', 4);
                /*/* 插入消息 */
                switch (GET_OPT(commandno)) {
                case IPTUX_BROADCASTOPT:
                        InsertMessage(pal, GROUP_BELONG_TYPE_BROADCAST, text);
                        break;
                case IPTUX_GROUPOPT:
                        InsertMessage(pal, GROUP_BELONG_TYPE_GROUP, text);
                        break;
                case IPTUX_SEGMENTOPT:
                        InsertMessage(pal, GROUP_BELONG_TYPE_SEGMENT, text);
                        break;
                case IPTUX_REGULAROPT:
                default:
                        InsertMessage(pal, GROUP_BELONG_TYPE_REGULAR, text);
                        break;
                }
                /*/* 注册消息 */
                pthread_mutex_lock(cthrd.GetMutex());
                switch (GET_OPT(commandno)) {
                case IPTUX_BROADCASTOPT:
                        grpinf = cthrd.GetPalBroadcastItem(pal);
                        break;
                case IPTUX_GROUPOPT:
                        grpinf = cthrd.GetPalGroupItem(pal);
                        break;
                case IPTUX_SEGMENTOPT:
                        grpinf = cthrd.GetPalSegmentItem(pal);
                        break;
                case IPTUX_REGULAROPT:
                default:
                        grpinf = cthrd.GetPalRegularItem(pal);
                        break;
                }
                if (!grpinf->dialog && !cthrd.MsglineContainItem(grpinf))
                        cthrd.PushItemToMsgline(grpinf);
                pthread_mutex_unlock(cthrd.GetMutex());
        }
        g_free(text);

        /* 播放提示音 */
        if (FLAG_ISSET(progdt.sndfgs, 1))
                sndsys.Playing(progdt.msgtip);
}
Exemplo n.º 17
0
/**
 * 好友发送消息.
 *
 */
void UdpData::SomeoneSendmsg()
{
        GroupInfo *grpinf;
        PalInfo *pal;
        Command cmd;
        uint32_t commandno, packetno;
        char *text;
        pthread_t pid;
        DialogPeer *dlgpr;
        GtkWidget *window;

        /* 如果对方兼容iptux协议,则无须再转换编码 */
        pal = cthrd.GetPalFromList(ipv4);
        if (!pal || !FLAG_ISSET(pal->flags, 0))
                ConvertEncode(pal ? pal->encode : progdt.encode);
        /* 确保好友在线,并对编码作出适当调整 */
        pal = AssertPalOnline();
        if (strcasecmp(pal->encode, encode ? encode : "utf-8") != 0) {
                g_free(pal->encode);
                pal->encode = g_strdup(encode ? encode : "utf-8");
        }

        /* 回复好友并检查此消息是否过时 */
        commandno = iptux_get_dec_number(buf, ':', 4);
        packetno = iptux_get_dec_number(buf, ':', 1);
        if (commandno & IPMSG_SENDCHECKOPT)
                cmd.SendReply(cthrd.UdpSockQuote(), pal, packetno);
        if (packetno <= pal->packetn)
                return;
        pal->packetn = packetno;

        /* 插入消息&在消息队列中注册 */
        text = ipmsg_get_attach(buf, ':', 5);
        if (text && *text != '\0') {
                /*/* 插入消息 */
//                if ((commandno & IPMSG_BROADCASTOPT) || (commandno & IPMSG_MULTICASTOPT))
//                        InsertMessage(pal, GROUP_BELONG_TYPE_BROADCAST, text);
//                else
                        InsertMessage(pal, GROUP_BELONG_TYPE_REGULAR, text);
        }
        g_free(text);
        /*/* 注册消息 */
        pthread_mutex_lock(cthrd.GetMutex());
//        if ((commandno & IPMSG_BROADCASTOPT) || (commandno & IPMSG_MULTICASTOPT))
//                grpinf = cthrd.GetPalBroadcastItem(pal);
//        else
                grpinf = cthrd.GetPalRegularItem(pal);
        if (!grpinf->dialog && !cthrd.MsglineContainItem(grpinf))
                cthrd.PushItemToMsgline(grpinf);
        pthread_mutex_unlock(cthrd.GetMutex());

        /* 标记位处理 先处理底层数据,后面显示窗口*/
        if (commandno & IPMSG_FILEATTACHOPT) {
                if ((commandno & IPTUX_SHAREDOPT) && (commandno & IPTUX_PASSWDOPT)) {
                        pthread_create(&pid, NULL, ThreadFunc(ThreadAskSharedPasswd), pal);
                        pthread_detach(pid);
                } else
                        RecvPalFile();
        }
        window = GTK_WIDGET(grpinf->dialog);
        //这里不知道为什么运行时一直会提示window不是object
        dlgpr = (DialogPeer *)(g_object_get_data(G_OBJECT(window),"dialog"));
        if(grpinf->dialog)
            dlgpr->ShowDialogPeer(dlgpr);
        /* 是否直接弹出聊天窗口 */
        if (FLAG_ISSET(progdt.flags, 7)) {
                gdk_threads_enter();
                if (!(grpinf->dialog)) {
//                     switch (grpinf->type) {
//                     case GROUP_BELONG_TYPE_REGULAR:
                          DialogPeer::PeerDialogEntry(grpinf);
//                          break;
//                     case GROUP_BELONG_TYPE_SEGMENT:
//                     case GROUP_BELONG_TYPE_GROUP:
//                     case GROUP_BELONG_TYPE_BROADCAST:
//                          DialogGroup::GroupDialogEntry(grpinf);
//                     default:
//                          break;
//                     }
                } else {
                     gtk_window_present(GTK_WINDOW(grpinf->dialog));
                }
                gdk_threads_leave();
        }

        /* 播放提示音 */
        if (FLAG_ISSET(progdt.sndfgs, 1))
                sndsys.Playing(progdt.msgtip);
}
Exemplo n.º 18
0
/* Get CACHE from free list or evict */
NVMED_CACHE* nvmed_get_cache(NVMED_HANDLE* nvmed_handle) {
	NVMED* nvmed = HtoD(nvmed_handle);
	NVMED_CACHE *cache = nvmed->free_head.tqh_first;
	NVMED_CACHE *__cache;
	NVMED_CACHE *ret_cache;
	int i;
	unsigned int start_lpaddr, end_lpaddr;
	TAILQ_HEAD(cache_list, nvmed_cache) temp_head;

	pthread_rwlock_wrlock(&nvmed->cache_radix_lock);
	pthread_spin_lock(&nvmed->cache_list_lock);

	if(cache==NULL)  {
		//HEAD -> LRU, //TAIL -> MRU
		//EVICT - LRU
		cache = nvmed->lru_head.tqh_first;
		if(!FLAG_ISSET(cache, CACHE_DIRTY)) {
			TAILQ_REMOVE(&nvmed->lru_head, cache, cache_list);
			LIST_REMOVE(cache, handle_cache_list);
			radix_tree_delete(&nvmed->cache_root, cache->lpaddr);
			FLAG_SET_FORCE(cache, 0);
			ret_cache = cache;
		}
		else {
			TAILQ_INIT(&temp_head);
			
			while(FLAG_ISSET_SYNC(cache, CACHE_LOCKED) || cache->ref != 0) {
				usleep(1);
			}
			
			start_lpaddr = cache->lpaddr;
			end_lpaddr = cache->lpaddr;
			
			__cache = cache->cache_list.tqe_next;

			TAILQ_REMOVE(&nvmed->lru_head, cache, cache_list);
			radix_tree_delete(&nvmed->cache_root, cache->lpaddr);
			TAILQ_INSERT_HEAD(&temp_head, cache, cache_list);

			for(i=1; i<NVMED_CACHE_FORCE_EVICT_MAX; i++) {
				cache = __cache;
				if(FLAG_ISSET_SYNC(cache, CACHE_LOCKED)) break;
				if(!FLAG_ISSET(cache, CACHE_DIRTY)) break;
				if(start_lpaddr != 0 && cache->lpaddr == start_lpaddr-1 ) {
					//front_merge
					start_lpaddr--;
					__cache = cache->cache_list.tqe_next;
					TAILQ_REMOVE(&nvmed->lru_head, cache, cache_list);
					radix_tree_delete(&nvmed->cache_root, cache->lpaddr);
					TAILQ_INSERT_HEAD(&temp_head, cache, cache_list);

					continue;
				}
				else if(cache->lpaddr == end_lpaddr+1) {
					//back_merge
					end_lpaddr++;
					__cache = cache->cache_list.tqe_next;
					TAILQ_REMOVE(&nvmed->lru_head, cache, cache_list);
					radix_tree_delete(&nvmed->cache_root, cache->lpaddr);
					TAILQ_INSERT_TAIL(&temp_head, cache, cache_list);

					continue;
				}
				else {
					break;
				}
			}
			
			if(FLAG_ISSET(cache, CACHE_DIRTY))
			nvmed_cache_io_rw(nvmed_handle, nvme_cmd_write, temp_head.tqh_first, 
					start_lpaddr * PAGE_SIZE, (end_lpaddr - start_lpaddr) * PAGE_SIZE, 
					HANDLE_SYNC_IO);

			cache = temp_head.tqh_first;
			FLAG_SET_FORCE(cache, 0);
			ret_cache = cache;

			TAILQ_REMOVE(&temp_head, cache, cache_list);
			LIST_REMOVE(cache, handle_cache_list);

			while(temp_head.tqh_first != NULL) {
				TAILQ_REMOVE(&temp_head, temp_head.tqh_first, cache_list);
				TAILQ_INSERT_HEAD(&nvmed->free_head, temp_head.tqh_first, cache_list);
				nvmed->num_cache_usage--;
			}
		}
	}
	else {
		// Remove From Free Queue
		TAILQ_REMOVE(&nvmed->free_head, cache, cache_list);
		FLAG_UNSET_SYNC(cache, CACHE_FREE);
		if(FLAG_ISSET(cache, CACHE_UNINIT)) {
			memset(cache->ptr, 0, PAGE_SIZE);
			virt_to_phys(nvmed, cache->ptr, &cache->paddr, 4096);
			FLAG_UNSET_SYNC(cache, CACHE_UNINIT);
		}
		ret_cache = cache;
	}

	INIT_SYNC(ret_cache->ref);
	pthread_spin_unlock(&nvmed->cache_list_lock);
	pthread_rwlock_unlock(&nvmed->cache_radix_lock);

	return ret_cache;
}
Exemplo n.º 19
0
/*
 * Get Handle Features
 */
int nvmed_handle_feature_get(NVMED_HANDLE* nvmed_handle, int feature) {
	return FLAG_ISSET(nvmed_handle, feature);
}
Exemplo n.º 20
0
/*
 * Make I/O request from NVMeDirect Cache
 */
ssize_t nvmed_cache_io_rw(NVMED_HANDLE* nvmed_handle, u8 opcode, NVMED_CACHE *__cache, 
		unsigned long start_lba, unsigned int len, int __flag) {
	NVMED_QUEUE* nvmed_queue;
	NVMED* nvmed;
	NVMED_CACHE* cache;
	int num_cache;
	int flag;
	ssize_t remain = 0;
	ssize_t io_size, io = 0, total_io = 0;
	unsigned long io_lba;

	u64 prp1, prp2;
	void* prp2_addr;

	if(len % PAGE_SIZE) return 0;

	if(__flag != 0) flag = __flag;
	else flag = nvmed_handle->flags;

	if(FLAG_ISSET(nvmed_handle, HANDLE_MQ)) {
		nvmed_queue = nvmed_handle->mq_get_queue(nvmed_handle, opcode, 
				start_lba, len);

		if(nvmed_queue == NULL)
			return 0;
	}
	else {
		nvmed_queue = HtoQ(nvmed_handle);
	}
	nvmed = nvmed_queue->nvmed;
	
	remain = len;
	cache = __cache;

	num_cache = len / PAGE_SIZE;
	while(num_cache-- > 0) {
		FLAG_SET_SYNC(cache, CACHE_LOCKED);
		cache = cache->cache_list.tqe_next;
	}

	cache = __cache;
	while(remain > 0) {
		if(remain > nvmed->dev_info->max_hw_sectors * 512 )
			io_size = nvmed->dev_info->max_hw_sectors * 512;
		else
			io_size = remain;

		io_lba = total_io + start_lba;

		num_cache = io_size / PAGE_SIZE;

		make_prp_list_from_cache(nvmed_handle, cache, num_cache, &prp1, &prp2, &prp2_addr);
		io = nvmed_io(nvmed_handle, opcode, prp1, prp2, prp2_addr, cache, 
				io_lba, io_size, flag, NULL);
		
		if(io <= 0) break;
		
		remain -= io;
		total_io += io;
		io_lba += io;

		while(num_cache-- > 0)
			cache = cache->cache_list.tqe_next;
	}
	
	return total_io;
}